mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1316 lines
61 KiB
Diff
1316 lines
61 KiB
Diff
From 4a177b109c83201a0f5015880af3f4bc221d7972 Mon Sep 17 00:00:00 2001
|
|
From: Zebediah Figura <z.figura12@gmail.com>
|
|
Date: Thu, 9 Jan 2020 13:44:01 -0600
|
|
Subject: [PATCH] ntdll/tests: Move some tests to a new sync.c file.
|
|
|
|
Signed-off-by: Zebediah Figura <z.figura12@gmail.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.30.2
|
|
|