2012-02-11 297 views
3

如何从他的程序中访问挂钩的手柄?在挂钩程序中访问挂钩

例子:

HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)hookProc, GetModuleHandle(NULL), 0); 

LRESULT CALLBACK hookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    //I want my HHOOK here :O 
} 
+0

看看这里:http://stackoverflow.com/questions/214022/how-to-correctly-use-setwindowshookex-callnexthookex – Asaf 2012-02-11 23:21:18

回答

3

您需要存储在全局内存HHOOK变量。不要将它声明为任何函数调用的局部变量SetWindowsHookEx()

编辑:这里是32位的CPU的基于类的示例:

class THookKeyboardLL 
{ 
private: 
    HHOOK hHook; 

    void *pProxy; 
    static LRESULT CALLBACK ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam); 

    LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam); 

public: 
    THookKeyboardLL(); 
    ~THookKeyboardLL(); 
}; 

#include <pshpack1.h> 
struct sProxy 
{ 
    unsigned char PopEax; 
    unsigned char Push; 
    void *ThisPtr; 
    unsigned char PushEax; 
    unsigned char Jmp; 
    int JmpOffset; 
}; 
#include <poppack.h> 

long CalcJmpOffset(void *Src, void *Dest) 
{ 
    return reinterpret_cast<long>(Dest) - (reinterpret_cast<long>(Src) + 5); 
} 

LRESULT CALLBACK THookKeyboardLL::ProxyStub(THookKeyboardLL *This, int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    return This->HookProc(nCode, wParam, lParam); 
} 

THookKeyboardLL::THookKeyboardLL() 
    : hHook(NULL), pProxy(NULL) 
{ 
    sProxy *Proxy = (sProxy*) VirtualAlloc(NULL, sizeof(sProxy), MEM_COMMIT, PAGE_READWRITE); 

    Proxy->PopEax = 0x58; 
    Proxy->Push = 0x68; 
    Proxy->ThisPtr = this; 
    Proxy->PushEax = 0x50; 
    Proxy->Jmp = 0xE9; 
    Proxy->JmpOffset = CalcJmpOffset(&(Proxy->Jmp), &ProxyStub); 

    // Note: it is possible, but not in a portable manner, to 
    // get the memory address of THookKeyboardLL::HookProc() 
    // directly in some compilers. If you can get that address, 
    // then you can pass it to CalcJmpOffset() above and eliminate 
    // THookKeyboardLL::ProxyStub() completely. The important 
    // piece is that the Proxy code above injects this class 
    // instance's "this" pointer into the call stack before 
    // calling THookKeyboardLL::HookProc()... 

    DWORD dwOldProtect; 
    VirtualProtect(Proxy, sizeof(sProxy), PAGE_EXECUTE, &dwOldProtect); 
    FlushInstructionCache(GetCurrentProcess(), Proxy, sizeof(sProxy)); 

    pProxy = Proxy; 
    hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)pProxy, GetModuleHandle(NULL), 0); 
} 

THookKeyboardLL::~THookKeyboardLL() 
{ 
    if (hHook != NULL) 
     UnhookWindowsHookEx(hHook); 

    if (pProxy) 
     VirtualFree(pProxy, 0, MEM_RELEASE); 
} 

LRESULT CALLBACK THookKeyboardLL::HookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    // ... 

    return CallNextHookEx(hHook, nCode, wParam, lParam); 
    // when this method exits, it will automatically jump 
    // back to the code that originally called the Proxy. 
    // The Proxy massaged the call stack to ensure that... 
} 
+0

但我想创建一个类,创建一个钩子,所以我不能使用全局变量,因为我必须能够创建几个对象。 – Triton 2012-02-11 23:14:48

+1

'SetWindowsHookEx()'不支持类的使用。如果你想使用一个类方法作为钩子程序,并使用多个类实例来设置多个钩子,那么你必须为每个类实例创建一个单独的代理thunk,将代理传递给'SetWindowsHookEx()',并且代理根据需要调用其关联的类实例。你不能直接在C/C++中完成这个工作,你必须在汇编中编写代理(至少是SetWindowsHookEx()调用的部分)。 – 2012-02-11 23:30:45

+0

这不是太困难(至少在32位,我不知道大约64位),我会稍后用一个例子更新我的答案。 – 2012-02-11 23:31:08

1

如果你看一下你CallNextHookEx看到,HHOOK参数是可选的Windows NT上,如果你需要支持Windows 9x中,那么你需要的HHOOK存储在一个全局变量的documentation

你的示例代码显示你正在创建一个全局钩子,全局钩子很贵,所以如果你想注册多个回调函数,你应该抽象这个,以便你的应用程序只设置一个钩子和你在那里注册的回调函数调用你的真实功能(在链接列表等)。