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
-- v9: userenv: Fix GetProfilesDirectoryA return value 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. userenv: Add another test for GetProfilesDirectoryA
From: Fabian Maurer dark.shadow4@web.de
--- dlls/userenv/tests/userenv.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/userenv/tests/userenv.c b/dlls/userenv/tests/userenv.c index a440f538723..7639f8470c1 100644 --- a/dlls/userenv/tests/userenv.c +++ b/dlls/userenv/tests/userenv.c @@ -296,6 +296,9 @@ static void test_get_profiles_dir(void) */ ok(profiles_len - 1 == r, "expected %ld, got %d\n", profiles_len - 1, r); ok(!strcmp(buf, profiles_dir), "expected %s, got %s\n", profiles_dir, buf); + ok(strlen(buf) + 1 == cch, "String length is %u, but cch is %lu\n", strlen(buf), cch); + todo_wine + ok(strlen(buf) + 1 == r, "String length is %u, but returned count is %u\n", strlen(buf), r);
HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, profiles_dir);
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 +++++++++++++++++------------------ dlls/shcore/tests/shcore.c | 3 -- dlls/shlwapi/tests/shreg.c | 7 +--- 5 files changed, 59 insertions(+), 56 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 }, }; diff --git a/dlls/shcore/tests/shcore.c b/dlls/shcore/tests/shcore.c index af6b3b392f3..731fa340e8b 100644 --- a/dlls/shcore/tests/shcore.c +++ b/dlls/shcore/tests/shcore.c @@ -567,10 +567,7 @@ static void test_SHQueryValueEx(void) ret = pSHQueryValueExA(hKey, "Test3", NULL, &type, buf, &size); ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
- todo_wine - { ok(!strcmp("", buf), "Unexpanded string %s.\n", buf); - }
ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2); ok(type == REG_SZ, "Unexpected type %ld.\n", type); diff --git a/dlls/shlwapi/tests/shreg.c b/dlls/shlwapi/tests/shreg.c index bc411779c8f..75d4dfae7eb 100644 --- a/dlls/shlwapi/tests/shreg.c +++ b/dlls/shlwapi/tests/shreg.c @@ -290,11 +290,8 @@ static void test_SHQueryValueEx(void) broken(ERROR_SUCCESS == dwRet), /* < IE5.5*/ "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
- todo_wine - { - ok( (0 == strcmp("", buf)) || (0 == strcmp(sTestpath2, buf)), - "Expected empty or unexpanded string (win98), got (%s)\n", buf); - } + ok( (0 == strcmp("", buf)) || (0 == strcmp(sTestpath2, buf)), + "Expected empty or unexpanded string (win98), got (%s)\n", buf);
ok( dwSize >= nUsedBuffer2 || broken(dwSize == (strlen("") + 1)), /* < IE 5.5 */
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/advapi32/tests/registry.c | 2 +- dlls/kernel32/tests/environ.c | 92 ++++++++++++++++------------------ dlls/kernelbase/process.c | 30 +++++++---- dlls/shcore/tests/shcore.c | 3 -- dlls/shlwapi/tests/shreg.c | 9 ++-- dlls/userenv/tests/userenv.c | 1 + 6 files changed, 69 insertions(+), 68 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 0f77b2fa066..2e4195e723f 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -934,7 +934,7 @@ static void test_get_value(void) size = 0; ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size); ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret); - todo_wine ok(size == strlen(expanded2)+2, + ok(size == strlen(expanded2)+2, "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%ld\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
/* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */ 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; }
diff --git a/dlls/shcore/tests/shcore.c b/dlls/shcore/tests/shcore.c index 731fa340e8b..3e621c8b950 100644 --- a/dlls/shcore/tests/shcore.c +++ b/dlls/shcore/tests/shcore.c @@ -584,11 +584,8 @@ static void test_SHQueryValueEx(void) ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size); ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
- todo_wine - { ok( (0 == strcmp("", buf)) || (0 == strcmp(test_envvar2, buf)), "Expected empty or first part of the string "%s", got "%s"\n", test_envvar2, buf); - }
ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2); ok(type == REG_SZ, "Unexpected type %ld.\n", type); diff --git a/dlls/shlwapi/tests/shreg.c b/dlls/shlwapi/tests/shreg.c index 75d4dfae7eb..72ca470856e 100644 --- a/dlls/shlwapi/tests/shreg.c +++ b/dlls/shlwapi/tests/shreg.c @@ -313,12 +313,9 @@ static void test_SHQueryValueEx(void) broken(ERROR_SUCCESS == dwRet), /* < IE5.5 */ "Expected ERROR_MORE_DATA, got (%lu)\n", dwRet);
- todo_wine - { - ok( (0 == strcmp("", buf)) || (0 == strcmp(sEnvvar2, buf)) || - broken(0 == strcmp(sTestpath2, buf)), /* IE 5.5 */ - "Expected empty or first part of the string "%s", got "%s"\n", sEnvvar2, buf); - } + ok( (0 == strcmp("", buf)) || (0 == strcmp(sEnvvar2, buf)) || + broken(0 == strcmp(sTestpath2, buf)), /* IE 5.5 */ + "Expected empty or first part of the string "%s", got "%s"\n", sEnvvar2, buf);
ok( dwSize >= nUsedBuffer2 || broken(dwSize == (strlen(sEnvvar2) + 1)) || /* IE4.01 SP1 (W98) and IE5 (W98SE) */ diff --git a/dlls/userenv/tests/userenv.c b/dlls/userenv/tests/userenv.c index 7639f8470c1..5ef6374fae8 100644 --- a/dlls/userenv/tests/userenv.c +++ b/dlls/userenv/tests/userenv.c @@ -294,6 +294,7 @@ static void test_get_profiles_dir(void) /* Rather than a BOOL, the return value is also the number of characters * stored in the buffer. */ + todo_wine ok(profiles_len - 1 == r, "expected %ld, got %d\n", profiles_len - 1, r); ok(!strcmp(buf, profiles_dir), "expected %s, got %s\n", profiles_dir, buf); ok(strlen(buf) + 1 == cch, "String length is %u, but cch is %lu\n", strlen(buf), cch);
From: Fabian Maurer dark.shadow4@web.de
This is now handled by ExpandEnvironmentStringsA, as should be --- dlls/userenv/tests/userenv.c | 2 -- dlls/userenv/userenv_main.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/dlls/userenv/tests/userenv.c b/dlls/userenv/tests/userenv.c index 5ef6374fae8..9c4d108a95d 100644 --- a/dlls/userenv/tests/userenv.c +++ b/dlls/userenv/tests/userenv.c @@ -294,11 +294,9 @@ static void test_get_profiles_dir(void) /* Rather than a BOOL, the return value is also the number of characters * stored in the buffer. */ - todo_wine ok(profiles_len - 1 == r, "expected %ld, got %d\n", profiles_len - 1, r); ok(!strcmp(buf, profiles_dir), "expected %s, got %s\n", profiles_dir, buf); ok(strlen(buf) + 1 == cch, "String length is %u, but cch is %lu\n", strlen(buf), cch); - todo_wine ok(strlen(buf) + 1 == r, "String length is %u, but returned count is %u\n", strlen(buf), r);
HeapFree(GetProcessHeap(), 0, buf); diff --git a/dlls/userenv/userenv_main.c b/dlls/userenv/userenv_main.c index dd04c40446e..de79156df3c 100644 --- a/dlls/userenv/userenv_main.c +++ b/dlls/userenv/userenv_main.c @@ -512,8 +512,7 @@ BOOL WINAPI GetProfilesDirectoryA( LPSTR lpProfilesDir, LPDWORD lpcchSize ) } *lpcchSize = expanded_len - 1; /* The return value is also the expected length. */ - ret = ExpandEnvironmentStringsA(unexpanded_profiles_dir, lpProfilesDir, - expanded_len) - 1; + ret = ExpandEnvironmentStringsA(unexpanded_profiles_dir, lpProfilesDir, expanded_len); end: HeapFree(GetProcessHeap(), 0, unexpanded_profiles_dir); RegCloseKey(key);