Module: wine Branch: master Commit: 812ebc67a4bf2830ee96eeb5c40e26eefb457500 URL: https://source.winehq.org/git/wine.git/?a=commit;h=812ebc67a4bf2830ee96eeb5c...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Apr 7 11:13:06 2022 +0200
kernelbase: Fix IsValidLocale() and GetLocaleInfo() with special LOCALE_* identifiers.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/lcformat.c | 2 ++ dlls/kernel32/tests/locale.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ dlls/kernelbase/locale.c | 16 ++++++++++++---- dlls/msvcrt/locale.c | 2 ++ 4 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/lcformat.c b/dlls/kernel32/lcformat.c index e029f328544..7f112767880 100644 --- a/dlls/kernel32/lcformat.c +++ b/dlls/kernel32/lcformat.c @@ -1108,6 +1108,7 @@ INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, TRACE("(0x%04lx,0x%08lx,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue), lpFormat, lpNumberStr, cchOut);
+ lcid = ConvertDefaultLocale(lcid); if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpNumberStr) || !IsValidLocale(lcid, 0) || (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep))) @@ -1498,6 +1499,7 @@ INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, TRACE("(0x%04lx,0x%08lx,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue), lpFormat, lpCurrencyStr, cchOut);
+ lcid = ConvertDefaultLocale(lcid); if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpCurrencyStr) || !IsValidLocale(lcid, 0) || (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep || diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 3b43dea2a2b..31cfb465798 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -266,6 +266,20 @@ static void test_GetLocaleInfoA(void) "got %d with '%s' (expected %d with '%s')\n", ret, buffer, len, expected);
+ len = GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_SLANGUAGE, expected, ARRAY_SIZE(expected)); + ret = GetLocaleInfoA(LOCALE_NEUTRAL, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer)); + ok( (ret == len) && !lstrcmpA(buffer, expected), "got %d with '%s' (expected %d with '%s')\n", + ret, buffer, len, expected); + ret = GetLocaleInfoA(LOCALE_CUSTOM_DEFAULT, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer)); + ok( (ret == len) && !lstrcmpA(buffer, expected), "got %d with '%s' (expected %d with '%s')\n", + ret, buffer, len, expected); + ret = GetLocaleInfoA(LOCALE_CUSTOM_UNSPECIFIED, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer)); + ok( (ret == len && !lstrcmpA(buffer, expected)) || broken(!ret), /* <= win8 */ + "got %d with '%s' (expected %d with '%s')\n", ret, buffer, len, expected); + len = GetLocaleInfoA(GetUserDefaultUILanguage(), LOCALE_SLANGUAGE, expected, ARRAY_SIZE(expected)); + ret = GetLocaleInfoA(LOCALE_CUSTOM_UI_DEFAULT, LOCALE_SLANGUAGE, buffer, ARRAY_SIZE(buffer)); + if (ret) ok( (ret == len && !lstrcmpA(buffer, expected)), + "got %d with '%s' (expected %d with '%s')\n", ret, buffer, len, expected);
/* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to * partially fill the buffer even if it is too short. See bug 637. @@ -2675,6 +2689,7 @@ static void test_LocaleNameToLCID(void) NTSTATUS status; INT ret; WCHAR buffer[LOCALE_NAME_MAX_LENGTH]; + WCHAR expbuff[LOCALE_NAME_MAX_LENGTH]; const struct neutralsublang_name_t *ptr;
if (!pLocaleNameToLCID) @@ -2710,6 +2725,25 @@ static void test_LocaleNameToLCID(void) ok(ret > 0, "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); trace("%08lx, %s\n", lcid, wine_dbgstr_w(buffer));
+ pLCIDToLocaleName(GetUserDefaultLCID(), expbuff, LOCALE_NAME_MAX_LENGTH, 0); + ret = pLCIDToLocaleName(LOCALE_NEUTRAL, buffer, LOCALE_NAME_MAX_LENGTH, 0); + ok(ret > 0, "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); + ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + + ret = pLCIDToLocaleName(LOCALE_CUSTOM_DEFAULT, buffer, LOCALE_NAME_MAX_LENGTH, 0); + ok(ret > 0, "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); + ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + + SetLastError( 0xdeadbeef ); + ret = pLCIDToLocaleName(LOCALE_CUSTOM_UNSPECIFIED, buffer, LOCALE_NAME_MAX_LENGTH, 0); + ok(ret > 0 || broken(!ret), /* <= win8 */ "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); + if (ret) ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + + SetLastError( 0xdeadbeef ); + ret = pLCIDToLocaleName(LOCALE_CUSTOM_UI_DEFAULT, buffer, LOCALE_NAME_MAX_LENGTH, 0); + if (ret) trace("%08x, %s\n", GetUserDefaultUILanguage(), wine_dbgstr_w(buffer)); + else ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError()); + /* bad name */ SetLastError(0xdeadbeef); lcid = pLocaleNameToLCID(invalidW, 0); @@ -2886,6 +2920,7 @@ static void test_LocaleNameToLCID(void) str.MaximumLength = sizeof( buffer ); memset( buffer, 0xcc, sizeof(buffer) );
+ ok( !IsValidLocale( LOCALE_NEUTRAL, 0 ), "expected invalid\n" ); status = pRtlLcidToLocaleName( LOCALE_NEUTRAL, &str, 0, 0 ); ok( status == STATUS_INVALID_PARAMETER_1, "wrong error %lx\n", status ); status = pRtlLcidToLocaleName( LOCALE_NEUTRAL, &str, 2, 0 ); @@ -2909,12 +2944,14 @@ static void test_LocaleNameToLCID(void) ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); ok( !wcscmp( buffer, L"en" ), "wrong name %s\n", debugstr_w(buffer) );
+ ok( IsValidLocale( 0x00010407, 0 ), "expected valid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( 0x00010407, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); ok( !wcscmp( buffer, L"de-DE_phoneb" ), "wrong name %s\n", debugstr_w(buffer) );
+ ok( !IsValidLocale( LOCALE_SYSTEM_DEFAULT, 0 ), "expected invalid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( LOCALE_SYSTEM_DEFAULT, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); @@ -2922,6 +2959,7 @@ static void test_LocaleNameToLCID(void) LCIDToLocaleName( GetSystemDefaultLCID(), expect, ARRAY_SIZE(expect), 0 ); ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) );
+ ok( !IsValidLocale( LOCALE_USER_DEFAULT, 0 ), "expected invalid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( LOCALE_USER_DEFAULT, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); @@ -2929,6 +2967,7 @@ static void test_LocaleNameToLCID(void) LCIDToLocaleName( GetUserDefaultLCID(), expect, ARRAY_SIZE(expect), 0 ); ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) );
+ ok( IsValidLocale( LOCALE_INVARIANT, 0 ), "expected valid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( LOCALE_INVARIANT, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); @@ -3655,6 +3694,12 @@ static void test_ConvertDefaultLocale(void) LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID()); LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID()); LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID()); + LCID_RES(LOCALE_CUSTOM_DEFAULT, GetUserDefaultLCID()); + lcid = ConvertDefaultLocale( LOCALE_CUSTOM_UNSPECIFIED ); + ok( lcid == GetUserDefaultLCID() || broken(lcid == LOCALE_CUSTOM_UNSPECIFIED), /* <= win8 */ + "wrong lcid %04lx\n", lcid ); + lcid = ConvertDefaultLocale( LOCALE_CUSTOM_UI_DEFAULT ); + ok( lcid == GetUserDefaultUILanguage() || lcid == LOCALE_CUSTOM_UI_DEFAULT, "wrong lcid %04lx\n", lcid ); lcid = ConvertDefaultLocale(LOCALE_INVARIANT); ok(lcid == LOCALE_INVARIANT || broken(lcid == 0x47f) /* win2k[3]/winxp */, "Expected lcid = %08lx, got %08lx\n", LOCALE_INVARIANT, lcid); diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 66c9a67cf28..8121efb8651 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -574,6 +574,8 @@ static const NLS_LOCALE_DATA *get_locale_by_id( LCID *lcid, DWORD flags ) case LOCALE_NEUTRAL: case LOCALE_USER_DEFAULT: case LOCALE_CUSTOM_DEFAULT: + case LOCALE_CUSTOM_UNSPECIFIED: + case LOCALE_CUSTOM_UI_DEFAULT: *lcid = user_lcid; return user_locale; default: @@ -5406,9 +5408,7 @@ INT WINAPI DECLSPEC_HOTPATCH GetUserDefaultLocaleName( LPWSTR name, INT len ) */ LANGID WINAPI DECLSPEC_HOTPATCH GetUserDefaultUILanguage(void) { - LANGID lang; - NtQueryDefaultUILanguage( &lang ); - return lang; + return LANGIDFROMLCID( GetUserDefaultLCID() ); }
@@ -5708,7 +5708,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLanguageGroup( LGRPID id, DWORD flags ) */ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocale( LCID lcid, DWORD flags ) { - return !!get_locale_by_id( &lcid, LOCALE_ALLOW_NEUTRAL_NAMES ); + switch (lcid) + { + case LOCALE_NEUTRAL: + case LOCALE_USER_DEFAULT: + case LOCALE_SYSTEM_DEFAULT: + return FALSE; + default: + return !!get_locale_by_id( &lcid, LOCALE_ALLOW_NEUTRAL_NAMES ); + } }
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 2421830e7b5..0fd99a40c86 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -262,6 +262,8 @@ find_best_locale_proc( WCHAR *name, DWORD locale_flags, LPARAM lParam ) char buff[MAX_ELEM_LEN]; unsigned int flags = 0;
+ if (lcid == LOCALE_CUSTOM_UNSPECIFIED) return CONTINUE_LOOKING; + #if _MSVCR_VER >= 110 if (res->allow_sname && compare_info(lcid,LOCALE_SNAME,buff,res->search_language, TRUE)) {