[PATCH 4/4] ntdll: Avoid taking loader lock in LdrGetDllHandle().

Paul Gofman pgofman at codeweavers.com
Fri Oct 30 07:34:38 CDT 2020


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/kernel32/tests/loader.c |  5 ++---
 dlls/ntdll/loader.c          | 23 +++++++++++++++++++----
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 5d8991bf0f0..8b4be58036d 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -4036,9 +4036,6 @@ static void test_loader_lock_scope(void)
     test_loader_lock_event = CreateEventA(NULL, FALSE, FALSE, NULL);
     test_loader_lock_test_done_event = CreateEventA(NULL, FALSE, FALSE, NULL);
 
-    hmodule = GetModuleHandleA("ntdll.dll");
-    ok(!!hmodule, "Got NULL hmodule.\n");
-
     hthread = CreateThread(NULL, 0, test_loader_lock_thread, NULL, 0, NULL);
     ok(!!hthread, "Thread creation failed.\n");
 
@@ -4052,6 +4049,8 @@ static void test_loader_lock_scope(void)
     RtlInitAnsiString(&name, "LdrLockLoaderLock");
     address = (void *)0xdeadbeef;
     /* Locks up on loader lock before Win7. */
+    hmodule = GetModuleHandleA("ntdll.dll");
+    ok(!!hmodule, "Got NULL hmodule.\n");
     status = pLdrGetProcedureAddress(hmodule, &name, 0, &address);
     ok(!status && address == pLdrLockLoaderLock, "Got unexpected status %#x, address %p.\n", status, address);
 
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 66956c3d373..443cf49e10b 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2267,12 +2267,17 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
     NTSTATUS status;
     HANDLE handle, mapping;
 
+    if (loaded_only)
+        lock_ldr_data();
     if ((*pwm = find_fullname_module( nt_name )))
     {
         NtUnmapViewOfSection( NtCurrentProcess(), *module );
         *module = NULL;
+        /* ldr_data_section to be unlocked by the caller. */
         return STATUS_SUCCESS;
     }
+    if (loaded_only)
+        unlock_ldr_data();
 
     attr.Length = sizeof(attr);
     attr.RootDirectory = 0;
@@ -2298,6 +2303,8 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
     if (!NtFsControlFile( handle, 0, NULL, NULL, &io, FSCTL_GET_OBJECT_ID, NULL, 0, &fid, sizeof(fid) ))
     {
         memcpy( id, fid.ObjectId, sizeof(*id) );
+        if (loaded_only)
+            lock_ldr_data();
         if ((*pwm = find_fileid_module( id )))
         {
             TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ),
@@ -2305,8 +2312,11 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
             NtClose( handle );
             NtUnmapViewOfSection( NtCurrentProcess(), *module );
             *module = NULL;
+            /* ldr_data_section to be unlocked by the caller. */
             return STATUS_SUCCESS;
         }
+        if (loaded_only)
+            unlock_ldr_data();
     }
 
     if (loaded_only)
@@ -2640,11 +2650,17 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con
         else
         {
             if (status != STATUS_SXS_KEY_NOT_FOUND) goto done;
+
+            if (loaded_only)
+                lock_ldr_data();
             if ((*pwm = find_basename_module( libname )) != NULL)
             {
                 status = STATUS_SUCCESS;
+                /* ldr_data_section to be unlocked by the caller. */
                 goto done;
             }
+            if (loaded_only)
+                unlock_ldr_data();
         }
     }
 
@@ -2866,17 +2882,16 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
     SECTION_IMAGE_INFORMATION image_info;
     struct file_id id;
 
-    RtlEnterCriticalSection( &loader_section );
-
     if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
 
     if (!(status = find_dll_file( load_path, name->Buffer, dllW,
             &nt_name, &wm, &module, &image_info, &id, TRUE )))
+    {
         *base = wm->ldr.DllBase;
-
+        unlock_ldr_data();
+    }
     RtlFreeUnicodeString( &nt_name );
 
-    RtlLeaveCriticalSection( &loader_section );
     TRACE( "%s -> %p (load path %s)\n", debugstr_us(name), status ? NULL : *base, debugstr_w(load_path) );
     return status;
 }
-- 
2.28.0




More information about the wine-devel mailing list