The other day I worked on a support case where a Windows service running as System in Session 0 was creating a process also running as System in Session 0, and this new process failed to create another process in the logged-on user's session (Session 2 in this particular case). And it failed because CreateProcessAsUser API didn't work and returned error 5 (Access Denied).
Note the issue happened on Windows 7, and because of Session 0 Isolation the logged-on user and the service (and its child process running as System) were running in different sessions.
To understand what was going on exactly, I did some kernel debugging of the issue and saw that the error in CreateProcessAsUser happened when trying to bind the process we were trying to spawn to its parent's Job (the Job that the process that the service spawned as System was a member of).
Indeed, I could verify with Process Explorer that the process running as System in Session 0 was member of a Job, by checking the properties of the process and going to the Job tab (note: when there is no Job, there is no Job tab).
After a process is associated with a job, by default any child processes it creates are also associated with the job (see Job Objects for more details on this).
But the following is also documented:
Terminal Services: All processes within a job must run within the same session as the job.
Which means that, as the new process we are trying to create is in a different session than its parent, we will fail to bind it to its parent's Job.
The only way to work around this, would be to create the process in the different session by passing this flag to the CreateProcessAsUser API:
Process Creation Flags
0x01000000 The child processes of a process associated with a job are not associated with the job.
If the calling process is not associated with a job, this constant has no effect. If the calling process is associated with a job, the job must set the JOB_OBJECT_LIMIT_BREAKAWAY_OK limit.
I hope this helps.
Alex (Alejandro Campos Magencio)