2012-03-22 109 views
2

我试过使用全局钩子,但hookprocedure只接收到我的程序线程的窗口过程消息,并且针对特定应用程序(线程)根本没有消息。挂钩后没有收到Window Procedure消息WH_CALLWNDPROC

我正确地使用DLL中的函数来处理非本地钩子。这是我的应用程序代码。

#include <Windows.h> 
#include <stdio.h> 

HINSTANCE hinst; 
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

int main() { 
    HWND notepad = FindWindow(NULL, L"Untitled - Notepad"); 

    if (!notepad) 
     return 0; 

    hinst = GetModuleHandle(NULL); 

    // create a window class: 
    WNDCLASS wc = {}; 
    wc.lpfnWndProc = WindowProc; 
    wc.hInstance = hinst; 
    wc.lpszClassName = L"hooking"; 

    // register class with operating system: 
    RegisterClass(&wc); 

    // create and show window: 
    HWND hwnd = CreateWindow(L"hooking", L"hooking", WS_OVERLAPPEDWINDOW, 0, 0, 500, 400, NULL, NULL, hinst, NULL); 

    if (hwnd == NULL) { 
     return 0; 
    } 

    ShowWindow(hwnd, SW_SHOW); 

    DWORD threadID = GetWindowThreadProcessId(notepad, NULL); 

    HINSTANCE hinstDLL = LoadLibrary(TEXT("..\\Debug\\ProcHookDLL.dll")); 

    void (*AttachHookProc)(DWORD); 
    AttachHookProc = (void (*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook"); 
    AttachHookProc(threadID); 

    // handle messages: 
    MSG msg = {}; 

    while(GetMessage(&msg, hwnd, 0, 0)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    printf("Done execution... press any key to exit"); 
    char garbage = getchar(); 
    return 0; 
} 


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 
    if (uMsg == WM_DESTROY) { 
     PostQuitMessage(0); 
    } 
    return DefWindowProc(hwnd, uMsg, wParam, lParam); 
} 

这是DLL的代码。我有没有收到任何消息的原因?

#include <Windows.h> 
#include <stdio.h> 

// TODO: create a mutex so this can only be loaded once 
HMODULE thisModule; 
HHOOK hook; 
LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam); 

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
{ 
    thisModule = hModule; 

    // Very restricted set of things that can be done in DllMain, refer to documentation 
    // before adding anything here. 

    switch (ul_reason_for_call) { 
    case DLL_PROCESS_ATTACH: 
    case DLL_THREAD_ATTACH: 
     break; 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 

#ifdef __cplusplus // If used by C++ code, 
extern "C" {   // we need to export the C interface 
#endif 
//window message loop is necessary for hooks to work? (didn't work with console app) 
//provide function pointer to execute when notepad is launched. 
__declspec(dllexport) void AttachHook(DWORD threadID) { 
    hook = SetWindowsHookEx(WH_CALLWNDPROC, LaunchListener, thisModule, threadID); 
} 
#ifdef __cplusplus 
} 
#endif 

LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam) { 
    // process event here 
    if (nCode >= 0) { 
     //wparam specifies if the message was sent by the current thread or not. 
     CWPSTRUCT * cwp = (CWPSTRUCT *)lParam; 
     wchar_t windowName[256]; 
     GetWindowText(cwp->hwnd, windowName, 256); 
     wprintf(L"%#8X: %s\n", cwp->message, windowName); 
     if (cwp->message == WM_CREATE) { 
      __debugbreak(); 
      wchar_t moduleName[256]; 
      //cwp->hwnd 
      //GetModuleFileName(0, moduleName, 256); 
      GetWindowText(cwp->hwnd, moduleName, 256); 
      int x = 0; 
      x++; 
     } 
    } 

    return CallNextHookEx(NULL, nCode, wParam, lParam); 
} 
+0

应该用'NULL'' hModule'调用'SetWindowsHookEx'。也可能需要检查LoadLibrary的返回值。过去我有一些相对路径问题。 – 2012-03-22 23:42:46

+0

@MikeKwan,如果线程'dwThreadId'是由相同的进程创建的'hModule'应该只是null。在这种情况下,它不是。 – 2012-03-23 00:14:47

+0

@NickWhaley:为什么不呢?他使用'LoadLibrary',将DLL加载到同一个进程中。 – 2012-03-23 00:17:12

回答

1

没有问题,挂钩安装正确。但是我不知道钩子过程从窗口过程已经获得消息的过程的上下文中运行。

1

看起来它应该工作。只是检查一些建议。

  • 32位DLL只会挂钩32位进程。而一个64位DLL只会挂钩64位进程。
  • 尝试将dwThreadId设置为0以创建全局钩子,以查看它是否以此方式工作。
  • 确保挂钩DLL可以找到并且可以被目标进程读取。
+0

当我将'dwThreadId'设置为'0'后,它将获取消息发布到我创建的空窗口('hooking'),以及另外两个名为DEFAULT IME的窗口和仅仅使用visual C++,chrome的'MSCTFIME UI' ,记事本也打开。 – cplusplus 2012-03-23 03:11:15

+0

阅读http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_1之后,可能系统范围的钩子已正确安装,但“LaunchListener”在目标进程的上下文中被调用,所以任何'printf'调用都不会输出到我拥有的控制台窗口(需要使用进程间通信)。这个理论只解释了“挂钩”窗口消息。此外,调试器没有附加到目标进程,只是调试与我的窗口相关的线程...所以'__debugbreak()'也不会被触发。 – cplusplus 2012-03-23 03:52:56

+0

但我不确定为什么交换钩子类型为'WH_KEYBOARD'使其工作 – cplusplus 2012-03-23 03:58:42