SetWindowsHookEx WH_MOUSE_LL Hook only takes 1 mouse movement - c++

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

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.

When to call PostQuitMessage

Like many applications, mine creates multiple windows. I do not know and cannot keep track of how many windows have been created, so I don't know when there are none.
My problem is that when all the windows are closed, unless I call PostQuitMessage somehow, the application keeps running with no windows open (obviously). I can't call PostQuitMessage in the message handler in response to the WM_DESTROY message because that will close all the windows when the first one is closed, even if there are twenty others still open.
My question is how do I know when to call PostQuitMessage(0) to actually terminate the application?
If, for some reason, you really can't count how many windows the application opens, you can still use EnumThreadWindows() and when there are no more windows, you PostQuitMessage(). If you have several threads, make sure you enumerate through those too.
From MSDN
BOOL WINAPI EnumThreadWindows(
__in DWORD dwThreadId,
__in WNDENUMPROC lpfn,
__in LPARAM lParam
);
Just keep a static variable with a count of the number of open windows. When a windows opens have it increment the counter; in the WM_DESTROY handler decrement it. When the count goes to zero, call PostQuitMessage.
Of course, the only clean way is keeping track of your windows and post the quitmessage if none is left.
A possible workaround would be using one of the window enumerating functions. You can count your windows using EnumWindows() which calls a callback where you can count all toplevel windows. If it reaches zero, call PostQuitMessage().
A static variable for the number of the windows?
I have never seen such a Program.
One the one hand child windows can open and close during the lifetime of the
application.
One the other hand the main window procedure has to close the application,
if the user closes the main window.
For to do this, we have to add PostQuitMessage(0) in the WM_DESTROY branch
of the main window procedure. After this message, GetMessage() returns 0 and
the message loop ends because of this (and the application ends too)

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

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
}

How to set global hook for WH_CALLWNDPROCRET?

I want to set global hook that tracks which application is active.
In my main program I am doing the foloowing :
HMODULE mod=::GetModuleHandle(L"HookProcDll");
HHOOK rslt=(WH_CALLWNDPROCRET,MyCallWndRetProc,mod,0);
The hook procedure which is called MyCallWndRetProc exists in separate dll called HookProcDll.dll. The hook procedure is watching for WM_ACTIVATE message.
The thing is that the code stucks in the line where I am setting the hook, i.e in the line where I am calling ::SetWindowsHookEx. And then Windows gets unresponsive, my task bar disappears and I am left with empty desktop. Then I must reset the computer.
What am doing wrong, why Windows get unresponsive ? and
Do I need to inject HookProcDll.dll in every process in order to set the global hook, and how can I do that ?
This almost definitely sounds like a crashing bug in MyCallWndRetProc. You specify your hook DLL to get loaded in every process with a window and it crashes when MyCallWndRetProc gets called after a window message. Since it gets called after every window message in every process, it'll eventually take down every process displaying UI in the user session. You can't even launch new apps since your hook proc will be immediately loaded into them.
Including the code to MyCallWndRetProc, and perhaps your DllMain as well, should give us some insight into what is happening.
This is the code for my hook procedure, and it is stored in HookProcDll.dll :
#include "HookProcDll.h"
LRESULT CALLBACK MyCallWndRetProc(
__in int nCode,
__in WPARAM wParam, /* whether the msg is sent by the current process */
__in LPARAM lParam /* pointer to CWPRETSTRUCT , which specifies details about the message */
)
{
if(nCode >=0)
{
CWPRETSTRUCT* retStruct=(CWPRETSTRUCT*)lParam;
if(retStruct->message == WM_ACTIVATE)
{
}
}
return ::CallNextHookEx(0,nCode,wParam,lParam);
}
My HookProcDll.dll has no explicit DllMain function .The HookProcDll.dll is made with visual studio dll project so I guess it includes standrad implementation for DllMain.

Windows/C++: detect when focus has changed between windows (globally)

I'm trying to find a way to detect when focus is changed to another window (without having to poll every X ms).
I've already figured out a way to detect when focus is switched between applications using WH_SHELL and HSHELL_ACTIVATESHELLWINDOW.
The problem is I want to detect when focus is switched between dialog/windows within the same app.
ie. In Notepad, I can determine when the app switches to Notepad, but I cannot detect when the "Open" or "Save" dialogs appear because the focus is still within the same application.
You can use SetWindowsHookEx with a WH_CBT hook type. If you just want to detect focus changes within an application, pass GetCurrentThreadId() as the last parameter, otherwise the hook will be for all threads on the current desktop.
Note that using windows hooks can have an adverse effect on system performance, so the hook should only be installed when necessary and you should do a minimum amount of work in the hook procedure.
Sorry for the delay, I don't have VS installed on this computer so it's a bit hard to find the code.
Use this to hook your code into the system.
HHOOK oldShellHook = SetWindowsHookEx(WH_SHELL, BCK_WndShellProc, hDll, NULL);
if (!info->oldShellHook) {
MessageBox(m_hwnd, L"Failed to load global hook.", strTitle, MB_OK | MB_ICONERROR);
return;
}
And this your hook. Depending on what you're doing, use nMsg to figure out when you want to apply your custom logic.
LRESULT CALLBACK BCK_WndShellProc(int nMsg, WPARAM wParam, LPARAM lParam) {
...
}
Read the MSDN docs for SetWindowsHookEx() to make sure you return the expected values, otherwise you can lock up the whole system.
I use code similar to this on my Breadcrumb Killer and Spasm (Show all programs on Start menu) programs and it seems to work fine.
How about the "Computer Based Training API"; SetWindowsHookEx with WH_CBT which will enable you to receive HCBT_SETFOCUS (among others)