MsgWaitForMultipleObjectsEx functions allow you to specify whether you want to want for any or all of the handles (either by passing
bWaitAll = TRUE or by passing
dwFlags = MWMO_WAITALL, accordingly). But you never want to wait for all handles.
Waiting for all handles means that the call does not return unless all the handles are signalled and a window message meeting your wake criteria has arrived. Since you are typically waiting for messages out of a sense of obligation (keeping the UI thread responsive) rather than one of expectation, even if all the handles you pass become signalled, your program will still stall until a window message arrives. (And if you thought you were being a good UI citizen by using
MsgWaitForMultipleObjectsEx, you aren't actually helping any because waiting for all objects means that the call will not return even if a message is ready, since it's also waiting for those handles you passed.) Functions which are built on top of the
MsgWaitForMultipleObjectsEx function such as
CoWaitForMultipleHandles suffer from the same problem.
The reason for this can be gleaned from the
MsgWaitForMultipleObjectsEx documentation; you just have to put on your thinking cap. Notice that if a message arrives when you are waiting for any handle, the return value is
WAIT_OBJECT_0 + cHandles
MAXIMUM_WAIT_OBJECTS - 1
MsgWaitForMultipleObjectsEx function creates a handle that will be signalled when the message queue reaches one of the states you requested in the wake mask, adds that handle to the end of the array you passed in, and then passes the whole thing to the
WaitForMultipleObjectsEx function. (Note that the getting access to that internal handle won't be of any use to you, the application, since you don't know how to tell the window manager what wait states should result in the event being set.)
(Larry Osterman reminded me that he covered the same topic a while back. So now you get to see it twice.)