In case this of use to anyone:
Quite often you find a bug in Delphi RTL and you come up with a fix. Patching involves replacing the RTL procedure with a new patched one. To do that you can use your favorite patching routine or library (I use Detours), but you need the address of the original function/method.
a) Patching a non-virtual public method
This is quite straight-forward:
type
TMethodType = procedure ... of object
function GetAddress: Pointer;
var
MethodPtr : TMethodType;
begin
MethodPtr := TRTLClass(nil).PublicMethod;
Result := TMethod(MethodPtr).Code;
end;
Note the type cast TRTLClass(nil).
b) Patching a virtual public method
If for example PublicMethod is virtual the above type cast TRTLClass(nil) with result in access violation, since to resolve the virtual method you need to access Self which is nil. You could create a class instance and use that instead of TRTLClass(nil), but apart from not being elegant, in some cases this has side-effects (for example it may require a valid windows handle). The trick is described in this Stackoverflow question.
function GetAddress: Pointer;
var
VMT : NativeInt;
MethodPtr: TMethodType;
begin
VMT := NativeInt(TRTLClass);
MethodPtr := TRTLClass(@VMT).PublicMethod;
Result := TMethod(MethodPtr).Code;
end;
This is based on two facts. A class is a pointer to the Virtual Method table (VMT) and an Object structure has as the first field a pointer to the VMT of its class.
c) Patching a private virtual method
The trick this time involves using a class helper to access the private method of the TRTLClass
type
TPrivateMethodType = procedure ... of object;
TRTLClassHookFix = class helper for TRTLCLass
function GetPriveMethodAddr: Pointer;
end;
function TRTLClassHookFix.GetPriveMethodAddr: Pointer;
var
VMT : NativeInt;
MethodPtr: TPrivateMethodType;
begin
// Adjust Self to point to the VMT
VMT := NativeInt(TRTLCLass);
Self := TRTLCLass(@VMT);
with Self do MethodPtr := PrivateMethod;
Result := TMethod(MethodPtr).Code;
end;
That's it.