I have two devices that create keyboard input, one of them is a real keyboard and the other uses SendInput() to send Injected keyboard input. I am modifying an existing program that uses a hook to send the keyboard message only to its own window and blocks the input globally to other programs. However I do not want the Injected input to be blocked, and I also don't want the program to process the Injected input.
I used a WH_KEYBOARD_LL hook to determine if the input is Injected, Then I used a global WH_KEYBOARD hook to send the message only to the window if it is the real keyboard. What I am looking for is a way to sendMessage() to everything except the main window. I couldn't find a method in the documentation to do this though, so I decided to pass the hook farther down.
// WH_KEYBOARD
static LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
//Report the event to the main window, but do not pass it to the hook chain
if (realKeyboard) {
SendMessage(hwndServer, WM_HOOK, wParam, lParam);//only listen to real keyboard, block emulated one
}
else {
//what i want is to sendMessage to everythng except the main window
return CallNextHookEx(hookHandle, code, wParam, lParam); //let injected keyboard passthrough
//however we want to ignore injected inputs in the main window(keyboard program).
}
return 1;
}
I created a local WH_GETMESSAGE hook using GetCurrentThreadId(), to see if I could ignore the injected input there.
// WH_GETMESSAGE
static LRESULT CALLBACK GetMessageProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
if (!realKeyboard) {
MSG * info = (MSG *)lParam;
info->message = WM_NULL;
}
return CallNextHookEx(hookHandle, code, wParam, lParam);
}
I read somewhere that info->message = WM_NULL; would work to block the message but it doesn't seem to have an effect. I also Tried creating a message loop something like this but it didn't work either.
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if(IsRealKeyboard()){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Any ideas how I can ignore the injected message only in the main window and let it through to the rest of the system?
You could use RAW INPUT in the target window and process the WM_INPUT message, then get the Raw Input buffer via GetRawInputData.
Related
I noticed that MSG from winuser.h (which is typedef'd to tagMSG) contains all the parameters from wndproc callback.
I was wondering if there's any real difference handling messages in wndproc vs handling the outside of wndproc by using MSG, along with the different use cases between the two
Basically something like the following
LRESULT WinApp::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(hwnd);
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
vs
MSG msg;
if ((PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(hwnd);
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Each window is associated with a WindowProc function. Both queued and non-queued messages that are dispatched to a window will arrive in its WindowProc. This is the preferred place to process messages that are specific to each window.
MSG is used when retrieving queued messages from a thread's message queue, before dispatching the messages to their target windows (see DispatchMessage()) . Processing messages directly in the message loop is the preferred way to handle messages that are specific to a thread but not necessarily to a specific window.
Basically it's the same, in terms of code processing and execution.
But, the main difference goes from the SendMessage function's family:
The SendMessage function calls the window procedure for the specified window...
Generally speaking, in Windows world each window has its own window's procedure, that can be called outside of the thread's message loop this window belongs to. As opposed to the PostMessage function, that:
Places (posts) a message in the message queue associated with the thread that created the specified window
So now it's clear, that messages might be handled in the main message loop, but in this case you are able to handle only the thread's messages. But you lose the ability to handle messages that was sent directly to your WndProc.
The difference is that using the normal message loop will handle cases involving multiple window classes, each with its own WndProc. What you show will only work if there is only going to be one set of message handlers for all windows (including popup menus).
I have written an application to hook some procedure onto a new process to monitor mouse down events and to disable mouse down events on the new process. As of now, I am able to capture to mouse down events coming to this process and I am trying to disable all mouse down events as a POC. This is what I am doing currently in the hook procedure.
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
When I perform mouse down event, I am getting the log message that I have written. But I also expect that click event to be blocked since I am returning false. but it does not happen so and click event proceed as a normal click. How could I disable mouse down event. Thanks in advance for any help on this
This is how I call setWindowsHookEx
HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
The reason you are supposed to call CallNextHookEx during your hook routine is so that the message can be passed on to any other hooks that might be installed. Failing to do so does not prevent the message from being seen by the application that received it.
The documentation for WM_NULL explains how to block the message:
For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number to WM_NULL so the recipient will ignore it.
The corrected code should therefore look something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
return false;
}
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
However, this may cause inconsistent behaviour if other hooks are present, because whether another hook sees WM_LBUTTONDOWN or WM_NULL will depend on the order of the hook chain, which is unpredictable. It might be preferable to try something like this:
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
if (code >= 0) {
LPMSG msg = (LPMSG)lParam;
int result = CallNextHookEx(NULL, code, wParam, lParam);
if (msg->message == WM_LBUTTONDOWN) {
OutputDebugString(L"Mouse down event happened \n");
msg->message = WM_NULL;
}
return result;
}
return(CallNextHookEx(NULL, code, wParam, lParam));
}
I'm using Windows 7 and VC++. The business is to know how many seconds my system has been set into screen saver mode or monitor screen off. To achieve this, I'm trying to catch the events WM_SYSCOMMAND and SC_SCREENSAVE, SC_MONITORPOWER. So I have created a Win32 project in Visual Studio 2008 and I'm receiving the events in WndProc function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case SC_SCREENSAVE:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_SCREENSAVE\n",fl);
fclose(fl);
}
break;
case SC_MONITORPOWER:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_MONITORPOWER\n",fl);
fclose(fl);
}
break;
default:
{
}
}
}
break;
}
}
It works fine when dialog is in foreground, but in background (or if I comment ShowWindow function) it only works if I manually send the events:
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, (LPARAM)2);
or
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
So, it is not working when system power configuration sets the screen saver after 2 minutes of inactivity, and the same thing with automatic monitor screen off. Thats the real thing I want, know when the system is turning off the screen or setting the screen saver, with a background monitoring program.
I have also tried to use hook events with extern dll. I have followed this example http://www.codeproject.com/Articles/1037/Hooks-and-DLLs adding in the CALLBACK msghook() function the same switch code above in WndProc. It doesn't work even using the SendMessage.
After several days stuck with this issue, searching in the Internet, forums... I don't know what else I can do. Can anyone help me?
I were not using hooks properly, but it has been rare. Firstly, about setWindowsHookEx function, I have read WH_CALLWNDPROC or WH_SYSMSGFILTER must be used to get WM_SYSCOMMAND sent messages, and then get SC_SCREENSAVE wParam. In this case, I don't know why and maybe I'm wrong, but thats seems not to be true.
After use every possible message to SetWindowsHookEx, I realised WH_GETMESSAGE is the only one who sends SC_SCREENSAVE wParam, at least in this hook example in Windows 7.
HHOOK hook;
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE,
(HOOKPROC)msghook,
hInst,
0);
Secondly, listening for every message catched in hook function, WM_SYSCOMMAND were appeared with LPMSG. I have read also that wParam must to be combined to 0xFFF0 to be compared. But wParam & 0xFFF0 == SC_SCREENSAVE didn't work and wParam == SC_SCREENSAVE neither. In this case the only way is using LPMSG for both WM_SYSCOMMAND and SC_SCREENSAVE.
static LRESULT CALLBACK msghook(UINT code, WPARAM wParam, LPARAM lParam)
{
if(code > 0)
{
CallNextHookEx(hook, code, wParam, lParam);
return 0;
}
LPMSG msg = (LPMSG)lParam;
if(msg->message == WM_SYSCOMMAND)
{
if (msg->wParam == SC_SCREENSAVE)
{
MessageBoxA(NULL,L"SC_SCREENSAVE",L"SC_SCREENSAVE",MB_OK);
}
if (msg->wParam == SC_MONITORPOWER)
{
MessageBoxA(NULL,L"SC_MONITORPOWER",L"SC_MONITORPOWER",MB_OK);
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
And using FILE to test the events was a very bad idea, I think using MessageBox is not much better but I don't know how to test ir correctly.
I want to detect everytime I paste something. It's just something to make some data entry work simpler.
I set a global hook and then "wait" for the wm_paste. This is part of the code I have:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)//Do not process the message
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
LPMSG m=(LPMSG)lParam;
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
if(m->message == WM_PASTE)
{
OutputString("Paste detected!\n");
}
return CallNextHookEx(msg_hook,nCode,wParam,lParam);
}
//DLL_ATTACH:
...
if(strstr(ProcName, LOADERNAME))
{
InitCommonControls();
if(!(msg_hook=SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDLL, 0)))
{
ErrorExit(TEXT("SetWindowsHookEx"));
//MessageBox(0, "WH_GETMESSAGE", 0, 0);
//return -1;
}
}
WM_PASTE debug string never gets printed. I'm aware that not all applications use WM_PASTE. But at least notepad should work.
Any suggestions?
Thanks!
In GetMsgProc, the wParam parameter is not the message being intercepted, but a flag that indicates whether or not the message in lParam and been removed from the message queue.
You should be using m->wParam instead.
Wm_paste message is fired only in combo box and edit control. There is no easy way to capture paste, but you can get copy message by creating a tiny window and adding this window to the chain of clipboard viewers.
The following code works fine. It gives out the message when the user presses a key. But there are certain things I am not aware of. What is the role of Message Loop here ? I read that calling SetWindowsHookEx(...) registers a function with the windows and windows calls the appropriate function automatically when a event of registered type happens. No doubt that i don't see the output if don't give the message loop it's space.
#include<iostream>
#include <windows.h>
using namespace std;
HINSTANCE hinst = NULL;
static HHOOK handleKeyboardHook = NULL;
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
void setWinHook() {
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,NULL, 0);
if(handleKeyboardHook == NULL) {
cout << "is NULL";
} else {
cout << "is not NULL";
}
cout<<("Inside function setWinHook !");
}
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
cout << ("You pressed a key !\n");
return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
EDIT
Does exiting the program (closing the console window) unregister the hook ?
EDIT 2
what role does Dispatch Message play here ? According to doc it dispatches a message to window procedure,but here even if i exclude that,it doesn't effect the output.
All events in Windows, even the low-level keyboard event used in your example, is sent using the normal message events. So for the program to be able to sense keyboard events, it has to use an event loop processing messages.
Without a loop, the program would exit immediately, and the hook would be removed at once too. You cannot register a hook and exit — the system would become a mess if buggy programs were leaving too many forgotten hooks after them. Once your process dies, the hook is scheduled for removal.
I don't remember about low-level keyboard hook, but callbacks of many other hooks are only called inside GetMessage/PeekMessage, and not on some other thread, so just an infinite loop won't suffice — it has to be a message loop.
"what role does Dispatch Message play here ? According to doc it dispatches a message to window procedure,but here even if i exclude that,it doesn't effect the output."
DispatchMessage is pretty useless cos console window doesnt receive much messages.
Only message received is when window loses focus.