Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Запуск приложений из сервиса с правами не LocalService [D7, WinXP]


Страницы:   1 2

Шуршик ©   (2005-03-04 03:35:00) 

Есть системный сервис, работающий под правами LOCAL SERVICE, необходимо через определённые промежутки времени запускать из него внешнюю программу.

Если запускать её как обычно (CreateProcess, все настройки по-умолчанию), то запускается дочерний к сервису процесс с пользователем LOCAL SERVICE. А мне надо бы, чтобы он запускался для пользователя, который работает в данный момент в системе. Как запустить процесс для текущего пользователя?

Я нашёл функции CreateProcessAsUser и LogonUser, но они требуют пары ИмяЮзера/Пароль. В тоже время некоторые системные сервисы умеют запускать процессы для уже залогиненых пользователей в системе. Они же не спрашивают пароля? Не могу никак найти, как же сделать так, чтобы, не спрашивая пароля для учётной записи пользователя, запустить из службы другой процесс с правами некоторого пользователя, с учётом того, что он уже вошёл в систему???


kami   (2005-04-16 15:21:00) [1]

WTSQuerySessionInformation(0,WTSGetActiveConsoleSessionId,WTSUserName,@UserName,pr);


Andr-04   (2005-04-16 14:45:00) [2]

Точнее, не самого пользователя, а лишь его имени :)). Если нет, то какая(какие) функция(функции) это может(могут) сделать?


Andr-04   (2005-04-16 14:44:00) [3]

Точнее, не самого пользователя, а лишь его имени :)). Если нет, то какая(какие) функция(функции) это может сделать?


kami   (2005-04-16 14:43:00) [4]

посмотрите на
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/enabling_and_disabling_privileges_in_c__.asp

Но если запускаете сервисом, то привилегия имеется:
The LocalSystem account has the following privileges:

SE_ASSIGNPRIMARYTOKEN_NAME
SE_AUDIT_NAME
SE_BACKUP_NAME
SE_CHANGE_NOTIFY_NAME
SE_CREATE_PAGEFILE_NAME
SE_CREATE_PERMANENT_NAME
SE_CREATE_TOKEN_NAME
SE_DEBUG_NAME
SE_INC_BASE_PRIORITY_NAME
SE_INCREASE_QUOTA_NAME
SE_LOAD_DRIVER_NAME
SE_LOCK_MEMORY_NAME
SE_PROF_SINGLE_PROCESS_NAME
SE_RESTORE_NAME
SE_SECURITY_NAME
SE_SHUTDOWN_NAME
SE_SYSTEM_ENVIRONMENT_NAME
SE_SYSTEM_PROFILE_NAME
SE_SYSTEMTIME_NAME
SE_TAKE_OWNERSHIP_NAME
SE_TCB_NAMESE_UNDOCK_NAME

(c)MSDN


Andr-04   (2005-04-16 14:41:00) [5]

А вообще данная функция даст мне строковое значение пользователя по его SessionID?


Игорь Шевченко   (2005-04-16 14:37:00) [6]

Andr-04   (16.04.05 14:15) [30]


> The caller does not have the SE_TCB_NAME privilege". Соответственно,
> как эту SE_TCB_NAME привелегию получить?


Соответственно, эта привилегия по умолчанию имеется у учетной записи LocalSystem. У всех другие ее нет, если очень хочется, то надо явно прописывать у учетной записи.


Andr-04   (2005-04-16 14:15:00) [7]

Блин? Что-то я сначала напишу, а потом думаю... GetLastError возвращает 1314. Это значит, что "The caller does not have the SE_TCB_NAME privilege". Соответственно, как эту SE_TCB_NAME привелегию получить?


Andr-04   (2005-04-16 13:52:00) [8]

Ой, простите за невежливость - забылся, не только здесь писал... Кого можно на ты, а кого надо на Вы, хотя, я лично, на ты называю после получения на то разрешения. Ладно. С процедурой WTSGetActiveConsoleSessionId разобрался (никак не мог понять, почему всё время возвращается 0, но когда запустил программу от имени второго вошедшего в систему пользователя, то вернулась 1 - стало всё понятно). Теперь другая проблема - не могу разобраться с функцией WTSQueryUserToken. Почему-то значение второго параметра не изменяется. Его нужно как var описывать или не обязательно (в описании самой функции)? И ещё: можно ли получить строковое имя пользователя при помощи этой процедуры? Если нет, то какую функцию (процедуру) для этого нужно использовать? Заранее спасибо.


kami   (2005-04-14 21:08:00) [9]

2 [26] Andr-04   (14.04.05 20:25)
In first, не ты а Вы. Смотреть надо хотя бы на значек ©
In second Гюльчатай, покажи личико? ибо User Anonimus. Access denied
Ну и в-третьих Велика и могучи русская языка!


mgcr   (2005-04-14 20:52:00) [10]

Andr-04   (14.04.05 20:25) [26]

kernel32.dll


Andr-04   (2005-04-14 20:25:00) [11]

А ты, Набережных С., где откапал процедуру WTSGetActiveConsoleSessionId? В WTSApi.dll ничего подобного я не нашёл...


Набережных С.   (2005-03-12 16:14:00) [12]

Нашел для XP. Ведь разбирался когда-то, и помню же, что совсем просто должно быть, а вот ведь как заклинило, а:( В общем, схема такая:

function ExecuteOnSession(SessionID: DWORD; const AppName: string): THandle;
var
 H: THandle;
 SI: TStartupInfo;
 PI: TProcessInformation;
begin
 Result:=0;
 if not WTSQueryUserToken(SessionID, H) then Exit;

 try

   FillChar(SI, SizeOf(SI), 0);
   SI.cb:=SizeOf(SI);
   if CreateProcessAsUser(H, nil, 'Notepad.exe', nil, nil, false,
                    CREATE_NEW_CONSOLE,  nil, nil, SI, PI) then
   begin
     CloseHandle(PI.hThread);
     Result:=PI.hProcess;
   end;

 finally
   CloseHandle(H);
 end;
end;

function ExecuteAsIU_XP(const AppName: string): THandle;
var
 SessionID: DWORD;
begin
 SessionID:=WTSGetActiveConsoleSessionId;
 Result:=ExecuteOnSession(SessionID, AppName);
end;

Проверено на XP Pro SP2.

P.S. Да здравствует Пиво - главная движущая сила IT-индустрии!:)))


Шуршик   (2005-03-10 03:27:00) [13]

Ничего-ничего, правильный разговор завели :))))

Спасибо всем огромное! Узнал много нового...

З.Ы. а хитрый, однако, способ :)


ламер_   (2005-03-09 21:31:00) [14]

Спасибо !!! Все понял, что надо учиться. Спокойной ночи !!!


Набережных С.   (2005-03-09 21:07:00) [15]

CoInitialize/CoUninitialize производит инициализацию/деинициалиазацию подсистемы COM для данного потока, там много чего делается. НО! действие оказывает только самая внешняя пара, все остальные, вложенные, завершатся ошибкой, однако, для соблюдения баланса, для каждого вызова CoInitialize должен быть сделан парный вызов CoUninitialize, вне зависимости от успешности/неуспешности CoInitialize. Здесь, в принципе, фрейм должен быть внешний, вне функции. Но так как такой фрейм есть и внутри, то ничего страшного не произойдет, даже если снаружи инициализации не будет, просто полученный из функции интерфейс нельзя будет использовать.

> IUnknown::Release

Это совсем из другой оперы. Delphi сама делает вызовы AddRef и Release по мере надобности, так что вызывать их вручную требуется только в редких, особых случаях. Здесь все интерфейсы кроме выходного будут автоматически освобождены при выходе из функции.

Мы с тобой совсем уже ушли от темы ветки, давай-ка закругляться, брат:) Если интересно, создавай ветки, я не единственный на этом форуме, кому все это известно, можешь быть уверен:))
Да и спать мне уже пора. Спокойной ночи:)


ламер_   (2005-03-09 20:36:00) [16]


> Не понял, о каком ты Release толкуешь.

Я про тот же MKParseDisplayName&CreateBindCtx и их последний параметр :
ppmk
[out] Address of IMoniker* pointer variable that.... When successful, the function has called IUnknown::AddRef on the moniker and the caller is responsible for calling IUnknown::Release. Ну и для остальных функций - то же самое, т.е.если я правильно понял, то MSDN предлагает вызвать Release для Moniker и Bind.


> А про CoInitialize/CoUninitialize почитай обязательно

Почитал, перед тем как писать [19]. Возник вопрос - а ежели (буде прибавится навыков и знаний) модифицируется код - (моить, появятся другие COM-объекты) ее нужно будет заменять? как я понял, она сам поток-то не закрывает, просто обрубает все "контакты"?

А смутило в основном:Only the CoUninitialize call corresponding to the CoInitializeor CoInitializeEx call that initialized the library can close it.


Набережных С.   (2005-03-09 20:09:00) [17]

1) MkParseDisplayName принимает указатель на первый символ строки из Wide Chars, заканчивающийся двумя нулями. Мы и даем ей такой адрес. Почти то же самое получится, если написать PWideChar(ws), но я предпочитаю такую запись, если точно известно, что строка не пустая. Передавать длину нет нужды, признаком конца служат два завершающих нуля.

2) В описании MkParseDisplayName этого, разумеется, нет. Это строка служит для инициализации моникера и ее соднржимое полность определяется задачей. Грубо говоря, она служит для связывания моникера с объектом и с данными, которыми его следует инициализировать, или определяет место расположения объекта, или, как в данном случае, контекст активации объекта. В общем, прими за данность:) Тема моникеров очень сложная, пожалуй, самая сложная в COM. Не объяснишь ни в двух, ни в двадцати словах, слишком издалека надо начинать.
Здесь эта строка просто указывает моникеру какой объект нас интересует и в каком пользовательском контексте его следует активировать.

3) Не понял, о каком ты Release толкуешь. А про CoInitialize/CoUninitialize почитай обязательно. Если тебя COM интересует. А если не интересует, то просто оставь как есть:)

Оффтопик : Бог помогает(надеюсь):))


ламер_   (2005-03-09 19:31:00) [18]

2  [18] Набережных С. ©   (09.03.05 17:34)


> А мне казалось, что я понятно изложил:

Прошу прощения, невнимательно прочитал - времени было мало. Ухватил только "но нужен локальный СОМ-сервер"Теперь, с последними пояснениями - почти кристально ясно. Осталась пара вопросов :
1)@ws[1] :Pointer to a zero-terminated wide character string (two bytes per character) containing the display name to be parsed - почему указатель на первый символ? или все дело в zero-terminated, так что длина строки не нужна ?
2) Ткните, пожалуйста, что называется носом в правила формирования строки ws - что-то в объявлении MkParseDisplayName я не нашел параметров Session и CLSID
3) Корректно ли вызывать CoUninitialize, или же, как пишет контора -  Release
Заранее спасибо.

Оффтопик : как Вы это все находите ???


Набережных С.   (2005-03-09 17:34:00) [19]


> ламер_   (09.03.05 14:41) [17]

СОМ сервер надо смому написать и зарегистрировать. А мне казалось, что я понятно изложил:( Цитата:

> Делаем COM сервер, в нем объект, реализующий следующий интерфейс

Т.е. надо создать новый проект приложения(не библиотеки!), добавить в него Automation object, назвать его Executor(чтобы меньше править приведенный выше код), и в его интерфейс добавить метод Execute. Откомпилировать и запустить один раз. Затем запустить DcomCnfg, найти в списке этот свой сервер и установить ему запуск от имени интерактивного пользователя. А в локальную константу записать ClsId этого созданного тобой объекта.

Суть этого дела в том, что мы создаем существующий в системах от W2k и выше моникер, с помощью биндера связываем его с нашим, написанным нами объекта, получаем интерфейс фабрики классов этого объекта и через него создаем уже наш объект. Вся схема предназначена для активации COM-серверов в контексте пользователя. А так как мы определили в нашем объекте метод Execute, то мы можем использовать его для запуска в контексте пользователя любого приложения.

Я уже проверил это дело в XP Pro SP2, работает как часы. Желательно бы еше в Home и в 2003.


ламер_   (2005-03-09 14:41:00) [20]

Желающие есть. Com-server - где он? если в службах, то понятно. Если нет, то где его включать ?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо