ntdll: Simplify loadorder code by using an enum instead of an array

to represent load order values.
Added a special value for default load order so that we can handle it
differently later on.
This commit is contained in:
Alexandre Julliard 2006-02-22 16:30:05 +01:00
parent a877fdc4dc
commit 4107751dd3
4 changed files with 93 additions and 136 deletions

View File

@ -34,7 +34,6 @@
#include "winnt.h"
#include "winternl.h"
#include "module.h"
#include "wine/exception.h"
#include "excpt.h"
#include "wine/library.h"
@ -1661,7 +1660,7 @@ overflow:
*/
static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
{
enum loadorder_type loadorder[LOADORDER_NTYPES];
enum loadorder loadorder;
WCHAR buffer[32];
WCHAR *filename;
ULONG size;
@ -1697,33 +1696,40 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
}
main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
MODULE_GetLoadOrderW( loadorder, main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename );
loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename );
nts = STATUS_DLL_NOT_FOUND;
switch(loadorder[0])
switch(loadorder)
{
case LOADORDER_DLL:
if (handle)
case LO_INVALID:
nts = STATUS_NO_MEMORY;
break;
case LO_DISABLED:
nts = STATUS_DLL_NOT_FOUND;
break;
case LO_NATIVE:
case LO_NATIVE_BUILTIN:
if (!handle) nts = STATUS_DLL_NOT_FOUND;
else
{
nts = load_native_dll( load_path, filename, handle, flags, pwm );
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 );
}
if (nts == STATUS_DLL_NOT_FOUND && loadorder[1] == LOADORDER_BI)
if (nts == STATUS_DLL_NOT_FOUND && loadorder == LO_NATIVE_BUILTIN)
nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
break;
case LOADORDER_BI:
case LO_BUILTIN:
case LO_BUILTIN_NATIVE:
case LO_DEFAULT: /* default is builtin,native */
nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
if (nts == STATUS_SUCCESS) break;
if (!handle) break; /* nothing else we can try */
/* file is not a builtin library, try without using the specified file */
nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
if (nts == STATUS_DLL_NOT_FOUND && loadorder[1] == LOADORDER_DLL)
if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN)
nts = load_native_dll( load_path, filename, handle, flags, pwm );
break;
default:
break;
}
if (nts == STATUS_SUCCESS)

View File

@ -30,7 +30,6 @@
#include "windef.h"
#include "winternl.h"
#include "ntdll_misc.h"
#include "module.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -42,7 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(module);
typedef struct module_loadorder
{
const WCHAR *modulename;
enum loadorder_type loadorder[LOADORDER_NTYPES];
enum loadorder loadorder;
} module_loadorder_t;
struct loadorder_list
@ -74,12 +73,6 @@ static const WCHAR default_builtins[][10] =
{ 'x','1','1','d','r','v',0 }
};
/* default if nothing else specified */
static const enum loadorder_type default_loadorder[LOADORDER_NTYPES] =
{
LOADORDER_BI, LOADORDER_DLL, 0
};
static const WCHAR separatorsW[] = {',',' ','\t',0};
static int init_done;
@ -142,47 +135,18 @@ static inline void remove_dll_ext( WCHAR *ext )
*
* Return a loadorder in printable form.
*/
static const char *debugstr_loadorder( enum loadorder_type lo[] )
static const char *debugstr_loadorder( enum loadorder lo )
{
int i;
char buffer[LOADORDER_NTYPES*3+1];
buffer[0] = 0;
for(i = 0; i < LOADORDER_NTYPES; i++)
switch(lo)
{
if (lo[i] == LOADORDER_INVALID) break;
switch(lo[i])
{
case LOADORDER_DLL: strcat( buffer, "n," ); break;
case LOADORDER_BI: strcat( buffer, "b," ); break;
default: strcat( buffer, "?," ); break;
}
case LO_DISABLED: return "";
case LO_NATIVE: return "n";
case LO_BUILTIN: return "b";
case LO_NATIVE_BUILTIN: return "n,b";
case LO_BUILTIN_NATIVE: return "b,n";
case LO_DEFAULT: return "default";
default: return "??";
}
if (buffer[0]) buffer[strlen(buffer)-1] = 0;
return debugstr_a(buffer);
}
/***************************************************************************
* 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 */
}
@ -192,25 +156,29 @@ static void append_load_order(enum loadorder_type lo[], enum loadorder_type appe
* Parses the loadorder options from the configuration and puts it into
* a structure.
*/
static void parse_load_order( const WCHAR *order, enum loadorder_type lo[] )
static enum loadorder parse_load_order( const WCHAR *order )
{
lo[0] = LOADORDER_INVALID;
enum loadorder ret = LO_DISABLED;
while (*order)
{
order += strspnW( order, separatorsW );
switch(*order)
{
case 'N': /* Native */
case 'N': /* native */
case 'n':
append_load_order( lo, LOADORDER_DLL );
if (ret == LO_DISABLED) ret = LO_NATIVE;
else if (ret == LO_BUILTIN) return LO_BUILTIN_NATIVE;
break;
case 'B': /* Builtin */
case 'B': /* builtin */
case 'b':
append_load_order( lo, LOADORDER_BI );
if (ret == LO_DISABLED) ret = LO_BUILTIN;
else if (ret == LO_NATIVE) return LO_NATIVE_BUILTIN;
break;
}
order += strcspnW( order, separatorsW );
}
return ret;
}
@ -228,7 +196,7 @@ static void add_load_order( const module_loadorder_t *plo )
if(!cmp_sort_func(plo, &env_list.order[i] ))
{
/* replace existing option */
memcpy( env_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder));
env_list.order[i].loadorder = plo->loadorder;
return;
}
}
@ -249,7 +217,7 @@ static void add_load_order( const module_loadorder_t *plo )
exit(1);
}
}
memcpy(env_list.order[i].loadorder, plo->loadorder, sizeof(plo->loadorder));
env_list.order[i].loadorder = plo->loadorder;
env_list.order[i].modulename = plo->modulename;
env_list.count++;
}
@ -267,7 +235,7 @@ static void add_load_order_set( WCHAR *entry )
if (!end) return;
*end++ = 0;
parse_load_order( end, ldo.loadorder );
ldo.loadorder = parse_load_order( end );
while (*entry)
{
@ -339,16 +307,16 @@ static void init_load_order(void)
*
* Get the load order for a given module from the WINEDLLOVERRIDES environment variable.
*/
static inline BOOL get_env_load_order( const WCHAR *module, enum loadorder_type lo[] )
static inline enum loadorder get_env_load_order( const WCHAR *module )
{
module_loadorder_t tmp, *res = NULL;
module_loadorder_t tmp, *res;
tmp.modulename = module;
/* some bsearch implementations (Solaris) are buggy when the number of items is 0 */
if (env_list.count &&
(res = bsearch(&tmp, env_list.order, env_list.count, sizeof(env_list.order[0]), cmp_sort_func)))
memcpy( lo, res->loadorder, sizeof(res->loadorder) );
return (res != NULL);
return res->loadorder;
return LO_INVALID;
}
@ -357,15 +325,13 @@ static inline BOOL get_env_load_order( const WCHAR *module, enum loadorder_type
*
* Get the load order for a given module from the default list.
*/
static inline BOOL get_default_load_order( const WCHAR *module, enum loadorder_type lo[] )
static inline enum loadorder get_default_load_order( const WCHAR *module )
{
const int count = sizeof(default_builtins) / sizeof(default_builtins[0]);
if (!bsearch( module, default_builtins, count, sizeof(default_builtins[0]), strcmp_func ))
return FALSE;
lo[0] = LOADORDER_BI;
lo[1] = LOADORDER_INVALID;
TRACE( "got compiled-in default %s for %s\n", debugstr_loadorder(lo), debugstr_w(module) );
return TRUE;
TRACE( "got compiled-in builtin default for %s\n", debugstr_w(module) );
return LO_BUILTIN;
}
@ -451,7 +417,7 @@ static HANDLE get_app_key( const WCHAR *app_name )
*
* Load the registry loadorder value for a given module.
*/
static BOOL get_registry_value( HANDLE hkey, const WCHAR *module, enum loadorder_type lo[] )
static enum loadorder get_registry_value( HANDLE hkey, const WCHAR *module )
{
UNICODE_STRING valueW;
char buffer[80];
@ -463,36 +429,10 @@ static BOOL get_registry_value( HANDLE hkey, const WCHAR *module, enum loadorder
if ((ret = !NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation,
buffer, sizeof(buffer), &count )))
{
int i, n = 0;
WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)buffer)->Data;
while (*str)
{
enum loadorder_type type = LOADORDER_INVALID;
while (*str == ',' || isspaceW(*str)) str++;
if (!*str) break;
switch(tolowerW(*str))
{
case 'n': type = LOADORDER_DLL; break;
case 'b': type = LOADORDER_BI; break;
case 's': break; /* no longer supported, ignore */
case 0: break; /* end of string */
default:
ERR("Invalid load order module-type %s, ignored\n", debugstr_w(str));
break;
}
if (type != LOADORDER_INVALID)
{
for (i = 0; i < n; i++) if (lo[i] == type) break; /* already specified */
if (i == n) lo[n++] = type;
}
while (*str && *str != ',' && !isspaceW(*str)) str++;
}
lo[n] = LOADORDER_INVALID;
return parse_load_order( str );
}
return ret;
return LO_INVALID;
}
@ -504,44 +444,43 @@ static BOOL get_registry_value( HANDLE hkey, const WCHAR *module, enum loadorder
* 2. The per-application DllOverrides key
* 3. The standard DllOverrides key
*/
static BOOL get_load_order_value( HANDLE std_key, HANDLE app_key, const WCHAR *module,
enum loadorder_type loadorder[] )
static enum loadorder get_load_order_value( HANDLE std_key, HANDLE app_key, const WCHAR *module )
{
if (get_env_load_order( module, loadorder ))
enum loadorder ret;
if ((ret = get_env_load_order( module )) != LO_INVALID)
{
TRACE( "got environment %s for %s\n",
debugstr_loadorder(loadorder), debugstr_w(module) );
return TRUE;
TRACE( "got environment %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
return ret;
}
if (app_key && get_registry_value( app_key, module, loadorder ))
if (app_key && ((ret = get_registry_value( app_key, module )) != LO_INVALID))
{
TRACE( "got app defaults %s for %s\n",
debugstr_loadorder(loadorder), debugstr_w(module) );
return TRUE;
TRACE( "got app defaults %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
return ret;
}
if (std_key && get_registry_value( std_key, module, loadorder ))
if (std_key && ((ret = get_registry_value( std_key, module )) != LO_INVALID))
{
TRACE( "got standard key %s for %s\n",
debugstr_loadorder(loadorder), debugstr_w(module) );
return TRUE;
TRACE( "got standard key %s for %s\n", debugstr_loadorder(ret), debugstr_w(module) );
return ret;
}
return FALSE;
return ret;
}
/***************************************************************************
* MODULE_GetLoadOrderW (internal)
* get_load_order (internal)
*
* Return the loadorder of a module.
* The system directory and '.dll' extension is stripped from the path.
*/
void MODULE_GetLoadOrderW( enum loadorder_type loadorder[], const WCHAR *app_name,
const WCHAR *path )
enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path )
{
static const WCHAR wildcardW[] = {'*',0};
enum loadorder ret = LO_INVALID;
HANDLE std_key, app_key = 0;
WCHAR *module, *basename;
UNICODE_STRING path_str;
@ -553,8 +492,6 @@ void MODULE_GetLoadOrderW( enum loadorder_type loadorder[], const WCHAR *app_nam
TRACE("looking for %s\n", debugstr_w(path));
loadorder[0] = LOADORDER_INVALID; /* in case something bad happens below */
/* Strip path information if the module resides in the system directory
*/
RtlInitUnicodeString( &path_str, path );
@ -565,39 +502,39 @@ void MODULE_GetLoadOrderW( enum loadorder_type loadorder[], const WCHAR *app_nam
if (!strchrW( p, '\\' ) && !strchrW( p, '/' )) path = p;
}
if (!(len = strlenW(path))) return;
if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return;
if (!(len = strlenW(path))) return ret;
if (!(module = RtlAllocateHeap( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) return ret;
strcpyW( module+1, path ); /* reserve module[0] for the wildcard char */
basename = (WCHAR *)get_basename( module+1 );
if (len >= 4) remove_dll_ext( module + 1 + len - 4 );
/* first explicit module name */
if (get_load_order_value( std_key, app_key, module+1, loadorder ))
if ((ret = get_load_order_value( std_key, app_key, module+1 )) != LO_INVALID)
goto done;
/* then module basename preceded by '*' */
basename[-1] = '*';
if (get_load_order_value( std_key, app_key, basename-1, loadorder ))
if ((ret = get_load_order_value( std_key, app_key, basename-1 )) != LO_INVALID)
goto done;
/* then module basename without '*' (only if explicit path) */
if (basename != module+1 && get_load_order_value( std_key, app_key, basename, loadorder ))
if (basename != module+1 && ((ret = get_load_order_value( std_key, app_key, basename )) != LO_INVALID))
goto done;
/* then compiled-in defaults */
if (get_default_load_order( basename, loadorder ))
if ((ret = get_default_load_order( basename )) != LO_INVALID)
goto done;
/* then wildcard entry (only if no explicit path) */
if (basename == module+1 && get_load_order_value( std_key, app_key, wildcardW, loadorder ))
if (basename == module+1 && ((ret = get_load_order_value( std_key, app_key, wildcardW )) != LO_INVALID))
goto done;
/* and last the hard-coded default */
memcpy( loadorder, default_loadorder, sizeof(default_loadorder) );
TRACE( "got hardcoded default %s for %s\n",
debugstr_loadorder(loadorder), debugstr_w(path) );
ret = LO_DEFAULT;
TRACE( "got hardcoded default %s for %s\n", debugstr_loadorder(ret), debugstr_w(path) );
done:
RtlFreeHeap( GetProcessHeap(), 0, module );
return ret;
}

View File

@ -1395,4 +1395,3 @@
# Wine dll separation hacks, these will go away, don't use them
#
@ cdecl MODULE_DllThreadAttach(ptr)
@ cdecl MODULE_GetLoadOrderW(ptr wstr wstr)

View File

@ -116,6 +116,21 @@ extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst,
extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen,
const char* defchar, int *used );
/* load order */
enum loadorder
{
LO_INVALID,
LO_DISABLED,
LO_NATIVE,
LO_BUILTIN,
LO_NATIVE_BUILTIN, /* native then builtin */
LO_BUILTIN_NATIVE, /* builtin then native */
LO_DEFAULT /* nothing specified, use default strategy */
};
extern enum loadorder get_load_order( const WCHAR *app_name, const WCHAR *path );
struct debug_info
{
char *str_pos; /* current position in strings buffer */