[PATCH v2 14/22] ntdll: Use shared loader locking in LdrAddRefDll().
Paul Gofman
pgofman at codeweavers.com
Tue Oct 5 17:49:20 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 5f4f4fea036..6b2e8d4686f 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -473,6 +473,16 @@ static void lock_loader_restore_exclusive(void)
locked_exclusive = TRUE;
}
+/*************************************************************************
+ * 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
*
@@ -3415,14 +3425,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++;
+ RtlAcquireSRWLockExclusive( &ldr_data_srw_lock );
+ /* 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;
+ RtlReleaseSRWLockExclusive( &ldr_data_srw_lock );
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