delphi에서 64비트 갈고리 구현 지원

델파이에서.about.com에서 갈고리의 실현 코드를 찾았는데 잘 썼어요. 아쉽게도 64자리를 지원하지 않았어요. 나중에 한 게시물에서classes 단원을 참고하여 고쳤다고 해서 직접 고쳤어요. 지금 여러분께 공유할게요.
수정 부분은 다음과 같다.
4
const
{$IF Defined(CPUX86)}
  CodeBytes = 2;
{$ELSEIF Defined(CPUX64)}
  CodeBytes = 8;
{$IFEND}


type
  pObjectInstance = ^TObjectInstance;
  TObjectInstance = packed record
    Code: Byte;
    Offset: Integer;
    case Integer of
      0: (Next: pObjectInstance);
      1: (Method: THookMethod);
  end;
const
//  InstanceCount = 313; // set so that sizeof (TInstanceBlock) < PageSize
  InstanceCount = (4096 - SizeOf(Pointer) * 2 - CodeBytes) div SizeOf(TObjectInstance) - 1;
type
  pInstanceBlock = ^TInstanceBlock;
  TInstanceBlock = packed record
    Next: pInstanceBlock;
    Code: array[1..CodeBytes] of Byte;
    WndProcPtr: Pointer;
    Instances: array[0..InstanceCount] of TObjectInstance;
  end;

var
  InstBlockList: pInstanceBlock = nil;
  InstFreeList: pObjectInstance = nil;


function StdHookProc(Code: UINT; WParam: WPARAM; LParam: WPARAM): LResult; stdcall;
{$IF Defined(CPUX86)}
{ In    ECX = Address of method pointer }
{ Out   EAX = Result }
asm
        XOR     EAX,EAX
        PUSH    EAX
        PUSH    LParam
        PUSH    WParam
        PUSH    Code
        MOV     EDX,ESP
        MOV     EAX,[ECX].Longint[4]
        CALL    [ECX].Pointer
        ADD     ESP,12
        POP     EAX
end;
{$ELSEIF Defined(CPUX64)}
{ In    R11 = Address of method pointer }
{ Out   RAX = Result }
var
  HookMsg: THookMsg;
asm
        .PARAMS 2
        MOV     HookMsg.Code,Code
        MOV     HookMsg.WParam,WParam
        MOV     HookMsg.LParam,LParam
        MOV     HookMsg.Result,0
        LEA     RDX,HookMsg
        MOV     RCX,[R11].TMethod.Data
        CALL    [R11].TMethod.Code
        MOV     RAX,HookMsg.Result
end;
{$IFEND}

{ Allocate a hook method instance }

function CalcJmpOffset(Src, Dest: Pointer): Longint;
begin
  Result := IntPtr(Dest) - (IntPtr(Src) + 5);
end;

function MakeHookInstance(Method: THookMethod): Pointer;
const
  BlockCode: array[1..CodeBytes] of Byte = (
{$IF Defined(CPUX86)}
    $59,                       { POP ECX }
    $E9);                      { JMP StdWndProc }
{$ELSEIF Defined(CPUX64)}
    $41,$5b,                   { POP R11 }
    $FF,$25,$00,$00,$00,$00);  { JMP [RIP+0] }
{$IFEND}
  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));
{$IF Defined(CPUX86)}
    Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdHookProc));
{$ELSEIF Defined(CPUX64)}
    Block^.WndProcPtr := @StdHookProc;
{$IFEND}
    Instance := @Block^.Instances;
    repeat
      Instance^.Code := $E8;  { CALL NEAR PTR Offset }
      Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
      Instance^.Next := InstFreeList;
      InstFreeList := Instance;
      Inc(PByte(Instance), SizeOf(TObjectInstance));
    until IntPtr(Instance) - IntPtr(Block) >= SizeOf(TInstanceBlock);
    InstBlockList := Block;
  end;
  Result := InstFreeList;
  Instance := InstFreeList;
  InstFreeList := Instance^.Next;
  Instance^.Method := Method;
end;

{ Free a hook method instance }

procedure FreeHookInstance(ObjectInstance: Pointer);
begin
  if ObjectInstance = nil then
    Exit;

  pObjectInstance(ObjectInstance)^.Next := InstFreeList;
  InstFreeList := ObjectInstance
end;
코드 예시를 사용합니다. 이 도구는 여러 가지 갈고리를 지원합니다. 저는 키보드 갈고리를 사용합니다.
procedure THookManager.CreateHook(hookMethod: THookNotify);
begin
  KeyboardHook := TKeyboardHook.Create;
  KeyboardHook.OnPreExecute := KeyboardHookPreEx;
  KeyboardHook.Active := True;
end;

procedure THookManager.KeyboardHookPreExecute(Hook: THook; var Hookmsg: THookMsg);
var
  Key: Word;
  Handled: Boolean;
begin
  Handled := false;
  Key := Hookmsg.WPARAM;
  if Hookmsg.Code = HC_ACTION then
  begin
    if (key=ord('1')) and InHotKeyState then
    begin
      // KeyDown     ,   keyup   alt        
      if KeyboardHook.KeyState = ksKeyDown then
      begin
        handled := HandleNumberKey(key);
        if not handled then
          HandleKey(key); //       
      end;
      //Keyup、KeyDown         ,                 
      Handled := True;
    end;
  end;
  Hookmsg.Result := IfThen(Handled, 1, 0); //math  
end;

function IsKeyPress( KeyState: TKeyBoardState; key: Byte ): Boolean;
begin
  Result := KeyState[key] shr 7 = 1;
end;

function THookManager.InHotKeyState(): Boolean;
var
  KeyState: TKeyBoardState;
  bAlt, bShift, bCtrl: Boolean;
begin
  GetKeyboardState(KeyState);
  bAlt := IsKeyPress(KeyState, VK_MENU);
  bCtrl := IsKeyPress(KeyState, VK_Control);
  bShift := IsKeyPress(KeyState, VK_Shift);
  Result := bAlt and not bCtrl and not bShift;
end;


전체 코드는 내 자원에서 다운로드해라. 나는 델피 XE2를 사용한다. (첫 번째 64비트 버전 지원)
http://download.csdn.net/detail/youthon/8442961

좋은 웹페이지 즐겨찾기