0

我正在尝试从 Windows 服务(以 SYSTEM 身份运行)调用 Windows api(似乎只在登录用户的上下文中工作)。我可以获得登录用户的令牌。当我调用 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);
4

1 回答 1

1

评论足够详细,可以指出原因,EnumWindows并按会话列举。

创建用户服务是一种可行的方法。而且下面的方法也有效:</p>

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);
}

新进程正在用户会话中运行。

编辑:

感谢@Eryk 指出,Window Stations

每个会话都与它自己的交互式窗口站相关联

SetThreadDesktop

桌面必须与进程的当前窗口站相关联。

SetProcessWindowStation

窗口站必须与当前会话相关联。

所以SetThreadDesktop在这里不起作用。

于 2019-11-08T03:40:00.973 回答