ntdll: Add a WINEBOOTSTRAPMODE environment variable to allow loading non-existent builtins.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50905
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-04-08 12:22:25 +02:00
parent 4f04994ef4
commit 446f7e3aa8
4 changed files with 36 additions and 24 deletions

View File

@ -1926,14 +1926,10 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name,
static void build_ntdll_module(void)
{
MEMORY_BASIC_INFORMATION meminfo;
FILE_BASIC_INFORMATION basic_info;
UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
WINE_MODREF *wm;
RtlInitUnicodeString( &nt_name, L"\\??\\C:\\windows\\system32\\ntdll.dll" );
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
is_prefix_bootstrap = NtQueryAttributesFile( &attr, &basic_info) != STATUS_SUCCESS;
NtQueryVirtualMemory( GetCurrentProcess(), build_ntdll_module, MemoryBasicInformation,
&meminfo, sizeof(meminfo), NULL );
wm = alloc_module( meminfo.AllocationBase, &nt_name, TRUE );
@ -2672,7 +2668,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
if (found_image)
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
else if (is_prefix_bootstrap && !wcspbrk( search, L":/\\" ))
else if (is_prefix_bootstrap && !contains_path( search ))
status = find_builtin_without_file( search, nt_name, pwm, mapping, image_info, id );
done:
@ -3498,10 +3494,14 @@ static void process_breakpoint(void)
static void load_global_options(void)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING name_str;
UNICODE_STRING name_str, val_str;
HANDLE hkey;
ULONG value;
RtlInitUnicodeString( &name_str, L"WINEBOOTSTRAPMODE" );
val_str.MaximumLength = 0;
is_prefix_bootstrap = RtlQueryEnvironmentVariable_U( NULL, &name_str, &val_str ) != STATUS_VARIABLE_NOT_FOUND;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &name_str;

View File

@ -64,6 +64,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(environ);
USHORT *uctable = NULL, *lctable = NULL;
SIZE_T startup_info_size = 0;
BOOL is_prefix_bootstrap = FALSE;
static const WCHAR bootstrapW[] = {'W','I','N','E','B','O','O','T','S','T','R','A','P','M','O','D','E'};
int main_argc = 0;
char **main_argv = NULL;
@ -1211,6 +1214,18 @@ static WCHAR *find_env_var( WCHAR *env, SIZE_T size, const WCHAR *name, SIZE_T n
return NULL;
}
static WCHAR *get_env_var( WCHAR *env, SIZE_T size, const WCHAR *name, SIZE_T namelen )
{
WCHAR *ret = NULL, *var = find_env_var( env, size, name, namelen );
if (var)
{
var += namelen + 1; /* skip name */
if ((ret = malloc( (wcslen(var) + 1) * sizeof(WCHAR) ))) wcscpy( ret, var );
}
return ret;
}
/* set an environment variable, replacing it if it exists */
static void set_env_var( WCHAR **env, SIZE_T *pos, SIZE_T *size,
const WCHAR *name, SIZE_T namelen, const WCHAR *value )
@ -1889,29 +1904,32 @@ static inline WCHAR *get_dos_path( WCHAR *nt_path )
*/
static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void)
{
static const WCHAR valueW[] = {'1',0};
static const WCHAR pathW[] = {'P','A','T','H'};
RTL_USER_PROCESS_PARAMETERS *params = NULL;
SIZE_T size, env_pos, env_size;
WCHAR *dst, *image, *cmdline, *p, *path = NULL;
WCHAR *dst, *image, *cmdline, *path, *bootstrap;
WCHAR *env = get_initial_environment( &env_pos, &env_size );
WCHAR *curdir = get_initial_directory();
void *module = NULL;
NTSTATUS status;
/* store the initial PATH value */
if ((p = find_env_var( env, env_pos, pathW, 4 )))
{
path = malloc( (wcslen(p + 5) + 1) * sizeof(WCHAR) );
wcscpy( path, p + 5 );
}
path = get_env_var( env, env_pos, pathW, 4 );
add_dynamic_environment( &env, &env_pos, &env_size );
add_registry_environment( &env, &env_pos, &env_size );
bootstrap = get_env_var( env, env_pos, bootstrapW, ARRAY_SIZE(bootstrapW) );
set_env_var( &env, &env_pos, &env_size, bootstrapW, ARRAY_SIZE(bootstrapW), valueW );
is_prefix_bootstrap = TRUE;
env[env_pos] = 0;
run_wineboot( env, env_pos );
/* reload environment now that wineboot has run */
set_env_var( &env, &env_pos, &env_size, pathW, 4, path ); /* reset PATH */
free( path );
set_env_var( &env, &env_pos, &env_size, bootstrapW, ARRAY_SIZE(bootstrapW), bootstrap );
is_prefix_bootstrap = !!bootstrap;
free( bootstrap );
add_registry_environment( &env, &env_pos, &env_size );
env[env_pos++] = 0;
@ -2012,6 +2030,7 @@ void init_startup_info(void)
memcpy( env, (char *)info + info_size, env_size * sizeof(WCHAR) );
env_pos = env_size - 1;
add_dynamic_environment( &env, &env_pos, &env_size );
is_prefix_bootstrap = !!find_env_var( env, env_pos, bootstrapW, ARRAY_SIZE(bootstrapW) );
env[env_pos++] = 0;
size = (sizeof(*params)

View File

@ -1387,10 +1387,10 @@ BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine )
{
static const WCHAR wow64W[] = {'\\','?','?','\\','c',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','w','o','w','6','4'};
BOOL is_prefix_bootstrap;
unsigned int len;
struct stat st;
char *ntdll;
/* only fake builtin existence during prefix bootstrap */
if (!is_prefix_bootstrap) return FALSE;
*machine = current_machine;
if (path->Length > wcslen(system_dir) * sizeof(WCHAR) &&
@ -1413,15 +1413,7 @@ found:
len = wcslen(system_dir);
while (len < path->Length / sizeof(WCHAR) && path->Buffer[len] == '\\') len++;
while (len < path->Length / sizeof(WCHAR) && path->Buffer[len] != '\\') len++;
if (len != path->Length / sizeof(WCHAR)) return FALSE;
/* if the corresponding ntdll exists, don't fake the existence of the builtin */
ntdll = build_path( config_dir, *machine == IMAGE_FILE_MACHINE_I386 ?
"dosdevices/c:/windows/syswow64/ntdll.dll" :
"dosdevices/c:/windows/system32/ntdll.dll" );
is_prefix_bootstrap = stat( ntdll, &st ) == -1;
free( ntdll );
return is_prefix_bootstrap;
return (len == path->Length / sizeof(WCHAR));
}

View File

@ -120,6 +120,7 @@ extern const char **dll_paths DECLSPEC_HIDDEN;
extern USHORT *uctable DECLSPEC_HIDDEN;
extern USHORT *lctable DECLSPEC_HIDDEN;
extern SIZE_T startup_info_size DECLSPEC_HIDDEN;
extern BOOL is_prefix_bootstrap DECLSPEC_HIDDEN;
extern SECTION_IMAGE_INFORMATION main_image_info DECLSPEC_HIDDEN;
extern int main_argc DECLSPEC_HIDDEN;
extern char **main_argv DECLSPEC_HIDDEN;