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 SearchPathW(wstr wstr wstr long ptr ptr) kernel32.SearchPathW
|
||||||
@ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
|
@ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
|
||||||
@ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
|
@ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
|
||||||
@ stub SetEnvironmentStringsW
|
@ stdcall SetEnvironmentStringsW(wstr) kernel32.SetEnvironmentStringsW
|
||||||
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
|
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
|
||||||
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
|
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
|
||||||
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle
|
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
@ stdcall SearchPathW(wstr wstr wstr long ptr ptr) kernel32.SearchPathW
|
@ stdcall SearchPathW(wstr wstr wstr long ptr ptr) kernel32.SearchPathW
|
||||||
@ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
|
@ stdcall SetCurrentDirectoryA(str) kernel32.SetCurrentDirectoryA
|
||||||
@ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
|
@ stdcall SetCurrentDirectoryW(wstr) kernel32.SetCurrentDirectoryW
|
||||||
@ stub SetEnvironmentStringsW
|
@ stdcall SetEnvironmentStringsW(wstr) kernel32.SetEnvironmentStringsW
|
||||||
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
|
@ stdcall SetEnvironmentVariableA(str str) kernel32.SetEnvironmentVariableA
|
||||||
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
|
@ stdcall SetEnvironmentVariableW(wstr wstr) kernel32.SetEnvironmentVariableW
|
||||||
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle
|
@ stdcall SetStdHandle(long long) kernel32.SetStdHandle
|
||||||
|
|
|
@ -1388,8 +1388,8 @@
|
||||||
@ stdcall SetDllDirectoryW(wstr)
|
@ stdcall SetDllDirectoryW(wstr)
|
||||||
# @ stub SetDynamicTimeZoneInformation
|
# @ stub SetDynamicTimeZoneInformation
|
||||||
@ stdcall -import SetEndOfFile(long)
|
@ stdcall -import SetEndOfFile(long)
|
||||||
# @ stub SetEnvironmentStringsA
|
@ stdcall -import SetEnvironmentStringsA(str)
|
||||||
# @ stub SetEnvironmentStringsW
|
@ stdcall -import SetEnvironmentStringsW(wstr)
|
||||||
@ stdcall -import SetEnvironmentVariableA(str str)
|
@ stdcall -import SetEnvironmentVariableA(str str)
|
||||||
@ stdcall -import SetEnvironmentVariableW(wstr wstr)
|
@ stdcall -import SetEnvironmentVariableW(wstr wstr)
|
||||||
@ stdcall -import SetErrorMode(long)
|
@ 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 *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
|
||||||
static BOOL (WINAPI *pOpenProcessToken)(HANDLE,DWORD,PHANDLE);
|
static BOOL (WINAPI *pOpenProcessToken)(HANDLE,DWORD,PHANDLE);
|
||||||
static BOOL (WINAPI *pGetUserProfileDirectoryA)(HANDLE,LPSTR,LPDWORD);
|
static BOOL (WINAPI *pGetUserProfileDirectoryA)(HANDLE,LPSTR,LPDWORD);
|
||||||
|
static BOOL (WINAPI *pSetEnvironmentStringsW)(WCHAR *);
|
||||||
|
|
||||||
static void init_functionpointers(void)
|
static void init_functionpointers(void)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +46,7 @@ static void init_functionpointers(void)
|
||||||
|
|
||||||
pGetComputerNameExA = (void *)GetProcAddress(hkernel32, "GetComputerNameExA");
|
pGetComputerNameExA = (void *)GetProcAddress(hkernel32, "GetComputerNameExA");
|
||||||
pGetComputerNameExW = (void *)GetProcAddress(hkernel32, "GetComputerNameExW");
|
pGetComputerNameExW = (void *)GetProcAddress(hkernel32, "GetComputerNameExW");
|
||||||
|
pSetEnvironmentStringsW = (void *)GetProcAddress(hkernel32, "SetEnvironmentStringsW");
|
||||||
pOpenProcessToken = (void *)GetProcAddress(hadvapi32, "OpenProcessToken");
|
pOpenProcessToken = (void *)GetProcAddress(hadvapi32, "OpenProcessToken");
|
||||||
pGetUserProfileDirectoryA = (void *)GetProcAddress(huserenv,
|
pGetUserProfileDirectoryA = (void *)GetProcAddress(huserenv,
|
||||||
"GetUserProfileDirectoryA");
|
"GetUserProfileDirectoryA");
|
||||||
|
@ -602,6 +604,89 @@ static void test_GetEnvironmentStringsW(void)
|
||||||
FreeEnvironmentStringsW(env2);
|
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)
|
START_TEST(environ)
|
||||||
{
|
{
|
||||||
init_functionpointers();
|
init_functionpointers();
|
||||||
|
@ -614,4 +699,5 @@ START_TEST(environ)
|
||||||
test_GetComputerNameExA();
|
test_GetComputerNameExA();
|
||||||
test_GetComputerNameExW();
|
test_GetComputerNameExW();
|
||||||
test_GetEnvironmentStringsW();
|
test_GetEnvironmentStringsW();
|
||||||
|
test_SetEnvironmentStrings();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1422,7 +1422,8 @@
|
||||||
@ stdcall SetDefaultDllDirectories(long)
|
@ stdcall SetDefaultDllDirectories(long)
|
||||||
# @ stub SetDynamicTimeZoneInformation
|
# @ stub SetDynamicTimeZoneInformation
|
||||||
@ stdcall SetEndOfFile(long)
|
@ stdcall SetEndOfFile(long)
|
||||||
@ stub SetEnvironmentStringsW
|
@ stdcall SetEnvironmentStringsA(str)
|
||||||
|
@ stdcall SetEnvironmentStringsW(wstr)
|
||||||
@ stdcall SetEnvironmentVariableA(str str)
|
@ stdcall SetEnvironmentVariableA(str str)
|
||||||
@ stdcall SetEnvironmentVariableW(wstr wstr)
|
@ stdcall SetEnvironmentVariableW(wstr wstr)
|
||||||
@ stdcall SetErrorMode(long)
|
@ 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.@)
|
* GetEnvironmentVariableA (kernelbase.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2619,6 +2619,9 @@ WINBASEAPI BOOL WINAPI SetDllDirectoryA(LPCSTR);
|
||||||
WINBASEAPI BOOL WINAPI SetDllDirectoryW(LPCWSTR);
|
WINBASEAPI BOOL WINAPI SetDllDirectoryW(LPCWSTR);
|
||||||
#define SetDllDirectory WINELIB_NAME_AW(SetDllDirectory)
|
#define SetDllDirectory WINELIB_NAME_AW(SetDllDirectory)
|
||||||
WINBASEAPI BOOL WINAPI SetEndOfFile(HANDLE);
|
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 SetEnvironmentVariableA(LPCSTR,LPCSTR);
|
||||||
WINBASEAPI BOOL WINAPI SetEnvironmentVariableW(LPCWSTR,LPCWSTR);
|
WINBASEAPI BOOL WINAPI SetEnvironmentVariableW(LPCWSTR,LPCWSTR);
|
||||||
#define SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
|
#define SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
|
||||||
|
|
Loading…
Reference in New Issue