Commit 446f7e3a authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 4f04994e
...@@ -1926,14 +1926,10 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, ...@@ -1926,14 +1926,10 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name,
static void build_ntdll_module(void) static void build_ntdll_module(void)
{ {
MEMORY_BASIC_INFORMATION meminfo; MEMORY_BASIC_INFORMATION meminfo;
FILE_BASIC_INFORMATION basic_info;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
WINE_MODREF *wm; WINE_MODREF *wm;
RtlInitUnicodeString( &nt_name, L"\\??\\C:\\windows\\system32\\ntdll.dll" ); 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, NtQueryVirtualMemory( GetCurrentProcess(), build_ntdll_module, MemoryBasicInformation,
&meminfo, sizeof(meminfo), NULL ); &meminfo, sizeof(meminfo), NULL );
wm = alloc_module( meminfo.AllocationBase, &nt_name, TRUE ); wm = alloc_module( meminfo.AllocationBase, &nt_name, TRUE );
...@@ -2672,7 +2668,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING * ...@@ -2672,7 +2668,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
if (found_image) if (found_image)
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; 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 ); status = find_builtin_without_file( search, nt_name, pwm, mapping, image_info, id );
done: done:
...@@ -3498,10 +3494,14 @@ static void process_breakpoint(void) ...@@ -3498,10 +3494,14 @@ static void process_breakpoint(void)
static void load_global_options(void) static void load_global_options(void)
{ {
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
UNICODE_STRING name_str; UNICODE_STRING name_str, val_str;
HANDLE hkey; HANDLE hkey;
ULONG value; 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.Length = sizeof(attr);
attr.RootDirectory = 0; attr.RootDirectory = 0;
attr.ObjectName = &name_str; attr.ObjectName = &name_str;
......
...@@ -64,6 +64,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(environ); ...@@ -64,6 +64,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(environ);
USHORT *uctable = NULL, *lctable = NULL; USHORT *uctable = NULL, *lctable = NULL;
SIZE_T startup_info_size = 0; 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; int main_argc = 0;
char **main_argv = NULL; char **main_argv = NULL;
...@@ -1211,6 +1214,18 @@ static WCHAR *find_env_var( WCHAR *env, SIZE_T size, const WCHAR *name, SIZE_T n ...@@ -1211,6 +1214,18 @@ static WCHAR *find_env_var( WCHAR *env, SIZE_T size, const WCHAR *name, SIZE_T n
return NULL; 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 */ /* set an environment variable, replacing it if it exists */
static void set_env_var( WCHAR **env, SIZE_T *pos, SIZE_T *size, static void set_env_var( WCHAR **env, SIZE_T *pos, SIZE_T *size,
const WCHAR *name, SIZE_T namelen, const WCHAR *value ) const WCHAR *name, SIZE_T namelen, const WCHAR *value )
...@@ -1889,29 +1904,32 @@ static inline WCHAR *get_dos_path( WCHAR *nt_path ) ...@@ -1889,29 +1904,32 @@ static inline WCHAR *get_dos_path( WCHAR *nt_path )
*/ */
static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void) static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void)
{ {
static const WCHAR valueW[] = {'1',0};
static const WCHAR pathW[] = {'P','A','T','H'}; static const WCHAR pathW[] = {'P','A','T','H'};
RTL_USER_PROCESS_PARAMETERS *params = NULL; RTL_USER_PROCESS_PARAMETERS *params = NULL;
SIZE_T size, env_pos, env_size; 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 *env = get_initial_environment( &env_pos, &env_size );
WCHAR *curdir = get_initial_directory(); WCHAR *curdir = get_initial_directory();
void *module = NULL; void *module = NULL;
NTSTATUS status; NTSTATUS status;
/* store the initial PATH value */ /* store the initial PATH value */
if ((p = find_env_var( env, env_pos, pathW, 4 ))) path = get_env_var( env, env_pos, pathW, 4 );
{
path = malloc( (wcslen(p + 5) + 1) * sizeof(WCHAR) );
wcscpy( path, p + 5 );
}
add_dynamic_environment( &env, &env_pos, &env_size ); add_dynamic_environment( &env, &env_pos, &env_size );
add_registry_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; env[env_pos] = 0;
run_wineboot( env, env_pos ); run_wineboot( env, env_pos );
/* reload environment now that wineboot has run */ /* reload environment now that wineboot has run */
set_env_var( &env, &env_pos, &env_size, pathW, 4, path ); /* reset PATH */ set_env_var( &env, &env_pos, &env_size, pathW, 4, path ); /* reset PATH */
free( 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 ); add_registry_environment( &env, &env_pos, &env_size );
env[env_pos++] = 0; env[env_pos++] = 0;
...@@ -2012,6 +2030,7 @@ void init_startup_info(void) ...@@ -2012,6 +2030,7 @@ void init_startup_info(void)
memcpy( env, (char *)info + info_size, env_size * sizeof(WCHAR) ); memcpy( env, (char *)info + info_size, env_size * sizeof(WCHAR) );
env_pos = env_size - 1; env_pos = env_size - 1;
add_dynamic_environment( &env, &env_pos, &env_size ); 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; env[env_pos++] = 0;
size = (sizeof(*params) size = (sizeof(*params)
......
...@@ -1387,10 +1387,10 @@ BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine ) ...@@ -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','\\', static const WCHAR wow64W[] = {'\\','?','?','\\','c',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','w','o','w','6','4'}; 's','y','s','w','o','w','6','4'};
BOOL is_prefix_bootstrap;
unsigned int len; unsigned int len;
struct stat st;
char *ntdll; /* only fake builtin existence during prefix bootstrap */
if (!is_prefix_bootstrap) return FALSE;
*machine = current_machine; *machine = current_machine;
if (path->Length > wcslen(system_dir) * sizeof(WCHAR) && if (path->Length > wcslen(system_dir) * sizeof(WCHAR) &&
...@@ -1413,15 +1413,7 @@ found: ...@@ -1413,15 +1413,7 @@ found:
len = wcslen(system_dir); len = wcslen(system_dir);
while (len < path->Length / sizeof(WCHAR) && path->Buffer[len] == '\\') len++; while (len < path->Length / sizeof(WCHAR) && path->Buffer[len] == '\\') len++;
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; return (len == path->Length / sizeof(WCHAR));
/* 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;
} }
......
...@@ -120,6 +120,7 @@ extern const char **dll_paths DECLSPEC_HIDDEN; ...@@ -120,6 +120,7 @@ extern const char **dll_paths DECLSPEC_HIDDEN;
extern USHORT *uctable DECLSPEC_HIDDEN; extern USHORT *uctable DECLSPEC_HIDDEN;
extern USHORT *lctable DECLSPEC_HIDDEN; extern USHORT *lctable DECLSPEC_HIDDEN;
extern SIZE_T startup_info_size 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 SECTION_IMAGE_INFORMATION main_image_info DECLSPEC_HIDDEN;
extern int main_argc DECLSPEC_HIDDEN; extern int main_argc DECLSPEC_HIDDEN;
extern char **main_argv DECLSPEC_HIDDEN; extern char **main_argv DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment