Установка локального хука
- Автор: Still Zero
- Уровень знаний: advanced
- Подразделы: нет
- Дата публикации: 06.12.2005
Впервые прочитав о локальных хуках, я решил, что это абсолютно никчемная вещь. Есть ведь сабклассинг, его вполне достаточно. Но, все-таки дочитал до конца и попробовал в применении. Реальная вещь. Сабклассинг отдыхает 🙂
Устанавливая хук, вы указываете процедуру, которая может обрабатывать сообщения ОС. По сути — тоже что и сабклассинг. Мулька в том, что сообщения приходят в процедуру хука раньше, чем они попадут в сабклассинг. Также, можно установить хук так, чтобы в него попадали сообщения уже после того, как они «побывали» в процедуре окна.
Хуки бывают разных типов. Тип задается при установке хука.
Хук, который отлавливает те же сообщения, которые попадают в процедуру сабклассинга имеет тип WH_CALLWNDPROC.
Хук, обрабатывающий сообщения после того как они побывали в процедуре сабклассинга имеет тип WH_CALLWNDPROCRET.
Глобальный хук распространяется на все запущенные приложения ОС. Локальный только на указанный поток. Поток можно узнать по API GetCurrentThreadId(). Как вы знаете сабклассинг обрабатывает сообщения только для указанного окна. Хук — для потока. Это значит, что в процедуру хука попадут все сообщения для всех контролов окна. Если вы откроете несколько окон в одном потоке, то также сможете обрабатывать сообщения для этих окон. И все в одной процедуре. А если вспомнить про возможность методов-конструкторов в классах с атрибутом THREAD в C6.x вызываться при создании потока, то можно на раз два «захучить» все окна в приложении.
Глобальный хук обязан жить в DLL. Локальный нет, т.е. вы можете разместить код процедуры хука прямо в exe-файле. Нет необходимости в разделении (расшаривании) данных. В процедуре хука можно использовать глобальные переменные.
Установка хука не обязательно должна происходить после открытия окна. При снятии хука вам не надо заботиться о последовательности снятий хуков, если их было установлено несколько штук, как это бывает при сабклассинге.
Устанавливается локальный хук достаточно просто:
hHook = SetWindowsHookEx(WH_CALLWNDPROC,address(MessageProc),0,GetCurrentThreadId())
Третий параметр это хэндл модуля местонахождение хука, если хук находится в этом же модуле, то можно не указывать, если в DLL, то можно узнать по GetModuleHandle().
Процедура хука для разных типов хуков имеет один и тот же прототип, но параметры в этой процедуре сильно различаются для разных типов хуков. Будьте бдительны 🙂
Пример, собственно, ничего полезного не демонстрирует. Просто устанавливается локальный хук и записывает сообщения в очередь, которая отображается в окне. Я отфильтровал несколько сообщений, дабы очередь не заполнялась вечно.
Пример выполнен на C6.2 9048.
LocalHookDemo (1211)
© Project Zero, 2005. Все права защищены.