ntdll: Implement RtlLcidToLocaleName().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-03-22 10:32:32 +01:00
parent ea9a776d7d
commit a2d44e89ea
4 changed files with 157 additions and 0 deletions

View File

@ -64,6 +64,7 @@ static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, L
static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
static NTSTATUS (WINAPI *pRtlLocaleNameToLcid)(LPCWSTR, LCID *, DWORD);
static BOOLEAN (WINAPI *pRtlIsValidLocaleName)(const WCHAR *,ULONG);
static NTSTATUS (WINAPI *pRtlLcidToLocaleName)(LCID, UNICODE_STRING *,DWORD,BYTE);
static INT (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
@ -147,6 +148,7 @@ static void InitFunctionPointers(void)
X(RtlUpcaseUnicodeChar);
X(RtlLocaleNameToLcid);
X(RtlIsValidLocaleName);
X(RtlLcidToLocaleName);
X(RtlNormalizeString);
X(RtlIsNormalizedString);
X(NtGetNlsSectionPtr);
@ -2866,6 +2868,96 @@ static void test_LocaleNameToLCID(void)
}
}
else win_skip( "RtlLocaleNameToLcid not available\n" );
if (pRtlLcidToLocaleName)
{
WCHAR buffer[128], expect[128];
UNICODE_STRING str;
str.Buffer = buffer;
str.MaximumLength = sizeof( buffer );
memset( buffer, 0xcc, sizeof(buffer) );
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 );
ok( status == STATUS_INVALID_PARAMETER_1, "wrong error %lx\n", status );
status = pRtlLcidToLocaleName( LOCALE_INVARIANT, NULL, 0, 0 );
ok( status == STATUS_INVALID_PARAMETER_2, "wrong error %lx\n", status );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &str, 0, 0 );
ok( status == STATUS_SUCCESS, "wrong error %lx\n", status );
ok( !wcscmp( buffer, L"en-US" ), "wrong name %s\n", debugstr_w(buffer) );
ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length );
ok( str.MaximumLength == sizeof(buffer), "wrong max len %u\n", str.MaximumLength );
status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), &str, 0, 0 );
ok( status == STATUS_INVALID_PARAMETER_1, "wrong error %lx\n", status );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), &str, 2, 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"en" ), "wrong name %s\n", debugstr_w(buffer) );
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) );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( LOCALE_SYSTEM_DEFAULT, &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 );
LCIDToLocaleName( GetSystemDefaultLCID(), expect, ARRAY_SIZE(expect), 0 );
ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( LOCALE_USER_DEFAULT, &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 );
LCIDToLocaleName( GetUserDefaultLCID(), expect, ARRAY_SIZE(expect), 0 );
ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( LOCALE_INVARIANT, &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"" ), "wrong name %s\n", debugstr_w(buffer) );
memset( buffer, 0xcc, sizeof(buffer) );
status = pRtlLcidToLocaleName( LOCALE_CUSTOM_DEFAULT, &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 );
LCIDToLocaleName( GetUserDefaultLCID(), expect, ARRAY_SIZE(expect), 0 );
ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) );
status = pRtlLcidToLocaleName( LOCALE_CUSTOM_UI_DEFAULT, &str, 0, 0 );
ok( status == STATUS_SUCCESS || status == STATUS_UNSUCCESSFUL, "wrong error %lx\n", status );
status = pRtlLcidToLocaleName( LOCALE_CUSTOM_UNSPECIFIED, &str, 0, 0 );
ok( status == STATUS_INVALID_PARAMETER_1, "wrong error %lx\n", status );
memset( buffer, 0xcc, sizeof(buffer) );
str.Length = 0xbeef;
str.MaximumLength = 5 * sizeof(WCHAR);
status = pRtlLcidToLocaleName( 0x00010407, &str, 0, 0 );
ok( status == STATUS_BUFFER_TOO_SMALL, "wrong error %lx\n", status );
ok( str.Length == 0xbeef, "wrong len %u\n", str.Length );
ok( str.MaximumLength == 5 * sizeof(WCHAR), "wrong len %u\n", str.MaximumLength );
ok( buffer[0] == 0xcccc, "wrong name %s\n", debugstr_w(buffer) );
memset( &str, 0xcc, sizeof(str) );
status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &str, 0, 1 );
ok( status == STATUS_SUCCESS, "wrong error %lx\n", status );
ok( str.Length == wcslen(str.Buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length );
ok( str.MaximumLength == str.Length + sizeof(WCHAR), "wrong max len %u\n", str.MaximumLength );
ok( !wcscmp( str.Buffer, L"en-US" ), "wrong name %s\n", debugstr_w(str.Buffer) );
RtlFreeUnicodeString( &str );
}
else win_skip( "RtlLcidToLocaleName not available\n" );
}
/* this requires collation table patch to make it MS compatible */

View File

@ -269,6 +269,21 @@ static const NLS_LOCALE_LCNAME_INDEX *find_lcname_entry( const WCHAR *name )
}
static const NLS_LOCALE_LCID_INDEX *find_lcid_entry( LCID lcid )
{
int min = 0, max = locale_table->nb_lcids - 1;
while (min <= max)
{
int pos = (min + max) / 2;
if (lcid < lcids_index[pos].id) max = pos - 1;
else if (lcid > lcids_index[pos].id) min = pos + 1;
else return &lcids_index[pos];
}
return NULL;
}
static const NLS_LOCALE_DATA *get_locale_data( UINT idx )
{
ULONG offset = locale_table->locales_offset + idx * locale_table->locale_size;
@ -1238,6 +1253,54 @@ BOOLEAN WINAPI RtlIsValidLocaleName( const WCHAR *name, ULONG flags )
}
/******************************************************************
* RtlLcidToLocaleName (NTDLL.@)
*/
NTSTATUS WINAPI RtlLcidToLocaleName( LCID lcid, UNICODE_STRING *str, ULONG flags, BOOLEAN alloc )
{
const NLS_LOCALE_LCID_INDEX *entry;
const WCHAR *name;
ULONG len;
if (!str) return STATUS_INVALID_PARAMETER_2;
switch (lcid)
{
case LOCALE_USER_DEFAULT:
NtQueryDefaultLocale( TRUE, &lcid );
break;
case LOCALE_SYSTEM_DEFAULT:
case LOCALE_CUSTOM_DEFAULT:
NtQueryDefaultLocale( FALSE, &lcid );
break;
case LOCALE_CUSTOM_UI_DEFAULT:
return STATUS_UNSUCCESSFUL;
case LOCALE_CUSTOM_UNSPECIFIED:
return STATUS_INVALID_PARAMETER_1;
}
if (!(entry = find_lcid_entry( lcid ))) return STATUS_INVALID_PARAMETER_1;
/* reject neutral locale unless flag 2 is set */
if (!(flags & 2) && !get_locale_data( entry->idx )->inotneutral) return STATUS_INVALID_PARAMETER_1;
name = locale_strings + entry->name;
len = *name++;
if (alloc)
{
if (!(str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
return STATUS_NO_MEMORY;
str->MaximumLength = (len + 1) * sizeof(WCHAR);
}
else if (str->MaximumLength < (len + 1) * sizeof(WCHAR)) return STATUS_BUFFER_TOO_SMALL;
wcscpy( str->Buffer, name );
str->Length = len * sizeof(WCHAR);
TRACE( "%04x -> %s\n", lcid, debugstr_us(str) );
return STATUS_SUCCESS;
}
/******************************************************************
* RtlLocaleNameToLcid (NTDLL.@)
*/

View File

@ -843,6 +843,7 @@
@ stdcall -arch=win32 -ret64 RtlLargeIntegerShiftRight(int64 long)
@ stdcall -arch=win32 -ret64 RtlLargeIntegerSubtract(int64 int64)
@ stdcall RtlLargeIntegerToChar(ptr long long ptr)
@ stdcall RtlLcidToLocaleName(long ptr long long)
@ stdcall RtlLeaveCriticalSection(ptr)
@ stdcall RtlLengthRequiredSid(long)
@ stdcall RtlLengthSecurityDescriptor(ptr)

View File

@ -4403,6 +4403,7 @@ NTSYSAPI BOOLEAN WINAPI RtlIsTextUnicode(LPCVOID,INT,INT *);
NTSYSAPI BOOLEAN WINAPI RtlIsValidHandle(const RTL_HANDLE_TABLE *, const RTL_HANDLE *);
NTSYSAPI BOOLEAN WINAPI RtlIsValidIndexHandle(const RTL_HANDLE_TABLE *, ULONG Index, RTL_HANDLE **);
NTSYSAPI BOOLEAN WINAPI RtlIsValidLocaleName(const WCHAR*,ULONG);
NTSYSAPI NTSTATUS WINAPI RtlLcidToLocaleName(LCID,UNICODE_STRING*,ULONG,BOOLEAN);
NTSYSAPI NTSTATUS WINAPI RtlLeaveCriticalSection(RTL_CRITICAL_SECTION *);
NTSYSAPI DWORD WINAPI RtlLengthRequiredSid(DWORD);
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR);