Home > Software design >  WTSQueryUserToken return 5 (ERROR_ACCESS_DENIED)
WTSQueryUserToken return 5 (ERROR_ACCESS_DENIED)

Time:04-12

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 enter image description here

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.

  • Related