Alexandre Julliard : ntdll: Set environment variables from the registry on the Unix side.
Alexandre Julliard
julliard at winehq.org
Thu Mar 4 15:53:36 CST 2021
Module: wine
Branch: master
Commit: f6e64c55f2ddcb92a9ff53f18d1b12f366dd4036
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f6e64c55f2ddcb92a9ff53f18d1b12f366dd4036
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Mar 3 11:25:43 2021 +0100
ntdll: Set environment variables from the registry on the Unix side.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/env.c | 2 +-
dlls/ntdll/unix/env.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c
index 4931e407e57..ade6aefc2d5 100644
--- a/dlls/ntdll/env.c
+++ b/dlls/ntdll/env.c
@@ -1023,7 +1023,7 @@ void init_user_process_params(void)
if (!params->DllPath.MaximumLength) /* not inherited from parent process */
{
- first_prefix_start = set_registry_environment( ¶ms->Environment, TRUE );
+ first_prefix_start = !ENV_FindVariable( params->Environment, L"COMSPEC", 7 );
set_additional_environment( ¶ms->Environment );
get_image_path( params->ImagePathName.Buffer, image, sizeof(image) );
diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c
index 92498318665..97a43a90000 100644
--- a/dlls/ntdll/unix/env.c
+++ b/dlls/ntdll/unix/env.c
@@ -1242,6 +1242,148 @@ static void add_dynamic_environment( WCHAR **env, SIZE_T *pos, SIZE_T *size )
}
+static WCHAR *expand_value( WCHAR *env, SIZE_T size, const WCHAR *src, SIZE_T src_len )
+{
+ SIZE_T len, retlen = src_len, count = 0;
+ const WCHAR *var;
+ WCHAR *ret;
+
+ ret = malloc( retlen * sizeof(WCHAR) );
+ while (src_len)
+ {
+ if (*src != '%')
+ {
+ for (len = 0; len < src_len; len++) if (src[len] == '%') break;
+ var = src;
+ src += len;
+ src_len -= len;
+ }
+ else /* we are at the start of a variable */
+ {
+ for (len = 1; len < src_len; len++) if (src[len] == '%') break;
+ if (len < src_len)
+ {
+ if ((var = find_env_var( env, size, src + 1, len - 1 )))
+ {
+ src += len + 1; /* skip the variable name */
+ src_len -= len + 1;
+ var += len;
+ len = wcslen(var);
+ }
+ else
+ {
+ var = src; /* copy original name instead */
+ len++;
+ src += len;
+ src_len -= len;
+ }
+ }
+ else /* unfinished variable name, ignore it */
+ {
+ var = src;
+ src += len;
+ src_len = 0;
+ }
+ }
+ if (len >= retlen - count)
+ {
+ retlen *= 2;
+ ret = realloc( ret, retlen * sizeof(WCHAR) );
+ }
+ memcpy( ret + count, var, len * sizeof(WCHAR) );
+ count += len;
+ }
+ ret[count] = 0;
+ return ret;
+}
+
+/***********************************************************************
+ * add_registry_variables
+ *
+ * Set environment variables by enumerating the values of a key;
+ * helper for add_registry_environment().
+ * Note that Windows happily truncates the value if it's too big.
+ */
+static void add_registry_variables( WCHAR **env, SIZE_T *pos, SIZE_T *size, HANDLE key, BOOL append )
+{
+ static const WCHAR pathW[] = {'P','A','T','H'};
+ NTSTATUS status;
+ DWORD index = 0, info_size, namelen, datalen;
+ WCHAR *data, *value, *p;
+ WCHAR buffer[offsetof(KEY_VALUE_FULL_INFORMATION, Name[1024]) / sizeof(WCHAR)];
+ KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+
+ for (;;)
+ {
+ status = NtEnumerateValueKey( key, index++, KeyValueFullInformation,
+ buffer, sizeof(buffer) - sizeof(WCHAR), &info_size );
+ if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) break;
+
+ value = data = buffer + info->DataOffset / sizeof(WCHAR);
+ datalen = info->DataLength / sizeof(WCHAR);
+ namelen = info->NameLength / sizeof(WCHAR);
+
+ if (datalen && !data[datalen - 1]) datalen--; /* don't count terminating null if any */
+ if (!datalen) continue;
+ data[datalen] = 0;
+ if (info->Type == REG_EXPAND_SZ) value = expand_value( *env, *pos, data, datalen );
+
+ /* PATH is magic */
+ if (append && namelen == 4 && !wcsnicmp( info->Name, pathW, 4 ) && (p = find_env_var( *env, *pos, pathW, 4 )))
+ {
+ static const WCHAR sepW[] = {';',0};
+ WCHAR *newpath = malloc( (wcslen(p) - 4 + datalen) * sizeof(WCHAR) );
+ wcscpy( newpath, p + 5 );
+ wcscat( newpath, sepW );
+ wcscat( newpath, data );
+ if (value != data) free( value );
+ value = newpath;
+ }
+
+ set_env_var( env, pos, size, info->Name, namelen, value );
+ if (value != data) free( value );
+ }
+}
+
+
+/***********************************************************************
+ * add_registry_environment
+ *
+ * Set the environment variables specified in the registry.
+ */
+static void add_registry_environment( WCHAR **env, SIZE_T *pos, SIZE_T *size )
+{
+ static const WCHAR syskeyW[] = {'\\','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 key;
+
+ InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL );
+ init_unicode_string( &nameW, syskeyW );
+ if (!NtOpenKey( &key, KEY_READ, &attr ))
+ {
+ add_registry_variables( env, pos, size, key, FALSE );
+ NtClose( key );
+ }
+ if (!open_hkcu_key( "Environment", &key ))
+ {
+ add_registry_variables( env, pos, size, key, TRUE );
+ NtClose( key );
+ }
+ if (!open_hkcu_key( "Volatile Environment", &key ))
+ {
+ add_registry_variables( env, pos, size, key, TRUE );
+ NtClose( key );
+ }
+}
+
+
/*************************************************************************
* get_initial_console
*
@@ -1485,6 +1627,7 @@ static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void)
NTSTATUS status;
add_dynamic_environment( &env, &env_pos, &env_size );
+ add_registry_environment( &env, &env_pos, &env_size );
env[env_pos++] = 0;
size = (sizeof(*params)
More information about the wine-cvs
mailing list