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:
parent
a877fdc4dc
commit
4107751dd3
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue