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

Alexandre Julliard julliard at winehq.org
Thu Apr 8 16:14:03 CDT 2021


Module: wine
Branch: master
Commit: 446f7e3aa8a906c9213d92f1572e8373286c543a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=446f7e3aa8a906c9213d92f1572e8373286c543a

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Apr  8 12:22:25 2021 +0200

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 at winehq.org>

---

 dlls/ntdll/loader.c            | 12 ++++++------
 dlls/ntdll/unix/env.c          | 31 +++++++++++++++++++++++++------
 dlls/ntdll/unix/loader.c       | 16 ++++------------
 dlls/ntdll/unix/unix_private.h |  1 +
 4 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index e1810bc5ab9..e919d7e2671 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -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;
diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c
index 10089a740c2..01d4f3ea418 100644
--- a/dlls/ntdll/unix/env.c
+++ b/dlls/ntdll/unix/env.c
@@ -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)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index e362f5eb4db..cbafa0d8882 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -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));
 }
 
 
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index d0fa7a54f49..0f14e69f2be 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -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;




More information about the wine-cvs mailing list