2012-02-11 130 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

你的示例代碼顯示你正在創建一個全局鉤子,全局鉤子很貴,所以如果你想註冊多個回調函數,你應該抽象這個,以便你的應用程序只設置一個鉤子和你在那裏註冊的回調函數調用你的真實功能(在鏈接列表等)。