Здравствуйте, Disappear, Вы писали:
D>Сразу скажу, что я перечитал все похожие топики, — не нужно на них ссылаться.
Видимо, все-таки, не все, потому что года полтора-два назад это уже обсуждалось. Что-то вроде "Запуск Outlook Express из службы".
D>Такова проблема:
D>Нужно запустить любую программу из моего системного севиса, да так, чтобы программа запустилась не в виде системного процесса, а как процесс текущего пользователя. Того, кто в настоящий момент залогинен в системе.
D>В статье http://www.microsoft.com/msj/0200/logon/logon.aspx я этого найти не смог, либо чего не понял.
D>Сейчас процессы запускается через CreateProcess, также реализована интерактивность через OpenWindowStation и OpenDesktop, но всеравно все процессы запускаются, как системные, поэтому им недоступен пользовательский реестр и т.д...
D>Как запустить процесс под текущим юзером, если я не знаю его username and pass????
Очень просто. Надо вызвать СreateProcessAsUser, указав в качестве токена токен интерактивного пользователя. Прежде чем приступить к перечислению способов получения этого токена, напомню, что в системе может быть более одного интерактивного пользователя. Поэтому прежде всего предлагаю подумать о том, как узнать, в контексте какого из интерактивных пользователей нужно запустить процесс. Именно эта часть задачи представляется мне наиболее интересной.
А токен можно получить несколькими способами:
1) [простой и надежный способ, работает на всех системах] Делается небольшая программа, которая регистируется в HKLM\Software\Microsoft\Windows\CurrentVersion\Run. При запуске программа соединяется со службой используя COM, RPC или named pipes. C одной стороны, это позволяет узнать службе о факте входа интерактивного пользователя в систему, а с другой — служба может имперсонировать соединение (CoImpersonateClient, RpcImpersonateClient, ImpersonateNamedPipeClient) и получить токен пользователя (OpenThreadToken). Tаким образом получается так называемый impersonation token, который нужно преобразовать в primary token с помощью DuplicateTokenEx, прежде чем можно будет вызвать CreateProcessAsUser.
2) [очень простой и в тоже время надежный способ, WinXP and later] WTSEnumerateSessions и WTSQueryUserToken. Таким образом получаются токены для всех интерактивных сессий в системе.
3) [вариация первого способа, Win2K and later] Написать Winlogon notification package, в котором отследить вход пользователя в систему и получить его токен.
4) [не очень надежный способ, к которому у меня персональная антипатия] Перечислить все процессы, найти процесс оболочки и получить токен этого процесса с помощью OpenProcessToken. Очевидная проблема в том, что процесса оболочки может и не существовать. Кроме того, надо аккуратно обрабатывать ситуации когда таких процессов несколько, так как они могут принадлежать как одной интерактивной сессии, так и разным.