We can't return the unicode string size, this returns sizes to small for multi-byte characters.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54295
-- v6: kernel32: Rework ExpandEnvironmentStringsA to return ansi size and fix corner cases.
From: Fabian Maurer dark.shadow4@web.de
--- dlls/ntdll/tests/env.c | 113 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+)
diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c index 450ee37db1f..4dda2cb04ff 100644 --- a/dlls/ntdll/tests/env.c +++ b/dlls/ntdll/tests/env.c @@ -32,6 +32,7 @@ static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPD LPCSTR src, DWORD srclen ); static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING); static NTSTATUS (WINAPI* pRtlQueryEnvironmentVariable)(WCHAR*, WCHAR*, SIZE_T, WCHAR*, SIZE_T, SIZE_T*); +static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings)(WCHAR*, WCHAR*, SIZE_T, WCHAR*, SIZE_T, SIZE_T*); static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG); static NTSTATUS (WINAPI *pRtlCreateProcessParameters)(RTL_USER_PROCESS_PARAMETERS**, const UNICODE_STRING*, const UNICODE_STRING*, @@ -243,6 +244,116 @@ static void testExpand(void)
}
+static void test_RtlExpandEnvironmentStrings(void) +{ + int i; + WCHAR buf[256]; + HRESULT status; + UNICODE_STRING us_src, us_dst, us_name, us_value; + static const struct test_info + { + const WCHAR *input; + const WCHAR *expected_str; + int count_in; + int expected_count_out; + BOOL todo_str; + } tests[] = + { + /* 0 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 0, 16 }, + /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16, TRUE }, + /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16, TRUE }, + /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16, TRUE }, + /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16, TRUE }, + /* 5 */ { L"Long long value", L"Long long value", 16, 16 }, + /* 6 */ { L"Long long value", L"Long long value", 17, 16 }, + /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15 }, + /* 8 */ { L"%TVAR% long long", L"", 1, 15, TRUE }, + /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE }, + /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE }, + /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15, TRUE }, + /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15, TRUE }, + /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15, TRUE }, + /* 14 */ { L"%TVAR% long long", L"WINE long long", 15, 15 }, + /* 15 */ { L"%TVAR% long long", L"WINE long long", 16, 15 }, + /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE }, + /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14, TRUE }, + /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE }, + /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE }, + /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14, TRUE }, + /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14, TRUE }, + /* 22 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 14, 14 }, + /* 23 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 15, 14 }, + /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15, TRUE }, + /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15, TRUE }, + /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE }, + /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE }, + /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15, TRUE }, + /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15, TRUE }, + /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15, TRUE }, + /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15, TRUE }, + /* 32 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 15, 15 }, + /* 33 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 16, 15 }, + /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18, TRUE }, + /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18, TRUE }, + /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18, TRUE }, + /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18, TRUE }, + /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18, TRUE }, + /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18, TRUE }, + /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18, TRUE }, + /* 41 */ { L"%TVAR2% long long", L"%TVAR2% long long", 18, 18 }, + /* 42 */ { L"%TVAR2% long long", L"%TVAR2% long long", 19, 18 }, + /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16, TRUE }, + /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16, TRUE }, + /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16, TRUE }, + /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16, TRUE }, + /* 47 */ { L"%TVAR long long", L"%TVAR long long", 16, 16 }, + /* 48 */ { L"%TVAR long long", L"%TVAR long long", 17, 16 }, + }; + + RtlInitUnicodeString(&us_name, L"TVAR"); + RtlInitUnicodeString(&us_value, L"WINE"); + status = RtlSetEnvironmentVariable(NULL, &us_name, &us_value); + ok(status == STATUS_SUCCESS, "RtlSetEnvironmentVariable failed with %lx\n", status); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + const struct test_info *test = &tests[i]; + SIZE_T out_len; + HRESULT expected_status = test->count_in >= test->expected_count_out ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL; + + wcscpy(buf, L"abcdefghijklmnopqrstuv"); + status = pRtlExpandEnvironmentStrings(NULL, (WCHAR*)test->input, wcslen(test->input), buf, test->count_in, &out_len); + ok(out_len == test->expected_count_out, "Test %d: got %lu\n", i, out_len); + ok(status == expected_status, "Test %d: Expected status %lx, got %lx\n", i, expected_status, status); + todo_wine_if(test->todo_str) + ok(!wcscmp(buf, test->expected_str), "Test %d: got %s\n", i, debugstr_w(buf)); + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + const struct test_info *test = &tests[i]; + DWORD out_len; + HRESULT expected_status = test->count_in >= test->expected_count_out ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL; + + us_src.Length = wcslen(test->input) * sizeof(WCHAR); + us_src.MaximumLength = us_src.Length; + us_src.Buffer = (WCHAR*)test->input; + + us_dst.Length = test->count_in * sizeof(WCHAR); + us_dst.MaximumLength = us_dst.Length; + us_dst.Buffer = buf; + + wcscpy(buf, L"abcdefghijklmnopqrstuv"); + status = pRtlExpandEnvironmentStrings_U(NULL, &us_src, &us_dst, &out_len); + ok(out_len / sizeof(WCHAR) == test->expected_count_out, "Test %d: got %lu\n", i, out_len / sizeof(WCHAR)); + ok(status == expected_status, "Test %d: Expected status %lx, got %lx\n", i, expected_status, status); + todo_wine_if(test->todo_str) + ok(!wcscmp(buf, test->expected_str), "Test %d: got %s\n", i, debugstr_w(buf)); + } + status = RtlSetEnvironmentVariable(NULL, &us_name, NULL); + ok(status == STATUS_SUCCESS, "RtlSetEnvironmentVariable failed with %lx\n", status); +} + static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_STRING *str ) { if (params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED) return str->Buffer; @@ -621,6 +732,7 @@ START_TEST(env) pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN"); pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U"); pRtlQueryEnvironmentVariable = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable"); + pRtlExpandEnvironmentStrings = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings"); pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U"); pRtlCreateProcessParameters = (void*)GetProcAddress(mod, "RtlCreateProcessParameters"); pRtlDestroyProcessParameters = (void*)GetProcAddress(mod, "RtlDestroyProcessParameters"); @@ -630,4 +742,5 @@ START_TEST(env) test_process_params(); test_RtlSetCurrentEnvironment(); test_RtlSetEnvironmentVariable(); + test_RtlExpandEnvironmentStrings(); }
From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/environ.c | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index c1a49e175be..36cedcdeaf5 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -379,6 +379,100 @@ 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) +{ + int i; + WCHAR buf[256]; + DWORD ret; + BOOL success; + static const struct test_info + { + const WCHAR *input; + const WCHAR *expected_str; + int count_in; + int expected_count_out; + BOOL todo_status; + BOOL todo_str; + } tests[] = + { + /* 0 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 0, 16, TRUE }, + /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16, TRUE, TRUE }, + /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16, TRUE, TRUE }, + /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16, TRUE, TRUE }, + /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16, TRUE, TRUE }, + /* 5 */ { L"Long long value", L"Long long value", 16, 16 }, + /* 6 */ { L"Long long value", L"Long long value", 17, 16 }, + /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15, TRUE }, + /* 8 */ { L"%TVAR% long long", L"", 1, 15, TRUE }, + /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE, TRUE }, + /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE, TRUE }, + /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15, TRUE }, + /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15, TRUE, TRUE }, + /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15, TRUE, TRUE }, + /* 14 */ { L"%TVAR% long long", L"WINE long long", 15, 15 }, + /* 15 */ { L"%TVAR% long long", L"WINE long long", 16, 15 }, + /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE, TRUE }, + /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14, TRUE }, + /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE, TRUE }, + /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE, TRUE }, + /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14, TRUE }, + /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14, TRUE, TRUE }, + /* 22 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 14, 14 }, + /* 23 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 15, 14 }, + /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15, TRUE }, + /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15, TRUE }, + /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE, TRUE }, + /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE, TRUE }, + /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15, TRUE }, + /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15, TRUE, TRUE }, + /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15, TRUE, TRUE }, + /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15, TRUE, TRUE }, + /* 32 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 15, 15 }, + /* 33 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 16, 15 }, + /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18, TRUE, TRUE }, + /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18, TRUE, TRUE }, + /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18, TRUE, TRUE }, + /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18, TRUE, TRUE }, + /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18, TRUE, TRUE }, + /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18, TRUE, TRUE }, + /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18, TRUE, TRUE }, + /* 41 */ { L"%TVAR2% long long", L"%TVAR2% long long", 18, 18 }, + /* 42 */ { L"%TVAR2% long long", L"%TVAR2% long long", 19, 18 }, + /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16, TRUE, TRUE }, + /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16, TRUE, TRUE }, + /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16, TRUE, TRUE }, + /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16, TRUE, TRUE }, + /* 47 */ { L"%TVAR long long", L"%TVAR long long", 16, 16 }, + /* 48 */ { L"%TVAR long long", L"%TVAR long long", 17, 16 }, + }; + + success = SetEnvironmentVariableW(L"TVAR", L"WINE"); + ok(success, "SetEnvironmentVariableW failed with %ld\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ExpandEnvironmentStringsW(L"Long long value", NULL, 0); + ok(ret == 16, "got %lu\n", ret); + todo_wine + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + const struct test_info *test = &tests[i]; + + SetLastError(0xdeadbeef); + wcscpy(buf, L"abcdefghijklmnopqrstuv"); + ret = ExpandEnvironmentStringsW(test->input, buf, test->count_in); + ok(ret == test->expected_count_out, "Test %d: got %lu\n", i, ret); + todo_wine_if(test->todo_status) + ok(GetLastError() == 0xdeadbeef, "Test %d: got last error %ld\n", i, GetLastError()); + todo_wine_if(test->todo_str) + ok(!wcscmp(buf, test->expected_str), "Test %d: got %s\n", i, debugstr_w(buf)); + } + + success = SetEnvironmentVariableW(L"TVAR", NULL); + ok(success, "SetEnvironmentVariableW failed with %ld\n", GetLastError()); +} + static void test_ExpandEnvironmentStringsA(void) { const char* value="Long long value"; @@ -780,6 +874,7 @@ START_TEST(environ) test_GetSetEnvironmentVariableA(); test_GetSetEnvironmentVariableW(); test_GetSetEnvironmentVariableAW(); + test_ExpandEnvironmentStringsW(); test_ExpandEnvironmentStringsA(); test_GetComputerName(); test_GetComputerNameExA();
From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/environ.c | 91 +++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index 36cedcdeaf5..22a73bb8dde 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -479,6 +479,70 @@ static void test_ExpandEnvironmentStringsA(void) const char* not_an_env_var="%NotAnEnvVar%"; char buf[256], buf1[256], buf2[0x8000]; DWORD ret_size, ret_size1; + int i; + DWORD ret; + BOOL success; + static const struct test_info + { + const char *input; + const char *expected_str; + int count_in; + int expected_count_out; + BOOL todo_status; + BOOL todo_str; + BOOL todo_len; + } tests[] = + { + /* 0 */ { "Long long value", "", 0, 17, TRUE, TRUE, TRUE }, + /* 1 */ { "Long long value", "", 1, 17, TRUE, FALSE, TRUE }, + /* 2 */ { "Long long value", "", 2, 17, TRUE, TRUE, TRUE }, + /* 3 */ { "Long long value", "", 3, 17, TRUE, TRUE, TRUE }, + /* 4 */ { "Long long value", "", 15, 17, TRUE, TRUE, TRUE }, + /* 5 */ { "Long long value", "", 16, 17, FALSE, TRUE, TRUE }, + /* 6 */ { "Long long value", "Long long value", 17, 16 }, + /* 7 */ { "%TVAR% long long", "", 0, 16, TRUE, TRUE, TRUE }, + /* 8 */ { "%TVAR% long long", "", 1, 16, TRUE, FALSE, TRUE }, + /* 9 */ { "%TVAR% long long", "", 2, 16, TRUE, TRUE, TRUE }, + /* 10 */ { "%TVAR% long long", "", 4, 16, TRUE, TRUE, TRUE }, + /* 11 */ { "%TVAR% long long", "", 5, 16, TRUE, TRUE, TRUE }, + /* 12 */ { "%TVAR% long long", "", 6, 16, TRUE, TRUE, TRUE }, + /* 13 */ { "%TVAR% long long", "", 7, 16, TRUE, TRUE, TRUE }, + /* 14 */ { "%TVAR% long long", "", 15, 16, FALSE, TRUE, TRUE }, + /* 15 */ { "%TVAR% long long", "WINE long long", 16, 15 }, + /* 16 */ { "%TVAR%%TVAR% long", "", 4, 15, TRUE, TRUE, TRUE }, + /* 17 */ { "%TVAR%%TVAR% long", "", 5, 15, TRUE, TRUE, TRUE }, + /* 18 */ { "%TVAR%%TVAR% long", "", 6, 15, TRUE, TRUE, TRUE }, + /* 19 */ { "%TVAR%%TVAR% long", "", 8, 15, TRUE, TRUE, TRUE }, + /* 20 */ { "%TVAR%%TVAR% long", "", 9, 15, TRUE, TRUE, TRUE }, + /* 21 */ { "%TVAR%%TVAR% long", "", 10, 15, TRUE, TRUE, TRUE }, + /* 22 */ { "%TVAR%%TVAR% long", "", 14, 15, FALSE, TRUE, TRUE }, + /* 23 */ { "%TVAR%%TVAR% long", "WINEWINE long", 15, 14 }, + /* 24 */ { "%TVAR% %TVAR% long", "", 5, 16, TRUE, TRUE, TRUE }, + /* 25 */ { "%TVAR% %TVAR% long", "", 6, 16, TRUE, TRUE, TRUE }, + /* 26 */ { "%TVAR% %TVAR% long", "", 8, 16, TRUE, TRUE, TRUE }, + /* 27 */ { "%TVAR% %TVAR% long", "", 9, 16, TRUE, TRUE, TRUE }, + /* 28 */ { "%TVAR% %TVAR% long", "", 10, 16, TRUE, TRUE, TRUE }, + /* 29 */ { "%TVAR% %TVAR% long", "", 11, 16, TRUE, TRUE, TRUE }, + /* 30 */ { "%TVAR% %TVAR% long", "", 12, 16, TRUE, TRUE, TRUE }, + /* 31 */ { "%TVAR% %TVAR% long", "", 14, 16, TRUE, TRUE, TRUE }, + /* 32 */ { "%TVAR% %TVAR% long", "", 15, 16, FALSE, TRUE, TRUE }, + /* 33 */ { "%TVAR% %TVAR% long", "WINE WINE long", 16, 15 }, + /* 34 */ { "%TVAR2% long long", "", 1, 19, TRUE, FALSE, TRUE }, + /* 35 */ { "%TVAR2% long long", "", 2, 19, TRUE, TRUE, TRUE }, + /* 36 */ { "%TVAR2% long long", "", 4, 19, TRUE, TRUE, TRUE }, + /* 37 */ { "%TVAR2% long long", "", 7, 19, TRUE, TRUE, TRUE }, + /* 38 */ { "%TVAR2% long long", "", 8, 19, TRUE, TRUE, TRUE }, + /* 39 */ { "%TVAR2% long long", "", 9, 19, TRUE, TRUE, TRUE }, + /* 40 */ { "%TVAR2% long long", "", 10, 19, TRUE, TRUE, TRUE }, + /* 41 */ { "%TVAR2% long long", "", 18, 19, FALSE, TRUE, TRUE }, + /* 42 */ { "%TVAR2% long long", "%TVAR2% long long", 19, 18 }, + /* 43 */ { "%TVAR long long", "", 1, 17, TRUE, FALSE, TRUE }, + /* 44 */ { "%TVAR long long", "", 2, 17, TRUE, TRUE, TRUE }, + /* 45 */ { "%TVAR long long", "", 3, 17, TRUE, TRUE, TRUE }, + /* 46 */ { "%TVAR long long", "", 15, 17, TRUE, TRUE, TRUE }, + /* 47 */ { "%TVAR long long", "", 16, 17, FALSE, TRUE, TRUE }, + /* 48 */ { "%TVAR long long", "%TVAR long long", 17, 16 }, + };
SetEnvironmentVariableA("EnvVar", value);
@@ -555,6 +619,33 @@ static void test_ExpandEnvironmentStringsA(void) SetEnvironmentVariableA("IndirectVar", NULL);
SetEnvironmentVariableA("EnvVar", NULL); + + success = SetEnvironmentVariableA("TVAR", "WINE"); + ok(success, "SetEnvironmentVariableA failed with %ld\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ExpandEnvironmentStringsW(L"Long long value", NULL, 0); + ok(ret == 16, "got %lu\n", ret); + todo_wine + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + const struct test_info *test = &tests[i]; + + SetLastError(0xdeadbeef); + strcpy(buf, "abcdefghijklmnopqrstuv"); + ret = ExpandEnvironmentStringsA(test->input, buf, test->count_in); + todo_wine_if(test->todo_len) + ok(ret == test->expected_count_out, "Test %d: got %lu\n", i, ret); + todo_wine_if(test->todo_status) + ok(GetLastError() == 0xdeadbeef, "Test %d: got last error %ld\n", i, GetLastError()); + todo_wine_if(test->todo_str) + ok(!strcmp(buf, test->expected_str), "Test %d: got %s\n", i, debugstr_a(buf)); + } + + success = SetEnvironmentVariableA("TVAR", NULL); + ok(success, "SetEnvironmentVariableA failed with %ld\n", GetLastError()); }
static void test_GetComputerName(void)
From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/environ.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index 22a73bb8dde..6a7844480cc 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -646,6 +646,39 @@ static void test_ExpandEnvironmentStringsA(void)
success = SetEnvironmentVariableA("TVAR", NULL); ok(success, "SetEnvironmentVariableA failed with %ld\n", GetLastError()); + + if (GetACP() == 932) /* shift-jis */ + { + const char *japanese_test = "\x88\xEA\x93\xF1\x8E\x4F\x8E\x6C\x8C\xDC\x98\x5A\x8E\xB5\x94\xAA\x8B\xE3"; /* Japanese Kanji for "one" to "nine", in shift-jis */ + int japanese_len = strlen(japanese_test); + + SetLastError(0xdeadbeef); + ret_size = ExpandEnvironmentStringsA(japanese_test, NULL, 0); + todo_wine + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + todo_wine + ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); + + SetLastError(0xdeadbeef); + ret_size = ExpandEnvironmentStringsA(japanese_test, buf, ret_size); + todo_wine + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + todo_wine + ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); + todo_wine + ok(!strcmp(buf, japanese_test), "Got %s\n", debugstr_a(buf)); + + SetLastError(0xdeadbeef); + ret_size = ExpandEnvironmentStringsA(japanese_test, buf, japanese_len / 2); /* Buffer too small */ + todo_wine + ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); + todo_wine + ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); + } + else + { + skip("Skipping japanese language tests\n"); + } }
static void test_GetComputerName(void)
From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/environ.c | 20 +++++----- dlls/ntdll/env.c | 15 ++++++-- dlls/ntdll/tests/env.c | 70 +++++++++++++++++------------------ 3 files changed, 57 insertions(+), 48 deletions(-)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index 6a7844480cc..ec5842c4a9e 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -404,25 +404,25 @@ static void test_ExpandEnvironmentStringsW(void) /* 6 */ { L"Long long value", L"Long long value", 17, 16 }, /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15, TRUE }, /* 8 */ { L"%TVAR% long long", L"", 1, 15, TRUE }, - /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE, TRUE }, - /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE, TRUE }, + /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE }, + /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE }, /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15, TRUE }, /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15, TRUE, TRUE }, /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15, TRUE, TRUE }, /* 14 */ { L"%TVAR% long long", L"WINE long long", 15, 15 }, /* 15 */ { L"%TVAR% long long", L"WINE long long", 16, 15 }, - /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE, TRUE }, + /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE }, /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14, TRUE }, - /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE, TRUE }, - /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE, TRUE }, + /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE }, + /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE }, /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14, TRUE }, /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14, TRUE, TRUE }, /* 22 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 14, 14 }, /* 23 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 15, 14 }, /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15, TRUE }, /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15, TRUE }, - /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE, TRUE }, - /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE, TRUE }, + /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE }, + /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE }, /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15, TRUE }, /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15, TRUE, TRUE }, /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15, TRUE, TRUE }, @@ -502,14 +502,14 @@ static void test_ExpandEnvironmentStringsA(void) /* 6 */ { "Long long value", "Long long value", 17, 16 }, /* 7 */ { "%TVAR% long long", "", 0, 16, TRUE, TRUE, TRUE }, /* 8 */ { "%TVAR% long long", "", 1, 16, TRUE, FALSE, TRUE }, - /* 9 */ { "%TVAR% long long", "", 2, 16, TRUE, TRUE, TRUE }, - /* 10 */ { "%TVAR% long long", "", 4, 16, TRUE, TRUE, TRUE }, + /* 9 */ { "%TVAR% long long", "", 2, 16, TRUE, FALSE, TRUE }, + /* 10 */ { "%TVAR% long long", "", 4, 16, TRUE, FALSE, TRUE }, /* 11 */ { "%TVAR% long long", "", 5, 16, TRUE, TRUE, TRUE }, /* 12 */ { "%TVAR% long long", "", 6, 16, TRUE, TRUE, TRUE }, /* 13 */ { "%TVAR% long long", "", 7, 16, TRUE, TRUE, TRUE }, /* 14 */ { "%TVAR% long long", "", 15, 16, FALSE, TRUE, TRUE }, /* 15 */ { "%TVAR% long long", "WINE long long", 16, 15 }, - /* 16 */ { "%TVAR%%TVAR% long", "", 4, 15, TRUE, TRUE, TRUE }, + /* 16 */ { "%TVAR%%TVAR% long", "", 4, 15, TRUE, FALSE, TRUE }, /* 17 */ { "%TVAR%%TVAR% long", "", 5, 15, TRUE, TRUE, TRUE }, /* 18 */ { "%TVAR%%TVAR% long", "", 6, 15, TRUE, TRUE, TRUE }, /* 19 */ { "%TVAR%%TVAR% long", "", 8, 15, TRUE, TRUE, TRUE }, diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index 720597dcaf9..58bfdbb9fe8 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -384,7 +384,7 @@ done: NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE_T src_len, WCHAR *dst, SIZE_T count, SIZE_T *plen ) { - SIZE_T len, total_size = 1; /* 1 for terminating '\0' */ + SIZE_T len, copy, total_size = 1; /* 1 for terminating '\0' */ LPCWSTR env, var;
if (!renv) @@ -402,6 +402,7 @@ NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE var = src; src += len; src_len -= len; + copy = len; } else /* we are at the start of a variable */ { @@ -413,6 +414,11 @@ NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE src += len + 1; /* Skip the variable name */ src_len -= len + 1; len = wcslen(var); + copy = len; + if (count <= copy) /* Either copy the entire value, or nothing at all */ + copy = 0; + if (dst && count) /* When the variable is the last thing that fits into dst, the string is null terminated */ + dst[copy] = 0; /* Either right after, or if it doesn't fit, where it would start */ } else { @@ -420,6 +426,7 @@ NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE len++; src += len; src_len -= len; + copy = len; } } else /* unfinished variable name, ignore it */ @@ -427,15 +434,17 @@ NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE var = src; src += len; src_len = 0; + copy = len; } } total_size += len; if (dst) { if (count < len) len = count; - memcpy(dst, var, len * sizeof(WCHAR)); + if (count <= copy) copy = count ? count - 1 : 0; /* If the buffer is too small, we copy one character less */ + memcpy(dst, var, copy * sizeof(WCHAR)); count -= len; - dst += len; + dst += copy; } }
diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c index 4dda2cb04ff..94d6525fde3 100644 --- a/dlls/ntdll/tests/env.c +++ b/dlls/ntdll/tests/env.c @@ -260,52 +260,52 @@ static void test_RtlExpandEnvironmentStrings(void) } tests[] = { /* 0 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 0, 16 }, - /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16, TRUE }, - /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16, TRUE }, - /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16, TRUE }, - /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16, TRUE }, + /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16 }, + /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16 }, + /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16 }, + /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16 }, /* 5 */ { L"Long long value", L"Long long value", 16, 16 }, /* 6 */ { L"Long long value", L"Long long value", 17, 16 }, /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15 }, - /* 8 */ { L"%TVAR% long long", L"", 1, 15, TRUE }, - /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE }, - /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE }, - /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15, TRUE }, - /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15, TRUE }, - /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15, TRUE }, + /* 8 */ { L"%TVAR% long long", L"", 1, 15 }, + /* 9 */ { L"%TVAR% long long", L"", 2, 15 }, + /* 10 */ { L"%TVAR% long long", L"", 4, 15 }, + /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15 }, + /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15 }, + /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15 }, /* 14 */ { L"%TVAR% long long", L"WINE long long", 15, 15 }, /* 15 */ { L"%TVAR% long long", L"WINE long long", 16, 15 }, - /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE }, - /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14, TRUE }, - /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE }, - /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE }, - /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14, TRUE }, - /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14, TRUE }, + /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14 }, + /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14 }, + /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14 }, + /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14 }, + /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14 }, + /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14 }, /* 22 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 14, 14 }, /* 23 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 15, 14 }, - /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15, TRUE }, - /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15, TRUE }, - /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE }, - /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE }, - /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15, TRUE }, - /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15, TRUE }, - /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15, TRUE }, - /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15, TRUE }, + /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15 }, + /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15 }, + /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15 }, + /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15 }, + /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15 }, + /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15 }, + /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15 }, + /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15 }, /* 32 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 15, 15 }, /* 33 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 16, 15 }, - /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18, TRUE }, - /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18, TRUE }, - /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18, TRUE }, - /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18, TRUE }, - /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18, TRUE }, - /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18, TRUE }, - /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18, TRUE }, + /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18 }, + /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18 }, + /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18 }, + /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18 }, + /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18 }, + /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18 }, + /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18 }, /* 41 */ { L"%TVAR2% long long", L"%TVAR2% long long", 18, 18 }, /* 42 */ { L"%TVAR2% long long", L"%TVAR2% long long", 19, 18 }, - /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16, TRUE }, - /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16, TRUE }, - /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16, TRUE }, - /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16, TRUE }, + /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16 }, + /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16 }, + /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16 }, + /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16 }, /* 47 */ { L"%TVAR long long", L"%TVAR long long", 16, 16 }, /* 48 */ { L"%TVAR long long", L"%TVAR long long", 17, 16 }, };
From: Fabian Maurer dark.shadow4@web.de
--- dlls/kernel32/tests/environ.c | 87 +++++++++++++++++------------------ dlls/kernelbase/process.c | 6 +-- 2 files changed, 45 insertions(+), 48 deletions(-)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index ec5842c4a9e..ec765758369 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -395,53 +395,53 @@ static void test_ExpandEnvironmentStringsW(void) BOOL todo_str; } tests[] = { - /* 0 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 0, 16, TRUE }, - /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16, TRUE, TRUE }, - /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16, TRUE, TRUE }, - /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16, TRUE, TRUE }, - /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16, TRUE, TRUE }, + /* 0 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 0, 16 }, + /* 1 */ { L"Long long value", L"abcdefghijklmnopqrstuv", 1, 16 }, + /* 2 */ { L"Long long value", L"Lbcdefghijklmnopqrstuv", 2, 16 }, + /* 3 */ { L"Long long value", L"Locdefghijklmnopqrstuv", 3, 16 }, + /* 4 */ { L"Long long value", L"Long long valuopqrstuv", 15, 16 }, /* 5 */ { L"Long long value", L"Long long value", 16, 16 }, /* 6 */ { L"Long long value", L"Long long value", 17, 16 }, - /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15, TRUE }, - /* 8 */ { L"%TVAR% long long", L"", 1, 15, TRUE }, - /* 9 */ { L"%TVAR% long long", L"", 2, 15, TRUE }, - /* 10 */ { L"%TVAR% long long", L"", 4, 15, TRUE }, - /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15, TRUE }, - /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15, TRUE, TRUE }, - /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15, TRUE, TRUE }, + /* 7 */ { L"%TVAR% long long", L"abcdefghijklmnopqrstuv", 0, 15 }, + /* 8 */ { L"%TVAR% long long", L"", 1, 15 }, + /* 9 */ { L"%TVAR% long long", L"", 2, 15 }, + /* 10 */ { L"%TVAR% long long", L"", 4, 15 }, + /* 11 */ { L"%TVAR% long long", L"WINE", 5, 15 }, + /* 12 */ { L"%TVAR% long long", L"WINE fghijklmnopqrstuv", 6, 15 }, + /* 13 */ { L"%TVAR% long long", L"WINE lghijklmnopqrstuv", 7, 15 }, /* 14 */ { L"%TVAR% long long", L"WINE long long", 15, 15 }, /* 15 */ { L"%TVAR% long long", L"WINE long long", 16, 15 }, - /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14, TRUE }, - /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14, TRUE }, - /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14, TRUE }, - /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14, TRUE }, - /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14, TRUE }, - /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14, TRUE, TRUE }, + /* 16 */ { L"%TVAR%%TVAR% long", L"", 4, 14 }, + /* 17 */ { L"%TVAR%%TVAR% long", L"WINE", 5, 14 }, + /* 18 */ { L"%TVAR%%TVAR% long", L"WINE", 6, 14 }, + /* 19 */ { L"%TVAR%%TVAR% long", L"WINE", 8, 14 }, + /* 20 */ { L"%TVAR%%TVAR% long", L"WINEWINE", 9, 14 }, + /* 21 */ { L"%TVAR%%TVAR% long", L"WINEWINE jklmnopqrstuv", 10, 14 }, /* 22 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 14, 14 }, /* 23 */ { L"%TVAR%%TVAR% long", L"WINEWINE long", 15, 14 }, - /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15, TRUE }, - /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15, TRUE }, - /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15, TRUE }, - /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15, TRUE }, - /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15, TRUE }, - /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15, TRUE, TRUE }, - /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15, TRUE, TRUE }, - /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15, TRUE, TRUE }, + /* 24 */ { L"%TVAR% %TVAR% long", L"WINE", 5, 15 }, + /* 25 */ { L"%TVAR% %TVAR% long", L"WINE ", 6, 15 }, + /* 26 */ { L"%TVAR% %TVAR% long", L"WINE ", 8, 15 }, + /* 27 */ { L"%TVAR% %TVAR% long", L"WINE ", 9, 15 }, + /* 28 */ { L"%TVAR% %TVAR% long", L"WINE WINE", 10, 15 }, + /* 29 */ { L"%TVAR% %TVAR% long", L"WINE WINE klmnopqrstuv", 11, 15 }, + /* 30 */ { L"%TVAR% %TVAR% long", L"WINE WINE llmnopqrstuv", 12, 15 }, + /* 31 */ { L"%TVAR% %TVAR% long", L"WINE WINE lonnopqrstuv", 14, 15 }, /* 32 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 15, 15 }, /* 33 */ { L"%TVAR% %TVAR% long", L"WINE WINE long", 16, 15 }, - /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18, TRUE, TRUE }, - /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18, TRUE, TRUE }, - /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18, TRUE, TRUE }, - /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18, TRUE, TRUE }, - /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18, TRUE, TRUE }, - /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18, TRUE, TRUE }, - /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18, TRUE, TRUE }, + /* 34 */ { L"%TVAR2% long long", L"abcdefghijklmnopqrstuv", 1, 18 }, + /* 35 */ { L"%TVAR2% long long", L"%bcdefghijklmnopqrstuv", 2, 18 }, + /* 36 */ { L"%TVAR2% long long", L"%TVdefghijklmnopqrstuv", 4, 18 }, + /* 37 */ { L"%TVAR2% long long", L"%TVAR2ghijklmnopqrstuv", 7, 18 }, + /* 38 */ { L"%TVAR2% long long", L"%TVAR2%hijklmnopqrstuv", 8, 18 }, + /* 39 */ { L"%TVAR2% long long", L"%TVAR2% ijklmnopqrstuv", 9, 18 }, + /* 40 */ { L"%TVAR2% long long", L"%TVAR2% ljklmnopqrstuv", 10, 18 }, /* 41 */ { L"%TVAR2% long long", L"%TVAR2% long long", 18, 18 }, /* 42 */ { L"%TVAR2% long long", L"%TVAR2% long long", 19, 18 }, - /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16, TRUE, TRUE }, - /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16, TRUE, TRUE }, - /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16, TRUE, TRUE }, - /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16, TRUE, TRUE }, + /* 43 */ { L"%TVAR long long", L"abcdefghijklmnopqrstuv", 1, 16 }, + /* 44 */ { L"%TVAR long long", L"%bcdefghijklmnopqrstuv", 2, 16 }, + /* 45 */ { L"%TVAR long long", L"%Tcdefghijklmnopqrstuv", 3, 16 }, + /* 46 */ { L"%TVAR long long", L"%TVAR long lonopqrstuv", 15, 16 }, /* 47 */ { L"%TVAR long long", L"%TVAR long long", 16, 16 }, /* 48 */ { L"%TVAR long long", L"%TVAR long long", 17, 16 }, }; @@ -452,7 +452,6 @@ static void test_ExpandEnvironmentStringsW(void) SetLastError(0xdeadbeef); ret = ExpandEnvironmentStringsW(L"Long long value", NULL, 0); ok(ret == 16, "got %lu\n", ret); - todo_wine ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError());
for (i = 0; i < ARRAY_SIZE(tests); i++) @@ -493,14 +492,14 @@ static void test_ExpandEnvironmentStringsA(void) BOOL todo_len; } tests[] = { - /* 0 */ { "Long long value", "", 0, 17, TRUE, TRUE, TRUE }, - /* 1 */ { "Long long value", "", 1, 17, TRUE, FALSE, TRUE }, + /* 0 */ { "Long long value", "", 0, 17, FALSE, TRUE, TRUE }, + /* 1 */ { "Long long value", "", 1, 17, TRUE, TRUE, TRUE }, /* 2 */ { "Long long value", "", 2, 17, TRUE, TRUE, TRUE }, /* 3 */ { "Long long value", "", 3, 17, TRUE, TRUE, TRUE }, /* 4 */ { "Long long value", "", 15, 17, TRUE, TRUE, TRUE }, /* 5 */ { "Long long value", "", 16, 17, FALSE, TRUE, TRUE }, /* 6 */ { "Long long value", "Long long value", 17, 16 }, - /* 7 */ { "%TVAR% long long", "", 0, 16, TRUE, TRUE, TRUE }, + /* 7 */ { "%TVAR% long long", "", 0, 16, FALSE, TRUE, TRUE }, /* 8 */ { "%TVAR% long long", "", 1, 16, TRUE, FALSE, TRUE }, /* 9 */ { "%TVAR% long long", "", 2, 16, TRUE, FALSE, TRUE }, /* 10 */ { "%TVAR% long long", "", 4, 16, TRUE, FALSE, TRUE }, @@ -527,7 +526,7 @@ static void test_ExpandEnvironmentStringsA(void) /* 31 */ { "%TVAR% %TVAR% long", "", 14, 16, TRUE, TRUE, TRUE }, /* 32 */ { "%TVAR% %TVAR% long", "", 15, 16, FALSE, TRUE, TRUE }, /* 33 */ { "%TVAR% %TVAR% long", "WINE WINE long", 16, 15 }, - /* 34 */ { "%TVAR2% long long", "", 1, 19, TRUE, FALSE, TRUE }, + /* 34 */ { "%TVAR2% long long", "", 1, 19, TRUE, TRUE, TRUE }, /* 35 */ { "%TVAR2% long long", "", 2, 19, TRUE, TRUE, TRUE }, /* 36 */ { "%TVAR2% long long", "", 4, 19, TRUE, TRUE, TRUE }, /* 37 */ { "%TVAR2% long long", "", 7, 19, TRUE, TRUE, TRUE }, @@ -536,7 +535,7 @@ static void test_ExpandEnvironmentStringsA(void) /* 40 */ { "%TVAR2% long long", "", 10, 19, TRUE, TRUE, TRUE }, /* 41 */ { "%TVAR2% long long", "", 18, 19, FALSE, TRUE, TRUE }, /* 42 */ { "%TVAR2% long long", "%TVAR2% long long", 19, 18 }, - /* 43 */ { "%TVAR long long", "", 1, 17, TRUE, FALSE, TRUE }, + /* 43 */ { "%TVAR long long", "", 1, 17, TRUE, TRUE, TRUE }, /* 44 */ { "%TVAR long long", "", 2, 17, TRUE, TRUE, TRUE }, /* 45 */ { "%TVAR long long", "", 3, 17, TRUE, TRUE, TRUE }, /* 46 */ { "%TVAR long long", "", 15, 17, TRUE, TRUE, TRUE }, @@ -626,7 +625,6 @@ static void test_ExpandEnvironmentStringsA(void) SetLastError(0xdeadbeef); ret = ExpandEnvironmentStringsW(L"Long long value", NULL, 0); ok(ret == 16, "got %lu\n", ret); - todo_wine ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError());
for (i = 0; i < ARRAY_SIZE(tests); i++) @@ -654,7 +652,6 @@ static void test_ExpandEnvironmentStringsA(void)
SetLastError(0xdeadbeef); ret_size = ExpandEnvironmentStringsA(japanese_test, NULL, 0); - todo_wine ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); todo_wine ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 2d08481cd35..c6f2f30b2d8 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -1487,10 +1487,10 @@ DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsW( LPCWSTR src, LPWSTR ds 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; } return res; }
From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54295 --- dlls/kernel32/tests/environ.c | 92 ++++++++++++++++------------------- dlls/kernelbase/process.c | 30 ++++++++---- 2 files changed, 64 insertions(+), 58 deletions(-)
diff --git a/dlls/kernel32/tests/environ.c b/dlls/kernel32/tests/environ.c index ec765758369..bd088d1670f 100644 --- a/dlls/kernel32/tests/environ.c +++ b/dlls/kernel32/tests/environ.c @@ -492,54 +492,54 @@ static void test_ExpandEnvironmentStringsA(void) BOOL todo_len; } tests[] = { - /* 0 */ { "Long long value", "", 0, 17, FALSE, TRUE, TRUE }, - /* 1 */ { "Long long value", "", 1, 17, TRUE, TRUE, TRUE }, - /* 2 */ { "Long long value", "", 2, 17, TRUE, TRUE, TRUE }, - /* 3 */ { "Long long value", "", 3, 17, TRUE, TRUE, TRUE }, - /* 4 */ { "Long long value", "", 15, 17, TRUE, TRUE, TRUE }, - /* 5 */ { "Long long value", "", 16, 17, FALSE, TRUE, TRUE }, + /* 0 */ { "Long long value", "", 0, 17 }, + /* 1 */ { "Long long value", "", 1, 17 }, + /* 2 */ { "Long long value", "", 2, 17 }, + /* 3 */ { "Long long value", "", 3, 17 }, + /* 4 */ { "Long long value", "", 15, 17 }, + /* 5 */ { "Long long value", "", 16, 17 }, /* 6 */ { "Long long value", "Long long value", 17, 16 }, - /* 7 */ { "%TVAR% long long", "", 0, 16, FALSE, TRUE, TRUE }, - /* 8 */ { "%TVAR% long long", "", 1, 16, TRUE, FALSE, TRUE }, - /* 9 */ { "%TVAR% long long", "", 2, 16, TRUE, FALSE, TRUE }, - /* 10 */ { "%TVAR% long long", "", 4, 16, TRUE, FALSE, TRUE }, - /* 11 */ { "%TVAR% long long", "", 5, 16, TRUE, TRUE, TRUE }, - /* 12 */ { "%TVAR% long long", "", 6, 16, TRUE, TRUE, TRUE }, - /* 13 */ { "%TVAR% long long", "", 7, 16, TRUE, TRUE, TRUE }, - /* 14 */ { "%TVAR% long long", "", 15, 16, FALSE, TRUE, TRUE }, + /* 7 */ { "%TVAR% long long", "", 0, 16 }, + /* 8 */ { "%TVAR% long long", "", 1, 16 }, + /* 9 */ { "%TVAR% long long", "", 2, 16 }, + /* 10 */ { "%TVAR% long long", "", 4, 16 }, + /* 11 */ { "%TVAR% long long", "", 5, 16 }, + /* 12 */ { "%TVAR% long long", "", 6, 16 }, + /* 13 */ { "%TVAR% long long", "", 7, 16 }, + /* 14 */ { "%TVAR% long long", "", 15, 16 }, /* 15 */ { "%TVAR% long long", "WINE long long", 16, 15 }, - /* 16 */ { "%TVAR%%TVAR% long", "", 4, 15, TRUE, FALSE, TRUE }, - /* 17 */ { "%TVAR%%TVAR% long", "", 5, 15, TRUE, TRUE, TRUE }, - /* 18 */ { "%TVAR%%TVAR% long", "", 6, 15, TRUE, TRUE, TRUE }, - /* 19 */ { "%TVAR%%TVAR% long", "", 8, 15, TRUE, TRUE, TRUE }, - /* 20 */ { "%TVAR%%TVAR% long", "", 9, 15, TRUE, TRUE, TRUE }, - /* 21 */ { "%TVAR%%TVAR% long", "", 10, 15, TRUE, TRUE, TRUE }, - /* 22 */ { "%TVAR%%TVAR% long", "", 14, 15, FALSE, TRUE, TRUE }, + /* 16 */ { "%TVAR%%TVAR% long", "", 4, 15 }, + /* 17 */ { "%TVAR%%TVAR% long", "", 5, 15 }, + /* 18 */ { "%TVAR%%TVAR% long", "", 6, 15 }, + /* 19 */ { "%TVAR%%TVAR% long", "", 8, 15 }, + /* 20 */ { "%TVAR%%TVAR% long", "", 9, 15 }, + /* 21 */ { "%TVAR%%TVAR% long", "", 10, 15 }, + /* 22 */ { "%TVAR%%TVAR% long", "", 14, 15 }, /* 23 */ { "%TVAR%%TVAR% long", "WINEWINE long", 15, 14 }, - /* 24 */ { "%TVAR% %TVAR% long", "", 5, 16, TRUE, TRUE, TRUE }, - /* 25 */ { "%TVAR% %TVAR% long", "", 6, 16, TRUE, TRUE, TRUE }, - /* 26 */ { "%TVAR% %TVAR% long", "", 8, 16, TRUE, TRUE, TRUE }, - /* 27 */ { "%TVAR% %TVAR% long", "", 9, 16, TRUE, TRUE, TRUE }, - /* 28 */ { "%TVAR% %TVAR% long", "", 10, 16, TRUE, TRUE, TRUE }, - /* 29 */ { "%TVAR% %TVAR% long", "", 11, 16, TRUE, TRUE, TRUE }, - /* 30 */ { "%TVAR% %TVAR% long", "", 12, 16, TRUE, TRUE, TRUE }, - /* 31 */ { "%TVAR% %TVAR% long", "", 14, 16, TRUE, TRUE, TRUE }, - /* 32 */ { "%TVAR% %TVAR% long", "", 15, 16, FALSE, TRUE, TRUE }, + /* 24 */ { "%TVAR% %TVAR% long", "", 5, 16 }, + /* 25 */ { "%TVAR% %TVAR% long", "", 6, 16 }, + /* 26 */ { "%TVAR% %TVAR% long", "", 8, 16 }, + /* 27 */ { "%TVAR% %TVAR% long", "", 9, 16 }, + /* 28 */ { "%TVAR% %TVAR% long", "", 10, 16 }, + /* 29 */ { "%TVAR% %TVAR% long", "", 11, 16 }, + /* 30 */ { "%TVAR% %TVAR% long", "", 12, 16 }, + /* 31 */ { "%TVAR% %TVAR% long", "", 14, 16 }, + /* 32 */ { "%TVAR% %TVAR% long", "", 15, 16 }, /* 33 */ { "%TVAR% %TVAR% long", "WINE WINE long", 16, 15 }, - /* 34 */ { "%TVAR2% long long", "", 1, 19, TRUE, TRUE, TRUE }, - /* 35 */ { "%TVAR2% long long", "", 2, 19, TRUE, TRUE, TRUE }, - /* 36 */ { "%TVAR2% long long", "", 4, 19, TRUE, TRUE, TRUE }, - /* 37 */ { "%TVAR2% long long", "", 7, 19, TRUE, TRUE, TRUE }, - /* 38 */ { "%TVAR2% long long", "", 8, 19, TRUE, TRUE, TRUE }, - /* 39 */ { "%TVAR2% long long", "", 9, 19, TRUE, TRUE, TRUE }, - /* 40 */ { "%TVAR2% long long", "", 10, 19, TRUE, TRUE, TRUE }, - /* 41 */ { "%TVAR2% long long", "", 18, 19, FALSE, TRUE, TRUE }, + /* 34 */ { "%TVAR2% long long", "", 1, 19 }, + /* 35 */ { "%TVAR2% long long", "", 2, 19 }, + /* 36 */ { "%TVAR2% long long", "", 4, 19 }, + /* 37 */ { "%TVAR2% long long", "", 7, 19 }, + /* 38 */ { "%TVAR2% long long", "", 8, 19 }, + /* 39 */ { "%TVAR2% long long", "", 9, 19 }, + /* 40 */ { "%TVAR2% long long", "", 10, 19 }, + /* 41 */ { "%TVAR2% long long", "", 18, 19 }, /* 42 */ { "%TVAR2% long long", "%TVAR2% long long", 19, 18 }, - /* 43 */ { "%TVAR long long", "", 1, 17, TRUE, TRUE, TRUE }, - /* 44 */ { "%TVAR long long", "", 2, 17, TRUE, TRUE, TRUE }, - /* 45 */ { "%TVAR long long", "", 3, 17, TRUE, TRUE, TRUE }, - /* 46 */ { "%TVAR long long", "", 15, 17, TRUE, TRUE, TRUE }, - /* 47 */ { "%TVAR long long", "", 16, 17, FALSE, TRUE, TRUE }, + /* 43 */ { "%TVAR long long", "", 1, 17 }, + /* 44 */ { "%TVAR long long", "", 2, 17 }, + /* 45 */ { "%TVAR long long", "", 3, 17 }, + /* 46 */ { "%TVAR long long", "", 15, 17 }, + /* 47 */ { "%TVAR long long", "", 16, 17 }, /* 48 */ { "%TVAR long long", "%TVAR long long", 17, 16 }, };
@@ -653,23 +653,17 @@ static void test_ExpandEnvironmentStringsA(void) SetLastError(0xdeadbeef); ret_size = ExpandEnvironmentStringsA(japanese_test, NULL, 0); ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); - todo_wine ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size);
SetLastError(0xdeadbeef); ret_size = ExpandEnvironmentStringsA(japanese_test, buf, ret_size); - todo_wine ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); - todo_wine ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); - todo_wine ok(!strcmp(buf, japanese_test), "Got %s\n", debugstr_a(buf));
SetLastError(0xdeadbeef); ret_size = ExpandEnvironmentStringsA(japanese_test, buf, japanese_len / 2); /* Buffer too small */ - todo_wine ok(GetLastError() == 0xdeadbeef, "got last error %ld\n", GetLastError()); - todo_wine ok(ret_size >= japanese_len, "Needed at least %d, got %lu\n", japanese_len, ret_size); } else diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index c6f2f30b2d8..09e6547245d 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -1447,20 +1447,32 @@ DWORD WINAPI DECLSPEC_HOTPATCH ExpandEnvironmentStringsA( LPCSTR src, LPSTR dst, { UNICODE_STRING us_src; PWSTR dstW = NULL; - DWORD ret; + DWORD count_neededW; + DWORD count_neededA = 0;
RtlCreateUnicodeStringFromAsciiz( &us_src, src ); - if (count) - { - if (!(dstW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR)))) return 0; - ret = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count); - if (ret) WideCharToMultiByte( CP_ACP, 0, dstW, ret, dst, count, NULL, NULL ); - } - else ret = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 );
+ /* We always need to call ExpandEnvironmentStringsW, since we need the result to calculate the needed buffer size */ + count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, NULL, 0 ); + if (!(dstW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count_neededW * sizeof(WCHAR) ))) goto cleanup; + count_neededW = ExpandEnvironmentStringsW( us_src.Buffer, dstW, count_neededW ); + + /* Calculate needed buffer */ + count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, NULL, 0, NULL, NULL ); + + /* If provided buffer is enough, do actual conversion */ + if (count > count_neededA) + count_neededA = WideCharToMultiByte( CP_ACP, 0, dstW, count_neededW, dst, count, NULL, NULL ); + else if(dst) + *dst = 0; + +cleanup: RtlFreeUnicodeString( &us_src ); HeapFree( GetProcessHeap(), 0, dstW ); - return ret; + + if (count_neededA >= count) /* When the buffer is too small, native over-reports by one byte */ + return count_neededA + 1; + return count_neededA; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147382
Your paranoid android.
=== debian11b (64 bit WoW report) ===
advapi32: registry.c:937: Test succeeded inside todo block: strlen(expanded2)=42, strlen(sTestpath2)=13, size=44
ddraw: ddraw7.c:3741: Test failed: Expected message 0x5, but didn't receive it. ddraw7.c:3743: Test failed: Expected screen size 1024x768, got 0x0.
kernel32: comm.c:1586: Test failed: Unexpected time 1001, expected around 500
shcore: shcore.c:572: Test succeeded inside todo block: Unexpanded string . shcore.c:592: Test succeeded inside todo block: Expected empty or first part of the string "ImARatherLongButIndeedNeededString", got ""
shlwapi: shreg.c:295: Test succeeded inside todo block: Expected empty or unexpanded string (win98), got () shreg.c:321: Test succeeded inside todo block: Expected empty or first part of the string "ImARatherLongButIndeedNeededString", got ""
user32: input.c:733: Test failed: peek: raw_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x46, lparam 0x10001 input.c:733: Test failed: peek: raw_legacy: 0: test->expect 2 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x66, lparam 0x10001 input.c:734: Test failed: peek: raw_legacy: 0: got F: 0 input.c:733: Test failed: peek: raw_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x46, lparam 0xffffffffc0020001 input.c:733: Test failed: peek: raw_vk_packet_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0xe7, lparam 0x10001 input.c:734: Test failed: peek: raw_vk_packet_legacy: 0: got 0xe7: 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_vk_packet_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0xe7, lparam 0xffffffffc0020001 input.c:733: Test failed: peek: raw_unicode_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x3c0, lparam 0x1 input.c:734: Test failed: peek: raw_unicode_legacy: 0: got 0xe7: 0 input.c:733: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x11, lparam 0xc00001 input.c:734: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: got VK_CONTROL: 0 input.c:734: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 0: got VK_LCONTROL: 0 input.c:733: Test failed: peek: raw_unicode_vkey_ctrl_legacy: 1: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x11, lparam 0xffffffffc0c00001 input.c:733: Test failed: peek: raw_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: peek: raw_vk_packet_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: peek: raw_vk_packet_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x46, lparam 0x10001 input.c:733: Test failed: receive: raw_legacy: 0: test->expect 2 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x66, lparam 0x10001 input.c:734: Test failed: receive: raw_legacy: 0: got F: 0 input.c:733: Test failed: receive: raw_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x46, lparam 0xffffffffc0020001 input.c:733: Test failed: receive: raw_vk_packet_legacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0xe7, lparam 0x10001 input.c:734: Test failed: receive: raw_vk_packet_legacy: 0: got 0xe7: 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_vk_packet_legacy: 1: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0xe7, lparam 0xffffffffc0020001 input.c:733: Test failed: receive: raw_unicode_legacy: 0: test->expect 1 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_CHAR, wparam 0x3c0, lparam 0x1 input.c:734: Test failed: receive: raw_unicode_legacy: 0: got 0xe7: 0 input.c:733: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYDOWN, wparam 0x11, lparam 0xc00001 input.c:734: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: got VK_CONTROL: 0 input.c:734: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 0: got VK_LCONTROL: 0 input.c:733: Test failed: receive: raw_unicode_vkey_ctrl_legacy: 1: test->expect 0 (missing): MSG_TEST_WIN hwnd 0000000000000000, WM_KEYUP, wparam 0x11, lparam 0xffffffffc0c00001 input.c:733: Test failed: receive: raw_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey F, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey F, message WM_KEYUP, extra 0 input.c:733: Test failed: receive: raw_vk_packet_nolegacy: 0: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x1, flags 0, vkey 0xe7, message WM_KEYDOWN, extra 0 input.c:733: Test failed: receive: raw_vk_packet_nolegacy: 1: test->expect 0 (missing): got WM_INPUT key hwnd 0000000000000000, code 0, make_code 0x2, flags 0x1, vkey 0xe7, message WM_KEYUP, extra 0
userenv: userenv.c:297: Test failed: expected 9, got 8
Finally came back to this, would you mind taking another look? The issue went a lot deeper, so I added a bunch of tests for all affected functions, and adjusted them one by another.