我正在尝试从 Windows 服务(以 SYSTEM 身份运行)调用 Windows API(似乎只能在登录用户的上下文中工作)。我能够获得登录用户的 token 。当我调用 ImpersonateLoggedOnUser() 时,我没有收到任何错误,它返回 true。但是 DoSomethingInUserContext() 仍然在 SYSTEM 上下文中执行。我究竟做错了什么?
DWORD sessionIdDw = WTSGetActiveConsoleSessionId();
HANDLE hToken;
if (!WTSQueryUserToken(sessionIdDw, &hToken))
LOG() << "WTSQueryUserToken failed: " << GetLastError();
HANDLE hDuplicated = NULL;
if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation, &hDuplicated)) {
LOG() << "DuplicateTokenEx failed: " <<GetLastError();
}
if (!ImpersonateLoggedOnUser(hDuplicated)) {
LOG() << "ImpersonateLoggedOnUser failed " << GetLastError();
}
else {
DoSomethingInUserContext();
if (!RevertToSelf()) {
LOG() << "RevertToSelf failed" << GetLastError();
}
}
CloseHandle(hDuplicated);
CloseHandle(hToken);
最佳答案
评论足够详细,可以指出原因,EnumWindows
按 session 枚举。
创建用户服务是一种可行的方法。而下面的方法也是有效的:
TCHAR Command[MAX_PATH] = L"C:\\EnumWindows.exe";
DWORD sessionIdDw = WTSGetActiveConsoleSessionId();
logfile(sessionIdDw);
HANDLE hToken;
if (!WTSQueryUserToken(sessionIdDw, &hToken))
LOG() << "WTSQueryUserToken failed: " << GetLastError();
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if(!CreateProcessAsUser(hToken,NULL,Command,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
LOG() << "CreateProcessAsUser failed: " << GetLastError();
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
新进程正在用户 session 中运行。
编辑:
感谢@Eryk 指出,Window Stations :
Each session is associated with its own interactive window station
The desktop must be associated with the current window station for the process.
The window station must be associated with the current session.
所以 SetThreadDesktop
在这里不起作用。
关于c++ - ImpersonateLoggedOnUser 无法在 Windows 服务中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58753029/