Чтение онлайн

ЖАНРЫ

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

Из-за того, что фильтры никак не сортируются при помещении их в очередь, вы не можете быть уверены, где находится ваша функция в любой момент времени кроме момента установки, когда ваша функция помещается в самое начало очереди. В результате, вы никогда не можете точно знать, что каждое событие в системе дойдет до вашего фильтра. Фильтрующая функция перед вашей функцией в цепочке – то есть функция, которая была установлена позже вашей – может не передать вам обработку события.

Фильтры в DLL

Фильтрующие функции с системной областью видимости

должны быть реализованы в DLL. В Win16 было возможно (хотя и не рекомендовалось) установить системный хук, находящийся в приложении. Это не сработает в Win32. Ни в коем случае не устанавливайте глобальных фильтров, не находящихся в отдельной DLL, даже если это где-нибудь и работает. Регистрационные хуки, WH_JOURNALRECORD и WH_JOURNALPLAYBACK, являются исключением из правила. Из-за того, как Windows вызывает эти хуки, их фильтрующим функциям не обязательно находиться в DLL.

Фильтрующие функции для хуков с системной областью видимости должны быть готовы разделять свои данные между разными процессами, из которых они запускаются. Каждая DLL отображается в адресное пространство использующего ее клиентского процесса. Глобальные переменные в DLL будут таковыми лишь в пределах одного экземпляра приложения, если только они не будут находиться в разделяемом сегменте данных (shared data section). Например, библиотека HOOKSDLL.DLL в примере Hooks использует две глобальные переменные:

• Хэндл окна для отображения сообщений.

• Высоту строк текста в этом окне.

Для того, чтобы сделать эти данные общими для всех экземпляров библиотеки, HOOKSDLL помещает их в разделяемый сегмент данных. Для этого HOOKSDLL предпринимает следующие шаги:

• Использует директивы компилятора (pragma) для помещения данных в именованный сегмент данных. Заметьте, что при этом переменные должны быть обязательно инициализированы.

// Shared DATA

#pragma data_seg(".SHARDATA")

static HWND hwndMain = NULL; // Главный hwnd. Мы получим его от приложения.

static int nLineHeight = 0; // Высота строк в окне.

#pragma data_seg

Добавляет блок SECTIONS в .DEF-файл библиотеки:

SECTIONS

 .SHARDATA Read Write Shared

Создает .EXP-файл из .DEF-файла:

hooksdll.exp: hooksdll.obj hooksdll.def

 $(implib) –machine:$(CPU) \

 –def:hooks.def \

 hooksdll.obj \

 –out:hooksdll.lib

Прилинковывает получившийся файл HOOKSDLL.EXP:

hooksdll.dll: hooksdll.obj hooksdll.def hooksdll.lib hooksdll.exp

 $(link) $(linkdebug) \

 –base:0x1C000000 \

 –dll \

 –entry:LibMain$(DLLENTRY) \

 –out:hooksdll.dll \

 hooksdll.exp hooksdll.obj hooksdll.rbj \

 $(guilibsdll)

Типы хуков
WH_CALLWNDPROC

Windows

вызывает этот хук при каждом вызове функции SendMessage. Фильтрующей функции передается код хука, показывающий, была ли произведена посылка сообщения из текущего потока, а также указатель на структуру с информацией о сообщении.

Структура CWPSTRUCT описана следующим образом:

typedef struct tagCWPSTRUCT {

 LPARAM lParam;

 WPARAM wParam;

 DWORD message;

 HWND hwnd;

} CWPSTRUCT, *PCWPSTRUCT, NEAR *NPCWPSTRUCT, FAR *LPCWPSTRUCT;

Фильтры могут обработать сообщение, но не могут изменять его (хотя это было возможно в Win16). Сообщение затем отсылается той функции, которой и предназначалось. Этот хук использует значительное количество системных ресурсов, особенно, когда он установлен с системной областью видимости, поэтому используйте его только в целях отладки.

WH_CBT

Чтобы написать приложение для интерактивного обучения (CBT application), разработчик должен координировать его работу с работой приложения, для которого оно разрабатывается. Для достижения этой цели Windows предоставляет разработчикам хук WH_CBT. Windows передает фильтрующей функции код хука, показывающий, какое произошло событие, и соответствующие этому событию данные.

Фильтр для хука WH_CBT должен знать о десяти хуковых кодах:

• HCBT_ACTIVATE

• HCBT_CREATEWND

• HCBT_DESTROYWND

• HCBT_MINMAX

• HCBT_MOVESIZE

• HCBT_SYSCOMMAND

• HCBT_CLICKSKIPPED

• HCBT_KEYSKIPPED

• HCBT_SETFOCUS

• HCBT_QS

HCBT_ACTIVATE

Windows вызывает хук WH_CBT с этим кодом при активации какого-нибудь окна. Когда хук WH_CBT установлен как локальный, это окно должно принадлежать потоку, на который установлен хук. Если фильтр в ответ на это событие вернет TRUE, окно не будет активизировано.

Параметр wParam содержит хэндл активизируемого окна. В lParam содержится указатель на структуру CBTACTIVATESTRUCT, которая описана следующим образом:

typedef struct tagCBTACTIVATESTRUCT {

 BOOL fMouse; // TRUE, если активация наступила в результате

 // мышиного клика; иначе FALSE.

 HWND hWndActive; // Содержит хэндл окна, активного

 // в настоящий момент.

} CBTACTIVATESTRUCT, *LPCBTACTIVATESTRUCT;

HCBT_CREATEWND

Windows вызывает хук WH_CBT с этим при создании окна. Когда хук установлен как локальный, это окно должно создаваться потоком, на который установлен хук. Хук WH_CBT вызывается до того, как Windows пошлет новому окну сообщения WM_GETMINMAXINFO, WM_NCCREATE, или WM_CREATE. Таким образом, фильтрующая функция может запретить создание окна, вернув TRUE.

Поделиться с друзьями: