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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 16.06.2011, 20:07   #1
TwiX
Участник клуба
 
Аватар для TwiX
 
Регистрация: 28.07.2009
Сообщений: 1,510
По умолчанию Подмена WndProc. Слетает прога.

Пытаюсь подменить функцию обработки сообщений... Нахожу окно (wnd), сохраняю адрес текущей функции (pnt), изменяю указатель на свой
Код:
pnt=GetWindowLongPtr(wnd, GWLP_WNDPROC);
      SetWindowLongPtr(wnd, GWLP_WNDPROC, Integer(@CallWindowProc));
//Просто пытаюсь передать управление старой функции, но прога слетает (в которой подменил). В pnt ннужный указатель - проверял.
Код:
function CallWindowProc(PrevWndProc: Pointer; Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint;
begin
  result:=CallWindowProc(Pointer(pnt), Wnd, msg, wParam, lParam);
end;
TwiX вне форума Ответить с цитированием
Старый 16.06.2011, 20:08   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вы подменяете в чужом процессе то?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 16.06.2011, 20:21   #3
TwiX
Участник клуба
 
Аватар для TwiX
 
Регистрация: 28.07.2009
Сообщений: 1,510
По умолчанию

Да. Уже даже на блокноте тестил. Думал защита =)
TwiX вне форума Ответить с цитированием
Старый 16.06.2011, 20:34   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

как вы думаете как код из вашего процесса попадет в чужой?
надо загружать в тот процесс DLL/код и уже на эти адреса переносить.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 16.06.2011, 20:35   #5
TwiX
Участник клуба
 
Аватар для TwiX
 
Регистрация: 28.07.2009
Сообщений: 1,510
По умолчанию

Это отрывок из локального хука. DLL подгружается - всё норм.
TwiX вне форума Ответить с цитированием
Старый 16.06.2011, 20:45   #6
TwiX
Участник клуба
 
Аватар для TwiX
 
Регистрация: 28.07.2009
Сообщений: 1,510
По умолчанию

Вот собственно скрин и файл хука. После того как я переключаюсь на окно блокнота, он зависает.

ХУк:
Код:
uses
  Windows, messages, Classes, SysUtils;

var
  HookHandle: HHOOK = 0;
  List: TStringList;
  procs: array[0..15] of Integer;
  pnt: Integer;


function CallWindowProc(PrevWndProc: Pointer; Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Longint;
begin
  SendMessage(FindWindow(nil, 'Form1'), WM_USER+2, pnt,0);

  result:=CallWindowProc(Pointer(pnt), Wnd, msg, wParam, lParam);
end;

function CBTProc(CODE, WParam, LParam: DWORD): DWORD; stdcall;
var
  wnd: HWND;
  s: string;
begin
  if CODE < 0 then
  begin
    result := CallNextHookEx(HookHandle, CODE, WParam, LParam);
    exit;
  end;


  wnd := WParam;
  if CODE = HCBT_ACTIVATE then
  begin
    if wnd = 0 then
    begin
      result := 0;
      exit;
    end;

    SendMessage(FindWindow(nil, 'Form1'), WM_USER+1, wnd,0);

    s:=IntToStr(wnd);
    if List.IndexOf(s)=-1 then
    begin
      list.Add(s);
      procs[List.IndexOf(s)]:=GetWindowLongPtr(wnd, GWLP_WNDPROC);
      pnt:=procs[List.IndexOf(s)];
      SendMessage(FindWindow(nil, 'Form1'), WM_USER+2, pnt,0);
      SetWindowLongPtr(wnd, GWLP_WNDPROC, Integer(@CallWindowProc));
    end;


    result:=0;
    exit;
  end;

  if CODE = HCBT_DESTROYWND then
  begin
    s:=IntToStr(wnd);
    if List.IndexOf(s)>=0 then
      List.Delete(List.IndexOf(s));
     SendMessage(FindWindow(nil, 'Form1'), WM_USER+2, 2111,0);
  end;

  result := CallNextHookEx(HookHandle, CODE, WParam, LParam);
end;

procedure SetHook(wnd: HWND); stdcall; export;
var
  pid: Cardinal;
begin
  //beep(1500,500);
  pid:=GetWindowThreadProcessId(wnd);
  if HookHandle=0 then
   HookHandle:=SetWindowsHookEx(WH_CBT, @CBTProc, hInstance, pid);
end;

procedure DelHook; stdcall; export;
begin
  //beep(1500,500);
  if HookHandle <> 0 then UnhookWindowsHookEx(HookHandle);
   HookHandle:=0;
end;

function IsActive:boolean; stdcall; export;
begin
  Result:=true;
  if HookHandle=0 then
    Result:=false;
end;


exports
  SetHook, DelHook, IsActive;

begin
  List:=TStringList.Create;
end.
TwiX вне форума Ответить с цитированием
Старый 16.06.2011, 21:02   #7
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

соглашение вызова какое должно быть у оконной процедуры?)

stdcall то забыли
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 16.06.2011, 21:08   #8
TwiX
Участник клуба
 
Аватар для TwiX
 
Регистрация: 28.07.2009
Сообщений: 1,510
По умолчанию

Ещё в начале пробовал... Убрал потому что на msdn (или где-то ещё читал) было написано без stdcall.
С stdcall блокнот не зависает, а вылетает с ошибкой=\

UPD: Брр.. Уже всё перечитал. Нигде подробно не написано, да и примеров не нашёл. Зато гугл уже проиндексировал эту страницу :D

UPD2: Читал, читал. Нашёл слово "глобальный"... Передал для глобального хука. Та же ошибка..

UPD3: Может у кого есть пример? Завтра наверно буду под C++ переписывать =\

Последний раз редактировалось TwiX; 16.06.2011 в 22:39.
TwiX вне форума Ответить с цитированием
Старый 16.06.2011, 23:07   #9
Silver_S
Форумчанин
 
Регистрация: 14.03.2011
Сообщений: 104
По умолчанию

Из за пересечения имен функций, прога уходит в рекурсию. Пишите Windows.CallWindowProc или переименуйте свою процедуру окна.

С++ по умолчанию использует способ передачи параметров STDCALL - через стек. Делфи - свой способ - через регистры. Первую процедуру окна вызывает винда. Поэтому stdcall нужен.

В процедуру окна передается 4 параметра, все целого 4-байтного типа (longint, dword и их производные)

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

Массив procs на 16 элементов, в блокноте может быть намного больше 16 окон.

Последний раз редактировалось Silver_S; 16.06.2011 в 23:12.
Silver_S вне форума Ответить с цитированием
Старый 16.06.2011, 23:11   #10
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
С++ по умолчанию использует способ передачи параметров STDCALL - через стек.
ничего подобного про С++ то не надо говорить.
WinAPI использует это соглашение о вызове, но не С++.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
H2269 Overriding virtual method 'TForm1.WndProc' has lower visibility (private) than base class 'TForm' AlexanderSatorin Общие вопросы Delphi 2 27.06.2010 10:08
Слетает ОС Медсестра Операционные системы общие вопросы 13 16.05.2010 01:51
Слетает верстка... lastalert HTML и CSS 6 02.05.2010 17:14
Смена WndProc в рантайме VVVadim Win Api 1 28.04.2009 18:16