Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It is really possible. The main problem which you have is that Windows should be seen as a terminal server and a users session as a remote session. Your service should be able to start a process which run in the remote session belongs to the user.</p> <p>By the way, if you write a service which run under Windows XP which is not added to a domain and the fast user switching is activated, you can have the same problems to start a process on running on the second (third and so on) logged users desktop.</p> <p>I hope you have a user token, which you receive for example with respect of impersonation or you have a <code>dwSessionId</code> of session. If you don't have it you can try use some WTS-function (Remote Desktop Services API <a href="http://msdn.microsoft.com/en-us/library/aa383464.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa383464.aspx</a>, for example <code>WTSEnumerateProcesses</code> or <code>WTSGetActiveConsoleSessionId</code>) or LSA-API to find out the corresponding users session (<code>LsaEnumerateLogonSessions</code> see <a href="http://msdn.microsoft.com/en-us/library/aa378275.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa378275.aspx</a> and <code>LsaGetLogonSessionData</code> see <a href="http://msdn.microsoft.com/en-us/library/aa378290.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa378290.aspx</a>) or <code>ProcessIdToSessionId</code> (see <a href="http://msdn.microsoft.com/en-us/library/aa382990.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa382990.aspx</a>).</p> <p>You can use <code>GetTokenInformation</code> function with the parameter <code>TokenSessionId</code> (see <a href="http://msdn.microsoft.com/en-us/library/aa446671.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa446671.aspx</a>) to receive the session id <code>dwSessionId</code> of the users session if you knows the users token <code>hClient</code>.</p> <pre><code>BOOL bSuccess; HANDLE hProcessToken = NULL, hNewProcessToken = NULL; DWORD dwSessionId, cbReturnLength; bSuccess = GetTokenInformation (hClient, TokenSessionId, &amp;dwSessionId, sizeof(DWORD), &amp;cbReturnLength); bSuccess = OpenProcessToken (GetCurrentProcess(), MAXIMUM_ALLOWED, &amp;hProcessToken); bSuccess = DuplicateTokenEx (hProcessToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &amp;hNewProcessToken); EnablePrivilege (SE_TCB_NAME); bSuccess = SetTokenInformation (hNewProcessToken, TokenSessionId, &amp;dwSessionId, sizeof(DWORD)); bSuccess = CreateProcessAsUser (hNewProcessToken, NULL, szCommandToExecute, ...); </code></pre> <p>This code only a schema. <code>EnablePrivilege</code> is a simple function used <code>AdjustTokenPrivileges</code> to enable <code>SE_TCB_NAME</code> privilege (see <a href="http://msdn.microsoft.com/en-us/library/aa446619.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/aa446619.aspx</a> as a template). It is important that the process from which you are start a process you have TCB privilege, but if your service run under the Local System you have enough permissions. By the way, following code fragment work with not only Local System account, but the account must have <code>SE_TCB_NAME</code> privilege to be able to switch current terminal server session.</p> <p>One more remark. In the code above we start new process with the same account as the current process have (for example Local System). You change change a code to use another account for example the users token <code>hClient</code>. It is only important to have a <code>primary token</code>. If you have an impersonation token you can convert it to the primary token exactly like in the code above.</p> <p>In the <code>STARTUPINFO</code> structure used in <code>CreateProcessAsUser</code> you should use <code>lpDesktop =</code> WinSta0\Default".</p> <p>Depend on your requirements it could be also needed to use <code>CreateEnvironmentBlock</code> to create an new environment block that you will be passing to the new process.</p> <p>I recommend you also to read <a href="https://stackoverflow.com/questions/3100934/how-to-ensure-process-window-launched-by-process-startprocessstartinfo-has-focu/3101061#3101061">How to ensure process window launched by Process.Start(ProcessStartInfo) has focus of all Forms?</a> where I describe how to force that the process will be started in foreground on the users desktop.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload