[PATCH 14/22] ntdll: Use shared loader locking in LdrAddRefDll().

Paul Gofman pgofman at codeweavers.com
Fri Oct 1 13:20:59 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/loader.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 766a3108425..927de8e25f5 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -496,6 +496,16 @@ static void unlock_module_info(void)
     RtlReleaseSRWLockExclusive( &loader_module_info_lock );
 }
 
+/*************************************************************************
+ *		is_thread_exclusive
+ *
+ * The loader must be locked while calling this function.
+ */
+static BOOL is_thread_exclusive(void)
+{
+    return RtlDllShutdownInProgress() || exclusive_lock_thread_id == GetCurrentThreadId();
+}
+
 /*************************************************************************
  *		get_cached_modref
  *
@@ -3431,14 +3441,24 @@ NTSTATUS WINAPI LdrAddRefDll( ULONG flags, HMODULE module )
 
     if (flags & ~LDR_ADDREF_DLL_PIN) FIXME( "%p flags %x not implemented\n", module, flags );
 
-    lock_loader_exclusive();
+    lock_loader_shared();
 
     if ((wm = get_modref( module )))
     {
-        if (flags & LDR_ADDREF_DLL_PIN)
-            wm->ldr.LoadCount = -1;
-        else
-            if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
+        lock_module_info();
+        /* If LdrAddRefDll is called during unloading from the application callback
+         * (DLL entry point or LDR notification) it fails with LDR_ADDREF_DLL_PIN flag
+         * but succeeds without, while module is still unloaded regardless. */
+        if (!wm->ldr.LoadCount)
+        {
+            if (is_thread_exclusive())
+                ret = flags & LDR_ADDREF_DLL_PIN ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
+            else
+                ret = STATUS_DLL_NOT_FOUND;
+        }
+        else if (flags & LDR_ADDREF_DLL_PIN) wm->ldr.LoadCount = -1;
+        else if (wm->ldr.LoadCount != -1)  ++wm->ldr.LoadCount;
+        unlock_module_info();
         TRACE( "(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
     }
     else ret = STATUS_INVALID_PARAMETER;
-- 
2.31.1




More information about the wine-devel mailing list