views:

66

answers:

2

I have an older C++ Windows program that I've been asked to get run in a kiosk style environment for a student project. From the main menu, hitting ESC will exit the program, which is undesirable. In ye olden days I would have trapped the keyboard interrupt or whatever and dug around to NOOP whatever JMP or CALL was getting referenced in the case statement that likely decides all that, but on Windows everything goes through various registered event handlers, and I haven't done any windows internals work in about 10 years.

Is there a good tool to breakpoint a program on certain WM_EVENT (WM_KEYDOWN being a prime target) messages or similar, so that I can narrow down where in the executable the check is made? I'm currently stepping back from various potential system calls made before the various thread cleanups and final exit calls but it seems like there has to be a better way to do this that I'm forgetting.

+1  A: 

Assuming that you don't have the sources of this program, you may inject a dll made by you in the process (with the old CreateRemoteThread/LoadLibrary trick), and in the DllMain subclass the main window. Now, all you have to do is to filter the WM_KEYDOWN and kill it (you may not call the original wndproc at all or replace it with a WM_NULL); you may also filter the WM_CLOSE messages to avoid other kind of close requests. You may obtain a similar effect also with hooks.

For more details about window subclassing, see the asveikau's answer.

Matteo Italia
Thanks! I should have been more specific on one point, which is other potential ESC key event do result in desired behavior, or intercepting all of them would have been my first choice. I am going to investigate just intercepting the WM_CLOSE messages with a DLL injection, which may cover what the students need.
rustyn2
+2  A: 

If you have an HWND to the window that processes the message, you can intercept its messages, selectively not delivering certain messages to the "real" window procedure.

For example:

/* Get the current window proc for this hwnd. */
WNDPROC OldWindowProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);

/* Set the window proc to your own override. */
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (ULONG_PTR)MyWindowProc);

Then inside MyWindowProc, you would intercept the WM_KEYDOWN. For all other messages (and for the WM_KEYDOWNs you want to fall through to the control), you would invoke OldWindowProc (the window proc you don't have source to) via CallWindowProc.

Update: Didn't realize this is an EXE you can't change directly. You may need to combine this technique with the DLL injection mentioned by Matteo. Maybe you can inject your DLL, get an HWND via FindWindow, and then change the window procedure as I've described.

asveikau