I have a 3rdparty application (target), which creates a window. I embed that window into my own application by setting parent, changing styles, etc.
The problem is that Spy++ shows target receiving WM_DESTROY two times (in case I close my app). Sometimes this leads to crash of the target.
I want to understand, why the message queue contains 2 WM_DESTROY associated with target window (btw, only 1 WM_NCDESTROY).
To do that I was setting breakpoints at DestroyWindow, PostMessage syscalls, but these functions appear not to be called for the main target window (first one is called only for child windows, second one - with different messages, except WM_DESTROY). I did that in context of both my process and the target process.
So the question is, is there any low-level function which puts messages into the thread message queue? I want to put breakpoint at it and catch a moment when the extra WM_DESTROY is put there.
Smth like PostThreadMessageInternal...
Thanks in advance!
Related
I need to pump COM messages while waiting for an event to fix a deadlock. It's better to pump as few messages as possible just to process that COM call. The best candidate for this role is CoWaitForMultipleHandles but starting from Vista it pumps WM_PAINT in addition to COM messages. Pumping WM_PAINT is too dangerous for me from re-entrance perspective and I don't want to install a custom shim database as a solution for this problem.
I'm trying to pump COM messages sent to the hidden message-only window manually.
I have found two ways to get HWND of the hidden window:
((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA using ntinfo.h from .NET Core. This seems to be undocumented and not reliable solution in terms of future changes.
Find window of OleMainThreadWndClass as suggested in this question. The problem is that CoInitialize does not create the window. It is created later on first cross-apartment call which may or may not happen in my application. Running the search loop every time I need HWND is bad from performance perspective but caching HWND seems impossible because I don't know when it's created.
Is there a way to determine if the hidden window is created for the current apartment? I suppose it will be cheaper than the loop and then I could find and cache HWND.
Is there a better way to pump COM messages without pumping WM_PAINT?
Update: you can force the window creation by calling CoMarshalInterThreadInterfaceInStream for any interface. Then call CoReleaseMarshalData to release the stream pointer. This is what I end up doing along with the search for OleMainThreadWndClass.
WM_PAINT is generated when there is no other message in the message queue and you execute GetMessage or use PeekMessage.
But WM_PAINT is only sent if you Dispatch it. Also there is no new WM_PAINT message until a window is invalidated again.
So it depends on you if you dispatch a WM_PAINT message or not. But be aware, there are other chances of reentrances like a WM_TIMER message.
The details about this are in the docs for WM_PAINT.
From my point of view the best solution would be to set you application in a "wait" mode, that even can handle WM_PAINT in this undefined waiting state. You know when you are reentered. It is always after a WM_PAINT... or similar messages that arrive like other input messages. So I don't see any problems here. An STA has one thread and you always process messages to an end, until you execute GetMessage, launch a modal dialog or show a MessageBox. When you are inside some message handling, nothing will disturb you.
Maybe an other solution would be to wait inside a second thread for this event. This thread may not have any windows and you can translate the event to anything you need in your application.
So you question may not have enough information how this deadlock really appears. So this answer may not be sufficient.
After writing als this I tend to the opinion that this is an XY problem.
I've got a relatively simple Window class. I've created a window, associated my this, etc etc. Now later, I've thrown an exception to indicate a problem. When I call MessageBox to pop up the error, the program crashes, because it's attempting to call my Window Proc. Now, I mean, admittedly, I failed SRP here and just writing a brief self-owning HWND class will solve this problem, as the window wasn't cleaned up properly. However, I'm really mystified as to why it's trying to process Window messages in my MessageBox call- the owner parameter is nullptr. Any suggestions?
Edit: If I call DestroyWindow appropriately, then now the message box just doesn't show up, although the app doesn't crash. It only works if I manually remove this from the window, so that if the proc were called it would forward to DefWindowProc, and then DestroyWindow. I mean, I thought that if you called MessageBox without an owner, then it would just work, regardless of what you had done to other windows in the system.
What is happening here is that there are still messages for the dud window in the queue when you show the message box. The message box runs a modal window message pump and dispatches the troublesome messages. Remember that all windows created from the same thread share a single message queue.
I have no idea how to fix your problem but that's what's going on.
By the way, passing a null owner isn't a great idea as it will result in your message box not being minimised when your main app is minimised, for example.
I'm programming a very big software.
It has a lot of projects inside it.
One of my projects is a UI thread. I want to post messages to this UI thread, from the main project.
When I use PostThreadMessage (after getting the thread by GetCurrentThreadId() ), everything works fine, except the times when a MessageBox is open...
So I want to send messages from the main project by PostMessage. How exactly can I send messages in that way? how do I know which window to send the message to?
Thanks
If it is an UI thread then you must have a primary window created in that thread. Just post message to this window. That's it.
EDIT 1: If it is another process, then probably you can create a hidden window with some unique title with special characters and underscores and use FindWindow API to find that window or use EnumWindows to enumerate top level windows and match the title.
Is there a way to hook for a particular windows message without subclassing the window.
There is WH_GETMESSAGE but that seems create performance issues.
Any other solutions apart from these which doesn't deteriorate performance?
AFAIK there's no better solution than what you mentioned. And, of course, subclassing the window is better than hooking all the messages of the thread.
Let's think which path the message passes up until it's handled by the window:
The message is either posted or sent to the window, either by explicit call to PostMessage/SendMessage or implicitly by the OS.
Posted messages only: eventually the thread pops this message from the message queue (by calling GetMessage or similar), and then calls DispatchMessage.
The OS invokes the window's procedure by calling CallWindowProc (or similar).
The CallWindowProc identifies the window procedore associated with the window (via GetClassLong/GetWindowLong)
The above procedure is called.
Subclassing - means replacing the window procedure for the target window. This seems to be the best variant.
Installing hook with WH_GETMESSAGE flag will monitor all the messages posted to the message queue. This is bad because of the following:
Performance reasons.
You'll get notified only for windows created in the specific thread
You'll get notified only for posted messages (sent messages will not be seen)
A "posted" message doesn't necessarily means "delivered". That is, it may be filtered by the message loop (thrown away without calling DispatchMessage).
You can't see what the actual window does and returns for that message.
So that subclassing seems much better.
One more solution - in case your specific message is posted (rather than sent) you may override the message loop, and for every retrieved message you may do some pre/post-processing
I written an exception handler routine that helps us catch problems with our software. I use
SetUnhandledExceptionFilter();
to catch any uncaught exceptions, and it works very well.
However my handler pop's up a dialog asking the user to detail what they were doing at the time of the crash. This is where the problem comes, because the dialog is in the same thread context as the crash, the dialog continues to pump the messages of application. This causes me a problem, as one of our crashes is in a WM_TIMER, which goes off every minute. As you can imagine if the dialog has been on the screen for over a minute, a WM_TIMER is dispatched and the app re-crashes. Re-entering the exception handler under this situation is bad news.
If I let Windows handle the crash, Windows displays a dialog that appears to function, but stops the messages propagating to the rest of the application, hence the WM_TIMER does not get re-issued.
Does anyone know how I can achieve the same effect?
Thanks
Rich
Perhaps you could launch a separate data collection process using CreateProcess() when you detect an unhandled exception. This separate process would prompt the user to enter information about what they were just doing, while your main application can continue to crash and terminate.
Alternatively, if you don't want to start another process, you could perhaps create another thread with a separate message queue, that blocks your main thread from doing anything at all while the dialog is on the screen. While your main thread is blocked it won't have the opportunity to handle WM_TIMER messages.
Show the dialog in a second thread.
I had more or less the same problem (but had to show a message box rather than a dialog).
Write a class in which you create two events using the Win32 CreateEvent function. One event (trigger) is used to trigger the dialog, one event (ready) is to signal that the dialog was handled.
Add a method 'execute' to the class and start this method in a second thread
Let the 'execute' method wait until the trigger event is set, and if it is set show the dialog
After the dialog has been handled, set the 'ready' event.
If your application crashes in the main thread, prepare some information for the dialog (via setters in the class) and set the 'trigger' event, then wait for the 'ready' event. The set'ting of the trigger event will activate the second thread, and the main thread will block until the second thread has set the 'ready' event