SendMessage - strange return values - winapi

I have an application which uses a three helper threads to read from a database (3 different tables, ~160,000 rows in total), create objects from those rows, then add the objects to one of two lists, depending on what type of object was created. The helper threads add objects to the list through a SendMessage call so that the main thread is the only object adding/removing to/from the list.
The odd thing is that SendMessage doesn't always succeed, I'll frequently get these two errors ERROR_ALREADY_EXISTS (183) and ERROR_TRUSTED_DOMAIN_FAILURE (1788). The function that SendMessage calls just adds an object to the list, and this function always returns success (0). There's no creating files (as ERROR_ALREADY_EXISTS seems to suggest) and there's no network calls so I'm not sure why I'm getting ERROR_TRUSTED_DOMAIN_FAILURE errors.
Any ideas on what might be causing these errors or any way to debug these errors?
As a note, before it was SendMessage I was using PostMessage and would get lots of ERROR_NOT_ENOUGH_QUOTA errors; SendMessage makes the utility work a lot better.

SendMessage() returns the result of the message that is sent. It is up to the message handler to decide what value is actually returned by SendMessage() to the sending code. GetLastError() is only meaningful if SendMessage() itself fails, and you have to use SetLastError() to detect that, eg:
SetLastError(0);
LRESULT res = SendMessage(...);
if ((res == 0) && (GetLastError() != 0))
{
// send failed, for example GetLastError()=ERROR_ACCESS_DENIED if UIPI blocked the message ...
}
else
{
// send succeeded, res is whatever value the message handler returned ...
}
This only works reliably if the target HWND is owned by a different thread than the one that is calling SendMessage(). GetLastError() cannot be influenced across thread boundaries. Any call to SetLastError() within the message handler affects the error code of the HWND's owning thread, not the error code of the sending thread.
However, if the target HWND is owned by the same thread that is calling SendMessage(), and the message handler happens to call SetLastError() (directly, or indirectly via a failed API call) to set a non-zero error code, and happens to return 0 as its result value for SendMessage() to return to the sender, then the only way I can think of for the sender to differentiate whether the error code returned by GetLastError() was set by SendMessage() itself on failure, or set by the message handler, is to use a thread-locale message hook via SetWindowsHookEx() to detect whether the message handler was actually called or not (the only condition I can think of for that happening is if the target HWND is invalid so SendMessage() cannot find its window procedure).
You can use GetWindowThreadProcessId() and GetCurrentThreadId() to check if the target HWND is owned by the calling thread or not.

Related

Stop WndProc processing during shutdown of the app

I have defined a WndProc which looks similar to below (the code is written in C++Builder, but it applies in similar form to Delphi as well):
#define WM_SETTINGS_UPDATE WM_APP + 1234
#define WM_GUI_UPDATE WM_APP + 1235
void __fastcall TForm1::WndProc(TMessage &fMessage)
{
switch (fMessage.Msg)
{
default: break;
case WM_SETTINGS_UPDATE: ProcessMySettingsUpdate();
fMessage.Result = 1;
return;
break; // I know this is not needed, I do this purely for aesthetics
case WM_GUI_UPDATE: ProcessMyGUIUpdate();
fMessage.Result = 1;
return;
break; // I know this is not needed, I do this purely for aesthetics
}
TForm::WndProc(fMessage);
}
So in essence this:
checks for my custom WM_APP range messages (WM_SETTINGS_UPDATE and WM_GUI_UPDATE) in this case.
processes those messages and then sets fMessage.Result to 1 indicating message was processed and returns (avoiding TForm:WndProc(fMessage), which I understand is the same as inherited in Delphi, and not needed if the message is processed).
if my messages are not processed, it just calls TForm:WndProc(fMessage) (or inherited) to do the default processing.
My concern is this - what if there is a situation where the application is shutting down, and there are still some messages being unprocessed (left in the message queue by PostMessage())?
What I'd like to do in such a situation is to avoid calling my own processing, as it might result in some uninitialized memory Access Violations or similar. Is this basically enough, or do I need to apply some special processing to avoid that kind of situation, or process some "application shutting down" code?
And also - do I need to call inherited / TForm:WndProc(fMessage) after I am done with my processing, or is it safe to do it like above (set Result to 1 and return)?
Note - this does not necessarily apply to the MainForm (the first Form being created).
what if there is a situation where the application is shutting down, and there are still some messages being unprocessed (left in the message queue by PostMessage())?
That is perfectly OK. Once a Form's HWND is destroyed, any remaining messages that were posted for that window will simply be discarded when dispatched by the main message loop. Your WndProc will not be called for them.
What I'd like to do in such a situation is to avoid calling my own processing, as it might result in some uninitialized memory Access Violations or similar.
That should not be a concern. One, because messages won't be dispatched to your Form's HWND after it is destroyed, and two, when the MainForm is closed, the main message loop is signaled to stop running, before any active Form HWNDs are destroyed. So, there won't be any further message dispatching anyway.
Is this basically enough, or do I need to apply some special processing to avoid that kind of situation
It should be enough. You typically do not need to handle this special (unless your custom messages are carrying pointers to objects that have to be freed).
or process some "application shutting down" code?
If you really want to detect when the app is being shut down, try having your WndProc handle the WM_CLOSE message (or you can use the Form's OnClose/Query events).
do I need to call inherited / TForm:WndProc(fMessage) after I am done with my processing, or is it safe to do it like above (set Result to 1 and return)?
That is perfectly OK for custom messages.

How can you tell if SendMessage() was successful (message was delivered)?

is it possible to determine if a SendMessage() call was successful and delivered my message to the target window?
The SendMessage() description in the Windows API seems quiet on this and only says the following:
The return value specifies the result of the message processing; it depends on the message sent.
This obviously refers to the fact that the return code reflects the value returned by the wndproc of the target window.
But what will the return code be if the message wasn't delivered at all (e.g. due to access control, or due to the window having been destoroyed in the meantime)? How can I detect such situations?
There is no way to reliably tell, whether a call to SendMessage succeeded or failed. After all, it only has a single return value, and the entire range of values is used. There is no designated error value.
Playing tricks with the calling thread's last error code won't work either. The scheme proposed in this answer (clearing the last error code prior to the call and evaluating it after the call) is brittle. It's easy to see that it can fail, when sending a message to a window owned by the calling thread (as that window's window procedure is at liberty to change the last error any way it sees fit).
It's not quite as well known, that this can also fail when sending a message to a window owned by a different thread. The code suggests, that no intervening API call can happen in the calling thread. Yet in that scenario, SendMessage will also dispatch incoming cross-thread messages (see When can a thread receive window messages?), allowing the thread's last error code to change.
The only option then is to use SendMessageTimeoutW, as that API reports both the result of the call, as well as an error/success indicator. Passing the SMTO_NOTIMEOUTIFNOTHUNG flag makes sure that an arbitrarily chosen timeout will not adversely affect the outcome.
if SendMessage fail, it set last win32 error code, which we can get back via call GetLastError(). and returned error code, in case fail, never will be 0 (NOERROR) despite this is clear not documented. but how detect that SendMessage is fail ? here we can not base on return value. but we can SetLastError(NOERROR) before call SendMessage and check GetLastError() after:
if SendMessage fail - value returned by GetLastError() will be
not 0. (most common in this case ERROR_INVALID_WINDOW_HANDLE or
ERROR_ACCESS_DENIED).
if we still got 0 as last error - this mean that message was
delivered with no error.
however, possible case, when during SendMessage call, some window procedure
in current thread will be called and
code inside window procedure, set last error to non 0 value. so we
get finally not 0 last error, but not because SendMessage fail.
distinguish between these two cases very problematic
-
SetLastError(NOERROR);
LRESULT lr = SendMessageW(hwnd, *, *, *);
ULONG dwErrorCode = GetLastError();
if (dwErrorCode == NOERROR)
{
DbgPrint("message was delivered (%p)\n", lr);
}
else
{
DbgPrint("fail with %u error\n", dwErrorCode);
}

Why are "TranslateMessage" and "DispatchMessage" separate calls?

Most of the Win32 main loops I've seen are all structured like:
while (GetMessage(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
}
It was pointed out to me that MsgWaitForMultipleObjects may be used to add some variety to a main loop. But is there a scenario where doing something between GetMessage, TranslateMessage and DispatchMessage is actually useful?
The more traditional message loop looks like this:
while (GetMessage(&msg, 0, 0, 0))
{
if (!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
It is a pretty big hint to what you'd want to do before dispatching the message: catch messages that ought to be intercepted and treated specially before the window sees them. Keyboard shortcuts are a classic example, they need to be detected no matter what window has the focus.
Any GUI class library exposes it with a virtual method named something like App.PreProcessMessage, a virtual function that can be overridden so your program can implement its own shortcuts and whatnot.
They are different beasts.
For TranslateMessage function
Translates virtual-key messages into
character messages. The character
messages are posted to the calling
thread's message queue, to be read the
next time the thread calls the
GetMessage or PeekMessage function.
[...]
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
DispatchMessage, on the other hand, dispatches a message to a window procedure.
So DispatchMessage does the actual work of processing the message. TranslateMessage MAY or MAY NOT post a new message to the thread queue. If the message is translated then a character message is posted to the thread's message queue.
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
They are separate calls so you, the programmer, can have a chance to avoid the message translation provided by TranslateMessage.
Well to quote an example from the MSDN:
You can modify a message loop in a variety of ways. For example, you can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages not specifying a window. You can also direct GetMessage to search for specific messages, leaving other messages in the queue. This is useful if you must temporarily bypass the usual FIFO order of the message queue.
You can also possibly avoid calls to Translate message if you don't need to convert keyboard input control codes.
TranslateMessage() converts virtual keys messages to character input messages.
It is a separate call for the remote chance that under certain circumstances you would want to not produce character input messages for certain virtual keys.

Best way to close and wait for a child frame window using Win32/MFC

There are a few options here, probably, but what would you suggest to be the safest way to accomplish the following:
I've got a child CFrameWnd with a parent = NULL (so that it can live a separate life from the main application, while the app is running, at least). I've got all those windows stored in a list. When the main app is closing (MainFrame getting an OnClose), I go through the array and issue a PostMessage(WM_CLOSE) to all. However, the problem is that each of them has to do stuff before closing down. So, I need to wait for them. But we're all on the same thread... So, how can I wait for the children to close, without blocking their own processing in a single-threaded application?
Or should I launch a worker thread to take care of that? Would it be easier?
Thanks in advance!
Use SendMessage() instead of PostMessage().
Edit: Another option might be to simply handle WM_DESTROY in your child windows (depending on your code of course).
Well you certainly can't just wait for them to close, you need to at least pump messages so that they would receive and handle the WM_CLOSE. How you do that is up to you I guess. But I see you are doing PostMessage. Why not do SendMessage instead - this will run the close synchronously in the window procedure for the window. Or are you trying to quit the app? Then you should really use PostQuitMessage then pump messages in the normal fashion until GetMessage returns 0. Lots of options.
Pumping messages means to have a loop in your code that looks like this. You don't have to call AfxPumpMessages, but that would probably do something similar. There are in fact many different ways to pump messages depending on what you want to do. In addition there are quite a few functions that pump messages for you.
BOOL bRet;
// note that GetMessage returns 0 when WM_QUIT is received - this is how PostQuitMessage
// would work to get us to shut down
// We are passing NULL for the hWnd parameter - this means receive all window and
// thread messages for this thread
while( (bRet = GetMessage( &msg, NULL /* hWnd */, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
If you post the message to a window or windows, then you need to pump messages. What happens is that the message goes into a queue for the thread associated with that window (this thread) - the message pump extracts them out and dispatches them off to the correct window procedure.
If you had sent the message instead of posting it, then the window procedure for the window is called directly - rather than going into a queue. You wouldn't need to pump messages because once SendMessage returns the message is fully handled.
The way PostQuitMessage works is by setting a flag on the message queue indicating that the application should quit. The WM_QUIT message isn't really a window message that you would send - what happens is that GetMessage will check this flag after all the other posted window messages are processed and returns 0 if it is set. This will cause all windows to correctly close, and you don't need to send it to the windows themselves.

How can I update a win32 app gui while it is waiting for another program to finish?

I am currently using CreateProcess/WaitForSingleObject from within a win32 GUI app to launch a small GUI app that deals with software licensing issues. This all works fine, but it essentially hangs the "parent" app while it waits for the licensing app to finish its work. During this time, updates to the parent app do not occur and it ends up with ugly white squares if the utility app window is moved.
Also, for some strange reason, while the utility app is running, if I copy something from within that app to the clipboard, it HANGS. I haven't figured out why yet, but it only happens if I am waiting for the app to finish from within the parent app.
So I'm thinking that if I can cause the parent app to handle its events while waiting for my other app to finish, it might solve both problems.
So, is there a replacement for CreateProcess/WaitForSingleObject that also handles UI updates?
Your parent process appears to hang because the WaitForSingleObject() call blocks your thread until the handle you pass into the call is signaled.
Your child process likely hangs during the copy-to-clipboard operation because it is, as a part of that operation, sending a message either specifically to the parent process's window or to all top-level windows. The message loop in your parent process's thread is not running, because it is blocked waiting until the child process exits, so the message is never processed and the child process remains blocked.
Instead of calling WaitForSingleObject(), you can call MsgWaitForMultipleObjects(). If you specifiy QS_ALLINPUT for the dwWaitMask parameter, MsgWaitForMultipleObjects will return either when your event is signaled or when there is input in the thread's message queue. If MsgWaitForMultipleObjects() returned because a message is available, you can process it and resume waiting:
MSG msg;
DWORD reason = WAIT_TIMEOUT;
while (WAIT_OBJECT_0 != reason) {
reason = MsgWaitForMultipleObjects(1, &hChildProcess, FALSE, INFINITE, QS_ALLINPUT);
switch (reason) {
case WAIT_OBJECT_0:
// Your child process is finished.
break;
case (WAIT_OBJECT_0 + 1):
// A message is available in the message queue.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
// Note that if your main message loop does additional processing
// (such as calling IsDialogMessage() for modeless dialogs)
// you will want to do those things here, too.
}
break;
}
}
You could put the WaitForSingleObject call in a loop and use a relatively small value for the dwMilliseconds parameter.
The condition to exit the loop is when the WaitForSingleObject call returns WAIT_OBJECT_0.
In the loop you have to examine the message queue to see if there are any that you must process. How you handle this is really up to you an it depends on your typical needs.
// Assuming hYourWaitHandle is the handle that you're waiting on
// and hwnd is your window's handle, msg is a MSG variable and
// result is a DWORD variable
//
// Give the process 33 ms (you can use a different value here depending on
// how responsive you wish your app to be)
while((result = WaitForSingleObject(hYourWaitHAndle, 33)) == WAIT_TIMEOUT)
{
// if after 33 ms the object's handle is not signaled..
// we examine the message queue and if ther eare any waiting..
// Note: see PeekMessage documentation for details on how to limit
// the types of messages to look for
while(PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE))
{
// we process them..
if(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
// if you're here it means WaitForSingleObject returned WAIT_OBJECT_0, so you're done
// (but you should always check and make sure it really is WAIT_OBJECT_0)
if(result != WAIT_OBJECT_0)
{
// This should not be.. so react!
}
I suggest you can handle this as follows:
Parent application does CreateProcess, and then returns immediately instead of waiting for a response or for the utility app to finish
Because the parent applicatin has returned, it can handle other Window messages (e.g. WM_PAINT)
When the utility app finishes, it notifies the parent application (e.g. using PostMessage and RegisterWindowMessage APIs)
Parent application handles positive notification received via PostMessage
Parent application may also have a Windows timer (WM_TIMER) running, so that it knows if the utility app is killed before it send its notification
You can get a hanging problem if the app you are spawning causes a sendmessage broadcast, either explicit or implicit. This is clipped from my website:
The problem arises because your application has a window but isn't pumping messages. If the spawned application invokes SendMessage with one of the broadcast targets (HWND_BROADCAST or HWND_TOPMOST), then the SendMessage won't return to the new application until all applications have handled the message - but your app can't handle the message because it isn't pumping messages.... so the new app locks up, so your wait never succeeds.... DEADLOCK.
I don't do clipboard code, but if that causes the situation above (believeable), then you'll deadlock. You can:
put the launch of the secondary application into a little thread
use a timeout and spin around a PeekMessage loop (yuck)
use the MsgWaitForMultipleObjects API.
No preference is implied by that ordering... I'm assuming you don't create the spawned application yourself, in which case you could use IPC to get around this issue, as ChrisW suggested.
You should create a thread that does only the following:
call CreateProcess() to run the other app
call WaitForSingleObject() to wait for the process to finish - since this is a background thread your app will not block
call CloseHandle() on the process handle
call PostMessage() with a notification message for your main thread
Now you only need to make sure that your main application has its GUI disabled to prevent reentrancy problems, possible by showing a modal dialog that informs the user that the other app is running and needs to be dealt with first. Make sure that the dialog can not be closed manually, and that it closes itself when it receives the posted notification message from the background thread. You can put the whole thread creation into this dialog as well, and wrap everything in a single function that creates, shows and destroys the dialog and returns the result your external application produces.

Resources