Understanding the low-level mouse and keyboard hook (win32) - c++

I'm trying to capture global mouse and keyboard input.
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_RBUTTONDOWN) printf("right mouse down\n");
if (wParam == WM_RBUTTONUP) printf("right mouse up\n");
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
while(true) {
MSG msg;
if (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
printf("msg recvd\n");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#ifdef TEST
Sleep(50);
#endif
}
So everything works here, except if I #define TEST to put in the Sleep, the mouse becomes incredibly sluggish, as might be expected if I suddenly only allow the mouse to update 20 times a second. And without the sleep, I am pegging the CPU at 100%. But that's okay for now (that goes away if I use GetMessage).
Now as I understand it, the low-level hooks work by context-switching to the process which installed it, and then sending the process some kind of message to let it execute the hook callback. What confuses me a little, though, is why my program will never print "msg recvd", but it prints "right mouse down/up" whenever i click the right mouse button. This leads me to conclude that my MouseHookProc is being invoked during the PeekMessage call. It just happens to be some kind of special message and PeekMessage returns 0. But I still need to call PeekMessage or some equivalent.
Since my program needs to do a bunch of things, I clearly can't weigh down my message pumping loop (the one that calls PeekMessage) by calling another function that takes, say 50ms to return. How might I multithread my program to maintain mouse responsiveness while simultaneously doing a little heavy lifting? In a multithreaded win32 program, there is still just one message queue, right?
Update: After reading up on MS's documentation I think I know what the right thing for me to do is. I should just spawn a thread in my application which calls SetWindowsHookEx to register the mouse hook, and then sit around in its own message loop, and the system will take care of sending the mouse updates to this thread. It will be free to do whatever it wants within the MouseHookProc, and the rest of my application will run independently.

The problem is your message loop, it burns 100% CPU cycles because you use PeekMessage(). Windows knows how to keep the hook alive even if you don't poll for messages, use GetMessage() to solve your problem. Using Sleep(1) will solve your problem too but is not necessary here.
Why must SetWindowsHookEx be used with a windows message queue

I aksed you whether you place the place MouseHookProc in DLL, because attempts to place it inside an EXE it is a typical error. I made it also many years ago.
First of all, how you can read in http://msdn.microsoft.com/en-us/library/ms644990.aspx:
SetWindowsHookEx can be used to inject
a DLL into another process. A 32-bit
DLL cannot be injected into a 64-bit
process, and a 64-bit DLL cannot be
injected into a 32-bit process. If an
application requires the use of hooks
in other processes, it is required
that a 32-bit application call
SetWindowsHookEx to inject a 32-bit
DLL into 32-bit processes, and a
64-bit application call
SetWindowsHookEx to inject a 64-bit
DLL into 64-bit processes. The 32-bit
and 64-bit DLLs must have different
names.
So you must place in a DLL. To be exactly if you want support both 32-bit and 64-bit platforms you have to implement two dlls: one 32-bit and 64-bit DLL. But why? And how SetWindowsHookEx works?
If you execute in an EXE the code like following
HINSTANCE hinstDLL = LoadLibrary(TEXT("c:\\myapp\\syshook.dll"));
HOOKPROC hkprcMouse = (HOOKPROC)GetProcAddress(hinstDLL, "MouseHookProc");
HHOOK hhookMouse = SetWindowsHookEx(
WH_MOUSE_LL,
hkprcMouse,
hinstDLL,
0);
you give user32.dll request to inject your syshook.dll in all other processes on the same windows station (dll will not be injected to services and processes of other users logged through fast user switching). Then user32.dll call LoadLibrary to the syshook.dll in different processes. Then if the function MouseHookProc will be called, in will be called in the context of the process which proccess the mouse message. If the process is not a console application the code like
printf("right mouse down\n");
can not work.
So I hope now you will undestend why you must place MouseHookProc in a DLL.

Instead of doing:
if (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
printf("msg recvd\n");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(50);
Switch this to:
while (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
// Add this potentially...
if (msg.message == WM_QUIT)
break;
printf("msg recvd\n");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
This will allow your app to continue to process all messages in the queue until it's empty (like having no sleep), then give up some CPU time when the app is "idle".

MouseHookProc should reside in dll, otherwise you can not capture "global" input ( http://msdn.microsoft.com/en-us/library/ms997537.aspx )
About the loop - you can modify it like this:
while(true) {
MSG msg;
while (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
printf("msg recvd\n");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#ifdef TEST
DoStuff();
Sleep(50);
#endif
}

Related

Process my WindowsHook before others

I have searched around on Google and the Microsoft hook documentation and I find plenty of how to make a hook, but I already know how to do that. How do I make my hook (keyboard hook in this case) be first in the queue to receive a message? I am trying to get my hook as close as hardware input as possible to prevent another keyhook from changing input.
I.E: App1 runs a key hook to spoof the flags of KBDLLHOOK to not be injected. How do I get to that message before they can change flags from LLKHF_INJECTED?
TL;DR How would my hook get the message before another to prevent key injection?
Simple code I am using to test
LRESULT CALLBACK keybdProc(int n, WPARAM w, LPARAM l)
{
KBDLLHOOKSTRUCT *kbdll = (KBDLLHOOKSTRUCT*)l;
if (w == WM_KEYDOWN)
{
switch (kbdll->flags)
{
case LLKHF_INJECTED:
printf("%d/%c is an Injected Key Press (Reject)\n", kbdll->vkCode, char(kbdll->vkCode));
break;
default:
printf("%d/%c Not injected (Continue)\n", kbdll->vkCode, char(kbdll->vkCode));
break;
}
}
return 0; //CallNextHookEx(NULL, n, w, l);
}
int main()
{
HHOOK keybdHk = SetWindowsHookEx(WH_KEYBOARD_LL, keybdProc, GetModuleHandle(NULL), 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(keybdHk);
return 0;
}
edit: I am aware the message queue goes in last-first order, but somehow no matter if I start my program before or after App1 it still gets the input before my Keyhook and then doesn't call NextHook (So my hook never gets it) or it spoofs it.
Hooks are managed in hook chains, where hook procedures are executed in order, from front to back. As documented:
The SetWindowsHookEx function always installs a hook procedure at the beginning of a hook chain. When an event occurs that is monitored by a particular type of hook, the system calls the procedure at the beginning of the hook chain associated with the hook. Each hook procedure in the chain determines whether to pass the event to the next procedure.
To have your hook called first, it needs to be installed last. While this is easy to establish, maintaining that position in the hook chain is impossible to do.
Two things.
First:
As of Windows 10, the struct KBDLLHOOKSTRUCT that you receive in the lParam argument can no longer be modified. The changes you make to it are not passed to the next hook procedures, even if you call CallNextHookEx(NULL, code, wParam, lParam).
You could even pass a completely different lParam pointer to CallNextHookEx and yet the subsequent hooks will still receive the original, unmodified structure.
The ability to modify KBDLLHOOKSTRUCT has never been documented, but was indeed possible on previous versions of window. However, not any more.
However, you can still prevent other hook procedures from receiving the input message by simply not calling CallNextHookEx.
Second:
The appropriate way to avoid other processes from interfering with the input you see, is by using the Raw Input API.
You use the function RegisterRawInputDevices so that your process receives the input directly from the device. Other processes cannot block, tamper or alter in anyway what you get from this API.
With Raw Input you can even detect which specific keyboard sent a given keystroke (in case there's more than one keyboard plugged in), which is not possible using a keyboard hook.
This is how games detect their input, so that users can't inject fake keystrokes into the game using the SendInput function.

How to ignore a mouse click in Windows? (C++)

I am trying to make a program that sits in the background that can ignore mouse clicks - outside of the program.
How do I tell Windows this through c++?
I already made the program recognize the mouse click. Just not how to ignore it.
The reason I need to do this is because my mouse has a flaw where it accidentally double-clicks (or more) when I only click one time.
So basically, when the program register that I click with the mouse, it will let the first click through, but then disable that button (ignoring every following clicks) for ~200 milliseconds.
If possible, I would like to avoid using any external libraries. Only the standard ones that comes with Visual Studio.
Thank you very much for reading!
You can use a low-level mouse hook:
// Variable to store the hook handle
HHOOK miHook;
// This is the hook procedure
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if(nCode == HC_ACTION) {
MSLLHOOKSTRUCT &msll = *(reinterpret_cast<MSLLHOOKSTRUCT*>(lParam)); // In there is more context if you need it
if(wParam == WM_LBUTTONDOWN) {
// Do your logic here
if(letsIgnoreThisClick) {
return -1; // This will make the click be ignored
}
}
}
return CallNextHookEx(miHook, nCode, wParam, lParam); // Important! Otherwise other mouse hooks may misbehave
}
// This is how you install the hook
miHook = SetWindowsHookEx(WH_MOUSE_LL, reinterpret_cast<HOOKPROC>(&LowLevelMouseProc), hInstance, 0);
// And this is how you would remove the hook again
UnhookWindowsHookEx(miHook);
This code example can't be used as-is of course, but has to be adjusted to your needs and the individual parts have to be put in the right locations in your code.
Please also read the remarks section for SetWindowsHookEx. You are probably going to need to create a DLL where your function is located (you can load it from your main code). The hInstance in my example has to be the instance handle of the module which contains the hook procedure. Also you need to pump messages in order for your hook to work correctly!

SetWindowsHookEx WH_MOUSE_LL Hook only takes 1 mouse movement

I am setting a global hook with the following code:
SetWindowsHookEx(WH_MOUSE_LL, MouseProc, NULL, 0)
I have a breakpoint set so that when I first run the application I can see that the MouseProc method is called. This works but after the first time it is no longer called. Is the Hook automatically removed, how do I get this so that the hook automatically persists? I am writing this application for windows and this is a C++ win32 project.
I have a breakpoint set
That's enough to explain the problem. The debugger will break of course. Which prevents further mouse messages from being delivered to the window with the focus. Windows puts up with that for 5 seconds, then unceremoniously disables your hook because it thinks your code is broken.
The timeout is configurable, you can use Regedit.exe to set the HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout value. Not present by default, add the DWORD value first. The unit is milliseconds.
First you need to do:
return CallNextHookEx(_hook, nCode, wParam, lParam);
in your MouseProc, so it should return.
Second, it's not possible to debug most of codes which does have hook, your app will crash, because windows expecting your MouseProc function to return as soon as possible with return.
Also your code should have Message handling code, like GetMessage, TranslateMessage and DispatchMessage.
Example code: SetWindowsHookEx for WH_MOUSE

Keyboard hooking alt-tab causing strange behavior?

I want to disallow the user of my application from using alt-tab. I'm trying to solve this by using a low level keyboard hook.
Setting it up works perfectly, the callback procedure is triggered when I press the key combination etc. The weird thing that happens is that I can alt-tab out of the application but then alt-tabbing is disabled, completely. I switch applications with the mouse and try alt-tabbing but nothing happens. I switch back to my application and alt-tab again and it switches the application, but only one step. When out of my application the alt-tab isn't working anymore.
I've tried different scenarios, first I thought it had something to do with the debugger in VS2010 but no, running it with out the debugger gives the same results.
Have I completely misunderstood this hook procedure, is it meant to only catch stuff happening when the application isn't in focus?
osman.hpp :
static HHOOK m_hhook;
static LRESULT CALLBACK lowLevelKeyboardProc( int key, WPARAM wParam, LPARAM lParam );
osman.cpp :
HHOOK OSMan::m_hhook;
/*
* pseudo init code
*/
void OSMan::init()
{
m_hHook = SetWindowsHookEx( WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc, 0, 0 );
}
LRESULT CALLBACK OSMan::lowLevelKeyboardProc( int key, WPARAM wParam, LPARAM lParam )
{
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
switch (key)
{
case HC_ACTION:
{
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
}
default:
break;
}
return CallNextHookEx( m_hHook, key, wParam, lParam);
}
edit:
added code.
If you want to disable alt+tab correctly, you should just register the hotkey via RegisterHotKey(0,0,MOD_ALT,VK_TAB); and then handle (well, more ignore) the message that this generates, this allows you to make it application local, not worry about Windows hook chains and allows you to easily enable or disable it on the fly.
Although for a game, the idTech 4 input handling code has a vast array of the input gems.
You are installing a System Wide hook, that is why you have disabled the use of Alt-TAB on the whole system.
You can't use a WH_KEYBOARD_LL you must use a WH_KEYBOARD hook, and make it process specific.
The params of the SetWindowsHookEx will change if you make your hook process specific.
Here is an overview of the params :
dwThreadId [in]
Type: DWORD
The identifier of the thread with which the hook procedure is to be associated.
If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.
PS : in reply to comment :
The hook only is installed after the process got one appropriate event. While hooking onto keyboard messages, you will have to send at least one keyboard message before the hook is installed.
Work Around
Maybe you want to work around this issue by using the ShowWindow function ?
Here is the doc : http://www.pinvoke.net/default.aspx/user32.showwindow
cf : http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces
cf http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
and
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644959(v=vs.85).aspx#wh_keyboardhook

If MessageBox()/related are synchronous, why doesn't my message loop freeze?

Why is it that if I call a seemingly synchronous Windows function like MessageBox() inside of my message loop, the loop itself doesn't freeze as if I called Sleep() (or a similar function) instead? To illustrate my point, take the following skeletal WndProc:
int counter = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1000, NULL); //start a 1 second timer
break;
case WM_PAINT:
// paint/display counter variable onto window
break;
case WM_TIMER: //occurs every second
counter++;
InvalidateRect(hwnd, NULL, TRUE); //force window to repaint itself
break;
case WM_LBUTTONDOWN: //someone clicks the window
MessageBox(hwnd, "", "", 0);
MessageBeep(MB_OK); //play a sound after MessageBox returns
break;
//default ....
}
return 0;
}
In the above example, the program's main function is to run a timer and display the counter's value every second. However, if the user clicks on our window, the program displays a message box and then beeps after the box is closed.
Here's where it gets interesting: we can tell MessageBox() is a synchronous function because MessageBeep() doesn't execute until the message box is closed. However, the timer keeps running, and the window is repainted every second even while the message box is displayed. So while MessageBox() is apparently a blocking function call, other messages (WM_TIMER/WM_PAINT) can still be processed. That's fine, except if I substitute MessageBox for another blocking call like Sleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
This blocks my application entirely, and no message processing occurs for the 10 seconds (WM_TIMER/WM_PAINT aren't processed, the counter doesn't update, program 'freezes', etc). So why is it that MessageBox() allows message processing to continue while Sleep() doesn't? Given that my application is single-threaded, what is it that MessageBox() does to allow this functionality? Does the system 'replicate' my application thread, so that way it can finish the WM_LBUTTONDOWN code once MessageBox() is done, while still allowing the original thread to process other messages in the interim? (that was my uneducated guess)
Thanks in advance
The MessageBox() and similar Windows API functions are not blocking the execution, like an IO operation or mutexing would do. The MessageBox() function creates a dialog box usually with an OK button - so you'd expect automatic handling of the window messages related to the message box. This is implemented with its own message loop: no new thread is created, but your application remains responsive, because selected messages (like for painting) are handled calling recursively your WndProc() function, while other messages are not transmitted, because of the modal type of the created window.
Sleep() and other functions (when called directly from your WndProc() handling a window message) would actually block the execution of your single threaded message loop - no other message would be processed.
MessageBox runs its own Win32 message loop (so as not to freeze calling app).
Beware of using it in non reentrant functions...
EDIT: to elaborate:
Message loop on windows is something like that (stolen from msdn):
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DispatchMessage will call whatever window procedure it needs to. That window proc can start its own loop (on the same thread), and it will call DispatchMessage itself, which will call whatever message handlers.
If you want to see it, launch your app in debugger, pop up message box and break. You will be dropped somewhere within its loop. Look at the callstack and see if you can find parent loop.