Alexandre Julliard : ntdll: Support loading a builtin dll by specifying an explicit path to

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 7 14:20:08 CST 2006


Module: wine
Branch: refs/heads/master
Commit: a458f3e538f925b60e2668efb2b3db7e1c8bf027
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=a458f3e538f925b60e2668efb2b3db7e1c8bf027

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Feb  7 21:16:25 2006 +0100

ntdll: Support loading a builtin dll by specifying an explicit path to
the .so file.

---

 dlls/ntdll/loader.c |  141 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 107 insertions(+), 34 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index c2e2f36..c72646a 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -77,6 +77,7 @@ typedef struct _wine_modref
 struct builtin_load_info
 {
     const WCHAR *load_path;
+    const WCHAR *filename;
     NTSTATUS     status;
     WINE_MODREF *wm;
 };
@@ -1194,6 +1195,48 @@ NTSTATUS WINAPI LdrGetProcedureAddress(H
 
 
 /***********************************************************************
+ *           get_builtin_fullname
+ *
+ * Build the full pathname for a builtin dll.
+ */
+static WCHAR *get_builtin_fullname( const WCHAR *path, const char *filename )
+{
+    static const WCHAR soW[] = {'.','s','o',0};
+    WCHAR *p, *fullname;
+    size_t i, len = strlen(filename);
+
+    /* check if path can correspond to the dll we have */
+    if (path && (p = strrchrW( path, '\\' )))
+    {
+        p++;
+        for (i = 0; i < len; i++)
+            if (tolowerW(p[i]) != tolowerW( (WCHAR)filename[i]) ) break;
+        if (i == len && (!p[len] || !strcmpiW( p + len, soW )))
+        {
+            /* the filename matches, use path as the full path */
+            len += p - path;
+            if ((fullname = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
+            {
+                memcpy( fullname, path, len * sizeof(WCHAR) );
+                fullname[len] = 0;
+            }
+            return fullname;
+        }
+    }
+
+    if ((fullname = RtlAllocateHeap( GetProcessHeap(), 0,
+                                     system_dir.MaximumLength + (len + 1) * sizeof(WCHAR) )))
+    {
+        memcpy( fullname, system_dir.Buffer, system_dir.Length );
+        p = fullname + system_dir.Length / sizeof(WCHAR);
+        if (p > fullname && p[-1] != '\\') *p++ = '\\';
+        ascii_to_unicode( p, filename, len + 1 );
+    }
+    return fullname;
+}
+
+
+/***********************************************************************
  *           load_builtin_callback
  *
  * Load a library in memory; callback function for wine_dll_register
@@ -1204,7 +1247,7 @@ static void load_builtin_callback( void 
     void *addr;
     IMAGE_NT_HEADERS *nt;
     WINE_MODREF *wm;
-    WCHAR *fullname, *p;
+    WCHAR *fullname;
     const WCHAR *load_path;
 
     if (!module)
@@ -1233,17 +1276,12 @@ static void load_builtin_callback( void 
 
     /* create the MODREF */
 
-    if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
-                                      system_dir.MaximumLength + (strlen(filename) + 1) * sizeof(WCHAR) )))
+    if (!(fullname = get_builtin_fullname( builtin_load_info->filename, filename )))
     {
         ERR( "can't load %s\n", filename );
         builtin_load_info->status = STATUS_NO_MEMORY;
         return;
     }
-    memcpy( fullname, system_dir.Buffer, system_dir.Length );
-    p = fullname + system_dir.Length / sizeof(WCHAR);
-    if (p > fullname && p[-1] != '\\') *p++ = '\\';
-    ascii_to_unicode( p, filename, strlen(filename) + 1 );
 
     wm = alloc_module( module, fullname );
     RtlFreeHeap( GetProcessHeap(), 0, fullname );
@@ -1385,13 +1423,14 @@ static NTSTATUS load_native_dll( LPCWSTR
 /***********************************************************************
  *           load_builtin_dll
  */
-static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
+static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
+                                  DWORD flags, WINE_MODREF** pwm )
 {
     char error[256], dllname[MAX_PATH];
     int file_exists;
     const WCHAR *name, *p;
     DWORD len, i;
-    void *handle;
+    void *handle = NULL;
     struct builtin_load_info info, *prev_info;
 
     /* Fix the name in case we have a full path and extension */
@@ -1399,28 +1438,53 @@ static NTSTATUS load_builtin_dll( LPCWST
     if ((p = strrchrW( name, '\\' ))) name = p + 1;
     if ((p = strrchrW( name, '/' ))) name = p + 1;
 
-    /* we don't want to depend on the current codepage here */
-    len = strlenW( name ) + 1;
-    if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
-    for (i = 0; i < len; i++)
-    {
-        if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
-        dllname[i] = (char)name[i];
-        if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
-    }
-
     /* load_library will modify info.status. Note also that load_library can be
      * called several times, if the .so file we're loading has dependencies.
      * info.status will gather all the errors we may get while loading all these
      * libraries
      */
     info.load_path = load_path;
+    info.filename  = NULL;
     info.status    = STATUS_SUCCESS;
     info.wm        = NULL;
-    prev_info = builtin_load_info;
-    builtin_load_info = &info;
-    handle = wine_dll_load( dllname, error, sizeof(error), &file_exists );
-    builtin_load_info = prev_info;
+
+    if (file)  /* we have a real file, try to load it */
+    {
+        UNICODE_STRING nt_name;
+        ANSI_STRING unix_name;
+
+        if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
+            return STATUS_DLL_NOT_FOUND;
+
+        if (!wine_nt_to_unix_file_name( &nt_name, &unix_name, FILE_OPEN, FALSE ))
+        {
+            file_exists = 1;
+            prev_info = builtin_load_info;
+            info.filename = nt_name.Buffer + 4;  /* skip \??\ */
+            builtin_load_info = &info;
+            handle = wine_dlopen( unix_name.Buffer, RTLD_NOW, error, sizeof(error) );
+            builtin_load_info = prev_info;
+            RtlFreeHeap( GetProcessHeap(), 0, unix_name.Buffer );
+        }
+        RtlFreeUnicodeString( &nt_name );
+    }
+    else
+    {
+        /* we don't want to depend on the current codepage here */
+        len = strlenW( name ) + 1;
+        if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
+        for (i = 0; i < len; i++)
+        {
+            if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
+            dllname[i] = (char)name[i];
+            if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
+        }
+
+        prev_info = builtin_load_info;
+        builtin_load_info = &info;
+        handle = wine_dll_load( dllname, error, sizeof(error), &file_exists );
+        builtin_load_info = prev_info;
+    }
 
     if (!handle)
     {
@@ -1449,10 +1513,16 @@ static NTSTATUS load_builtin_dll( LPCWST
     info.wm->ldr.SectionHandle = handle;
     if (strcmpiW( info.wm->ldr.BaseDllName.Buffer, name ))
     {
-        ERR( "loaded .so for %s but got %s instead - probably 16-bit dll\n",
-             debugstr_w(name), debugstr_w(info.wm->ldr.BaseDllName.Buffer) );
-        /* wine_dll_unload( handle );*/
-        return STATUS_INVALID_IMAGE_FORMAT;
+        /* check without .so extension */
+        static const WCHAR soW[] = {'.','s','o',0};
+        DWORD len = info.wm->ldr.BaseDllName.Length / sizeof(WCHAR);
+        if (strncmpiW( info.wm->ldr.BaseDllName.Buffer, name, len ) || strcmpiW( name + len, soW ))
+        {
+            ERR( "loaded .so for %s but got %s instead - probably 16-bit dll\n",
+                 debugstr_w(name), debugstr_w(info.wm->ldr.BaseDllName.Buffer) );
+            /* wine_dll_unload( handle );*/
+            return STATUS_INVALID_IMAGE_FORMAT;
+        }
     }
     *pwm = info.wm;
     return STATUS_SUCCESS;
@@ -1576,7 +1646,6 @@ static NTSTATUS load_dll( LPCWSTR load_p
     WCHAR buffer[32];
     WCHAR *filename;
     ULONG size;
-    const char *filetype = "";
     WINE_MODREF *main_exe;
     HANDLE handle = 0;
     NTSTATUS nts;
@@ -1626,12 +1695,15 @@ static NTSTATUS load_dll( LPCWSTR load_p
             TRACE("Trying native dll %s\n", debugstr_w(filename));
             if (!handle) continue;  /* it cannot possibly be loaded */
             nts = load_native_dll( load_path, filename, handle, flags, pwm );
-            filetype = "native";
+            if (nts == STATUS_INVALID_FILE_FOR_SECTION)
+            {
+                /* not in PE format, maybe it's a builtin */
+                nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
+            }
             break;
         case LOADORDER_BI:
             TRACE("Trying built-in %s\n", debugstr_w(filename));
-            nts = load_builtin_dll( load_path, filename, flags, pwm );
-            filetype = "builtin";
+            nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
             break;
         default:
             nts = STATUS_INTERNAL_ERROR;
@@ -1641,8 +1713,9 @@ static NTSTATUS load_dll( LPCWSTR load_p
         if (nts == STATUS_SUCCESS)
         {
             /* Initialize DLL just loaded */
-            TRACE("Loaded module %s (%s) at %p\n",
-                  debugstr_w(filename), filetype, (*pwm)->ldr.BaseAddress);
+            TRACE("Loaded module %s (%s) at %p\n", debugstr_w(filename),
+                  ((*pwm)->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native",
+                  (*pwm)->ldr.BaseAddress);
             /* Set the ldr.LoadCount here so that an attach failure will */
             /* decrement the dependencies through the MODULE_FreeLibrary call. */
             (*pwm)->ldr.LoadCount = 1;
@@ -2169,7 +2242,7 @@ void __wine_process_init( int argc, char
     /* setup the load callback and create ntdll modref */
     wine_dll_set_callback( load_builtin_callback );
 
-    if ((status = load_builtin_dll( NULL, kernel32W, 0, &wm )) != STATUS_SUCCESS)
+    if ((status = load_builtin_dll( NULL, kernel32W, 0, 0, &wm )) != STATUS_SUCCESS)
     {
         MESSAGE( "wine: could not load kernel32.dll, status %lx\n", status );
         exit(1);




More information about the wine-cvs mailing list