diff --git a/documentation/wine.man.in b/documentation/wine.man.in index 47b1b263fe9..d37137b4f28 100644 --- a/documentation/wine.man.in +++ b/documentation/wine.man.in @@ -170,7 +170,7 @@ Use a desktop window of the given geometry, e.g. "640x480" .I --display name Use the specified X display .TP -.I --dll name[,name[,...]]={native|elfdll|so|builtin}[,{n|e|s|b}[,...]][:...] +.I --dll name[,name[,...]]={native|elfdll|so|builtin}[,{n|e|s|b}[,...]][+...] Selects the override type and load order of dll used in the loading process for any dll. The default is set in @sysconfdir@/wine.conf or ~/.winerc. There are currently four types of libraries that can be loaded into a process' address @@ -191,8 +191,10 @@ internal dlls ( Each dll may have its own specific load order. The load order determines which verion of the dll is attempted to be loaded into the address space. If the first fails, then the next is tried and so on. Different load orders can -be specified by separating the entries with a colon. Multiple libraries -with the same load order can be separated with commas. +be specified by separating the entries with a plus sign. Multiple libraries +with the same load order can be separated with commas. It is also possible to +use the --dll option several times, to specify different loadorders for different +libraries .br Examples: .br @@ -201,7 +203,12 @@ Examples: Try to load comdlg32 and commdlg as native windows dll first and try the builtin version if the native load fails. .br -.I --dll comdlg32,commdlg=e,n:shell,shell32=b:comctl32,commctrl=n +.I --dll shell,shell32=n --dll c:\\foo\\bar\\baz=b +.br +Try to load the libraries shell and shell32 as native windows dlls. Furthermore, if +an application request to load c:\\foo\\bar\\baz.dll load the builtin library baz. +.br +.I --dll comdlg32,commdlg=e,n:shell,shell32=b+comctl32,commctrl=n .br Try to load comdlg32 and commdlg as elfdll first and try the native version if the elfdll load fails; load shell32/shell always as builtin and diff --git a/include/loadorder.h b/include/loadorder.h index d64dcc81078..4d6b404e402 100644 --- a/include/loadorder.h +++ b/include/loadorder.h @@ -22,7 +22,7 @@ typedef struct module_loadorder { } module_loadorder_t; BOOL MODULE_InitLoadOrder(void); -module_loadorder_t *MODULE_GetLoadOrder(const char *path); +module_loadorder_t *MODULE_GetLoadOrder(const char *path, BOOL win32); #endif diff --git a/loader/elf.c b/loader/elf.c index 1fbe3247889..e33a67ad48b 100644 --- a/loader/elf.c +++ b/loader/elf.c @@ -158,7 +158,7 @@ WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags) SNOOP_RegisterDLL(hmod,libname,STUBSIZE/sizeof(ELF_STDCALL_STUB)); - wm = PE_CreateModule( hmod, modname, 0, -1, FALSE ); + wm = PE_CreateModule( hmod, libname, 0, -1, FALSE ); wm->find_export = ELF_FindExportedFunction; wm->dlhandle = dlhandle; return wm; diff --git a/loader/loadorder.c b/loader/loadorder.c index 4b574dccd24..f91306b5fd7 100644 --- a/loader/loadorder.c +++ b/loader/loadorder.c @@ -271,7 +271,7 @@ static BOOL AddLoadOrderSet(char *key, char *order, BOOL override) * ParseCommandlineOverrides (internal, static) * * The commandline is in the form: - * name[,name,...]=native[,b,...][:...] + * name[,name,...]=native[,b,...][+...] */ static BOOL ParseCommandlineOverrides(void) { @@ -289,7 +289,7 @@ static BOOL ParseCommandlineOverrides(void) next = key; for(; next; key = next) { - next = strchr(key, ':'); + next = strchr(key, '+'); if(next) { *next = '\0'; @@ -425,14 +425,14 @@ BOOL MODULE_InitLoadOrder(void) /* Add the commandline overrides to the pool */ if(!ParseCommandlineOverrides()) { - MESSAGE( "Syntax: -dll name[,name[,...]]={native|elfdll|so|builtin}[,{n|e|s|b}[,...]][:...]\n" + MESSAGE( "Syntax: -dll name[,name[,...]]={native|elfdll|so|builtin}[,{n|e|s|b}[,...]][+...]\n" " - 'name' is the name of any dll without extension\n" " - the order of loading (native, elfdll, so and builtin) can be abbreviated\n" " with the first letter\n" " - different loadorders for different dlls can be specified by seperating the\n" - " commandline entries with a ':'\n" + " commandline entries with a '+'\n" " Example:\n" - " -dll comdlg32,commdlg=n:shell,shell32=b\n" + " -dll comdlg32,commdlg=n+shell,shell32=b\n" ); return FALSE; } @@ -445,8 +445,8 @@ BOOL MODULE_InitLoadOrder(void) while (dllpair->dll1) { module_loadorder_t *plo1, *plo2; - plo1 = MODULE_GetLoadOrder(dllpair->dll1); - plo2 = MODULE_GetLoadOrder(dllpair->dll2); + plo1 = MODULE_GetLoadOrder(dllpair->dll1, FALSE); + plo2 = MODULE_GetLoadOrder(dllpair->dll2, FALSE); assert(plo1 && plo2); if(memcmp(plo1->loadorder, plo2->loadorder, sizeof(plo1->loadorder))) MESSAGE("Warning: Modules '%s' and '%s' have different loadorder which may cause trouble\n", dllpair->dll1, dllpair->dll2); @@ -479,10 +479,11 @@ BOOL MODULE_InitLoadOrder(void) * '.dll' and '.exe'. A lookup in the table can yield an override for * the specific dll. Otherwise the default load order is returned. */ -module_loadorder_t *MODULE_GetLoadOrder(const char *path) +module_loadorder_t *MODULE_GetLoadOrder(const char *path, BOOL win32 ) { module_loadorder_t lo, *tmp; char fname[256]; + char sysdir[MAX_PATH+1]; char *cptr; char *name; int len; @@ -491,26 +492,36 @@ module_loadorder_t *MODULE_GetLoadOrder(const char *path) assert(path != NULL); - /* Strip path information */ - cptr = strrchr(path, '\\'); - if(!cptr) - name = strrchr(path, '/'); - else - name = strrchr(cptr, '/'); - - if(!name) - name = cptr ? cptr+1 : (char *)path; - else - name++; - - if((cptr = strchr(name, ':')) != NULL) /* Also strip drive if in format 'C:MODULE.DLL' */ - name = cptr+1; + if ( ! GetSystemDirectoryA ( sysdir, MAX_PATH ) ) + return &default_loadorder; /* Hmmm ... */ + /* Strip path information for 16 bit modules or if the module + resides in the system directory */ + if ( !win32 || !strncasecmp ( sysdir, path, strlen (sysdir) ) ) + { + + cptr = strrchr(path, '\\'); + if(!cptr) + name = strrchr(path, '/'); + else + name = strrchr(cptr, '/'); + + if(!name) + name = cptr ? cptr+1 : (char *)path; + else + name++; + + if((cptr = strchr(name, ':')) != NULL) /* Also strip drive if in format 'C:MODULE.DLL' */ + name = cptr+1; + } + else + name = (char *)path; + len = strlen(name); if(len >= sizeof(fname) || len <= 0) { - ERR("Path '%s' -> '%s' reduces to zilch or just too large...\n", path, name); - return &default_loadorder; + ERR("Path '%s' -> '%s' reduces to zilch or just too large...\n", path, name); + return &default_loadorder; } strcpy(fname, name); diff --git a/loader/module.c b/loader/module.c index a68f4081fde..e1198b9b60b 100644 --- a/loader/module.c +++ b/loader/module.c @@ -415,7 +415,7 @@ HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 ) /********************************************************************** - * MODULE_FindModule32 + * MODULE_FindModule * * Find a (loaded) win32 module depending on path * @@ -1258,11 +1258,48 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) WINE_MODREF *pwm; int i; module_loadorder_t *plo; + LPSTR filename, p; + + if ( !libname ) return NULL; + + filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 ); + if ( !filename ) return NULL; + + /* build the modules filename */ + if (!SearchPathA( NULL, libname, ".dll", MAX_PATH, filename, NULL )) + { + if ( ! GetSystemDirectoryA ( filename, MAX_PATH ) ) + goto error; + + /* if the library name contains a path and can not be found, return an error. + exception: if the path is the system directory, proceed, so that modules, + which are not PE-modules can be loaded + + if the library name does not contain a path and can not be found, assume the + system directory is meant */ + + if ( ! strncasecmp ( filename, libname, strlen ( filename ) )) + strcpy ( filename, libname ); + else + { + if ( strchr ( libname, '\\' ) || strchr ( libname, ':') || strchr ( libname, '/' ) ) + goto error; + else + { + strcat ( filename, "\\" ); + strcat ( filename, libname ); + } + } + + /* if the filename doesn't have an extension append .DLL */ + if (!(p = strrchr( filename, '.')) || strchr( p, '/' ) || strchr( p, '\\')) + strcat( filename, ".DLL" ); + } EnterCriticalSection(&PROCESS_Current()->crit_section); /* Check for already loaded module */ - if((pwm = MODULE_FindModule(libname))) + if((pwm = MODULE_FindModule(filename))) { if(!(pwm->flags & WINE_MODREF_MARKER)) pwm->refCount++; @@ -1274,12 +1311,13 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS; fixup_imports( pwm ); } - TRACE("Already loaded module '%s' at 0x%08x, count=%d, \n", libname, pwm->module, pwm->refCount); + TRACE("Already loaded module '%s' at 0x%08x, count=%d, \n", filename, pwm->module, pwm->refCount); LeaveCriticalSection(&PROCESS_Current()->crit_section); + HeapFree ( GetProcessHeap(), 0, filename ); return pwm; } - plo = MODULE_GetLoadOrder(libname); + plo = MODULE_GetLoadOrder(filename, TRUE); for(i = 0; i < MODULE_LOADORDER_NTYPES; i++) { @@ -1287,25 +1325,25 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) switch(plo->loadorder[i]) { case MODULE_LOADORDER_DLL: - TRACE("Trying native dll '%s'\n", libname); - pwm = PE_LoadLibraryExA(libname, flags); + TRACE("Trying native dll '%s'\n", filename); + pwm = PE_LoadLibraryExA(filename, flags); break; case MODULE_LOADORDER_ELFDLL: - TRACE("Trying elfdll '%s'\n", libname); - if (!(pwm = BUILTIN32_LoadLibraryExA(libname, flags))) - pwm = ELFDLL_LoadLibraryExA(libname, flags); + TRACE("Trying elfdll '%s'\n", filename); + if (!(pwm = BUILTIN32_LoadLibraryExA(filename, flags))) + pwm = ELFDLL_LoadLibraryExA(filename, flags); break; case MODULE_LOADORDER_SO: - TRACE("Trying so-library '%s'\n", libname); - if (!(pwm = BUILTIN32_LoadLibraryExA(libname, flags))) - pwm = ELF_LoadLibraryExA(libname, flags); + TRACE("Trying so-library '%s'\n", filename); + if (!(pwm = BUILTIN32_LoadLibraryExA(filename, flags))) + pwm = ELF_LoadLibraryExA(filename, flags); break; case MODULE_LOADORDER_BI: - TRACE("Trying built-in '%s'\n", libname); - pwm = BUILTIN32_LoadLibraryExA(libname, flags); + TRACE("Trying built-in '%s'\n", filename); + pwm = BUILTIN32_LoadLibraryExA(filename, flags); break; default: @@ -1320,7 +1358,7 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) if(pwm) { /* Initialize DLL just loaded */ - TRACE("Loaded module '%s' at 0x%08x, \n", libname, pwm->module); + TRACE("Loaded module '%s' at 0x%08x, \n", filename, pwm->module); /* Set the refCount here so that an attach failure will */ /* decrement the dependencies through the MODULE_FreeLibrary call. */ @@ -1328,6 +1366,7 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) LeaveCriticalSection(&PROCESS_Current()->crit_section); SetLastError( err ); /* restore last error */ + HeapFree ( GetProcessHeap(), 0, filename ); return pwm; } @@ -1335,8 +1374,10 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) break; } - WARN("Failed to load module '%s'; error=0x%08lx, \n", libname, GetLastError()); LeaveCriticalSection(&PROCESS_Current()->crit_section); + error: + WARN("Failed to load module '%s'; error=0x%08lx, \n", filename, GetLastError()); + HeapFree ( GetProcessHeap(), 0, filename ); return NULL; } diff --git a/loader/ne/module.c b/loader/ne/module.c index 565db3b5e7f..15a3dc1b2f9 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -912,7 +912,7 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ int i; module_loadorder_t *plo; - plo = MODULE_GetLoadOrder(libname); + plo = MODULE_GetLoadOrder(libname, FALSE); for(i = 0; i < MODULE_LOADORDER_NTYPES; i++) { diff --git a/loader/pe_image.c b/loader/pe_image.c index 9c53fe4cda7..9380f986f1f 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -702,19 +702,14 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) { HMODULE hModule32; WINE_MODREF *wm; - char filename[256]; HANDLE hFile; - - /* Search for and open PE file */ - if ( SearchPathA( NULL, name, ".DLL", - sizeof(filename), filename, NULL ) == 0 ) return NULL; - hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, + hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, -1 ); if ( hFile == INVALID_HANDLE_VALUE ) return NULL; /* Load PE module */ - hModule32 = PE_LoadImage( hFile, filename, flags ); + hModule32 = PE_LoadImage( hFile, name, flags ); if (!hModule32) { CloseHandle( hFile ); @@ -722,9 +717,9 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) } /* Create 32-bit MODREF */ - if ( !(wm = PE_CreateModule( hModule32, filename, flags, -1, FALSE )) ) + if ( !(wm = PE_CreateModule( hModule32, name, flags, -1, FALSE )) ) { - ERR( "can't load %s\n", filename ); + ERR( "can't load %s\n", name ); CloseHandle( hFile ); SetLastError( ERROR_OUTOFMEMORY ); return NULL; diff --git a/misc/options.c b/misc/options.c index 9c1b576759b..e81fefd05d5 100644 --- a/misc/options.c +++ b/misc/options.c @@ -130,13 +130,16 @@ static void do_dll( const char *arg ) { if (Options.dllFlags) { - /* don't overwrite previous value. Should we - * automatically add the ',' between multiple DLLs ? - */ - MESSAGE("Only one -dll flag is allowed. Use ',' between multiple DLLs\n"); - ExitProcess(1); + Options.dllFlags = (char *) realloc ( Options.dllFlags, + strlen ( Options.dllFlags ) + strlen ( arg ) + 2 ); + if ( !Options.dllFlags ) out_of_memory(); + strcat ( Options.dllFlags, "+" ); + strcat ( Options.dllFlags, arg ); + } + else + { + Options.dllFlags = xstrdup( arg ); } - Options.dllFlags = xstrdup( arg ); } static void do_language( const char *arg ) diff --git a/relay32/builtin32.c b/relay32/builtin32.c index 3f1e93eacda..c3851f2a07f 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -269,8 +269,9 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) int i; /* Fix the name in case we have a full path and extension */ - if ((p = strrchr( path, '\\' ))) path = p + 1; - lstrcpynA( dllname, path, sizeof(dllname) ); + if ((p = strrchr( path, '\\' ))) p++; + else p = (char *)path; + lstrcpynA( dllname, p, sizeof(dllname) ); p = strrchr( dllname, '.' ); if (!p) strcat( dllname, ".dll" ); @@ -295,7 +296,7 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) if (!(module = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL; /* Create 32-bit MODREF */ - if ( !(wm = PE_CreateModule( module, dllname, flags, -1, TRUE )) ) + if ( !(wm = PE_CreateModule( module, path, flags, -1, TRUE )) ) { ERR( "can't load %s\n", path ); SetLastError( ERROR_OUTOFMEMORY );