From: Kevin Puetz PuetzKevinA@JohnDeere.com
All cases, not just COWAIT_ALTERTABLE (APCs) should check for success before blocking in MsgWaitForMultipleObjectsEx. Using COWAIT_WAITALL in an STA has the same well-known drawback as MWMO_WAITALL; the queue status then counts as part of the "all handles" return.
But this test shows that that should apply only if there is a need to wait for messages at all - if all the specified handles are signaled, CoWaitForMultipleHandles shouldn't check messages at all. --- dlls/combase/combase.c | 7 ++----- dlls/ole32/tests/compobj.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index fc8414b52d3..42e9fbc2468 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -2074,7 +2074,7 @@ static BOOL com_peek_message(struct apartment *apt, MSG *msg) HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle_count, HANDLE *handles, DWORD *index) { - BOOL check_apc = !!(flags & COWAIT_ALERTABLE), post_quit = FALSE, message_loop; + BOOL post_quit = FALSE, message_loop; struct apartment *apt; UINT exit_code; DWORD res; @@ -2122,10 +2122,7 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle
TRACE("waiting for rpc completion or window message\n");
- if (check_apc) - { - res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, TRUE); - } + res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, !!(flags & COWAIT_ALERTABLE));
if (res == WAIT_TIMEOUT) res = MsgWaitForMultipleObjectsEx(handle_count, handles, diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 66680ba5952..1e011e1354b 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -3011,6 +3011,21 @@ static void test_CoWaitForMultipleHandles(void) success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE); ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
+ ReleaseSemaphore(handles[0], 1, NULL); + + /* COWAIT_ALL will get time out even if the handles became signaled while it waits + * in MsgWaitForMultipleObjects(...,MWIO_WAITALL), as it demands a posted message too */ + index = 0xdeadbeef; + thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid); + hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 500, 2, handles, &index); + ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08lx\n", hr); + + /* but will succeed immediately if the handles are already available + * i.e. it checks the handles first before calling MsgWaitForMultipleObjects */ + hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 0, 2, handles, &index); + ok(hr == S_OK, "expected S_OK, got 0x%08lx\n", hr); + ok(index == 0, "expected index 0, got %lu\n", index); + ReleaseSemaphore(handles[0], 1, NULL); ReleaseSemaphore(handles[1], 1, NULL);