This is my C++ code:
#include <iostream>
#include <windows.h>
HHOOK hook;
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
std::cout << "Hook callback" << std::endl;
return CallNextHookEx(hook, nCode, wParam, lParam);
}
int main(int argc, char **argv)
{
hook = SetWindowsHookEx(WH_KEYBOARD, keyboardHook, NULL, NULL);
if (hook == NULL) {
std::cout << "Error " << GetLastError() << std::endl;
return 1;
}
std::cout << "Hook set" << std::endl;
}
I compile it using Visual Studio like this:
cl /D_WIN32_WINNT=0x0401 foo.cc /link user32.lib
When I run it, I get error 1428.
C:\>foo.exe
Error 1428
This is the meaning of error 1428.
C:\nocaps>net helpmsg 1428
Cannot set nonlocal hook without a module handle.
Could you please help me to understand this error and get this code working? It would be great if you could provide me a working code that works and invokes the callback?
I see that if I use WH_KEYBOARD_LL hook instead, it works fine. But I need to understand how WH_KEYBOARD hook can be made to work.
WH_KEYBOARD_LL
hooks are always run in the context of the thread that installed the hook. The hook function doesn't need to be in a DLL, and the hook may catch events from applications, irrespective of their bitness. The trick is: the OS does some sort of special "SendMessage" to your thread message queue. That is why you'll have to install an active message loop in your hooking thread.WH_KEYBOARD
hooks may be run in the context of the thread that installed the hook. That means that they also may be run in the context of the hooked threads. That imposes a hook function located in a DLL. I believe (but not sure about that) that the hook function will be executed "in place" (in the context of the hooked threads) if the bitness is the same, and that the fallback for a bitness mismatch relies on the same technique used for WH_KEYBOARD_LL. That means you also have to install an active message loop in your hooking thread (and if you don't, you'll miss all the events from applications with another bitness)Note: a hook function being excecuted in the context of the hooked threads renders all
cout << "Hello\n"
useless. You'll have to use file(s) (or IPC).