Commit 6517f6c2 authored by Alexandre Julliard's avatar Alexandre Julliard

kernelbase: Implement NlsValidateLocale().

parent 812ebc67
...@@ -86,6 +86,7 @@ static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG* ...@@ -86,6 +86,7 @@ static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*
static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR); static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int); 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 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 *pSetThreadUILanguage)(LANGID);
static LANGID (WINAPI *pGetThreadUILanguage)(VOID); static LANGID (WINAPI *pGetThreadUILanguage)(VOID);
static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT); static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT);
...@@ -144,6 +145,9 @@ static void InitFunctionPointers(void) ...@@ -144,6 +145,9 @@ static void InitFunctionPointers(void)
X(GetNLSVersionEx); X(GetNLSVersionEx);
X(IsValidNLSVersion); X(IsValidNLSVersion);
mod = GetModuleHandleA("kernelbase");
X(NlsValidateLocale);
mod = GetModuleHandleA("ntdll"); mod = GetModuleHandleA("ntdll");
X(RtlUpcaseUnicodeChar); X(RtlUpcaseUnicodeChar);
X(RtlLocaleNameToLcid); X(RtlLocaleNameToLcid);
...@@ -3005,6 +3009,84 @@ static void test_LocaleNameToLCID(void) ...@@ -3005,6 +3009,84 @@ static void test_LocaleNameToLCID(void)
RtlFreeUnicodeString( &str ); RtlFreeUnicodeString( &str );
} }
else win_skip( "RtlLcidToLocaleName not available\n" ); 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 */ /* this requires collation table patch to make it MS compatible */
......
...@@ -1001,7 +1001,7 @@ ...@@ -1001,7 +1001,7 @@
@ stub NlsIsUserDefaultLocale @ stub NlsIsUserDefaultLocale
@ stub NlsUpdateLocale @ stub NlsUpdateLocale
@ stub NlsUpdateSystemLocale @ stub NlsUpdateSystemLocale
@ stub NlsValidateLocale @ stdcall NlsValidateLocale(ptr long)
@ stub NlsWriteEtwEvent @ stub NlsWriteEtwEvent
@ stdcall NormalizeString(long wstr long ptr long) @ stdcall NormalizeString(long wstr long ptr long)
@ stub NotifyMountMgr @ stub NotifyMountMgr
......
...@@ -561,8 +561,14 @@ static const NLS_LOCALE_DATA *get_locale_by_name( const WCHAR *name, LCID *lcid ...@@ -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_LCID_INDEX *entry;
const NLS_LOCALE_DATA *locale; const NLS_LOCALE_DATA *locale;
...@@ -581,8 +587,9 @@ static const NLS_LOCALE_DATA *get_locale_by_id( LCID *lcid, DWORD flags ) ...@@ -581,8 +587,9 @@ static const NLS_LOCALE_DATA *get_locale_by_id( LCID *lcid, DWORD flags )
default: default:
if (!(entry = find_lcid_entry( *lcid ))) return NULL; if (!(entry = find_lcid_entry( *lcid ))) return NULL;
locale = get_locale_data( entry->idx ); locale = get_locale_data( entry->idx );
if (!(flags & LOCALE_ALLOW_NEUTRAL_NAMES) && !locale->inotneutral) if ((flags & LOCALE_ALLOW_NEUTRAL_NAMES) || locale->inotneutral) return locale;
locale = get_locale_by_name( locale_strings + locale->ssortlocale + 1, lcid ); if ((name_entry = find_lcname_entry( locale_strings + locale->ssortlocale + 1 )))
locale = get_locale_data( name_entry->idx );
return locale; return locale;
} }
} }
...@@ -1756,27 +1763,23 @@ void init_locale( HMODULE module ) ...@@ -1756,27 +1763,23 @@ void init_locale( HMODULE module )
NtQueryDefaultLocale( FALSE, &system_lcid ); NtQueryDefaultLocale( FALSE, &system_lcid );
NtQueryDefaultLocale( FALSE, &user_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) )) if (GetEnvironmentVariableW( L"WINELOCALE", bufferW, ARRAY_SIZE(bufferW) ))
{
system_locale = get_locale_by_name( bufferW, &system_lcid ); 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) )) if (GetEnvironmentVariableW( L"WINEUSERLOCALE", bufferW, ARRAY_SIZE(bufferW) ))
{
user_locale = get_locale_by_name( bufferW, &user_lcid ); user_locale = get_locale_by_name( bufferW, &user_lcid );
if (user_lcid == LOCALE_CUSTOM_UNSPECIFIED) user_lcid = LOCALE_CUSTOM_DEFAULT; if (!user_locale) user_locale = system_locale;
}
else
{
user_locale = system_locale;
user_lcid = system_lcid;
}
} }
user_lcid = user_locale->ilanguage;
if (user_lcid == LOCALE_CUSTOM_UNSPECIFIED) user_lcid = LOCALE_CUSTOM_DEFAULT;
if (GetEnvironmentVariableW( L"WINEUNIXCP", bufferW, ARRAY_SIZE(bufferW) )) if (GetEnvironmentVariableW( L"WINEUNIXCP", bufferW, ARRAY_SIZE(bufferW) ))
unix_cp = wcstoul( bufferW, NULL, 10 ); unix_cp = wcstoul( bufferW, NULL, 10 );
...@@ -4140,7 +4143,8 @@ INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1, ...@@ -4140,7 +4143,8 @@ INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1,
*/ */
LCID WINAPI DECLSPEC_HOTPATCH ConvertDefaultLocale( LCID lcid ) 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; return lcid;
} }
...@@ -4848,7 +4852,7 @@ INT WINAPI DECLSPEC_HOTPATCH GetCalendarInfoW( LCID lcid, CALID calendar, CALTYP ...@@ -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 ); 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 ); SetLastError( ERROR_INVALID_PARAMETER );
return 0; return 0;
...@@ -5063,7 +5067,7 @@ INT WINAPI DECLSPEC_HOTPATCH GetLocaleInfoW( LCID lcid, LCTYPE lctype, WCHAR *bu ...@@ -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 ); 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 ); SetLastError( ERROR_INVALID_PARAMETER );
return 0; return 0;
...@@ -5715,7 +5719,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocale( LCID lcid, DWORD flags ) ...@@ -5715,7 +5719,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocale( LCID lcid, DWORD flags )
case LOCALE_SYSTEM_DEFAULT: case LOCALE_SYSTEM_DEFAULT:
return FALSE; return FALSE;
default: 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 ...@@ -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 ) 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) if (!locale)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment