diff --git a/dlls/kernel/ne_module.c b/dlls/kernel/ne_module.c index 6b5ff076863..08b62d8b9e7 100644 --- a/dlls/kernel/ne_module.c +++ b/dlls/kernel/ne_module.c @@ -47,6 +47,7 @@ #include "builtin16.h" #include "stackframe.h" #include "excpt.h" +#include "wine/unicode.h" #include "wine/exception.h" #include "wine/debug.h" @@ -1201,7 +1202,18 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ loadorder[0] = LOADORDER_BI; loadorder[1] = LOADORDER_INVALID; } - else MODULE_GetLoadOrder(loadorder, basename, FALSE); + else + { + WCHAR buffer[MAX_PATH], *p; + + if (!GetModuleFileNameW( 0, buffer, MAX_PATH )) p = NULL; + else + { + if ((p = strrchrW( buffer, '\\' ))) p++; + else p = buffer; + } + MODULE_GetLoadOrder(loadorder, p, basename, FALSE); + } for(i = 0; i < LOADORDER_NTYPES; i++) { diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index 09bc9d164e2..2e1f1f344b2 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -185,7 +185,7 @@ static HANDLE open_exe_file( const char *name ) name = buffer; } - MODULE_GetLoadOrder( loadorder, name, TRUE ); + MODULE_GetLoadOrder( loadorder, NULL, name, TRUE ); for(i = 0; i < LOADORDER_NTYPES; i++) { @@ -246,7 +246,7 @@ static BOOL find_exe_file( const char *name, char *buffer, int buflen, HANDLE *h return FALSE; } - MODULE_GetLoadOrder( loadorder, buffer, TRUE ); + MODULE_GetLoadOrder( loadorder, NULL, buffer, TRUE ); for(i = 0; i < LOADORDER_NTYPES; i++) { diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 67c59179941..c2e39ef971f 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -12,7 +12,6 @@ C_SRCS = \ $(TOPOBJDIR)/files/drive.c \ $(TOPOBJDIR)/files/file.c \ $(TOPOBJDIR)/files/smb.c \ - $(TOPOBJDIR)/loader/loadorder.c \ $(TOPOBJDIR)/loader/module.c \ $(TOPOBJDIR)/loader/task.c \ $(TOPOBJDIR)/loader/ne/module.c \ @@ -42,6 +41,7 @@ C_SRCS = \ heap.c \ large_int.c \ loader.c \ + loadorder.c \ misc.c \ nt.c \ om.c \ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 1b2b01c3966..a0cc743cdc8 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1263,6 +1263,7 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm ) LPSTR filename; const char *filetype = ""; DWORD found; + WINE_MODREF *main_exe; BOOL allocated_libdir = FALSE; static LPCSTR libdir = NULL; /* See above */ NTSTATUS nts = STATUS_NO_SUCH_FILE; @@ -1343,7 +1344,8 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm ) return STATUS_SUCCESS; } - MODULE_GetLoadOrder( loadorder, filename, TRUE); + main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress ); + MODULE_GetLoadOrder( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE); for (i = 0; i < LOADORDER_NTYPES; i++) { diff --git a/loader/loadorder.c b/dlls/ntdll/loadorder.c similarity index 72% rename from loader/loadorder.c rename to dlls/ntdll/loadorder.c index 672fd359d8d..ab7c9d4c758 100644 --- a/loader/loadorder.c +++ b/dlls/ntdll/loadorder.c @@ -1,7 +1,8 @@ /* - * Module/Library loadorder + * Dlls load order support * * Copyright 1999 Bertho Stultiens + * Copyright 2003 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,6 +34,7 @@ #include "winternl.h" #include "file.h" #include "module.h" +#include "ntdll_misc.h" #include "wine/debug.h" #include "wine/unicode.h" @@ -109,7 +111,8 @@ static const enum loadorder_type default_path_loadorder[LOADORDER_NTYPES] = LOADORDER_DLL, LOADORDER_BI, 0 }; -static struct loadorder_list cmdline_list; +static int init_done; +static struct loadorder_list env_list; /*************************************************************************** @@ -125,46 +128,6 @@ static int cmp_sort_func(const void *s1, const void *s2) } -/*************************************************************************** - * get_tok (internal, static) - * - * strtok wrapper for non-destructive buffer writing. - * NOTE: strtok is not reentrant and therefore this code is neither. - */ -static char *get_tok(const char *str, const char *delim) -{ - static char *buf = NULL; - char *cptr; - - if(!str && !buf) - return NULL; - - if(str && buf) - { - HeapFree(GetProcessHeap(), 0, buf); - buf = NULL; - } - - if(str && !buf) - { - buf = HeapAlloc(GetProcessHeap(), 0, strlen(str)+1); - strcpy( buf, str ); - cptr = strtok(buf, delim); - } - else - { - cptr = strtok(NULL, delim); - } - - if(!cptr) - { - HeapFree(GetProcessHeap(), 0, buf); - buf = NULL; - } - return cptr; -} - - /*************************************************************************** * get_basename * @@ -208,153 +171,172 @@ static const char *debugstr_loadorder( enum loadorder_type lo[] ) /*************************************************************************** - * ParseLoadOrder (internal, static) + * append_load_order + * + * Append a load order to the list if necessary. + */ +static void append_load_order(enum loadorder_type lo[], enum loadorder_type append) +{ + int i; + + for (i = 0; i < LOADORDER_NTYPES; i++) + { + if (lo[i] == LOADORDER_INVALID) /* append it here */ + { + lo[i++] = append; + lo[i] = LOADORDER_INVALID; + return; + } + if (lo[i] == append) return; /* already in the list */ + } + assert(0); /* cannot get here */ +} + + +/*************************************************************************** + * parse_load_order * * Parses the loadorder options from the configuration and puts it into * a structure. */ -static BOOL ParseLoadOrder(char *order, enum loadorder_type lo[]) +static void parse_load_order( const char *order, enum loadorder_type lo[] ) { - static int warn; - char *cptr; - int n = 0; - - cptr = get_tok(order, ", \t"); - while(cptr) - { - enum loadorder_type type = LOADORDER_INVALID; - - if(n >= LOADORDER_NTYPES-1) - { - ERR("More than existing %d module-types specified, rest ignored\n", LOADORDER_NTYPES-1); - break; - } - - switch(*cptr) - { - case 'N': /* Native */ - case 'n': type = LOADORDER_DLL; break; - - case 'S': /* So */ - case 's': - if (!warn++) MESSAGE("Load order 'so' no longer supported, ignored\n"); - break; - - case 'B': /* Builtin */ - case 'b': type = LOADORDER_BI; break; - - default: - ERR("Invalid load order module-type '%s', ignored\n", cptr); - } - - if(type != LOADORDER_INVALID) lo[n++] = type; - cptr = get_tok(NULL, ", \t"); - } - lo[n] = LOADORDER_INVALID; - return TRUE; + lo[0] = LOADORDER_INVALID; + while (*order) + { + order += strspn( order, ", \t" ); + switch(*order) + { + case 'N': /* Native */ + case 'n': + append_load_order( lo, LOADORDER_DLL ); + break; + case 'B': /* Builtin */ + case 'b': + append_load_order( lo, LOADORDER_BI ); + break; + } + order += strcspn( order, ", \t" ); + } } /*************************************************************************** - * AddLoadOrder (internal, static) + * add_load_order * - * Adds an entry in the list of command-line overrides. + * Adds an entry in the list of environment overrides. */ -static BOOL AddLoadOrder(module_loadorder_t *plo) +static void add_load_order( const module_loadorder_t *plo ) { - int i; + int i; - /* TRACE(module, "'%s' -> %08lx\n", plo->modulename, *(DWORD *)(plo->loadorder)); */ + for(i = 0; i < env_list.count; i++) + { + if(!cmp_sort_func(plo, &env_list.order[i] )) + { + /* replace existing option */ + memcpy( env_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder)); + return; + } + } - for(i = 0; i < cmdline_list.count; i++) - { - if(!cmp_sort_func(plo, &cmdline_list.order[i] )) - { - /* replace existing option */ - memcpy( cmdline_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder)); - return TRUE; - } - } - - if (i >= cmdline_list.alloc) - { - /* No space in current array, make it larger */ - cmdline_list.alloc += LOADORDER_ALLOC_CLUSTER; - cmdline_list.order = HeapReAlloc(GetProcessHeap(), 0, cmdline_list.order, - cmdline_list.alloc * sizeof(module_loadorder_t)); - if(!cmdline_list.order) - { - MESSAGE("Virtual memory exhausted\n"); - exit(1); - } - } - memcpy(cmdline_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder)); - cmdline_list.order[i].modulename = HeapAlloc(GetProcessHeap(), 0, strlen(plo->modulename)+1); - strcpy( (char *)cmdline_list.order[i].modulename, plo->modulename ); - cmdline_list.count++; - return TRUE; + if (i >= env_list.alloc) + { + /* No space in current array, make it larger */ + env_list.alloc += LOADORDER_ALLOC_CLUSTER; + if (env_list.order) + env_list.order = RtlReAllocateHeap(GetProcessHeap(), 0, env_list.order, + env_list.alloc * sizeof(module_loadorder_t)); + else + env_list.order = RtlAllocateHeap(GetProcessHeap(), 0, + env_list.alloc * sizeof(module_loadorder_t)); + if(!env_list.order) + { + MESSAGE("Virtual memory exhausted\n"); + exit(1); + } + } + memcpy(env_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder)); + env_list.order[i].modulename = RtlAllocateHeap(GetProcessHeap(), 0, strlen(plo->modulename)+1); + strcpy( (char *)env_list.order[i].modulename, plo->modulename ); + env_list.count++; } /*************************************************************************** - * AddLoadOrderSet (internal, static) + * add_load_order_set * * Adds a set of entries in the list of command-line overrides from the key parameter. */ -static BOOL AddLoadOrderSet(char *key, char *order) +static void add_load_order_set( char *entry ) { - module_loadorder_t ldo; - char *cptr; + module_loadorder_t ldo; + char *end = strchr( entry, '=' ); - /* Parse the loadorder before the rest because strtok is not reentrant */ - if(!ParseLoadOrder(order, ldo.loadorder)) - return FALSE; + if (!end) return; + *end++ = 0; + parse_load_order( end, ldo.loadorder ); - cptr = get_tok(key, ", \t"); - while(cptr) + while (*entry) + { + entry += strspn( entry, ", \t" ); + end = entry + strcspn( entry, ", \t" ); + if (*end) *end++ = 0; + if (*entry) { - char *ext = strrchr(cptr, '.'); - if(ext && !FILE_strcasecmp( ext, ".dll" )) *ext = 0; - ldo.modulename = cptr; - if(!AddLoadOrder(&ldo)) return FALSE; - cptr = get_tok(NULL, ", \t"); + char *ext = strrchr(entry, '.'); + if(ext && !FILE_strcasecmp( ext, ".dll" )) *ext = 0; + ldo.modulename = entry; + add_load_order( &ldo ); + entry = end; } - return TRUE; + } } /*************************************************************************** - * MODULE_AddLoadOrderOption - * - * The commandline option is in the form: - * name[,name,...]=native[,b,...] + * init_load_order */ -void MODULE_AddLoadOrderOption( const char *option ) +static void init_load_order(void) { - char *value, *key = HeapAlloc(GetProcessHeap(), 0, strlen(option)+1); + const char *order = getenv( "WINEDLLOVERRIDES" ); + char *str, *entry, *next; - strcpy( key, option ); - if (!(value = strchr(key, '='))) goto error; - *value++ = '\0'; + init_done = 1; + if (!order) return; - TRACE("Commandline override '%s' = '%s'\n", key, value); + if (!strcmp( order, "help" )) + { + MESSAGE( "Syntax:\n" + " WINEDLLOVERRIDES=\"entry;entry;entry...\"\n" + " where each entry is of the form:\n" + " module[,module...]={native|builtin}[,{b|n}]\n" + "\n" + " Only the first letter of the override (native or builtin)\n" + " is significant.\n\n" + "Example:\n" + " WINEDLLOVERRIDES=\"comdlg32,commdlg=n,b;shell,shell32=b\"\n" ); + exit(0); + } - if (!AddLoadOrderSet(key, value)) goto error; - HeapFree(GetProcessHeap(), 0, key); + str = RtlAllocateHeap( GetProcessHeap(), 0, strlen(order)+1 ); + strcpy( str, order ); + entry = str; + while (*entry) + { + while (*entry && *entry == ';') entry++; + if (!*entry) break; + next = strchr( entry, ';' ); + if (next) *next++ = 0; + else next = entry + strlen(entry); + add_load_order_set( entry ); + entry = next; + } + RtlFreeHeap( GetProcessHeap(), 0, str ); /* sort the array for quick lookup */ - qsort(cmdline_list.order, cmdline_list.count, sizeof(cmdline_list.order[0]), cmp_sort_func); - return; - - error: - MESSAGE( "Syntax: -dll name[,name[,...]]={native|so|builtin}[,{n|s|b}[,...]]\n" - " - 'name' is the name of any dll without extension\n" - " - the order of loading (native, so and builtin) can be abbreviated\n" - " with the first letter\n" - " - the option can be specified multiple times\n" - " Example:\n" - " -dll comdlg32,commdlg=n -dll shell,shell32=b\n" ); - ExitProcess(1); + if (env_list.count) + qsort(env_list.order, env_list.count, sizeof(env_list.order[0]), cmp_sort_func); } @@ -382,27 +364,29 @@ static BOOL get_list_load_order( const char *module, const struct loadorder_list * * Open the registry key to the app-specific DllOverrides list. */ -static HKEY open_app_key( const char *module ) +static HKEY open_app_key( const WCHAR *app_name, const char *module ) { OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; - HKEY hkey, appkey; - char buffer[MAX_PATH+16], *appname; + HKEY hkey; + WCHAR *str; static const WCHAR AppDefaultsW[] = {'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', 'W','i','n','e','\\', 'W','i','n','e','\\', 'C','o','n','f','i','g','\\', - 'A','p','p','D','e','f','a','u','l','t','s',0}; + 'A','p','p','D','e','f','a','u','l','t','s','\\',0}; + static const WCHAR DllOverridesW[] = {'\\','D','l','l','O','v','e','r','r','i','d','e','s',0}; - if (!GetModuleFileNameA( 0, buffer, MAX_PATH )) - { - WARN( "could not get module file name loading %s\n", module ); - return 0; - } - appname = (char *)get_basename( buffer ); + str = RtlAllocateHeap( GetProcessHeap(), 0, + sizeof(AppDefaultsW) + sizeof(DllOverridesW) + + strlenW(app_name) * sizeof(WCHAR) ); + if (!str) return 0; + strcpyW( str, AppDefaultsW ); + strcatW( str, app_name ); + strcatW( str, DllOverridesW ); - TRACE( "searching '%s' in AppDefaults\\%s\\DllOverrides\n", module, appname ); + TRACE( "searching '%s' in %s\n", module, debugstr_w(str) ); attr.Length = sizeof(attr); attr.RootDirectory = 0; @@ -410,18 +394,11 @@ static HKEY open_app_key( const char *module ) attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - RtlInitUnicodeString( &nameW, AppDefaultsW ); + RtlInitUnicodeString( &nameW, str ); - if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) return 0; - attr.RootDirectory = hkey; - - /* open AppDefaults\\appname\\DllOverrides key */ - strcat( appname, "\\DllOverrides" ); - RtlCreateUnicodeStringFromAsciiz( &nameW, appname ); - if (NtOpenKey( &appkey, KEY_ALL_ACCESS, &attr )) appkey = 0; - RtlFreeUnicodeString( &nameW ); - NtClose( hkey ); - return appkey; + if (NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) hkey = 0; + RtlFreeHeap( GetProcessHeap(), 0, str ); + return hkey; } @@ -501,7 +478,7 @@ BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename if (strlen(libname) >= size) return FALSE; /* too long */ if (strchr( libname, '/' )) /* need to convert slashes */ { - if (!(tmp = HeapAlloc( GetProcessHeap(), 0, strlen(libname)+1 ))) return FALSE; + if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, strlen(libname)+1 ))) return FALSE; strcpy( tmp, libname ); for (p = tmp; *p; p++) if (*p == '/') *p = '\\'; } @@ -512,7 +489,7 @@ BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename strcpy( filename, tmp ); ret = TRUE; } - if (tmp != libname) HeapFree( GetProcessHeap(), 0, tmp ); + if (tmp != libname) RtlFreeHeap( GetProcessHeap(), 0, tmp ); if (!ret) return FALSE; } else @@ -539,8 +516,11 @@ BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename * Any path is stripped from the path-argument and so are the extension * '.dll' and '.exe'. A lookup in the table can yield an override for * the specific dll. Otherwise the default load order is returned. + * + * FIXME: 'path' should be Unicode too. */ -void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const char *path, BOOL win32 ) +void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const WCHAR *app_name, + const char *path, BOOL win32 ) { static const WCHAR DllOverridesW[] = {'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', @@ -554,6 +534,8 @@ void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const char *path, BOO char *module, *basename; int len; + if (!init_done) init_load_order(); + TRACE("looking for %s\n", path); loadorder[0] = LOADORDER_INVALID; /* in case something bad happens below */ @@ -573,7 +555,7 @@ void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const char *path, BOO } if (!(len = strlen(path))) return; - if (!(module = HeapAlloc( GetProcessHeap(), 0, len + 2 ))) return; + if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, len + 2 ))) return; strcpy( module+1, path ); /* reserve module[0] for the wildcard char */ if (len >= 4) @@ -582,21 +564,24 @@ void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const char *path, BOO if (!FILE_strcasecmp( ext, ".dll" )) *ext = 0; } - /* check command-line first */ - if (get_list_load_order( module+1, &cmdline_list, loadorder )) + /* check environment variable first */ + if (get_list_load_order( module+1, &env_list, loadorder )) { - TRACE( "got cmdline %s for %s\n", + TRACE( "got environment %s for %s\n", debugstr_loadorder(loadorder), debugstr_a(path) ); goto done; } /* then explicit module name in AppDefaults */ - app_key = open_app_key( module+1 ); - if (app_key && get_registry_value( app_key, module+1, loadorder )) + if (app_name) { - TRACE( "got app defaults %s for %s\n", - debugstr_loadorder(loadorder), debugstr_a(path) ); - goto done; + app_key = open_app_key( app_name, module+1 ); + if (app_key && get_registry_value( app_key, module+1, loadorder )) + { + TRACE( "got app defaults %s for %s\n", + debugstr_loadorder(loadorder), debugstr_a(path) ); + goto done; + } } /* then explicit module name in standard section */ @@ -681,5 +666,5 @@ void MODULE_GetLoadOrder( enum loadorder_type loadorder[], const char *path, BOO done: if (app_key) NtClose( app_key ); - HeapFree( GetProcessHeap(), 0, module ); + RtlFreeHeap( GetProcessHeap(), 0, module ); } diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index aad260b545e..1164bb000e9 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -51,6 +51,7 @@ static inline HANDLE ntdll_get_process_heap(void) { return NtCurrentTeb()->Peb->ProcessHeap; } +#define GetProcessHeap() ntdll_get_process_heap() static inline RTL_USER_PROCESS_PARAMETERS* ntdll_get_process_pmts(void) { diff --git a/documentation/wine.man.in b/documentation/wine.man.in index decee800b61..63c54c8e14a 100644 --- a/documentation/wine.man.in +++ b/documentation/wine.man.in @@ -104,49 +104,6 @@ For more information on debugging messages, see the file .I documentation/running.sgml in the source distribution (FIXME: outdated). .RE -.TP -.I --dll name[,name[,...]]={native|builtin}[,{n|b}[,...]] -Selects the override type and load order of dll used in the loading -process for any dll. The default is set in the configuration -file. There are currently three types of libraries that can be loaded -into a process' address space: Native windows dlls ( -.I native -), -.B wine -internal dlls ( -.I builtin -). The type may be abbreviated with the first letter of the type ( -.I n, b -). Each sequence of orders must be separated by commas. -.br -Each dll may have its own specific load order. The load order -determines which version of the dll is attempted to be loaded into the -address space. If the first fails, then the next is tried and so -on. 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 -.I --dll comdlg32,commdlg=n,b -.br -Try to load comdlg32 and commdlg as native windows dll first and try -the builtin version if the native load fails. -.br -.I --dll shell,shell32=n --dll c:\(rs\(rsfoo\(rs\(rsbar\(rs\(rsbaz=b -.br -Try to load the libraries shell and shell32 as native windows dlls. Furthermore, if -an application request to load c:\(rsfoo\(rsbar\(rsbaz.dll load the builtin library baz. -.br -.I --dll comdlg32,commdlg=b,n --dll shell,shell32=b --dll comctl32,commctrl=n -.br -Try to load comdlg32 and commdlg as builtin first and try the native version -if the builtin load fails; load shell32/shell always as builtin and -comctl32/commctrl always as native. -.br -Note: It is wise to keep dll pairs (comdlg32/commdlg, shell/shell32, etc.) -having exactly the same load order. This will prevent mismatches at runtime. -See also configuration file format below. .PD 1 .SH PROGRAM/ARGUMENTS The program name may be specified in DOS format ( @@ -181,7 +138,7 @@ by For example, if you want to execute .B wine with the options -.I --dll riched32=n +.I --debugmsg +module and if .B wine should run the program @@ -191,7 +148,7 @@ with the arguments , then you could use the following command line to invoke .B wine: .PP -.I wine --dll riched32=n -- myapp.exe --display 3d somefile +.I wine --debugmsg +module -- myapp.exe --display 3d somefile .PP Note that in contrast to previous versions of .B wine, @@ -255,14 +212,61 @@ addition to any directory specified in Wine will also look in .B @dlldir@. .TP +.I WINEDLLOVERRIDES +Defines the override type and load order of dlls used in the loading +process for any dll. The default is set in the configuration +file. There are currently two types of libraries that can be loaded +into a process' address space: Native windows dlls ( +.I native +), +.B wine +internal dlls ( +.I builtin +). The type may be abbreviated with the first letter of the type ( +.I n, b +). Each sequence of orders must be separated by commas. +.br +Each dll may have its own specific load order. The load order +determines which version of the dll is attempted to be loaded into the +address space. If the first fails, then the next is tried and so +on. Multiple libraries with the same load order can be separated with +commas. It is also possible to use specify different loadorders for +different libraries by separating the entries by ";". +.br +Examples: +.RS +.TP +WINEDLLOVERRIDES="comdlg32,commdlg=n,b" +.br +Try to load comdlg32 and commdlg as native windows dll first and try +the builtin version if the native load fails. +.TP +WINEDLLOVERRIDES="shell,shell32=n;c:\(rs\(rsfoo\(rs\(rsbar\(rs\(rsbaz=b" +.br +Try to load the libraries shell and shell32 as native windows dlls. Furthermore, if +an application request to load c:\(rsfoo\(rsbar\(rsbaz.dll load the builtin library baz. +.TP +WINEDLLOVERRIDES="comdlg32,commdlg=b,n;shell,shell32=b;comctl32,commctrl=n" +.br +Try to load comdlg32 and commdlg as builtin first and try the native version +if the builtin load fails; load shell32/shell always as builtin and +comctl32/commctrl always as native. +.br +Note: It is wise to keep dll pairs (comdlg32/commdlg, shell/shell32, etc.) +having exactly the same load order. This will prevent mismatches at runtime. +See also configuration file format below. +.RE +.TP .I DISPLAY Specifies the X11 display to use. .SH CONFIGURATION FILE .B wine expects a configuration file ( .I $WINEPREFIX/config -(~/.wine/config) -), which must conform to the format specified in the +or +.I ~/.wine/config +if WINEPREFIX is not set), which must conform to the format specified +in the .BR wine.conf (5) man page. A sample configuration file is documentation/samples/config in the .B wine diff --git a/include/module.h b/include/module.h index 1b3ebc74fa5..46b006633cd 100644 --- a/include/module.h +++ b/include/module.h @@ -217,8 +217,8 @@ extern HRSRC PE_FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD); /* loader/loadorder.c */ extern BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename, UINT size ); -extern void MODULE_GetLoadOrder( enum loadorder_type plo[], const char *path, BOOL win32 ); -extern void MODULE_AddLoadOrderOption( const char *option ); +extern void MODULE_GetLoadOrder( enum loadorder_type plo[], const WCHAR *app_name, + const char *path, BOOL win32 ); /* relay32/builtin.c */ extern HMODULE BUILTIN32_LoadExeModule( HMODULE main ); diff --git a/misc/options.c b/misc/options.c index a323b080601..48691a197a5 100644 --- a/misc/options.c +++ b/misc/options.c @@ -56,6 +56,7 @@ static void out_of_memory(void) } static void do_debugmsg( const char *arg ); +static void do_dll( const char *arg ); static void do_help( const char *arg ); static void do_version( const char *arg ); @@ -63,8 +64,8 @@ static const struct option_descr option_table[] = { { "debugmsg", 0, 1, 1, do_debugmsg, "--debugmsg name Turn debugging-messages on or off" }, - { "dll", 0, 1, 1, MODULE_AddLoadOrderOption, - "--dll name Enable or disable built-in DLLs" }, + { "dll", 0, 1, 1, do_dll, + "--dll name This option is no longer supported" }, { "help", 'h', 0, 0, do_help, "--help,-h Show this help message" }, { "version", 'v', 0, 0, do_version, @@ -96,6 +97,14 @@ static void do_debugmsg( const char *arg ) } } +static void do_dll( const char *arg ) +{ + MESSAGE("The --dll option has been removed, you should use\n" + "the WINEDLLOVERRIDES environment variable instead.\n" + "To see a help message, run:\n" + " WINEDLLOVERRIDES=help wine \n"); + ExitProcess(1); +} static void remove_options( char *argv[], int pos, int count, int inherit ) { diff --git a/tools/runtest b/tools/runtest index 10032af257a..f2d16072e37 100755 --- a/tools/runtest +++ b/tools/runtest @@ -109,9 +109,9 @@ fi # set environment variables needed for Wine -if [ -n "$modules" ]; then - WINEOPTIONS="$WINEOPTIONS --dll $modules=b" - export WINEOPTIONS +if [ -n "$modules" ]; then + WINEDLLOVERRIDES="$WINEDLLOVERRIDES;$modules=b" + export WINEDLLOVERRIDES fi WINETEST_PLATFORM=${platform:-wine} export WINETEST_PLATFORM WINETEST_DEBUG