From: Fabian Maurer dark.shadow4@web.de
It doesn't set error code ERROR_INSUFFICIENT_BUFFER, and doesn't null terminate the string either --- dlls/kernel32/tests/environ.c | 49 +++++++++++++++++++++++++++++++++++ dlls/kernelbase/process.c | 10 ++++--- 2 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index c1a49e175be..2a15fb92dfd 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -379,6 +379,54 @@ static void test_GetSetEnvironmentVariableAW(void) ok(lstrcmpW(bufW, valueW) == 0, "expected %s, got %s\n", debugstr_w(valueW), debugstr_w(bufW)); }
+static void test_ExpandEnvironmentStringsW(void) +{ + const WCHAR *value = L"Long long value"; + WCHAR buf[256]; + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdef"); + ExpandEnvironmentStringsW(value, buf, 0); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"abcdef"), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdef"); + ExpandEnvironmentStringsW(value, buf, 1); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"abcdef"), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdef"); + ExpandEnvironmentStringsW(value, buf, 2); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"Lbcdef"), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdef"); + ExpandEnvironmentStringsW(value, buf, 3); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"Locdef"), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef"); + ExpandEnvironmentStringsW(value, buf, 15); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"Long long valucdefabcdefabcdefabcdefabcdefabcdef"), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef"); + ExpandEnvironmentStringsW(value, buf, 16); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, value), "got %s\n", debugstr_w(buf)); + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdef"); + ExpandEnvironmentStringsW(value, NULL, 0); + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + ok(!wcscmp(buf, L"abcdef"), "got %s\n", debugstr_w(buf)); +} + static void test_ExpandEnvironmentStringsA(void) { const char* value="Long long value"; @@ -780,6 +828,7 @@ START_TEST(environ) test_GetSetEnvironmentVariableA(); test_GetSetEnvironmentVariableW(); test_GetSetEnvironmentVariableAW(); + test_ExpandEnvironmentStringsW(); test_ExpandEnvironmentStringsA(); test_GetComputerName(); test_GetComputerNameExA(); diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 4807e84594d..8aa732602ec 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -1425,6 +1425,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR ds UNICODE_STRING us_src, us_dst; NTSTATUS status; DWORD res; + WCHAR last_char;
TRACE( "(%s %p %lu)\n", debugstr_w(src), dst, len );
@@ -1437,14 +1438,17 @@ DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR ds us_dst.MaximumLength = len * sizeof(WCHAR); us_dst.Buffer = dst;
+ /* Tests show windows keeps the last character instead of a null terminator */ + if (dst && len) last_char = dst[len - 1]; res = 0; status = RtlExpandEnvironmentStrings_U( NULL, &us_src, &us_dst, &res ); res /= sizeof(WCHAR); - if (!set_ntstatus( status )) + if (status != STATUS_BUFFER_TOO_SMALL) { - if (status != STATUS_BUFFER_TOO_SMALL) return 0; - if (len && dst) dst[len - 1] = 0; + if (!set_ntstatus( status )) return 0; } + else if (dst && len) dst[len - 1] = last_char; + return res; }