Subversion Repositories userdetect2

Compare Revisions

Regard whitespace Rev 71 → Rev 72

/trunk/vcl/PatchU.pas
0,0 → 1,70
unit PatchU;
 
interface
 
type
pPatchEvent = ^TPatchEvent;
 
// "Asm" opcode hack to patch an existing routine
TPatchEvent = packed record
Jump: Byte;
Offset: Integer;
end;
 
TPatchMethod = class
private
PatchedMethod, OriginalMethod: TPatchEvent;
PatchPositionMethod: pPatchEvent;
FIsPatched: boolean;
public
property IsPatched: boolean read FIsPatched;
constructor Create(const aSource, aDestination: Pointer);
destructor Destroy; override;
procedure Restore;
procedure Hook;
end;
 
implementation
 
uses
Windows, Sysutils;
 
{ TPatchMethod }
 
constructor TPatchMethod.Create(const aSource, aDestination: Pointer);
var
OldProtect: Cardinal;
begin
PatchPositionMethod := pPatchEvent(aSource);
OriginalMethod := PatchPositionMethod^;
PatchedMethod.Jump := $E9;
PatchedMethod.Offset := Integer(PByte(aDestination)) - Integer(PByte(PatchPositionMethod)) - SizeOf(TPatchEvent);
 
if not VirtualProtect(PatchPositionMethod, SizeOf(TPatchEvent), PAGE_EXECUTE_READWRITE, OldProtect) then
RaiseLastOSError;
 
Hook;
end;
 
destructor TPatchMethod.Destroy;
begin
Restore;
inherited;
end;
 
procedure TPatchMethod.Hook;
begin
if FIsPatched then Exit;
FIsPatched := true;
PatchPositionMethod^ := PatchedMethod;
end;
 
procedure TPatchMethod.Restore;
begin
if not FIsPatched then Exit;
FIsPatched := false;
PatchPositionMethod^ := OriginalMethod;
end;
 
end.