'WTSQueryUserToken return 5 (ERROR_ACCESS_DENIED)

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 example.

I expect that my program is run as LocalSystem account as the last second argument (NULL) in CreateServer().



Solution 1:[1]

in previous version of MSDN documentation of WTSQueryUserToken was more complete in part of possible error values

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 RbMm