
library hook;
uses
  Windows,
  HookData;

//****************************************************
//Экспортируемые функции
function InstallHook(wnd: HWND; spy: HWND): Boolean stdcall; forward;
function RemoveHook(): Boolean stdcall; forward;
exports
  InstallHook,
  RemoveHook;
//****************************************************

//Функция проверяет, функция связывает указатель hook_info с проекцией файла
//в память
function GetFileMapping(): Boolean;
begin
  //Пытаемся открыть проекцию файла
  hFile := OpenFileMapping(FILE_MAP_WRITE, FALSE, PAnsiChar(strFileMapName));
  //Получаем адрес разделяемой памяти
  hook_info := MapViewOfFile(hFile, FILE_MAP_WRITE, 0, 0, SizeOf(THookInfo));
  GetFileMapping := hook_info <> nil;
end;

//Процедура отменяет проецирование файла в память
procedure ReleaseFileMapping();
begin
  UnmapViewOfFile(hook_info);
  hook_info := nil;
  CloseHandle(hFile);
  hFile := 0;
end;

//////////////////////////////////////////////////////////////////
//Функция ловушки
function WndProcHook(code: Integer; wparam: WPARAM; lparam: LPARAM)
                     : LRESULT stdcall;
var
  hook_data: ^TCWPStruct;
begin
  //Получим доступ к проекции файла
  if not GetFileMapping() then
  begin
    //Не удалось получить доступ к проекции файла. Ценой потери
    //сообщений не дадим возникнуть ошибок доступа к памяти
    WndProcHook := 0;
    Exit;
  end;

  if code < 0 then
  begin
    WndProcHook := CallNextHookEx(hook_info^.hook_handle, code, wParam, lParam);
    //Освободим проекцию файла
    ReleaseFileMapping();
    Exit;
  end;

  //Можно обрабатывать сообщение
  hook_data := Pointer(lParam);
  //Обрабатываем только сообщения нужного окна
  if hook_data^.hwnd = hook_info^.wnd then
  begin
    //Заполняем поля структуры о общей области памяти и посылаем
    //сообщение окну-шпиону
    hook_info^.mess := hook_data^.message;
    hook_info^.wParam := hook_data^.wParam;
    hook_info^.lParam := hook_data^.lParam;
    PostMessage(hook_info^.spy_wnd, WM_SPY_NOTIFY, 0, 0);
  end;

  //Передаем сообщение для дальнейшей обработки
  WndProcHook := CallNextHookEx(hook_info^.hook_handle, code, wParam, lParam);

  //Освободим проекцию файла
  ReleaseFileMapping();
end;
/////////////////////////////////////////////////////////////////////////

//Функция установки ловушки
//Параметры:
//  wnd: дескриптор окна, сообения которого перехватывать
//  spy: этому окну перепосылаются сообщения WM_SPY_NOTIFY при перехвате
//сообщений
function InstallHook(wnd: HWND; spy: HWND): Boolean stdcall;
begin
  //Открываем проекцию файла (области файла подкачки)
  if not GetFileMapping() then
  begin
    //Не удалось спроецировать файл в память
    InstallHook := False;
    Exit;
  end;

  //Сохраняем данные, необходимые для работы ловушки
  hook_info^.wnd := wnd;
  hook_info^.spy_wnd := spy;

  //Создаем ловушку
  if (GetWindowThreadProcessId(wnd) <> 0) and
     (GetWindowThreadProcessId(wnd) <> GetWindowThreadProcessId(spy))
  then
    hook_info^.hook_handle := SetWindowsHookEx(WH_CALLWNDPROC, WndProcHook,
                                               hInstance,
                                               GetWindowThreadProcessId(wnd))
  else
    //Создание ловушки для потокой нашего приложения было бы фатальным
    hook_info^.hook_handle := 0;

  InstallHook := hook_info^.hook_handle <> 0;
  //Освободим проекцию файла
  ReleaseFileMapping();
end;

//Функция удаления ловушки
function RemoveHook(): Boolean stdcall;
begin
  if GetFileMapping() then
  begin
    if hook_info^.hook_handle <> 0 then
      //Удаляем ловушку
      UnhookWindowsHookEx(hook_info^.hook_handle);
    //Закрываем проекцию файла
    ReleaseFileMapping();
    RemoveHook := True;
  end
  else
    RemoveHook := False;
end;

begin
  hook_info := nil;
  hFile := 0;
end.
