2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 ////////////////////////////////////////////////////////////////////////////
12 // Purpose: functions that need to be emulated on downlevel platforms.
14 ////////////////////////////////////////////////////////////////////////////
16 #ifndef MUI_LANGUAGE_NAME
17 #define MUI_LANGUAGE_NAME 0
20 #ifndef CALINFO_ENUMPROCEXEX
21 typedef BOOL (CALLBACK* CALINFO_ENUMPROCEXEX)(LPWSTR, CALID, LPWSTR, LPARAM);
24 #ifndef DATEFMT_ENUMPROCEXEX
25 typedef BOOL (CALLBACK* DATEFMT_ENUMPROCEXEX)(LPWSTR, CALID, LPARAM);
28 #ifndef TIMEFMT_ENUMPROCEX
29 typedef BOOL (CALLBACK* TIMEFMT_ENUMPROCEX)(LPWSTR, LPARAM);
32 #ifndef LOCALE_ENUMPROCEX
33 typedef BOOL (CALLBACK* LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM);
36 #if !defined(LPNLSVERSIONINFOEX)
37 #define LPNLSVERSIONINFOEX LPNLSVERSIONINFO
40 #ifndef COMPARE_OPTIONS_ORDINAL
41 #define COMPARE_OPTIONS_ORDINAL 0x40000000
44 #ifndef LINGUISTIC_IGNORECASE
45 #define LINGUISTIC_IGNORECASE 0x00000010 // linguistically appropriate 'ignore case'
48 #ifndef FIND_STARTSWITH
49 #define FIND_STARTSWITH 0x00100000 // see if value is at the beginning of source
53 #define FIND_ENDSWITH 0x00200000 // see if value is at the end of source
56 #ifndef FIND_FROMSTART
57 #define FIND_FROMSTART 0x00400000 // look for value in source, starting at the beginning
61 #define FIND_FROMEND 0x00800000 // look for value in source, starting at the end
64 #ifndef NORM_LINGUISTIC_CASING
65 #define NORM_LINGUISTIC_CASING 0x08000000 // use linguistic rules for casing
68 #ifndef LCMAP_LINGUISTIC_CASING
69 #define LCMAP_LINGUISTIC_CASING 0x01000000 // use linguistic rules for casing
72 #ifndef LCMAP_TITLECASE
73 #define LCMAP_TITLECASE 0x00000300 // Title Case Letters
76 #ifndef LCMAP_SORTHANDLE
77 #define LCMAP_SORTHANDLE 0x20000000
81 #define LCMAP_HASH 0x00040000
85 #define LOCALE_ALL 0 // enumerate all named based locales
88 #ifndef LOCALE_WINDOWS
89 #define LOCALE_WINDOWS 0x00000001 // shipped locales and/or replacements for them
90 #endif // LOCALE_WINDOWS
92 #ifndef LOCALE_SUPPLEMENTAL
93 #define LOCALE_SUPPLEMENTAL 0x00000002 // supplemental locales only
94 #endif // LOCALE_SUPPLEMENTAL
96 #ifndef LOCALE_ALTERNATE_SORTS
97 #define LOCALE_ALTERNATE_SORTS 0x00000004 // alternate sort locales
98 #endif // LOCALE_ALTERNATE_SORTS
100 #ifndef LOCALE_NEUTRALDATA
101 #define LOCALE_NEUTRALDATA 0x00000010 // Locales that are "neutral" (language only, region data is default)
102 #endif // LOCALE_NEUTRALDATA
104 #ifndef LOCALE_SPECIFICDATA
105 #define LOCALE_SPECIFICDATA 0x00000020 // Locales that contain language and region data
106 #endif // LOCALE_SPECIFICDATA
108 #ifndef LOCALE_INEUTRAL
109 #define LOCALE_INEUTRAL 0x00000071 // Returns 0 for specific cultures, 1 for neutral cultures.
110 #endif // LOCALE_INEUTRAL
112 #ifndef LOCALE_SSORTLOCALE
113 #define LOCALE_SSORTLOCALE 0x0000007b // Name of locale to use for sorting/collation/casing behavior.
114 #endif // LOCALE_SSORTLOCALE
116 #ifndef LOCALE_RETURN_NUMBER
117 #define LOCALE_RETURN_NUMBER 0x20000000 // return number instead of string
118 #endif // LOCALE_RETURN_NUMBER
120 #ifndef LOCALE_ALLOW_NEUTRAL_NAMES
121 #define LOCALE_ALLOW_NEUTRAL_NAMES 0x08000000 //Flag to allow returning neutral names/lcids for name conversion
122 #endif // LOCALE_ALLOW_NEUTRAL_NAMES
125 #define LOCALE_SNAME 0x0000005c
128 #define FIND_NLS_STRING_FLAGS_NEGATION (~(FIND_STARTSWITH | FIND_ENDSWITH | FIND_FROMSTART | FIND_FROMEND))
129 #define CASING_BITS (NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE | NORM_IGNORECASE)
132 #ifndef __out_xcount_opt
133 #define __out_xcount_opt(var)
136 // TODO: NLS Arrowhead -This isn't really right, custom locales could start with en- and have different sort behavior
137 // IS_FAST_COMPARE_LOCALE is used to do the fast ordinal index of when having string of Lower Ansi codepoints
138 // that less than 0x80. There are some locales that we cannot do optimization with, like Turkish and Azeri
139 // because of Turkish I problem and Humgerian because of lower Ansi compressions.
140 #define IS_FAST_COMPARE_LOCALE(loc) \
141 (wcsncmp(loc,W("tr-"),3)!=0 && wcsncmp(loc,W("az-"),3)!=0 && wcsncmp(loc,W("hu-"),3)!=0)
143 #define TURKISH_LOCALE_NAME W("tr-TR")
144 #define AZERBAIJAN_LOCALE_NAME W("az-Latn-AZ")
145 #define TURKISH_SORTING_LOCALE_NAME W("tr-TR_turkic")
146 #define AZERBAIJAN_SORTING_LOCALE_NAME W("az-Latn-AZ_turkic")
148 #define MUI_MERGE_SYSTEM_FALLBACK 0x10
149 #define MUI_MERGE_USER_FALLBACK 0x20
154 #if defined(FEATURE_CORESYSTEM)
155 __inline bool IsWindows7Platform()
160 __inline bool IsVistaPlatform()
165 __inline BOOL IsZhTwSku()
171 // Return true if we're on Windows 7 or up (ie: if we have neutral native support and sorting knows about versions)
172 __inline bool IsWindows7Platform()
174 static int isRunningOnWindows7 = -1; // -1 notinitialized, 0 not running on Windows 7, other value means running on Windows 7
176 if (isRunningOnWindows7 == -1)
178 OSVERSIONINFOEX sVer;
179 ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
180 sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
181 sVer.dwMajorVersion = 6;
182 sVer.dwMinorVersion = 1;
183 sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
185 DWORDLONG dwlConditionMask = 0;
186 VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL);
187 VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_GREATER_EQUAL);
188 VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
190 if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION|CLR_VER_MINORVERSION|CLR_VER_PLATFORMID, dwlConditionMask))
192 isRunningOnWindows7 = 1;
196 isRunningOnWindows7 = 0;
200 return isRunningOnWindows7 == 1;
204 // IsVistaPlatform return true if running on Vista and false if running on pre or post Vista
206 __inline BOOL IsVistaPlatform()
208 static int isRunningOnVista = -1; // -1 notinitialized, 0 not running on Vista, other value meanse running on Vista
210 if (isRunningOnVista == -1)
212 OSVERSIONINFOEX sVer;
213 ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
214 sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
215 sVer.dwMajorVersion = 6;
216 sVer.dwMinorVersion = 0;
217 sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
219 DWORDLONG dwlConditionMask = 0;
220 VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_EQUAL);
221 VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_EQUAL);
222 VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
224 if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION|CLR_VER_MINORVERSION|CLR_VER_PLATFORMID, dwlConditionMask))
226 isRunningOnVista = 1;
230 isRunningOnVista = 0;
234 return isRunningOnVista == 1;
238 __inline BOOL IsZhTwSku()
240 const INT32 LANGID_ZH_TW = 0x0404;
241 LPCWSTR DEFAULT_REGION_NAME_0404 = W("\x53f0\x7063");
243 if(::GetSystemDefaultUILanguage() == LANGID_ZH_TW)
246 int result = ::GetLocaleInfoW(LANGID_ZH_TW, LOCALE_SNATIVECTRYNAME, wszBuffer, 32);
249 if (wcsncmp(wszBuffer, DEFAULT_REGION_NAME_0404, 3) != 0)
257 #endif // FEATURE_CORESYSTEM
259 __inline BOOL NotLeakingFrameworkOnlyCultures(__in LPCWSTR lpLocaleName)
261 return wcscmp(lpLocaleName, W("zh-CHS")) != 0
262 && wcscmp(lpLocaleName, W("zh-CHT")) != 0;
265 // System/user defaults
266 __success(return == TRUE) BOOL
267 GetUserPreferredUILanguages (__in DWORD dwFlags, __out PULONG pulNumLanguages, __out_ecount_opt(*pcchLanguagesBuffer) PWSTR pwszLanguagesBuffer, __in PULONG pcchLanguagesBuffer);
269 __success(return > 0) int
270 GetSystemDefaultLocaleName(__out_ecount(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
272 __success(return != 0) int
273 GetUserDefaultLocaleName(__out_ecount(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
275 // Comparison functions (ala CompareInfo)
276 int CompareStringEx(__in LPCWSTR lpLocaleName, __in DWORD dwCmpFlags, __in_ecount(cchCount1) LPCWSTR lpString1, __in int cchCount1, __in_ecount(cchCount2) LPCWSTR lpString2,
277 __in int cchCount2, __in_opt LPNLSVERSIONINFO lpVersionInformation, __in_opt LPVOID lpReserved, __in_opt LPARAM lParam );
279 int CompareStringOrdinal(__in_ecount(cchCount1) LPCWSTR lpString1, __in int cchCount1, __in_ecount(cchCount2) LPCWSTR lpString2, __in int cchCount2, __in BOOL bIgnoreCase);
281 int LCMapStringEx (__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags, __in_ecount(cchSrc) LPCWSTR lpSrcStr, __in int cchSrc,
282 __out_xcount_opt(cchDest) LPWSTR lpDestStr, __in int cchDest, __in_opt LPNLSVERSIONINFO lpVersionInformation, __in_opt LPVOID lpReserved, __in_opt LPARAM lParam );
284 LPWSTR GetLingusticLocaleName(__in LPWSTR pLocaleName, __in DWORD dwFlags);
286 int IndexOfString(__in LPCWSTR lpLocaleName,
287 __in_ecount(cchCount1) LPCWSTR pString1, // String to search in
288 __in int cchCount1, // length of pString1
289 __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
290 __in int cchCount2, // length of pString2
291 __in DWORD dwFlags, // search flags
292 __in BOOL startWith);
294 int LastIndexOfString(__in LPCWSTR lpLocaleName,
295 __in_ecount(cchCount1) LPCWSTR pString1, // String to search in
296 __in int cchCount1, // length of pString1
297 __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
298 __in int cchCount2, // length of pString2
302 int FindNLSStringEx(__in LPCWSTR lpLocaleName,
303 __in DWORD dwFindNLSStringFlags,
304 __in_ecount(cchSource) LPCWSTR lpStringSource,
306 __in_ecount(cchValue) LPCWSTR lpStringValue,
308 __out_opt LPINT pcchFound,
309 __in_opt LPNLSVERSIONINFO lpVersionInformation,
310 __in_opt LPVOID lpReserved,
311 __in_opt LPARAM lParam);
313 BOOL IsNLSDefinedString(__in NLS_FUNCTION Function, __in DWORD dwFlags, __in_opt LPNLSVERSIONINFOEX lpVersionInfo, __in LPCWSTR lpString, __in int cchStr );
315 // Calendar and locale information
316 __success(return != 0) int
317 GetCalendarInfoEx(__in LPCWSTR lpLocaleName, __in CALID Calendar, __in_opt LPCWSTR pReserved, __in CALTYPE CalType, __out_ecount_opt(cchData) LPWSTR lpCalData, __in int cchData, __out_opt LPDWORD lpValue );
319 __success(return != 0) int
320 GetLocaleInfoEx (__in LPCWSTR lpLocaleName, __in LCTYPE LCType, __out_ecount_opt(cchData) LPWSTR lpLCData, __in int cchData);
322 __success(return != 0) int
323 GetDateFormatEx(__in LPCWSTR lpLocaleName, __in DWORD dwFlags, __in_opt CONST SYSTEMTIME* lpDate, __in_opt LPCWSTR lpFormat,
324 __out_ecount(cchDate) LPWSTR lpDateStr, __in int cchDate, __in_opt LPCWSTR lpCalendar);
326 // Enumeration functions
327 __success(return != 0) BOOL
328 EnumDateFormatsExEx (DATEFMT_ENUMPROCEXEX lpDateFmtEnumProcExEx, LPCWSTR lpLocaleName, DWORD dwFlags, LPARAM lParam);
329 BOOL EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX lpTimeFmtEnumProcEx, LPCWSTR lpLocaleName, DWORD dwFlags, LPARAM lParam);
330 BOOL EnumCalendarInfoExEx(CALINFO_ENUMPROCEXEX pCalInfoEnumProcExEx, LPCWSTR lpLocaleName, CALID Calendar, CALTYPE CalType, LPARAM lParam);
332 int LCIDToLocaleName(__in LCID Locale, __out_ecount_opt(cchName) LPWSTR lpName, __in int cchName, __in DWORD dwFlags);
333 LCID LocaleNameToLCID(__in LPCWSTR lpName , __in DWORD dwFlags);
335 int ResolveLocaleName(__in LPCWSTR lpNameToResolve, __in_ecount_opt(cchLocaleName) LPWSTR lpLocaleName, __in int cchLocaleName);
337 __success(return == TRUE) BOOL
338 GetThreadPreferredUILanguages(__in DWORD dwFlags,
339 __out PULONG pulNumLanguages,
340 __out_ecount_opt(*pcchLanguagesBuffer) PWSTR pwszLanguagesBuffer,
341 __inout PULONG pcchLanguagesBuffer);
343 BOOL WINAPI EnumSystemLocalesEx(__in LOCALE_ENUMPROCEX lpLocaleEnumProc,
346 __in_opt LPVOID lpReserved);