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



Вопросы
  Числовой формат ячейки в Excel
   Категория: Базы данных
  Отступ в Memo
   Категория: Компоненты
  Получить имена всех папок и файлов в директории
   Категория: Файловая система
  Создание ярлыка на Рабочем столе
   Категория: Приложение
  Распознавание кодировки. Перекодировка.
   Категория: Текст и строки
  Получение списка всех сетевых дисков из Delphi
   Категория: Интернет и Сети
  Перегенерировать все индексы Dbase
   Категория: Базы данных
  Корректное колесико мыши
   Категория: Приложение
  Пароль на ADO
   Категория: Базы данных
  Компонент HotKey
   Категория: Компоненты

Delphi - База Знаний: Что такое хук (hook)?

  << Вернуться к Содержанию  

hook - это механизм перехвата сообщений, путем установки специальной функции на верх стека hook-функций системы.
Без установки таких ловушек практически невозможно обойтись при написании различных средств удаленного администрирования, шпионов и других программ в той или иной степени осуществляющих контроль
за пользователем, использующем ОС windows.
hook'и бывают глобальные (на всю систему) и локальные (на какой-либо поток).
Установить в систему hook можно при помощи функции setwindowshookex(), со
следующим заголовком:

hhook setwindowshookex(int idhook, hookproc lpfn, hinstance hmod, dword
dwthreadid);


Если ты плохо воспринимаешь Си-шный код, на delphi заголовок выглядит так:

setwindowshookex(idhook: integer; lpfn: tfnhookproc;
hmod: hinst; dwthreadid: dword): hhook;


Функция setwindowshookex() в случае установки hook'a возвращает
его дескриптор, в случае ошибки возвращает 0.

Разберем подробней все входящие параметры этой функции:

1. idhook - константа, определяет типа устанавливаемого hook'а. Может принимать одно из ниже перечисленных значений:

wh_callwndproc - Следит за сообщениями до отправки в оконную функцию и
вызывается, когда процедуре окна посылается сообщение.

Ловушка срабатывает при каждом вызове функции sendmessage.

wh_callwndprocret - Контролирует сообщения после их отправки в оконную функцию.

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

wh_debug - Вызывается перед любой другой ловушкой. Полезно для отладки hook'ов.

wh_getmessage - Вызывается, когда из очереди приложения считывается сообщение.

wh_hardware - Вызывается, когда из очереди приложения считывается сообщение установленного на компьютере оборудования.

wh_journalplayback - Вызывается, когда из очереди системы считывается сообщение. Применяется для добавления в очередь системных событий.

wh_journalrecord - Вызывается, когда из очереди системы запрашивается какое-нибудь событие. Применяется для регистрации системных событий.

wh_keyboard - Вызывается, когда из очереди приложения считывается сообщения wm_keydown или wm_keyup. Одна из самых распространенных ловушек -).

wh_mouse - Вызывается, когда из очереди приложения считывается сообщение мыши.

wh_msgfilter - Вызывается, когда сообщение должно быть обработано диалоговым окном приложения, меню или окном приложения.

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

2. lpfn - указатель на саму hook функцию. Ее заголовок:

function hookfunction(code: integer; wparam: wparam;
lparam: lparam): lresult stdcall;


Значения входящих параметров зависят от типа hook'a.

Если ставится глобальный hook, эта функция должна обязательно находиться в dll.

3. hmod - принимает значение hinstance или дескриптор dll (в глобальных ловушках).
4. dwthreadid - идентифицирует поток, в который вставляется ловушка.

В глобальных hook'ах этот параметр должен быть равен 0.

Для удаления установленной ловушки существует функция unhookwindowshookex().
В качестве параметра нужно использовать указатель (дескриптор) на hook функцию (значение, которое возвращает функция setwindowshookex()).
Ну вот и все, с основами мы ознакомлены. Теперь напишем маленькую шуточную программу, ставящую hook на считывания сообщений мыши (wh_mouse).
Сделаем так, чтобы при нажатии на правую кнопку мыши скрывалась кнопка "Пуск", при нажатии на левую - появлялась, среднею - изменялся заголовок активного окна.
Сама hook функция будет находиться в dll. Кроме того, в dll будут находиться две процедуры - sethook() и removehook(), соответственно устанавливающие и удаляющие ловушку.
Привожу код dll библиотеки:

library lib;
uses
windows,messages;
var
h : thandle;
{hook-функция}
function hook(c0de, wparam, lparam : integer): lresult; stdcall;
{Объявления переменных}
var
w : thandle;
hw : hwnd;
begin
{Если c0de не меньше 0, все в порядке, продолжаем}
if c0de >= 0 then
begin
{ Если wparam = wm_rbuttonup, т.е. нажата правая кнопка мыши, получаем
хендл (handle) кнопки "Пуск" и скрываем ее }
case wparam of
wm_rbuttonup :
begin
w:= findwindow('shell_traywnd', nil);
w:= findwindowex(w, hwnd(0),'button', nil);
showwindow(w, sw_hide);
end;
{ Если wparam = wm_lbuttonup, т.е. нажата левая кнопка мыши, получаем
хендл кнопки пуск и показываем ее }
wm_lbuttonup:
begin
w:= findwindow('shell_traywnd', nil);
w:= findwindowex(w, hwnd(0),'button', nil);
showwindow(w, sw_show);
end;
{ Если wparam = wm_mbuttonup, т.е. нажата средняя кнопка мыши, получаем
указатель на заголовок активного окна и изменяем его }
wm_mbuttonup:
begin
hw:=getforegroundwindow;
setwindowtext(hw,'example of windows hook (wh_mouse) - by dark lord
');
end;
end;
end else
{Если c0de меньше 0}
begin
{Вызываем следующую ловушку в цепочке ловушек windows и выходим из процедуры}
result := callnexthookex(h, c0de, wparam, lparam);
exit;
end;
{Вызываем следующую ловушку в цепочке ловушек windows}
result := callnexthookex(h, c0de, wparam, lparam);
end;

{ Процедура установки ловушки, если не удалось
установить - выводим сообщение об ошибке }
procedure sethook;
begin
h:= setwindowshookex(wh_mouse, @hook, hinstance, 0);
if h = 0 then
messagebox(0,'hmmm..','error',mb_iconhand);
end;
{ Процедура удаления ловушки }
procedure removehook;
begin
unhookwindowshookex(h);
end;
{ Экспорт процедур установки и удаления hook'a }
exports
sethook index 1 name 'sethook',
removehook index 2 name 'removehook';
end.


В самой программе ловушка будет устанавливаться вызовом из dll процедуры sethook, удаляться - вызовом процедуры removehook.
В данной статье были рассмотрены только основы установки ловушек.
Есть немалое количество нюансов и возникающих проблем при установке нескольких
hook'ов, установки hook'ов в разных ОС (особенно это касается глобальных ловушек). Для получения подробностей по этим вопросам рекомендую использовать win32 api reference или msdn (если нет диска с msdn - прогуляйтесь на msdn.microsoft.com, здесь правда не вся информация, но большая ее часть).
  << Вернуться к Содержанию