Трудно понять, какие у тебя проблеммы с декстопами. Ведь на практике всё это чудо делаеться за один заход сервисом. Потому во избежании недопонимания предлагаю „упрощенную” схему создания системного процесса. Маленькая экскурсия в теорию: 1) AdjustTokenPrivileges – способна лишь изменить состояние привилегии Disable\Enable. При создании токена, система сама указывает привилегии. Их можно лишь активизировать, или наоборот скинуть. Посмотреть какие привилегии доступны процессу можно с помощью «Process Explorer» Марка Руссиновича (Properties->Security). Скажем так – для пользователя там привилегий не густо. 2) Если необходимо добавить отсутствующие привилегии и, естественно, активизировать их - используют ZwCreateToken. После чего вызовом CreateProcessAsUser создают процесс с новым набором привилегий. 3) Есть функция ZwSetInformationToken - „устанавливает информацию, влияющую на объект маркера”. Да вот беда, из 12 информационных классов, установке подлежат лишь 4 – TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSessionId. Класс TokenPrivileges установке не подлежит (можно только читать). На эту функцию люди или забивают или правят сам объект токена (с режима драйвера). Это не есть гуд, так как объект не документирован, изменения происходят без ведома системы и т.д. и т.п. У меня после таких фокусов система не падала „почти” пару минут. Итак. Схема такова. 1. сервис. Пусть будет Father. 2. пользовательский процесс. Пусть будет Mother. 3.пользовательская программа, которой необходимы привилегии. 1) Mother сообщает Father свой PID. Используешь средства межпроцессного взаимодействия: пайпы, окошка, атомы, проецированные файлы … 2) Father берёт свой токен, и дублирует его для Mother. Код (Text): //Получить токен текущего процесса Father. HANDLE hFatherToken; OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hFatherToken); //Получить описатель процесса Mather используя PID. DWORD MatherPID = 0x??????; HANDLE hProcMather = OpenProcess(PROCESS_ALL_ACCESS, false, MatherPID); //Дублировать токен. HANDLE hDuplicateFatherToken;//После дублирования нужно передать эту "штуку" в Mather. DuplicateHandle( GetCurrentProcess(), hFatherToken, hProcMather, &hDuplicateFatherToken, 0, FALSE, DUPLICATE_SAME_ACCESS ); 3) Father ставит в известность Mother, что мол получай мой токен. Средства межпроцессного взаимодействия. 4) Mother спрашивает у юзера, какой процесс должен стать системным. 5) Mother с помощью CreateProcessAsUser(hDuplicateFatherToken, …) создаёт системный процесс для юзера. Код (Text): STARTUPINFO si; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); PROCESS_INFORMATION pi; //В примере запускаем командный интерпретатор. CreateProcessAsUser( hDuplicateFatherToken , 0, "cmd.exe", 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, &si ,&pi ); P.S. Если ты начнёшь всё это реализовывать, то очень скоро пропадёт желание так играться ради призрачной проблемы десктопов. И возможно тогда ты вернешься к простому варианту, когда сервис вызывает CreateProcessAsUser, задав перед этим si.lpDesktop = "WinSta0\\Default"; Вот и сказке конец, а кто читал – молодец.
IMHO не стоит так делать (повышать привилегии юзерского процесса). Так можно создать нехилую дыру в безопасности. Если это всё не для внутреннего пользования конечно... Лучше, как уже советовали, сделать юзерский процесс клиентом сервиса, который будет делать всю привилегированную работу. Средствами RPC или COM межпроцессное взаимодействие делается довольно прозрачным.
Zero Ice Насчёт десктопов - утилитка перечисляет окна, Station, Desktop: hххp://www.anticracking.sk/EliCZ/export/EnumWD.zip
2DelExe OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hFatherToken); Этот токен позволяет запустит приложение, но есть непонятный глюк - если прога запушена под админом, то полчив токен делаю CreateProcessAsUser и получаю cmd.exe с правами SYSTEM, если же запускаю прогу под гостем - токен есть, но CreateProcessAsUser проваливается. GetLastError == 2 (Не удается найти указанный файл). Прописывал полный путь к exe - не помогло.
Прототип функции: BOOL CreateProcessAsUser( HANDLE hToken, LPCTSTR lpApplicationName, LPTSTR lpCommandLine, ....) Попробуй передавать "cmd.exe" не в параметре lpCommandLine, а в lpApplicationName (тогда вместо lpCommandLine поставь 0).
Пробовал. Тут что-то не то. Уже сам замучился с этой проблемой и всех достал, но салюшина так пока и не нашел. Проблема в том, что когда даешь токен непривелигированному процу, то у него видать не хватает привелегий для использования этого токена. Значит всё надо установить в сервисе. А ХЗ как это делать... Буду рыть дальше. Если найду ришение - выложу тут.
MSDN: "Typically, the process that calls the CreateProcessAsUser function must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges." Сервис создаётся с флагом SERVICE_INTERACTIVE_PROCESS ? При этом твой "приподнятый" процесс не могёт десктоп юзать ?
Знаю про эту привилегию. И флаг SERVICE_INTERACTIVE_PROCESS. Но мне больше интересно как права дать. Как его приподнять? (убийство и запуск с правами system не особо радует)