Alexandre Julliard : kernel32: Move registry environment initialization to ntdll.

Alexandre Julliard julliard at winehq.org
Tue Oct 22 16:57:00 CDT 2019


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Oct 22 10:05:24 2019 +0200

kernel32: Move registry environment initialization to ntdll.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/process.c |  34 ++++++++++---
 dlls/ntdll/env.c        | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index d03d147d95..1d6f6b4737 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -507,6 +507,31 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
 }
 
 
+/***********************************************************************
+ *           has_registry_environment
+ */
+static BOOL has_registry_environment(void)
+{
+    static const WCHAR env_keyW[] = {'\\','R','e','g','i','s','t','r','y','\\',
+                                     'M','a','c','h','i','n','e','\\',
+                                     'S','y','s','t','e','m','\\',
+                                     'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+                                     'C','o','n','t','r','o','l','\\',
+                                     'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
+                                     'E','n','v','i','r','o','n','m','e','n','t',0};
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    HANDLE hkey;
+    BOOL ret;
+
+    InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
+    RtlInitUnicodeString( &nameW, env_keyW );
+    ret = !NtOpenKey( &hkey, KEY_READ, &attr );
+    if (ret) NtClose( hkey );
+    return ret;
+}
+
+
 /***********************************************************************
  *           set_registry_environment
  *
@@ -519,7 +544,7 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
  * %SystemRoot% which are predefined. But Wine defines these in the
  * registry, so we need two passes.
  */
-static BOOL set_registry_environment( BOOL volatile_only )
+static void set_registry_environment( BOOL volatile_only )
 {
     static const WCHAR env_keyW[] = {'\\','R','e','g','i','s','t','r','y','\\',
                                      'M','a','c','h','i','n','e','\\',
@@ -534,7 +559,6 @@ static BOOL set_registry_environment( BOOL volatile_only )
     OBJECT_ATTRIBUTES attr;
     UNICODE_STRING nameW;
     HANDLE hkey;
-    BOOL ret = FALSE;
 
     attr.Length = sizeof(attr);
     attr.RootDirectory = 0;
@@ -550,11 +574,10 @@ static BOOL set_registry_environment( BOOL volatile_only )
         set_registry_variables( hkey, REG_SZ );
         set_registry_variables( hkey, REG_EXPAND_SZ );
         NtClose( hkey );
-        ret = TRUE;
     }
 
     /* then the ones for the current user */
-    if (RtlOpenCurrentUser( KEY_READ, &attr.RootDirectory ) != STATUS_SUCCESS) return ret;
+    if (RtlOpenCurrentUser( KEY_READ, &attr.RootDirectory ) != STATUS_SUCCESS) return;
     RtlInitUnicodeString( &nameW, envW );
     if (!volatile_only && NtOpenKey( &hkey, KEY_READ, &attr ) == STATUS_SUCCESS)
     {
@@ -572,7 +595,6 @@ static BOOL set_registry_environment( BOOL volatile_only )
     }
 
     NtClose( attr.RootDirectory );
-    return ret;
 }
 
 
@@ -1207,7 +1229,7 @@ void * CDECL __wine_kernel_init(void)
         /* convert old configuration to new format */
         convert_old_config();
 
-        got_environment = set_registry_environment( FALSE );
+        got_environment = has_registry_environment();
         set_additional_environment();
     }
 
diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c
index 64bd9b15a3..1499879271 100644
--- a/dlls/ntdll/env.c
+++ b/dlls/ntdll/env.c
@@ -82,6 +82,129 @@ static inline BOOL is_special_env_var( const char *var )
 }
 
 
+/***********************************************************************
+ *           set_registry_variables
+ *
+ * Set environment variables by enumerating the values of a key;
+ * helper for set_registry_environment().
+ * Note that Windows happily truncates the value if it's too big.
+ */
+static void set_registry_variables( WCHAR **env, HANDLE hkey, ULONG type )
+{
+    static const WCHAR pathW[] = {'P','A','T','H'};
+    static const WCHAR sep[] = {';',0};
+    UNICODE_STRING env_name, env_value;
+    NTSTATUS status;
+    DWORD size;
+    int index;
+    char buffer[1024*sizeof(WCHAR) + sizeof(KEY_VALUE_FULL_INFORMATION)];
+    WCHAR tmpbuf[1024];
+    UNICODE_STRING tmp;
+    KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+
+    tmp.Buffer = tmpbuf;
+    tmp.MaximumLength = sizeof(tmpbuf);
+
+    for (index = 0; ; index++)
+    {
+        status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
+                                      buffer, sizeof(buffer), &size );
+        if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) break;
+        if (info->Type != type) continue;
+        env_name.Buffer = info->Name;
+        env_name.Length = env_name.MaximumLength = info->NameLength;
+        env_value.Buffer = (WCHAR *)(buffer + info->DataOffset);
+        env_value.Length = info->DataLength;
+        env_value.MaximumLength = sizeof(buffer) - info->DataOffset;
+        if (env_value.Length && !env_value.Buffer[env_value.Length/sizeof(WCHAR)-1])
+            env_value.Length -= sizeof(WCHAR);  /* don't count terminating null if any */
+        if (!env_value.Length) continue;
+        if (info->Type == REG_EXPAND_SZ)
+        {
+            status = RtlExpandEnvironmentStrings_U( *env, &env_value, &tmp, NULL );
+            if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) continue;
+            RtlCopyUnicodeString( &env_value, &tmp );
+        }
+        /* PATH is magic */
+        if (env_name.Length == sizeof(pathW) &&
+            !strncmpiW( env_name.Buffer, pathW, ARRAY_SIZE( pathW )) &&
+            !RtlQueryEnvironmentVariable_U( *env, &env_name, &tmp ))
+        {
+            RtlAppendUnicodeToString( &tmp, sep );
+            if (RtlAppendUnicodeStringToString( &tmp, &env_value )) continue;
+            RtlCopyUnicodeString( &env_value, &tmp );
+        }
+        RtlSetEnvironmentVariable( env, &env_name, &env_value );
+    }
+}
+
+
+/***********************************************************************
+ *           set_registry_environment
+ *
+ * Set the environment variables specified in the registry.
+ *
+ * Note: Windows handles REG_SZ and REG_EXPAND_SZ in one pass with the
+ * consequence that REG_EXPAND_SZ cannot be used reliably as it depends
+ * on the order in which the variables are processed. But on Windows it
+ * does not really matter since they only use %SystemDrive% and
+ * %SystemRoot% which are predefined. But Wine defines these in the
+ * registry, so we need two passes.
+ */
+static void set_registry_environment( WCHAR **env )
+{
+    static const WCHAR env_keyW[] = {'\\','R','e','g','i','s','t','r','y','\\',
+                                     'M','a','c','h','i','n','e','\\',
+                                     'S','y','s','t','e','m','\\',
+                                     'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+                                     'C','o','n','t','r','o','l','\\',
+                                     'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
+                                     'E','n','v','i','r','o','n','m','e','n','t',0};
+    static const WCHAR envW[] = {'E','n','v','i','r','o','n','m','e','n','t',0};
+    static const WCHAR volatile_envW[] = {'V','o','l','a','t','i','l','e',' ','E','n','v','i','r','o','n','m','e','n','t',0};
+
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    HANDLE hkey;
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    /* first the system environment variables */
+    RtlInitUnicodeString( &nameW, env_keyW );
+    if (!NtOpenKey( &hkey, KEY_READ, &attr ))
+    {
+        set_registry_variables( env, hkey, REG_SZ );
+        set_registry_variables( env, hkey, REG_EXPAND_SZ );
+        NtClose( hkey );
+    }
+
+    /* then the ones for the current user */
+    if (RtlOpenCurrentUser( KEY_READ, &attr.RootDirectory ) != STATUS_SUCCESS) return;
+    RtlInitUnicodeString( &nameW, envW );
+    if (!NtOpenKey( &hkey, KEY_READ, &attr ))
+    {
+        set_registry_variables( env, hkey, REG_SZ );
+        set_registry_variables( env, hkey, REG_EXPAND_SZ );
+        NtClose( hkey );
+    }
+
+    RtlInitUnicodeString( &nameW, volatile_envW );
+    if (!NtOpenKey( &hkey, KEY_READ, &attr ))
+    {
+        set_registry_variables( env, hkey, REG_SZ );
+        set_registry_variables( env, hkey, REG_EXPAND_SZ );
+        NtClose( hkey );
+    }
+
+    NtClose( attr.RootDirectory );
+}
+
+
 /***********************************************************************
  *           build_initial_environment
  *
@@ -122,6 +245,7 @@ static WCHAR *build_initial_environment( char **env )
         p += strlenW(p) + 1;
     }
     *p = 0;
+    set_registry_environment( &ptr );
     return ptr;
 }
 




More information about the wine-cvs mailing list