ImpersonateLoggedOnUser не работает в службе Windows - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь вызвать Windows API (который, кажется, работает только в контексте входа пользователя) из службы Windows (работает как SYSTEM). Я могу получить токен для вошедшего в систему пользователя. Я не получаю никаких ошибок при вызове 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);

1 Ответ

1 голос
/ 08 ноября 2019

Комментарии достаточно подробны, чтобы указать причину, EnumWindows перечисляет по сеансам.

Создание пользовательского сервиса - выполнимый метод. И следующий метод также эффективен:

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 за указание, Оконные станции :

Каждый сеанс связан с собственной интерактивной оконной станцией

SetThreadDesktop:

Рабочий стол должен быть связан с текущей станцией окна для процесса.

SetProcessWindowStation:

Станция окна должна бытьсвязан с текущим сеансом.

Так что SetThreadDesktop здесь не работает.

...