|
Delphi. Методы объектов как то по другому хранятся в памяти? | ☑ | ||
---|---|---|---|---|
0
H A D G E H O G s
30.09.11
✎
13:39
|
День добрый.
Собственно ситуация. Есть рабочий код: function MessageHooker1(Code: Integer; WParam: wParam; LParam: LParam): LongInt;stdcall; var HookStructure:PHookStructure; begin HookStructure:=ptr(LParam); if (Code>=HC_ACTION) and (HookStructure<>nil) then begin if HookStructure^.MSG=WM_MOVE then showmessage('URRRRA'); end; Result :=1; //Result := CallNextHookEx(HookHandle, Code, wParam, LParam); end; Procedure Test1();stdcall; var addr:pointer; HookHandle:Cardinal; begin addr:= @MessageHooker1; HookHandle:=SetWindowsHookEx(WH_CALLWNDPROC,addr , 0, GetCurrentThreadId()); End; |
|||
1
Jstunner
30.09.11
✎
13:41
|
глаза режет
|
|||
2
H A D G E H O G s
30.09.11
✎
13:41
|
И есть идентичный нерабочий:
function TMyObject.MessageHooker2(Code: Integer; WParam: wParam; LParam: LParam): LongInt;stdcall; var HookStructure:PHookStructure; begin HookStructure:=ptr(LParam); if (Code>=HC_ACTION) and (HookStructure<>nil) then begin if HookStructure^.MSG=WM_MOVE then showmessage('URRRRA'); end; Result :=1; //Result := CallNextHookEx(HookHandle, Code, wParam, LParam); end; procedure TMyObject.StartHook; var addr:pointer; HookHandle:Cardinal; begin addr:= Self.MethodAddress('MessageHooker2'); HookHandle:=SetWindowsHookEx(WH_CALLWNDPROC,addr , 0, GetCurrentThreadId()); end; Причем в нерабочем коде (через объект) - в callback процедуру управление передается, но вот LParam указывает то на мусор, то вообще на нечитаемую область памяти. ЧЯДНТ? |
|||
3
posq
30.09.11
✎
13:43
|
Ааа... Хуки...
|
|||
4
posq
30.09.11
✎
13:43
|
Как же хорошо что я все это два года назад забыл.
|
|||
5
Ненавижу 1С
гуру
30.09.11
✎
13:49
|
по-другому конечно, он вызываться будет для какого объекта?
короче, оберни в обычную процедуру из которой и вызывай метод СВОЕГО объекта |
|||
6
Serginio1
30.09.11
✎
13:51
|
Адрес адресом, а во Self нужно указать. Для этого существует функция которая создает в памяти запись self в регистр и переход к процедуре. чнго то там Make...
|
|||
7
H A D G E H O G s
30.09.11
✎
13:53
|
(5) Еще раз.
Медленно и по другому. |
|||
8
Serginio1
30.09.11
✎
13:54
|
Посмотри
MakeObjectInstance |
|||
9
Serginio1
30.09.11
✎
13:55
|
Посмотри в Windows. Она там часто используется
|
|||
10
Ненавижу 1С
гуру
30.09.11
✎
13:56
|
function MessageHooker3(Code: Integer; WParam: wParam; LParam: LParam): LongInt;stdcall;
begin Result:=YourObject.MessageHooker1(Code,WParam,LParam); end; addr:= Self.MethodAddress('MessageHooker3'); |
|||
11
Кирпич
30.09.11
✎
14:03
|
Delphi в метод объекта всегда передает первым параметром Self
т.е. написано так function TMyObject.MessageHooker3(Code: Integer; WParam: wParam; LParam: LParam) а на самом деле так function (SELF;Code: Integer; WParam: wParam; LParam: LParam) windows вызовет MessageHooker3 с тремя параметрами, а на самом деле там четыре параметра. можно в реализации метода вставить на асме чо нибудь чтобы стек подправил. или использовать обычную процедуру, куда ссылка на объект не передается. |
|||
12
Serginio1
30.09.11
✎
14:03
|
Для примера http://delphi-faq.zoxt.net/1642.htm
|
|||
13
H A D G E H O G s
30.09.11
✎
14:06
|
(11) Ясно.
Блинн, вчера весь вечер себе сломал из за этого. |
|||
14
H A D G E H O G s
30.09.11
✎
14:12
|
(11) Тоесть, первые 4 байта переданные Windows - мне будут недоступны?
|
|||
15
H A D G E H O G s
30.09.11
✎
14:14
|
(12) Там подмена оконной процедуры своей процедурой с последующим вызовом старой процедуры.
Это как раз то, от чего я сейчас избавляюсь. |
|||
16
Кирпич
30.09.11
✎
14:22
|
(14) Да доступны. Надо там указатель стека сдвинуть что ли, или адрес первого параметра в регистре каком то. Я уж забыл как, но делал когда то. В дебаггере глянь.
|
|||
17
Serginio1
30.09.11
✎
15:13
|
(15) В SetWindowsHookEx тебе нужно передать ссылку на статический метод MakeObjectInstance как раз и создает такой метод но определенной сигнатуры. Еще была аналогичная процедура посмотри
function MethodToProcedure(self: TObject; methodAddr: pointer) : pointer; type TMethodToProc = packed record popEax : byte; // $58 pop EAX pushSelf : record // push self opcode : byte; // $B8 self : pointer; // self end; pushEax : byte; // $50 push EAX jump : record // jmp [target] opcode : byte; // $FF modRm : byte; // $25 pTarget : ^pointer; // @target target : pointer; // @MethodAddr end; end; var mtp : ^TMethodToProc absolute result; begin mtp := VirtualAlloc(nil, sizeOf(mtp^), MEM_COMMIT, PAGE_EXECUTE_READWRITE); with mtp^ do begin popEax := $58; pushSelf.opcode := $68; pushSelf.self := self; pushEax := $50; jump.opcode := $FF; jump.modRm := $25; jump.pTarget := @jump.target; jump.target := methodAddr; end; end; function MethodToProcedure(method: TMethod) : pointer; begin result := MethodToProcedure(TObject(method.data), method.code); end; function ProcedureToMethod(self: TObject; procAddr: pointer) : TMethod; begin result.Data := self; result.Code := procAddr; end; |
|||
18
Serginio1
30.09.11
✎
15:18
|
У меня нт delph под рукой посмотри. По уму там и MakeObjectInstance подойдет,главное присвоить ссылку уже типизированной переменной содержащий нужную сигнатуру метода
|
|||
19
Serginio1
30.09.11
✎
15:27
|
Вот метод
function MakeObjectInstance(Method: TWndMethod): Pointer; const BlockCode: array[1..2] of Byte = ( $59, { POP ECX } $E9); { JMP StdWndProc } PageSize = 4096; var Block: PInstanceBlock; Instance: PObjectInstance; begin if InstFreeList = nil then begin Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Block^.Next := InstBlockList; Move(BlockCode, Block^.Code, SizeOf(BlockCode)); Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdWndProc)); Instance := @Block^.Instances; repeat Instance^.Code := $E8; { CALL NEAR PTR Offset } Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code); Instance^.Next := InstFreeList; InstFreeList := Instance; Inc(Longint(Instance), SizeOf(TObjectInstance)); until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock); InstBlockList := Block; end; Result := InstFreeList; Instance := InstFreeList; InstFreeList := Instance^.Next; Instance^.Method := Method; end; |
|||
20
Serginio1
30.09.11
✎
15:33
|
||||
21
H A D G E H O G s
30.09.11
✎
15:40
|
(20) Посмотрю, спасибо.
|
|||
22
Serginio1
30.09.11
✎
15:50
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |