Module: wine Branch: master Commit: 628ca4aafe2c918744cbbf3079830379f3b936dd URL: https://source.winehq.org/git/wine.git/?a=commit;h=628ca4aafe2c918744cbbf307...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Oct 22 10:05:24 2019 +0200
kernel32: Move registry environment initialization to ntdll.
Signed-off-by: Alexandre Julliard julliard@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; }