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