From 730ad81287cfb42dae5f4dd070cc0ea6979d5c54 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Sun, 10 Jun 2018 00:29:27 -0500
Subject: [PATCH 33/83] ntdll, server: Implement NtOpenSemaphore().

---
 dlls/ntdll/esync.c  | 60 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/esync.h  |  2 ++
 dlls/ntdll/sync.c   |  3 +++
 server/esync.c      | 30 +++++++++++++++++++++++
 server/protocol.def | 12 +++++++++
 5 files changed, 107 insertions(+)

diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 2b4555959..f014003fc 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -276,6 +276,37 @@ static NTSTATUS create_esync(enum esync_type *type, int *fd, HANDLE *handle,
     return ret;
 }
 
+static NTSTATUS open_esync( enum esync_type *type, int *fd, HANDLE *handle,
+    ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
+{
+    NTSTATUS ret;
+    obj_handle_t fd_handle;
+    sigset_t sigset;
+
+    server_enter_uninterrupted_section( &fd_cache_section, &sigset );
+    SERVER_START_REQ( open_esync )
+    {
+        req->access     = access;
+        req->attributes = attr->Attributes;
+        req->rootdir    = wine_server_obj_handle( attr->RootDirectory );
+        req->type       = *type;
+        if (attr->ObjectName)
+            wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
+        if (!(ret = wine_server_call( req )))
+        {
+            *handle = wine_server_ptr_handle( reply->handle );
+            *type = reply->type;
+            *fd = receive_fd( &fd_handle );
+            assert( wine_server_ptr_handle(fd_handle) == *handle );
+        }
+    }
+    SERVER_END_REQ;
+    server_leave_uninterrupted_section( &fd_cache_section, &sigset );
+
+    TRACE("-> handle %p, fd %d.\n", *handle, *fd);
+    return ret;
+}
+
 NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
     const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
 {
@@ -304,6 +335,35 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
     return ret;
 }
 
+NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access,
+    const OBJECT_ATTRIBUTES *attr )
+{
+    enum esync_type type = ESYNC_SEMAPHORE;
+    struct semaphore *semaphore;
+    NTSTATUS ret;
+    int fd = -1;
+
+    TRACE("name %s.\n", debugstr_us(attr->ObjectName));
+
+    ret = open_esync( &type, &fd, handle, access, attr );
+    if (!ret)
+    {
+        semaphore = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*semaphore) );
+        if (!semaphore)
+            return STATUS_NO_MEMORY;
+
+        semaphore->obj.type = ESYNC_SEMAPHORE;
+        semaphore->obj.fd = fd;
+
+        FIXME("Attempt to open a semaphore, this will not work.\n");
+        semaphore->max = 0xdeadbeef;
+
+        add_to_list( *handle, &semaphore->obj );
+    }
+
+    return ret;
+}
+
 NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
 {
     struct semaphore *semaphore = esync_get_object( handle );
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index ebf5c97c2..b0d756ec1 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -32,6 +32,8 @@ extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
 extern NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access,
     const OBJECT_ATTRIBUTES *attr, BOOLEAN initial ) DECLSPEC_HIDDEN;
 extern NTSTATUS esync_release_mutex( HANDLE *handle, LONG *prev ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_open_semaphore( HANDLE *handle, ACCESS_MASK access,
+    const OBJECT_ATTRIBUTES *attr ) DECLSPEC_HIDDEN;
 
 extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
                                     BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 2f54bb4a1..3b902e669 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -279,6 +279,9 @@ NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJEC
 
     if ((ret = validate_open_object_attributes( attr ))) return ret;
 
+    if (do_esync())
+        return esync_open_semaphore( handle, access, attr );
+
     SERVER_START_REQ( open_semaphore )
     {
         req->access     = access;
diff --git a/server/esync.c b/server/esync.c
index 9ff1a847b..1f9602a43 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -235,6 +235,36 @@ DECL_HANDLER(create_esync)
     if (root) release_object( root );
 }
 
+DECL_HANDLER(open_esync)
+{
+    struct unicode_str name = get_req_unicode_str();
+
+    reply->handle = open_object( current->process, req->rootdir, req->access,
+                                 &esync_ops, &name, req->attributes );
+
+    /* send over the fd */
+    if (reply->handle)
+    {
+        struct esync *esync;
+
+        if (!(esync = (struct esync *)get_handle_obj( current->process, reply->handle,
+                                                      0, &esync_ops )))
+            return;
+
+        if (!type_matches( req->type, esync->type ))
+        {
+            set_error( STATUS_OBJECT_TYPE_MISMATCH );
+            release_object( esync );
+            return;
+        }
+
+        reply->type = esync->type;
+
+        send_client_fd( current->process, esync->fd, reply->handle );
+        release_object( esync );
+    }
+}
+
 /* Retrieve a file descriptor for an esync object which will be signaled by the
  * server. The client should only read from (i.e. wait on) this object. */
 DECL_HANDLER(get_esync_fd)
diff --git a/server/protocol.def b/server/protocol.def
index 50735ee78..7dbd0a6db 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4054,6 +4054,18 @@ struct handle_info
     int          type;          /* type of esync object (see below) */
 @END
 
+/* Open an esync object */
+@REQ(open_esync)
+    unsigned int access;        /* wanted access rights */
+    unsigned int attributes;    /* object attributes */
+    obj_handle_t rootdir;       /* root directory */
+    int          type;          /* type of esync object (above) */
+    VARARG(name,unicode_str);   /* object name */
+@REPLY
+    obj_handle_t handle;        /* handle to the event */
+    int          type;          /* type of esync object (above) */
+@END
+
 /* Retrieve the esync fd for an object. */
 @REQ(get_esync_fd)
     obj_handle_t handle;        /* handle to the object */
-- 
2.20.1

