Имеется сервис, который работает с правами системы. Он отслеживает подключение терминальных сессий, при подключении новой терминальной сесии, внутри этой сесии создается процесс с правами, такими же как у сервиса. Код следующий:
var
hToken, hNewToken: Cardinal;
si: STARTUPINFOW;
pi: PROCESS_INFORMATION;
SessionId: Cardinal;
...
SessionId := WTSGetActiveConsoleSessionId;
...
stSystemUserSession: // Текущая терминальная сессия с правами системы.
begin
if not OpenProcessToken(GetCurrentProcess,
TOKEN_QUERY or TOKEN_DUPLICATE, hToken) then
begin
AppendLog('Error WTSStartProcess - OpenProcessToken ' + IntToStr(GetLastError));
Exit;
end;
if not DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityIdentification,
TokenPrimary, hNewToken) then
begin
AppendLog('Error WTSStartProcess - DuplicateTokenEx ' + IntToStr(GetLastError));
Exit;
end;
if not SetTokenInformation(hNewToken,
TokenSessionId, @SessionId, SizeOf(Cardinal)) then
begin
AppendLog('Error WTSStartProcess - SetTokenInformation ' + IntToStr(GetLastError));
Exit;
end;
// Запуск процесса.
try
si.lpDesktop := '';
if CreateProcessAsUserW(hNewToken, nil, PWideChar(APath),
nil, nil, false, 0, nil, nil, si, pi) then
begin
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end
else
begin
AppendLog('Error WTSStartProcess - CreateProcessAsUserW ' + IntToStr(GetLastError));
Exit;
end;
finally
CloseHandle(hToken);
CloseHandle(hNewToken);
end;
end;
Теперь о проблеме.
Запускаем данный сервис в ОС WinXP, логиним первого пользователя (данный код не выполняем, т.к. первый пользователь в XP находится в 0 терм. сесии), делаем SwitchUser, логиним второго пользователя — данный код успешно отрабатывает, в 1 терминальной сессии запускается интересующий нас процесс с правами системы. Делаем LogOff этого второго пользователя (при этом создается еще одна терм. сессии, в которой отображается Logon экран после Logoff'а этого юзера) и, как говориться, баста хрю — функция CreateProcessAsUserW возвращает ошибку ERROR_PIPE_NOT_CONNECTED.
Так же пробовал запускать с токеном winlogon'a текущей терм. сессии — то же самое.
Самое удивительное то, что в Висте данный код работает всегда, проблема только в XP (в 2003 не проверял еще).
PS
пробовал CreateProcessAsUser (ANSI версию) — те же грабли.
PPS
Заранее спасибо знатокам внутренностей ОС!