I have a program runs as SYSTEM and try to query logon user token by the following code:
WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
for (i = 0; i < dwCount; i ) {
WTS_SESSION_INFO si = pSessionInfo[i];
if (WTSActive == si.State) {
WTSQueryUserToken(si.SessionId, &hUserToken)
}
}
The above codes run successfully in Win10. But in Win7 32-bit, WTSQueryUserToken() always return False with error 5 (ERROR_ACCESS_DENIED).
Did I miss any configuration in Win7 environment?
=== Edit ====
My program run as a service which follows the
ERROR_ACCESS_DENIED:
The caller does not have the appropriate permissions to call this function. The caller must be running within the context of the LocalSystem account and have the
SE_TCB_NAME
privilege.
but when caller have no SE_TCB_NAME
privilege was another error
ERROR_PRIVILEGE_NOT_HELD:
The caller does not have the
SE_TCB_NAME
privilege.
so ERROR_ACCESS_DENIED
was in case when caller does not running within the context of the LocalSystem. more concrete this mean that TokenUser
of user token is S-1-5-18
( NT AUTHORITY\SYSTEM - WellKnownGroup )
internally WTSQueryUserToken
first check SE_TCB_NAME
privilege and if it not exist or not enabled - ERROR_PRIVILEGE_NOT_HELD
returned.
otherwise WinStationQueryInformationW
called with WinStationUserToken
. the WINSTATIONUSERTOKEN
returned on success. this is remote call to LSM service. usually it run in svchost.exe process with LSM in command line. call is handled by lsm.dll. at begin the
RPC_STATUS CALLBACK CPrivateRpc::staticRpcSecurityCallback(void *,int);
called (this function inside lsm.dll)
inside this called
HRESULT CUtils::IsCallerSystem();
this function check caller token TokenUser
- are it equal to S-1-5-18
if not - CPrivateRpc::staticRpcSecurityCallback
return ERROR_ACCESS_DENIED
- and error returned for caller.
so check - under which token your code really run
CodePudding user response:
Eventually, I solved this problem. Here are my experience for someone if they also hit this problem.
The root cause is that under Windows 7 32bit, a created thread doesn't get full access right by calling CreateThread
. Usually, we use NULL
for the 1st argument of CreateThread
to get full access right in other version of Windows. However, it doesn't work in Windows 7 32-bit.
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
pDataArray[i], // argument to thread function
0, // use default creation flags
&dwThreadIdArray[i]); // returns the thread identifier
We need to prepare the SECURITY ATTRIBUTES for the 1st argument by following the example.