I currently have some trouble to get a global keyhook working on a Windows 7 64-Bit O/S. Now I know that there are a lot of threads on this topic already here on Stackoverflow, but none of them quite give me an answer that I can work with or I don't quite understand how the issue is solved in these threads.
So I will try to explain what I am struggling with and hope that anyone can help me out or point me into the right direction.
Basically my goal is to intercept the CTRL+C and CTRL+V keyboard inputs for a sort of clipboard manager. For this reason my current attempt is to register a syste-wide WH_KEYBOARD
hook which deals with the intercepted keystrokes to my needs.
I am running the hook on a 64-Bit Windows 7 O/S, and that is where the problems start. It is obvious to me that a 32-Bit Hook DLL causes problems for 64-Bit processes, vice versa. For this reason I have generated a x86 and x64 version of my library containing the hook, as well as for the invoker of the hook (the one who calls SetWindowsHookEx()
), both with different filenames as the documentation suggests.
But what now? If I set a my 64-Bit DLL as a system-wide hook, all the 32-Bit applications start hanging as soon as I press a key when they are focused. Same thing when I apply the 32-Bit hook, my Windows is practically unusable because the explorer.exe
is 64-Bit. If I set both hooks, my system is effectivley at a standstill, having a global "bitness" fight in place.
Now I assume that the issue arises from e.g. the 64-Bit hooking DLL trying to be injected into a 32-Bit process and so forth, which is of course nonesense. But for this case the documentation of SetWindowsHookEx()
says the following:
Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes.
I don't fully understand the bold part of the text, but I interpret it as in that if the "bitness" of a hooking target differs from the one of the hook, it is executed on the thread that has actually set the hook so it can be executed at all. Furthermore, this means that this thread must still be active and probably running a sort of message loop. Is this correct? Or am I totally off on this one? The documentation also seems to give exact instructions on what to do for my scenario:
To hook all applications on the desktop of a 64-bit Windows installation, install a 32-bit global hook and a 64-bit global hook, each from appropriate processes, and be sure to keep pumping messages in the hooking application to avoid blocking normal functioning.
But yet I fail to grasp what has to be done in my implementation. To finally show some code, let's take this basic example of trying to set a system-wide keyhook. I guess the creating code for the thread should be irrelevant:
volatile static bool runThread = false;
DWORD WINAPI threadStart(LPVOID lpThreadParameter) {
HMODULE hMod = LoadLibraryA(is64Bit() ? "keyhook.x64.dll" : "keyhook.x86.dll");
HHOOK hHook = SetWindowsHookExA(WH_KEYBOARD, (HOOKPROC)GetProcAddress(hMod, "hookProc"), hMod, 0)));
runThread = true;
while(runThread) {
// Message pump? Yes? No? How?
Sleep(10);
}
UnhookWindowsHookEx(hHook);
FreeLibrary(hMod);
return 0;
}
The hook itself is kept quite trivial - it is enough to cause the hangup issues when crossing the bitness:
extern "C" LRESULT hookProc(int code, WPARAM wParam, LPARAM lParam) {
if(code == HC_ACTION) {
}
return CallNextHookEx(nullptr, code, wParam, lParam);
}
I assume that some people might throw there hands over their heads right now, and that you can tell that I seldom have worked with hooks ;)
But that's exactly why I am asking :)
To keep things short: I would be grateful if someone could tell me how to change the above example to get a system-wide keyhook working on 64-Bit Windows. My problem is that certain applications with other "bitness" than the hook start hanging and I don't know how to solve the issue.
Any help is very much appreciated!
Thanks and regards
PuerNoctis