如何从SetWindowsHookEx回调中调用功能指针

时间:2019-06-25 13:57:50

标签: c++ winapi function-pointers setwindowshookex

我试图从DLL中调用一个函数指针,该DLL钩住了屏幕上显示的所有窗口上的WM_LBUTONDOWN或WM_TOUCH消息。

我有以下dll源代码:

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;
}

我的监听器源代码如下:

    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);

我自己的显示“ Hello click”的回调就是这个:

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

我知道我的钩子正在工作,因为我可以通过使用消息框而不是pf(nCode, wParam, lParam)来显示单击消息,但是当我使用此功能指针时,不会触发MyCallback。 我检查了我的函数是否对pf函数指针有很好的影响,并且一切似乎都还可以。

您知道为什么pf(nCode, wParam, lParam)的调用不会触发侦听器的MyCallback函数吗?

2 个答案:

答案 0 :(得分:0)

这种方法行不通。

消息钩子在每个被钩住的线程的上下文中运行。每个挂钩的进程都将获得自己的DLL副本,并将其注入其中。这样,只有最初安装该挂钩的副本才具有有效的函数指针集。此外,您还是无法跨进程边界调用回调函数。

您需要使用其他IPC机制,以使注入的钩子与您的主应用程序进程通信。

例如,您可以创建一个隐藏的HWND并将其存储在全局共享内存的块中,然后每个注入的挂钩都可以向其发送窗口消息,例如WM_COPYDATA。或者,您的主应用程序可以打开一个命名管道,每个注入的钩子可以随后连接到该管道并向其发送数据。

答案 1 :(得分:0)

您仅针对进程中加载​​的dll调用setCallbackSetWindowsHookEx将在所有其他进程中注入的dll将没有设置回调。最重要的是,MyCallback仅在您自己的过程中定义;在其他进程中注入的Dll没有访问它的简单方法。

由于您不知道Windows为您注入了哪些进程,因此您将需要Dll通过进程间通信向您广播其“位置”。命名管道。获得注入的每个DLL的进程ID后,就可以使用CreateRemoteThread来调用Dll中的一个函数,例如setCallback ..还有一些工作要做,以便Dll可以直接调用您的回调:您将需要为Dll提供回调与模块基数的确切偏移量,然后Dll将需要使用CreateRemoteThread本身来发出调用。 这一切很快就会变得很乏味,因此明智的做法是只使用命名管道通信而不是直接发出函数调用。

提示:从其他进程记录事件的一种简便方法是使用OutputDebugString。或者,写入文件。