From f0c5814c083c825326b2e3d3bc03e688262f4012 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Tue, 19 Jun 2018 10:50:09 -0500
Subject: [PATCH 52/83] ntdll: Go through the server if necessary when
 performing event/semaphore/mutex ops.

Because we might have a duplicated or inherited handle, and we won't know about it until we ask the server.
---
 dlls/ntdll/esync.c | 50 +++++++++++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 583174499..5eef7e3c8 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -197,7 +197,7 @@ static BOOL add_to_list( HANDLE handle, struct esync *obj )
     return TRUE;
 }
 
-static void *esync_get_object( HANDLE handle )
+static struct esync *get_cached_object( HANDLE handle )
 {
     UINT_PTR entry, idx = handle_to_index( handle, &entry );
 
@@ -206,11 +206,14 @@ static void *esync_get_object( HANDLE handle )
     return esync_list[entry][idx];
 }
 
-/* Gets a waitable object. This is either a proper esync object (i.e. an event,
+/* Gets an object. This is either a proper esync object (i.e. an event,
  * semaphore, etc. created using create_esync) or a generic synchronizable
  * server-side object which the server will signal (e.g. a process, thread,
- * message queue, etc.) */
-static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj )
+ * message queue, etc.)
+ *
+ * Note that we have to make the server path available even for esync objects
+ * since we might be passed a duplicated or inherited handle. */
+static NTSTATUS get_object( HANDLE handle, struct esync **obj )
 {
     obj_handle_t fd_handle;
     enum esync_type type;
@@ -220,11 +223,11 @@ static NTSTATUS get_waitable_object( HANDLE handle, struct esync **obj )
     NTSTATUS ret;
     int fd;
 
-    if ((*obj = esync_get_object( handle ))) return STATUS_SUCCESS;
+    if ((*obj = get_cached_object( handle ))) return STATUS_SUCCESS;
 
     /* We need to try grabbing it from the server. */
     server_enter_uninterrupted_section( &fd_cache_section, &sigset );
-    if (!(esync = esync_get_object( handle )))
+    if (!(esync = get_cached_object( handle )))
     {
         SERVER_START_REQ( get_esync_fd )
         {
@@ -421,7 +424,7 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
         /* Initialize the shared memory portion.
          * Note we store max here (even though we don't need to) just to keep
          * it the same size as the mutex's shm portion. */
-        struct esync *obj = esync_get_object( *handle );
+        struct esync *obj = get_cached_object( *handle );
         struct semaphore *semaphore = obj->shm;
         semaphore->max = max;
         semaphore->count = initial;
@@ -447,14 +450,15 @@ NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access,
 
 NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
 {
-    struct esync *obj = esync_get_object( handle );
+    struct esync *obj;
     struct semaphore *semaphore;
     uint64_t count64 = count;
     ULONG current;
+    NTSTATUS ret;
 
     TRACE("%p, %d, %p.\n", handle, count, prev);
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( handle, &obj))) return ret;
     semaphore = obj->shm;
 
     do
@@ -499,12 +503,13 @@ NTSTATUS esync_open_event( HANDLE *handle, ACCESS_MASK access,
 
 NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
 {
-    struct esync *obj = esync_get_object( handle );
     static const uint64_t value = 1;
+    struct esync *obj;
+    NTSTATUS ret;
 
     TRACE("%p.\n", handle);
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( handle, &obj ))) return ret;
 
     if (prev)
     {
@@ -520,12 +525,13 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
 
 NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
 {
-    struct esync *obj = esync_get_object( handle );
     static uint64_t value;
+    struct esync *obj;
+    NTSTATUS ret;
 
     TRACE("%p.\n", handle);
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( handle, &obj ))) return ret;
 
     if (prev)
     {
@@ -541,12 +547,13 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
 
 NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev )
 {
-    struct esync *obj = esync_get_object( handle );
     static uint64_t value = 1;
+    struct esync *obj;
+    NTSTATUS ret;
 
     TRACE("%p.\n", handle);
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( handle, &obj ))) return ret;
 
     if (prev)
     {
@@ -578,7 +585,7 @@ NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access,
     if (!ret)
     {
         /* Initialize the shared memory portion. */
-        struct esync *obj = esync_get_object( *handle );
+        struct esync *obj = get_cached_object( *handle );
         struct mutex *mutex = obj->shm;
         mutex->tid = initial ? GetCurrentThreadId() : 0;
         mutex->count = initial ? 1 : 0;
@@ -604,13 +611,14 @@ NTSTATUS esync_open_mutex( HANDLE *handle, ACCESS_MASK access,
 
 NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev )
 {
-    struct esync *obj = esync_get_object( handle );
+    struct esync *obj;
     struct mutex *mutex;
     static const uint64_t value = 1;
+    NTSTATUS ret;
 
     TRACE("%p, %p.\n", handle, prev);
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( handle, &obj ))) return ret;
     mutex = obj->shm;
 
     /* This is thread-safe, because the only thread that can change the tid to
@@ -734,7 +742,7 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
 
     for (i = 0; i < count; i++)
     {
-        ret = get_waitable_object( handles[i], &objs[i] );
+        ret = get_object( handles[i], &objs[i] );
         if (ret == STATUS_SUCCESS)
             has_esync = 1;
         else if (ret == STATUS_NOT_IMPLEMENTED)
@@ -1091,10 +1099,10 @@ userapc:
 NTSTATUS esync_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable,
     const LARGE_INTEGER *timeout )
 {
-    struct esync *obj = esync_get_object( signal );
+    struct esync *obj;
     NTSTATUS ret;
 
-    if (!obj) return STATUS_INVALID_HANDLE;
+    if ((ret = get_object( signal, &obj ))) return ret;
 
     switch (obj->type)
     {
-- 
2.20.1

