c++winapifunction-pointerssetwindowshookex

How to call fuction-pointer from SetWindowsHookEx callback


I tried to call a function-pointer from a dll that hooks the WM_LBUTONDOWN or WM_TOUCH message on all windows displayed at screen.

I have the following dll source code:

typedef void (*PtrFonct)(int nCode, WPARAM wParam, LPARAM lParam);
PtrFonct pf;
HHOOK global;

extern "C" __declspec(dllexport) LRESULT WINAPI procedure(int nCode, WPARAM wParam,LPARAM lParam)
{
    if (nCode == HC_ACTION){
        MSG* pMSG = (MSG*)lParam;
        if (pMSG->message == WM_LBUTTONDOWN){
            pf(nCode, wParam, lParam);
        }
    }
    return CallNextHookEx(global, nCode, wParam, lParam);
} 

extern "C" __declspec(dllexport) BOOL setCallback(void ((*callbackFunc)(int, WPARAM, LPARAM))){
    pf = callbackFunc;
    if (pf)
        return TRUE;
    return FALSE;
}

and my listener source code is the following one:

    MSG message;
    HMODULE lib = LoadLibrary(L"C:/HookTouch.dll");
    if (lib) {
        HOOKPROC procedure = (HOOKPROC)GetProcAddress(lib, "_procedure@12");
        dllFunct fonctionCallback = (dllFunct)GetProcAddress(lib, "setCallback");
        if (fonctionCallback)
            fonctionCallback(MyCallback);
        if (procedure)
            hook = SetWindowsHookEx(WH_GETMESSAGE, procedure, lib, 0);
    }
    else
        printf("Can't find dll!\n");

    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
    FreeLibrary(lib);
    UnhookWindowsHookEx(hook);

My own callback to display "Hello click" is this one:

void MyCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("Hello Click\n");
}

I know my hook is working because I can display a message on click by using a message box instead of pf(nCode, wParam, lParam) but when I use this function-pointer, MyCallback is not triggered. I checked if my function was well affected to the pf function-pointer and all seems to be ok.

Do you know why the call of pf(nCode, wParam, lParam) don't trigger the MyCallback function of the listener?


Solution

  • You are calling setCallback only for the dll that's loaded in your process. The dll's that will be injected by SetWindowsHookEx in all the other process will not have the callback set. On top of that, MyCallback is only defined in your own process; the Dll's injected in other processes have no trivial way of accessing it.

    Since you cannot know which processes Windows has injected for you, you will need the Dll to broadcast its 'location' to you, via Inter-Process communcation, eg. Named Pipes. Once you have the process ID of each of the DLL's that were injected, you can use CreateRemoteThread to call a function inside the Dll, like setCallback.. there's still some work to be done so that the Dll can directly call you callback: You will need to give the Dll the exact offset of your callback from the module base, and the Dll will then need to use CreateRemoteThread itself to issue the call. This all quickly becomes too tedious, and you would be wise to just use Named Pipe communication instead of issuing direct function calls.

    Tip: An easy way to log things from other processes is using OutputDebugString. Alternatively, write to a file.