From 35ea9cd99ac06b9b8711840c4ae704a3ec7eb91f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 20 Nov 2019 22:46:44 +0100 Subject: [PATCH] kernel32: Move the locale registry setup to kernelbase. Signed-off-by: Alexandre Julliard --- dlls/kernel32/kernel_main.c | 3 - dlls/kernel32/kernel_private.h | 1 - dlls/kernel32/locale.c | 147 -------------------------------- dlls/kernelbase/kernelbase.h | 2 +- dlls/kernelbase/locale.c | 149 ++++++++++++++++++++++++++++----- dlls/kernelbase/main.c | 3 +- 6 files changed, 130 insertions(+), 175 deletions(-) diff --git a/dlls/kernel32/kernel_main.c b/dlls/kernel32/kernel_main.c index dfa66f02958..954b08b523a 100644 --- a/dlls/kernel32/kernel_main.c +++ b/dlls/kernel32/kernel_main.c @@ -85,9 +85,6 @@ static BOOL process_attach( HMODULE module ) NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL ); - /* Setup registry locale information */ - LOCALE_InitRegistry(); - /* Setup registry timezone information */ TIMEZONE_InitRegistry(); diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h index cd6c63efa34..184c0dad3f4 100644 --- a/dlls/kernel32/kernel_private.h +++ b/dlls/kernel32/kernel_private.h @@ -74,7 +74,6 @@ extern void COMPUTERNAME_Init(void) DECLSPEC_HIDDEN; /* locale.c */ extern void LOCALE_Init(void) DECLSPEC_HIDDEN; -extern void LOCALE_InitRegistry(void) DECLSPEC_HIDDEN; /* time.c */ extern void TIMEZONE_InitRegistry(void) DECLSPEC_HIDDEN; diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index eda27faf1bc..791234cb129 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -311,153 +311,6 @@ static inline HANDLE create_registry_key(void) } -/* update the registry settings for a given locale parameter */ -/* return TRUE if an update was needed */ -static BOOL locale_update_registry( HKEY hkey, const WCHAR *name, LCID lcid, - const LCTYPE *values, UINT nb_values ) -{ - static const WCHAR formatW[] = { '%','0','8','x',0 }; - WCHAR bufferW[40]; - UNICODE_STRING nameW; - DWORD count, i; - - RtlInitUnicodeString( &nameW, name ); - count = sizeof(bufferW); - if (!NtQueryValueKey(hkey, &nameW, KeyValuePartialInformation, bufferW, count, &count)) - { - const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)bufferW; - LPCWSTR text = (LPCWSTR)info->Data; - - if (strtoulW( text, NULL, 16 ) == lcid) return FALSE; /* already set correctly */ - TRACE( "updating registry, locale %s changed %s -> %08x\n", - debugstr_w(name), debugstr_w(text), lcid ); - } - else TRACE( "updating registry, locale %s changed none -> %08x\n", debugstr_w(name), lcid ); - sprintfW( bufferW, formatW, lcid ); - NtSetValueKey( hkey, &nameW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR) ); - - for (i = 0; i < nb_values; i++) - { - GetLocaleInfoW( lcid, values[i] | LOCALE_NOUSEROVERRIDE, bufferW, ARRAY_SIZE( bufferW )); - SetLocaleInfoW( lcid, values[i], bufferW ); - } - return TRUE; -} - - -/*********************************************************************** - * LOCALE_InitRegistry - * - * Update registry contents on startup if the user locale has changed. - * This simulates the action of the Windows control panel. - */ -void LOCALE_InitRegistry(void) -{ - static const WCHAR acpW[] = {'A','C','P',0}; - static const WCHAR oemcpW[] = {'O','E','M','C','P',0}; - static const WCHAR maccpW[] = {'M','A','C','C','P',0}; - static const WCHAR localeW[] = {'L','o','c','a','l','e',0}; - static const WCHAR lc_ctypeW[] = { 'L','C','_','C','T','Y','P','E',0 }; - static const struct - { - LPCWSTR name; - USHORT value; - } update_cp_values[] = { - { acpW, LOCALE_IDEFAULTANSICODEPAGE }, - { oemcpW, LOCALE_IDEFAULTCODEPAGE }, - { maccpW, LOCALE_IDEFAULTMACCODEPAGE } - }; - static const LCTYPE lc_messages_values[] = { - LOCALE_SABBREVLANGNAME, - LOCALE_SCOUNTRY, - LOCALE_SLIST, - LOCALE_SCURRENCY, - LOCALE_ICURRENCY, - LOCALE_INEGCURR, - LOCALE_ICURRDIGITS, - LOCALE_ILZERO, - LOCALE_SMONDECIMALSEP, - LOCALE_SMONGROUPING, - LOCALE_SMONTHOUSANDSEP, - LOCALE_SDECIMAL, - LOCALE_STHOUSAND, - LOCALE_IDIGITS, - LOCALE_IDIGITSUBSTITUTION, - LOCALE_SNATIVEDIGITS, - LOCALE_INEGNUMBER, - LOCALE_SNEGATIVESIGN, - LOCALE_SPOSITIVESIGN, - LOCALE_SGROUPING, - LOCALE_S1159, - LOCALE_S2359, - LOCALE_STIME, - LOCALE_ITIME, - LOCALE_ITLZERO, - LOCALE_SSHORTDATE, - LOCALE_SLONGDATE, - LOCALE_SDATE, - LOCALE_ITIMEMARKPOSN, - LOCALE_ICALENDARTYPE, - LOCALE_IFIRSTDAYOFWEEK, - LOCALE_IFIRSTWEEKOFYEAR, - LOCALE_STIMEFORMAT, - LOCALE_SYEARMONTH, - LOCALE_IDATE, - LOCALE_IMEASURE, - LOCALE_ICOUNTRY, - LOCALE_IPAPERSIZE }; - - UNICODE_STRING nameW; - WCHAR bufferW[80]; - DWORD count, i; - HANDLE hkey; - LCID lcid = GetUserDefaultLCID(); - - if (!(hkey = create_registry_key())) - return; /* don't do anything if we can't create the registry key */ - - locale_update_registry( hkey, localeW, lcid, lc_messages_values, - ARRAY_SIZE( lc_messages_values )); - - if (locale_update_registry( hkey, lc_ctypeW, GetSystemDefaultLCID(), NULL, 0 )) - { - static const WCHAR codepageW[] = - {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\','N','l','s','\\','C','o','d','e','p','a','g','e',0}; - - OBJECT_ATTRIBUTES attr; - HANDLE nls_key; - DWORD len = 14; - - RtlInitUnicodeString( &nameW, codepageW ); - InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL ); - while (codepageW[len]) - { - nameW.Length = len * sizeof(WCHAR); - if (NtCreateKey( &nls_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) break; - NtClose( nls_key ); - len++; - while (codepageW[len] && codepageW[len] != '\\') len++; - } - nameW.Length = len * sizeof(WCHAR); - if (!NtCreateKey( &nls_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) - { - for (i = 0; i < ARRAY_SIZE( update_cp_values ); i++) - { - count = GetLocaleInfoW( lcid, update_cp_values[i].value | LOCALE_NOUSEROVERRIDE, - bufferW, ARRAY_SIZE( bufferW )); - RtlInitUnicodeString( &nameW, update_cp_values[i].name ); - NtSetValueKey( nls_key, &nameW, 0, REG_SZ, bufferW, count * sizeof(WCHAR) ); - } - NtClose( nls_key ); - } - } - - NtClose( hkey ); -} - - static BOOL get_dummy_preferred_ui_language( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size ) { LCTYPE type; diff --git a/dlls/kernelbase/kernelbase.h b/dlls/kernelbase/kernelbase.h index 63d4b21d768..4aed1829e37 100644 --- a/dlls/kernelbase/kernelbase.h +++ b/dlls/kernelbase/kernelbase.h @@ -27,13 +27,13 @@ extern WCHAR *file_name_AtoW( LPCSTR name, BOOL alloc ) DECLSPEC_HIDDEN; extern DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen ) DECLSPEC_HIDDEN; extern void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params ) DECLSPEC_HIDDEN; +extern void init_locale(void) DECLSPEC_HIDDEN; extern const WCHAR windows_dir[] DECLSPEC_HIDDEN; extern const WCHAR system_dir[] DECLSPEC_HIDDEN; static const BOOL is_win64 = (sizeof(void *) > sizeof(int)); extern BOOL is_wow64 DECLSPEC_HIDDEN; -extern HANDLE kernel32_handle DECLSPEC_HIDDEN; static inline BOOL is_console_handle(HANDLE h) { diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 082d6933a35..4ec5016b3f2 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -41,17 +41,124 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls); #define CALINFO_MAX_YEAR 2029 -static const WCHAR codepages_key[] = -{ 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', - '\\','C','o','n','t','r','o','l','\\','N','l','s','\\','C','o','d','e','P','a','g','e',0}; -static const WCHAR language_groups_key[] = -{ 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', - '\\','C','o','n','t','r','o','l','\\','N','l','s', - '\\','L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0 }; -static const WCHAR locales_key[] = -{ 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', - '\\','C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0}; -static const WCHAR altsort_key[] = {'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s',0}; +static HANDLE kernel32_handle; + +static const struct registry_value +{ + DWORD lctype; + const WCHAR *name; +} registry_values[] = +{ + { LOCALE_ICALENDARTYPE, L"iCalendarType" }, + { LOCALE_ICURRDIGITS, L"iCurrDigits" }, + { LOCALE_ICURRENCY, L"iCurrency" }, + { LOCALE_IDIGITS, L"iDigits" }, + { LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek" }, + { LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear" }, + { LOCALE_ILZERO, L"iLZero" }, + { LOCALE_IMEASURE, L"iMeasure" }, + { LOCALE_INEGCURR, L"iNegCurr" }, + { LOCALE_INEGNUMBER, L"iNegNumber" }, + { LOCALE_IPAPERSIZE, L"iPaperSize" }, + { LOCALE_ITIME, L"iTime" }, + { LOCALE_S1159, L"s1159" }, + { LOCALE_S2359, L"s2359" }, + { LOCALE_SCURRENCY, L"sCurrency" }, + { LOCALE_SDATE, L"sDate" }, + { LOCALE_SDECIMAL, L"sDecimal" }, + { LOCALE_SGROUPING, L"sGrouping" }, + { LOCALE_SLIST, L"sList" }, + { LOCALE_SLONGDATE, L"sLongDate" }, + { LOCALE_SMONDECIMALSEP, L"sMonDecimalSep" }, + { LOCALE_SMONGROUPING, L"sMonGrouping" }, + { LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep" }, + { LOCALE_SNEGATIVESIGN, L"sNegativeSign" }, + { LOCALE_SPOSITIVESIGN, L"sPositiveSign" }, + { LOCALE_SSHORTDATE, L"sShortDate" }, + { LOCALE_STHOUSAND, L"sThousand" }, + { LOCALE_STIME, L"sTime" }, + { LOCALE_STIMEFORMAT, L"sTimeFormat" }, + { LOCALE_SYEARMONTH, L"sYearMonth" }, + /* The following are not listed under MSDN as supported, + * but seem to be used and also stored in the registry. + */ + { LOCALE_SNAME, L"LocaleName" }, + { LOCALE_ICOUNTRY, L"iCountry" }, + { LOCALE_IDATE, L"iDate" }, + { LOCALE_ILDATE, L"iLDate" }, + { LOCALE_ITLZERO, L"iTLZero" }, + { LOCALE_SCOUNTRY, L"sCountry" }, + { LOCALE_SABBREVLANGNAME, L"sLanguage" }, + { LOCALE_IDIGITSUBSTITUTION, L"Numshape" }, + { LOCALE_SNATIVEDIGITS, L"sNativeDigits" }, + { LOCALE_ITIMEMARKPOSN, L"iTimePrefix" }, +}; + +static UINT ansi_cp = 1252; +static UINT oem_cp = 437; +static UINT mac_cp = 10000; +static HKEY intl_key; +static HKEY nls_key; + + +/*********************************************************************** + * init_locale + */ +void init_locale(void) +{ + LCID lcid = GetUserDefaultLCID(); + WCHAR bufferW[80]; + DWORD count, i; + HKEY hkey; + + kernel32_handle = GetModuleHandleW( L"kernel32.dll" ); + + GetLocaleInfoW( LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&ansi_cp, sizeof(ansi_cp)/sizeof(WCHAR) ); + GetLocaleInfoW( LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTMACCODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&mac_cp, sizeof(mac_cp)/sizeof(WCHAR) ); + GetLocaleInfoW( LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR) ); + + RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Nls", + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &nls_key, NULL ); + RegCreateKeyExW( HKEY_CURRENT_USER, L"Control Panel\\International", + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &intl_key, NULL ); + + /* Update registry contents if the user locale has changed. + * This simulates the action of the Windows control panel. */ + + count = sizeof(bufferW); + if (!RegQueryValueExW( intl_key, L"Locale", NULL, NULL, (BYTE *)bufferW, &count )) + { + if (wcstoul( bufferW, NULL, 16 ) == lcid) return; /* already set correctly */ + TRACE( "updating registry, locale changed %s -> %08x\n", debugstr_w(bufferW), lcid ); + } + else TRACE( "updating registry, locale changed none -> %08x\n", lcid ); + swprintf( bufferW, ARRAY_SIZE(bufferW), L"%08x", lcid ); + RegSetValueExW( intl_key, L"Locale", 0, REG_SZ, + (BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR) ); + + for (i = 0; i < ARRAY_SIZE(registry_values); i++) + { + GetLocaleInfoW( LOCALE_USER_DEFAULT, registry_values[i].lctype | LOCALE_NOUSEROVERRIDE, + bufferW, ARRAY_SIZE( bufferW )); + RegSetValueExW( intl_key, registry_values[i].name, 0, REG_SZ, + (BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR) ); + } + + if (!RegCreateKeyExW( nls_key, L"Codepage", + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) + { + count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", ansi_cp ); + RegSetValueExW( hkey, L"ACP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) ); + count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", oem_cp ); + RegSetValueExW( hkey, L"OEMCP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) ); + count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", mac_cp ); + RegSetValueExW( hkey, L"MACCP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) ); + RegCloseKey( hkey ); + } +} /* Note: the Internal_ functions are not documented. The number of parameters @@ -181,8 +288,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumLanguageGroupLocales( LANGGROUPLOCALE return FALSE; } - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE; - if (RegOpenKeyExW( key, altsort_key, 0, KEY_READ, &altkey )) altkey = 0; + if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( key, L"Alternate Sorts", 0, KEY_READ, &altkey )) altkey = 0; for (;;) { @@ -222,7 +329,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemCodePages( CODEPAGE_ENUMPROCW p DWORD name_len, type, index = 0; HKEY key; - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, codepages_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Codepage", 0, KEY_READ, &key )) return FALSE; for (;;) { @@ -273,7 +380,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemLanguageGroups( LANGUAGEGROUP_E return FALSE; } - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, language_groups_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE; for (;;) { @@ -366,7 +473,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumUILanguages( UILANGUAGE_ENUMPROCW pro return FALSE; } - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE; for (;;) { @@ -516,7 +623,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesA( LOCALE_ENUMPROCA proc, DWORD f DWORD name_len, type, index = 0; HKEY key; - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE; for (;;) { @@ -540,7 +647,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesW( LOCALE_ENUMPROCW proc, DWORD f DWORD name_len, type, index = 0; HKEY key; - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE; for (;;) { @@ -572,8 +679,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesEx( LOCALE_ENUMPROCEX proc, DWORD return FALSE; } - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE; - if (RegOpenKeyExW( key, altsort_key, 0, KEY_READ, &altkey )) altkey = 0; + if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( key, L"Alternate Sorts", 0, KEY_READ, &altkey )) altkey = 0; for (;;) { @@ -680,7 +787,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidLanguageGroup( LGRPID id, DWORD flags ) BOOL ret = FALSE; HKEY key; - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, language_groups_key, 0, KEY_READ, &key )) return FALSE; + if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE; swprintf( name, ARRAY_SIZE(name), format, id ); if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)value, &value_len ) && type == REG_SZ) diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 3015078d912..b735e7dee98 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -34,7 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(kernelbase); -HANDLE kernel32_handle = 0; BOOL is_wow64 = FALSE; /*********************************************************************** @@ -46,7 +45,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { DisableThreadLibraryCalls( hinst ); IsWow64Process( GetCurrentProcess(), &is_wow64 ); - kernel32_handle = GetModuleHandleA( "kernel32.dll" ); + init_locale(); init_startup_info( NtCurrentTeb()->Peb->ProcessParameters ); } return TRUE;