Jacek Caban : winemac: Directly use ntdll in get_lcid.
Alexandre Julliard
julliard at winehq.org
Mon May 30 15:34:59 CDT 2022
Module: wine
Branch: master
Commit: 221fce4c17751da0966c2d5750f1f067592f9638
URL: https://source.winehq.org/git/wine.git/?a=commit;h=221fce4c17751da0966c2d5750f1f067592f9638
Author: Jacek Caban <jacek at codeweavers.com>
Date: Sun May 29 19:38:15 2022 +0200
winemac: Directly use ntdll in get_lcid.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/winemac.drv/keyboard.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index 94860f2e36c..9574b2797b5 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -441,16 +441,94 @@ static pthread_mutex_t layout_list_mutex = PTHREAD_MUTEX_INITIALIZER;
int macdrv_layout_list_needs_update = TRUE;
+static const NLS_LOCALE_HEADER *locale_table;
+
+static int compare_locale_names(const WCHAR *n1, const WCHAR *n2)
+{
+ for (;;)
+ {
+ WCHAR ch1 = *n1++;
+ WCHAR ch2 = *n2++;
+ if (ch1 >= 'a' && ch1 <= 'z') ch1 -= 'a' - 'A';
+ else if (ch1 == '_') ch1 = '-';
+ if (ch2 >= 'a' && ch2 <= 'z') ch2 -= 'a' - 'A';
+ else if (ch2 == '_') ch2 = '-';
+ if (!ch1 || ch1 != ch2) return ch1 - ch2;
+ }
+}
+
+
+static const NLS_LOCALE_LCNAME_INDEX *find_lcname_entry(const WCHAR *name)
+{
+ const NLS_LOCALE_LCNAME_INDEX *lcnames_index;
+ const WCHAR *locale_strings;
+ int min = 0, max = locale_table->nb_lcnames - 1;
+
+ locale_strings = (const WCHAR *)((char *)locale_table + locale_table->strings_offset);
+ lcnames_index = (const NLS_LOCALE_LCNAME_INDEX *)((char *)locale_table + locale_table->lcnames_offset);
+
+ while (min <= max)
+ {
+ int res, pos = (min + max) / 2;
+ const WCHAR *str = locale_strings + lcnames_index[pos].name;
+ res = compare_locale_names(name, str + 1);
+ if (res < 0) max = pos - 1;
+ else if (res > 0) min = pos + 1;
+ else return &lcnames_index[pos];
+ }
+ return NULL;
+}
+
+
static DWORD get_lcid(CFStringRef lang)
{
+ const NLS_LOCALE_LCNAME_INDEX *entry;
+ const NLS_LOCALE_DATA *locale;
CFRange range;
WCHAR str[10];
+ ULONG offset;
+
+ if (!locale_table)
+ {
+ struct
+ {
+ UINT ctypes;
+ UINT unknown1;
+ UINT unknown2;
+ UINT unknown3;
+ UINT locales;
+ UINT charmaps;
+ UINT geoids;
+ UINT scripts;
+ } *header;
+ LCID system_lcid;
+ LARGE_INTEGER size;
+
+ if (NtInitializeNlsFiles((void **)&header, &system_lcid, &size))
+ {
+ ERR("NtInitializeNlsFiles failed\n");
+ return 0;
+ }
+
+ if (InterlockedCompareExchangePointer((void **)&locale_table,
+ (char *)header + header->locales, NULL))
+ NtUnmapViewOfSection(GetCurrentProcess(), header);
+ }
range.location = 0;
range.length = min(CFStringGetLength(lang), ARRAY_SIZE(str) - 1);
CFStringGetCharacters(lang, range, str);
str[range.length] = 0;
- return LocaleNameToLCID(str, 0);
+
+ if (!(entry = find_lcname_entry(str)))
+ {
+ ERR("%s not found\n", debugstr_w(str));
+ return 0;
+ }
+
+ offset = locale_table->locales_offset + entry->idx * locale_table->locale_size;
+ locale = (const NLS_LOCALE_DATA *)((const char *)locale_table + offset);
+ return locale->inotneutral ? entry->id : locale->idefaultlanguage;
}
static HKL get_hkl(CFStringRef lang, CFStringRef type)
More information about the wine-cvs
mailing list