From 6517f6c239e9f6b7909daefa3680365bbbdbbe1f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 7 Apr 2022 11:21:21 +0200 Subject: [PATCH] kernelbase: Implement NlsValidateLocale(). Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/locale.c | 82 +++++++++++++++++++++++++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/locale.c | 46 ++++++++++++----------- 3 files changed, 108 insertions(+), 22 deletions(-) diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 31cfb465798..9b95fcae640 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -86,6 +86,7 @@ static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG* static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR); static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int); static INT (WINAPI *pFindNLSStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT, LPINT, LPNLSVERSIONINFO, LPVOID, LPARAM); +static void * (WINAPI *pNlsValidateLocale)(LCID*,ULONG); static LANGID (WINAPI *pSetThreadUILanguage)(LANGID); static LANGID (WINAPI *pGetThreadUILanguage)(VOID); static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT); @@ -144,6 +145,9 @@ static void InitFunctionPointers(void) X(GetNLSVersionEx); X(IsValidNLSVersion); + mod = GetModuleHandleA("kernelbase"); + X(NlsValidateLocale); + mod = GetModuleHandleA("ntdll"); X(RtlUpcaseUnicodeChar); X(RtlLocaleNameToLcid); @@ -3005,6 +3009,84 @@ static void test_LocaleNameToLCID(void) RtlFreeUnicodeString( &str ); } else win_skip( "RtlLcidToLocaleName not available\n" ); + + if (pNlsValidateLocale) + { + void *ret, *ret2; + LCID lcid; + + lcid = LOCALE_NEUTRAL; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == GetUserDefaultLCID(), "wrong lcid %04lx\n", lcid ); + + lcid = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), "wrong lcid %04lx\n", lcid ); + + lcid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL); + ret2 = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret2, "failed for %04lx\n", lcid ); + ok( ret == ret2, "got different pointer for neutral\n" ); + ok( lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), "wrong lcid %04lx\n", lcid ); + + lcid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL); + ret2 = pNlsValidateLocale( &lcid, LOCALE_ALLOW_NEUTRAL_NAMES ); + ok( !!ret2, "failed for %04lx\n", lcid ); + ok( ret != ret2, "got same pointer for neutral\n" ); + ok( lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), "wrong lcid %04lx\n", lcid ); + + lcid = 0x00010407; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == 0x00010407, "wrong lcid %04lx\n", lcid ); + + lcid = LOCALE_SYSTEM_DEFAULT; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == GetSystemDefaultLCID(), "wrong lcid %04lx\n", lcid ); + ret2 = pNlsValidateLocale( &lcid, 0 ); + ok( ret == ret2, "got different pointer for system\n" ); + + lcid = LOCALE_USER_DEFAULT; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == GetUserDefaultLCID(), "wrong lcid %04lx\n", lcid ); + ret2 = pNlsValidateLocale( &lcid, 0 ); + ok( ret == ret2, "got different pointer for user\n" ); + + lcid = LOCALE_INVARIANT; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == LOCALE_INVARIANT, "wrong lcid %04lx\n", lcid ); + ret2 = pNlsValidateLocale( &lcid, 0 ); + ok( ret == ret2, "got different pointer for invariant\n" ); + + lcid = LOCALE_CUSTOM_DEFAULT; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !!ret, "failed for %04lx\n", lcid ); + ok( lcid == GetUserDefaultLCID(), "wrong lcid %04lx\n", lcid ); + ret2 = pNlsValidateLocale( &lcid, 0 ); + ok( ret == ret2, "got different pointer for custom default\n" ); + + lcid = LOCALE_CUSTOM_UNSPECIFIED; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( ret || broken(!ret), /* <= win8 */ "failed for %04lx\n", lcid ); + if (ret) ok( lcid == GetUserDefaultLCID(), "wrong lcid %04lx\n", lcid ); + + SetLastError( 0xdeadbeef ); + lcid = LOCALE_CUSTOM_UI_DEFAULT; + ret = pNlsValidateLocale( &lcid, 0 ); + if (!ret) ok( GetLastError() == 0xdeadbeef, "error %lu\n", GetLastError()); + + lcid = 0xbeef; + ret = pNlsValidateLocale( &lcid, 0 ); + ok( !ret, "succeeded\n" ); + ok( lcid == 0xbeef, "wrong lcid %04lx\n", lcid ); + ok( GetLastError() == 0xdeadbeef, "error %lu\n", GetLastError()); + } + else win_skip( "NlsValidateLocale not available\n" ); } /* this requires collation table patch to make it MS compatible */ diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index b5116ae9b5a..9c14a9fbd23 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1001,7 +1001,7 @@ @ stub NlsIsUserDefaultLocale @ stub NlsUpdateLocale @ stub NlsUpdateSystemLocale -@ stub NlsValidateLocale +@ stdcall NlsValidateLocale(ptr long) @ stub NlsWriteEtwEvent @ stdcall NormalizeString(long wstr long ptr long) @ stub NotifyMountMgr diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 8121efb8651..2c2a47a08b8 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -561,8 +561,14 @@ static const NLS_LOCALE_DATA *get_locale_by_name( const WCHAR *name, LCID *lcid } -static const NLS_LOCALE_DATA *get_locale_by_id( LCID *lcid, DWORD flags ) +/****************************************************************************** + * NlsValidateLocale (kernelbase.@) + * + * Note: it seems to return some internal data on Windows, we simply return the locale.nls data pointer. + */ +const NLS_LOCALE_DATA * WINAPI NlsValidateLocale( LCID *lcid, ULONG flags ) { + const NLS_LOCALE_LCNAME_INDEX *name_entry; const NLS_LOCALE_LCID_INDEX *entry; const NLS_LOCALE_DATA *locale; @@ -581,8 +587,9 @@ static const NLS_LOCALE_DATA *get_locale_by_id( LCID *lcid, DWORD flags ) default: if (!(entry = find_lcid_entry( *lcid ))) return NULL; locale = get_locale_data( entry->idx ); - if (!(flags & LOCALE_ALLOW_NEUTRAL_NAMES) && !locale->inotneutral) - locale = get_locale_by_name( locale_strings + locale->ssortlocale + 1, lcid ); + if ((flags & LOCALE_ALLOW_NEUTRAL_NAMES) || locale->inotneutral) return locale; + if ((name_entry = find_lcname_entry( locale_strings + locale->ssortlocale + 1 ))) + locale = get_locale_data( name_entry->idx ); return locale; } } @@ -1756,27 +1763,23 @@ void init_locale( HMODULE module ) NtQueryDefaultLocale( FALSE, &system_lcid ); NtQueryDefaultLocale( FALSE, &user_lcid ); - if (!(system_locale = get_locale_by_id( &system_lcid, 0 ))) + if (!(system_locale = NlsValidateLocale( &system_lcid, 0 ))) { if (GetEnvironmentVariableW( L"WINELOCALE", bufferW, ARRAY_SIZE(bufferW) )) - { system_locale = get_locale_by_name( bufferW, &system_lcid ); - if (system_lcid == LOCALE_CUSTOM_UNSPECIFIED) system_lcid = LOCALE_CUSTOM_DEFAULT; - } + if (!system_locale) system_locale = get_locale_by_name( L"en-US", &system_lcid ); } - if (!(user_locale = get_locale_by_id( &user_lcid, 0 ))) + system_lcid = system_locale->ilanguage; + if (system_lcid == LOCALE_CUSTOM_UNSPECIFIED) system_lcid = LOCALE_CUSTOM_DEFAULT; + + if (!(user_locale = NlsValidateLocale( &user_lcid, 0 ))) { if (GetEnvironmentVariableW( L"WINEUSERLOCALE", bufferW, ARRAY_SIZE(bufferW) )) - { user_locale = get_locale_by_name( bufferW, &user_lcid ); - if (user_lcid == LOCALE_CUSTOM_UNSPECIFIED) user_lcid = LOCALE_CUSTOM_DEFAULT; - } - else - { - user_locale = system_locale; - user_lcid = system_lcid; - } + if (!user_locale) user_locale = system_locale; } + user_lcid = user_locale->ilanguage; + if (user_lcid == LOCALE_CUSTOM_UNSPECIFIED) user_lcid = LOCALE_CUSTOM_DEFAULT; if (GetEnvironmentVariableW( L"WINEUNIXCP", bufferW, ARRAY_SIZE(bufferW) )) unix_cp = wcstoul( bufferW, NULL, 10 ); @@ -4140,7 +4143,8 @@ INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1, */ LCID WINAPI DECLSPEC_HOTPATCH ConvertDefaultLocale( LCID lcid ) { - get_locale_by_id( &lcid, 0 ); + const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 ); + if (locale) lcid = locale->ilanguage; return lcid; } @@ -4848,7 +4852,7 @@ INT WINAPI DECLSPEC_HOTPATCH GetCalendarInfoW( LCID lcid, CALID calendar, CALTYP TRACE( "%04lx %lu 0x%lx %p %d %p\n", lcid, calendar, type, buffer, len, value ); - if (!(locale = get_locale_by_id( &lcid, 0 ))) + if (!(locale = NlsValidateLocale( &lcid, 0 ))) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; @@ -5063,7 +5067,7 @@ INT WINAPI DECLSPEC_HOTPATCH GetLocaleInfoW( LCID lcid, LCTYPE lctype, WCHAR *bu TRACE( "(lcid=0x%lx,lctype=0x%lx,%p,%d)\n", lcid, lctype, buffer, len ); - if (!(locale = get_locale_by_id( &lcid, 0 ))) + if (!(locale = NlsValidateLocale( &lcid, 0 ))) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; @@ -5715,7 +5719,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocale( LCID lcid, DWORD flags ) case LOCALE_SYSTEM_DEFAULT: return FALSE; default: - return !!get_locale_by_id( &lcid, LOCALE_ALLOW_NEUTRAL_NAMES ); + return !!NlsValidateLocale( &lcid, LOCALE_ALLOW_NEUTRAL_NAMES ); } } @@ -5768,7 +5772,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH IsValidNLSVersion( NLS_FUNCTION func, const WCHAR */ INT WINAPI DECLSPEC_HOTPATCH LCIDToLocaleName( LCID lcid, WCHAR *name, INT count, DWORD flags ) { - const NLS_LOCALE_DATA *locale = get_locale_by_id( &lcid, flags ); + const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, flags ); if (!locale) { -- 2.11.4.GIT