Apropos Service, hier ist eine Version die mit 'pascal', 'stdcall' und 'safecall' (auch unter WinXP SP2) funktioniert:
(falls es mal jemand brauchen sollte)
Delphi-Quellcode:
////////////////////////////////////////////////////////////////////////////////
//
// MakeStdcallCallback (thunk to use stdcall method as static callback)
// (works too for pascal and safecall, but NOT for cdecl and register!)
function MakeStdcallCallback(
const Method: TMethod): Pointer;
{$IFDEF WIN32}
type
PCallbackCode = ^TCallbackCode;
TCallbackCode =
packed record
Ops1:
array [0..2]
of Longword;
Val1: Pointer;
Ops2:
array [0..1]
of Longword;
Val2: Pointer;
end;
{$ENDIF}
begin
{$IFDEF WIN32}
Result := VirtualAlloc(
nil, $100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if Assigned(Result)
then
try
with PCallbackCode(Result)^
do
begin
// ; do not change registers!
// push eax ; stack space (Self)
// push eax ; backup accumulator
// mov eax, [esp+8] ; get return address
// mov [esp+4], eax ; save at lower addr
// mov eax, [x].TMethod.Data ; get x.Self pointer
// mov [esp+8], eax ; save it into space
// pop eax ; get eax from stack
// nop ; think about it *g*
// jmp dword ptr [x].TMethod.Code ; now jump to method
// ; no need to cleanup stack
Ops1[0] := $448B5050;
Ops1[1] := $44890824;
Ops1[2] := $058B0424;
Val1 := Addr(Method.Data);
Ops2[0] := $08244489;
Ops2[1] := $25FF9058;
Val2 := Addr(Method.Code);
end;
except
VirtualFree(Result, 0, MEM_RELEASE);
Result :=
nil;
end;
{$ELSE}
Result :=
nil;
{$ENDIF}
end;
procedure FreeCallback(Callback: Pointer);
begin
{$IFDEF WIN32}
if Assigned(Callback)
then
VirtualFree(Callback, 0, MEM_RELEASE);
{$ENDIF}
end;
Fehlt nur noch 'register', aber dazu bin ich heute zu faul.