[PATCH 1/2] ntdll/tests: Move some tests to a new sync.c file.

Zebediah Figura zfigura at codeweavers.com
Tue Oct 26 21:43:02 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ntdll/tests/Makefile.in |   1 +
 dlls/ntdll/tests/om.c        | 574 -------------------------------
 dlls/ntdll/tests/sync.c      | 630 +++++++++++++++++++++++++++++++++++
 3 files changed, 631 insertions(+), 574 deletions(-)
 create mode 100644 dlls/ntdll/tests/sync.c

diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in
index 7ad39e0992c..8c6a86fb965 100644
--- a/dlls/ntdll/tests/Makefile.in
+++ b/dlls/ntdll/tests/Makefile.in
@@ -21,6 +21,7 @@ C_SRCS = \
 	rtlbitmap.c \
 	rtlstr.c \
 	string.c \
+	sync.c \
 	threadpool.c \
 	time.c \
 	virtual.c \
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index af5e014f069..77eb58a23b5 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -30,10 +30,6 @@
 static VOID     (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
 static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN);
 static NTSTATUS (WINAPI *pNtOpenEvent)   ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES);
-static NTSTATUS (WINAPI *pNtPulseEvent)  ( HANDLE, PLONG );
-static NTSTATUS (WINAPI *pNtQueryEvent)  ( HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
-static NTSTATUS (WINAPI *pNtResetEvent)  ( HANDLE, LONG* );
-static NTSTATUS (WINAPI *pNtSetEvent)    ( HANDLE, LONG* );
 static NTSTATUS (WINAPI *pNtCreateJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
 static NTSTATUS (WINAPI *pNtOpenJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
 static NTSTATUS (WINAPI *pNtCreateKey)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG,
@@ -44,11 +40,8 @@ static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ACCESS_MASK, POBJECT_A
                                                  ULONG, ULONG, ULONG, PLARGE_INTEGER );
 static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
 static NTSTATUS (WINAPI *pNtOpenMutant)  ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
-static NTSTATUS (WINAPI *pNtQueryMutant) ( HANDLE, MUTANT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
-static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, PLONG );
 static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
 static NTSTATUS (WINAPI *pNtOpenSemaphore)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
-static NTSTATUS (WINAPI *pNtQuerySemaphore)( PHANDLE, SEMAPHORE_INFORMATION_CLASS, PVOID, ULONG, PULONG );
 static NTSTATUS (WINAPI *pNtCreateTimer) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, TIMER_TYPE );
 static NTSTATUS (WINAPI *pNtOpenTimer)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
 static NTSTATUS (WINAPI *pNtCreateSection)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, const PLARGE_INTEGER,
@@ -67,15 +60,9 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U
 static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG);
 static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
 static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
-static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
-static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
 static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, void *, ULONG, FILE_INFORMATION_CLASS);
-static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
-static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
-static void     (WINAPI *pRtlWakeAddressAll)( const void * );
-static void     (WINAPI *pRtlWakeAddressSingle)( const void * );
 static NTSTATUS (WINAPI *pNtOpenProcess)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID * );
 static NTSTATUS (WINAPI *pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG );
 static NTSTATUS (WINAPI *pNtGetNextThread)(HANDLE process, HANDLE thread, ACCESS_MASK access, ULONG attributes,
@@ -1939,286 +1926,6 @@ static void test_type_mismatch(void)
     pNtClose( h );
 }
 
-static void test_event(void)
-{
-    HANDLE Event;
-    HANDLE Event2;
-    LONG prev_state = 0xdeadbeef;
-    NTSTATUS status;
-    UNICODE_STRING str;
-    OBJECT_ATTRIBUTES attr;
-    EVENT_BASIC_INFORMATION info;
-
-    pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" );
-    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-
-    status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 2, 0);
-    ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08x\n", status );
-
-    status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, NotificationEvent, 0);
-    ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
-    ok( info.EventType == NotificationEvent && info.EventState == 0,
-        "NtQueryEvent failed, expected 0 0, got %d %d\n", info.EventType, info.EventState );
-    pNtClose(Event);
-
-    status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, SynchronizationEvent, 0);
-    ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
-
-    status = pNtPulseEvent(Event, &prev_state);
-    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
-    ok( !prev_state, "prev_state = %x\n", prev_state );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
-    ok( info.EventType == SynchronizationEvent && info.EventState == 0,
-        "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
-
-    status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
-    ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
-
-    pNtClose(Event);
-    Event = Event2;
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
-    ok( info.EventType == SynchronizationEvent && info.EventState == 0,
-        "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
-
-    status = pNtSetEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
-    ok( !prev_state, "prev_state = %x\n", prev_state );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
-    ok( info.EventType == SynchronizationEvent && info.EventState == 1,
-        "NtQueryEvent failed, expected 1 1, got %d %d\n", info.EventType, info.EventState );
-
-    status = pNtSetEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
-    ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
-    status = pNtResetEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
-    ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
-    status = pNtResetEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
-    ok( !prev_state, "prev_state = %x\n", prev_state );
-
-    status = pNtPulseEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
-    ok( !prev_state, "prev_state = %x\n", prev_state );
-
-    status = pNtSetEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
-    ok( !prev_state, "prev_state = %x\n", prev_state );
-
-    status = pNtPulseEvent( Event, &prev_state );
-    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
-    ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
-    pNtClose(Event);
-}
-
-static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent";
-
-static DWORD WINAPI keyed_event_thread( void *arg )
-{
-    HANDLE handle;
-    NTSTATUS status;
-    LARGE_INTEGER timeout;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING str;
-    ULONG_PTR i;
-
-    attr.Length                   = sizeof(attr);
-    attr.RootDirectory            = 0;
-    attr.ObjectName               = &str;
-    attr.Attributes               = 0;
-    attr.SecurityDescriptor       = NULL;
-    attr.SecurityQualityOfService = NULL;
-    RtlInitUnicodeString( &str, keyed_nameW );
-
-    status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
-    ok( !status, "NtOpenKeyedEvent failed %x\n", status );
-
-    for (i = 0; i < 20; i++)
-    {
-        if (i & 1)
-            status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
-        else
-            status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
-        ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
-        Sleep( 20 - i );
-    }
-
-    status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
-    ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
-
-    timeout.QuadPart = -10000;
-    status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
-    NtClose( handle );
-    return 0;
-}
-
-static void test_keyed_events(void)
-{
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING str;
-    HANDLE handle, event, thread;
-    NTSTATUS status;
-    LARGE_INTEGER timeout;
-    ULONG_PTR i;
-
-    if (!pNtCreateKeyedEvent)
-    {
-        win_skip( "Keyed events not supported\n" );
-        return;
-    }
-
-    attr.Length                   = sizeof(attr);
-    attr.RootDirectory            = 0;
-    attr.ObjectName               = &str;
-    attr.Attributes               = 0;
-    attr.SecurityDescriptor       = NULL;
-    attr.SecurityQualityOfService = NULL;
-    RtlInitUnicodeString( &str, keyed_nameW );
-
-    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-
-    status = WaitForSingleObject( handle, 1000 );
-    ok( status == 0, "WaitForSingleObject %x\n", status );
-
-    timeout.QuadPart = -100000;
-    status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
-    ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
-    ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
-
-    status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
-    status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
-    status = pNtWaitForKeyedEvent( NULL, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
-        "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( NULL, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
-        "NtReleaseKeyedEvent %x\n", status );
-
-    status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
-    ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
-    ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
-
-    status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
-    ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
-    ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
-
-    thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
-    for (i = 0; i < 20; i++)
-    {
-        if (i & 1)
-            status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
-        else
-            status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
-        ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
-        Sleep( i );
-    }
-    status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
-    ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
-    ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
-
-    NtClose( handle );
-
-    /* test access rights */
-
-    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
-    NtClose( handle );
-
-    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-    NtClose( handle );
-
-    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-    status = WaitForSingleObject( handle, 1000 );
-    ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
-        "WaitForSingleObject %x err %u\n", status, GetLastError() );
-    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-    NtClose( handle );
-
-    /* GENERIC_READ gives wait access */
-    status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
-    NtClose( handle );
-
-    /* GENERIC_WRITE gives wake access */
-    status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
-    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
-    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
-    /* it's not an event */
-    status = pNtPulseEvent( handle, NULL );
-    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
-
-    status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
-    ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH /* 7+ */,
-        "CreateEvent %x\n", status );
-
-    NtClose( handle );
-
-    status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
-    ok( status == 0, "CreateEvent %x\n", status );
-    status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
-    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
-    status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
-    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
-    NtClose( event );
-}
-
 static void test_null_device(void)
 {
     OBJECT_ATTRIBUTES attr;
@@ -2292,269 +1999,6 @@ static void test_null_device(void)
     CloseHandle(ov.hEvent);
 }
 
-static DWORD WINAPI mutant_thread( void *arg )
-{
-    MUTANT_BASIC_INFORMATION info;
-    NTSTATUS status;
-    HANDLE mutant;
-    DWORD ret;
-
-    mutant = arg;
-    ret = WaitForSingleObject( mutant, 1000 );
-    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-    /* abandon mutant */
-
-    return 0;
-}
-
-static void test_mutant(void)
-{
-    MUTANT_BASIC_INFORMATION info;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING str;
-    NTSTATUS status;
-    HANDLE mutant;
-    HANDLE thread;
-    DWORD ret;
-    ULONG len;
-    LONG prev;
-
-    pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_mutant");
-    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-    status = pNtCreateMutant(&mutant, GENERIC_ALL, &attr, TRUE);
-    ok( status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status );
-
-    /* bogus */
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, 0, NULL);
-    ok( status == STATUS_INFO_LENGTH_MISMATCH,
-        "Failed to NtQueryMutant, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
-    status = pNtQueryMutant(mutant, 0x42, &info, sizeof(info), NULL);
-    ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_NOT_IMPLEMENTED), /* 32-bit on Vista/2k8 */
-        "Failed to NtQueryMutant, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
-    status = pNtQueryMutant((HANDLE)0xdeadbeef, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_INVALID_HANDLE,
-        "Failed to NtQueryMutant, expected STATUS_INVALID_HANDLE, got %08x\n", status );
-
-    /* new */
-    len = -1;
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), &len);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-    ok( len == sizeof(info), "got %u\n", len );
-
-    ret = WaitForSingleObject( mutant, 1000 );
-    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == -1, "expected -1, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseMutant(mutant, &prev);
-    ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
-    ok( prev == -1, "NtReleaseMutant failed, expected -1, got %d\n", prev );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseMutant(mutant, &prev);
-    ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
-    ok( prev == 0, "NtReleaseMutant failed, expected 0, got %d\n", prev );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
-    /* abandoned */
-    thread = CreateThread( NULL, 0, mutant_thread, mutant, 0, NULL );
-    ret = WaitForSingleObject( thread, 1000 );
-    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-    CloseHandle( thread );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == 1, "expected 0, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == TRUE, "expected TRUE, got %d\n", info.AbandonedState );
-
-    ret = WaitForSingleObject( mutant, 1000 );
-    ok( ret == WAIT_ABANDONED_0, "WaitForSingleObject failed %08x\n", ret );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
-    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
-    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
-    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
-    NtClose( mutant );
-}
-
-static void test_semaphore(void)
-{
-    SEMAPHORE_BASIC_INFORMATION info;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING str;
-    NTSTATUS status;
-    HANDLE semaphore;
-    ULONG prev;
-    ULONG len;
-    DWORD ret;
-
-    pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore");
-    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-
-    status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1);
-    ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status );
-    status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2);
-    ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status );
-
-    /* bogus */
-    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL);
-    ok( status == STATUS_INFO_LENGTH_MISMATCH,
-        "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
-    status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL);
-    ok( status == STATUS_INVALID_INFO_CLASS,
-        "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
-    status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_INVALID_HANDLE,
-        "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status );
-
-    len = -1;
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len);
-    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
-    ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
-    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
-    ok( len == sizeof(info), "got %u\n", len );
-
-    ret = WaitForSingleObject( semaphore, 1000 );
-    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
-    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
-    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseSemaphore(semaphore, 3, &prev);
-    ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
-    ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseSemaphore(semaphore, 1, &prev);
-    ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
-    ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseSemaphore(semaphore, 1, &prev);
-    ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
-    ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev );
-
-    prev = 0xdeadbeef;
-    status = pNtReleaseSemaphore(semaphore, 1, &prev);
-    ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
-    ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
-
-    memset(&info, 0xcc, sizeof(info));
-    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
-    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
-    ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount );
-    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
-
-    NtClose( semaphore );
-}
-
-static void test_wait_on_address(void)
-{
-    SIZE_T size;
-    NTSTATUS status;
-    LARGE_INTEGER start, end, timeout;
-    DWORD elapsed;
-    LONG64 address, compare;
-
-    if (!pRtlWaitOnAddress)
-    {
-        win_skip("RtlWaitOnAddress not supported, skipping test\n");
-        return;
-    }
-
-    if (0) /* crash on Windows */
-    {
-        pRtlWaitOnAddress(&address, NULL, 8, NULL);
-        pRtlWaitOnAddress(NULL, &compare, 8, NULL);
-        pRtlWaitOnAddress(NULL, NULL, 8, NULL);
-    }
-
-    /* don't crash */
-    pRtlWakeAddressSingle(NULL);
-    pRtlWakeAddressAll(NULL);
-
-    /* invalid values */
-    address = 0;
-    compare = 0;
-    status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
-    ok(status == STATUS_INVALID_PARAMETER, "got %x\n", status);
-
-    /* values match */
-    address = 0;
-    compare = 0;
-    pNtQuerySystemTime(&start);
-    timeout.QuadPart = start.QuadPart + 100 * 10000;
-    status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
-    pNtQuerySystemTime(&end);
-    ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
-    elapsed = (end.QuadPart - start.QuadPart) / 10000;
-    ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
-    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
-    ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
-
-    /* different address size */
-    for (size = 1; size <= 4; size <<= 1)
-    {
-        compare = ~0;
-        compare <<= size * 8;
-
-        pNtQuerySystemTime(&start);
-        timeout.QuadPart = -100 * 10000;
-        status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
-        pNtQuerySystemTime(&end);
-        ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
-        elapsed = (end.QuadPart - start.QuadPart) / 10000;
-        ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
-
-        status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
-        ok(!status, "got 0x%08x\n", status);
-    }
-    address = 0;
-    compare = 1;
-    status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
-    ok(!status, "got 0x%08x\n", status);
-
-    /* no waiters */
-    address = 0;
-    pRtlWakeAddressSingle(&address);
-    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
-    pRtlWakeAddressAll(&address);
-    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
-}
-
 static void test_process(void)
 {
     OBJECT_ATTRIBUTES attr;
@@ -2957,13 +2401,7 @@ START_TEST(om)
     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
     pNtCreateMutant         = (void *)GetProcAddress(hntdll, "NtCreateMutant");
     pNtOpenEvent            = (void *)GetProcAddress(hntdll, "NtOpenEvent");
-    pNtQueryEvent           = (void *)GetProcAddress(hntdll, "NtQueryEvent");
-    pNtPulseEvent           = (void *)GetProcAddress(hntdll, "NtPulseEvent");
-    pNtResetEvent           = (void *)GetProcAddress(hntdll, "NtResetEvent");
-    pNtSetEvent             = (void *)GetProcAddress(hntdll, "NtSetEvent");
     pNtOpenMutant           = (void *)GetProcAddress(hntdll, "NtOpenMutant");
-    pNtQueryMutant          = (void *)GetProcAddress(hntdll, "NtQueryMutant");
-    pNtReleaseMutant        = (void *)GetProcAddress(hntdll, "NtReleaseMutant");
     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
@@ -2975,7 +2413,6 @@ START_TEST(om)
     pNtQuerySymbolicLinkObject  = (void *)GetProcAddress(hntdll, "NtQuerySymbolicLinkObject");
     pNtCreateSemaphore      =  (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
     pNtOpenSemaphore        =  (void *)GetProcAddress(hntdll, "NtOpenSemaphore");
-    pNtQuerySemaphore       =  (void *)GetProcAddress(hntdll, "NtQuerySemaphore");
     pNtCreateTimer          =  (void *)GetProcAddress(hntdll, "NtCreateTimer");
     pNtOpenTimer            =  (void *)GetProcAddress(hntdll, "NtOpenTimer");
     pNtCreateSection        =  (void *)GetProcAddress(hntdll, "NtCreateSection");
@@ -2984,15 +2421,9 @@ START_TEST(om)
     pNtReleaseSemaphore     =  (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
     pNtCreateKeyedEvent     =  (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent");
     pNtOpenKeyedEvent       =  (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
-    pNtWaitForKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
-    pNtReleaseKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
     pNtCreateIoCompletion   =  (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
     pNtOpenIoCompletion     =  (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
     pNtQueryInformationFile =  (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
-    pNtQuerySystemTime      =  (void *)GetProcAddress(hntdll, "NtQuerySystemTime");
-    pRtlWaitOnAddress       =  (void *)GetProcAddress(hntdll, "RtlWaitOnAddress");
-    pRtlWakeAddressAll      =  (void *)GetProcAddress(hntdll, "RtlWakeAddressAll");
-    pRtlWakeAddressSingle   =  (void *)GetProcAddress(hntdll, "RtlWakeAddressSingle");
     pNtOpenProcess          =  (void *)GetProcAddress(hntdll, "NtOpenProcess");
     pNtCreateDebugObject    =  (void *)GetProcAddress(hntdll, "NtCreateDebugObject");
     pNtGetNextThread        =  (void *)GetProcAddress(hntdll, "NtGetNextThread");
@@ -3009,12 +2440,7 @@ START_TEST(om)
     test_symboliclink();
     test_query_object();
     test_type_mismatch();
-    test_event();
-    test_mutant();
-    test_semaphore();
-    test_keyed_events();
     test_null_device();
-    test_wait_on_address();
     test_process();
     test_token();
     test_duplicate_object();
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
new file mode 100644
index 00000000000..3d6b6a3a04d
--- /dev/null
+++ b/dlls/ntdll/tests/sync.c
@@ -0,0 +1,630 @@
+/*
+ * Unit tests for NT synchronization objects
+ *
+ * Copyright 2020 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "wine/test.h"
+
+static NTSTATUS (WINAPI *pNtClose)( HANDLE );
+static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN);
+static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
+static NTSTATUS (WINAPI *pNtCreateMutant)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, BOOLEAN );
+static NTSTATUS (WINAPI *pNtCreateSemaphore)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, LONG, LONG );
+static NTSTATUS (WINAPI *pNtOpenEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
+static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
+static NTSTATUS (WINAPI *pNtPulseEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtQueryEvent)( HANDLE, EVENT_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQueryMutant)( HANDLE, MUTANT_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQuerySemaphore)( HANDLE, SEMAPHORE_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static void     (WINAPI *pRtlInitUnicodeString)( UNICODE_STRING *, const WCHAR * );
+static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
+static void     (WINAPI *pRtlWakeAddressAll)( const void * );
+static void     (WINAPI *pRtlWakeAddressSingle)( const void * );
+
+#define KEYEDEVENT_WAIT       0x0001
+#define KEYEDEVENT_WAKE       0x0002
+#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
+
+static void test_event(void)
+{
+    HANDLE event;
+    HANDLE event2;
+    LONG prev_state = 0xdeadbeef;
+    NTSTATUS status;
+    UNICODE_STRING str;
+    OBJECT_ATTRIBUTES attr;
+    EVENT_BASIC_INFORMATION info;
+
+    pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" );
+    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+
+    status = pNtCreateEvent(&event, GENERIC_ALL, &attr, 2, 0);
+    ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08x\n", status );
+
+    status = pNtCreateEvent(&event, GENERIC_ALL, &attr, NotificationEvent, 0);
+    ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+    ok( info.EventType == NotificationEvent && info.EventState == 0,
+        "NtQueryEvent failed, expected 0 0, got %d %d\n", info.EventType, info.EventState );
+    pNtClose(event);
+
+    status = pNtCreateEvent(&event, GENERIC_ALL, &attr, SynchronizationEvent, 0);
+    ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
+
+    status = pNtPulseEvent(event, &prev_state);
+    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+    ok( !prev_state, "prev_state = %x\n", prev_state );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+    ok( info.EventType == SynchronizationEvent && info.EventState == 0,
+        "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
+
+    status = pNtOpenEvent(&event2, GENERIC_ALL, &attr);
+    ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
+
+    pNtClose(event);
+    event = event2;
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+    ok( info.EventType == SynchronizationEvent && info.EventState == 0,
+        "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
+
+    status = pNtSetEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+    ok( !prev_state, "prev_state = %x\n", prev_state );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+    ok( info.EventType == SynchronizationEvent && info.EventState == 1,
+        "NtQueryEvent failed, expected 1 1, got %d %d\n", info.EventType, info.EventState );
+
+    status = pNtSetEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+    ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+    status = pNtResetEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+    ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+    status = pNtResetEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+    ok( !prev_state, "prev_state = %x\n", prev_state );
+
+    status = pNtPulseEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+    ok( !prev_state, "prev_state = %x\n", prev_state );
+
+    status = pNtSetEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+    ok( !prev_state, "prev_state = %x\n", prev_state );
+
+    status = pNtPulseEvent( event, &prev_state );
+    ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+    ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+    pNtClose(event);
+}
+
+static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent";
+
+static DWORD WINAPI keyed_event_thread( void *arg )
+{
+    HANDLE handle;
+    NTSTATUS status;
+    LARGE_INTEGER timeout;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING str;
+    ULONG_PTR i;
+
+    attr.Length                   = sizeof(attr);
+    attr.RootDirectory            = 0;
+    attr.ObjectName               = &str;
+    attr.Attributes               = 0;
+    attr.SecurityDescriptor       = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &str, keyed_nameW );
+
+    status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
+    ok( !status, "NtOpenKeyedEvent failed %x\n", status );
+
+    for (i = 0; i < 20; i++)
+    {
+        if (i & 1)
+            status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+        else
+            status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+        ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
+        Sleep( 20 - i );
+    }
+
+    status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
+    ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
+
+    timeout.QuadPart = -10000;
+    status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+    NtClose( handle );
+    return 0;
+}
+
+static void test_keyed_events(void)
+{
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING str;
+    HANDLE handle, event, thread;
+    NTSTATUS status;
+    LARGE_INTEGER timeout;
+    ULONG_PTR i;
+
+    if (!pNtCreateKeyedEvent)
+    {
+        win_skip( "Keyed events not supported\n" );
+        return;
+    }
+
+    attr.Length                   = sizeof(attr);
+    attr.RootDirectory            = 0;
+    attr.ObjectName               = &str;
+    attr.Attributes               = 0;
+    attr.SecurityDescriptor       = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &str, keyed_nameW );
+
+    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+
+    status = WaitForSingleObject( handle, 1000 );
+    ok( status == 0, "WaitForSingleObject %x\n", status );
+
+    timeout.QuadPart = -100000;
+    status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
+    ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
+    ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
+
+    status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+    status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+    status = pNtWaitForKeyedEvent( NULL, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
+        "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( NULL, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
+        "NtReleaseKeyedEvent %x\n", status );
+
+    status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
+    ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
+    ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
+
+    status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
+    ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
+    ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
+
+    thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
+    for (i = 0; i < 20; i++)
+    {
+        if (i & 1)
+            status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+        else
+            status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+        ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
+        Sleep( i );
+    }
+    status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
+    ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+    ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
+
+    NtClose( handle );
+
+    /* test access rights */
+
+    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
+    NtClose( handle );
+
+    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+    NtClose( handle );
+
+    status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+    status = WaitForSingleObject( handle, 1000 );
+    ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
+        "WaitForSingleObject %x err %u\n", status, GetLastError() );
+    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+    NtClose( handle );
+
+    /* GENERIC_READ gives wait access */
+    status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
+    NtClose( handle );
+
+    /* GENERIC_WRITE gives wake access */
+    status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
+    ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+    status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+    ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+    /* it's not an event */
+    status = pNtPulseEvent( handle, NULL );
+    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
+
+    status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
+    ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH /* 7+ */,
+        "CreateEvent %x\n", status );
+
+    NtClose( handle );
+
+    status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
+    ok( status == 0, "CreateEvent %x\n", status );
+    status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
+    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
+    status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
+    ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
+    NtClose( event );
+}
+
+static DWORD WINAPI mutant_thread( void *arg )
+{
+    MUTANT_BASIC_INFORMATION info;
+    NTSTATUS status;
+    HANDLE mutant;
+    DWORD ret;
+
+    mutant = arg;
+    ret = WaitForSingleObject( mutant, 1000 );
+    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+    /* abandon mutant */
+
+    return 0;
+}
+
+static void test_mutant(void)
+{
+    MUTANT_BASIC_INFORMATION info;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING str;
+    NTSTATUS status;
+    HANDLE mutant;
+    HANDLE thread;
+    DWORD ret;
+    ULONG len;
+    LONG prev;
+
+    pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_mutant");
+    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+    status = pNtCreateMutant(&mutant, GENERIC_ALL, &attr, TRUE);
+    ok( status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status );
+
+    /* bogus */
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, 0, NULL);
+    ok( status == STATUS_INFO_LENGTH_MISMATCH,
+        "Failed to NtQueryMutant, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
+    status = pNtQueryMutant(mutant, 0x42, &info, sizeof(info), NULL);
+    ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_NOT_IMPLEMENTED), /* 32-bit on Vista/2k8 */
+        "Failed to NtQueryMutant, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
+    status = pNtQueryMutant((HANDLE)0xdeadbeef, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_INVALID_HANDLE,
+        "Failed to NtQueryMutant, expected STATUS_INVALID_HANDLE, got %08x\n", status );
+
+    /* new */
+    len = -1;
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), &len);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+    ok( len == sizeof(info), "got %u\n", len );
+
+    ret = WaitForSingleObject( mutant, 1000 );
+    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == -1, "expected -1, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseMutant(mutant, &prev);
+    ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
+    ok( prev == -1, "NtReleaseMutant failed, expected -1, got %d\n", prev );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseMutant(mutant, &prev);
+    ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
+    ok( prev == 0, "NtReleaseMutant failed, expected 0, got %d\n", prev );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+    /* abandoned */
+    thread = CreateThread( NULL, 0, mutant_thread, mutant, 0, NULL );
+    ret = WaitForSingleObject( thread, 1000 );
+    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+    CloseHandle( thread );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == 1, "expected 0, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == TRUE, "expected TRUE, got %d\n", info.AbandonedState );
+
+    ret = WaitForSingleObject( mutant, 1000 );
+    ok( ret == WAIT_ABANDONED_0, "WaitForSingleObject failed %08x\n", ret );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+    ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+    ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+    NtClose( mutant );
+}
+
+static void test_semaphore(void)
+{
+    SEMAPHORE_BASIC_INFORMATION info;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING str;
+    NTSTATUS status;
+    HANDLE semaphore;
+    ULONG prev;
+    ULONG len;
+    DWORD ret;
+
+    pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore");
+    InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+
+    status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1);
+    ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status );
+    status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2);
+    ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status );
+
+    /* bogus */
+    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL);
+    ok( status == STATUS_INFO_LENGTH_MISMATCH,
+        "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
+    status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL);
+    ok( status == STATUS_INVALID_INFO_CLASS,
+        "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
+    status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_INVALID_HANDLE,
+        "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status );
+
+    len = -1;
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len);
+    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+    ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
+    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+    ok( len == sizeof(info), "got %u\n", len );
+
+    ret = WaitForSingleObject( semaphore, 1000 );
+    ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+    ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseSemaphore(semaphore, 3, &prev);
+    ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
+    ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseSemaphore(semaphore, 1, &prev);
+    ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
+    ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseSemaphore(semaphore, 1, &prev);
+    ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
+    ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev );
+
+    prev = 0xdeadbeef;
+    status = pNtReleaseSemaphore(semaphore, 1, &prev);
+    ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
+    ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
+
+    memset(&info, 0xcc, sizeof(info));
+    status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+    ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+    ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount );
+    ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+
+    NtClose( semaphore );
+}
+
+static void test_wait_on_address(void)
+{
+    DWORD ticks;
+    SIZE_T size;
+    NTSTATUS status;
+    LARGE_INTEGER timeout;
+    LONG64 address, compare;
+
+    if (!pRtlWaitOnAddress)
+    {
+        win_skip("RtlWaitOnAddress not supported, skipping test\n");
+        return;
+    }
+
+    if (0) /* crash on Windows */
+    {
+        pRtlWaitOnAddress(&address, NULL, 8, NULL);
+        pRtlWaitOnAddress(NULL, &compare, 8, NULL);
+        pRtlWaitOnAddress(NULL, NULL, 8, NULL);
+    }
+
+    /* don't crash */
+    pRtlWakeAddressSingle(NULL);
+    pRtlWakeAddressAll(NULL);
+
+    /* invalid values */
+    address = 0;
+    compare = 0;
+    status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
+    ok(status == STATUS_INVALID_PARAMETER, "got %x\n", status);
+
+    /* values match */
+    address = 0;
+    compare = 0;
+    pNtQuerySystemTime(&timeout);
+    timeout.QuadPart += 100*10000;
+    ticks = GetTickCount();
+    status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
+    ticks = GetTickCount() - ticks;
+    ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+    ok(ticks >= 90 && ticks <= 1000, "got %u\n", ticks);
+    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+    ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
+
+    /* different address size */
+    for (size = 1; size <= 4; size <<= 1)
+    {
+        compare = ~0;
+        compare <<= size * 8;
+
+        timeout.QuadPart = -100 * 10000;
+        ticks = GetTickCount();
+        status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
+        ticks = GetTickCount() - ticks;
+        ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+        ok(ticks >= 90 && ticks <= 1000, "got %u\n", ticks);
+
+        status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
+        ok(!status, "got 0x%08x\n", status);
+    }
+    address = 0;
+    compare = 1;
+    status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
+    ok(!status, "got 0x%08x\n", status);
+
+    /* no waiters */
+    address = 0;
+    pRtlWakeAddressSingle(&address);
+    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+    pRtlWakeAddressAll(&address);
+    ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+}
+
+START_TEST(sync)
+{
+    HMODULE module = GetModuleHandleA("ntdll.dll");
+
+    pNtClose                        = (void *)GetProcAddress(module, "NtClose");
+    pNtCreateEvent                  = (void *)GetProcAddress(module, "NtCreateEvent");
+    pNtCreateKeyedEvent             = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
+    pNtCreateMutant                 = (void *)GetProcAddress(module, "NtCreateMutant");
+    pNtCreateSemaphore              = (void *)GetProcAddress(module, "NtCreateSemaphore");
+    pNtOpenEvent                    = (void *)GetProcAddress(module, "NtOpenEvent");
+    pNtOpenKeyedEvent               = (void *)GetProcAddress(module, "NtOpenKeyedEvent");
+    pNtPulseEvent                   = (void *)GetProcAddress(module, "NtPulseEvent");
+    pNtQueryEvent                   = (void *)GetProcAddress(module, "NtQueryEvent");
+    pNtQueryMutant                  = (void *)GetProcAddress(module, "NtQueryMutant");
+    pNtQuerySemaphore               = (void *)GetProcAddress(module, "NtQuerySemaphore");
+    pNtQuerySystemTime              = (void *)GetProcAddress(module, "NtQuerySystemTime");
+    pNtReleaseKeyedEvent            = (void *)GetProcAddress(module, "NtReleaseKeyedEvent");
+    pNtReleaseMutant                = (void *)GetProcAddress(module, "NtReleaseMutant");
+    pNtReleaseSemaphore             = (void *)GetProcAddress(module, "NtReleaseSemaphore");
+    pNtResetEvent                   = (void *)GetProcAddress(module, "NtResetEvent");
+    pNtSetEvent                     = (void *)GetProcAddress(module, "NtSetEvent");
+    pNtWaitForKeyedEvent            = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
+    pRtlInitUnicodeString           = (void *)GetProcAddress(module, "RtlInitUnicodeString");
+    pRtlWaitOnAddress               = (void *)GetProcAddress(module, "RtlWaitOnAddress");
+    pRtlWakeAddressAll              = (void *)GetProcAddress(module, "RtlWakeAddressAll");
+    pRtlWakeAddressSingle           = (void *)GetProcAddress(module, "RtlWakeAddressSingle");
+
+    test_wait_on_address();
+    test_event();
+    test_mutant();
+    test_semaphore();
+    test_keyed_events();
+}
-- 
2.33.0




More information about the wine-devel mailing list