From 7c1b7ee87d32b09f2b48bdef7bba86a447f28d50 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 8 May 2025 14:03:01 +0300 Subject: [PATCH] [KERNEL32_VISTA] Implement LocaleNameToLCID --- .../kernel32/kernel32_vista/CMakeLists.txt | 1 + .../kernel32_vista/LocaleNameToLCID.c | 107 ++++++++++++++++++ .../kernel32_vista/kernel32_vista.spec | 1 + dll/win32/kernel32/winnls/string/locale.c | 11 +- 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 dll/win32/kernel32/kernel32_vista/LocaleNameToLCID.c diff --git a/dll/win32/kernel32/kernel32_vista/CMakeLists.txt b/dll/win32/kernel32/kernel32_vista/CMakeLists.txt index 261a6bdf8b5..815928b896f 100644 --- a/dll/win32/kernel32/kernel32_vista/CMakeLists.txt +++ b/dll/win32/kernel32/kernel32_vista/CMakeLists.txt @@ -12,6 +12,7 @@ list(APPEND SOURCE GetTickCount64.c GetUserDefaultLocaleName.c InitOnce.c + LocaleNameToLCID.c sync.c vista.c) diff --git a/dll/win32/kernel32/kernel32_vista/LocaleNameToLCID.c b/dll/win32/kernel32/kernel32_vista/LocaleNameToLCID.c new file mode 100644 index 00000000000..99eaf2a2226 --- /dev/null +++ b/dll/win32/kernel32/kernel32_vista/LocaleNameToLCID.c @@ -0,0 +1,107 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of LocaleNameToLCID + * COPYRIGHT: Copyright 2025 Timo Kreuzer + */ + +#include "k32_vista.h" +#include + +#define NDEBUG +#include + +LCID +WINAPI +LocaleNameToLCID( + _In_ LPCWSTR lpName, + _In_ DWORD dwFlags) +{ + NTSTATUS Status; + LCID Lcid; + + /* Validate flags */ + if (dwFlags & ~LOCALE_ALLOW_NEUTRAL_NAMES) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* Check for LOCALE_NAME_USER_DEFAULT (NULL) */ + if (lpName == NULL) + { + return GetUserDefaultLCID(); + } + + /* Check for LOCALE_NAME_INVARIANT (L"") */ + if (lpName[0] == L'\0') + { + return MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT); + } + + /* Call the RTL function (include neutral names) */ + Status = RtlLocaleNameToLcid(lpName, &Lcid, RTL_LOCALE_ALLOW_NEUTRAL_NAMES); + if (!NT_SUCCESS(Status)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* Are neutral locales allowed? */ + if ((dwFlags & LOCALE_ALLOW_NEUTRAL_NAMES) == 0) + { + /* Check if we got a neutral locale */ + LANGID LangId = LANGIDFROMLCID(Lcid); + USHORT SubLangId = SUBLANGID(LangId); + if (SubLangId == SUBLANG_NEUTRAL) + { + /* Adjust it to be the default locale */ + Lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(LangId), SUBLANG_DEFAULT), SORT_DEFAULT); + } + else if (SubLangId >= 0x18) + { + /* Handle special neutral LCIDs */ + switch (Lcid) + { + case 0x0742C: return 0x0082C; // "az-Cyrl" -> "az-Cyrl-AZ" + case 0x0782C: return 0x0042C; // "az-Latn" -> "az-Latn-AZ" + case 0x07C67: return 0x00867; // "ff-Latn" -> "ff-Latn-SN" + case 0x0781A: return 0x0141A; // "bs" -> "bs-Latn-BA" + case 0x0641A: return 0x0201A; // "bs-Cyrl" -> "bs-Cyrl-BA" + case 0x0681A: return 0x0141A; // "bs-Latn" -> "bs-Latn-BA" + case 0x07C5C: return 0x0045C; // "chr-Cher" -> "chr-Cher-US" + case 0x07C2E: return 0x0082E; // "dsb" -> "dsb-DE" + case 0x07C68: return 0x00468; // "ha-Latn" -> "ha-Latn-NG" + case 0x0785D: return 0x0045D; // "iu-Cans" -> "iu-Cans-CA" + case 0x07C5D: return 0x0085D; // "iu-Latn" -> "iu-Latn-CA" + case 0x07C92: return 0x00492; // "ku-Arab" -> "ku-Arab-IQ" + case 0x07850: return 0x00450; // "mn-Cyrl" -> "mn-MN" + case 0x07C50: return 0x00850; // "mn-Mong" -> "mn-Mong-CN" + case 0x07C14: return 0x00414; // "nb" -> "nb-NO" + case 0x07814: return 0x00814; // "nn" -> "nn-NO" + case 0x07C46: return 0x00846; // "pa-Arab" -> "pa-Arab-PK" + case 0x0703B: return 0x0243B; // "smn" -> "smn-FI" + case 0x07C59: return 0x00859; // "sd-Arab" -> "sd-Arab-PK" + case 0x0783B: return 0x01C3B; // "sma" -> "sma-SE" + case 0x07C3B: return 0x0143B; // "smj" -> "smj-SE" + case 0x0743B: return 0x0203B; // "sms" -> "sms-FI" + case 0x06C1A: return 0x0281A; // "sr-Cyrl" -> "sr-Cyrl-RS" + case 0x0701A: return 0x0241A; // "sr-Latn" -> "sr-Latn-RS" + case 0x07C28: return 0x00428; // "tg-Cyrl" -> "tg-Cyrl-TJ" + case 0x07C5F: return 0x0085F; // "tzm-Latn" -> "tzm-Latn-DZ" + case 0x0785F: return 0x0105F; // "tzm-Tfng" -> "tzm-Tfng-MA" + case 0x07843: return 0x00843; // "uz-Cyrl" -> "uz-Cyrl-UZ" + case 0x07C43: return 0x00443; // "uz-Latn" -> "uz-Latn-UZ" + case 0x07804: return 0x00804; // "zh" -> "zh-CN" + case 0x07C04: return 0x00C04; // "zh-Hant" -> "zh-HK" + } + + /* Should not happen */ + DPRINT1("Unandled neutral LCID %x\n", Lcid); + ASSERT(FALSE); + return 0; + } + } + + return Lcid; +} diff --git a/dll/win32/kernel32/kernel32_vista/kernel32_vista.spec b/dll/win32/kernel32/kernel32_vista/kernel32_vista.spec index c717bbcf53b..ea6fd7db61e 100644 --- a/dll/win32/kernel32/kernel32_vista/kernel32_vista.spec +++ b/dll/win32/kernel32/kernel32_vista/kernel32_vista.spec @@ -44,6 +44,7 @@ @ stdcall GetUILanguageInfo(long wstr wstr ptr ptr) @ stdcall GetUserDefaultLocaleName(wstr long) @ stdcall GetUserPreferredUILanguages(long ptr wstr ptr) +@ stdcall LocaleNameToLCID(wstr long) @ stdcall OpenFileById(ptr ptr long long ptr long) @ stdcall QueryFullProcessImageNameA(ptr long str ptr) @ stdcall QueryFullProcessImageNameW(ptr long wstr ptr) diff --git a/dll/win32/kernel32/winnls/string/locale.c b/dll/win32/kernel32/winnls/string/locale.c index 1b642efe6cb..607620f82c4 100644 --- a/dll/win32/kernel32/winnls/string/locale.c +++ b/dll/win32/kernel32/winnls/string/locale.c @@ -333,6 +333,7 @@ static const union cptable *get_codepage_table( unsigned int codepage ) #endif // !__REACTOS__ #if (WINVER >= 0x0600) +#if 0 // See kernel32_vista /*********************************************************************** * charset_cmp (internal) */ @@ -362,6 +363,7 @@ static UINT find_charset( const WCHAR *name ) if (entry) return entry->codepage; return 0; } +#endif // 0 See kernel32_vista #endif // (WINVER >= 0x0600) static LANGID get_default_sublang( LANGID lang ) @@ -383,6 +385,7 @@ static LANGID get_default_sublang( LANGID lang ) } #if (WINVER >= 0x0600) +#if 0 // See kernel32_vista /*********************************************************************** * find_locale_id_callback */ @@ -467,7 +470,7 @@ done: } return (data->matches < 4); /* no need to continue for perfect match */ } - +#endif // 0 See kernel32_vista /*********************************************************************** * parse_locale_name @@ -476,6 +479,7 @@ done: * Unix format is: lang[_country][.charset][@modifier] * Windows format is: lang[-script][-country][_modifier] */ +#if 0 // See kernel32_vista static void parse_locale_name( const WCHAR *str, struct locale_name *name ) { static const WCHAR sepW[] = {'-','_','.','@',0}; @@ -576,7 +580,8 @@ done: EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, find_locale_id_callback, (LPARAM)name ); } -#endif +#endif // 0 See kernel32_vista +#endif // (WINVER >= 0x0600) /*********************************************************************** @@ -1400,6 +1405,7 @@ LANGID WINAPI GetSystemDefaultUILanguage(void) } #if (WINVER >= 0x0600) +#if 0 // See kernel32_vista /*********************************************************************** * LocaleNameToLCID (KERNEL32.@) */ @@ -1430,6 +1436,7 @@ LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags ) return locale_name.lcid; } +#endif /***********************************************************************