Здравствуйте, okman, Вы писали:
O>Здравствуйте, Maclaud, Вы писали:
M>>Опиши пожалуйста второй способ.
M>>У меня как раз задача, есть сервис и нужно чтобы он запускал себя же (в смысле свой exe) с теми же правами но в консольной сессии.
M>>За ранее благодарю.
O>Несколько основных положений:
O>1. Сервис должен выполняться от имени LocalSystem, иначе некоторые функции будут недоступны.
O>2. При старте нужно подписаться на событие SERVICE_ACCEPT_SESSIONCHANGE.
O>Любые события, связанные со входом и выходом пользователя из системы, включая
O>терминальный доступ, будут проходить через обработчик (HandlerEx), а по параметрам
O>легко определить тип события (например, WTS_SESSION_LOGON, см. WTSSESSION_NOTIFICATION).
O>Я настоятельно рекомендую сделать демо-сервис с записью событий в журнал, а затем
O>поэкспериментировать с тем, какие события и когда вызываются, особенно в контексте
O>быстрого переключения пользователей и терминальных сеансов. Потому что кроме событий
O>logon/logoff есть еще connect/disconnect, которые вносят некоторую путаницу.
O>3. Id сессии, в которой произошло событие, нужно получать именно из обработчика, а
O>не путем всяких WTSGetActiveConsoleSessionId, потому что так можно будет вести учет того,
O>какие сеансы у нас запускаются, а какие отключаются.
O>4. Есть один подводный камень, связанный с запуском службы и перехватом первого логина.
O>Дело в том, что если используется простой вход в систему (минуя окно ввода имя
O>пользователя и пароля), служба в некоторых случаях может не успеть запуститься.
O>То есть, событие первого входа в систему не будет перехвачено.
O>Я не знаю, каков рекомендованный MSDN способ обхода этого ограничения и поступаю так -
O>всегда указываю принадлежность своей службы группе "Boot Bus Extender".
O>Радикально, но работает.
O>5. Id сессии, в которой произошел вход в систему, нужно запомнить.
O>Потому что это — "наше все". По нему можно определить имя пользователя, тип сеанса
O>(консольный или терминальный) и многие другие данные, см. WTSQuerySessionInformation.
O>Еще один ключевой показатель — маркер безопасности пользователя.
O>Получается с помощью WTSQueryUserToken.
O>Допустим, некто вошел в систему и мы знаем Id его сессии, а также получили маркер безопасности.
O>И нужно создать в его сессии интерактивный процесс, выполняющийся в контексте безопасности
O>нашей службы (LocalSystem).
O>Последовательность действий примерно такова:
O>1. Заполняем структуру STARTUPINFO, в lpDesktop пишем "WinSta0\Default".
O>2. Создаем новый маркер безопасности:
O>O>DuplicateTokenEx(hProcessToken, // получается с помощью OpenProcessToken.
O> MAXIMUM_ALLOWED,
O> NULL,
O> SecurityDelegation,
O> TokenPrimary,
O> &hNewToken);
O>
O>В созданном маркере устанавливаем Id сессии:
O>O>SetTokenInformation(hNewToken,
O> TokenSessionId,
O> &IdSession,
O> sizeof (IdSession));
O>
O>3. Создаем процесс с помощью CreateProcessAsUser, первым
O>аргументом передается новый маркер безопасности.
O>Созданный процесс будет отображаться в диспетчере задач как SYSTEM и его
O>нельзя будет "прибить" из-под неадминистраторской учетки, но при этом он
O>приаттачен к пользовательской сессии и полностью интерактивен.
O>Со всеми, так сказать, вытекающими.
O>Процессы, создаваемые описанным выше способом, имеют несколько особенностей.
O>Во-первых, происходит путаница с пользовательскими профилями.
O>Во-вторых, такой процесс представляет собой потенциальную дыру в безопасности.
O>В-третьих, при выходе из системы пользователя процесс уничтожается как и все
O>оконные — то есть, не позже обработки WM_ENDSESSION.
O>Есть и другие особенности, но они специфичны и к теме отношения не имеют.
O>Собственно, все.
Спасибо за ответ. Я так понял тут основной момент это установка ID сессии в новом маркере.
А OpenProcessToken как процесс сервиса я так понял делается?