Module: wine Branch: master Commit: be25d225adc0771be35f67eb827a6a5da9fde20b URL: https://source.winehq.org/git/wine.git/?a=commit;h=be25d225adc0771be35f67eb8...
Author: Jon Doron arilou@gmail.com Date: Mon Mar 18 07:20:42 2019 +0200
kernel32: Make GetEnvironmentStringsW returns a copy of the environment.
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) .
Signed-off-by: Jon Doron arilou@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/environ.c | 18 ++++++++++++++++-- dlls/kernel32/tests/environ.c | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/environ.c b/dlls/kernel32/environ.c index 99bf706..0fa7596 100644 --- a/dlls/kernel32/environ.c +++ b/dlls/kernel32/environ.c @@ -139,7 +139,21 @@ LPSTR WINAPI GetEnvironmentStringsA(void) */ LPWSTR WINAPI GetEnvironmentStringsW(void) { - return NtCurrentTeb()->Peb->ProcessParameters->Environment; + LPWSTR ret, ptrW; + unsigned len; + + RtlAcquirePebLock(); + + ptrW = NtCurrentTeb()->Peb->ProcessParameters->Environment; + while (*ptrW) ptrW += strlenW(ptrW) + 1; + ptrW++; + + len = (ptrW - NtCurrentTeb()->Peb->ProcessParameters->Environment) * sizeof(WCHAR); + ret = HeapAlloc(GetProcessHeap(), 0, len); + if (ret) memcpy(ret, NtCurrentTeb()->Peb->ProcessParameters->Environment, len); + + RtlReleasePebLock(); + return ret; }
@@ -157,7 +171,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 f8452be..4249ea7 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(); }