KeyboardProc returning TRUE causes performance drops - c++

I'm developing an interface for an add-on to a game. I can't use the game API (for several reasons including the fact that the code must be game-agnostic) and I need to get keyboard input from the user so I've decided to use a keyboard hook (WH_KEYBOARD) to process user input when certain conditions are met.
The problem is that while I can receive and process the input correctly, when my hook returns TRUE instead of CallNextHookEx the system seems to take up a lot of time (well over 800ms) before letting things go on as expected and that's not acceptable because it doesn't even allow for a fluid typing experience.
What I have to achieve is preventing the key press message to reach the WndProc, so the question is: what can I do to achieve my target without hurting the game performance so much that the result will be unacceptable?
EDIT: due to specific requirements (games using anticheats which might create problems with my code despite it's not cheating-related) subclassing the active wndproc is not an option.

First you need your DLL to be injected into the target process, either by hooks, or by any other way.
Find the window handle of interest.
Obtain the current window procedure of that window, by calling GetWindowLongPtr(wnd, GWLP_WNDPROC), and save it.
Sub-class the window, by calling SetWindowLongPtr( wnd, GWLP_WNDPROC, &NewWndProc ) where NewWndProc is your DLL-implemented message procedure.
Inside NewWndProc you'll want to process keyboard messages (there're a dozen of them, type "keyboard input" in MSDN index, I can't post more then 1 link). For the rest of windows messages call the original window procedure you've saved during (3), and return the value it returned. Don't call it directly, use CallWindowProc instead.
This way is not very reliable, some antivirus and anti-bot (e.g. "warden client") software might not like it, and debugging may be challenging.
However it should work.

A keyboard hook should not make things that slow. There's probably something else going on that causes the 800ms delay. Is it still slow if your hook does nothing and simply returns TRUE?

If you want to prevent from message to arrive to the WndProc then you need to subclass using SetWindowLong, this way you will be able to catch all messages and decide if to continue their route.

As much as I don't like answering my own question I've found the cause of the delay. The message pump of the games I've tested my code against was implemented with a while(PeekMessage) { GetMessage... } and removing the keyboard input message somehow caused GetMessage to block for sometime. Using PostMessage and WM_NULL helped preventing GetMessage from blocking.

Related

look for keypress only if window is in focus

I am writing a program which interfaces with some testing equipment. I want the user to be able to press a button to stop the test, but only if the program is in focus. This is because they can be using their pc for other work at the same time. This is what I have now.
if ((GetAsyncKeyState(VK_ESCAPE) & 0x8000)&&(GetFocus() == FindWindow(NULL,TEXT("Window name")))){
break;
}
The problem is, the keypress is still determined even when the user is working on other programs. I also want this to happen without waiting for user input so the program can continue running(i realize I could probably use threading but I think that seems a little overkill in this case). If anybody knows a statement I can use in the second half of the IF statement that would be great, or even a different method altogether.
Thank you.
Wild guess this one. Maybe you could use the GetForegroundWindow function and check the handle against your test window handle. Possibly a better method is for your test window to handle the WM_KEYDOWN message. My understanding is that this message is only posted if the window has focus.

Is it possible to trap the Windows Start Menu popup via Windows key(possibly without a hook)?

I've been working on an input event system.
I mapped all the keys on my own keyboard, the scancodes and so on, including both windows keys.
When I press them, the program successfully receives the distinct keydown events for them without any trouble.
When I release the keys, however, the Start Menu pops up, obscuring the program in windows mode, or even minimizing it in fullscreen.
So my problem lies in suppressing that.
Arma 2, a Military Simulator/Game allows commands to be mapped on those keys without any trouble.
Where do I have to catch that event?
Can I do it for my own window as long as it has focus?
Am I going to be stuck with a disabled win-key as long as it is running?
Or something else?
Googling it was mainly fruitless due to Windows key also referring to the product key, and when I did find something, it usually flat out disabled the whole button.
I just want to suppress the popup.
Edit:
I tried
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_TASKLIST:
return 0;
default:
break;
}
But that gave me very odd results.
If I spammed the winkeys and only the winkeys, it seemed to work, as soon as I moved the mouse while doing so, it didn't, the start menu would pop up again.
Edit:
I also tried hooks, but on win7 they get removed if the callback takes too much time, which can happen when large data is loaded, so they suggest a dedicated thread for it, but I think that's overkill for just one key that needs handled.
I just want to know where the Start Menu gets called. My own program? The system?
This is so friggin annoying, I am contemplating trying to reach the people from Bohemia Interactive and ask them how they did it.
Just this one key, sheesh Microsoft...even with "Super key/superkey" search terms, I usually only get flat out disabling methods, from registry changes to third party background programs.
Bah!
This artcile was relating to C# but may point you in the right direction;
From MSDN:
A global hook monitors messages for all threads in the same desktop as
the calling thread. A thread-specific hook monitors messages for only
an individual thread. A global hook procedure can be called in the
context of any application in the same desktop as the calling thread,
so the procedure must be in a separate DLL module. A thread-specific
hook procedure is called only in the context of the associated thread.
This was the most helpful link in order to answer the question in the above article
The Raw Input API should solve your problem.
http://msdn.microsoft.com/en-us/library/ms645543.aspx

Closing a MessageBox automatically

I have a third party encryption library, which may create a MessageBox if key creation fails. The failure can be caused by bad random number generation or other rarities, and in most cases, trying again will result in success. My code will attempt key creation up to three times before deciding it failed.
Now, the issue is that the program may be used with automation. If a MessageBox is created during automation, it will block the process forever, because there's nobody to click the 'OK' button.
Does anyone know of a way to catch when this message box is created and automatically close it?
Anything is fair game, as long as it's not something that will make security suites angry. This means no hooking or code tunneling.
In summary, I need to catch when a MessageBox is created and close it. The MessageBox's creation is outside of my control. Modifying the code at runtime is not acceptable.
Also, I've noticed there are some other similar questions, but they don't have the same requirements.
EDIT: Additional note, I can find the message box via searching through all windows until I find one with a matching title and then send it a WM_CLOSE message, but I don't think this is a great solution. I also have no guarantee that the message box has been/will be displayed, or how long after my call it will be displayed. It could display instantly, it could display 1200 ms later, or it could not display at all.
Just before you begin the encryption process, install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, or if that doesn't work post a WM_CLOSE (or a BM_CLICK to a relevant button if selecting an option is necessary). Uninstall the hook after the process for not messing with every possible dialog your application pops up.
That sounds like bad design on the part of that library. Generally any sort of utility library (like encryption) has no business invoking any kind of GUI (unless you explicitly ask it to).
Is there possibly some configuration or setting in this library that could disable its use of message boxes?
If not, I'd suggest that you might want to investigate using a different library. After all, if the designers of this library have already made this kind of poor design decision once, then there may be other unfortunate surprises lurking in there.
You can hope that it will be found by GetForegroundWindow, but this may catch other applications. The more brute force way is to iterate over all windows with EnumWindows looking for something that has a caption or text equal to this shown by the library.
I have once "remote controlled" an application by sending mouse click events to some controls. I guess you would have to do this in a separate thread that is watching for Events if a window is opened. Pretty ugly but working...
Create a new thread. If your function fails and a Message Box is opened, obtain a handle to the message box by looping through the windows (GetTopWindow, GetNextWindow) and comparing the window's process id to the one returned from GetCurrentProcessId().
Or, you can avoid all the hard work and just hook the MessageBox API with detours. It's not very hard, and if you don't want to pay for detours, you can do it manually.
Call VirtualProtect and set the memory protection at MessageBox at PAGE_EXECUTE_READWRITE
Create a naked function, and use it as a trampoline.
Create a function identical in parameters to MessageBox (this will be your hook)
Create a jump from MessageBox to your hook function.

Globally intercept window movement

I am having trouble getting a global system hook to work. I want to be notified whenever a window is moving, as early as possible, and change the window size. This means the CBT hook HCBT_MOVESIZE won't cut it, it only happens after the window has been moved. I want to hook the actual movement of the window, and be able to change the window size during the move.
The hooks are set from a DLL, and the callback function is within that DLL. This is what I've tried.
WH_CALLWNDPROC. It does alert me when a window is moved (WM_MOVING is received for windows from other applications), but I cannot change the contents of the message.
WH_CALLWNDPROCRET Same as WH_CALLWNDPROC.
CBT hook HCBT_MOVESIZE. Event happens to late.
WH_GETMESSAGE. Never receive WM_MOVE, WM_MOVING or WM_WINDOWPOSCHANGING. This hook would allow me to change the messages.
Update: Windows event hooks seem to allow me to capture it:
hWinEventHook = SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART,
EVENT_SYSTEM_MOVESIZEEND, NULL, WinEventProc,
0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
However, this creates a different problem: changing the size of the window using SetWindowPos() does not work (it changes size alright, but immediately changes back to its previous size), even though I use SWP_NOSENDCHANGING. Ideas?
Update 2: Subclassing seems to work, however Visual Studio crashes after each program run (so does a lot of other windows). It works well if I place breakpoints and walk through the "unsubclassing", but not when I let the program run by itself. Ideas?
I have a CBT hook (it was there from earlier), and whenever HCBT_ACTIVATE is sent for a new window, I remove any previous subclassing using SetWindowLongPtr() (this has to run on 64-bit as well), and then subclass the new window. If I put a breakpoint anywhere, and immediately resume the session when it breaks, everything works fine. However, when I do not have any breakpoints, Visual Studio crashes when the program exits.
Hm, I would've thought that HCBT_MOVESIZE is precisely what you want, given that the MSDN says this about CBT hooks:
The system calls this function before activating, creating, destroying,
minimizing, maximizing, moving, or sizing a window.
and in particular:
HCBT_MOVESIZE
A window is about to be moved or sized.
(these quotes were taken from http://msdn.microsoft.com/en-us/library/ms644977%28VS.85%29.aspx)
...so I'd have thought that you get the HCBT_MOVESIZE call in time. The hook function which handles HCBT_MOVESIZE is also allowed to return an integer so that the system can determine whether the operation is allowed or should be prevented. Hence, given that the HCBT_MOVESIZE hook should get an option to prevent the operation, I'd say it's called before the move event occurred.
Are you really sure the hook function is called after the move event? If you do a GetWindowRect call on the particular handle within your hook function, does the returned rect equal the rectangle which is passed to the hook function?
Hooks are pretty heavy. You only want to use them when you absolutely have to.
That said, you could use one of the basic hooks simply as a way to get into the process. Once in the process, you could subclass the window you're interested in and handle the sizing messages in your subclass proc rather than trying to catch everything at the hook level.
Depending on what you want to do in response to the resize, you might need some interprocess communication.

WINAPI: Look at messages from other process

I'm quite new to the Windows API and would like to know how to peek at messages another process receives. As an example, I would like to get the HWND of, say, notepad and peek at all messages that are sent to this window. I code in C/C++.
Thank you
You can use SetWindowsHookEx function, with WH_CALLWNDPROC or some other type of hook, and here is an example.
The WH_CBT can give you great opportunities because you can get a HCBT_CREATEWND code from it and it's sent to you right before a window is created, thus giving you a possibility to provide your own window proc instead of the real one and then be able to get all messages possible with it.
Remember though, greater possibilities also mean greater responsibility. Say you "subclassed" some window, providing your window proc, if your application that set a hook exits, next thing you'll see is the application, whose messages you were peeking at, crashes if you didn't put the address of the original window proc back to where it belongs. The benefit of this kind of hooking is the ability to wait for a certain window (say with a certain window class, or name) to be created and get into that process before any window you're interested in would even be created.
You want to look into SetWindowsHookEx
You are looking for Windows Hooks .
http://msdn.microsoft.com/en-us/library/ms997537.aspx
You can trap SendMessage in the target process using CallWndProc hook procedure.