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
-- v7: kernel32: Rework ExpandEnvironmentStringsA to return ansi size and fix corner cases. kernel32: Rework ExpandEnvironmentStringsW error handling. ntdll: Rework RtlExpandEnvironmentStrings/_U to account for corner cases. kernel32: Add ExpandEnvironmentStringsA tests for japanese. kernel32: Add more tests for ExpandEnvironmentStringsA. kernel32: Add tests for ExpandEnvironmentStringsW. ntdll: Add more tests for RtlExpandEnvironmentStrings/_U.
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..ad653afa439 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 %Iu\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 %Iu\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 ad653afa439..1760501a434 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=147383
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
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:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000016C00DE, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
userenv: userenv.c:297: Test failed: expected 9, got 8