Signed-off-by: Frank Uhlig uhlig.frank@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);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71314
Your paranoid android.
=== wxppro (32 bit report) ===
kernel32: environ: Timeout
=== debiant (32 bit WoW report) ===
kernel32: change.c:320: Test failed: should be ready