Типовой сервис стартует вместе с ОС (например WinXP) от имени системы. Сразу после старта сервис пускает ряд процессов, среди них часть интерактивных.
Процессы пускаются от имени другого пользователя с известными реквизитами (права что то типа PowerUser).
Делается это приблизительно так как описано в примере от MSDN "Starting an Interactive Client Process".
Вот фрагмент кода Delphi5 (исключая проверки результатов функций и освобождение ресурсов)
// получаем маркер пользователя
LogonUser(UserName, nil, UserPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ClientToken);
// подключаемся к WinSta0 и Desktop Default
hwinstaSave:=GetProcessWindowStation;
_WINSTA:=OpenWindowStation('WinSta0', FALSE, READ_CONTROL or WRITE_DAC);
SetProcessWindowStation(_WINSTA);
_desk:=OpenDesktop('Default', 0, FALSE, READ_CONTROL or WRITE_DAC or DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS);
// далее все как в примере: получаем SID регистрации пользователя и модифицируем ACL рабочей станции и стола соответственно
GetLogonSid(ClientToken, pSid);
AddAceToWindowStation(_WINSTA, pSid);
AddAceToDesktop(_desk, pSid);
// заимствуем права и создаем процесс
ImpersonateLoggedOnUser(ClientToken);
with supInfo do begin
cb:=sizeof(supInfo);
lpDesktop:=PChar('WinSta0\Default');
dwFlags:=STARTF_USEPOSITION or STARTF_USESIZE or STARTF_USECOUNTCHARS or STARTF_USEFILLATTRIBUTE or STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
wShowWindow:=SW_NORMAL;
end;
CreateProcessAsUser(ClientToken, nil, CmdLine[Index], nil, nil, false, CREATE_DEFAULT_ERROR_MODE, nil, LastDir, supInfo, ProcInfo);
RevertToSelf;
SetProcessWindowStation(hwinstaSave);
Вроде как все весело отрабатывает.
После входа в систему на рабочем столе вижу окна запущеных приложений, правда окна имеют немного не тот цвет, но отрисовано вроде правильно.
При попытке вызвать Help из этих приложений получаю пустые рамки окон с графическими багами.
Если успеть залогиниться до того как сервис стартует процессы то все окна открытые из этих процессов отображаются правильно.
Что я делаю не так?