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

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

Странная проблема с Хуком [WinXP]


Nostradamus ©   (2006-05-18 17:37:00) 

Я использую в своей программе хук WH_CALLWNDPROCRET.
Заметил странный побочный эффект: если запустить определённую программу (на пример IE), потом мою и потом закрыть IE, то он (IE) крэшится.
Вот хук:

library hookshell;

uses
 Windows, Messages;

const
 MapID = 'CALLWND_Hook';

type
 PData = ^TData;
 TData = record
   AppWnd: HWND;
   OldHook: HHOOK;
 end;

var
 HMap: THandle = 0;
 Data: PData = nil;

procedure DLLEntryPoint(dwReason: Integer);
begin
 case dwReason of
   DLL_PROCESS_ATTACH:
     begin
       HMap := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TData), MapID);
       Data := MapViewOfFile(HMap, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TData));
     end;
   DLL_PROCESS_DETACH:
     begin
       UnMapViewOfFile(Data);
       CloseHandle(HMap);
     end;
 end;
end;

function ShellHook(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT; stdcall;
var
WS : CWPRETSTRUCT;
begin      
 if Code < 0 then
  Result := CallNextHookEx(Data^.OldHook, Code, ParamW, ParamL)
 else begin
  if Code =  HC_ACTION then begin
   WS := CWPRETSTRUCT(Pointer(ParamL)^);
   if (WS.message = WM_ACTIVATE) OR (WS.message = WM_SETFOCUS) OR (WS.message = WM_SHOWWINDOW) then
    SendMessage(Data^.AppWnd, WM_USER, WS.message, ParamL);
  end;
  Result := CallNextHookEx(Data^.OldHook, Code, ParamW, ParamL) //если сдесь сделать Result := 0, то побочный эффект не происходит
end;
end;

function SetShellHook(Wnd: HWND): BOOL; stdcall;
begin
 if Data <> nil then
 begin
   Data^.AppWnd := Wnd;
   Data^.OldHook := SetWindowsHookEx(WH_CALLWNDPROCRET, @ShellHook, HInstance, 0);
   Result := Data^.OldHook <> 0
 end
 else Result := False;
end;

function RemoveShellHook: BOOL; stdcall;
begin
 Result := UnhookWindowsHookEx(Data^.OldHook);
end;

exports
 SetShellHook,
 RemoveShellHook;

begin
DllProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.


Что интересно, если не возвращать результат CallNextHookEx, то этот феномен не наблюдается.

Подскажите, пожалуйста, в чём может быть проблема.


Leonid Troyanovsky   (2006-05-24 18:20:00) [1]


> Nostradamus ©   (23.05.06 21:49) [7]

> DLL_PROCESS_DETACH и после того как я запускал какое-то
> приложение паралельно моему и закрывал его, то код в DLL_PROCESS_DETACH
> выполнялся (не смотря на то, что я не вызывал DLLEntryPoint
> и моя программа работала дальше). У меня такое ощущение,
>  что моя DLL подгружается другими приложениями...


Что-то не очень понятно.
Сначала ты устанавливаешь глобальный хук (на все потоки,
последний параметр 0), а после удивляешься тому,
что твоя бибиотека загружается другими процессами.
Если тебя интересует конкретный поток, задай его threadId,
получить который можно, например, GetWindowThreadProcessId.

--
Regards, LVT.


Nostradamus   (2006-05-23 21:49:00) [2]

Я использовал совет Leonid Troyanovsky ©   (19.05.06 18:09) [5] и добавил UnhookWindowsHookEx(Data^.OldHook); в DLL_PROCESS_DETACH и после того как я запускал какое-то приложение паралельно моему и закрывал его, то код в DLL_PROCESS_DETACH выполнялся (не смотря на то, что я не вызывал DLLEntryPoint и моя программа работала дальше). У меня такое ощущение, что моя DLL подгружается другими приложениями...
Единственное объяснение, которое мне приходит в голову, это тот факт, что у меня в самой программе вызывается AttachThreadInput. Я предполагаю, что именно те программы к которым атачится мой процесс и подгружают ДЛЛ.
Вопрос теперь в том как это предотвратить???


Nostradamus   (2006-05-20 03:41:00) [3]

Спасибо за советы, обязательно ими воспользуюсь


Leonid Troyanovsky   (2006-05-19 18:09:00) [4]


> Nostradamus   (18.05.06 17:37)  


Проблемы, видимо, с теми (многопоточными?) приложениями,
которые сами используют хуки, т.е., во взаимодействии с оными.
По всей видимости, порядок имеет значение, и стоит, IMHO,
попробывать включить вызов RemoveShellHook в обработчик
DLL_PROCESS_DETACH.

Ну, а для избежания повторного UnHook после Remove
обнулять OldHook (с проверкой в хуковой процедуре).

--
Regards, LVT.


Nostradamus   (2006-05-19 16:16:00) [5]

В том то и дело, что делаю всё, так сказать, по учебнику...

Конечно может быть, что программы у которых наблюдается такой эффект криво написаны, но странно что их есть N и от разных производителей.
Этот эффект наблюдается с: MS IE 6, MS Outlook, Skype 2, Babylon

Одним словом, пока установил Result := 0, чтоб заказчик не морочил голову, но мне это решение очень не нравится :(


Игорь Шевченко   (2006-05-19 13:39:00) [6]


> Но тем не менее MSDN рекомендует вызывать CallNextHookEx()
> только при условии Code < 0


Вообще-то во всех случаях рекомендует вызывать

"Calling CallNextHookEx is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications"


Сергей М.   (2006-05-19 13:23:00) [7]

Извиняюсь, я не прав.

Но тем не менее MSDN рекомендует вызывать CallNextHookEx() только при условии Code < 0


Сергей М.   (2006-05-19 13:19:00) [8]

А нафига ты допускаешь 2 раза вызов CallNextHookEx() ?

Первый раз - при условии Code < 0, второй - вообще безусловно ..

Для начала убери безусловный вызов !


Наверх

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