Alexandre Julliard : ntdll: Support delayed loading of modules referenced by forwarded entry points.

Alexandre Julliard julliard at winehq.org
Fri Dec 7 11:01:48 CST 2007


Module: wine
Branch: master
Commit: 0861141725827ddc378665d7cc570362ddc172be
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0861141725827ddc378665d7cc570362ddc172be

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Dec  6 21:40:37 2007 +0100

ntdll: Support delayed loading of modules referenced by forwarded entry points.

---

 dlls/ntdll/loader.c |   48 +++++++++++++++++++++++++++++++++---------------
 1 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index ca1ebdd..05538a0 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -115,8 +115,9 @@ static WINE_MODREF *current_modref;
 static WINE_MODREF *last_failed_modref;
 
 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
+static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved );
 static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
-                                  DWORD exp_size, const char *name, int hint );
+                                  DWORD exp_size, const char *name, int hint, LPCWSTR load_path );
 
 /* convert PE image VirtualAddress to Real Address */
 static inline void *get_rva( HMODULE module, DWORD va )
@@ -330,7 +331,7 @@ static WINE_MODREF *find_fullname_module( LPCWSTR name )
  * Find the final function pointer for a forwarded function.
  * The loader_section must be locked while calling this function.
  */
-static FARPROC find_forwarded_export( HMODULE module, const char *forward )
+static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWSTR load_path )
 {
     const IMAGE_EXPORT_DIRECTORY *exports;
     DWORD exp_size;
@@ -351,13 +352,27 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
 
     if (!(wm = find_basename_module( mod_name )))
     {
-        ERR("module not found for forward '%s' used by %s\n",
-            forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
-        return NULL;
+        TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
+        if (load_dll( load_path, mod_name, 0, &wm ) == STATUS_SUCCESS &&
+            !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
+        {
+            if (process_attach( wm, NULL ) != STATUS_SUCCESS)
+            {
+                LdrUnloadDll( wm->ldr.BaseAddress );
+                wm = NULL;
+            }
+        }
+
+        if (!wm)
+        {
+            ERR( "module not found for forward '%s' used by %s\n",
+                 forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
+            return NULL;
+        }
     }
     if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
                                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
-        proc = find_named_export( wm->ldr.BaseAddress, exports, exp_size, end + 1, -1 );
+        proc = find_named_export( wm->ldr.BaseAddress, exports, exp_size, end + 1, -1, load_path );
 
     if (!proc)
     {
@@ -378,7 +393,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
  * The loader_section must be locked while calling this function.
  */
 static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
-                                    DWORD exp_size, DWORD ordinal )
+                                    DWORD exp_size, DWORD ordinal, LPCWSTR load_path )
 {
     FARPROC proc;
     const DWORD *functions = get_rva( module, exports->AddressOfFunctions );
@@ -395,7 +410,7 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY
     /* if the address falls into the export dir, it's a forward */
     if (((const char *)proc >= (const char *)exports) && 
         ((const char *)proc < (const char *)exports + exp_size))
-        return find_forwarded_export( module, (const char *)proc );
+        return find_forwarded_export( module, (const char *)proc, load_path );
 
     if (TRACE_ON(snoop))
     {
@@ -418,7 +433,7 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY
  * The loader_section must be locked while calling this function.
  */
 static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
-                                  DWORD exp_size, const char *name, int hint )
+                                  DWORD exp_size, const char *name, int hint, LPCWSTR load_path )
 {
     const WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
     const DWORD *names = get_rva( module, exports->AddressOfNames );
@@ -429,7 +444,7 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *
     {
         char *ename = get_rva( module, names[hint] );
         if (!strcmp( ename, name ))
-            return find_ordinal_export( module, exports, exp_size, ordinals[hint] );
+            return find_ordinal_export( module, exports, exp_size, ordinals[hint], load_path );
     }
 
     /* then do a binary search */
@@ -438,7 +453,7 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *
         int res, pos = (min + max) / 2;
         char *ename = get_rva( module, names[pos] );
         if (!(res = strcmp( ename, name )))
-            return find_ordinal_export( module, exports, exp_size, ordinals[pos] );
+            return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path );
         if (res > 0) max = pos - 1;
         else min = pos + 1;
     }
@@ -548,7 +563,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
 
             thunk_list->u1.Function = (ULONG_PTR)find_ordinal_export( imp_mod, exports, exp_size,
-                                                                      ordinal - exports->Base );
+                                                                      ordinal - exports->Base, load_path );
             if (!thunk_list->u1.Function)
             {
                 thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );
@@ -563,7 +578,8 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
             IMAGE_IMPORT_BY_NAME *pe_name;
             pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
             thunk_list->u1.Function = (ULONG_PTR)find_named_export( imp_mod, exports, exp_size,
-                                                                    (const char*)pe_name->Name, pe_name->Hint );
+                                                                    (const char*)pe_name->Name,
+                                                                    pe_name->Hint, load_path );
             if (!thunk_list->u1.Function)
             {
                 thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );
@@ -1196,8 +1212,9 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
     else if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
                                                       IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
     {
-        void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1 )
-                          : find_ordinal_export( module, exports, exp_size, ord - exports->Base );
+        LPCWSTR load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
+        void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, load_path )
+                          : find_ordinal_export( module, exports, exp_size, ord - exports->Base, load_path );
         if (proc)
         {
             *address = proc;
@@ -1812,6 +1829,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
 
     TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
 
+    *pwm = NULL;
     filename = buffer;
     size = sizeof(buffer);
     for (;;)




More information about the wine-cvs mailing list