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