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

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

Использование хука из сервиса [D6, WinXP]


Неопытный ©   (2004-01-19 04:46:00) 

При написаниии сервиса столкнулся с проблемой. Необходимо поставить хук типа WH_SHELL (что впрочем не важно). Функция, которая устанавливает хук возвращает true. Но хук не работает.

В DLL использую PostThreadMessage для отправки сообщений сервису.
У меня складывается впечатление, что процедура обработки хука не доходит до конца, хотя там и стоит только PostThreadMessage. Пытался перед ней ставить запись в файл какой-нибудь информации (например того-же дескриптора процесса). Но файл даже не создается, а если и создается, то пустой и его нельзя удалить, потому что он используется. То есть получается, что процедура обработки прерывается еще до закрытия файла. Это может происходить только при запуске сервиса, когда хук ставится и сразу же ловит запуск сервиса, который его и поставил (не пойму, почему). После этого похоже хук падает вообще.

Возможно в этой теме в конце как раз такой случай
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1069096480&n=5

Могу привести исходные тексты, если нужно.


NiaSoft   (2004-01-20 20:49:00) [1]

А у меня надо писать :)


Sting   (2004-01-20 11:50:00) [2]

> NiaSoft
Нет писать никуда ничего не надо.
Доступ на чтение подойдет.

> Digitman
Спасибо. Попробую.


Digitman   (2004-01-20 08:24:00) [3]

кстати, упомянутый бродкаст следует выполнить и сразу после SetWindowsHookEx(), иначе хук не будет сразу же внедрен в некоторые "висящие в трее" процессы а-ля Винамп... можешь убедиться в этом сам, выводя по таймеру список процессов, в которые был внедрен хук сразу после его установки ... как только мышка "поелозит" в зоне иконок трея (читай - система пошлет при этом Винампу соотв.оконное сообщение), ты сразу увидишь появление в списке процессов со внедренным хук-модулем процесс того же Винампа


Digitman   (2004-01-20 08:18:00) [4]


> Sting   (19.01.04 19:06) [14]


сразу после выполнения UnhookWindowsHookEx() (т.е. снятия глоб.хука в ходе завершения или остановки сервиса) выполни

SendMessage(HWND_BROADCAST, WM_NULL, 0, 0);

дело в том, что в трее у тебя наверняка висят разного рода Винампы и иже с ними ... вот в их адресном пр-ве уже после снятия хука и продолжают еще "висеть" экз-ры хук-библ-ки, в контексте которых объеуты глоб.доступа/синхронизации, как ты понимаешь, на этот момент еще не закрыты (оттого и <> 0)

выполнив бродкаст любого dummy-сообщения, ты "подстегнешь" эти оставшиеся процессы, и система выгрузит твою хук-библ-ку и из их АП ... разумеется, сервис должен иметь опцию взаимодействия с дисктопом


NiaSoft   (2004-01-19 23:10:00) [5]

А выше приведенные методы несколько не подойдут, если из из хуков нужно будет писать в расшаренную область памяти, ведь доступ только на чтение.


NiaSoft   (2004-01-19 23:06:00) [6]

Я тут попробовал следующую штуку, и как ни странно с первого раза заработало (такое случается достаточно редко :) )


   SetSecurityInfo(hFileMappingObject, SE_KERNEL_OBJECT,
     DACL_SECURITY_INFORMATION,
     Nil, Nil, Nil, Nil);


данный код вызывыется после создания мап-файла, и дает всем полные права на доступ к объекту.
ЗЫ: Конечно не так хорошо с по отношению к безопастности как хотелось бы, но работает :).


Sting   (2004-01-19 19:06:00) [7]

Вот я тут попробовал приведенный код. И все же не пойму. В первый раз он у меня сработал. А потом опять первый вызов функции OpenMutex выдвал не ноль. После перезагрузки компьютера опять все заработало. После рестарта службы история повторяется. Ведь даже в хэлпе написано, что после того как последний процесс, используюший мьютекс закрывается, то и мьютекс уничтожается. Почему этого не происходит у меня. Дллка выдь из памяти выгружается. И службы тоже нет.


Sting   (2004-01-19 15:50:00) [8]

Ладно. Попробую разобраться.
В любом случае спасибо большое.
Если что, уж тогда через реестр сделаю, хотя при этом DLL получается большая. Еще раз спасибо.


Digitman   (2004-01-19 15:47:00) [9]

ладно, не мучайся

поступи проще - используй мьютекс


function OpenGlobalData: Boolean;
begin
 InitializeSecurityDescriptor(@SecAttr, SECURITY_DESCRIPTOR_REVISION);
 WM_ETKAHOOK:= RegisterWindowMessage(HookMonMsg);
 hMutex := OpenMutex(SYNCHRONIZE, False, MutexName);
 if hMutex = 0 then
   IsFirstInstance := True;
 try
   if IsFirstInstance then
     begin
       hMutex := CreateMutex(@SecAttr, False, MutexName);
       Win32Check(hMutex <> 0);
     end;
   try
     if IsFirstInstance then
       begin
         hMMF:= CreateFileMapping(INVALID_HANDLE_VALUE, @SecAttr, PAGE_READWRITE, 0, SizeOf(GlobalHookData^), MMFName);
         Win32Check(hMMF <> 0);
         try
           GlobalHookData:= MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(GlobalHookData^));
           Win32Check(Assigned(GlobalHookData));
           with GlobalHookData^ do
             begin
               hCallWndProc := 0;
               hCallWndProcRet := 0;
               hMonitor := 0;
             end;
         except
           CloseHandle(hMMF);
           hMMF := 0;
           raise;
         end;
       end
     else
       begin
         WaitForSingleObject(hMutex, INFINITE);
         ReleaseMutex(hMutex);
         hMMF:= OpenFileMapping(FILE_MAP_READ, False, MMFName);
         Win32Check(hMMF <> 0);
         try
           GlobalHookData:= MapViewOfFile(hMMF, FILE_MAP_READ, 0, 0, SizeOf(GlobalHookData^));
           Win32Check(Assigned(GlobalHookData));
         except
           CloseHandle(hMMF);
           hMMF := 0;
           raise;
         end;
       end;
   except
     CloseHandle(hMutex);
     hMutex := 0;
     raise;
   end;
   Result := True;
 except
   Result := False;
 end;
end;

procedure CloseGlobalData;
begin
 if Assigned(GlobalHookData) then
   UnmapViewOfFile(GlobalHookData);
 if hMMF <> 0 then
   CloseHandle(hMMF);
 if hMutex <> 0 then
   CloseHandle(hMutex);
end;


SuperDee   (2004-01-19 15:06:00) [10]

Ты лол


Sting   (2004-01-19 14:51:00) [11]

Вот наваял код:

MapHandle1:=OpenFileMapping(FILE_MAP_READ, false, GlobMapID1);
if MapHandle1 = 0 then
       begin
         MapHandle1:=CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TShareInf), GlobMapID1);
         ShareInfo:=MapViewOfFile(MapHandle1, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TShareInf));
       end else
         ShareInfo:=MapViewOfFile(MapHandle1, FILE_MAP_READ, 0, 0, SizeOf(TShareInf));

После первого вызова OpenFileMapping возвращает не ноль. Почему? Может я что-то с параметрами напутал.


Digitman   (2004-01-19 14:01:00) [12]

да

и, соответственно, последующий вызов MapViewOfFile() должен быть выполнен с теми же правами, что и предыдущий CreateFileMapping или OpenFileMapping, завершившийся успешно


Sting   (2004-01-19 13:58:00) [13]

То есть поставить такой код:
if OpenFileMapping(только чтение)=0 then CreateFileMapping(запись и чтение) ?


Digitman   (2004-01-19 13:24:00) [14]

можно и без выкрутасов с SE обойтись

достаточно просто попытаться сначала выполнить OpenFileMapping(только чтение)

если MMF-объект не существует еще, то это первый экз-р хук-DLL и следует тут же выполнить CreateFileMapping(запись и чтение)


Digitman   (2004-01-19 13:00:00) [15]


> Sting


проблема - в SecurityAttributes при открытии MMF .. необходимо настроить SE должным образом


Sting   (2004-01-19 12:57:00) [16]

А ведь причина действительно кроется в использовании CreateFileMapping. Только что попробовал убрал ее и нужную переменную записал в реестр, все заработало. Конечно хотелось бы обойтись без дополнительных средств, типа реестра, но видимо тут поделать ничего нельзя.


Sting   (2004-01-19 12:21:00) [17]

Все это установлено. Interactive = true.


BiN   (2004-01-19 10:06:00) [18]

скорее всего не установлено взаимодейсвтие с рабочим столом, а точнее с пользовательской средой


Sting   (2004-01-19 07:41:00) [19]

Смотрел. Там есть пример на перехват клавиш. Он у меня прекрасно работает, но не в сервисе. А насчет сервисов я там ничего не видел.


VMcL   (2004-01-19 06:53:00) [20]

В FAQ смотрел? Там пример есть.


Наверх

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