Доступ к процедуре подключения - PullRequest
3 голосов
/ 12 февраля 2012

Как я могу получить доступ к ручке крючка из его процедуры?

Пример:

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
}

Ответы [ 2 ]

3 голосов
/ 12 февраля 2012

Вам необходимо сохранить переменную 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...
}
1 голос
/ 12 февраля 2012

Если вы посмотрите документацию для CallNextHookEx, то увидите, что параметр HHOOK является необязательным в Windows NT, если вам требуется поддержка Windows 9x, вам нужно сохранить HHOOK в глобальной переменной.

Ваш пример кода показывает, что вы создаете глобальный хук, глобальные хуки стоят дорого, поэтому, если вы хотите зарегистрировать более одной функции обратного вызова, вы должны абстрагировать это так, чтобы ваше приложение установило только один хук, и функция обратного вызова, которую вы зарегистрировали там, вызывает ваши реальные функции (в связанном списке и т. д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...