Alexandre Julliard : kernelbase: Fix IsValidLocale() and GetLocaleInfo() with special LOCALE_* identifiers.
Alexandre Julliard
julliard at winehq.org
Thu Apr 7 16:19:07 CDT 2022
Module: wine
Branch: master
Commit: 812ebc67a4bf2830ee96eeb5c40e26eefb457500
URL: https://source.winehq.org/git/wine.git/?a=commit;h=812ebc67a4bf2830ee96eeb5c40e26eefb457500
Author: Alexandre Julliard <julliard at 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 at 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))
{
More information about the wine-cvs
mailing list