我有一个程序以 SYSTEM 身份运行,并尝试通过以下代码查询登录用户令牌:
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)
}
}
以上代码在Win10中运行成功。但在 Win7 32 位中,WTSQueryUserToken() 总是返回 False,错误为 5 (ERROR_ACCESS_DENIED)。
我是否遗漏了Win7环境下的任何配置?
===编辑====
我的程序作为服务运行,遵循示例。
我希望我的程序作为 LocalSystem 帐户运行,作为 CreateServer() 中的最后第二个参数 (NULL)。
之前版本的 MSDN 文档
WTSQueryUserToken
在可能的错误值方面更加完整
错误_访问_拒绝:
调用者没有适当的权限来调用此函数。调用者必须在上下文中运行 LocalSystem 帐户并拥有
权限。SE_TCB_NAME
但是当调用者没有
SE_TCB_NAME
权限时,会返回不同的错误代码:
错误_PRIVILEGE_NOT_HELD:
调用者没有
权限。SE_TCB_NAME
因此,当调用者不作为
LocalSystem 运行时,会返回ERROR_ACCESS_DENIED
。具体来说,这意味着调用者令牌的 TokenUser
不是 S-1-5-18
( NT AUTHORITY\SYSTEM - WellKnownGroup )
在内部
WTSQueryUserToken
首先检查是否持有并启用 SE_TCB_NAME
权限,如果不是,则返回 ERROR_PRIVILEGE_NOT_HELD
。
WinStationQueryInformationW
来调用 WinStationUserToken
。成功时会返回 WINSTATIONUSERTOKEN
。这是对 LSM 服务的远程调用,它通常在 svchost.exe 进程中运行,命令行中带有 LSM。调用由 lsm.dll 处理,其中
RPC_STATUS CALLBACK CPrivateRpc::staticRpcSecurityCallback(void *,int);
被调用(该函数位于lsm.dll内部)。里面有一个函数
HRESULT CUtils::IsCallerSystem();
TokenUser
是否为 S-1-5-18
,如果不是 - CPrivateRpc::staticRpcSecurityCallback
使用 ERROR_ACCESS_DENIED
删除调用 - 并向调用者返回错误。
因此请检查您的代码真正在哪个上下文中运行。