kernelbase: Implement ResolveLocaleName().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-05-02 14:12:10 +02:00
parent 1adb4b52ff
commit ea1eae646d
2 changed files with 108 additions and 3 deletions

View File

@ -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();

View File

@ -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;
}