4 uses KOL
, Windows
, Messages
;
7 TWndMethod
= procedure(var Message: TMessage
) of object;
9 function MakeObjectInstance(Method
: TWndMethod
): Pointer;
10 procedure FreeObjectInstance(ObjectInstance
: Pointer);
11 function AllocateHWnd(Method
: TWndMethod
): HWND
;
12 procedure DeallocateHWnd(Wnd
: HWND
);
17 PObjectInstance
= ^TObjectInstance
;
18 TObjectInstance
= packed record
22 0: (Next
: PObjectInstance
);
23 1: (Method
: TWndMethod
);
27 PInstanceBlock
= ^TInstanceBlock
;
28 TInstanceBlock
= packed record
30 Code
: array[1..2] of Byte;
32 Instances
: array[0..100] of TObjectInstance
;
36 InstBlockList
: PInstanceBlock
;
37 InstFreeList
: PObjectInstance
;
39 { Standard window procedure }
40 { In ECX = Address of method pointer }
43 function StdWndProc(Window
: HWND
; Message, WParam
: Longint;
44 LParam
: Longint): Longint; stdcall; assembler;
52 MOV EAX,[ECX].Longint
[4]
58 { Allocate an object instance }
60 function CalcJmpOffset(Src
, Dest
: Pointer): Longint;
62 Result
:= Longint(Dest
) - (Longint(Src
) + 5);
65 function MakeObjectInstance(Method
: TWndMethod
): Pointer;
67 BlockCode
: array[1..2] of Byte = (
69 $E9); { JMP StdWndProc }
72 Block
: PInstanceBlock
;
73 Instance
: PObjectInstance
;
75 if InstFreeList
= nil then
77 Block
:= VirtualAlloc(nil, PageSize
, MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
78 Block
^.Next
:= InstBlockList
;
79 Move(BlockCode
, Block
^.Code
, SizeOf(BlockCode
));
80 Block
^.WndProcPtr
:= Pointer(CalcJmpOffset(@Block
^.Code
[2], @StdWndProc
));
81 Instance
:= @Block
^.Instances
;
83 Instance
^.Code
:= $E8; { CALL NEAR PTR Offset }
84 Instance
^.Offset
:= CalcJmpOffset(Instance
, @Block
^.Code
);
85 Instance
^.Next
:= InstFreeList
;
86 InstFreeList
:= Instance
;
87 Inc(Longint(Instance
), SizeOf(TObjectInstance
));
88 until Longint(Instance
) - Longint(Block
) >= SizeOf(TInstanceBlock
);
89 InstBlockList
:= Block
;
91 Result
:= InstFreeList
;
92 Instance
:= InstFreeList
;
93 InstFreeList
:= Instance
^.Next
;
94 Instance
^.Method
:= Method
;
97 { Free an object instance }
99 procedure FreeObjectInstance(ObjectInstance
: Pointer);
101 if ObjectInstance
<> nil then
103 PObjectInstance(ObjectInstance
)^.Next
:= InstFreeList
;
104 InstFreeList
:= ObjectInstance
;
109 UtilWindowClass
: TWndClass
= (
111 lpfnWndProc
: @DefWindowProc
;
119 lpszClassName
: 'KOLFakeUtilWindow');
121 function AllocateHWnd(Method
: TWndMethod
): HWND
;
123 TempClass
: TWndClass
;
124 ClassRegistered
: Boolean;
126 UtilWindowClass
.hInstance
:= HInstance
;
127 ClassRegistered
:= GetClassInfo(HInstance
, UtilWindowClass
.lpszClassName
,
129 if not ClassRegistered
or (TempClass
.lpfnWndProc
<> @DefWindowProc
) then
131 if ClassRegistered
then
132 Windows
.UnregisterClass(UtilWindowClass
.lpszClassName
, HInstance
);
133 Windows
.RegisterClass(UtilWindowClass
);
135 Result
:= CreateWindowEx(WS_EX_TOOLWINDOW
, UtilWindowClass
.lpszClassName
,
136 '', WS_POPUP
{!0}, 0, 0, 0, 0, 0, 0, HInstance
, nil);
137 if Assigned(Method
) then
138 SetWindowLong(Result
, GWL_WNDPROC
, Longint(MakeObjectInstance(Method
)));
141 procedure DeallocateHWnd(Wnd
: HWND
);
145 Instance
:= Pointer(GetWindowLong(Wnd
, GWL_WNDPROC
));
147 if Instance
<> @DefWindowProc
then FreeObjectInstance(Instance
);
151 InstBlockList
:= nil;