Windows Event_System_Foreground delivery order - windows

Working in a plugin architecture (specifically, Sparx Systems Enterprise Architect), which does not forward either raw or cooked keyboard events, keyboard shortcuts for the plugin can be defined using RegisterHotKey(). These hotkeys are global, and the registration call fails if the specified key combination is already registered.
Since the application within which the plugin executes can be run in multiple instances, the hotkeys need to be repeatedly registered and unregistered based on which instance is in the foreground. An event hook for EVENT_SYSTEM_FOREGROUND can be set up for this purpose, but the question is: is there a guaranteed delivery order?
I need the instance that is losing focus to be told first so that it can unregister the hotkeys before the instance gaining focus tries to register them.
Is this possible? Or will I have to implement synchronization to be sure?

Windows DevCenter WM_ACTIVATE message says
..Sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. If the windows use different input queues, the message is sent asynchronously, so the window is activated immediately..
So if all of your windows come from the same application sharing the same input queue then it should be guaranteed. I guess that the EVENT_SYSTEM_FOREGROUND is built on top of the older code following the older logic (at least the implementation in ReactOS at http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/focus.c?view=markup (see EVENT_SYSTEM_FOREGROUND inside co_IntSetActiveWindow) does it)
Your problem might be easier if you'd monitor only keyboard events in your original hosting process (no global side effects) using the Windows DevCenter SetWindowsHookEx function, filter WH_KEYBOARD
In that case your code would exist once in one exe having one global variables, no cross-process synchronization would be needed

Related

Why does Spy++ fail with console windows

I was attempting to verify that messages were being sent to my window using Spy++ (running Windows 7), but I mistakingly tried to spy on a console window that my program was using for debug output. Spy++ promptly notified me that "The specified window cannot be spied upon. Windows will not allow access to the message stream for this window."
While Spy++ does correctly gather other information about the window (e.x. name, style, class name), it cannot process the message queue. Why is this? And, out of morbid curiosity, is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?
While Spy++ does correctly gather other information about the window (e.x. name, style, class name), it cannot process the message queue. Why is this?
The console window belongs to the CSRSS process, not the CMD.EXE process. CSRSS is a critical system service that is protected and cannot be hooked without special debug privileges.
"When a user-mode process calls a function involving console windows, process/thread creation, or side-by-side support, instead of issuing a system call, the Win32 libraries (kernel32.dll, user32.dll, gdi32.dll) send an inter-process call to the CSRSS process which does most of the actual work without compromising the kernel."
And, out of morbid curiosity, is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?
Typically, no. Unless you manage to run your window in a protected system process.
So, I discovered this myself recently, I created a console .NET application which launches a process using CMD.EXE and I ran into an issue with some Win32 interop around the keyboard. So I broke out the previously trusty Spy++ utility to see what was happening to find that I was completely unable to monitor the message queue for my application from it.
So as per the op's question:
"Is there a way to prevent Spy++ from accessing the message queue of my own custom window using the Windows API?"
There is a list of restricted windows classes baked into Spy++:
SpyxxHk (presumably it's own hooking class),
#32768 (Context Menu),
#32769 (the Desktop),
ttyGrab ,
ConsoleWindowClass (Command Prompt)
So, if you in any way tie your app to these classes Spy++ will display that block message when attempting to watch their messages, of course this may not prove useful since it only restricts those classes.
Referring to MS documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
"For out-of-context events, the event is delivered on the same thread that called SetWinEventHook. In some situations, even if you request WINEVENT_INCONTEXT events, the events will still be delivered out-of-context. These scenarios include events from console windows and events from processes that have a different bit-depth (64 bit versus 32 bits)"
Suggests it is possible to get console window events.

How to intercept a window message in a shell extension

I have a shell extension that needs to reload its configuration when a specific window message (custom message registered with RegisterWindowMessage) is broadcasted by another application.
I tried several approaches to intercept the message:
Installing a window subclass callback on a window of Windows Explorer, using SetWindowSubclass. This works on Window 7, but not on Windows 8, because apparently DllMain is not called on the main thread, and SetWindowSubclass doesn't work from another thread. This is mentioned in the documentation:
You cannot use the subclassing helper functions to subclass a window across threads
Installing a hook for CALLWNDPROC, using SetWindowsHookEx. Because I don't want to slow down the whole system, I install the hook for a specific thread only (the explorer's main thread). This works on Windows 8, but not on Windows 7... I suspect this is because I'm hooking on the wrong thread, but I'm not sure. And anyway, this approach seems overly intrusive.
Creating a message-only window to handle the message. This doesn't work at all, because message-only windows don't receive broadcasted messages.
Is there a reliable way to receive a window message in a shell extension?
A window message initially seemed to be the easiest way to notify the shell extension, but if you think another mechanism would be more appropriate, I'm open to suggestions.
Create a hidden window and listen for the message in its window procedure.
Register a window class that has default values for all the fields apart from the window procedure and class name. You don't need to specify anything else in the window class since the window will never be visible.
When you create the window, pass 0 for the window style. Specifically exclude WS_VISIBLE.
Pass 0 for the WndParent when you create the window. This will make it a top level window and so eligible to receive broadcast messages.

WH_KEYBOARD_LL hook doesn't capture input in own process

I'm using a low-level keyboard hook (WH_KEYBOARD_LL) to disable certain input, such as Alt-Tab. I create the hook on a thread with a message pump, so I can properly handle the notifications.
The hook's callback function is able to process keyboard events whenever I'm not focused in the window that created the hook (i.e. my main window), but as soon as I activate that window, no events show up in the hook until I deactivate the window again and the input instead propagates to the window's WindowProc.
Does anybody have any clue what's going on here?
UPDATE: So, it turns out this behavior is caused by also registering for raw input in the same process. Apparently, using raw input causes my low-level keyboard hook to be disabled whenever my process’s window is focused. Does anybody know why and how to work around this?
Windows doesn't call low-level keyboard hooks if the most recently registered hook (aka the first hook to be executed) comes from a process that registered itself for raw keyboard events.
So a workaround is to create a second low-level keyboard hook in another process afterwards. Yes, this will cause both low-level keyboard hooks to be executed even when the focus is on a window from the first process.
Bad for performance, and who knows what Windows will bodge next - so I'm not really endorsing it - but it works.

Window hooks and applications

Related to my question here, is it possible to create a window hook that will monitor if an application has been opened or not?
Most that I have found about hooks seem to focus on user input (keyboard press, mouse events), but I could not confirm if it is possible to know that the "double click" the user made is to open an application, or just to highlight a word.
Thank you.
Indeed, window hooks would not be sufficient. In fact for the task you are asking about you could use various strategies, such as:
enumerating the processes to find the one you're looking for (Tool Help API or PSAPI)
enumerating the top-level windows on the desktop (but you're limited to your desktop then)
check for a global or local event, mutex (or other kernel object) to deduce from that that some instance of the application is running
... or even from kernel PsSetCreateProcessNotifyRoutine
probably there are variations on the above plus some more.
In essence the question is whether you want to check for the process or for some other indicator that signifies whether the program you want to check for has been started.

Why might IsDialogMessage() never return?

I am debugging an application which, in its message loop, calls IsDialogMessage(). Occasionally, IsDialogMessage() never returns (where never is an interval greater than 1 hour). Based on the symbols for user32.dll available from Microsoft's symbol server, it appears to be stuck in GetNextDlgGroupItem() (or an internal variant of the same), iterating over some set of windows.
The application is multithreaded and frequently receives notification of external events, which arrive as DCOM calls. I suspect that such a call is handled incorrectly in a way that corrupts some window state. If I can learn what sort of state corruption might cause an infinite loop in IsDialogMessage(), I think I will be more easily able to identify the source of the corruption.
I know this is old, but answering for posterity since no one here mentioned it.
More than likely what is going on is trouble with the windows manager determining where to forward a message. If you have a hierarchy of windows, as you probably do, then you need to ensure that non-top-level windows that contain controls themselves must have the WS_EX_CONTROLPARENT style set. If it is a dialog, you use the DS_CONTROL style. The presence of these flags modify the behavior of IsDialogMessage; they identify a window as having its own controls which can receive focus and handle tab order, etc, rather than just being a control itself.
For example, if you have a main frame window, which has a child window with WS_EX_CONTROLPARENT, which has a child window without WS_EX_CONTROLPARENT, which has a child window that has focus, and you hit TAB, you will likely encounter an infinite loop at the same place you mention.
Setting the second child's extended style to include WS_EX_CONTROLPARENT will resolve the issue.
Are you maybe disabling controls (using ::EnableWindow()) without checking first whether that control has the focus? If yes, then the focus gets lost and GetNextDlgGroupItem() gets confused.
Another reason this can happen is if you reparent a modeless dialog. At least this can happen with wxWidgets...
I've made some investigation, trying to answer this question. But only in situation, when parent window is in native MFC project and child is a managed C# Windows Forms. If you have such situation, then you may try 3 resolutions:
Run MFC dialog message loop on Windows Forms side. Here is more info: Integrate Windows Forms Into Your MFC Applications Through C++ Interop
Create 2 threads: one for Windows Forms dialog and one for native dialog. Here you can create dialog in Windows Forms, then with SetParent() set it's parent to native dialog. But be ware: if you add TabControl to Windows Forms, than hang with "IsDialogMessage() never return" will occur.
Make a wrapper for Windows Forms dialog to use in native project. For ex., wrapper may be WPF, see here: Windows Form as child window of an unmanaged app
I've taken information mostly from: http://msdn.microsoft.com/en-us/library/ms229600.aspx
And the temporary cure can be to change focus behavior. For example, disable them, or SetFocus() to parent or child windows only. But I strongly recommend to investigate the real reason, why IsDialogMessage() never return in your case.

Resources