[PATCH 2/2] kernel32: Properly expand environment variables in PEB block
Fabian Maurer
dark.shadow4 at web.de
Tue May 7 13:12:09 CDT 2019
Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
dlls/kernel32/process.c | 68 +++++++++++++++++++++++++++++++----------
dlls/ntdll/tests/env.c | 1 -
2 files changed, 52 insertions(+), 17 deletions(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 09f0433deb..0f13879c1f 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -62,6 +62,7 @@
#include "wine/server.h"
#include "wine/unicode.h"
#include "wine/debug.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(process);
WINE_DECLARE_DEBUG_CHANNEL(relay);
@@ -502,6 +503,14 @@ static BOOL build_initial_environment(void)
return TRUE;
}
+struct environment_variable
+{
+ struct list entry;
+ UNICODE_STRING name;
+ UNICODE_STRING value;
+ ULONG type;
+};
+
/***********************************************************************
* set_registry_variables
@@ -510,7 +519,7 @@ static BOOL build_initial_environment(void)
* helper for set_registry_environment().
* Note that Windows happily truncates the value if it's too big.
*/
-static void set_registry_variables( HANDLE hkey, ULONG type )
+static void set_registry_variables( HANDLE hkey )
{
static const WCHAR pathW[] = {'P','A','T','H'};
static const WCHAR sep[] = {';',0};
@@ -522,6 +531,11 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
WCHAR tmpbuf[1024];
UNICODE_STRING tmp;
KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+ struct list registry_variables = LIST_INIT(registry_variables);
+ struct environment_variable *variable, *variable_next;
+ PWSTR penv = NULL;
+
+ RtlCreateEnvironment(FALSE, &penv);
tmp.Buffer = tmpbuf;
tmp.MaximumLength = sizeof(tmpbuf);
@@ -532,8 +546,10 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
buffer, sizeof(buffer), &size );
if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW)
break;
- if (info->Type != type)
+ if (info->Type != REG_SZ && info->Type != REG_EXPAND_SZ)
continue;
+
+ variable = malloc(sizeof(struct environment_variable));
env_name.Buffer = info->Name;
env_name.Length = env_name.MaximumLength = info->NameLength;
env_value.Buffer = (WCHAR *)(buffer + info->DataOffset);
@@ -542,12 +558,6 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
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( NULL, &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) &&
!memicmpW( env_name.Buffer, pathW, ARRAY_SIZE( pathW )) &&
@@ -557,8 +567,37 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
if (RtlAppendUnicodeStringToString( &tmp, &env_value )) continue;
RtlCopyUnicodeString( &env_value, &tmp );
}
- RtlSetEnvironmentVariable( NULL, &env_name, &env_value );
+
+ RtlDuplicateUnicodeString(0, &env_name, &variable->name);
+ RtlDuplicateUnicodeString(0, &env_value, &variable->value);
+ variable->type = info->Type;
+ list_add_head(®istry_variables, &variable->entry);
+ RtlSetEnvironmentVariable(&penv, &env_name, &env_value);
}
+
+ LIST_FOR_EACH_ENTRY_SAFE(variable, variable_next, ®istry_variables, struct environment_variable, entry)
+ {
+ if (variable->type == REG_EXPAND_SZ)
+ {
+ /* Expand values found inside outside environment */
+ status = RtlExpandEnvironmentStrings_U(NULL, &variable->value, &tmp, NULL);
+ if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) continue;
+ RtlCopyUnicodeString(&variable->value, &tmp);
+
+ /* Expand values found inside the registry environment we're currently adding */
+ status = RtlExpandEnvironmentStrings_U(penv, &variable->value, &tmp, NULL);
+ if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) continue;
+ RtlCopyUnicodeString(&variable->value, &tmp);
+ }
+
+ RtlSetEnvironmentVariable(NULL, &variable->name, &variable->value);
+
+ RtlFreeUnicodeString(&variable->name);
+ RtlFreeUnicodeString(&variable->value);
+ free(variable);
+ }
+
+ RtlDestroyEnvironment(penv);
}
@@ -572,7 +611,7 @@ static void set_registry_variables( HANDLE hkey, ULONG type )
* 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.
+ * registry, so we need two passes inside set_registry_variables
*/
static BOOL set_registry_environment( BOOL volatile_only )
{
@@ -602,8 +641,7 @@ static BOOL set_registry_environment( BOOL volatile_only )
RtlInitUnicodeString( &nameW, env_keyW );
if (!volatile_only && NtOpenKey( &hkey, KEY_READ, &attr ) == STATUS_SUCCESS)
{
- set_registry_variables( hkey, REG_SZ );
- set_registry_variables( hkey, REG_EXPAND_SZ );
+ set_registry_variables( hkey );
NtClose( hkey );
ret = TRUE;
}
@@ -613,16 +651,14 @@ static BOOL set_registry_environment( BOOL volatile_only )
RtlInitUnicodeString( &nameW, envW );
if (!volatile_only && NtOpenKey( &hkey, KEY_READ, &attr ) == STATUS_SUCCESS)
{
- set_registry_variables( hkey, REG_SZ );
- set_registry_variables( hkey, REG_EXPAND_SZ );
+ set_registry_variables( hkey );
NtClose( hkey );
}
RtlInitUnicodeString( &nameW, volatile_envW );
if (NtOpenKey( &hkey, KEY_READ, &attr ) == STATUS_SUCCESS)
{
- set_registry_variables( hkey, REG_SZ );
- set_registry_variables( hkey, REG_EXPAND_SZ );
+ set_registry_variables( hkey );
NtClose( hkey );
}
diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c
index 41cb44ecd2..e295fb97b2 100644
--- a/dlls/ntdll/tests/env.c
+++ b/dlls/ntdll/tests/env.c
@@ -558,7 +558,6 @@ static void test_peb_environment(void)
if (lstrcmpW(env, result2) == 0)
found2 = TRUE;
}
- todo_wine
ok(found1, "Didn't find %s in the PEB environment variables\n", wine_dbgstr_w(result1));
ok(found2, "Didn't find %s in the PEB environment variables\n", wine_dbgstr_w(result2));
}
--
2.21.0
More information about the wine-devel
mailing list