Вам необходимо сохранить переменную HHOOK
в глобальной памяти. Не объявляйте его как локальную переменную любой функции, вызывающей SetWindowsHookEx()
.
Редактировать : Вот пример класса для 32-битных процессоров:
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...
}