Zebediah Figura : ntoskrnl.exe: Implement KeReleaseMutex() and waiting on mutexes.

Alexandre Julliard julliard at winehq.org
Tue Nov 27 14:26:10 CST 2018


Module: wine
Branch: master
Commit: 1aaabb781b6c1a59ea0573a57d0c698b62cad339
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=1aaabb781b6c1a59ea0573a57d0c698b62cad339

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon Nov 26 19:39:19 2018 -0600

ntoskrnl.exe: Implement KeReleaseMutex() and waiting on mutexes.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/ntoskrnl.c        | 10 -------
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec |  2 +-
 dlls/ntoskrnl.exe/sync.c            | 46 +++++++++++++++++++++++++++--
 dlls/ntoskrnl.exe/tests/driver.c    | 58 +++++++++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 1d1033e..7838bd9 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -2288,16 +2288,6 @@ NTSTATUS WINAPI KeWaitForMutexObject(PRKMUTEX Mutex, KWAIT_REASON WaitReason, KP
 }
 
 
- /***********************************************************************
- *           KeReleaseMutex   (NTOSKRNL.EXE.@)
- */
-LONG WINAPI KeReleaseMutex(PRKMUTEX Mutex, BOOLEAN Wait)
-{
-    FIXME( "stub: %p, %d\n", Mutex, Wait );
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-
 /***********************************************************************
  *           KeInitializeSpinLock   (NTOSKRNL.EXE.@)
  */
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index d127a25..f56bde1 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1404,7 +1404,7 @@
 @ stdcall -private ZwUnloadKey(ptr) NtUnloadKey
 @ stdcall -private ZwUnmapViewOfSection(long ptr) NtUnmapViewOfSection
 @ stdcall -private ZwWaitForMultipleObjects(long ptr long long ptr) NtWaitForMultipleObjects
-@ stdcall -private ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject
+@ stdcall ZwWaitForSingleObject(long long ptr) NtWaitForSingleObject
 @ stdcall ZwWriteFile(long long ptr ptr ptr ptr long ptr ptr) NtWriteFile
 @ stdcall -private ZwYieldExecution() NtYieldExecution
 @ stdcall -private -arch=arm,x86_64 -norelay __chkstk()
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 6f356f6..0947b67 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -82,6 +82,9 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
             case TYPE_AUTO_EVENT:
                 objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL );
                 break;
+            case TYPE_MUTEX:
+                objs[i]->WaitListHead.Blink = CreateMutexW( NULL, FALSE, NULL );
+                break;
             case TYPE_SEMAPHORE:
             {
                 KSEMAPHORE *semaphore = CONTAINING_RECORD(objs[i], KSEMAPHORE, Header);
@@ -108,6 +111,7 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
             case TYPE_AUTO_EVENT:
                 objs[i]->SignalState = FALSE;
                 break;
+            case TYPE_MUTEX:
             case TYPE_SEMAPHORE:
                 --objs[i]->SignalState;
                 break;
@@ -116,8 +120,24 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
 
         if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink))
         {
-            CloseHandle(objs[i]->WaitListHead.Blink);
-            objs[i]->WaitListHead.Blink = NULL;
+            switch (objs[i]->Type)
+            {
+            case TYPE_MANUAL_EVENT:
+            case TYPE_AUTO_EVENT:
+            case TYPE_SEMAPHORE:
+                CloseHandle(objs[i]->WaitListHead.Blink);
+                objs[i]->WaitListHead.Blink = NULL;
+                break;
+            case TYPE_MUTEX:
+                /* Native will panic if a mutex is destroyed while held, so we
+                 * don't have to worry about leaking the handle here. */
+                if (objs[i]->SignalState == 1)
+                {
+                    CloseHandle(objs[i]->WaitListHead.Blink);
+                    objs[i]->WaitListHead.Blink = NULL;
+                }
+                break;
+            }
         }
     }
     LeaveCriticalSection( &sync_cs );
@@ -232,3 +252,25 @@ void WINAPI KeInitializeMutex( PRKMUTEX mutex, ULONG level )
     mutex->Header.WaitListHead.Blink = NULL;
     mutex->Header.WaitListHead.Flink = NULL;
 }
+
+/***********************************************************************
+ *           KeReleaseMutex   (NTOSKRNL.EXE.@)
+ */
+LONG WINAPI KeReleaseMutex( PRKMUTEX mutex, BOOLEAN wait )
+{
+    HANDLE handle = mutex->Header.WaitListHead.Blink;
+    LONG ret;
+
+    TRACE("mutex %p, wait %u.\n", mutex, wait);
+
+    EnterCriticalSection( &sync_cs );
+    ret = mutex->Header.SignalState++;
+    if (!ret && !mutex->Header.WaitListHead.Flink)
+    {
+        CloseHandle( handle );
+        mutex->Header.WaitListHead.Blink = NULL;
+    }
+    LeaveCriticalSection( &sync_cs );
+
+    return ret;
+}
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 852a726..8294882 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -226,6 +226,36 @@ 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 void run_thread(PKSTART_ROUTINE proc, void *arg)
+{
+    OBJECT_ATTRIBUTES attr = {0};
+    HANDLE thread;
+    NTSTATUS ret;
+
+    attr.Length = sizeof(attr);
+    attr.Attributes = OBJ_KERNEL_HANDLE;
+    ret = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, &attr, NULL, NULL, proc, arg);
+    ok(!ret, "got %#x\n", ret);
+
+    ret = ZwWaitForSingleObject(thread, FALSE, NULL);
+    ok(!ret, "got %#x\n", ret);
+    ret = ZwClose(thread);
+    ok(!ret, "got %#x\n", ret);
+}
+
+static KMUTEX test_mutex;
+
+static void WINAPI mutex_thread(void *arg)
+{
+    NTSTATUS ret, expect = (NTSTATUS)(DWORD_PTR)arg;
+
+    ret = wait_single(&test_mutex, 0);
+    ok(ret == expect, "expected %#x, got %#x\n", expect, ret);
+
+    if (!ret) KeReleaseMutex(&test_mutex, FALSE);
+    PsTerminateSystemThread(STATUS_SUCCESS);
+}
+
 static void test_sync(void)
 {
     KSEMAPHORE semaphore, semaphore2;
@@ -387,6 +417,33 @@ static void test_sync(void)
 
     ret = wait_multiple(2, objs, WaitAny, 0);
     ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
+
+    /* test mutexes */
+    KeInitializeMutex(&test_mutex, 0);
+
+    for (i = 0; i < 10; i++)
+    {
+        ret = wait_single(&test_mutex, 0);
+        ok(ret == 0, "got %#x\n", ret);
+    }
+
+    for (i = 0; i < 10; i++)
+    {
+        ret = KeReleaseMutex(&test_mutex, FALSE);
+        ok(ret == i - 9, "expected %d, got %d\n", i - 9, ret);
+    }
+
+    run_thread(mutex_thread, (void *)0);
+
+    ret = wait_single(&test_mutex, 0);
+    ok(ret == 0, "got %#x\n", ret);
+
+    run_thread(mutex_thread, (void *)STATUS_TIMEOUT);
+
+    ret = KeReleaseMutex(&test_mutex, 0);
+    ok(ret == 0, "got %#x\n", ret);
+
+    run_thread(mutex_thread, (void *)0);
 }
 
 static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
@@ -410,6 +467,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info)
     winetest_debug = test_input->winetest_debug;
     winetest_report_success = test_input->winetest_report_success;
     attr.ObjectName = &pathU;
+    attr.Attributes = OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */
     ZwOpenFile(&okfile, FILE_APPEND_DATA, &attr, &io, 0, 0);
 
     test_currentprocess();




More information about the wine-cvs mailing list