Module: wine Branch: refs/heads/master Commit: a458f3e538f925b60e2668efb2b3db7e1c8bf027 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=a458f3e538f925b60e2668ef...
Author: Alexandre Julliard julliard@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);