gpt4 book ai didi

c++ - 永远不会调用全局 CBT Hook

转载 作者:行者123 更新时间:2023-11-30 01:16:25 25 4
gpt4 key购买 nike

我正在尝试制作一个应用程序,以获取有关系统范围内顶级窗口的创建和销毁的信息。我编写了一个代码来利用 CBT Hook 。该解决方案包含两个项目,DLL 和 EXE。 EXE 项目引用了 DLL 项目。 Hook 是从 DLL 设置的。 EXE 项目中有一个消息循环。问题是 CBT Hook 不起作用。在 VS 调试器的帮助下,我发现 hook callback 从未被调用,而 SetWindowsHookEx 的返回代码是非零的,这意味着 hook 已设置。怎么了?我该如何解决?

这是一个最小的例子。 DLL,main.cpp:

#include <windows.h>

typedef void(*DECODERPROC)(int code, WPARAM wParam, LPARAM lParam);

HINSTANCE hInst = nullptr;
HHOOK hHook = nullptr;
DECODERPROC fpDecoder = nullptr;

LRESULT CALLBACK cbtProc(int code, WPARAM wParam, LPARAM lParam) {
// FIXME: never called
if (code > 0 && fpDecoder) {
fpDecoder(code, wParam, lParam);
}
return CallNextHookEx(hHook, code, wParam, lParam);
}

__declspec(dllexport) bool InstallHook(DECODERPROC decoder) {
if (hHook) return false;
fpDecoder = decoder;
return (hHook = SetWindowsHookEx(WH_CBT, cbtProc, hInst, 0)) != NULL;
}

__declspec(dllexport) bool UninstallHook() {
if (!hHook) return false;
bool res = UnhookWindowsHookEx(hHook) != NULL;
if (res) hHook = NULL;
return res;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
hInst = reinterpret_cast<HINSTANCE>(hModule);
return TRUE;
}

EXE, main.cpp

#include <iostream>
#include <locale>

#include <windows.h>
#include <fcntl.h>
#include <io.h>
using namespace std;

typedef void(*DECODERPROC)(int code, WPARAM wParam, LPARAM lParam);
__declspec(dllimport) bool InstallHook(DECODERPROC);
__declspec(dllimport) bool UninstallHook();

int main() {
_setmode(_fileno(stdout), _O_U8TEXT);
WNDCLASS windowClass = {};
windowClass.lpfnWndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT {
if (message == WM_DESTROY)
UninstallHook();
return DefWindowProc(hWnd, message, wParam, lParam);
};
LPCWSTR windowClassName = L"Foobar";
windowClass.lpszClassName = windowClassName;
if (!RegisterClass(&windowClass)) {
wcerr << L"Failed to register window class" << endl;
return 1;
}
HWND messageWindow = CreateWindow(windowClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
if (!messageWindow) {
wcerr << L"Failed to create message-only window" << endl;
return 1;
}

InstallHook([](int code, WPARAM wParam, LPARAM lParam) {
wcout << L"Never called" << endl;
});

MSG msg;
while (GetMessage(&msg, 0, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

最佳答案

如果您在 64 位 Windows 上运行,则需要 32 位和 64 位版本的 DLL 才能 Hook 每个正在运行的进程。 32 位 DLL 无法 Hook 64 位进程,反之亦然。因此,您需要从 32 位进程调用 SetWindowsHookEx() 以挂接 32 位进程,并从 64 位进程调用以挂接 64 位进程。

比这更重要的是,你的 DLL 的一个单独实例被注入(inject)到每个正在运行的进程中,所以你的 fpDecoder 回调指针在每个 DLL 实例中都是 NULL,除了你的 EXE 正在调用的那个InstallHook() 打开。所以你需要重新设计你的钩子(Hook)来使用进程间通信(窗口消息、命名管道、邮槽、套接字等)来与你的主 EXE 通信,你不能使用函数指针。

根据您实际调试的进程,您可能看不到 cbtProc() 被调用。如果您正在调试您的主 EXE 进程,一旦安装了 Hook ,您的代码就不会在您的 EXE 进程中触发任何 CBT 事件,并且调试器不会向您显示在它未调试的其他进程中发生的任何 CBT 事件.

根据您在 Hook 中实际寻找的内容,您可能会考虑使用 SetWinEventHook(),因为它可以与 DLL 一起使用,也可以不与 DLL 一起使用,并且它具有比SetWindowsHookEx()

关于c++ - 永远不会调用全局 CBT Hook ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26611982/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com