[PATCH v2] kernelbase: Add SetEnvironmentStringsW().

Frank Uhlig uhlig.frank at gmail.com
Wed May 6 14:50:17 CDT 2020


Signed-off-by: Frank Uhlig <uhlig.frank at gmail.com>
---
 ...ms-win-core-processenvironment-l1-1-0.spec |  2 +-
 ...ms-win-core-processenvironment-l1-2-0.spec |  2 +-
 dlls/kernel32/kernel32.spec                   |  2 +-
 dlls/kernel32/tests/environ.c                 | 82 +++++++++++++++++++
 dlls/kernelbase/kernelbase.spec               |  2 +-
 dlls/kernelbase/process.c                     | 50 +++++++++++
 include/winbase.h                             |  1 +
 7 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/dlls/api-ms-win-core-processenvironment-l1-1-0/api-ms-win-core-processenvironment-l1-1-0.spec b/dlls/api-ms-win-core-processenvironment-l1-1-0/api-ms-win-core-processenvironment-l1-1-0.spec
index e3698d6efd..7a62b74390 100644
--- a/dlls/api-ms-win-core-processenvironment-l1-1-0/api-ms-win-core-processenvironment-l1-1-0.spec
+++ b/dlls/api-ms-win-core-processenvironment-l1-1-0/api-ms-win-core-processenvironment-l1-1-0.spec
@@ -15,7 +15,7 @@
 @ stdcall SearchPathW(wstr wstr wstr long ptr ptr) kernel32.SearchPathW
 @ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
 @ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
-@ stub SetEnvironmentStringsW
+@ stdcall SetEnvironmentStringsW(ptr) kernel32.SetEnvironmentStringsW
 @ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
 @ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
 @ stdcall SetStdHandle(long long) kernel32.SetStdHandle
diff --git a/dlls/api-ms-win-core-processenvironment-l1-2-0/api-ms-win-core-processenvironment-l1-2-0.spec b/dlls/api-ms-win-core-processenvironment-l1-2-0/api-ms-win-core-processenvironment-l1-2-0.spec
index 2c25ee1a07..c93d221c5e 100644
--- a/dlls/api-ms-win-core-processenvironment-l1-2-0/api-ms-win-core-processenvironment-l1-2-0.spec
+++ b/dlls/api-ms-win-core-processenvironment-l1-2-0/api-ms-win-core-processenvironment-l1-2-0.spec
@@ -17,7 +17,7 @@
 @ stdcall SearchPathW(wstr wstr wstr long ptr ptr) kernel32.SearchPathW
 @ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
 @ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
-@ stub SetEnvironmentStringsW
+@ stdcall SetEnvironmentStringsW(ptr) kernel32.SetEnvironmentStringsW
 @ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
 @ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
 @ stdcall SetStdHandle(long long) kernel32.SetStdHandle
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 0dd3813987..a27098fa42 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1389,7 +1389,7 @@
 # @ stub SetDynamicTimeZoneInformation
 @ stdcall -import SetEndOfFile(long)
 # @ stub SetEnvironmentStringsA
-# @ stub SetEnvironmentStringsW
+@ stdcall -import SetEnvironmentStringsW (ptr)
 @ stdcall -import SetEnvironmentVariableA(str str)
 @ stdcall -import SetEnvironmentVariableW(wstr wstr)
 @ stdcall -import SetErrorMode(long)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c
index 128a5fdbe5..fff31cd80e 100644
--- a/dlls/kernel32/tests/environ.c
+++ b/dlls/kernel32/tests/environ.c
@@ -602,6 +602,87 @@ static void test_GetEnvironmentStringsW(void)
     FreeEnvironmentStringsW(env2);
 }
 
+static void test_SetEnvironmentStringsW(void)
+{
+    DWORD buf_len;
+    BOOL ret;
+    DWORD ret_size;
+
+    WCHAR buf[256];
+
+    WCHAR name[] = {'N','a','m','e',0};
+    WCHAR value[] = {'V','a','l','u','e',0};
+    WCHAR env[] = {'N','a','m','e','=','V','a','l','u','e',0,0};
+
+    WCHAR eman[] = {'e','m','a','N',0};
+    WCHAR eulav[] = {'e','u','l','a','V',0};
+    WCHAR vne[] = {'e','m','a','N','=','e','u','l','a','V',0,0};
+
+    WCHAR var[] = {'V','a','r',0};
+    WCHAR val[] = {'V','a','l',0};
+    WCHAR rav[] = {'r','a','V',0};
+    WCHAR lav[] = {'l','a','V',0};
+    WCHAR mul[] = {'V','a','r','=','V','a','l',0,'r','a','V','=','l','a','V',0,0};
+
+    WCHAR empty[] = {'V','a','r','=',0,0};
+
+    WCHAR fwlt1[] = {'V','a','r',0,0};
+    WCHAR fwlt2[] = {'=','V','a','l',0,0};
+    WCHAR fwlt3[] = {'V','a','r','=','V','a','l',0,'r','a','V',0,0};
+
+    buf_len = ARRAY_SIZE(buf);
+
+    ret = SetEnvironmentStringsW(env);
+    ok( ret, "Setting environment strings failed with ret=%d\n", ret );
+
+    ret_size = GetEnvironmentVariableW(name, buf, buf_len);
+    ok( ret_size && ((ARRAY_SIZE(value)-1 == ret_size) && (0 == wcscmp(buf, value))),
+       "Difference in env, expected (%s) gotten (%s)\n",
+       debugstr_w(value), debugstr_w(buf));
+    memset(buf, 0, buf_len * sizeof(WCHAR));
+
+    ret = SetEnvironmentStringsW(vne);
+    ok( ret, "Setting environment strings failed with ret=%d\n", ret );
+
+    ret_size = GetEnvironmentVariableW(eman, buf, buf_len);
+    ok( ret_size && ((ARRAY_SIZE(eulav)-1 == ret_size) && (0 == wcscmp(buf, eulav))),
+       "Difference in env, expected (%s) gotten (%s)\n",
+       debugstr_w(eulav), debugstr_w(buf));
+    memset(buf, 0, buf_len * sizeof(WCHAR));
+
+    ret = SetEnvironmentStringsW(mul);
+    ok( ret, "Setting environment strings failed with ret=%d\n", ret);
+
+    ret_size = GetEnvironmentVariableW(var, buf, buf_len);
+    ok( ret_size && ((ARRAY_SIZE(val)-1 == ret_size) && (0 == wcscmp(buf, val))),
+       "Difference in env, expected (%s) gotten (%s)\n",
+       debugstr_w(val), debugstr_w(buf));
+    memset(buf, 0, buf_len * sizeof(WCHAR));
+
+    ret_size = GetEnvironmentVariableW(rav, buf, buf_len);
+    ok( ret_size && ((ARRAY_SIZE(lav)-1 == ret_size) && (0 == wcscmp(buf, lav))),
+       "Difference in env, expected (%s) gotten (%s)\n",
+       debugstr_w(lav), debugstr_w(buf));
+    memset(buf, 0, buf_len * sizeof(WCHAR));
+
+    ret = SetEnvironmentStringsW(empty);
+    ok( ret, "Setting empty environment failed with ret=%d\n", ret);
+
+    ret_size = GetEnvironmentVariableW(var, buf, buf_len);
+    ok( (0 == ret_size),
+       "Difference in env, should have been null, is (%s)\n", debugstr_w(buf));
+    memset(buf, 0, buf_len * sizeof(WCHAR));
+
+    ret = SetEnvironmentStringsW(fwlt1);
+    ok( FALSE == ret, "Non-environment string did not fail as expected, ret=%d\n", ret);
+
+    ret = SetEnvironmentStringsW(fwlt2);
+    ok( FALSE == ret, "Non-environment string did not fail as expected, ret=%d\n", ret);
+
+    ret = SetEnvironmentStringsW(fwlt3);
+    ok( FALSE == ret, "Non-environment string did not fail as expected, ret=%d\n", ret);
+}
+
 START_TEST(environ)
 {
     init_functionpointers();
@@ -614,4 +695,5 @@ START_TEST(environ)
     test_GetComputerNameExA();
     test_GetComputerNameExW();
     test_GetEnvironmentStringsW();
+    test_SetEnvironmentStringsW();
 }
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index e73682af0f..c252d1ebd4 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1422,7 +1422,7 @@
 @ stdcall SetDefaultDllDirectories(long)
 # @ stub SetDynamicTimeZoneInformation
 @ stdcall SetEndOfFile(long)
-@ stub SetEnvironmentStringsW
+@ stdcall SetEnvironmentStringsW(ptr)
 @ stdcall SetEnvironmentVariableA(str str)
 @ stdcall SetEnvironmentVariableW(wstr wstr)
 @ stdcall SetErrorMode(long)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c
index acef2c55a1..7e9b44aa15 100644
--- a/dlls/kernelbase/process.c
+++ b/dlls/kernelbase/process.c
@@ -1392,6 +1392,56 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW( LPCWSTR name, LPCWSTR val
 }
 
 
+/***********************************************************************
+ *           SetEnvironmentStringsW   (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env )
+{
+    BOOL rc = FALSE;
+    WCHAR *var, *val, *buff, *end, *tmp, *cur;
+    size_t bufflen = 0, len;
+
+    TRACE( "(%p)\n", env);
+
+    if (!env)
+        return rc;
+
+    RtlAcquirePebLock();
+    len = get_env_length( NtCurrentTeb()->Peb->ProcessParameters->Environment ) * sizeof(WCHAR);
+    if ((cur = HeapAlloc( GetProcessHeap(), 0, len )))
+        memset( NtCurrentTeb()->Peb->ProcessParameters->Environment, 0, len );
+    RtlReleasePebLock();
+
+    if ( !(bufflen = get_env_length(env)) )
+        return rc;
+
+    if (NULL == (buff = HeapAlloc(GetProcessHeap(), 0, bufflen * sizeof(WCHAR))))
+        return rc;
+
+    memcpy(buff, env, bufflen * sizeof(WCHAR));
+    end = buff +bufflen -1;
+    var = buff;
+
+    while (var < end) {
+        if (NULL == (val = wcschr(var, L'=')))
+            return FALSE;
+        *val++ = L'\0';
+
+        if ( !(rc = SetEnvironmentVariableW(var, val)) )
+            return rc;
+
+        if (NULL == (var = wcschr(val, L'\0')))
+            return FALSE;
+
+        ++var;
+    }
+
+    HeapFree(GetProcessHeap(), 0, buff);
+
+    return rc;
+}
+
+
 /***********************************************************************
  * Process/thread attribute lists
  ***********************************************************************/
diff --git a/include/winbase.h b/include/winbase.h
index f92d864c78..043bd3269f 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2622,6 +2622,7 @@ WINBASEAPI BOOL        WINAPI SetEndOfFile(HANDLE);
 WINBASEAPI BOOL        WINAPI SetEnvironmentVariableA(LPCSTR,LPCSTR);
 WINBASEAPI BOOL        WINAPI SetEnvironmentVariableW(LPCWSTR,LPCWSTR);
 #define                       SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
+WINBASEAPI BOOL        WINAPI SetEnvironmentStringsW(WCHAR *);
 WINBASEAPI UINT        WINAPI SetErrorMode(UINT);
 WINBASEAPI BOOL        WINAPI SetEvent(HANDLE);
 WINBASEAPI VOID        WINAPI SetFileApisToANSI(void);
-- 
2.26.2




More information about the wine-devel mailing list