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>
This commit is contained in:
parent
e012bd5811
commit
877bf2a7a0
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue