kernelbase: Implement SetEnvironmentStrings().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48308
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Zebediah Figura 2020-05-06 09:40:28 -05:00 committed by Alexandre Julliard
parent e012bd5811
commit 877bf2a7a0
7 changed files with 161 additions and 5 deletions

View File

@ -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(wstr) kernel32.SetEnvironmentStringsW
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle

View File

@ -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(wstr) kernel32.SetEnvironmentStringsW
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle

View File

@ -1388,8 +1388,8 @@
@ stdcall SetDllDirectoryW(wstr)
# @ stub SetDynamicTimeZoneInformation
@ stdcall -import SetEndOfFile(long)
# @ stub SetEnvironmentStringsA
# @ stub SetEnvironmentStringsW
@ stdcall -import SetEnvironmentStringsA(str)
@ stdcall -import SetEnvironmentStringsW(wstr)
@ stdcall -import SetEnvironmentVariableA(str str)
@ stdcall -import SetEnvironmentVariableW(wstr wstr)
@ stdcall -import SetErrorMode(long)

View File

@ -36,6 +36,7 @@ static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
static BOOL (WINAPI *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
static BOOL (WINAPI *pOpenProcessToken)(HANDLE,DWORD,PHANDLE);
static BOOL (WINAPI *pGetUserProfileDirectoryA)(HANDLE,LPSTR,LPDWORD);
static BOOL (WINAPI *pSetEnvironmentStringsW)(WCHAR *);
static void init_functionpointers(void)
{
@ -45,6 +46,7 @@ static void init_functionpointers(void)
pGetComputerNameExA = (void *)GetProcAddress(hkernel32, "GetComputerNameExA");
pGetComputerNameExW = (void *)GetProcAddress(hkernel32, "GetComputerNameExW");
pSetEnvironmentStringsW = (void *)GetProcAddress(hkernel32, "SetEnvironmentStringsW");
pOpenProcessToken = (void *)GetProcAddress(hadvapi32, "OpenProcessToken");
pGetUserProfileDirectoryA = (void *)GetProcAddress(huserenv,
"GetUserProfileDirectoryA");
@ -602,6 +604,89 @@ static void test_GetEnvironmentStringsW(void)
FreeEnvironmentStringsW(env2);
}
#define copy_string(dst, src) memcpy(dst, src, sizeof(src))
static void check_env_var_(int line, const char *var, const char *value)
{
char buffer[20];
DWORD size = GetEnvironmentVariableA(var, buffer, sizeof(buffer));
if (value)
{
ok_(__FILE__, line)(size == strlen(value), "wrong size %u\n", size);
ok_(__FILE__, line)(!strcmp(buffer, value), "wrong value %s\n", debugstr_a(buffer));
}
else
{
ok_(__FILE__, line)(!size, "wrong size %u\n", size);
ok_(__FILE__, line)(GetLastError() == ERROR_ENVVAR_NOT_FOUND, "got error %u\n", GetLastError());
}
}
#define check_env_var(a, b) check_env_var_(__LINE__, a, b)
static void test_SetEnvironmentStrings(void)
{
static const WCHAR testenv[] = L"testenv1=unus\0testenv3=tres\0";
WCHAR env[200];
WCHAR *old_env;
BOOL ret;
if (!pSetEnvironmentStringsW)
{
win_skip("SetEnvironmentStringsW() is not available\n");
return;
}
ret = SetEnvironmentVariableA("testenv1", "heis");
ok(ret, "got error %u\n", GetLastError());
ret = SetEnvironmentVariableA("testenv2", "dyo");
ok(ret, "got error %u\n", GetLastError());
old_env = GetEnvironmentStringsW();
memcpy(env, testenv, sizeof(testenv));
ret = pSetEnvironmentStringsW(env);
ok(ret, "got error %u\n", GetLastError());
ok(!memcmp(env, testenv, sizeof(testenv)), "input parameter should not be changed\n");
check_env_var("testenv1", "unus");
check_env_var("testenv2", NULL);
check_env_var("testenv3", "tres");
check_env_var("PATH", NULL);
ret = pSetEnvironmentStringsW(old_env);
ok(ret, "got error %u\n", GetLastError());
check_env_var("testenv1", "heis");
check_env_var("testenv2", "dyo");
check_env_var("testenv3", NULL);
SetEnvironmentVariableA("testenv1", NULL);
SetEnvironmentVariableA("testenv2", NULL);
copy_string(env, L"testenv\0");
SetLastError(0xdeadbeef);
ret = pSetEnvironmentStringsW(env);
ok(!ret, "expected failure\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
copy_string(env, L"=unus\0");
SetLastError(0xdeadbeef);
ret = pSetEnvironmentStringsW(env);
ok(!ret, "expected failure\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
copy_string(env, L"one=two=three four=five\0");
ret = pSetEnvironmentStringsW(env);
ok(ret, "got error %u\n", GetLastError());
check_env_var("one", "two=three four=five");
ret = pSetEnvironmentStringsW(old_env);
ok(ret, "got error %u\n", GetLastError());
ret = FreeEnvironmentStringsW(old_env);
ok(ret, "got error %u\n", GetLastError());
}
START_TEST(environ)
{
init_functionpointers();
@ -614,4 +699,5 @@ START_TEST(environ)
test_GetComputerNameExA();
test_GetComputerNameExW();
test_GetEnvironmentStringsW();
test_SetEnvironmentStrings();
}

View File

@ -1422,7 +1422,8 @@
@ stdcall SetDefaultDllDirectories(long)
# @ stub SetDynamicTimeZoneInformation
@ stdcall SetEndOfFile(long)
@ stub SetEnvironmentStringsW
@ stdcall SetEnvironmentStringsA(str)
@ stdcall SetEnvironmentStringsW(wstr)
@ stdcall SetEnvironmentVariableA(str str)
@ stdcall SetEnvironmentVariableW(wstr wstr)
@ stdcall SetErrorMode(long)

View File

@ -1274,6 +1274,72 @@ LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
}
/***********************************************************************
* SetEnvironmentStringsA (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsA( char *env )
{
WCHAR *envW;
const char *p = env;
DWORD len;
BOOL ret;
for (p = env; *p; p += strlen( p ) + 1);
len = MultiByteToWideChar( CP_ACP, 0, env, p - env, NULL, 0 );
if (!(envW = HeapAlloc( GetProcessHeap(), 0, len )))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
MultiByteToWideChar( CP_ACP, 0, env, p - env, envW, len );
ret = SetEnvironmentStringsW( envW );
HeapFree( GetProcessHeap(), 0, envW );
return ret;
}
/***********************************************************************
* SetEnvironmentStringsW (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentStringsW( WCHAR *env )
{
WCHAR *p;
WCHAR *new_env;
NTSTATUS status;
for (p = env; *p; p += wcslen( p ) + 1)
{
const WCHAR *eq = wcschr( p, '=' );
if (!eq || eq == p)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
if ((status = RtlCreateEnvironment( FALSE, &new_env )))
return set_ntstatus( status );
for (p = env; *p; p += wcslen( p ) + 1)
{
const WCHAR *eq = wcschr( p, '=' );
UNICODE_STRING var, value;
var.Buffer = p;
var.Length = (eq - p) * sizeof(WCHAR);
RtlInitUnicodeString( &value, eq + 1 );
if ((status = RtlSetEnvironmentVariable( &new_env, &var, &value )))
{
RtlDestroyEnvironment( new_env );
return set_ntstatus( status );
}
}
RtlSetCurrentEnvironment( new_env, NULL );
return TRUE;
}
/***********************************************************************
* GetEnvironmentVariableA (kernelbase.@)
*/

View File

@ -2619,6 +2619,9 @@ WINBASEAPI BOOL WINAPI SetDllDirectoryA(LPCSTR);
WINBASEAPI BOOL WINAPI SetDllDirectoryW(LPCWSTR);
#define SetDllDirectory WINELIB_NAME_AW(SetDllDirectory)
WINBASEAPI BOOL WINAPI SetEndOfFile(HANDLE);
WINBASEAPI BOOL WINAPI SetEnvironmentStringsA(char *);
WINBASEAPI BOOL WINAPI SetEnvironmentStringsW(WCHAR *);
#define SetEnvironmentStrings WINELIB_NAME_AW(SetEnvironmentStrings)
WINBASEAPI BOOL WINAPI SetEnvironmentVariableA(LPCSTR,LPCSTR);
WINBASEAPI BOOL WINAPI SetEnvironmentVariableW(LPCWSTR,LPCWSTR);
#define SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)