Jacek Caban : ntoskrnl.exe: Support creating event objects from server handle.
Alexandre Julliard
julliard at winehq.org
Tue Mar 26 16:43:14 CDT 2019
Module: wine
Branch: master
Commit: 0decadd62a76b968abf75c9943dd0869249ec716
URL: https://source.winehq.org/git/wine.git/?a=commit;h=0decadd62a76b968abf75c9943dd0869249ec716
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Mar 25 14:38:44 2019 +0100
ntoskrnl.exe: Support creating event objects from server handle.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntoskrnl.exe/ntoskrnl_private.h | 2 ++
dlls/ntoskrnl.exe/sync.c | 63 +++++++++++++++++++++++++++++-------
dlls/ntoskrnl.exe/tests/driver.c | 41 +++++++++++++++++++++--
server/event.c | 11 ++++++-
4 files changed, 101 insertions(+), 16 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h
index 58ecf0c..9bef13d 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl_private.h
+++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h
@@ -27,6 +27,8 @@ struct _OBJECT_TYPE {
void (*release)(void*); /* called when the last reference is released */
};
+void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref ) DECLSPEC_HIDDEN;
+
extern POBJECT_TYPE ExEventObjectType;
extern POBJECT_TYPE ExSemaphoreObjectType;
extern POBJECT_TYPE IoDeviceObjectType;
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 926df05..7cb3185 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -76,6 +76,13 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
EnterCriticalSection( &sync_cs );
for (i = 0; i < count; i++)
{
+ if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE)
+ {
+ FIXME("unsupported on kernel objects\n");
+ handles[i] = INVALID_HANDLE_VALUE;
+ continue;
+ }
+
++*((ULONG_PTR *)&objs[i]->WaitListHead.Flink);
if (!objs[i]->WaitListHead.Blink)
{
@@ -127,6 +134,8 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
}
}
+ if (objs[i]->WaitListHead.Blink == INVALID_HANDLE_VALUE) continue;
+
if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
{
switch (objs[i]->Type)
@@ -186,10 +195,24 @@ void WINAPI KeInitializeEvent( PRKEVENT event, EVENT_TYPE type, BOOLEAN state )
event->Header.WaitListHead.Flink = NULL;
}
+static void *create_event_object( HANDLE handle )
+{
+ EVENT_BASIC_INFORMATION info;
+ KEVENT *event;
+
+ if (!(event = alloc_kernel_object( ExEventObjectType, handle, sizeof(*event), 0 ))) return NULL;
+
+ if (!NtQueryEvent( handle, EventBasicInformation, &info, sizeof(info), NULL ))
+ KeInitializeEvent( event, info.EventType, info.EventState );
+ event->Header.WaitListHead.Blink = INVALID_HANDLE_VALUE; /* mark as kernel object */
+ return event;
+}
+
static const WCHAR event_type_name[] = {'E','v','e','n','t',0};
static struct _OBJECT_TYPE event_type = {
event_type_name,
+ create_event_object
};
POBJECT_TYPE ExEventObjectType = &event_type;
@@ -200,15 +223,23 @@ POBJECT_TYPE ExEventObjectType = &event_type;
LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
{
HANDLE handle;
- LONG ret;
+ ULONG ret = 0;
TRACE("event %p, increment %d, wait %u.\n", event, increment, wait);
- EnterCriticalSection( &sync_cs );
- ret = InterlockedExchange( &event->Header.SignalState, TRUE );
- if ((handle = event->Header.WaitListHead.Blink))
- SetEvent( handle );
- LeaveCriticalSection( &sync_cs );
+ if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
+ {
+ EnterCriticalSection( &sync_cs );
+ ret = InterlockedExchange( &event->Header.SignalState, TRUE );
+ if ((handle = event->Header.WaitListHead.Blink))
+ SetEvent( handle );
+ LeaveCriticalSection( &sync_cs );
+ }
+ else
+ {
+ FIXME("unsupported on kernel objects\n");
+ event->Header.SignalState = TRUE;
+ }
return ret;
}
@@ -219,15 +250,23 @@ LONG WINAPI KeSetEvent( PRKEVENT event, KPRIORITY increment, BOOLEAN wait )
LONG WINAPI KeResetEvent( PRKEVENT event )
{
HANDLE handle;
- LONG ret;
+ ULONG ret = 0;
TRACE("event %p.\n", event);
- EnterCriticalSection( &sync_cs );
- ret = InterlockedExchange( &event->Header.SignalState, FALSE );
- if ((handle = event->Header.WaitListHead.Blink))
- ResetEvent( handle );
- LeaveCriticalSection( &sync_cs );
+ if (event->Header.WaitListHead.Blink != INVALID_HANDLE_VALUE)
+ {
+ EnterCriticalSection( &sync_cs );
+ ret = InterlockedExchange( &event->Header.SignalState, FALSE );
+ if ((handle = event->Header.WaitListHead.Blink))
+ ResetEvent( handle );
+ LeaveCriticalSection( &sync_cs );
+ }
+ else
+ {
+ FIXME("unsupported on kernel objects\n");
+ event->Header.SignalState = FALSE;
+ }
return ret;
}
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 64abca4..55455d7 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -308,6 +308,14 @@ static NTSTATUS wait_multiple(ULONG count, void *objs[], WAIT_TYPE wait_type, UL
return KeWaitForMultipleObjects(count, objs, wait_type, Executive, KernelMode, FALSE, &integer, NULL);
}
+static NTSTATUS wait_single_handle(HANDLE handle, ULONGLONG timeout)
+{
+ LARGE_INTEGER integer;
+
+ integer.QuadPart = timeout;
+ return ZwWaitForSingleObject(handle, FALSE, &integer);
+}
+
static void run_thread(PKSTART_ROUTINE proc, void *arg)
{
OBJECT_ATTRIBUTES attr = {0};
@@ -341,11 +349,13 @@ static void WINAPI mutex_thread(void *arg)
static void test_sync(void)
{
KSEMAPHORE semaphore, semaphore2;
- KEVENT manual_event, auto_event;
+ KEVENT manual_event, auto_event, *event;
KTIMER timer;
LARGE_INTEGER timeout;
+ OBJECT_ATTRIBUTES attr;
void *objs[2];
NTSTATUS ret;
+ HANDLE handle;
int i;
KeInitializeEvent(&manual_event, NotificationEvent, FALSE);
@@ -440,6 +450,33 @@ static void test_sync(void)
ret = wait_multiple(2, objs, WaitAny, 0);
ok(ret == 1, "got %#x\n", ret);
+ InitializeObjectAttributes(&attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
+ ret = ZwCreateEvent(&handle, SYNCHRONIZE, &attr, NotificationEvent, TRUE);
+ ok(!ret, "ZwCreateEvent failed: %#x\n", ret);
+
+ ret = ObReferenceObjectByHandle(handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, (void **)&event, NULL);
+ ok(!ret, "ObReferenceObjectByHandle failed: %#x\n", ret);
+
+ ret = wait_single(event, 0);
+ todo_wine
+ ok(ret == 0, "got %#x\n", ret);
+ KeResetEvent(event);
+ ret = wait_single(event, 0);
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
+ ret = wait_single_handle(handle, 0);
+ todo_wine
+ ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
+
+ KeSetEvent(event, 0, FALSE);
+ ret = wait_single(event, 0);
+ todo_wine
+ ok(ret == 0, "got %#x\n", ret);
+ ret = wait_single_handle(handle, 0);
+ ok(!ret, "got %#x\n", ret);
+
+ ZwClose(handle);
+ ObDereferenceObject(event);
+
/* test semaphores */
KeInitializeSemaphore(&semaphore, 0, 5);
@@ -731,14 +768,12 @@ static void test_ob_reference(const WCHAR *test_path)
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, *pExEventObjectType, KernelMode, &obj2, NULL);
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
- todo_wine
ok(obj1 == obj2, "obj1 != obj2\n");
ObDereferenceObject(obj2);
status = ObReferenceObjectByHandle(event_handle, SYNCHRONIZE, NULL, KernelMode, &obj2, NULL);
ok(!status, "ObReferenceObjectByHandle failed: %#x\n", status);
- todo_wine
ok(obj1 == obj2, "obj1 != obj2\n");
ObDereferenceObject(obj2);
diff --git a/server/event.c b/server/event.c
index f5feca9..d339d85 100644
--- a/server/event.c
+++ b/server/event.c
@@ -39,6 +39,7 @@
struct event
{
struct object obj; /* object header */
+ struct list kernel_object; /* list of kernel object pointers */
int manual_reset; /* is it a manual reset event? */
int signaled; /* event has been signaled */
};
@@ -49,6 +50,7 @@ static int event_signaled( struct object *obj, struct wait_queue_entry *entry );
static void event_satisfied( struct object *obj, struct wait_queue_entry *entry );
static unsigned int event_map_access( struct object *obj, unsigned int access );
static int event_signal( struct object *obj, unsigned int access);
+static struct list *event_get_kernel_obj_list( struct object *obj );
static const struct object_ops event_ops =
{
@@ -68,7 +70,7 @@ static const struct object_ops event_ops =
directory_link_name, /* link_name */
default_unlink_name, /* unlink_name */
no_open_file, /* open_file */
- no_kernel_obj_list, /* get_kernel_obj_list */
+ event_get_kernel_obj_list, /* get_kernel_obj_list */
no_close_handle, /* close_handle */
no_destroy /* destroy */
};
@@ -119,6 +121,7 @@ struct event *create_event( struct object *root, const struct unicode_str *name,
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
{
/* initialize it if it didn't already exist */
+ list_init( &event->kernel_object );
event->manual_reset = manual_reset;
event->signaled = initial_state;
}
@@ -204,6 +207,12 @@ static int event_signal( struct object *obj, unsigned int access )
return 1;
}
+static struct list *event_get_kernel_obj_list( struct object *obj )
+{
+ struct event *event = (struct event *)obj;
+ return &event->kernel_object;
+}
+
struct keyed_event *create_keyed_event( struct object *root, const struct unicode_str *name,
unsigned int attr, const struct security_descriptor *sd )
{
More information about the wine-cvs
mailing list