From: Rémi Bernon rbernon@codeweavers.com
The functions take a WAIT_TYPE argument instead of a BOOLEAN.
This causes test failures in kernel32:sync when compiled with clang and optimizations enabled, as it optimizes away clearing the higher bytes of the register used for the WAIT_TYPE argument, leaving set bits in the higher bytes ending up with an invalid WAIT_TYPE value. --- dlls/kernel32/tests/sync.c | 18 +++++++++--------- dlls/kernelbase/sync.c | 2 +- dlls/ntdll/signal_arm64ec.c | 2 +- dlls/ntdll/threadpool.c | 4 ++-- dlls/ntdll/unix/env.c | 2 +- dlls/ntdll/unix/sync.c | 29 +++++++++++++++-------------- dlls/win32u/message.c | 3 ++- dlls/wow64/sync.c | 4 ++-- include/ddk/wdm.h | 2 +- include/winternl.h | 2 +- 10 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 7ccc91e0a38..faaaa381623 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -61,7 +61,7 @@ static DWORD (WINAPI *pQueueUserAPC2)(PAPCFUNC,HANDLE,ULONG_PTR,QUEUE_USER_APC_F static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); -static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); +static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,WAIT_TYPE,BOOLEAN,const LARGE_INTEGER*); static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, PSLIST_ENTRY last, ULONG count); static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first, @@ -1408,15 +1408,15 @@ static void test_WaitForMultipleObjects(void) SetEvent(maxevents[i]);
/* a manual-reset event remains signaled, an auto-reset event is cleared */ - status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAny, FALSE, NULL); ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08lx\n", status); - status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAny, FALSE, NULL); ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08lx\n", status); ok(ResetEvent(maxevents[0]), "ResetEvent\n"); for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) { /* the lowest index is checked first and remaining events are untouched */ - status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAny, FALSE, NULL); ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08lx\n", i, status); }
@@ -1441,12 +1441,12 @@ static void test_WaitForMultipleObjects(void)
timeout.QuadPart = -1000000; maxevents[0] = GetCurrentProcess(); - status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); + status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
timeout.QuadPart = -1000000; maxevents[0] = GetCurrentThread(); - status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); + status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); }
@@ -2626,15 +2626,15 @@ static DWORD WINAPI alertable_wait_thread(void *param)
ReleaseSemaphore(semaphores[0], 1, NULL); timeout.QuadPart = -10000000; - status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); + status = pNtWaitForMultipleObjects(1, &semaphores[1], WaitAll, TRUE, &timeout); ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status); timeout.QuadPart = -2000000; - status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); + status = pNtWaitForMultipleObjects(1, &semaphores[1], WaitAll, TRUE, &timeout); ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08lx\n", status);
ReleaseSemaphore(semaphores[0], 1, NULL); timeout.QuadPart = -10000000; - status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); + status = pNtWaitForMultipleObjects(1, &semaphores[1], WaitAll, TRUE, &timeout); ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status); result = WaitForSingleObject(semaphores[0], 0); ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", result); diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index 6c69a0ab88f..36e29a3cab0 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -436,7 +436,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH WaitForMultipleObjectsEx( DWORD count, const HAND } for (i = 0; i < count; i++) hloc[i] = normalize_std_handle( handles[i] );
- status = NtWaitForMultipleObjects( count, hloc, !wait_all, alertable, + status = NtWaitForMultipleObjects( count, hloc, wait_all ? WaitAll : WaitAny, alertable, get_nt_timeout( &time, timeout ) ); if (HIWORD(status)) /* is it an error code? */ { diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 9cbc6b48a2b..45387d86f11 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -588,7 +588,7 @@ DEFINE_WRAPPED_SYSCALL(NtUnmapViewOfSectionEx, (HANDLE process, PVOID addr, ULON DEFINE_SYSCALL(NtWaitForAlertByThreadId, (const void *address, const LARGE_INTEGER *timeout)) DEFINE_SYSCALL(NtWaitForDebugEvent, (HANDLE handle, BOOLEAN alertable, LARGE_INTEGER *timeout, DBGUI_WAIT_STATE_CHANGE *state)) DEFINE_SYSCALL(NtWaitForKeyedEvent, (HANDLE handle, const void *key, BOOLEAN alertable, const LARGE_INTEGER *timeout)) -DEFINE_SYSCALL(NtWaitForMultipleObjects, (DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout)) +DEFINE_SYSCALL(NtWaitForMultipleObjects, (DWORD count, const HANDLE *handles, WAIT_TYPE type, BOOLEAN alertable, const LARGE_INTEGER *timeout)) DEFINE_SYSCALL(NtWaitForMultipleObjects32, (ULONG count, LONG *handles, WAIT_TYPE type, BOOLEAN alertable, const LARGE_INTEGER *timeout)) DEFINE_SYSCALL(NtWaitForSingleObject, (HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout)) DEFINE_SYSCALL(NtWorkerFactoryWorkerReady, (HANDLE handle)) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 5fb11c35698..4f707bdd782 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -1313,7 +1313,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) assert( num_handles == 0 ); RtlLeaveCriticalSection( &waitqueue.cs ); timeout.QuadPart = (ULONGLONG)THREADPOOL_WORKER_TIMEOUT * -10000; - status = NtWaitForMultipleObjects( 1, &bucket->update_event, TRUE, bucket->alertable, &timeout ); + status = NtWaitForMultipleObjects( 1, &bucket->update_event, WaitAny, bucket->alertable, &timeout ); RtlEnterCriticalSection( &waitqueue.cs );
if (status == STATUS_TIMEOUT && !bucket->objcount) @@ -1323,7 +1323,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) { handles[num_handles] = bucket->update_event; RtlLeaveCriticalSection( &waitqueue.cs ); - status = NtWaitForMultipleObjects( num_handles + 1, handles, TRUE, bucket->alertable, &timeout ); + status = NtWaitForMultipleObjects( num_handles + 1, handles, WaitAny, bucket->alertable, &timeout ); RtlEnterCriticalSection( &waitqueue.cs );
if (status >= STATUS_WAIT_0 && status < STATUS_WAIT_0 + num_handles) diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index 314a024cbb7..93902136ace 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -1658,7 +1658,7 @@ static void run_wineboot( WCHAR *env, SIZE_T size )
wait: timeout.QuadPart = (ULONGLONG)5 * 60 * 1000 * -10000; - if (NtWaitForMultipleObjects( count, handles, TRUE, FALSE, &timeout ) == WAIT_TIMEOUT) + if (NtWaitForMultipleObjects( count, handles, WaitAny, FALSE, &timeout ) == WAIT_TIMEOUT) ERR( "boot event wait timed out\n" ); while (count) NtClose( handles[--count] ); } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index e67bc4d3f1e..747069f3b4d 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -397,8 +397,8 @@ static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) return STATUS_SUCCESS; }
-static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, - BOOLEAN wait_any, int alert_fd, const LARGE_INTEGER *timeout ) +static NTSTATUS linux_wait_objs( int device, DWORD count, const int *objs, WAIT_TYPE type, + int alert_fd, const LARGE_INTEGER *timeout ) { struct ntsync_wait_args args = {0}; unsigned long request; @@ -426,7 +426,7 @@ static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, args.index = ~0u; args.alert = alert_fd;
- if (wait_any || count == 1) request = NTSYNC_IOC_WAIT_ANY; + if (type != WaitAll || count == 1) request = NTSYNC_IOC_WAIT_ANY; else request = NTSYNC_IOC_WAIT_ALL;
do { ret = ioctl( device, request, &args ); } @@ -443,9 +443,9 @@ static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, return ret; }
- return wait_any ? args.index : 0; + return type != WaitAll ? args.index : 0; } - if (errno == EOWNERDEAD) return STATUS_ABANDONED + (wait_any ? args.index : 0); + if (errno == EOWNERDEAD) return STATUS_ABANDONED + (type != WaitAll ? args.index : 0); if (errno == ETIMEDOUT) return STATUS_TIMEOUT; return errno_to_status( errno ); } @@ -492,8 +492,8 @@ static NTSTATUS linux_query_mutex_obj( int obj, MUTANT_BASIC_INFORMATION *info ) return STATUS_NOT_IMPLEMENTED; }
-static NTSTATUS linux_wait_objs( int device, const DWORD count, const int *objs, - BOOLEAN wait_any, int alert_fd, const LARGE_INTEGER *timeout ) +static NTSTATUS linux_wait_objs( int device, DWORD count, const int *objs, WAIT_TYPE type, + int alert_fd, const LARGE_INTEGER *timeout ) { return STATUS_NOT_IMPLEMENTED; } @@ -886,7 +886,7 @@ static int get_inproc_alert_fd(void) return fd; }
-static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, +static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, WAIT_TYPE type, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { struct inproc_sync *syncs[64], stack[ARRAY_SIZE(syncs)]; @@ -907,7 +907,7 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an }
if (alertable) alert_fd = get_inproc_alert_fd(); - ret = linux_wait_objs( inproc_device_fd, count, objs, wait_any, alert_fd, timeout ); + ret = linux_wait_objs( inproc_device_fd, count, objs, type, alert_fd, timeout );
while (count--) release_inproc_sync( syncs[count] ); return ret; @@ -938,7 +938,7 @@ static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, if (!ret) { if (alertable) alert_fd = get_inproc_alert_fd(); - ret = linux_wait_objs( inproc_device_fd, 1, &wait_sync->fd, TRUE, alert_fd, timeout ); + ret = linux_wait_objs( inproc_device_fd, 1, &wait_sync->fd, WaitAny, alert_fd, timeout ); }
release_inproc_sync( wait_sync ); @@ -2290,7 +2290,7 @@ NTSTATUS WINAPI NtQueryTimer( HANDLE handle, TIMER_INFORMATION_CLASS class, /****************************************************************** * NtWaitForMultipleObjects (NTDLL.@) */ -NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, +NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, WAIT_TYPE type, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { union select_op select_op; @@ -2298,22 +2298,23 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO unsigned int ret;
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1; + if (type != WaitAll && type != WaitAny) FIXME( "Unsupported wait type %u\n", type );
if (TRACE_ON(sync)) { - TRACE( "wait_any %u, alertable %u, handles {%p", wait_any, alertable, handles[0] ); + TRACE( "type %u, alertable %u, handles {%p", type, alertable, handles[0] ); for (i = 1; i < count; i++) TRACE( ", %p", handles[i] ); TRACE( "}, timeout %s\n", debugstr_timeout(timeout) ); }
- if ((ret = inproc_wait( count, handles, wait_any, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) + if ((ret = inproc_wait( count, handles, type, alertable, timeout )) != STATUS_NOT_IMPLEMENTED) { TRACE( "-> %#x\n", ret ); return ret; }
if (alertable) flags |= SELECT_ALERTABLE; - select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL; + select_op.wait.op = type == WaitAll ? SELECT_WAIT_ALL : SELECT_WAIT; for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] ); ret = server_wait( &select_op, offsetof( union select_op, wait.handles[count] ), flags, timeout ); TRACE( "-> %#x\n", ret ); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e8bbe229141..a88580cc29c 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3291,6 +3291,7 @@ static inline LARGE_INTEGER *get_nt_timeout( LARGE_INTEGER *time, DWORD timeout static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DWORD wake_mask, DWORD changed_mask, DWORD flags ) { struct thunk_lock_params params = {.dispatch.callback = thunk_lock_callback}; + WAIT_TYPE type = flags & MWMO_WAITALL ? WaitAll : WaitAny; LARGE_INTEGER time, now, *abs; void *ret_ptr; ULONG ret_len; @@ -3310,7 +3311,7 @@ static DWORD wait_message( DWORD count, const HANDLE *handles, DWORD timeout, DW }
process_driver_events( QS_ALLINPUT, wake_mask, changed_mask ); - do ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), abs ); + do ret = NtWaitForMultipleObjects( count, handles, type, !!(flags & MWMO_ALERTABLE), abs ); while (ret == count - 1 && !process_driver_events( QS_ALLINPUT, wake_mask, changed_mask )); if (HIWORD(ret)) /* is it an error code? */ { diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index f7464934e85..756f5962837 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1788,7 +1788,7 @@ NTSTATUS WINAPI wow64_NtWaitForMultipleObjects( UINT *args ) { DWORD count = get_ulong( &args ); LONG *handles_ptr = get_ptr( &args ); - BOOLEAN wait_any = get_ulong( &args ); + WAIT_TYPE type = get_ulong( &args ); BOOLEAN alertable = get_ulong( &args ); const LARGE_INTEGER *timeout = get_ptr( &args );
@@ -1796,7 +1796,7 @@ NTSTATUS WINAPI wow64_NtWaitForMultipleObjects( UINT *args ) DWORD i;
for (i = 0; i < count && i < MAXIMUM_WAIT_OBJECTS; i++) handles[i] = LongToHandle( handles_ptr[i] ); - return NtWaitForMultipleObjects( count, handles, wait_any, alertable, timeout ); + return NtWaitForMultipleObjects( count, handles, type, alertable, timeout ); }
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index fcaf7b4a462..9bbba22d2fe 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -2014,7 +2014,7 @@ NTSTATUS WINAPI ZwUnloadDriver(const UNICODE_STRING *); NTSTATUS WINAPI ZwUnloadKey(HANDLE); NTSTATUS WINAPI ZwUnmapViewOfSection(HANDLE,PVOID); NTSTATUS WINAPI ZwWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*); -NTSTATUS WINAPI ZwWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); +NTSTATUS WINAPI ZwWaitForMultipleObjects(ULONG,const HANDLE*,WAIT_TYPE,BOOLEAN,const LARGE_INTEGER*); NTSTATUS WINAPI ZwWriteFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,const void*,ULONG,PLARGE_INTEGER,PULONG); NTSTATUS WINAPI ZwYieldExecution(void);
diff --git a/include/winternl.h b/include/winternl.h index 36c24b01e56..2c985465096 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4774,7 +4774,7 @@ NTSYSAPI NTSTATUS WINAPI NtWaitForAlertByThreadId(const void*,const LARGE_INTEG NTSYSAPI NTSTATUS WINAPI NtWaitForDebugEvent(HANDLE,BOOLEAN,LARGE_INTEGER*,DBGUI_WAIT_STATE_CHANGE*); NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE,const void*,BOOLEAN,const LARGE_INTEGER*); NTSYSAPI NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,const LARGE_INTEGER*); -NTSYSAPI NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); +NTSYSAPI NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,WAIT_TYPE,BOOLEAN,const LARGE_INTEGER*); NTSYSAPI NTSTATUS WINAPI NtWaitHighEventPair(HANDLE); NTSYSAPI NTSTATUS WINAPI NtWaitLowEventPair(HANDLE); NTSYSAPI NTSTATUS WINAPI NtWriteFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,const void*,ULONG,PLARGE_INTEGER,PULONG);