create process in user session from service
I use code similar to yours in my own service and it works fine. There are some things that need to be taken into account that the code you showed is not doing:
When calling
WTSQueryUserToken()
, you have to make sure your service process has theSE_TCB_NAME
privilege enabled. UseAdjustTokenPrivileges()
for that.The session ID returned by
WTSGetActiveConsoleSessionId()
may not be the correct session that you need to run your spawned process on! It returns the session ID that is attached to the physical console (screen/keyboard/mouse) of the local machine, if any. That session may be displaying the secure WinLogon desktop, meaning no user is actually logged in to the physical machine, so callingWTSQueryUserToken()
on that session ID would fail with anERROR_NO_TOKEN
error. A user can log in over a Remote Desktop Connection, for instance, in which case that connection would be running in a different session than the console. If you want your spawned process to run in a session that has a user logged in, you need to useWTSEnumerateSessions()
to find a session that is in theWTSActive
state. And even then,WTSQueryUserToken()
may not return a token depending on how the user is logged in, so you need to callWTSQueryUserToken()
on each active session you find until you find one that successfully gives you a token.When calling
DuplicateTokenEx()
, useSecurityIdentification
instead ofSecurityDelegation
.When calling
CreateProcessAsUser()
, you can callCreateEnvironmentBlock()
first to create an environment that is appropriate for that specific user and then pass that pointer toCreateProcessAsUser()
. Otherwise, the spawned process will use your service's environment instead. This step is optional, depending on the particular needs of the spawned app.