[PATCH v3] kernel32: make GetEnvironmentStringsW returns a copy of the environment

Jon Doron arilou at gmail.com
Mon Mar 18 00:20:42 CDT 2019


There are certain applications which try to traverse the environement
being returned, but this is problematic since they cannot acquire the
PEB Lock (i.e cl.exe on Visual Studio 14.15) .

To resolve the issue provide a copy of the current environment same as
in GetEnvironmentStringsA .

Signed-off-by: Jon Doron <arilou at gmail.com>
---
 dlls/kernel32/environ.c       | 27 +++++++++++++++++++++++++--
 dlls/kernel32/tests/environ.c | 15 +++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/environ.c b/dlls/kernel32/environ.c
index 99bf706e95..5a5f50340e 100644
--- a/dlls/kernel32/environ.c
+++ b/dlls/kernel32/environ.c
@@ -139,7 +139,30 @@ LPSTR WINAPI GetEnvironmentStringsA(void)
  */
 LPWSTR WINAPI GetEnvironmentStringsW(void)
 {
-    return NtCurrentTeb()->Peb->ProcessParameters->Environment;
+    LPWSTR ret, ptrW;
+    unsigned len;
+
+    RtlAcquirePebLock();
+
+    ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment;
+    if (!ptrW || !*ptrW)
+    {
+        RtlReleasePebLock();
+        return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * 2);
+    }
+
+    while (*ptrW)
+        ptrW += strlenW(ptrW) + 1;
+
+    len = (ULONG_PTR)ptrW - (ULONG_PTR)NtCurrentTeb()->Peb->ProcessParameters->Environment;
+    ret = HeapAlloc(GetProcessHeap(), 0, len + sizeof(WCHAR));
+    if (ret) {
+        memcpy(ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len);
+        ret[len / 2] = 0;
+    }
+
+    RtlReleasePebLock();
+    return ret;
 }
 
 
@@ -157,7 +180,7 @@ BOOL WINAPI FreeEnvironmentStringsA( LPSTR ptr )
  */
 BOOL WINAPI FreeEnvironmentStringsW( LPWSTR ptr )
 {
-    return TRUE;
+    return HeapFree( GetProcessHeap(), 0, ptr );
 }
 
 
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c
index f8452be2ee..4249ea7ebe 100644
--- a/dlls/kernel32/tests/environ.c
+++ b/dlls/kernel32/tests/environ.c
@@ -554,6 +554,20 @@ static void test_GetComputerNameExW(void)
     HeapFree(GetProcessHeap(), 0, nameW);
 }
 
+static void test_GetEnvironmentStringsW(void)
+{
+    PWCHAR env1;
+    PWCHAR env2;
+
+    env1 = GetEnvironmentStringsW();
+    env2 = GetEnvironmentStringsW();
+    ok(env1 != env2 ||
+       broken(env1 == env2), /* NT <= 5.1 */
+       "should return different copies\n");
+    FreeEnvironmentStringsW(env1);
+    FreeEnvironmentStringsW(env2);
+}
+
 START_TEST(environ)
 {
     init_functionpointers();
@@ -565,4 +579,5 @@ START_TEST(environ)
     test_GetComputerName();
     test_GetComputerNameExA();
     test_GetComputerNameExW();
+    test_GetEnvironmentStringsW();
 }
-- 
2.19.2




More information about the wine-devel mailing list