riqitang
riqitang

Reputation: 3371

SendMessage - strange return values

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.

Upvotes: 0

Views: 2561

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595622

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.

Upvotes: 2

Related Questions