From c6654c5479568c9bc5d5d64457c3cfbbf1c27f70 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Sat, 9 Jun 2018 15:48:46 -0500
Subject: [PATCH 26/83] ntdll: Create esync objects for mutexes.

---
 dlls/ntdll/esync.c  | 39 +++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/esync.h  |  2 ++
 dlls/ntdll/sync.c   |  3 +++
 server/protocol.def |  1 +
 4 files changed, 45 insertions(+)

diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 4d708c6df..0798786df 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -97,6 +97,13 @@ struct event
     struct esync obj;
 };
 
+struct mutex
+{
+    struct esync obj;
+    DWORD tid;
+    int count;    /* recursion count */
+};
+
 /* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
  * This is copied and adapted from the fd cache code. */
 
@@ -407,6 +414,38 @@ NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev )
     return STATUS_SUCCESS;
 }
 
+NTSTATUS esync_create_mutex( HANDLE *handle, ACCESS_MASK access,
+    const OBJECT_ATTRIBUTES *attr, BOOLEAN initial )
+{
+    struct mutex *mutex;
+    NTSTATUS ret;
+    int fd;
+
+    TRACE("name %s, initial %d.\n",
+        attr ? debugstr_us(attr->ObjectName) : "<no name>", initial);
+
+    ret = create_esync( &fd, handle, access, attr, initial ? 0 : 1, 0 );
+    if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+    {
+        mutex = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*mutex) );
+        if (!mutex)
+            return STATUS_NO_MEMORY;
+
+        /* can't take ownership of the mutex if we didn't create it */
+        if (ret == STATUS_OBJECT_NAME_EXISTS)
+            initial = FALSE;
+
+        mutex->obj.type = ESYNC_MUTEX;
+        mutex->obj.fd = fd;
+        mutex->tid = initial ? GetCurrentThreadId() : 0;
+        mutex->count = initial ? 1 : 0;
+
+        add_to_list( *handle, &mutex->obj);
+    }
+
+    return ret;
+}
+
 #define TICKSPERSEC        10000000
 #define TICKSPERMSEC       10000
 
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index 551257fbc..7af718027 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -29,6 +29,8 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
 extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
 extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
 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_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 74b50cbc7..f6e507c2f 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -540,6 +540,9 @@ NTSTATUS WINAPI NtCreateMutant(OUT HANDLE* MutantHandle,
     data_size_t len;
     struct object_attributes *objattr;
 
+    if (do_esync())
+        return esync_create_mutex( MutantHandle, access, attr, InitialOwner );
+
     if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
 
     SERVER_START_REQ( create_mutex )
diff --git a/server/protocol.def b/server/protocol.def
index cebe0e88e..721ffb96d 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4064,6 +4064,7 @@ enum esync_type
     ESYNC_SEMAPHORE = 1,
     ESYNC_AUTO_EVENT,
     ESYNC_MANUAL_EVENT,
+    ESYNC_MUTEX,
     ESYNC_MANUAL_SERVER,
     ESYNC_QUEUE,
 };
-- 
2.20.1

