Alexandre Julliard : kernelbase: Implement ResolveLocaleName().

Alexandre Julliard julliard at winehq.org
Mon May 2 16:02:10 CDT 2022


Module: wine
Branch: master
Commit: ea1eae646dd8aceb5078a8675e32be65c53da304
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ea1eae646dd8aceb5078a8675e32be65c53da304

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon May  2 14:12:10 2022 +0200

kernelbase: Implement ResolveLocaleName().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/locale.c | 74 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/kernelbase/locale.c     | 37 ++++++++++++++++++++--
 2 files changed, 108 insertions(+), 3 deletions(-)

diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 65687313fbb..dc9fc7c09e6 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -72,6 +72,7 @@ static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
+static INT (WINAPI *pResolveLocaleName)(LPCWSTR,LPWSTR,INT);
 static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
 static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT,
                                       LPNLSVERSIONINFO, LPVOID, LPARAM);
@@ -125,6 +126,7 @@ static void InitFunctionPointers(void)
   X(IdnToUnicode);
   X(GetLocaleInfoEx);
   X(IsValidLocaleName);
+  X(ResolveLocaleName);
   X(CompareStringOrdinal);
   X(CompareStringEx);
   X(GetGeoInfoA);
@@ -5160,6 +5162,77 @@ static void test_IsValidLocaleName(void)
     ok(!ret, "RtlIsValidLocaleName should have failed\n");
 }
 
+static void test_ResolveLocaleName(void)
+{
+    static const struct { const WCHAR *name, *exp; BOOL broken; } tests[] =
+    {
+        { L"en-US", L"en-US" },
+        { L"en", L"en-US" },
+        { L"en-RR", L"en-US" },
+        { L"en-na", L"en-NA", TRUE /* <= win8 */ },
+        { L"EN-zz", L"en-US" },
+        { L"en-US", L"en-US" },
+        { L"de-DE_phoneb", L"de-DE" },
+        { L"DE-de-phoneb", L"de-DE" },
+        { L"fr-029", L"fr-029", TRUE /* <= win8 */ },
+        { L"fr-CH_XX", L"fr-CH", TRUE /* <= win10 1809 */ },
+        { L"fr-CHXX", L"fr-FR" },
+        { L"zh", L"zh-CN" },
+        { L"zh-Hant", L"zh-HK" },
+        { L"zh-hans", L"zh-CN" },
+        { L"ja-jp_radstr", L"ja-JP" },
+        { L"az", L"az-Latn-AZ" },
+        { L"uz", L"uz-Latn-UZ" },
+        { L"uz-cyrl", L"uz-Cyrl-UZ" },
+        { L"ia", L"ia-001", TRUE /* <= win10 1809 */ },
+        { L"zz", L"" },
+        { L"zzz-ZZZ", L"" },
+        { L"zzzz", L"" },
+        { L"zz+XX", NULL },
+        { L"zz.XX", NULL },
+        { LOCALE_NAME_INVARIANT, L"" },
+        { LOCALE_NAME_SYSTEM_DEFAULT, NULL },
+    };
+    INT i, ret;
+    WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
+
+    if (!pResolveLocaleName)
+    {
+        win_skip( "ResolveLocaleName not available\n" );
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        SetLastError( 0xdeadbeef );
+        memset( buffer, 0xcc, sizeof(buffer) );
+        ret = pResolveLocaleName( tests[i].name, buffer, sizeof(buffer) );
+        if (tests[i].exp)
+        {
+            ok( !wcscmp( buffer, tests[i].exp ) || broken( tests[i].broken ),
+                "%s: got %s\n", debugstr_w(tests[i].name), debugstr_w(buffer) );
+            ok( ret == wcslen(buffer) + 1, "%s: got %u\n", debugstr_w(tests[i].name), ret );
+        }
+        else
+        {
+            ok( !ret || broken( ret == 1 ) /* win7 */,
+                "%s: got %s\n", debugstr_w(tests[i].name), debugstr_w(buffer) );
+            if (!ret)
+                ok( GetLastError() == ERROR_INVALID_PARAMETER,
+                    "%s: wrong error %lu\n", debugstr_w(tests[i].name), GetLastError() );
+        }
+    }
+    SetLastError( 0xdeadbeef );
+    ret = pResolveLocaleName( L"en-US", buffer, 4 );
+    ok( !ret, "got %u\n", ret );
+    ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %lu\n", GetLastError() );
+    ok( !wcscmp( buffer, L"en-" ), "got %s\n", debugstr_w(buffer) );
+
+    SetLastError( 0xdeadbeef );
+    ret = pResolveLocaleName( L"en-US", NULL, 0 );
+    ok( ret == 6, "got %u\n", ret );
+    ok( GetLastError() == 0xdeadbeef, "wrong error %lu\n", GetLastError() );
+}
+
 static void test_CompareStringOrdinal(void)
 {
     INT ret;
@@ -7635,6 +7708,7 @@ START_TEST(locale)
   test_GetStringTypeW();
   test_Idn();
   test_IsValidLocaleName();
+  test_ResolveLocaleName();
   test_CompareStringOrdinal();
   test_GetGeoInfo();
   test_EnumSystemGeoID();
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index 25ccfc5f010..b002d219d61 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -6057,10 +6057,41 @@ INT WINAPI DECLSPEC_HOTPATCH NormalizeString(NORM_FORM form, const WCHAR *src, I
  */
 INT WINAPI DECLSPEC_HOTPATCH ResolveLocaleName( LPCWSTR name, LPWSTR buffer, INT len )
 {
-    FIXME( "stub: %s, %p, %d\n", wine_dbgstr_w(name), buffer, len );
+    LCID lcid;
+    UINT pos, datalen;
+    const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
 
-    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
-    return 0;
+    if (!locale)
+    {
+        static const WCHAR valid[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+        WCHAR *p, tmp[LOCALE_NAME_MAX_LENGTH];
+
+        if (wcsspn( name, valid ) < wcslen( name ))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+        lstrcpynW( tmp, name, LOCALE_NAME_MAX_LENGTH );
+        while (!locale)
+        {
+            for (p = tmp + wcslen(tmp) - 1; p >= tmp; p--) if (*p == '-' || *p == '_') break;
+            if (p <= tmp) break;
+            *p = 0;
+            locale = get_locale_by_name( tmp, &lcid );
+        }
+    }
+
+    pos = locale ? (locale->inotneutral ? locale->sname : locale->ssortlocale) : 0;
+    datalen = locale_strings[pos] + 1;
+
+    if (!len) return datalen;
+    lstrcpynW( buffer, locale_strings + pos + 1, len );
+    if (datalen > len)
+    {
+        SetLastError( ERROR_INSUFFICIENT_BUFFER );
+        return 0;
+    }
+    return datalen;
 }
 
 




More information about the wine-cvs mailing list