Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.08.2012, 13:50   #1
praeeo
 
Регистрация: 30.03.2010
Сообщений: 9
По умолчанию Проблема с хуком на оконную процедуру

Приветствую!
Изучаю способы перехвата и отмены сообщений для чужого окна (например, WM_CANCELMODE). Для этого ставлю хук WH_CBT (просто чтобы из его процедуры поменять адрес оконной процедуры, например при активации окна - см. код). Устанавливаю вызовом LoadLibrary ----> SetHook из своего приложения. Всё устанавливается, но загвоздка в том, что при попытке прочитать значения lParam, преобразовав его предварительно в PCWPSTRUCT, вылетает ошибка о том, что "Память не может быть быть read". В чем может быть дело? Перепробовал копирование значения lParam через GetMem, VirtualAlloc - всё равно не работает. Грешил на DEP - тоже не оно.

Код:
library HookLib;

uses
  ShareMem,
  Windows,
  Messages,
  Dialogs,
  SysUtils;

var
  Hook: HHook;
  sdl_handle: HWND;
  app_handle: HWND;
  buffer: array [0 .. 49] of Char;

  map_handle: HWND;
  ptr: PChar;
  PrevWndProc: Pointer = nil;
  buf: array [0 .. MAX_PATH] of Char;

  cds: COPYDATASTRUCT;
  cds_buffer: array [0 .. 99] of Char;

procedure ShowLastErrorMsg;
begin
  MessageBox(0, PWideChar(SysErrorMessage(GetLastError)), 'Error', MB_OK or MB_ICONERROR);
end;

function SetData(data: String): COPYDATASTRUCT;
begin
  cds.dwData := 0;
  cds.cbData := SizeOf(cds_buffer);
  StrPCopy(cds_buffer, data);
  cds.lpData := @cds_buffer;
  Result := cds;
end;

function NewWndProc(Handle: THandle; Msg, wParam, lParam: LongInt): LongInt; stdcall;
var
  str: PCWPSTRUCT;
  str1: PCWPSTRUCT;
  p: Pointer;
  data: COPYDATASTRUCT;
begin
  str := PCWPSTRUCT(lParam);
  p := VirtualAlloc(nil, SizeOf(str), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if p = nil then
    MessageBox(0, 'p = nil', '', MB_OK);
  try
    Move(str, p, SizeOf(str));
    if PCWPSTRUCT(p).message <> 0 then //Вот здесь вылетает даже просто при попытке обращения. 
    begin 
    end;
  finally
    VirtualFree(p, SizeOf(str), MEM_RELEASE);
  end;

  data := SetData('NewWndProc');
  SendMessage(app_handle, WM_COPYDATA, 0, LongInt(@data));

//Закомментированные вызовы ведут к той же ошибке. 
  // str := PCWPSTRUCT(lParam);
  // MessageBox(0, 'SC_MINIMIZE', '', MB_OK);
  // Move(Pointer(lParam)^, str, SizeOf(str));
  // MessageBox(0, PWideChar(IntToStr(CWPSTRUCT(Pointer(lParam)^).message)), '', MB_OK);
  // if (CWPSTRUCT(Pointer(lParam)^).wParam = WM_CANCELMODE) then
  // begin
  // end;
  Result := CallWindowProc(PrevWndProc, Handle, Msg, wParam, lParam);
end;

procedure SetNewWndProc;
begin
  sdl_handle := FindWindow(nil, 'Form1');
  PrevWndProc := Pointer(SetWindowLong(sdl_handle, GWL_WNDPROC, LongInt(@NewWndProc)));
  if PrevWndProc = nil then
    ShowLastErrorMsg;
end;

function ReadMap(name: PChar): Variant;
var
  map_handle: HWND;
begin
.......
end;

function WndProc(code: Integer; wParam: wParam; lParam: lParam): LResult; stdcall;
var
  data: COPYDATASTRUCT;
begin
  data := SetData('WndProc');
  SendMessage(app_handle, WM_COPYDATA, 0, LongInt(@data));
  if code = HCBT_ACTIVATE then
  begin
    if PrevWndProc = nil then
      SetNewWndProc;
  end;
  if Hook = 0 then
  begin
    Hook := HHook(ReadMap('HookHandle'));
    MessageBox(0, PWideChar(IntToStr(Hook)), '', MB_OK);
  end;
  Result := CallNextHookEx(Hook, code, wParam, lParam);
end;

procedure MapHookHandle(Hook: HHook);
var
  map_handle: HWND;
  ptr: PChar;
begin
..........
end;

procedure SetHook;
var
  pid: DWORD;
  tid: Cardinal;
begin
  tid := GetWindowThreadProcessId(sdl_handle, @pid);
  MessageBox(0, 'SetHook', '', MB_OK);
  if tid <> 0 then
  begin
    Hook := SetWindowsHookEx(WH_CBT, @WndProc, HInstance, tid);
    if Hook = 0 then
    begin
      MessageBox(0, 'Could not set Hook', 'HookLib', MB_OK or MB_ICONERROR);
      Halt;
    end
    else
      MapHookHandle(Hook);
  end
  else
  begin
    MessageBox(0, 'GetWindowThreadProcessId failed', 'HookLib', MB_OK or MB_ICONERROR);
    Halt;
  end;
end;

procedure RemoveHook;
begin
  SetWindowLong(sdl_handle, GWL_WNDPROC, LongInt(@PrevWndProc));
  UnhookWindowsHookEx(Hook);
end;

exports
  SetHook index 1 name 'SetHook',
  RemoveHook index 2 name 'RemoveHook';

begin
  sdl_handle := FindWindow(nil, 'Form1');
  GetModuleFileName(0, buf, SizeOf(buf));
  if LowerCase(ExtractFileName(StrPas(buf))) = 'test.exe' then
  begin
    MessageBox(0, 'start', '', MB_OK);
    app_handle := HWND(ReadMap('AppHandle'));
    if app_handle = 0 then
    begin
      MessageBox(0, 'Unable to get AppHandle', 'Error', MB_OK);
      Halt;
    end;
  end;

end.
praeeo вне форума Ответить с цитированием
Старый 01.08.2012, 14:31   #2
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Ты серьёзно полагаешь, что в оконную процедуру передаётся одно-единственное сообщение? :-D
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 01.08.2012, 14:47   #3
praeeo
 
Регистрация: 30.03.2010
Сообщений: 9
По умолчанию

Я полагаю, что они передаются по очереди, а ты?
praeeo вне форума Ответить с цитированием
Старый 01.08.2012, 15:54   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вам говорят про то, что не каждое сообщение это нужное вам.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 01.08.2012, 15:56   #5
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Я полагаю, что они передаются по очереди, а ты?
Заметно, как ты "полагаешь":

Код:
function NewWndProc(Handle: THandle; Msg, wParam, lParam: LongInt): LongInt; stdcall;
var
  str: PCWPSTRUCT;
begin
  str := PCWPSTRUCT(lParam); // у любого сообщения? серьёзно?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с хуком WH_MOUSE sav0k Win Api 4 12.04.2012 08:51
Траблы с хуком qazwar Visual C++ 0 09.02.2012 11:14
проблема с хуком (не пишет русский) KWN, lnc Win Api 7 22.09.2011 11:54
Отладка dll с хуком или Мистика на марше Tihon Win Api 8 02.01.2009 13:55
Проблема с хуком, Делаю подмену клавиш мыши zhefran Win Api 12 17.04.2008 18:03