ReactOS 0.4.16-dev-737-g3368adc
getqloc_downlevel.cpp
Go to the documentation of this file.
1/***
2*getqloc_downlevel.c - get qualified locale for downlevel OS
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* defines __acrt_get_qualified_locale_downlevel - get complete locale information
8*
9*******************************************************************************/
10#include <corecrt_internal.h>
11#include <locale.h>
12#include <stdlib.h>
13#include <string.h>
14
15extern "C" {
16
17// local defines
18#define __LCID_DEFAULT 0x1 // default language locale for country
19#define __LCID_PRIMARY 0x2 // primary language locale for country
20#define __LCID_FULL 0x4 // fully matched language locale for country
21#define __LCID_LANGUAGE 0x100 // language default seen
22#define __LCID_EXISTS 0x200 // language is installed
23
24typedef struct tagRGLOCINFO
25{
27 wchar_t chILanguage[8];
28 wchar_t * pchSEngLanguage;
30 wchar_t * pchSEngCountry;
35
36static bool TranslateName(const __crt_locale_string_table *, int, const wchar_t **);
37
38static void GetLcidFromLangCountry (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
40
41static void GetLcidFromLanguage (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
43
44static void GetLcidFromCountry (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
46
47static void GetLcidFromDefault (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
48
49static int ProcessCodePage (LPCWSTR lpCodePageStr, __crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
51static BOOL TestDefaultLanguage (LCID lcid, BOOL bTestPrimary, __crt_qualified_locale_data_downlevel* _psetloc_downlevel_data);
52
54static int GetPrimaryLen(wchar_t const*);
55
56// LANGID's of locales of nondefault languages
57extern __declspec(selectany) LANGID const __rglangidNotDefault[] =
58{
69};
70
71/***
72*BOOL __acrt_get_qualified_locale_downlevel - return fully qualified locale
73*
74*Purpose:
75* get default locale, qualify partially complete locales
76*
77*Entry:
78* lpInStr - input strings to be qualified
79* lpOutId - pointer to numeric LCIDs and codepage output
80* lpOutStr - pointer to string LCIDs and codepage output
81*
82*Exit:
83* TRUE if success, qualified locale is valid
84* FALSE if failure
85*
86*Exceptions:
87*
88*******************************************************************************/
90{
91 int iCodePage;
92
93 // Get setloc data from per thread data struct
95
96 // Set downlevel setloc data in per thread data struct for use by LCID downlevel APIs
98 __crt_qualified_locale_data_downlevel* _psetloc_downlevel_data;
99
100 memset(&downlevel_setloc, '\0', sizeof(__crt_qualified_locale_data_downlevel));
101 _psetloc_downlevel_data = __acrt_getptd()->_setloc_downlevel_data = &downlevel_setloc;
102
103 // initialize pointer to call locale info routine based on operating system
104
105 _psetloc_data->pchLanguage = lpInStr->szLanguage;
106
107 // convert non-NLS country strings to three-letter abbreviations
108 _psetloc_data->pchCountry = lpInStr->szCountry;
109 if (_psetloc_data->pchCountry && *_psetloc_data->pchCountry)
111 static_cast<int>(__acrt_rg_country_count - 1),
112 &_psetloc_data->pchCountry);
113
114 _psetloc_downlevel_data->iLcidState = 0;
115
116 if (_psetloc_data->pchLanguage && *_psetloc_data->pchLanguage)
117 {
118 if (_psetloc_data->pchCountry && *_psetloc_data->pchCountry)
119 {
120 // both language and country strings defined
121 GetLcidFromLangCountry(_psetloc_downlevel_data);
122 }
123 else
124 {
125 // language string defined, but country string undefined
126 GetLcidFromLanguage(_psetloc_downlevel_data);
127 }
128
129 if (!_psetloc_downlevel_data->iLcidState) {
130 // first attempt failed, try substituting the language name
131 // convert non-NLS language strings to three-letter abbrevs
133 static_cast<int>(__acrt_rg_language_count - 1),
134 &_psetloc_data->pchLanguage))
135 {
136 if (_psetloc_data->pchCountry && *_psetloc_data->pchCountry)
137 {
138 GetLcidFromLangCountry(_psetloc_downlevel_data);
139 }
140 else
141 {
142 GetLcidFromLanguage(_psetloc_downlevel_data);
143 }
144 }
145 }
146 }
147 else
148 {
149 if (_psetloc_data->pchCountry && *_psetloc_data->pchCountry)
150 {
151 // country string defined, but language string undefined
152 GetLcidFromCountry(_psetloc_downlevel_data);
153 }
154 else
155 {
156 // both language and country strings undefined
157 GetLcidFromDefault(_psetloc_downlevel_data);
158 }
159 }
160
161 // test for error in LCID processing
162 if (!_psetloc_downlevel_data->iLcidState)
163 return FALSE;
164
165 // process codepage value
166 iCodePage = ProcessCodePage(lpInStr ? lpInStr->szCodePage: nullptr, _psetloc_downlevel_data);
167
168 // verify codepage validity
169 if (!iCodePage || !IsValidCodePage((WORD)iCodePage))
170 return FALSE;
171
172 // verify locale is installed
173 if (!IsValidLocale(_psetloc_downlevel_data->lcidLanguage, LCID_INSTALLED))
174 return FALSE;
175
176 // set codepage
177 if (lpOutCodePage)
178 {
179 *lpOutCodePage = (UINT)iCodePage;
180 }
181
182 // store locale name in cache
184 _psetloc_downlevel_data->lcidLanguage,
185 _psetloc_data->_cacheLocaleName,
186 (int)_countof(_psetloc_data->_cacheLocaleName),
187 0);
188
189 // set locale name and codepage results
190 if (lpOutStr)
191 {
193 _psetloc_downlevel_data->lcidLanguage,
194 lpOutStr->szLocaleName,
195 (int)_countof(lpOutStr->szLocaleName),
196 0);
197
198 if (GetLocaleInfoW(_psetloc_downlevel_data->lcidLanguage, LOCALE_SENGLANGUAGE,
199 lpOutStr->szLanguage, MAX_LANG_LEN) == 0)
200 return FALSE;
201
202 if (GetLocaleInfoW(_psetloc_downlevel_data->lcidCountry, LOCALE_SENGCOUNTRY,
203 lpOutStr->szCountry, MAX_CTRY_LEN) == 0)
204 return FALSE;
205
206 _itow_s((int)iCodePage, (wchar_t *)lpOutStr->szCodePage, MAX_CP_LEN, 10);
207 }
208
209 return TRUE;
210}
211
212/***
213*BOOL TranslateName - convert known non-NLS string to NLS equivalent
214*
215*Purpose:
216* Provide compatibility with existing code for non-NLS strings
217*
218*Entry:
219* lpTable - pointer to __crt_locale_string_table used for translation
220* high - maximum index of table (size - 1)
221* ppchName - pointer to pointer of string to translate
222*
223*Exit:
224* ppchName - pointer to pointer of string possibly translated
225* TRUE if string translated, FALSE if unchanged
226*
227*Exceptions:
228*
229*******************************************************************************/
230static bool TranslateName (
231 const __crt_locale_string_table* lpTable,
232 int high,
233 const wchar_t ** ppchName)
234{
235 int low = 0;
236
237 // typical binary search - do until no more to search or match
238 while (low <= high)
239 {
240 int const i = (low + high) / 2;
241 int const cmp = _wcsicmp(*ppchName, lpTable[i].szName);
242
243 if (cmp == 0)
244 {
245 *ppchName = lpTable[i].chAbbrev;
246 return true;
247 }
248 else if (cmp < 0)
249 high = i - 1;
250 else
251 low = i + 1;
252 }
253
254 return false;
255}
256
257/***
258*void GetLcidFromLangCountry - get LCIDs from language and country strings
259*
260*Purpose:
261* Match the best LCIDs to the language and country string given.
262* After global variables are initialized, the LangCountryEnumProc
263* routine is registered as an EnumSystemLocalesA callback to actually
264* perform the matching as the LCIDs are enumerated.
265*
266*Entry:
267* pchLanguage - language string
268* bAbbrevLanguage - language string is a three-letter abbreviation
269* pchCountry - country string
270* bAbbrevCountry - country string ia a three-letter abbreviation
271* iPrimaryLen - length of language string with primary name
272*
273*Exit:
274* lcidLanguage - LCID of language string
275* lcidCountry - LCID of country string
276*
277*Exceptions:
278*
279*******************************************************************************/
281{
283
284 // initialize static variables for callback use
285 _psetloc_data->bAbbrevLanguage = wcslen(_psetloc_data->pchLanguage) == 3;
286 _psetloc_data->bAbbrevCountry = wcslen(_psetloc_data->pchCountry) == 3;
287 _psetloc_downlevel_data->lcidLanguage = 0;
288 _psetloc_data->iPrimaryLen = _psetloc_data->bAbbrevLanguage ?
289 2 : GetPrimaryLen(_psetloc_data->pchLanguage);
290
292
293 // locale value is invalid if the language was not installed or the language
294 // was not available for the country specified
295 if (!(_psetloc_downlevel_data->iLcidState & __LCID_LANGUAGE) ||
296 !(_psetloc_downlevel_data->iLcidState & __LCID_EXISTS) ||
297 !(_psetloc_downlevel_data->iLcidState & (__LCID_FULL |
300 _psetloc_downlevel_data->iLcidState = 0;
301}
302
303/***
304*BOOL CALLBACK LangCountryEnumProc - callback routine for GetLcidFromLangCountry
305*
306*Purpose:
307* Determine if LCID given matches the language in pchLanguage
308* and country in pchCountry.
309*
310*Entry:
311* lpLcidString - pointer to string with decimal LCID
312* pchCountry - pointer to country name
313* bAbbrevCountry - set if country is three-letter abbreviation
314*
315*Exit:
316* iLcidState - status of match
317* __LCID_FULL - both language and country match (best match)
318* __LCID_PRIMARY - primary language and country match (better)
319* __LCID_DEFAULT - default language and country match (good)
320* __LCID_LANGUAGE - default primary language exists
321* __LCID_EXISTS - full match of language string exists
322* (Overall match occurs for the best of FULL/PRIMARY/DEFAULT
323* and LANGUAGE/EXISTS both set.)
324* lcidLanguage - LCID matched
325* lcidCountry - LCID matched
326* FALSE if match occurred to terminate enumeration, else TRUE.
327*
328*Exceptions:
329*
330*******************************************************************************/
332{
335 LCID lcid = LcidFromHexString(lpLcidString);
336 wchar_t rgcInfo[120];
337
338 // test locale country against input value
339 if (GetLocaleInfoW(lcid,
340 _psetloc_data->bAbbrevCountry ?
342 rgcInfo, _countof(rgcInfo)) == 0)
343 {
344 // set error condition and exit
345 _psetloc_downlevel_data->iLcidState = 0;
346 return TRUE;
347 }
348 if (!_wcsicmp(_psetloc_data->pchCountry, rgcInfo))
349 {
350 // country matched - test for language match
351 if (GetLocaleInfoW(lcid,
352 _psetloc_data->bAbbrevLanguage ?
354 rgcInfo, _countof(rgcInfo)) == 0)
355 {
356 // set error condition and exit
357 _psetloc_downlevel_data->iLcidState = 0;
358 return TRUE;
359 }
360 if (!_wcsicmp(_psetloc_data->pchLanguage, rgcInfo))
361 {
362 // language matched also - set state and value
363 _psetloc_downlevel_data->iLcidState |= (__LCID_FULL |
366 _psetloc_downlevel_data->lcidLanguage = _psetloc_downlevel_data->lcidCountry = lcid;
367 }
368
369 // test if match already for primary langauage
370 else if (!(_psetloc_downlevel_data->iLcidState & __LCID_PRIMARY))
371 {
372 // if not, use _psetloc_data->iPrimaryLen to partial match language string
373 if (_psetloc_data->iPrimaryLen && !_wcsnicmp(_psetloc_data->pchLanguage, rgcInfo, _psetloc_data->iPrimaryLen))
374 {
375 // primary language matched - set state and country LCID
376 _psetloc_downlevel_data->iLcidState |= __LCID_PRIMARY;
377 _psetloc_downlevel_data->lcidCountry = lcid;
378
379 // if language is primary only (no subtype), set language LCID
380 if ((int)wcslen(_psetloc_data->pchLanguage) == _psetloc_data->iPrimaryLen)
381 _psetloc_downlevel_data->lcidLanguage = lcid;
382 }
383
384 // test if default language already defined
385 else if (!(_psetloc_downlevel_data->iLcidState & __LCID_DEFAULT))
386 {
387 // if not, test if locale language is default for country
388 if (TestDefaultCountry(lcid))
389 {
390 // default language for country - set state, value
391 _psetloc_downlevel_data->iLcidState |= __LCID_DEFAULT;
392 _psetloc_downlevel_data->lcidCountry = lcid;
393 }
394 }
395 }
396 }
397 // test if input language both exists and default primary language defined
398 if ((_psetloc_downlevel_data->iLcidState & (__LCID_LANGUAGE | __LCID_EXISTS)) !=
400 {
401 // test language match to determine whether it is installed
402 if (GetLocaleInfoW(lcid, _psetloc_data->bAbbrevLanguage ? LOCALE_SABBREVLANGNAME
404 rgcInfo, _countof(rgcInfo)) == 0)
405 {
406 // set error condition and exit
407 _psetloc_downlevel_data->iLcidState = 0;
408 return TRUE;
409 }
410
411 if (!_wcsicmp(_psetloc_data->pchLanguage, rgcInfo))
412 {
413 // language matched - set bit for existance
414 _psetloc_downlevel_data->iLcidState |= __LCID_EXISTS;
415
416 if (_psetloc_data->bAbbrevLanguage)
417 {
418 // abbreviation - set state
419 // also set language LCID if not set already
420 _psetloc_downlevel_data->iLcidState |= __LCID_LANGUAGE;
421 if (!_psetloc_downlevel_data->lcidLanguage)
422 _psetloc_downlevel_data->lcidLanguage = lcid;
423 }
424
425 // test if language is primary only (no sublanguage)
426 else if (_psetloc_data->iPrimaryLen && ((int)wcslen(_psetloc_data->pchLanguage) == _psetloc_data->iPrimaryLen))
427 {
428 // primary language only - test if default LCID
429 if (TestDefaultLanguage(lcid, TRUE, _psetloc_downlevel_data))
430 {
431 // default primary language - set state
432 // also set LCID if not set already
433 _psetloc_downlevel_data->iLcidState |= __LCID_LANGUAGE;
434 if (!_psetloc_downlevel_data->lcidLanguage)
435 _psetloc_downlevel_data->lcidLanguage = lcid;
436 }
437 }
438 else
439 {
440 // language with sublanguage - set state
441 // also set LCID if not set already
442 _psetloc_downlevel_data->iLcidState |= __LCID_LANGUAGE;
443 if (!_psetloc_downlevel_data->lcidLanguage)
444 _psetloc_downlevel_data->lcidLanguage = lcid;
445 }
446 }
447 else if (!_psetloc_data->bAbbrevLanguage && _psetloc_data->iPrimaryLen
448 && !_wcsicmp(_psetloc_data->pchLanguage, rgcInfo))
449 {
450 // primary language match - test for default language only
451 if (TestDefaultLanguage(lcid, FALSE, _psetloc_downlevel_data))
452 {
453 // default primary language - set state
454 // also set LCID if not set already
455 _psetloc_downlevel_data->iLcidState |= __LCID_LANGUAGE;
456 if (!_psetloc_downlevel_data->lcidLanguage)
457 _psetloc_downlevel_data->lcidLanguage = lcid;
458 }
459 }
460 }
461
462 // if LOCALE_FULL set, return FALSE to stop enumeration,
463 // else return TRUE to continue
464 return (_psetloc_downlevel_data->iLcidState & __LCID_FULL) == 0;
465}
466
467/***
468*void GetLcidFromLanguage - get LCIDs from language string
469*
470*Purpose:
471* Match the best LCIDs to the language string given. After global
472* variables are initialized, the LanguageEnumProc routine is
473* registered as an EnumSystemLocalesA callback to actually perform
474* the matching as the LCIDs are enumerated.
475*
476*Entry:
477* pchLanguage - language string
478* bAbbrevLanguage - language string is a three-letter abbreviation
479* iPrimaryLen - length of language string with primary name
480*
481*Exit:
482* lcidLanguage - lcidCountry - LCID of language with default
483* country
484*
485*Exceptions:
486*
487*******************************************************************************/
488static void GetLcidFromLanguage (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data)
489{
491
492 // initialize static variables for callback use
493 _psetloc_data->bAbbrevLanguage = wcslen(_psetloc_data->pchLanguage) == 3;
494 _psetloc_data->iPrimaryLen = _psetloc_data->bAbbrevLanguage ? 2 : GetPrimaryLen(_psetloc_data->pchLanguage);
495
497
498 // locale value is invalid if the language was not installed
499 // or the language was not available for the country specified
500 if (!(_psetloc_downlevel_data->iLcidState & __LCID_FULL))
501 _psetloc_downlevel_data->iLcidState = 0;
502}
503
504/***
505*BOOL CALLBACK LanguageEnumProc - callback routine for GetLcidFromLanguage
506*
507*Purpose:
508* Determine if LCID given matches the default country for the
509* language in pchLanguage.
510*
511*Entry:
512* lpLcidString - pointer to string with decimal LCID
513* pchLanguage - pointer to language name
514* bAbbrevLanguage - set if language is three-letter abbreviation
515*
516*Exit:
517* lcidLanguage - lcidCountry - LCID matched
518* FALSE if match occurred to terminate enumeration, else TRUE.
519*
520*Exceptions:
521*
522*******************************************************************************/
524{
527
528 LCID lcid = LcidFromHexString(lpLcidString);
529 wchar_t rgcInfo[120];
530
531 // test locale for language specified
532 if (GetLocaleInfoW(lcid, _psetloc_data->bAbbrevLanguage ? LOCALE_SABBREVLANGNAME
534 rgcInfo, _countof(rgcInfo)) == 0)
535 {
536 // set error condition and exit
537 _psetloc_downlevel_data->iLcidState = 0;
538 return TRUE;
539 }
540
541 if (!_wcsicmp(_psetloc_data->pchLanguage, rgcInfo))
542 {
543 // language matched - test if locale country is default
544 // or if locale is implied in the language string
545 if (_psetloc_data->bAbbrevLanguage || TestDefaultLanguage(lcid, TRUE, _psetloc_downlevel_data))
546 {
547 // this locale has the default country
548 _psetloc_downlevel_data->lcidLanguage = _psetloc_downlevel_data->lcidCountry = lcid;
549 _psetloc_downlevel_data->iLcidState |= __LCID_FULL;
550 }
551 }
552 else if (!_psetloc_data->bAbbrevLanguage && _psetloc_data->iPrimaryLen
553 && !_wcsicmp(_psetloc_data->pchLanguage, rgcInfo))
554 {
555 // primary language matched - test if locale country is default
556 if (TestDefaultLanguage(lcid, FALSE, _psetloc_downlevel_data))
557 {
558 // this is the default country
559 _psetloc_downlevel_data->lcidLanguage = _psetloc_downlevel_data->lcidCountry = lcid;
560 _psetloc_downlevel_data->iLcidState |= __LCID_FULL;
561 }
562 }
563
564 return (_psetloc_downlevel_data->iLcidState & __LCID_FULL) == 0;
565}
566
567/***
568*void GetLcidFromCountry - get LCIDs from country string
569*
570*Purpose:
571* Match the best LCIDs to the country string given. After global
572* variables are initialized, the CountryEnumProc routine is
573* registered as an EnumSystemLocalesA callback to actually perform
574* the matching as the LCIDs are enumerated.
575*
576*Entry:
577* pchCountry - country string
578* bAbbrevCountry - country string is a three-letter abbreviation
579*
580*Exit:
581* lcidLanguage - lcidCountry - LCID of country with default
582* language
583*
584*Exceptions:
585*
586*******************************************************************************/
587static void GetLcidFromCountry (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data)
588{
590 _psetloc_data->bAbbrevCountry = wcslen(_psetloc_data->pchCountry) == 3;
591
593
594 // locale value is invalid if the country was not defined or
595 // no default language was found
596 if (!(_psetloc_downlevel_data->iLcidState & __LCID_FULL))
597 _psetloc_downlevel_data->iLcidState = 0;
598}
599
600/***
601*BOOL CALLBACK CountryEnumProc - callback routine for GetLcidFromCountry
602*
603*Purpose:
604* Determine if LCID given matches the default language for the
605* country in pchCountry.
606*
607*Entry:
608* lpLcidString - pointer to string with decimal LCID
609* pchCountry - pointer to country name
610* bAbbrevCountry - set if country is three-letter abbreviation
611*
612*Exit:
613* lcidLanguage - lcidCountry - LCID matched
614* FALSE if match occurred to terminate enumeration, else TRUE.
615*
616*Exceptions:
617*
618*******************************************************************************/
620{
623 LCID lcid = LcidFromHexString(lpLcidString);
624 wchar_t rgcInfo[120];
625
626 // test locale for country specified
627 if (GetLocaleInfoW(lcid, _psetloc_data->bAbbrevCountry ? LOCALE_SABBREVCTRYNAME
629 rgcInfo, _countof(rgcInfo)) == 0)
630 {
631 // set error condition and exit
632 _psetloc_downlevel_data->iLcidState = 0;
633 return TRUE;
634 }
635 if (!_wcsicmp(_psetloc_data->pchCountry, rgcInfo))
636 {
637 // language matched - test if locale country is default
638 if (TestDefaultCountry(lcid))
639 {
640 // this locale has the default language
641 _psetloc_downlevel_data->lcidLanguage = _psetloc_downlevel_data->lcidCountry = lcid;
642 _psetloc_downlevel_data->iLcidState |= __LCID_FULL;
643 }
644 }
645 return (_psetloc_downlevel_data->iLcidState & __LCID_FULL) == 0;
646}
647
648/***
649*void GetLcidFromDefault - get default LCIDs
650*
651*Purpose:
652* Set both language and country LCIDs to the system default.
653*
654*Entry:
655* None.
656*
657*Exit:
658* lcidLanguage - set to system LCID
659* lcidCountry - set to system LCID
660*
661*Exceptions:
662*
663*******************************************************************************/
664static void GetLcidFromDefault (__crt_qualified_locale_data_downlevel* _psetloc_downlevel_data)
665{
666 _psetloc_downlevel_data->iLcidState |= (__LCID_FULL | __LCID_LANGUAGE);
667 _psetloc_downlevel_data->lcidLanguage = _psetloc_downlevel_data->lcidCountry = GetUserDefaultLCID();
668}
669
670/***
671*int ProcessCodePage - convert codepage string to numeric value
672*
673*Purpose:
674* Process codepage string consisting of a decimal string, or the
675* special case strings "ACP" and "OCP", for ANSI and OEM codepages,
676* respectively. Null pointer or string returns the ANSI codepage.
677*
678*Entry:
679* lpCodePageStr - pointer to codepage string
680*
681*Exit:
682* Returns numeric value of codepage.
683*
684*Exceptions:
685*
686*******************************************************************************/
687static int ProcessCodePage (LPCWSTR lpCodePageStr, __crt_qualified_locale_data_downlevel* _psetloc_downlevel_data)
688{
689 int iCodePage;
690
691 if (!lpCodePageStr || !*lpCodePageStr || !wcscmp(lpCodePageStr, L"ACP"))
692 {
693 // get ANSI codepage for the country LCID
694 if (GetLocaleInfoW(_psetloc_downlevel_data->lcidCountry, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
695 (LPWSTR) &iCodePage, sizeof(iCodePage) / sizeof(wchar_t)) == 0)
696 return 0;
697
698 if (iCodePage == 0) // for locales have no assoicated ANSI codepage, e.g. Hindi locale
699 return GetACP();
700 }
701 else if (!wcscmp(lpCodePageStr, L"OCP"))
702 {
703 // get OEM codepage for the country LCID
704 if (GetLocaleInfoW(_psetloc_downlevel_data->lcidCountry, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
705 (LPWSTR) &iCodePage, sizeof(iCodePage) / sizeof(wchar_t)) == 0)
706 return 0;
707 }
708 else
709 {
710 // convert decimal string to numeric value
711 iCodePage = (int)_wtol(lpCodePageStr);
712 }
713
714 return iCodePage;
715}
716
717/***
718*BOOL TestDefaultCountry - determine if default locale for country
719*
720*Purpose:
721* Using a hardcoded list, determine if the locale of the given LCID
722* has the default sublanguage for the locale primary language. The
723* list contains the locales NOT having the default sublanguage.
724*
725*Entry:
726* lcid - LCID of locale to test
727*
728*Exit:
729* Returns TRUE if default sublanguage, else FALSE.
730*
731*Exceptions:
732*
733*******************************************************************************/
735{
737 int i;
738
739 for (i = 0; i < _countof(__rglangidNotDefault); i++)
740 {
741 if (langid == __rglangidNotDefault[i])
742 return FALSE;
743 }
744 return TRUE;
745}
746
747/***
748*BOOL TestDefaultLanguage - determine if default locale for language
749*
750*Purpose:
751* Determines if the given LCID has the default sublanguage.
752* If bTestPrimary is set, also allow TRUE when string contains an
753* implicit sublanguage.
754*
755*Entry:
756* LCID - lcid of locale to test
757* bTestPrimary - set if testing if language is primary
758*
759*Exit:
760* Returns TRUE if sublanguage is default for locale tested.
761* If bTestPrimary set, TRUE is language has implied sublanguge.
762*
763*Exceptions:
764*
765*******************************************************************************/
766static BOOL TestDefaultLanguage (LCID lcid, BOOL bTestPrimary, __crt_qualified_locale_data_downlevel* _psetloc_downlevel_data)
767{
768 UNREFERENCED_PARAMETER(_psetloc_downlevel_data); // CRT_REFACTOR TODO
769
770 DWORD dwLanguage;
773
774 if (GetLocaleInfoW(lcidDefault, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER,
775 (LPWSTR) &dwLanguage, sizeof(dwLanguage) / sizeof(wchar_t)) == 0)
776 return FALSE;
777
778 if (lcid != dwLanguage)
779 {
780 // test if string contains an implicit sublanguage by
781 // having a character other than upper/lowercase letters.
782 if (bTestPrimary && GetPrimaryLen(_psetloc_data->pchLanguage) == (int)wcslen(_psetloc_data->pchLanguage))
783 return FALSE;
784 }
785 return TRUE;
786}
787
788/***
789*LCID LcidFromHexString - convert hex string to value for LCID
790*
791*Purpose:
792* LCID values returned in hex ANSI strings - straight conversion
793*
794*Entry:
795* lpHexString - pointer to hex string to convert
796*
797*Exit:
798* Returns LCID computed.
799*
800*Exceptions:
801*
802*******************************************************************************/
804{
805 wchar_t ch;
806 DWORD lcid = 0;
807
808#pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 This is an idiomatic nul termination check that Prefast doesn't understand.
809 while ((ch = *lpHexString++) != '\0')
810 {
811 if (ch >= 'a' && ch <= 'f')
812 ch += static_cast<wchar_t>('9' + 1 - 'a');
813 else if (ch >= 'A' && ch <= 'F')
814 ch += static_cast<wchar_t>('9' + 1 - 'A');
815 lcid = lcid * 0x10 + ch - '0';
816 }
817
818 return (LCID)lcid;
819}
820
821/***
822*int GetPrimaryLen - get length of primary language name
823*
824*Purpose:
825* Determine primary language string length by scanning until
826* first non-alphabetic character.
827*
828*Entry:
829* pchLanguage - string to scan
830*
831*Exit:
832* Returns length of primary language string.
833*
834*Exceptions:
835*
836*******************************************************************************/
837static int GetPrimaryLen (wchar_t const* pchLanguage)
838{
839 int len = 0;
840 wchar_t ch;
841
842 ch = *pchLanguage++;
843 while ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
844 {
845 len++;
846 ch = *pchLanguage++;
847 }
848
849 return len;
850}
851
852} // extern "C"
#define __cdecl
Definition: accygwin.h:79
#define MAX_LANG_LEN
#define MAX_CP_LEN
#define MAX_CTRY_LEN
__acrt_ptd *__cdecl __acrt_getptd(void)
__crt_locale_string_table const __acrt_rg_language[]
__crt_locale_string_table const __acrt_rg_country[]
size_t const __acrt_rg_language_count
int WINAPI __acrt_LCIDToLocaleName(_In_ LCID locale, _Out_writes_opt_(name_count) LPWSTR name, _In_ int name_count, _In_ DWORD flags)
size_t const __acrt_rg_country_count
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CALLBACK
Definition: compat.h:35
BOOL WINAPI EnumSystemLocalesW(LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2999
UINT WINAPI GetACP(void)
Definition: locale.c:2021
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2079
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: locale.c:2923
LCID WINAPI GetUserDefaultLCID(void)
Definition: locale.c:1211
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1666
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
void __declspec(noinline) __cdecl _free_base(void *const block)
Definition: free_base.cpp:98
static BOOL CALLBACK LangCountryEnumProc(_In_z_ PWSTR)
BOOL __cdecl __acrt_get_qualified_locale_downlevel(const __crt_locale_strings *lpInStr, UINT *lpOutCodePage, __crt_locale_strings *lpOutStr)
static void GetLcidFromDefault(__crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
struct tagRGLOCINFO RGLOCINFO
#define __LCID_LANGUAGE
static void GetLcidFromLangCountry(__crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
static LCID LcidFromHexString(_In_z_ PCWSTR)
#define __LCID_EXISTS
static void GetLcidFromCountry(__crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
static bool TranslateName(const __crt_locale_string_table *, int, const wchar_t **)
static BOOL CALLBACK LanguageEnumProc(_In_z_ PWSTR)
static int ProcessCodePage(LPCWSTR lpCodePageStr, __crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
#define __LCID_PRIMARY
#define __LCID_FULL
static BOOL CALLBACK CountryEnumProc(_In_z_ PWSTR)
static int GetPrimaryLen(wchar_t const *)
static void GetLcidFromLanguage(__crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
static BOOL TestDefaultCountry(LCID)
#define __LCID_DEFAULT
static BOOL TestDefaultLanguage(LCID lcid, BOOL bTestPrimary, __crt_qualified_locale_data_downlevel *_psetloc_downlevel_data)
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
int CDECL _itow_s(int value, wchar_t *str, size_t size, int radix)
Definition: itow.c:222
USHORT LANGID
Definition: mui.h:9
#define cmp(status, error)
Definition: error.c:114
LANGID langid
Definition: msctf.idl:644
unsigned int UINT
Definition: ndis.h:50
#define _In_z_
Definition: no_sal2.h:164
#define SORT_DEFAULT
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define MAKELCID(lgid, srtid)
#define L(x)
Definition: ntvdm.h:50
static const WCHAR szName[]
Definition: powrprof.c:45
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define SUBLANG_SWEDISH_FINLAND
Definition: nls.h:359
#define SUBLANG_SERBIAN_CYRILLIC
Definition: nls.h:330
#define MAKELANGID(p, s)
Definition: nls.h:15
#define SUBLANG_FRENCH_SWISS
Definition: nls.h:245
#define SUBLANG_ITALIAN_SWISS
Definition: nls.h:270
#define LANG_GERMAN
Definition: nls.h:62
#define LANG_BASQUE
Definition: nls.h:34
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define SUBLANG_FRENCH_CANADIAN
Definition: nls.h:244
#define SUBLANG_FRENCH_BELGIAN
Definition: nls.h:243
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define LANG_SWEDISH
Definition: nls.h:125
#define LANG_SERBIAN
Definition: nls.h:116
DWORD LCID
Definition: nls.h:13
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_AFRIKAANS
Definition: nls.h:25
#define LANG_FRENCH
Definition: nls.h:58
#define LANG_ITALIAN
Definition: nls.h:75
#define LANG_CATALAN
Definition: nls.h:41
#define SUBLANG_GERMAN_LUXEMBOURG
Definition: nls.h:254
#define memset(x, y, z)
Definition: compat.h:39
#define _countof(array)
Definition: sndvol32.h:70
__crt_qualified_locale_data_downlevel * _setloc_downlevel_data
__crt_qualified_locale_data _setloc_data
wchar_t szLocaleName[LOCALE_NAME_MAX_LENGTH]
wchar_t szLanguage[MAX_LANG_LEN]
wchar_t szCountry[MAX_CTRY_LEN]
wchar_t szCodePage[MAX_CP_LEN]
wchar_t _cacheLocaleName[LOCALE_NAME_MAX_LENGTH]
wchar_t chIDefaultAnsiCodepage[8]
wchar_t chILanguage[8]
wchar_t chSAbbrevLangName[4]
wchar_t * pchSEngCountry
wchar_t chIDefaultCodepage[8]
wchar_t * pchSEngLanguage
wchar_t chSAbbrevCtryName[4]
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define LOCALE_IDEFAULTCODEPAGE
Definition: winnls.h:39
#define LCID_INSTALLED
Definition: winnls.h:203
#define LOCALE_SENGLANGUAGE
Definition: winnls.h:27
#define LOCALE_ILANGUAGE
Definition: winnls.h:25
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:40
#define LOCALE_SABBREVLANGNAME
Definition: winnls.h:29
#define LOCALE_SENGCOUNTRY
Definition: winnls.h:33
#define LOCALE_SABBREVCTRYNAME
Definition: winnls.h:35
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185