Перехват WH_GETMESSAGE и WM_CHAR

 
0
 
Delphi, Kylix & Pascal
ava
TechnoMag | 21.09.2013, 21:57
Похоже, что функция-фильтр не фиксирует WM_CHAR:


    library CharHook;
     
    uses
      System.SysUtils,
      System.Classes,
      Windows, Messages;
     
    {$R *.res}
     
    const
      MMFName: PChar = 'MMFChar';
     
    type
      PGlobalDLLData = ^TGlobalDLLData;
      TGlobalDLLData=packed record
        SysHook:HWND; //дескриптор установленной ловушки
        MyAppWnd:HWND; //дескриптор нашего приложения
      end;
     
    var
      GlobalData:PGlobalDLLData;
      MMFHandle:THandle;
      WM_MYCHARHOOK:Cardinal;
     
    function GetMsgProc(Code: Integer; wParam: DWORD; lParam: DWORD): Longint; stdcall;
    begin
      if TMsg(Pointer(lParam)^).message=WM_CHAR then
         SendMessage(GlobalData.MyAppWnd, WM_MYCHARHOOK, 0, lParam);
      Result := CallNextHookEx(GlobalData.SysHook, Code, wParam, lParam);
    end;
     
     
    function mcharHook(switch: boolean; hMainProg: HWND): boolean; export; stdcall;
    begin
      if switch = True then
      begin
        GlobalData^.SysHook := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, hInstance, 0);
        GlobalData^.MyAppWnd := hMainProg;
        //if GlobalData^.HookWnd <> 0 then
        //  Result:= True;
      end
      else
      begin
        UnhookWindowsHookEx(GlobalData^.SysHook);
        //Result:= False;
      end;
      Result := true;
    end;
     
    procedure OpenGlobalData();
    begin
      {регестрируем свой тип сообщения в системе}
      WM_MYCHARHOOK := RegisterWindowMessage('WM_MYCHARHOOK');
      MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
      GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
      if GlobalData = nil then
        CloseHandle(MMFHandle);
    end;
     
    procedure CloseGlobalData();
    begin
      UnmapViewOfFile(GlobalData);
      CloseHandle(MMFHandle);
    end;
     
    procedure DLLEntryPoint(dwReason: DWord); stdcall;
    begin
      case dwReason of
        DLL_PROCESS_ATTACH: OpenGlobalData;
        DLL_PROCESS_DETACH: CloseGlobalData;
      end;
    end;
     
    exports mcharHook;
     
    begin
      //DLLProc:= @DLLEntryPoint;
      {вызываем назнаxенную процедуру для отражения факта присоединения данной
     библиотеки к процессу}
      DLLEntryPoint(DLL_PROCESS_ATTACH);
    end.



    WM_MYCHARHOOK: Cardinal;
     
    function mcharHook(switch : Boolean; hMainProg: HWND):boolean; stdcall; external 'CharHook.dll';
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      mcharHook(true, Form1.Handle);
    end;
     
    procedure TForm1.WndProc(var Msg: TMessage);
    begin
     inherited;
    if Msg.Msg = WM_MYCHARHOOK then
     begin
       Memo1.Lines.Add('--------  Нажата клавиша ------------');  // это сообщение не выводится
     end;
    end;
     
    initialization
      WM_MYCHARHOOK := RegisterWindowMessage('WM_MYCHARHOOK');
    end.
Comments (11)
ava
kami | 22.09.2013, 20:54 #
Цитата (TechnoMag @  21.9.2013,  20:57 findReferencedText)
Похоже, что функция-фильтр не фиксирует WM_CHAR:

OpenGlobalData точно отрабатывает нормально?
Приложение, устанавливающее хук случайно запускается не с повышением прав ?
ava
TechnoMag | 23.09.2013, 00:28 #
OpenGlobalData отрабатывает нормально. Запускаю без повышения прав.

Пересобрал c Target Platform - Win64 и с опцией milti-byte character support. WM_CHAR стал отрабатывать, но

   

    procedure TForm1.WndProc(var Msg: TMessage);
    begin
     inherited;
    if Msg.Msg = WM_MYCHARHOOK then
     begin
       Memo1.Lines.Add('--------  Нажата клавиша ------------'  + char(Msg.lParam));  // здесь выводится неправильный символ, или как-будто в другой кодироваке
     end;
    end;



Часто на этой строке приложение выдает AV.
ava
kami | 23.09.2013, 08:08 #
Цитата (TechnoMag @  23.9.2013,  00:28 findReferencedText)
Пересобрал c Target Platform - Win64 и с опцией milti-byte character support, но срабатывает только для 64-разрядных приложений.

ну дык...
Цитата


A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process.


Источник: MSDN

Кстати, размер HWND случайно не отличается на 32 и 64 - платформах? 
ava
TechnoMag | 23.09.2013, 12:22 #
Как же тогда перехватывать нажатия клавиш одновременно в 32-битных и 64-битных приложениях?
ava
kami | 23.09.2013, 19:18 #
Почитал немножко MSDN... пишут, что проблем нет с получением данных 32-битной длл из 64-битных процессов ( Community Additions про SetWindowsHookEx)
Однако, возвращаясь к первому вопросу -
Цитата (kami @  22.9.2013,  20:54 findReferencedText)
OpenGlobalData точно отрабатывает нормально?

Не только при установке, но и в хуке?

Эх, проверить бы... да не на чем...

А вот если явно задействовать SecurityAttributes?
ava
TechnoMag | 23.09.2013, 23:44 #
OpenGlobalData вроде нормально отрабатывает:


procedure OpenGlobalData();
begin
  {регестрируем свой тип сообщения в системе}
  WM_MYCHARHOOK := RegisterWindowMessage('WM_MYCHARHOOK');
  MMFHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
  if MMFHandle=0 then
    MessageBox(0, PWideChar('CharHook.dll'), PWIdeChar(SysErrorMessage(GetLastError)), MB_ICONINFORMATION or MB_OK);
  GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
  if GlobalData = nil then
  begin
    MessageBox(0, PWideChar('CharHook.dll'), PWideChar(SysErrorMessage(GetLastError)), MB_ICONINFORMATION or MB_OK);
    CloseHandle(MMFHandle);
  end;
end;


Ошибок не выдает. Вам исходники дать для проверки?
ava
kami | 24.09.2013, 08:45 #
Цитата (TechnoMag @  23.9.2013,  23:44 findReferencedText)
Вам исходники дать для проверки?

Мне - нет, я ж говорю - проверить не на чем. У меня исключительно 32-битные оси...
Но вот сюда выложить минимально рабочий набор наверное, стоит. Может, кто из Гуру чего подскажет.

Цитата (kami @  23.9.2013,  19:18 findReferencedText)
А вот если явно задействовать SecurityAttributes?

это не пробовали?
ava
TechnoMag | 24.09.2013, 11:03 #
Я не пойму, куда вы рекомендуете это подставить? В процедуре OpenGlobalData нет функции, которая бы принимала параметры связанные с Атрибутами безопасности.


function InitMyDescriptor( SecDescriptor: PSECURITY_DESCRIPTOR): bool;
begin
  Result := False;
  if InitializeSecurityDescriptor(SecDescriptor, SECURITY_DESCRIPTOR_REVISION) then
    if SetSecurityDescriptorDACL(SecDescriptor, True, nil, True) then // устанавливаем полный доступ для всех.
      Result := True;
end;
var
  sa: TSecurityAttributes;
  sd: TSecurityDescriptor;
begin
  if not InitMyDescriptor(@sd) then
    exit;
  sa.lpSecurityDescriptor:[email protected];
  sa.nLength := SizeOf(TSecurityAttributes);
  sa.bInheritHandle := False;
ava
kami | 24.09.2013, 11:27 #
Цитата (TechnoMag @  24.9.2013,  11:03 findReferencedText)
Я не пойму, куда вы рекомендуете это подставить?

Второй параметр CreateFileMapping
ava
TechnoMag | 24.09.2013, 11:56 #
Никакого эффекта.
У меня такая же проблема и по этой теме: Перехват смены активного окна


procedure OpenGlobalData();
var
  sa: TSecurityAttributes;
  sd: TSecurityDescriptor;
begin
   if not InitMyDescriptor(@sd) then
   begin
    MessageBox(0, PWideChar('ShellHook.dll'), PWIdeChar('Не возможно определить атрибуты безопасности'), MB_ICONINFORMATION or MB_OK);
    exit;
   end;
    sa.lpSecurityDescriptor:[email protected];
    sa.nLength := SizeOf(TSecurityAttributes);
    sa.bInheritHandle := False;
  {регестрируем свой тип сообщения в системе}
  WM_MYSHELLHOOK := RegisterWindowMessage('WM_MYSHELLHOOK');
  MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, @sa, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
  if MMFHandle=0 then
    MessageBox(0, PWIdeChar(SysErrorMessage(GetLastError)), PWideChar('ShellHook.dll'), MB_ICONINFORMATION or MB_OK);
  GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
  if GlobalData = nil then
  begin
    MessageBox(0, PWIdeChar(SysErrorMessage(GetLastError)), PWideChar('ShellHook.dll'),MB_ICONINFORMATION or MB_OK);
    CloseHandle(MMFHandle);
  end;
end;
ava
ZaDoXliK | 30.09.2013, 03:45 #
У тебя задача просто отловить нажатые клавиши или ты хочешь замутить всё это что сверху своим кодом???
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit