Process my WindowsHook before others - c++

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.

Related

Blocking Keyboard Play/Pause Button in Win 8

I am writing an application that needs to temporarily disable the Play/Pause button that appears on multimedia keyboards.
Normally, a key can be blocked quite easily by installing a low level keyboard hook (WH_KEYBOARD_LL) where the KeyboardProc intercepts the key (in this case VK_MEDIA_PLAY_PAUSE) and returns 1 instead of calling CallNextHookEx. I have tried this with other keys (including the Windows key VK_LWIN) and this works perfectly. I also have no problems with this method under Windows 7 where all keys, including VK_MEDIA_PLAY_PAUSE get blocked.
Windows 8 is a different story. When my application has input focus, everything works as expected, meaning the VK_MEDIA_PLAY_PAUSE key gets blocked and no other application responds to it. However, when my application loses focus, my hook procedure gets called (this was verified by sending out a OutputDebugString) but other applications respond to key even though I return 1. As soon as my app gets focus again, everything is block as it should.
After some investigation, I found that the multimedia keys not only generate keystrokes but also generate WM_APPCOMMAND messages so I added ShellProc (WH_SHELL) hook with the following hook procedure:
LRESULT __declspec(dllexport)__stdcall CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam)
{
// Do we have to handle this message?
if (nCode == HSHELL_APPCOMMAND)
{
OutputDebugStringX(">>>>> HSHELL_APPCOMMAND");
// Process the hook if the hNotifyWnd window handle is valid
short AppCommand = GET_APPCOMMAND_LPARAM(lParam);
switch (AppCommand)
{
case APPCOMMAND_MEDIA_NEXTTRACK:
case APPCOMMAND_MEDIA_PLAY_PAUSE:
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
case APPCOMMAND_MEDIA_STOP:
OutputDebugString(">>>>>ShellProc got a media command");
return 1;
}
}
// Call the next handler in the chain
return CallNextHookEx (hsh, nCode, wParam, lParam);
}
This procedure is only getting called when my app has input focus. Whenever I have input focus and return 1 the Play/Pause command gets blocked. As soon as I lose focus the procedure does not get called/hooked.
Anyone have any idea as to what is going on? As I have mentioned, the code works for other keys, just not the multimedia keys. Everything works fine in Windows 7.
Alternatively, can anyone suggest another way of blocking the multimedia keyboards Play/Pause button?
From the MSDN documentation for ShellProc:
HSHELL_APPCOMMAND: The user completed an input event (for example, pressed an application command button on the mouse or an application command key on the keyboard), and the application did not handle the WM_APPCOMMAND message generated by that input. [Emphasis added.]
The emphasized portion suggests that your hook callback only gets called after an application ignores the WM_APPCOMMAND. In other words, you're too late.
To catch the message in flight, I think you need a different type of hook. Perhaps WH_GETMESSAGE or WH_CALLWNDPROC.
But why are you trying to prevent the users from interacting with their applications as they choose?

Uninstalling keyboard hook when the user leaves the application

I am trying to detect when a user alt tabs out of my window. I have tried several messages (WM_ACTIVATE, WM_KILLFOCUS, WM_ACTIVATEAPP, WM_NCACTIVATE, WM_CANCELMODE, and WM_SYSCOMMAND checking for SC_MINIMIZE). But the same problem still occurs. The following happens.
My application is in focus, and I hold down alt and press tab.
The next window is brought forth.
I keep holding down alt and then press tab again, but this time, only tab is recognized and so I end up tabbing in the new window rather than alt tabbing again as is the usual behavior.
I am using a low level keyboard hook, and if I uninstall that this alt tabbing behavior described above works perfectly. I basically want to uninstall the keyboard hook as soon as the user leaves my window in this fashion. As soon as I release alt tab while in another window, my window receives several of the messages I look for and the hook is uninstalled. But when you hold the keys in this manner, it does not work as expected while the hook is installed.
why do you need to remove the keyboard hook? The SetWindowsHook is local to your application and not affect the other apps, therefore it already does nothing if your app doesn't have the focus.
Edit
make sure you call the next hook in your callback with CallNextHookEx to not screw up screen readers
I used the following code and it seems to be catching the focus changes, and I am not getting any problem with regard to holding down ALT or TAB in various combinations. But I didn't thoroughly test it yet.
EDIT: I read your post again and see that your problem is probably an interaction between the two different hooks. So I am also hooking the keyboard in my app, but I am using an Import Address Table hook of DispatchMessage. My hooks don't interact the way yours do, but my solution may not be appropriate for you.
bool AddHookToKeyboardFocusChanges()
{
HHOOK hhookFocusChange = NULL;
hhookFocusChange = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWindowProcHook, NULL, GetCurrentThreadId()); // the last parameter makes it a local, not global hook
if(hhookFocusChange == NULL)
return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////
// This is the routine that we register to be called on every call to a
// WindowProc in our application; we use it to catch WM_SETFOCUS and
// WM_KILLFOCUS messages that indicate gaining or losing keyboard input focus.
// Unlike keyboard, mouse, paint, and timer messages, the focus messages are not
// posted to the message queue. Instead they are sent directly to WindowProc.
// We must hook them here.
//
LRESULT WINAPI CallWindowProcHook(int nCode, WPARAM wParam, LPARAM lParam)
{
UINT message = ((CWPSTRUCT*)lParam)->message;
switch(message)
{
case WM_ACTIVATE:
OutputDebugString(L"Window activated.\n");
break;
case WM_SETFOCUS:
OutputDebugString(L"Window focused.\n");
break;
case WM_KILLFOCUS:
OutputDebugString(L"Window focus lost.\n");
break;
default:
break;
}
// CallNextHookEx calls the next hook in the chain.
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

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

Intercept mouse input

I was wondering if there is a way to intercept and modify mouse input before it gets to windows?
What I'm wanting to do is intercept mouse motion events, apply some custom scaling and acceleration to the values, and then continue passing them along. I'd need something that can do this before the inputs get to the raw input API or DirectInput.
In order to affect all mouse input, including DirectInput, during logon and the SAS screen, etc., you'll need to load a filter driver into the mouse driver stack.
Other people have done it, for example http://www.maf-soft.de/mafmouse/
There should be a moufiltr sample in the Windows DDK which you can use as a starting point. You will most likely want to use a virtual machine for development since errors in a driver on your development machine could be difficult to recover from.
Have you seen this method of intercepting mouse and keyboard input without having to make a filter driver or hook?
http://oblita.com/Interception.html
There is a LowLevelMouseProc hook procedure that you can use to get information on any mouse input entering the system, although I doubt if you can actually change this information (and the docs are silent on this).
If this fails, GetMsgProc is an alternative that lets you intercept all messages posted to any window. Though this hook does let you modify the message, it's probably too late to have any effect on APIs such as DirectInput.
You could try a windows hook - which are functions you set to receive windows messages before they get passed through to the rest of the system - a CBT hook (for computer based training) is what might get you best results.
I don't know Whether this will work with DirectInput or the other new stuff MS has added to break all the old internal consistency. Its easy to set up though, so try it and see.
As far as I know the best way is to hook to windows message loop, In your case you should pass HWND 0 (If I remember correctly this the HWND of the desktop) so all the messages will pass though your function first.
http://msdn.microsoft.com/en-us/library/ms633591%28VS.85%29.aspx
More on hooks : http://msdn.microsoft.com/en-us/library/ms644959%28VS.85%29.aspx
Use it as follows:
m_nOldWindowProc = ::SetWindowLong(0 /I think.../, GWL_WNDPROC, (LPARAM)(WNDPROC)WindowProcCallback);
and the callback:
LRESULT CALLBACK CStubWindow::WindowProcCallback(HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lParam)->cx = STATUS_BAR_WIDTH;
((WINDOWPOS*)lParam)->flags = SWP_NOOWNERZORDER | SWP_NOMOVE;
break;
default:
break;
}
return ::CallWindowProc(m_nOldWindowProc, hwnd, message, wParam, lParam);
}

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
}