Программирование на Visual C++. Архив рассылки
Шрифт:
Хук | Область видимости |
---|---|
WH_CALLWNDPROC | Поток или вся система |
WH_CBT | Поток или вся система |
WH_DEBUG | Поток или вся система |
WH_GETMESSAGE | Поток или вся система |
WH_JOURNALRECORD | Только система |
WH_JOURNALPLAYBACK | Только система |
WH_FOREGROUNDIDLE | Поток
|
WH_SHELL | Поток или вся система |
WH_KEYBOARD | Поток или вся система |
WH_MOUSE | Поток или вся система |
WH_MSGFILTER | Поток или вся система |
WH_SYSMSGFILTER | Только система |
Для любого данного типа хука, первыми вызываются хуки потоков, и только затем системные хуки.
Есть несколько причин, по которым лучше использовать потоковые хуки вместо системных. Хуки потоков:
• Не создают лишней работы приложениям, которые не заинтересованы в вызове хука.
• Не помещают все события, относящиеся к хуку, в очередь (так, чтобы они поступали не одновременно, а одно за другим). Например, если приложение установит клавиатурный хук для всей системы, то все клавиатурные сообщения будут пропущены через фильтрующую функцию этого хука, оставляя неиспользованными системные возможности многопотоковой обработки ввода. Если эта функция прекратит обрабатывать клавиатурные события, система будет выглядеть зависшей, хотя на самом деле и не зависнет. Пользователь всегда сможет использовать комбинацию CTRL+ALT+DEL для того, чтобы выйти из системы (log-out) и решить проблему, но ему это вряд ли понравится. К тому же, пользователь может не знать, что подобную ситуацию можно решить, войдя в систему под другим именем (log-out/log-in).
• Не требуют нахождения функции-фильтра в отдельной DLL. Все системные хуки и хуки для потоков в другом приложении должны находиться в DLL.
• Им не нужно разделять данные между DLL, загруженными в разные процессы. Фильтрующие функции с системной областью видимости, которые обязаны находиться в DLL, должны к тому же разделять необходимые данные с другими процессами. Так как такое поведение не является типичным для DLL, вы должны принимать специальные меры предосторожности при реализации системных фильтрующих функций. Если функция-фильтр не умеет разделять данные и неправильно использует данные в другом процессе, этот процесс может рухнуть.
SetWindowsHookEx возвращает хэндл установленного хука (тип hhook). Приложение или библиотека должны использовать этот хэндл для вызова функции UnhookWindowsHookEx. SetWindowsHookEx возвращает null если она не смогла добавить функцию к хуку. SetWindowsHookEx также устанавливает код последней ошибки в одно из следующих значений для индикации неудачного завершения функции.
• ERROR_INVALID_HOOK_FILTER: Неверный код хука.
• ERROR_INVALID_FILTER_PROC: Неверная фильтрующая функция.
• ERROR_HOOK_NEEDS_HMOD: Глобальный хук устанавливается с параметром hInstance, равным NULL либо локальный хук устанавливается для потока, который не принадлежит данному приложению.
• ERROR_GLOBAL_ONLY_HOOK: Хук, который может быть только системным, устанавливается как потоковый.
• ERROR_INVALID_PARAMETER: Неверный идентификатор потока.
• ERROR_JOURNAL_HOOK_SET: Для регистрационного хука (journal hook) уже установлена фильтрующая функция. В любой момент времени может быть установлен только один записывающий или воспроизводящий хук. Этот код ошибки может также означать, что приложение пытается установить регистрационный хук в то время, как запущен хранитель экрана.
• ERROR_MOD_NOT_FOUND: Параметр hInstance в случае, когда
• Любое другое значение: Система безопасности не позволяет установить данный хук, либо в системе закончилась память.
Windows сама заботится об организации очереди функций-фильтров (см. рисунок ниже), не доверяя функциям хранение адресов следующих функций в очереди (как поступали Windows до версии 3.1). Таким образом, система хуков в Windows 3.1 и более поздних версий стала гораздо яснее. Плюс к тому, факт хранения цепочки функций-фильтров внутри Windows значительно улучшило производительность.
Для удаления функции-фильтра из очереди хука вызовите функцию UnhookWindowsHookEx. Эта функция принимает хэндл хука, полученный от SetWindowsHookEx и возвращает логическое значение, показывающее успех операции. На данный момент UnhookWindowsHookEx всегда возвращает TRUE.
Фильтрующие (хуковые) функции – это функции, прикрепленные к хуку. Из-за того, что эти функции вызываются Windows, а не приложением, их часто называют функциями обратного вызова (callback functions). Из соображений целостности изложения, эта статья использует термин фильтрующие функции (или функции-фильтры).
Все фильтрующие функции должны быть описаны следующим образом:
Все функции-фильтры должны возвращать LONG. Вместо FilterFunc должно стоять имя вашей фильтрующей функции.
Фильтрующие функции принимают три параметра: nCode (код хука), wParam, и lParam. Код хука – это целое значение, которое передает функции дополнительную информацию. К примеру, код хука может описывать событие, которое привело к срабатыванию хука.
В первых версиях Windows (до 3.1), код хука указывал, должна функция-фильтр обработать событие сама или вызвать DefHookProc. Если код хука меньше нуля, фильтр не должен был обрабатывать событие, а должен был вызвать DefHookProc, передавая ей три своих параметра без изменений. Windows использовала отрицательные коды для организации цепочки функций-фильтров с помощью приложений.
Windows 3.1 также требует при отрицательном коде хука вызывать CallNextHookEx с неизмененными параметрами, плюс к тому функция должна вернуть значение, которое вернет CallNextHookEx. Но Windows 3.1 никогда не посылает фильтрующим функциям отрицательных кодов.
Второй параметр функции-фильтра, wParam, имеет тип WPARAM, и третий параметр, lParam, имеет тип LPARAM. Эти параметры передают информацию фильтрующим функциям. У каждого хука значения wParam и lParam различаются. Например, фильтры хука WH_KEYBOARD получают в wParam виртуальный код клавиши, а в lParam – состояние клавиатуры на момент нажатия клавиши. Фильтрующие функции, прикрепленные к хуку WH_MSGFILTER получают в wParam значение NULL, а в lParam – указатель на структуру, описывающую сообщение. За полным описанием значений аргументов каждого типа хука обратитесь к Win32 SDK for Windows NT, руководствуясь списком фильтрующих функций, приведенным ниже.