ReactOS 0.4.15-dev-5884-gab5aff5
lang.c
Go to the documentation of this file.
1/*
2 * Locale support
3 *
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 David Lee Lambert
6 * Copyright 2000 Julio César Gázquez
7 * Copyright 2002 Alexandre Julliard for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <k32.h>
25
26#define NDEBUG
27#include <debug.h>
29
30#include "lcformat_private.h"
31#ifdef __REACTOS__
32 #include "japanese.h"
33#endif
34
35#define REG_SZ 1
36extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen);
37extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen);
38extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2);
39#ifdef __REACTOS__
41#else
43#endif
44#define NLSRC_OFFSET 5000 /* FIXME */
45
47
48#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|\
49 LOCALE_RETURN_NUMBER|LOCALE_RETURN_GENITIVE_NAMES)
50
51static const WCHAR szLocaleKeyName[] = {
52 '\\', 'R', 'e', 'g', 'i', 's', 't', 'r', 'y', '\\',
53 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
54 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
55 'C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0
56};
57
58static const WCHAR szLangGroupsKeyName[] = {
59 '\\', 'R', 'e', 'g', 'i', 's', 't', 'r', 'y', '\\',
60 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
61 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
62 'C','o','n','t','r','o','l','\\','N','l','s','\\',
63 'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0
64};
65
66#if (WINVER >= 0x0600)
67/* Charset to codepage map, sorted by name. */
68static const struct charset_entry
69{
70 const char *charset_name;
72} charset_names[] =
73{
74 { "BIG5", 950 },
75 { "CP1250", 1250 },
76 { "CP1251", 1251 },
77 { "CP1252", 1252 },
78 { "CP1253", 1253 },
79 { "CP1254", 1254 },
80 { "CP1255", 1255 },
81 { "CP1256", 1256 },
82 { "CP1257", 1257 },
83 { "CP1258", 1258 },
84 { "CP932", 932 },
85 { "CP936", 936 },
86 { "CP949", 949 },
87 { "CP950", 950 },
88 { "EUCJP", 20932 },
89 { "GB2312", 936 },
90 { "IBM037", 37 },
91 { "IBM1026", 1026 },
92 { "IBM424", 424 },
93 { "IBM437", 437 },
94 { "IBM500", 500 },
95 { "IBM850", 850 },
96 { "IBM852", 852 },
97 { "IBM855", 855 },
98 { "IBM857", 857 },
99 { "IBM860", 860 },
100 { "IBM861", 861 },
101 { "IBM862", 862 },
102 { "IBM863", 863 },
103 { "IBM864", 864 },
104 { "IBM865", 865 },
105 { "IBM866", 866 },
106 { "IBM869", 869 },
107 { "IBM874", 874 },
108 { "IBM875", 875 },
109 { "ISO88591", 28591 },
110 { "ISO885910", 28600 },
111 { "ISO885913", 28603 },
112 { "ISO885914", 28604 },
113 { "ISO885915", 28605 },
114 { "ISO885916", 28606 },
115 { "ISO88592", 28592 },
116 { "ISO88593", 28593 },
117 { "ISO88594", 28594 },
118 { "ISO88595", 28595 },
119 { "ISO88596", 28596 },
120 { "ISO88597", 28597 },
121 { "ISO88598", 28598 },
122 { "ISO88599", 28599 },
123 { "KOI8R", 20866 },
124 { "KOI8U", 21866 },
125 { "UTF8", CP_UTF8 }
126};
127#endif
128
130{
131 WCHAR win_name[128]; /* Windows name ("en-US") */
132 WCHAR lang[128]; /* language ("en") (note: buffer contains the other strings too) */
133 WCHAR *country; /* country ("US") */
134 WCHAR *charset; /* charset ("UTF-8") for Unix format only */
135 WCHAR *script; /* script ("Latn") for Windows format only */
136 WCHAR *modifier; /* modifier or sort order */
137 LCID lcid; /* corresponding LCID */
138 int matches; /* number of elements matching LCID (0..4) */
139 UINT codepage; /* codepage corresponding to charset */
140};
141
142/* locale ids corresponding to the various Unix locale parameters */
151
152static const WCHAR iCalendarTypeW[] = {'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
153static const WCHAR iCountryW[] = {'i','C','o','u','n','t','r','y',0};
154static const WCHAR iCurrDigitsW[] = {'i','C','u','r','r','D','i','g','i','t','s',0};
155static const WCHAR iCurrencyW[] = {'i','C','u','r','r','e','n','c','y',0};
156static const WCHAR iDateW[] = {'i','D','a','t','e',0};
157static const WCHAR iDigitsW[] = {'i','D','i','g','i','t','s',0};
158static const WCHAR iFirstDayOfWeekW[] = {'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
159static const WCHAR iFirstWeekOfYearW[] = {'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
160static const WCHAR iLDateW[] = {'i','L','D','a','t','e',0};
161static const WCHAR iLZeroW[] = {'i','L','Z','e','r','o',0};
162static const WCHAR iMeasureW[] = {'i','M','e','a','s','u','r','e',0};
163static const WCHAR iNegCurrW[] = {'i','N','e','g','C','u','r','r',0};
164static const WCHAR iNegNumberW[] = {'i','N','e','g','N','u','m','b','e','r',0};
165static const WCHAR iPaperSizeW[] = {'i','P','a','p','e','r','S','i','z','e',0};
166static const WCHAR iTLZeroW[] = {'i','T','L','Z','e','r','o',0};
167static const WCHAR iTimePrefixW[] = {'i','T','i','m','e','P','r','e','f','i','x',0};
168static const WCHAR iTimeW[] = {'i','T','i','m','e',0};
169static const WCHAR s1159W[] = {'s','1','1','5','9',0};
170static const WCHAR s2359W[] = {'s','2','3','5','9',0};
171static const WCHAR sCountryW[] = {'s','C','o','u','n','t','r','y',0};
172static const WCHAR sCurrencyW[] = {'s','C','u','r','r','e','n','c','y',0};
173static const WCHAR sDateW[] = {'s','D','a','t','e',0};
174static const WCHAR sDecimalW[] = {'s','D','e','c','i','m','a','l',0};
175static const WCHAR sGroupingW[] = {'s','G','r','o','u','p','i','n','g',0};
176static const WCHAR sLanguageW[] = {'s','L','a','n','g','u','a','g','e',0};
177static const WCHAR sListW[] = {'s','L','i','s','t',0};
178static const WCHAR sLongDateW[] = {'s','L','o','n','g','D','a','t','e',0};
179static const WCHAR sMonDecimalSepW[] = {'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
180static const WCHAR sMonGroupingW[] = {'s','M','o','n','G','r','o','u','p','i','n','g',0};
181static const WCHAR sMonThousandSepW[] = {'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
182static const WCHAR sNativeDigitsW[] = {'s','N','a','t','i','v','e','D','i','g','i','t','s',0};
183static const WCHAR sNegativeSignW[] = {'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
184static const WCHAR sPositiveSignW[] = {'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
185static const WCHAR sShortDateW[] = {'s','S','h','o','r','t','D','a','t','e',0};
186static const WCHAR sThousandW[] = {'s','T','h','o','u','s','a','n','d',0};
187static const WCHAR sTimeFormatW[] = {'s','T','i','m','e','F','o','r','m','a','t',0};
188static const WCHAR sTimeW[] = {'s','T','i','m','e',0};
189static const WCHAR sYearMonthW[] = {'s','Y','e','a','r','M','o','n','t','h',0};
190static const WCHAR NumShapeW[] = {'N','u','m','s','h','a','p','e',0};
191
192static struct registry_value
193{
195 const WCHAR *name;
197} registry_values[] =
198{
209 { LOCALE_IPAPERSIZE, iPaperSizeW },
210 { LOCALE_ITIME, iTimeW },
211 { LOCALE_S1159, s1159W },
212 { LOCALE_S2359, s2359W },
214 { LOCALE_SDATE, sDateW },
217 { LOCALE_SLIST, sListW },
226 { LOCALE_STIME, sTimeW },
228 { LOCALE_SYEARMONTH, sYearMonthW },
229 /* The following are not listed under MSDN as supported,
230 * but seem to be used and also stored in the registry.
231 */
233 { LOCALE_IDATE, iDateW },
238 /* The following are used in XP and later */
239 { LOCALE_IDIGITSUBSTITUTION, NumShapeW },
243
244static RTL_CRITICAL_SECTION cache_section = { NULL, -1, 0, 0, 0, 0 };
245
246#ifndef __REACTOS__
247/* Copy Ascii string to Unicode without using codepages */
248static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
249{
250 while (n > 1 && *src)
251 {
252 *dst++ = (unsigned char)*src++;
253 n--;
254 }
255 if (n) *dst = 0;
256}
257#endif
258
259/***********************************************************************
260 * get_lcid_codepage
261 *
262 * Retrieve the ANSI codepage for a given locale.
263 */
264static inline UINT get_lcid_codepage( LCID lcid )
265{
266 UINT ret;
267 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
268 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
269 return ret;
270}
271
272#if (WINVER >= 0x0600)
273/***********************************************************************
274 * charset_cmp (internal)
275 */
276static int charset_cmp( const void *name, const void *entry )
277{
278 const struct charset_entry *charset = entry;
279 return strcasecmp( name, charset->charset_name );
280}
281
282/***********************************************************************
283 * find_charset
284 */
285static UINT find_charset( const WCHAR *name )
286{
287 const struct charset_entry *entry;
288 char charset_name[16];
289 size_t i, j;
290
291 /* remove punctuation characters from charset name */
292 for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++)
293 if (isalnum((unsigned char)name[i])) charset_name[j++] = name[i];
294 charset_name[j] = 0;
295
296 entry = bsearch( charset_name, charset_names, ARRAY_SIZE( charset_names ),
297 sizeof(charset_names[0]), charset_cmp );
298 if (entry) return entry->codepage;
299 return 0;
300}
301
302static LANGID get_default_sublang( LANGID lang )
303{
304 switch (lang)
305 {
315 }
317 return lang;
318}
319
320/***********************************************************************
321 * find_locale_id_callback
322 */
323static BOOL CALLBACK find_locale_id_callback( HMODULE hModule, LPCWSTR type,
325{
326 struct locale_name *data = (struct locale_name *)lParam;
327 WCHAR buffer[128];
328 int matches = 0;
329 LCID lcid = MAKELCID( lang, SORT_DEFAULT ); /* FIXME: handle sort order */
330
331 if (PRIMARYLANGID(lang) == LANG_NEUTRAL) return TRUE; /* continue search */
332
333 /* first check exact name */
334 if (data->win_name[0] &&
336 {
337 if (!strcmpiW( data->win_name, buffer ))
338 {
339 matches = 4; /* everything matches */
340 goto done;
341 }
342 }
343
346 return TRUE;
347 if (strcmpiW( buffer, data->lang )) return TRUE;
348 matches++; /* language name matched */
349
350 if (data->script)
351 {
352 if (GetLocaleInfoW( lcid, LOCALE_SSCRIPTS | LOCALE_NOUSEROVERRIDE,
354 {
355 const WCHAR *p = buffer;
356 unsigned int len = strlenW( data->script );
357 while (*p)
358 {
359 if (!strncmpiW( p, data->script, len ) && (!p[len] || p[len] == ';')) break;
360 if (!(p = strchrW( p, ';'))) goto done;
361 p++;
362 }
363 if (!*p) goto done;
364 matches++; /* script matched */
365 }
366 }
367
368 if (data->country)
369 {
372 {
373 if (strcmpiW( buffer, data->country )) goto done;
374 matches++; /* country name matched */
375 }
376 }
377 else /* match default language */
378 {
379 LANGID def_lang = data->script ? lang : MAKELANGID( PRIMARYLANGID(lang), LANG_NEUTRAL );
380 if (lang == get_default_sublang( def_lang )) matches++;
381 }
382
383 if (data->codepage)
384 {
385 UINT unix_cp;
386 if (GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER,
387 (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) ))
388 {
389 if (unix_cp == data->codepage) matches++;
390 }
391 }
392
393 /* FIXME: check sort order */
394
395done:
396 if (matches > data->matches)
397 {
398 data->lcid = lcid;
399 data->matches = matches;
400 }
401 return (data->matches < 4); /* no need to continue for perfect match */
402}
403
404
405/***********************************************************************
406 * parse_locale_name
407 *
408 * Parse a locale name into a struct locale_name, handling both Windows and Unix formats.
409 * Unix format is: lang[_country][.charset][@modifier]
410 * Windows format is: lang[-script][-country][_modifier]
411 */
412static void parse_locale_name( const WCHAR *str, struct locale_name *name )
413{
414 static const WCHAR sepW[] = {'-','_','.','@',0};
415 static const WCHAR winsepW[] = {'-','_',0};
416 static const WCHAR posixW[] = {'P','O','S','I','X',0};
417 static const WCHAR cW[] = {'C',0};
418 static const WCHAR latinW[] = {'l','a','t','i','n',0};
419 static const WCHAR latnW[] = {'-','L','a','t','n',0};
420 WCHAR *p;
421
422 TRACE("%s\n", debugstr_w(str));
423
424 name->country = name->charset = name->script = name->modifier = NULL;
426 name->matches = 0;
427 name->codepage = 0;
428 name->win_name[0] = 0;
429 lstrcpynW( name->lang, str, ARRAY_SIZE( name->lang ));
430
431 if (!*name->lang)
432 {
433 name->lcid = LOCALE_INVARIANT;
434 name->matches = 4;
435 return;
436 }
437
438 if (!(p = strpbrkW( name->lang, sepW )))
439 {
440 if (!strcmpW( name->lang, posixW ) || !strcmpW( name->lang, cW ))
441 {
442 name->matches = 4; /* perfect match for default English lcid */
443 return;
444 }
445 strcpyW( name->win_name, name->lang );
446 }
447 else if (*p == '-') /* Windows format */
448 {
449 strcpyW( name->win_name, name->lang );
450 *p++ = 0;
451 name->country = p;
452 if ((p = strpbrkW( p, winsepW )) && *p == '-')
453 {
454 *p++ = 0;
455 name->script = name->country;
456 name->country = p;
457 p = strpbrkW( p, winsepW );
458 }
459 if (p)
460 {
461 *p++ = 0;
462 name->modifier = p;
463 }
464 /* second value can be script or country, check length to resolve the ambiguity */
465 if (!name->script && strlenW( name->country ) == 4)
466 {
467 name->script = name->country;
468 name->country = NULL;
469 }
470 }
471 else /* Unix format */
472 {
473 if (*p == '_')
474 {
475 *p++ = 0;
476 name->country = p;
477 p = strpbrkW( p, sepW + 2 );
478 }
479 if (p && *p == '.')
480 {
481 *p++ = 0;
482 name->charset = p;
483 p = strchrW( p, '@' );
484 }
485 if (p)
486 {
487 *p++ = 0;
488 name->modifier = p;
489 }
490
491 if (name->charset)
492 name->codepage = find_charset( name->charset );
493
494 /* rebuild a Windows name if possible */
495
496 if (name->charset) goto done; /* can't specify charset in Windows format */
497 if (name->modifier && strcmpW( name->modifier, latinW ))
498 goto done; /* only Latn script supported for now */
499 strcpyW( name->win_name, name->lang );
500 if (name->modifier) strcatW( name->win_name, latnW );
501 if (name->country)
502 {
503 p = name->win_name + strlenW(name->win_name);
504 *p++ = '-';
505 strcpyW( p, name->country );
506 }
507 }
508done:
510 find_locale_id_callback, (LPARAM)name );
511}
512#endif
513
514/***********************************************************************
515 * convert_default_lcid
516 *
517 * Get the default LCID to use for a given lctype in GetLocaleInfo.
518 */
520{
524 {
525 LCID default_id = 0;
526
527 switch(lctype & 0xffff)
528 {
529 case LOCALE_SSORTNAME:
530 default_id = lcid_LC_COLLATE;
531 break;
532
536 case LOCALE_IDEFAULTEBCDICCODEPAGE:
539 default_id = lcid_LC_CTYPE;
540 break;
541
543 case LOCALE_ICURRENCY:
545 case LOCALE_INEGCURR:
552 case LOCALE_SCURRENCY:
557 case LOCALE_SNATIVECURRNAME:
558 default_id = lcid_LC_MONETARY;
559 break;
560
561 case LOCALE_IDIGITS:
562 case LOCALE_IDIGITSUBSTITUTION:
563 case LOCALE_ILZERO:
565 case LOCALE_SDECIMAL:
566 case LOCALE_SGROUPING:
567 //case LOCALE_SNAN:
570 //case LOCALE_SNEGINFINITY:
571 //case LOCALE_SPOSINFINITY:
573 case LOCALE_STHOUSAND:
574 default_id = lcid_LC_NUMERIC;
575 break;
576
578 case LOCALE_ICENTURY:
579 case LOCALE_IDATE:
580 case LOCALE_IDAYLZERO:
583 case LOCALE_ILDATE:
584 case LOCALE_IMONLZERO:
586 case LOCALE_ITIME:
588 case LOCALE_ITLZERO:
589 case LOCALE_S1159:
590 case LOCALE_S2359:
611 case LOCALE_SDATE:
612 case LOCALE_SDAYNAME1:
613 case LOCALE_SDAYNAME2:
614 case LOCALE_SDAYNAME3:
615 case LOCALE_SDAYNAME4:
616 case LOCALE_SDAYNAME5:
617 case LOCALE_SDAYNAME6:
618 case LOCALE_SDAYNAME7:
619 //case LOCALE_SDURATION:
620 case LOCALE_SLONGDATE:
635 //case LOCALE_SSHORTESTDAYNAME1:
636 //case LOCALE_SSHORTESTDAYNAME2:
637 //case LOCALE_SSHORTESTDAYNAME3:
638 //case LOCALE_SSHORTESTDAYNAME4:
639 //case LOCALE_SSHORTESTDAYNAME5:
640 //case LOCALE_SSHORTESTDAYNAME6:
641 //case LOCALE_SSHORTESTDAYNAME7:
642 case LOCALE_STIME:
644 case LOCALE_SYEARMONTH:
645 default_id = lcid_LC_TIME;
646 break;
647
648 case LOCALE_IPAPERSIZE:
649 default_id = lcid_LC_PAPER;
650 break;
651
652 case LOCALE_IMEASURE:
653 default_id = lcid_LC_MEASUREMENT;
654 break;
655
656 case LOCALE_ICOUNTRY:
657 default_id = lcid_LC_TELEPHONE;
658 break;
659 }
660 if (default_id) lcid = default_id;
661 }
662 return ConvertDefaultLocale( lcid );
663}
664
665/***********************************************************************
666 * is_genitive_name_supported
667 *
668 * Determine could LCTYPE basically support genitive name form or not.
669 */
671{
672 switch(lctype & 0xffff)
673 {
687 return TRUE;
688 default:
689 return FALSE;
690 }
691}
692
693/***********************************************************************
694 * create_registry_key
695 *
696 * Create the Control Panel\\International registry key.
697 */
698static inline HANDLE create_registry_key(void)
699{
700 static const WCHAR cplW[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l',0};
701 static const WCHAR intlW[] = {'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
704 HANDLE cpl_key, hkey = 0;
705
706 if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey ) != STATUS_SUCCESS) return 0;
707
708 attr.Length = sizeof(attr);
709 attr.RootDirectory = hkey;
710 attr.ObjectName = &nameW;
711 attr.Attributes = 0;
712 attr.SecurityDescriptor = NULL;
713 attr.SecurityQualityOfService = NULL;
714 RtlInitUnicodeString( &nameW, cplW );
715
716 if (!NtCreateKey( &cpl_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
717 {
718 NtClose( attr.RootDirectory );
719 attr.RootDirectory = cpl_key;
720 RtlInitUnicodeString( &nameW, intlW );
721 if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) hkey = 0;
722 }
723 NtClose( attr.RootDirectory );
724 return hkey;
725}
726
727/***********************************************************************
728 * GetUserDefaultLangID (KERNEL32.@)
729 *
730 * Get the default language Id for the current user.
731 *
732 * PARAMS
733 * None.
734 *
735 * RETURNS
736 * The current LANGID of the default language for the current user.
737 */
739{
741}
742
743
744/***********************************************************************
745 * GetSystemDefaultLangID (KERNEL32.@)
746 *
747 * Get the default language Id for the system.
748 *
749 * PARAMS
750 * None.
751 *
752 * RETURNS
753 * The current LANGID of the default language for the system.
754 */
756{
758}
759
760
761/***********************************************************************
762 * GetUserDefaultLCID (KERNEL32.@)
763 *
764 * Get the default locale Id for the current user.
765 *
766 * PARAMS
767 * None.
768 *
769 * RETURNS
770 * The current LCID of the default locale for the current user.
771 */
773{
774 LCID lcid;
776 return lcid;
777}
778
779
780/***********************************************************************
781 * GetSystemDefaultLCID (KERNEL32.@)
782 *
783 * Get the default locale Id for the system.
784 *
785 * PARAMS
786 * None.
787 *
788 * RETURNS
789 * The current LCID of the default locale for the system.
790 */
792{
793 LCID lcid;
795 return lcid;
796}
797
798
799/***********************************************************************
800 * GetUserDefaultUILanguage (KERNEL32.@)
801 *
802 * Get the default user interface language Id for the current user.
803 *
804 * PARAMS
805 * None.
806 *
807 * RETURNS
808 * The current LANGID of the default UI language for the current user.
809 */
811{
812 LANGID lang;
814 return lang;
815}
816
817
818/***********************************************************************
819 * GetSystemDefaultUILanguage (KERNEL32.@)
820 *
821 * Get the default user interface language Id for the system.
822 *
823 * PARAMS
824 * None.
825 *
826 * RETURNS
827 * The current LANGID of the default UI language for the system. This is
828 * typically the same language used during the installation process.
829 */
831{
832 LANGID lang;
834 return lang;
835}
836
837#if (WINVER >= 0x0600)
838/***********************************************************************
839 * LocaleNameToLCID (KERNEL32.@)
840 */
841LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags )
842{
844 static int once;
845
846 if (flags && !once++)
847 FIXME( "unsupported flags %x\n", flags );
848
849 if (name == LOCALE_NAME_USER_DEFAULT)
850 return GetUserDefaultLCID();
851
852 /* string parsing */
853 parse_locale_name( name, &locale_name );
854
855 TRACE( "found lcid %x for %s, matches %d\n",
857
858 if (!locale_name.matches)
859 {
861 return 0;
862 }
863
864 if (locale_name.matches == 1)
865 WARN( "locale %s not recognized, defaulting to %s\n",
867
868 return locale_name.lcid;
869}
870
871
872/***********************************************************************
873 * LCIDToLocaleName (KERNEL32.@)
874 */
875INT WINAPI LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags )
876{
877 static int once;
878 if (flags && !once++) FIXME( "unsupported flags %x\n", flags );
879
881}
882#endif
883
884/******************************************************************************
885 * get_registry_locale_info
886 *
887 * Retrieve user-modified locale info from the registry.
888 * Return length, 0 on error, -1 if not found.
889 */
891{
892 DWORD size;
893 INT ret;
894 HANDLE hkey;
898 static const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
899
901
903 {
904 if (!(hkey = create_registry_key()))
905 {
907 return -1;
908 }
909
911 size = info_size + len * sizeof(WCHAR);
912
913 if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
914 {
915 NtClose( hkey );
918 return 0;
919 }
920
922
923 /* try again with a bigger buffer when we have to return the correct size */
924 if (status == STATUS_BUFFER_OVERFLOW && !buffer && size > info_size)
925 {
927 if ((new_info = HeapReAlloc( GetProcessHeap(), 0, info, size )))
928 {
929 info = new_info;
931 }
932 }
933
934 NtClose( hkey );
935
936 if (!status)
937 {
938 INT length = (size - info_size) / sizeof(WCHAR);
939 LPWSTR cached_value;
940
941 if (!length || ((WCHAR *)&info->Data)[length-1])
942 length++;
943
944 cached_value = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) );
945
946 if (!cached_value)
947 {
951 return 0;
952 }
953
954 memcpy( cached_value, info->Data, (length-1) * sizeof(WCHAR) );
955 cached_value[length-1] = 0;
957 registry_value->cached_value = cached_value;
958 }
959 else
960 {
962 {
963 ret = (size - info_size) / sizeof(WCHAR);
964 }
966 {
967 ret = -1;
968 }
969 else
970 {
972 ret = 0;
973 }
976 return ret;
977 }
978 }
979
981
982 if (buffer)
983 {
984 if (ret > len)
985 {
987 ret = 0;
988 }
989 else
990 {
992 }
993 }
994
996
997 return ret;
998}
999
1000
1001/******************************************************************************
1002 * GetLocaleInfoA (KERNEL32.@)
1003 *
1004 * Get information about an aspect of a locale.
1005 *
1006 * PARAMS
1007 * lcid [I] LCID of the locale
1008 * lctype [I] LCTYPE_ flags from "winnls.h"
1009 * buffer [O] Destination for the information
1010 * len [I] Length of buffer in characters
1011 *
1012 * RETURNS
1013 * Success: The size of the data requested. If buffer is non-NULL, it is filled
1014 * with the information.
1015 * Failure: 0. Use GetLastError() to determine the cause.
1016 *
1017 * NOTES
1018 * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
1019 * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE,
1020 * which is a bit string.
1021 */
1023{
1024 WCHAR *bufferW;
1025 INT lenW, ret;
1026
1027 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len );
1028
1029 if (len < 0 || (len && !buffer))
1030 {
1032 return 0;
1033 }
1034 if (((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_SSHORTTIME) ||
1036 {
1038 return 0;
1039 }
1040
1041 if (!len) buffer = NULL;
1042
1043 if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0;
1044
1045 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
1046 {
1048 return 0;
1049 }
1050 if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW )))
1051 {
1052 if ((lctype & LOCALE_RETURN_NUMBER) ||
1054 {
1055 /* it's not an ASCII string, just bytes */
1056 ret *= sizeof(WCHAR);
1057 if (buffer)
1058 {
1059 if (ret <= len) memcpy( buffer, bufferW, ret );
1060 else
1061 {
1063 ret = 0;
1064 }
1065 }
1066 }
1067 else
1068 {
1070 if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
1071 ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL );
1072 }
1073 }
1074 HeapFree( GetProcessHeap(), 0, bufferW );
1075 return ret;
1076}
1077
1079{
1080 return lctype == LOCALE_ILANGUAGE || lctype == LOCALE_IDEFAULTLANGUAGE ? 16 : 10;
1081}
1082
1083/******************************************************************************
1084 * get_locale_registry_value
1085 *
1086 * Gets the registry value name and cache for a given lctype.
1087 */
1089{
1090 int i;
1091 for (i=0; i < sizeof(registry_values)/sizeof(registry_values[0]); i++)
1093 return &registry_values[i];
1094 return NULL;
1095}
1096
1097/******************************************************************************
1098 * GetLocaleInfoW (KERNEL32.@)
1099 *
1100 * See GetLocaleInfoA.
1101 */
1103{
1104 LANGID lang_id;
1105 HRSRC hrsrc;
1106 HGLOBAL hmem;
1107 LPCWSTR lpType, lpName;
1108 INT ret;
1109 UINT lcflags;
1110 const WCHAR *p;
1111 unsigned int i;
1112
1113 if (len < 0 || (len && !buffer))
1114 {
1116 return 0;
1117 }
1120 {
1122 return 0;
1123 }
1124
1125 if (!len) buffer = NULL;
1126
1127 lcid = convert_default_lcid( lcid, lctype );
1128
1130 lctype &= 0xffff;
1131
1132 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len );
1133
1134 /* first check for overrides in the registry */
1135
1136 if (!(lcflags & LOCALE_NOUSEROVERRIDE) &&
1138 {
1140
1141 if (value)
1142 {
1143 if (lcflags & LOCALE_RETURN_NUMBER)
1144 {
1145 WCHAR tmp[16];
1146 ret = get_registry_locale_info( value, tmp, sizeof(tmp)/sizeof(WCHAR) );
1147 if (ret > 0)
1148 {
1149 WCHAR *end;
1151 if (*end) /* invalid number */
1152 {
1154 return 0;
1155 }
1156 ret = sizeof(UINT)/sizeof(WCHAR);
1157 if (!buffer) return ret;
1158 if (ret > len)
1159 {
1161 return 0;
1162 }
1163 memcpy( buffer, &number, sizeof(number) );
1164 }
1165 }
1167
1168 if (ret != -1) return ret;
1169 }
1170 }
1171
1172 /* now load it from kernel resources */
1173
1174 lang_id = LANGIDFROMLCID( lcid );
1175
1176 /* replace SUBLANG_NEUTRAL by SUBLANG_DEFAULT */
1177 if (SUBLANGID(lang_id) == SUBLANG_NEUTRAL)
1178 lang_id = MAKELANGID(PRIMARYLANGID(lang_id), SUBLANG_DEFAULT);
1179
1181 {
1182 lpType = MAKEINTRESOURCEW(RT_STRING);
1184 }
1185 else
1186 {
1187 lpType = MAKEINTRESOURCEW(RT_RCDATA);
1189 }
1190
1191 if (!(hrsrc = FindResourceExW( kernel32_handle, lpType, lpName, lang_id )))
1192 {
1193 SetLastError( ERROR_INVALID_FLAGS ); /* no such lctype */
1194 return 0;
1195 }
1196 if (!(hmem = LoadResource( kernel32_handle, hrsrc )))
1197 return 0;
1198
1199 p = LockResource( hmem );
1201 {
1202 for (i = 0; i < (lctype & 0x0f); i++) p += *p + 1;
1203 }
1204
1205 if (lcflags & LOCALE_RETURN_NUMBER) ret = sizeof(UINT)/sizeof(WCHAR);
1206 else if (is_genitive_name_supported( lctype ) && *p)
1207 {
1208 /* genitive form's stored after a null separator from a nominative */
1209 for (i = 1; i <= *p; i++) if (!p[i]) break;
1210
1211 if (i <= *p && (lcflags & LOCALE_RETURN_GENITIVE_NAMES))
1212 {
1213 ret = *p - i + 1;
1214 p += i;
1215 }
1216 else ret = i;
1217 }
1218 else if (lctype != LOCALE_FONTSIGNATURE)
1219 ret = *p + 1;
1220 else
1221 ret = SizeofResource(kernel32_handle, hrsrc) / sizeof(WCHAR);
1222
1223 if (!buffer) return ret;
1224
1225 if (ret > len)
1226 {
1228 return 0;
1229 }
1230
1231 if (lcflags & LOCALE_RETURN_NUMBER)
1232 {
1233 UINT number;
1234 WCHAR *end, *tmp = HeapAlloc( GetProcessHeap(), 0, (*p + 1) * sizeof(WCHAR) );
1235 if (!tmp) return 0;
1236 memcpy( tmp, p + 1, *p * sizeof(WCHAR) );
1237 tmp[*p] = 0;
1239 if (!*end)
1240 memcpy( buffer, &number, sizeof(number) );
1241 else /* invalid number */
1242 {
1244 ret = 0;
1245 }
1246 HeapFree( GetProcessHeap(), 0, tmp );
1247
1248 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning number %d\n",
1249 lcid, lctype, buffer, len, number );
1250 }
1251 else
1252 {
1253 if (lctype != LOCALE_FONTSIGNATURE) p++;
1254 memcpy( buffer, p, ret * sizeof(WCHAR) );
1255 if (lctype != LOCALE_FONTSIGNATURE) buffer[ret-1] = 0;
1256
1257 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning %d %s\n",
1258 lcid, lctype, buffer, len, ret, debugstr_w(buffer) );
1259 }
1260 return ret;
1261}
1262
1263#if (WINVER >= 0x0600)
1265int
1266WINAPI
1267GetLocaleInfoEx(
1268 _In_opt_ LPCWSTR lpLocaleName,
1269 _In_ LCTYPE LCType,
1270 _Out_writes_opt_(cchData) LPWSTR lpLCData,
1271 _In_ int cchData)
1272{
1273 TRACE( "GetLocaleInfoEx not implemented (lcid=%s,lctype=0x%x,%s,%d)\n", debugstr_w(lpLocaleName), LCType, debugstr_w(lpLCData), cchData );
1274 return 0;
1275}
1276
1277BOOL
1278WINAPI
1279IsValidLocaleName(
1280 LPCWSTR lpLocaleName
1281)
1282{
1283 TRACE( "IsValidLocaleName not implemented (lpLocaleName=%s)\n", debugstr_w(lpLocaleName));
1284 return TRUE;
1285}
1286
1287INT
1288WINAPI
1289GetUserDefaultLocaleName(
1290 LPWSTR lpLocaleName,
1291 INT cchLocaleName
1292)
1293{
1294 TRACE( "GetUserDefaultLocaleName not implemented (lpLocaleName=%s, cchLocaleName=%d)\n", debugstr_w(lpLocaleName), cchLocaleName);
1295 return 0;
1296}
1297#endif
1298
1299/******************************************************************************
1300 * SetLocaleInfoA [KERNEL32.@]
1301 *
1302 * Set information about an aspect of a locale.
1303 *
1304 * PARAMS
1305 * lcid [I] LCID of the locale
1306 * lctype [I] LCTYPE_ flags from "winnls.h"
1307 * data [I] Information to set
1308 *
1309 * RETURNS
1310 * Success: TRUE. The information given will be returned by GetLocaleInfoA()
1311 * whenever it is called without LOCALE_NOUSEROVERRIDE.
1312 * Failure: FALSE. Use GetLastError() to determine the cause.
1313 *
1314 * NOTES
1315 * - Values are only be set for the current user locale; the system locale
1316 * settings cannot be changed.
1317 * - Any settings changed by this call are lost when the locale is changed by
1318 * the control panel (in Wine, this happens every time you change LANG).
1319 * - The native implementation of this function does not check that lcid matches
1320 * the current user locale, and simply sets the new values. Wine warns you in
1321 * this case, but behaves the same.
1322 */
1324{
1326 WCHAR *strW;
1327 DWORD len;
1328 BOOL ret;
1329
1331
1332 if (!data)
1333 {
1335 return FALSE;
1336 }
1337 len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 );
1338 if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1339 {
1341 return FALSE;
1342 }
1344 ret = SetLocaleInfoW( lcid, lctype, strW );
1345 HeapFree( GetProcessHeap(), 0, strW );
1346 return ret;
1347}
1348
1349
1350/******************************************************************************
1351 * SetLocaleInfoW (KERNEL32.@)
1352 *
1353 * See SetLocaleInfoA.
1354 */
1356{
1357 struct registry_value *value;
1358 static const WCHAR intlW[] = {'i','n','t','l',0 };
1361 HANDLE hkey;
1362
1363 lctype &= 0xffff;
1365
1366 if (!data || !value)
1367 {
1369 return FALSE;
1370 }
1371
1373 {
1375 return FALSE;
1376 }
1377
1378 TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value->name), debugstr_w(data) );
1379
1380 /* FIXME: should check that data to set is sane */
1381
1382 /* FIXME: profile functions should map to registry */
1383 WriteProfileStringW( intlW, value->name, data );
1384
1385 if (!(hkey = create_registry_key())) return FALSE;
1387 status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, (PVOID)data, (strlenW(data)+1)*sizeof(WCHAR) );
1388
1390 HeapFree( GetProcessHeap(), 0, value->cached_value );
1391 value->cached_value = NULL;
1393
1395 {
1396 /* Set I-value from S value */
1397 WCHAR *lpD, *lpM, *lpY;
1398 WCHAR szBuff[2];
1399
1400 lpD = strrchrW(data, 'd');
1401 lpM = strrchrW(data, 'M');
1402 lpY = strrchrW(data, 'y');
1403
1404 if (lpD <= lpM)
1405 {
1406 szBuff[0] = '1'; /* D-M-Y */
1407 }
1408 else
1409 {
1410 if (lpY <= lpM)
1411 szBuff[0] = '2'; /* Y-M-D */
1412 else
1413 szBuff[0] = '0'; /* M-D-Y */
1414 }
1415
1416 szBuff[1] = '\0';
1417
1420 else
1422
1424
1425 WriteProfileStringW( intlW, value->name, szBuff );
1426
1428 status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) );
1429
1431 HeapFree( GetProcessHeap(), 0, value->cached_value );
1432 value->cached_value = NULL;
1434 }
1435
1436 NtClose( hkey );
1437
1439 return !status;
1440}
1441
1442/***********************************************************************
1443 * GetThreadLocale (KERNEL32.@)
1444 *
1445 * Get the current threads locale.
1446 *
1447 * PARAMS
1448 * None.
1449 *
1450 * RETURNS
1451 * The LCID currently associated with the calling thread.
1452 */
1454{
1455 LCID ret = NtCurrentTeb()->CurrentLocale;
1456 if (!ret) NtCurrentTeb()->CurrentLocale = ret = GetUserDefaultLCID();
1457 return ret;
1458}
1459
1460/**********************************************************************
1461 * SetThreadLocale (KERNEL32.@)
1462 *
1463 * Set the current threads locale.
1464 *
1465 * PARAMS
1466 * lcid [I] LCID of the locale to set
1467 *
1468 * RETURNS
1469 * Success: TRUE. The threads locale is set to lcid.
1470 * Failure: FALSE. Use GetLastError() to determine the cause.
1471 */
1473{
1474 TRACE("(0x%04X)\n", lcid);
1475
1476 lcid = ConvertDefaultLocale(lcid);
1477
1478 if (lcid != GetThreadLocale())
1479 {
1480 if (!IsValidLocale(lcid, LCID_SUPPORTED))
1481 {
1483 return FALSE;
1484 }
1485
1486 NtCurrentTeb()->CurrentLocale = lcid;
1487 }
1488 return TRUE;
1489}
1490
1491/******************************************************************************
1492 * ConvertDefaultLocale (KERNEL32.@)
1493 *
1494 * Convert a default locale identifier into a real identifier.
1495 *
1496 * PARAMS
1497 * lcid [I] LCID identifier of the locale to convert
1498 *
1499 * RETURNS
1500 * lcid unchanged, if not a default locale or its sublanguage is
1501 * not SUBLANG_NEUTRAL.
1502 * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT.
1503 * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL.
1504 * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT.
1505 */
1507{
1508 LANGID langid;
1509
1510 switch (lcid)
1511 {
1512 case LOCALE_INVARIANT:
1513 /* keep as-is */
1514 break;
1516 lcid = GetSystemDefaultLCID();
1517 break;
1519 case LOCALE_NEUTRAL:
1520 lcid = GetUserDefaultLCID();
1521 break;
1522 default:
1523 /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
1524 langid = LANGIDFROMLCID(lcid);
1526 {
1528 lcid = MAKELCID(langid, SORTIDFROMLCID(lcid));
1529 }
1530 }
1531 return lcid;
1532}
1533
1534
1535/******************************************************************************
1536 * IsValidLocale (KERNEL32.@)
1537 *
1538 * Determine if a locale is valid.
1539 *
1540 * PARAMS
1541 * lcid [I] LCID of the locale to check
1542 * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system
1543 *
1544 * RETURNS
1545 * TRUE, if lcid is valid,
1546 * FALSE, otherwise.
1547 *
1548 * NOTES
1549 * Wine does not currently make the distinction between supported and installed. All
1550 * languages supported are installed by default.
1551 */
1553{
1554 /* check if language is registered in the kernel32 resources */
1557}
1558
1559
1562{
1563 LOCALE_ENUMPROCA lpfnLocaleEnum = (LOCALE_ENUMPROCA)lParam;
1564 char buf[20];
1565
1566 sprintf(buf, "%08x", (UINT)LangID);
1567 return lpfnLocaleEnum( buf );
1568}
1569
1572{
1573 static const WCHAR formatW[] = {'%','0','8','x',0};
1574 LOCALE_ENUMPROCW lpfnLocaleEnum = (LOCALE_ENUMPROCW)lParam;
1575 WCHAR buf[20];
1576 sprintfW( buf, formatW, (UINT)LangID );
1577 return lpfnLocaleEnum( buf );
1578}
1579
1580/******************************************************************************
1581 * EnumSystemLocalesA (KERNEL32.@)
1582 *
1583 * Call a users function for each locale available on the system.
1584 *
1585 * PARAMS
1586 * lpfnLocaleEnum [I] Callback function to call for each locale
1587 * dwFlags [I] LOCALE_SUPPORTED=All supported, LOCALE_INSTALLED=Installed only
1588 *
1589 * RETURNS
1590 * Success: TRUE.
1591 * Failure: FALSE. Use GetLastError() to determine the cause.
1592 */
1594{
1595 TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags);
1598 (LONG_PTR)lpfnLocaleEnum);
1599 return TRUE;
1600}
1601
1602
1603/******************************************************************************
1604 * EnumSystemLocalesW (KERNEL32.@)
1605 *
1606 * See EnumSystemLocalesA.
1607 */
1609{
1610 TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags);
1613 (LONG_PTR)lpfnLocaleEnum);
1614 return TRUE;
1615}
1616
1617
1619{
1623};
1624
1627{
1629 WCHAR buffer[256];
1630 DWORD neutral;
1631 unsigned int flags;
1632
1636 LOCALE_INEUTRAL | LOCALE_NOUSEROVERRIDE | LOCALE_RETURN_NUMBER,
1637 (LPWSTR)&neutral, sizeof(neutral) / sizeof(WCHAR) ))
1638 neutral = 0;
1641 if (data->flags && !(data->flags & flags)) return TRUE;
1642 return data->proc( buffer, flags, data->lparam );
1643}
1644
1645/******************************************************************************
1646 * EnumSystemLocalesEx (KERNEL32.@)
1647 */
1649{
1651
1652 if (reserved)
1653 {
1655 return FALSE;
1656 }
1657 data.proc = proc;
1658 data.flags = flags;
1659 data.lparam = lparam;
1663 return TRUE;
1664}
1665
1666
1667/***********************************************************************
1668 * VerLanguageNameA (KERNEL32.@)
1669 *
1670 * Get the name of a language.
1671 *
1672 * PARAMS
1673 * wLang [I] LANGID of the language
1674 * szLang [O] Destination for the language name
1675 *
1676 * RETURNS
1677 * Success: The size of the language name. If szLang is non-NULL, it is filled
1678 * with the name.
1679 * Failure: 0. Use GetLastError() to determine the cause.
1680 *
1681 */
1683{
1684 return GetLocaleInfoA( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
1685}
1686
1687
1688/***********************************************************************
1689 * VerLanguageNameW (KERNEL32.@)
1690 *
1691 * See VerLanguageNameA.
1692 */
1694{
1695 return GetLocaleInfoW( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
1696}
1697
1698/******************************************************************************
1699 * GetStringTypeW (KERNEL32.@)
1700 *
1701 * See GetStringTypeA.
1702 */
1704{
1705 static const unsigned char type2_map[16] =
1706 {
1707 C2_NOTAPPLICABLE, /* unassigned */
1708 C2_LEFTTORIGHT, /* L */
1709 C2_RIGHTTOLEFT, /* R */
1710 C2_EUROPENUMBER, /* EN */
1711 C2_EUROPESEPARATOR, /* ES */
1712 C2_EUROPETERMINATOR, /* ET */
1713 C2_ARABICNUMBER, /* AN */
1714 C2_COMMONSEPARATOR, /* CS */
1715 C2_BLOCKSEPARATOR, /* B */
1716 C2_SEGMENTSEPARATOR, /* S */
1717 C2_WHITESPACE, /* WS */
1718 C2_OTHERNEUTRAL, /* ON */
1719 C2_RIGHTTOLEFT, /* AL */
1720 C2_NOTAPPLICABLE, /* NSM */
1721 C2_NOTAPPLICABLE, /* BN */
1722 C2_OTHERNEUTRAL /* LRE, LRO, RLE, RLO, PDF */
1723 };
1724
1725 if (!src)
1726 {
1728 return FALSE;
1729 }
1730
1731 if (count == -1) count = strlenW(src) + 1;
1732 switch(type)
1733 {
1734 case CT_CTYPE1:
1735 while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff;
1736 break;
1737 case CT_CTYPE2:
1738 while (count--) *chartype++ = type2_map[get_char_typeW( *src++ ) >> 12];
1739 break;
1740 case CT_CTYPE3:
1741 {
1742 WARN("CT_CTYPE3: semi-stub.\n");
1743 while (count--)
1744 {
1745 int c = *src;
1746 WORD type1, type3 = 0; /* C3_NOTAPPLICABLE */
1747
1748 type1 = get_char_typeW( *src++ ) & 0xfff;
1749 /* try to construct type3 from type1 */
1750 if(type1 & C1_SPACE) type3 |= C3_SYMBOL;
1751 if(type1 & C1_ALPHA) type3 |= C3_ALPHA;
1752 if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA;
1753 if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA;
1754 if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH;
1755 if (c == 0x0640) type3 |= C3_KASHIDA;
1756 if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL;
1757
1758 if ((c>=0xD800)&&(c<=0xDBFF)) type3 |= C3_HIGHSURROGATE;
1759 if ((c>=0xDC00)&&(c<=0xDFFF)) type3 |= C3_LOWSURROGATE;
1760
1761 if ((c>=0xFF00)&&(c<=0xFF60)) type3 |= C3_FULLWIDTH;
1762 if ((c>=0xFF00)&&(c<=0xFF20)) type3 |= C3_SYMBOL;
1763 if ((c>=0xFF3B)&&(c<=0xFF40)) type3 |= C3_SYMBOL;
1764 if ((c>=0xFF5B)&&(c<=0xFF60)) type3 |= C3_SYMBOL;
1765 if ((c>=0xFF21)&&(c<=0xFF3A)) type3 |= C3_ALPHA;
1766 if ((c>=0xFF41)&&(c<=0xFF5A)) type3 |= C3_ALPHA;
1767 if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_FULLWIDTH;
1768 if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_SYMBOL;
1769
1770 if ((c>=0xFF61)&&(c<=0xFFDC)) type3 |= C3_HALFWIDTH;
1771 if ((c>=0xFF61)&&(c<=0xFF64)) type3 |= C3_SYMBOL;
1772 if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_KATAKANA;
1773 if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_ALPHA;
1774 if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_HALFWIDTH;
1775 if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_SYMBOL;
1776 *chartype++ = type3;
1777 }
1778 break;
1779 }
1780 default:
1782 return FALSE;
1783 }
1784 return TRUE;
1785}
1786
1787
1788/******************************************************************************
1789 * GetStringTypeExW (KERNEL32.@)
1790 *
1791 * See GetStringTypeExA.
1792 */
1794{
1795 /* locale is ignored for Unicode */
1796 return GetStringTypeW( type, src, count, chartype );
1797}
1798
1799
1800/******************************************************************************
1801 * GetStringTypeA (KERNEL32.@)
1802 *
1803 * Get characteristics of the characters making up a string.
1804 *
1805 * PARAMS
1806 * locale [I] Locale Id for the string
1807 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
1808 * src [I] String to analyse
1809 * count [I] Length of src in chars, or -1 if src is NUL terminated
1810 * chartype [O] Destination for the calculated characteristics
1811 *
1812 * RETURNS
1813 * Success: TRUE. chartype is filled with the requested characteristics of each char
1814 * in src.
1815 * Failure: FALSE. Use GetLastError() to determine the cause.
1816 */
1818{
1819 UINT cp;
1820 INT countW;
1821 LPWSTR srcW;
1822 BOOL ret = FALSE;
1823
1824 if(count == -1) count = strlen(src) + 1;
1825
1826 if (!(cp = get_lcid_codepage( locale )))
1827 {
1828 FIXME("For locale %04x using current ANSI code page\n", locale);
1829 cp = GetACP();
1830 }
1831
1832 countW = MultiByteToWideChar(cp, 0, src, count, NULL, 0);
1833 if((srcW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
1834 {
1835 MultiByteToWideChar(cp, 0, src, count, srcW, countW);
1836 /*
1837 * NOTE: the target buffer has 1 word for each CHARACTER in the source
1838 * string, with multibyte characters there maybe be more bytes in count
1839 * than character space in the buffer!
1840 */
1841 ret = GetStringTypeW(type, srcW, countW, chartype);
1842 HeapFree(GetProcessHeap(), 0, srcW);
1843 }
1844 return ret;
1845}
1846
1847/******************************************************************************
1848 * GetStringTypeExA (KERNEL32.@)
1849 *
1850 * Get characteristics of the characters making up a string.
1851 *
1852 * PARAMS
1853 * locale [I] Locale Id for the string
1854 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
1855 * src [I] String to analyse
1856 * count [I] Length of src in chars, or -1 if src is NUL terminated
1857 * chartype [O] Destination for the calculated characteristics
1858 *
1859 * RETURNS
1860 * Success: TRUE. chartype is filled with the requested characteristics of each char
1861 * in src.
1862 * Failure: FALSE. Use GetLastError() to determine the cause.
1863 */
1865{
1866 return GetStringTypeA(locale, type, src, count, chartype);
1867}
1868
1869/*************************************************************************
1870 * LCMapStringEx (KERNEL32.@)
1871 *
1872 * Map characters in a locale sensitive string.
1873 *
1874 * PARAMS
1875 * name [I] Locale name for the conversion.
1876 * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h")
1877 * src [I] String to map
1878 * srclen [I] Length of src in chars, or -1 if src is NUL terminated
1879 * dst [O] Destination for mapped string
1880 * dstlen [I] Length of dst in characters
1881 * version [I] reserved, must be NULL
1882 * reserved [I] reserved, must be NULL
1883 * lparam [I] reserved, must be 0
1884 *
1885 * RETURNS
1886 * Success: The length of the mapped string in dst, including the NUL terminator.
1887 * Failure: 0. Use GetLastError() to determine the cause.
1888 */
1891{
1892 LPWSTR dst_ptr;
1893
1894 if (version) FIXME("unsupported version structure %p\n", version);
1895 if (reserved) FIXME("unsupported reserved pointer %p\n", reserved);
1896 if (lparam)
1897 {
1898 static int once;
1899 if (!once++) FIXME("unsupported lparam %lx\n", lparam);
1900 }
1901
1902 if (!src || !srclen || dstlen < 0)
1903 {
1905 return 0;
1906 }
1907
1908 /* mutually exclusive flags */
1913 {
1915 return 0;
1916 }
1917
1918 if (!dstlen) dst = NULL;
1919
1920 if (flags & LCMAP_SORTKEY)
1921 {
1922 INT ret;
1923 if (src == dst)
1924 {
1926 return 0;
1927 }
1928
1929 if (srclen < 0) srclen = strlenW(src);
1930
1931 TRACE("(%s,0x%08x,%s,%d,%p,%d)\n",
1933
1934 ret = wine_get_sortkey(flags, src, srclen, (char *)dst, dstlen);
1935 if (ret == 0)
1937 else
1938 ret++;
1939 return ret;
1940 }
1941
1942 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1943 if (flags & SORT_STRINGSORT)
1944 {
1946 return 0;
1947 }
1948
1949 if (srclen < 0) srclen = strlenW(src) + 1;
1950
1951 TRACE("(%s,0x%08x,%s,%d,%p,%d)\n",
1953
1954 if (!dst) /* return required string length */
1955 {
1956 INT len;
1957
1958 for (len = 0; srclen; src++, srclen--)
1959 {
1960 WCHAR wch = *src;
1961 /* tests show that win2k just ignores NORM_IGNORENONSPACE,
1962 * and skips white space and punctuation characters for
1963 * NORM_IGNORESYMBOLS.
1964 */
1966 continue;
1967 len++;
1968 }
1969 return len;
1970 }
1971
1972 if (flags & LCMAP_UPPERCASE)
1973 {
1974 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
1975 {
1976 WCHAR wch = *src;
1978 continue;
1979 *dst_ptr++ = toupperW(wch);
1980 dstlen--;
1981 }
1982 }
1983 else if (flags & LCMAP_LOWERCASE)
1984 {
1985 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
1986 {
1987 WCHAR wch = *src;
1989 continue;
1990 *dst_ptr++ = tolowerW(wch);
1991 dstlen--;
1992 }
1993 }
1994 else
1995 {
1996 if (src == dst)
1997 {
1999 return 0;
2000 }
2001 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
2002 {
2003 WCHAR wch = *src;
2005 continue;
2006 *dst_ptr++ = wch;
2007 dstlen--;
2008 }
2009 }
2010
2011#ifdef __REACTOS__
2012 if (flags & LCMAP_KATAKANA)
2013 {
2014 INT convlen = dst_ptr - dst;
2015 for (dst_ptr = dst; convlen; --convlen, ++dst_ptr)
2016 {
2017 /*
2018 * U+3041 ... U+3093: Hiragana
2019 * U+3095: Hiragana Letter Small KA
2020 * U+309D: Hiragana Iteration Mark
2021 * U+309E: Hiragana Voiced Iteration Mark
2022 */
2023 WCHAR wch = *dst_ptr;
2024 if ((0x3041 <= wch && wch <= 0x3093) || wch == 0x3095 || wch == 0x309D || wch == 0x309E)
2025 *dst_ptr = wch + 0x60; /* Hiragana to Katanaka */
2026 }
2027 }
2028 else if (flags & LCMAP_HIRAGANA)
2029 {
2030 INT convlen = dst_ptr - dst;
2031 for (dst_ptr = dst; convlen; --convlen, ++dst_ptr)
2032 {
2033 /*
2034 * U+30A1 ... U+30F3: Katakana
2035 * U+30F5: Katakana Letter Small KA
2036 * U+30FD: Katakana Iteration Mark
2037 * U+30FE: Katakana Voiced Iteration Mark
2038 */
2039 WCHAR wch = *dst_ptr;
2040 if ((0x30A1 <= wch && wch <= 0x30F3) || wch == 0x30F5 || wch == 0x30FD || wch == 0x30FE)
2041 *dst_ptr = wch - 0x60; /* Katanaka to Hiragana */
2042 }
2043 }
2044#endif
2045
2046 if (srclen)
2047 {
2049 return 0;
2050 }
2051
2052 return dst_ptr - dst;
2053}
2054
2055/*************************************************************************
2056 * LCMapStringW (KERNEL32.@)
2057 *
2058 * See LCMapStringA.
2059 */
2062{
2063 TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n",
2065
2066 return LCMapStringEx(NULL, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
2067}
2068
2069/*************************************************************************
2070 * LCMapStringA (KERNEL32.@)
2071 *
2072 * Map characters in a locale sensitive string.
2073 *
2074 * PARAMS
2075 * lcid [I] LCID for the conversion.
2076 * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h").
2077 * src [I] String to map
2078 * srclen [I] Length of src in chars, or -1 if src is NUL terminated
2079 * dst [O] Destination for mapped string
2080 * dstlen [I] Length of dst in characters
2081 *
2082 * RETURNS
2083 * Success: The length of the mapped string in dst, including the NUL terminator.
2084 * Failure: 0. Use GetLastError() to determine the cause.
2085 */
2088{
2089 WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
2090 LPWSTR srcW, dstW;
2091 INT ret = 0, srclenW, dstlenW;
2092 UINT locale_cp = CP_ACP;
2093
2094 if (!src || !srclen || dstlen < 0)
2095 {
2097 return 0;
2098 }
2099
2100 if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
2101
2102 srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
2103 if (srclenW)
2104 srcW = bufW;
2105 else
2106 {
2107 srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, NULL, 0);
2108 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
2109 if (!srcW)
2110 {
2112 return 0;
2113 }
2114 MultiByteToWideChar(locale_cp, 0, src, srclen, srcW, srclenW);
2115 }
2116
2117 if (flags & LCMAP_SORTKEY)
2118 {
2119 if (src == dst)
2120 {
2122 goto map_string_exit;
2123 }
2124 ret = wine_get_sortkey(flags, srcW, srclenW, dst, dstlen);
2125 if (ret == 0)
2127 else
2128 ret++;
2129 goto map_string_exit;
2130 }
2131
2132 if (flags & SORT_STRINGSORT)
2133 {
2135 goto map_string_exit;
2136 }
2137
2138 dstlenW = LCMapStringEx(NULL, flags, srcW, srclenW, NULL, 0, NULL, NULL, 0);
2139 if (!dstlenW)
2140 goto map_string_exit;
2141
2142 dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
2143 if (!dstW)
2144 {
2146 goto map_string_exit;
2147 }
2148
2149 LCMapStringEx(NULL, flags, srcW, srclenW, dstW, dstlenW, NULL, NULL, 0);
2150 ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL);
2151 HeapFree(GetProcessHeap(), 0, dstW);
2152
2153map_string_exit:
2154 if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW);
2155 return ret;
2156}
2157
2158/*************************************************************************
2159 * FoldStringA (KERNEL32.@)
2160 *
2161 * Map characters in a string.
2162 *
2163 * PARAMS
2164 * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
2165 * src [I] String to map
2166 * srclen [I] Length of src, or -1 if src is NUL terminated
2167 * dst [O] Destination for mapped string
2168 * dstlen [I] Length of dst, or 0 to find the required length for the mapped string
2169 *
2170 * RETURNS
2171 * Success: The length of the string written to dst, including the terminating NUL. If
2172 * dstlen is 0, the value returned is the same, but nothing is written to dst,
2173 * and dst may be NULL.
2174 * Failure: 0. Use GetLastError() to determine the cause.
2175 */
2178{
2179 INT ret = 0, srclenW = 0;
2180 WCHAR *srcW = NULL, *dstW = NULL;
2181
2182 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
2183 {
2185 return 0;
2186 }
2187
2189 src, srclen, NULL, 0);
2190 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
2191
2192 if (!srcW)
2193 {
2195 goto FoldStringA_exit;
2196 }
2197
2199 src, srclen, srcW, srclenW);
2200
2201 dwFlags = (dwFlags & ~MAP_PRECOMPOSED) | MAP_FOLDCZONE;
2202
2203 ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0);
2204 if (ret && dstlen)
2205 {
2206 dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
2207
2208 if (!dstW)
2209 {
2211 goto FoldStringA_exit;
2212 }
2213
2214 ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret);
2215 if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
2216 {
2217 ret = 0;
2219 }
2220 }
2221
2222 HeapFree(GetProcessHeap(), 0, dstW);
2223
2224FoldStringA_exit:
2225 HeapFree(GetProcessHeap(), 0, srcW);
2226 return ret;
2227}
2228
2229/*************************************************************************
2230 * FoldStringW (KERNEL32.@)
2231 *
2232 * See FoldStringA.
2233 */
2236{
2237 int ret;
2238
2239 switch (dwFlags & (MAP_COMPOSITE|MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES))
2240 {
2241 case 0:
2242 if (dwFlags)
2243 break;
2244 /* Fall through for dwFlags == 0 */
2246 case MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES:
2247 case MAP_COMPOSITE|MAP_EXPAND_LIGATURES:
2249 return 0;
2250 }
2251
2252 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
2253 {
2255 return 0;
2256 }
2257
2259 if (!ret)
2261 return ret;
2262}
2263
2264/******************************************************************************
2265 * CompareStringEx (KERNEL32.@)
2266 */
2269{
2272 DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
2273 /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
2274 INT ret;
2275 static int once;
2276
2277 if (version) FIXME("unexpected version parameter\n");
2278 if (reserved) FIXME("unexpected reserved value\n");
2279 if (lParam) FIXME("unexpected lParam\n");
2280
2281 if (!str1 || !str2)
2282 {
2284 return 0;
2285 }
2286
2287 if (flags & ~(supported_flags|semistub_flags))
2288 {
2290 return 0;
2291 }
2292
2293 if (flags & semistub_flags)
2294 {
2295 if (!once++)
2296 FIXME("semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags);
2297 }
2298
2299 if (len1 < 0) len1 = strlenW(str1);
2300 if (len2 < 0) len2 = strlenW(str2);
2301
2302 ret = wine_compare_string(flags, str1, len1, str2, len2);
2303
2304 if (ret) /* need to translate result */
2305 return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
2306 return CSTR_EQUAL;
2307}
2308
2309/******************************************************************************
2310 * CompareStringW (KERNEL32.@)
2311 *
2312 * See CompareStringA.
2313 */
2315 LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
2316{
2317 return CompareStringEx(NULL, flags, str1, len1, str2, len2, NULL, NULL, 0);
2318}
2319
2320/******************************************************************************
2321 * CompareStringA (KERNEL32.@)
2322 *
2323 * Compare two locale sensitive strings.
2324 *
2325 * PARAMS
2326 * lcid [I] LCID for the comparison
2327 * flags [I] Flags for the comparison (NORM_ constants from "winnls.h").
2328 * str1 [I] First string to compare
2329 * len1 [I] Length of str1, or -1 if str1 is NUL terminated
2330 * str2 [I] Second string to compare
2331 * len2 [I] Length of str2, or -1 if str2 is NUL terminated
2332 *
2333 * RETURNS
2334 * Success: CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN depending on whether
2335 * str1 is less than, equal to or greater than str2 respectively.
2336 * Failure: FALSE. Use GetLastError() to determine the cause.
2337 */
2339 LPCSTR str1, INT len1, LPCSTR str2, INT len2)
2340{
2341 WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
2342 WCHAR *buf2W = buf1W + 130;
2343 LPWSTR str1W, str2W;
2344 INT len1W = 0, len2W = 0, ret;
2345 UINT locale_cp = CP_ACP;
2346
2347 if (!str1 || !str2)
2348 {
2350 return 0;
2351 }
2352 if (len1 < 0) len1 = strlen(str1);
2353 if (len2 < 0) len2 = strlen(str2);
2354
2355 if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
2356
2357 if (len1)
2358 {
2359 if (len1 <= 130) len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
2360 if (len1W)
2361 str1W = buf1W;
2362 else
2363 {
2364 len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0);
2365 str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
2366 if (!str1W)
2367 {
2369 return 0;
2370 }
2371 MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
2372 }
2373 }
2374 else
2375 {
2376 len1W = 0;
2377 str1W = buf1W;
2378 }
2379
2380 if (len2)
2381 {
2382 if (len2 <= 130) len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
2383 if (len2W)
2384 str2W = buf2W;
2385 else
2386 {
2387 len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0);
2388 str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
2389 if (!str2W)
2390 {
2391 if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
2393 return 0;
2394 }
2395 MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W);
2396 }
2397 }
2398 else
2399 {
2400 len2W = 0;
2401 str2W = buf2W;
2402 }
2403
2404 ret = CompareStringEx(NULL, flags, str1W, len1W, str2W, len2W, NULL, NULL, 0);
2405
2406 if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
2407 if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
2408 return ret;
2409}
2410
2411#ifdef __REACTOS__
2412HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
2413#else
2414static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
2415#endif
2416{
2417 UNICODE_STRING keyName;
2419 HANDLE hkey;
2420
2421 RtlInitUnicodeString( &keyName, szKeyName );
2422#ifdef __REACTOS__
2424#else
2425 InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
2426#endif
2427
2428 if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
2429 hkey = 0;
2430
2431 return hkey;
2432}
2433
2434#ifdef __REACTOS__
2436 LPWSTR szValueName, ULONG valueNameSize,
2437 LPWSTR szValueData, ULONG valueDataSize)
2438#else
2440 LPWSTR szValueName, ULONG valueNameSize,
2441 LPWSTR szValueData, ULONG valueDataSize)
2442#endif
2443{
2444 BYTE buffer[80];
2446 DWORD dwLen;
2447
2449 buffer, sizeof(buffer), &dwLen ) != STATUS_SUCCESS ||
2450 info->NameLength > valueNameSize ||
2451 info->DataLength > valueDataSize)
2452 {
2453 return FALSE;
2454 }
2455
2456 TRACE("info->Name %s info->DataLength %d\n", debugstr_w(info->Name), info->DataLength);
2457
2458 memcpy( szValueName, info->Name, info->NameLength);
2459 szValueName[info->NameLength / sizeof(WCHAR)] = '\0';
2460 memcpy( szValueData, buffer + info->DataOffset, info->DataLength );
2461 szValueData[info->DataLength / sizeof(WCHAR)] = '\0';
2462
2463 TRACE("returning %s %s\n", debugstr_w(szValueName), debugstr_w(szValueData));
2464 return TRUE;
2465}
2466
2467static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
2468{
2469 BYTE buffer[128];
2471 DWORD dwSize = sizeof(buffer);
2472 UNICODE_STRING valueName;
2473
2474 RtlInitUnicodeString( &valueName, szValueName );
2475
2476 TRACE("%p, %s\n", hKey, debugstr_w(szValueName));
2479 info->DataLength == sizeof(DWORD))
2480 {
2481 memcpy(lpVal, info->Data, sizeof(DWORD));
2482 return TRUE;
2483 }
2484
2485 return FALSE;
2486}
2487
2489{
2490 LANGID langId;
2491 LPCWSTR szResourceName = MAKEINTRESOURCEW(((lgrpid + 0x2000) >> 4) + 1);
2492 HRSRC hResource;
2493 BOOL bRet = FALSE;
2494
2495 /* FIXME: Is it correct to use the system default langid? */
2496 langId = GetSystemDefaultLangID();
2497
2498 if (SUBLANGID(langId) == SUBLANG_NEUTRAL)
2499 langId = MAKELANGID( PRIMARYLANGID(langId), SUBLANG_DEFAULT );
2500
2501 hResource = FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, szResourceName, langId );
2502
2503 if (hResource)
2504 {
2505 HGLOBAL hResDir = LoadResource( kernel32_handle, hResource );
2506
2507 if (hResDir)
2508 {
2509 ULONG iResourceIndex = lgrpid & 0xf;
2510 LPCWSTR lpResEntry = LockResource( hResDir );
2511 ULONG i;
2512
2513 for (i = 0; i < iResourceIndex; i++)
2514 lpResEntry += *lpResEntry + 1;
2515
2516 if (*lpResEntry < nameSize)
2517 {
2518 memcpy( szName, lpResEntry + 1, *lpResEntry * sizeof(WCHAR) );
2519 szName[*lpResEntry] = '\0';
2520 bRet = TRUE;
2521 }
2522
2523 }
2524 FreeResource( hResource );
2525 }
2526 return bRet;
2527}
2528
2529/* Callback function ptrs for EnumSystemLanguageGroupsA/W */
2530typedef struct
2531{
2537
2538/* Internal implementation of EnumSystemLanguageGroupsA/W */
2540{
2541 WCHAR szNumber[10], szValue[4];
2542 HANDLE hKey;
2543 BOOL bContinue = TRUE;
2544 ULONG ulIndex = 0;
2545
2546 if (!lpProcs)
2547 {
2549 return FALSE;
2550 }
2551
2552 switch (lpProcs->dwFlags)
2553 {
2554 case 0:
2555 /* Default to LGRPID_INSTALLED */
2556 lpProcs->dwFlags = LGRPID_INSTALLED;
2557 /* Fall through... */
2558 case LGRPID_INSTALLED:
2559 case LGRPID_SUPPORTED:
2560 break;
2561 default:
2563 return FALSE;
2564 }
2565
2567
2568 if (!hKey)
2569 FIXME("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
2570
2571 while (bContinue)
2572 {
2573 if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
2574 szValue, sizeof(szValue) ))
2575 {
2576 BOOL bInstalled = szValue[0] == '1';
2577 LGRPID lgrpid = strtoulW( szNumber, NULL, 16 );
2578
2579 TRACE("grpid %s (%sinstalled)\n", debugstr_w(szNumber),
2580 bInstalled ? "" : "not ");
2581
2582 if (lpProcs->dwFlags == LGRPID_SUPPORTED || bInstalled)
2583 {
2584 WCHAR szGrpName[48];
2585
2586 if (!NLS_GetLanguageGroupName( lgrpid, szGrpName, sizeof(szGrpName) / sizeof(WCHAR) ))
2587 szGrpName[0] = '\0';
2588
2589 if (lpProcs->procW)
2590 bContinue = lpProcs->procW( lgrpid, szNumber, szGrpName, lpProcs->dwFlags,
2591 lpProcs->lParam );
2592 else
2593 {
2594 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
2595 char szGrpNameA[48];
2596
2597 /* FIXME: MSDN doesn't say which code page the W->A translation uses,
2598 * or whether the language names are ever localised. Assume CP_ACP.
2599 */
2600
2601 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
2602 WideCharToMultiByte(CP_ACP, 0, szGrpName, -1, szGrpNameA, sizeof(szGrpNameA), 0, 0);
2603
2604 bContinue = lpProcs->procA( lgrpid, szNumberA, szGrpNameA, lpProcs->dwFlags,
2605 lpProcs->lParam );
2606 }
2607 }
2608
2609 ulIndex++;
2610 }
2611 else
2612 bContinue = FALSE;
2613
2614 if (!bContinue)
2615 break;
2616 }
2617
2618 if (hKey)
2619 NtClose( hKey );
2620
2621 return TRUE;
2622}
2623
2624/******************************************************************************
2625 * EnumSystemLanguageGroupsA (KERNEL32.@)
2626 *
2627 * Call a users function for each language group available on the system.
2628 *
2629 * PARAMS
2630 * pLangGrpEnumProc [I] Callback function to call for each language group
2631 * dwFlags [I] LGRPID_SUPPORTED=All Supported, LGRPID_INSTALLED=Installed only
2632 * lParam [I] User parameter to pass to pLangGrpEnumProc
2633 *
2634 * RETURNS
2635 * Success: TRUE.
2636 * Failure: FALSE. Use GetLastError() to determine the cause.
2637 */
2640{
2642
2643 TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
2644
2645 procs.procA = pLangGrpEnumProc;
2646 procs.procW = NULL;
2647 procs.dwFlags = dwFlags;
2648 procs.lParam = lParam;
2649
2650 return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
2651}
2652
2653/******************************************************************************
2654 * EnumSystemLanguageGroupsW (KERNEL32.@)
2655 *
2656 * See EnumSystemLanguageGroupsA.
2657 */
2660{
2662
2663 TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
2664
2665 procs.procA = NULL;
2666 procs.procW = pLangGrpEnumProc;
2667 procs.dwFlags = dwFlags;
2668 procs.lParam = lParam;
2669
2670 return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
2671}
2672
2673/******************************************************************************
2674 * IsValidLanguageGroup (KERNEL32.@)
2675 *
2676 * Determine if a language group is supported and/or installed.
2677 *
2678 * PARAMS
2679 * lgrpid [I] Language Group Id (LGRPID_ values from "winnls.h")
2680 * dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed
2681 *
2682 * RETURNS
2683 * TRUE, if lgrpid is supported and/or installed, according to dwFlags.
2684 * FALSE otherwise.
2685 */
2687{
2688 static const WCHAR szFormat[] = { '%','x','\0' };
2689 WCHAR szValueName[16], szValue[2];
2690 BOOL bSupported = FALSE, bInstalled = FALSE;
2691 HANDLE hKey;
2692
2693
2694 switch (dwFlags)
2695 {
2696 case LGRPID_INSTALLED:
2697 case LGRPID_SUPPORTED:
2698
2700
2701 sprintfW( szValueName, szFormat, lgrpid );
2702
2703 if (NLS_RegGetDword( hKey, szValueName, (LPDWORD)szValue ))
2704 {
2705 bSupported = TRUE;
2706
2707 if (szValue[0] == '1')
2708 bInstalled = TRUE;
2709 }
2710
2711 if (hKey)
2712 NtClose( hKey );
2713
2714 break;
2715 }
2716
2717 if ((dwFlags == LGRPID_SUPPORTED && bSupported) ||
2718 (dwFlags == LGRPID_INSTALLED && bInstalled))
2719 return TRUE;
2720
2721 return FALSE;
2722}
2723
2724/* Callback function ptrs for EnumLanguageGrouplocalesA/W */
2725typedef struct
2726{
2733
2734/* Internal implementation of EnumLanguageGrouplocalesA/W */
2736{
2737 static const WCHAR szAlternateSortsKeyName[] = {
2738 'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s','\0'
2739 };
2740 WCHAR szNumber[10], szValue[4];
2741 HANDLE hKey;
2742 BOOL bContinue = TRUE, bAlternate = FALSE;
2743 LGRPID lgrpid;
2744 ULONG ulIndex = 1; /* Ignore default entry of 1st key */
2745
2746 if (!lpProcs || !lpProcs->lgrpid || lpProcs->lgrpid > LGRPID_ARMENIAN)
2747 {
2749 return FALSE;
2750 }
2751
2752 if (lpProcs->dwFlags)
2753 {
2755 return FALSE;
2756 }
2757
2759
2760 if (!hKey)
2761 WARN("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
2762
2763 while (bContinue)
2764 {
2765 if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
2766 szValue, sizeof(szValue) ))
2767 {
2768 lgrpid = strtoulW( szValue, NULL, 16 );
2769
2770 TRACE("lcid %s, grpid %d (%smatched)\n", debugstr_w(szNumber),
2771 lgrpid, lgrpid == lpProcs->lgrpid ? "" : "not ");
2772
2773 if (lgrpid == lpProcs->lgrpid)
2774 {
2775 LCID lcid;
2776
2777 lcid = strtoulW( szNumber, NULL, 16 );
2778
2779 /* FIXME: native returns extra text for a few (17/150) locales, e.g:
2780 * '00000437 ;Georgian'
2781 * At present we only pass the LCID string.
2782 */
2783
2784 if (lpProcs->procW)
2785 bContinue = lpProcs->procW( lgrpid, lcid, szNumber, lpProcs->lParam );
2786 else
2787 {
2788 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
2789
2790 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
2791
2792 bContinue = lpProcs->procA( lgrpid, lcid, szNumberA, lpProcs->lParam );
2793 }
2794 }
2795
2796 ulIndex++;
2797 }
2798 else
2799 {
2800 /* Finished enumerating this key */
2801 if (!bAlternate)
2802 {
2803 /* Enumerate alternate sorts also */
2804 hKey = NLS_RegOpenKey( hKey, szAlternateSortsKeyName );
2805 bAlternate = TRUE;
2806 ulIndex = 0;
2807 }
2808 else
2809 bContinue = FALSE; /* Finished both keys */
2810 }
2811
2812 if (!bContinue)
2813 break;
2814 }
2815
2816 if (hKey)
2817 NtClose( hKey );
2818
2819 return TRUE;
2820}
2821
2827
2835};
2836
2837static const struct geoinfo_t geoinfodata[] = {
2838 { 2, {'A','G',0}, {'A','T','G',0}, 10039880, 28 }, /* Antigua and Barbuda */
2839 { 3, {'A','F',0}, {'A','F','G',0}, 47614, 4 }, /* Afghanistan */
2840 { 4, {'D','Z',0}, {'D','Z','A',0}, 42487, 12 }, /* Algeria */
2841 { 5, {'A','Z',0}, {'A','Z','E',0}, 47611, 31 }, /* Azerbaijan */
2842 { 6, {'A','L',0}, {'A','L','B',0}, 47610, 8 }, /* Albania */
2843 { 7, {'A','M',0}, {'A','R','M',0}, 47611, 51 }, /* Armenia */
2844 { 8, {'A','D',0}, {'A','N','D',0}, 47610, 20 }, /* Andorra */
2845 { 9, {'A','O',0}, {'A','G','O',0}, 42484, 24 }, /* Angola */
2846 { 10, {'A','S',0}, {'A','S','M',0}, 26286, 16 }, /* American Samoa */
2847 { 11, {'A','R',0}, {'A','R','G',0}, 31396, 32 }, /* Argentina */
2848 { 12, {'A','U',0}, {'A','U','S',0}, 10210825, 36 }, /* Australia */
2849 { 14, {'A','T',0}, {'A','U','T',0}, 10210824, 40 }, /* Austria */
2850 { 17, {'B','H',0}, {'B','H','R',0}, 47611, 48 }, /* Bahrain */
2851 { 18, {'B','B',0}, {'B','R','B',0}, 10039880, 52 }, /* Barbados */
2852 { 19, {'B','W',0}, {'B','W','A',0}, 10039883, 72 }, /* Botswana */
2853 { 20, {'B','M',0}, {'B','M','U',0}, 23581, 60 }, /* Bermuda */
2854 { 21, {'B','E',0}, {'B','E','L',0}, 10210824, 56 }, /* Belgium */
2855 { 22, {'B','S',0}, {'B','H','S',0}, 10039880, 44 }, /* Bahamas, The */
2856 { 23, {'B','D',0}, {'B','G','D',0}, 47614, 50 }, /* Bangladesh */
2857 { 24, {'B','Z',0}, {'B','L','Z',0}, 27082, 84 }, /* Belize */
2858 { 25, {'B','A',0}, {'B','I','H',0}, 47610, 70 }, /* Bosnia and Herzegovina */
2859 { 26, {'B','O',0}, {'B','O','L',0}, 31396, 68 }, /* Bolivia */
2860 { 27, {'M','M',0}, {'M','M','R',0}, 47599, 104 }, /* Myanmar */
2861 { 28, {'B','J',0}, {'B','E','N',0}, 42483, 204 }, /* Benin */
2862 { 29, {'B','Y',0}, {'B','L','R',0}, 47609, 112 }, /* Belarus */
2863 { 30, {'S','B',0}, {'S','L','B',0}, 20900, 90 }, /* Solomon Islands */
2864 { 32, {'B','R',0}, {'B','R','A',0}, 31396, 76 }, /* Brazil */
2865 { 34, {'B','T',0}, {'B','T','N',0}, 47614, 64 }, /* Bhutan */
2866 { 35, {'B','G',0}, {'B','G','R',0}, 47609, 100 }, /* Bulgaria */
2867 { 37, {'B','N',0}, {'B','R','N',0}, 47599, 96 }, /* Brunei */
2868 { 38, {'B','I',0}, {'B','D','I',0}, 47603, 108 }, /* Burundi */
2869 { 39, {'C','A',0}, {'C','A','N',0}, 23581, 124 }, /* Canada */
2870 { 40, {'K','H',0}, {'K','H','M',0}, 47599, 116 }, /* Cambodia */
2871 { 41, {'T','D',0}, {'T','C','D',0}, 42484, 148 }, /* Chad */
2872 { 42, {'L','K',0}, {'L','K','A',0}, 47614, 144 }, /* Sri Lanka */
2873 { 43, {'C','G',0}, {'C','O','G',0}, 42484, 178 }, /* Congo */
2874 { 44, {'C','D',0}, {'C','O','D',0}, 42484, 180 }, /* Congo (DRC) */
2875 { 45, {'C','N',0}, {'C','H','N',0}, 47600, 156 }, /* China */
2876 { 46, {'C','L',0}, {'C','H','L',0}, 31396, 152 }, /* Chile */
2877 { 49, {'C','M',0}, {'C','M','R',0}, 42484, 120 }, /* Cameroon */
2878 { 50, {'K','M',0}, {'C','O','M',0}, 47603, 174 }, /* Comoros */
2879 { 51, {'C','O',0}, {'C','O','L',0}, 31396, 170 }, /* Colombia */
2880 { 54, {'C','R',0}, {'C','R','I',0}, 27082, 188 }, /* Costa Rica */
2881 { 55, {'C','F',0}, {'C','A','F',0}, 42484, 140 }, /* Central African Republic */
2882 { 56, {'C','U',0}, {'C','U','B',0}, 10039880, 192 }, /* Cuba */
2883 { 57, {'C','V',0}, {'C','P','V',0}, 42483, 132 }, /* Cape Verde */
2884 { 59, {'C','Y',0}, {'C','Y','P',0}, 47611, 196 }, /* Cyprus */
2885 { 61, {'D','K',0}, {'D','N','K',0}, 10039882, 208 }, /* Denmark */
2886 { 62, {'D','J',0}, {'D','J','I',0}, 47603, 262 }, /* Djibouti */
2887 { 63, {'D','M',0}, {'D','M','A',0}, 10039880, 212 }, /* Dominica */
2888 { 65, {'D','O',0}, {'D','O','M',0}, 10039880, 214 }, /* Dominican Republic */
2889 { 66, {'E','C',0}, {'E','C','U',0}, 31396, 218 }, /* Ecuador */
2890 { 67, {'E','G',0}, {'E','G','Y',0}, 42487, 818 }, /* Egypt */
2891 { 68, {'I','E',0}, {'I','R','L',0}, 10039882, 372 }, /* Ireland */
2892 { 69, {'G','Q',0}, {'G','N','Q',0}, 42484, 226 }, /* Equatorial Guinea */
2893 { 70, {'E','E',0}, {'E','S','T',0}, 10039882, 233 }, /* Estonia */
2894 { 71, {'E','R',0}, {'E','R','I',0}, 47603, 232 }, /* Eritrea */
2895 { 72, {'S','V',0}, {'S','L','V',0}, 27082, 222 }, /* El Salvador */
2896 { 73, {'E','T',0}, {'E','T','H',0}, 47603, 231 }, /* Ethiopia */
2897 { 75, {'C','Z',0}, {'C','Z','E',0}, 47609, 203 }, /* Czech Republic */
2898 { 77, {'F','I',0}, {'F','I','N',0}, 10039882, 246 }, /* Finland */
2899 { 78, {'F','J',0}, {'F','J','I',0}, 20900, 242 }, /* Fiji Islands */
2900 { 80, {'F','M',0}, {'F','S','M',0}, 21206, 583 }, /* Micronesia */
2901 { 81, {'F','O',0}, {'F','R','O',0}, 10039882, 234 }, /* Faroe Islands */
2902 { 84, {'F','R',0}, {'F','R','A',0}, 10210824, 250 }, /* France */
2903 { 86, {'G','M',0}, {'G','M','B',0}, 42483, 270 }, /* Gambia, The */
2904 { 87, {'G','A',0}, {'G','A','B',0}, 42484, 266 }, /* Gabon */
2905 { 88, {'G','E',0}, {'G','E','O',0}, 47611, 268 }, /* Georgia */
2906 { 89, {'G','H',0}, {'G','H','A',0}, 42483, 288 }, /* Ghana */
2907 { 90, {'G','I',0}, {'G','I','B',0}, 47610, 292 }, /* Gibraltar */
2908 { 91, {'G','D',0}, {'G','R','D',0}, 10039880, 308 }, /* Grenada */
2909 { 93, {'G','L',0}, {'G','R','L',0}, 23581, 304 }, /* Greenland */
2910 { 94, {'D','E',0}, {'D','E','U',0}, 10210824, 276 }, /* Germany */
2911 { 98, {'G','R',0}, {'G','R','C',0}, 47610, 300 }, /* Greece */
2912 { 99, {'G','T',0}, {'G','T','M',0}, 27082, 320 }, /* Guatemala */
2913 { 100, {'G','N',0}, {'G','I','N',0}, 42483, 324 }, /* Guinea */
2914 { 101, {'G','Y',0}, {'G','U','Y',0}, 31396, 328 }, /* Guyana */
2915 { 103, {'H','T',0}, {'H','T','I',0}, 10039880, 332 }, /* Haiti */
2916 { 104, {'H','K',0}, {'H','K','G',0}, 47600, 344 }, /* Hong Kong S.A.R. */
2917 { 106, {'H','N',0}, {'H','N','D',0}, 27082, 340 }, /* Honduras */
2918 { 108, {'H','R',0}, {'H','R','V',0}, 47610, 191 }, /* Croatia */
2919 { 109, {'H','U',0}, {'H','U','N',0}, 47609, 348 }, /* Hungary */
2920 { 110, {'I','S',0}, {'I','S','L',0}, 10039882, 352 }, /* Iceland */
2921 { 111, {'I','D',0}, {'I','D','N',0}, 47599, 360 }, /* Indonesia */
2922 { 113, {'I','N',0}, {'I','N','D',0}, 47614, 356 }, /* India */
2923 { 114, {'I','O',0}, {'I','O','T',0}, 39070, 86 }, /* British Indian Ocean Territory */
2924 { 116, {'I','R',0}, {'I','R','N',0}, 47614, 364 }, /* Iran */
2925 { 117, {'I','L',0}, {'I','S','R',0}, 47611, 376 }, /* Israel */
2926 { 118, {'I','T',0}, {'I','T','A',0}, 47610, 380 }, /* Italy */
2927 { 119, {'C','I',0}, {'C','I','V',0}, 42483, 384 }, /* Côte d'Ivoire */
2928 { 121, {'I','Q',0}, {'I','R','Q',0}, 47611, 368 }, /* Iraq */
2929 { 122, {'J','P',0}, {'J','P','N',0}, 47600, 392 }, /* Japan */
2930 { 124, {'J','M',0}, {'J','A','M',0}, 10039880, 388 }, /* Jamaica */
2931 { 125, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Jan Mayen */
2932 { 126, {'J','O',0}, {'J','O','R',0}, 47611, 400 }, /* Jordan */
2933 { 127, {'X','X',0}, {'X','X',0}, 161832256 }, /* Johnston Atoll */
2934 { 129, {'K','E',0}, {'K','E','N',0}, 47603, 404 }, /* Kenya */
2935 { 130, {'K','G',0}, {'K','G','Z',0}, 47590, 417 }, /* Kyrgyzstan */
2936 { 131, {'K','P',0}, {'P','R','K',0}, 47600, 408 }, /* North Korea */
2937 { 133, {'K','I',0}, {'K','I','R',0}, 21206, 296 }, /* Kiribati */
2938 { 134, {'K','R',0}, {'K','O','R',0}, 47600, 410 }, /* Korea */
2939 { 136, {'K','W',0}, {'K','W','T',0}, 47611, 414 }, /* Kuwait */
2940 { 137, {'K','Z',0}, {'K','A','Z',0}, 47590, 398 }, /* Kazakhstan */
2941 { 138, {'L','A',0}, {'L','A','O',0}, 47599, 418 }, /* Laos */
2942 { 139, {'L','B',0}, {'L','B','N',0}, 47611, 422 }, /* Lebanon */
2943 { 140, {'L','V',0}, {'L','V','A',0}, 10039882, 428 }, /* Latvia */
2944 { 141, {'L','T',0}, {'L','T','U',0}, 10039882, 440 }, /* Lithuania */
2945 { 142, {'L','R',0}, {'L','B','R',0}, 42483, 430 }, /* Liberia */
2946 { 143, {'S','K',0}, {'S','V','K',0}, 47609, 703 }, /* Slovakia */
2947 { 145, {'L','I',0}, {'L','I','E',0}, 10210824, 438 }, /* Liechtenstein */
2948 { 146, {'L','S',0}, {'L','S','O',0}, 10039883, 426 }, /* Lesotho */
2949 { 147, {'L','U',0}, {'L','U','X',0}, 10210824, 442 }, /* Luxembourg */
2950 { 148, {'L','Y',0}, {'L','B','Y',0}, 42487, 434 }, /* Libya */
2951 { 149, {'M','G',0}, {'M','D','G',0}, 47603, 450 }, /* Madagascar */
2952 { 151, {'M','O',0}, {'M','A','C',0}, 47600, 446 }, /* Macao S.A.R. */
2953 { 152, {'M','D',0}, {'M','D','A',0}, 47609, 498 }, /* Moldova */
2954 { 154, {'M','N',0}, {'M','N','G',0}, 47600, 496 }, /* Mongolia */
2955 { 156, {'M','W',0}, {'M','W','I',0}, 47603, 454 }, /* Malawi */
2956 { 157, {'M','L',0}, {'M','L','I',0}, 42483, 466 }, /* Mali */
2957 { 158, {'M','C',0}, {'M','C','O',0}, 10210824, 492 }, /* Monaco */
2958 { 159, {'M','A',0}, {'M','A','R',0}, 42487, 504 }, /* Morocco */
2959 { 160, {'M','U',0}, {'M','U','S',0}, 47603, 480 }, /* Mauritius */
2960 { 162, {'M','R',0}, {'M','R','T',0}, 42483, 478 }, /* Mauritania */
2961 { 163, {'M','T',0}, {'M','L','T',0}, 47610, 470 }, /* Malta */
2962 { 164, {'O','M',0}, {'O','M','N',0}, 47611, 512 }, /* Oman */
2963 { 165, {'M','V',0}, {'M','D','V',0}, 47614, 462 }, /* Maldives */
2964 { 166, {'M','X',0}, {'M','E','X',0}, 27082, 484 }, /* Mexico */
2965 { 167, {'M','Y',0}, {'M','Y','S',0}, 47599, 458 }, /* Malaysia */
2966 { 168, {'M','Z',0}, {'M','O','Z',0}, 47603, 508 }, /* Mozambique */
2967 { 173, {'N','E',0}, {'N','E','R',0}, 42483, 562 }, /* Niger */
2968 { 174, {'V','U',0}, {'V','U','T',0}, 20900, 548 }, /* Vanuatu */
2969 { 175, {'N','G',0}, {'N','G','A',0}, 42483, 566 }, /* Nigeria */
2970 { 176, {'N','L',0}, {'N','L','D',0}, 10210824, 528 }, /* Netherlands */
2971 { 177, {'N','O',0}, {'N','O','R',0}, 10039882, 578 }, /* Norway */
2972 { 178, {'N','P',0}, {'N','P','L',0}, 47614, 524 }, /* Nepal */
2973 { 180, {'N','R',0}, {'N','R','U',0}, 21206, 520 }, /* Nauru */
2974 { 181, {'S','R',0}, {'S','U','R',0}, 31396, 740 }, /* Suriname */
2975 { 182, {'N','I',0}, {'N','I','C',0}, 27082, 558 }, /* Nicaragua */
2976 { 183, {'N','Z',0}, {'N','Z','L',0}, 10210825, 554 }, /* New Zealand */
2977 { 184, {'P','S',0}, {'P','S','E',0}, 47611, 275 }, /* Palestinian Authority */
2978 { 185, {'P','Y',0}, {'P','R','Y',0}, 31396, 600 }, /* Paraguay */
2979 { 187, {'P','E',0}, {'P','E','R',0}, 31396, 604 }, /* Peru */
2980 { 190, {'P','K',0}, {'P','A','K',0}, 47614, 586 }, /* Pakistan */
2981 { 191, {'P','L',0}, {'P','O','L',0}, 47609, 616 }, /* Poland */
2982 { 192, {'P','A',0}, {'P','A','N',0}, 27082, 591 }, /* Panama */
2983 { 193, {'P','T',0}, {'P','R','T',0}, 47610, 620 }, /* Portugal */
2984 { 194, {'P','G',0}, {'P','N','G',0}, 20900, 598 }, /* Papua New Guinea */
2985 { 195, {'P','W',0}, {'P','L','W',0}, 21206, 585 }, /* Palau */
2986 { 196, {'G','W',0}, {'G','N','B',0}, 42483, 624 }, /* Guinea-Bissau */
2987 { 197, {'Q','A',0}, {'Q','A','T',0}, 47611, 634 }, /* Qatar */
2988 { 198, {'R','E',0}, {'R','E','U',0}, 47603, 638 }, /* Reunion */
2989 { 199, {'M','H',0}, {'M','H','L',0}, 21206, 584 }, /* Marshall Islands */
2990 { 200, {'R','O',0}, {'R','O','U',0}, 47609, 642 }, /* Romania */
2991 { 201, {'P','H',0}, {'P','H','L',0}, 47599, 608 }, /* Philippines */
2992 { 202, {'P','R',0}, {'P','R','I',0}, 10039880, 630 }, /* Puerto Rico */
2993 { 203, {'R','U',0}, {'R','U','S',0}, 47609, 643 }, /* Russia */
2994 { 204, {'R','W',0}, {'R','W','A',0}, 47603, 646 }, /* Rwanda */
2995 { 205, {'S','A',0}, {'S','A','U',0}, 47611, 682 }, /* Saudi Arabia */
2996 { 206, {'P','M',0}, {'S','P','M',0}, 23581, 666 }, /* St. Pierre and Miquelon */
2997 { 207, {'K','N',0}, {'K','N','A',0}, 10039880, 659 }, /* St. Kitts and Nevis */
2998 { 208, {'S','C',0}, {'S','Y','C',0}, 47603, 690 }, /* Seychelles */
2999 { 209, {'Z','A',0}, {'Z','A','F',0}, 10039883, 710 }, /* South Africa */
3000 { 210, {'S','N',0}, {'S','E','N',0}, 42483, 686 }, /* Senegal */
3001 { 212, {'S','I',0}, {'S','V','N',0}, 47610, 705 }, /* Slovenia */
3002 { 213, {'S','L',0}, {'S','L','E',0}, 42483, 694 }, /* Sierra Leone */
3003 { 214, {'S','M',0}, {'S','M','R',0}, 47610, 674 }, /* San Marino */
3004 { 215, {'S','G',0}, {'S','G','P',0}, 47599, 702 }, /* Singapore */
3005 { 216, {'S','O',0}, {'S','O','M',0}, 47603, 706 }, /* Somalia */
3006 { 217, {'E','S',0}, {'E','S','P',0}, 47610, 724 }, /* Spain */
3007 { 218, {'L','C',0}, {'L','C','A',0}, 10039880, 662 }, /* St. Lucia */
3008 { 219, {'S','D',0}, {'S','D','N',0}, 42487, 736 }, /* Sudan */
3009 { 220, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Svalbard */
3010 { 221, {'S','E',0}, {'S','W','E',0}, 10039882, 752 }, /* Sweden */
3011 { 222, {'S','Y',0}, {'S','Y','R',0}, 47611, 760 }, /* Syria */
3012 { 223, {'C','H',0}, {'C','H','E',0}, 10210824, 756 }, /* Switzerland */
3013 { 224, {'A','E',0}, {'A','R','E',0}, 47611, 784 }, /* United Arab Emirates */
3014 { 225, {'T','T',0}, {'T','T','O',0}, 10039880, 780 }, /* Trinidad and Tobago */
3015 { 227, {'T','H',0}, {'T','H','A',0}, 47599, 764 }, /* Thailand */
3016 { 228, {'T','J',0}, {'T','J','K',0}, 47590, 762 }, /* Tajikistan */
3017 { 231, {'T','O',0}, {'T','O','N',0}, 26286, 776 }, /* Tonga */
3018 { 232, {'T','G',0}, {'T','G','O',0}, 42483, 768 }, /* Togo */
3019 { 233, {'S','T',0}, {'S','T','P',0}, 42484, 678 }, /* São Tomé and Príncipe */
3020 { 234, {'T','N',0}, {'T','U','N',0}, 42487, 788 }, /* Tunisia */
3021 { 235, {'T','R',0}, {'T','U','R',0}, 47611, 792 }, /* Turkey */
3022 { 236, {'T','V',0}, {'T','U','V',0}, 26286, 798 }, /* Tuvalu */
3023 { 237, {'T','W',0}, {'T','W','N',0}, 47600, 158 }, /* Taiwan */
3024 { 238, {'T','M',0}, {'T','K','M',0}, 47590, 795 }, /* Turkmenistan */
3025 { 239, {'T','Z',0}, {'T','Z','A',0}, 47603, 834 }, /* Tanzania */
3026 { 240, {'U','G',0}, {'U','G','A',0}, 47603, 800 }, /* Uganda */
3027 { 241, {'U','A',0}, {'U','K','R',0}, 47609, 804 }, /* Ukraine */
3028 { 242, {'G','B',0}, {'G','B','R',0}, 10039882, 826 }, /* United Kingdom */
3029 { 244, {'U','S',0}, {'U','S','A',0}, 23581, 840 }, /* United States */
3030 { 245, {'B','F',0}, {'B','F','A',0}, 42483, 854 }, /* Burkina Faso */
3031 { 246, {'U','Y',0}, {'U','R','Y',0}, 31396, 858 }, /* Uruguay */
3032 { 247, {'U','Z',0}, {'U','Z','B',0}, 47590, 860 }, /* Uzbekistan */
3033 { 248, {'V','C',0}, {'V','C','T',0}, 10039880, 670 }, /* St. Vincent and the Grenadines */
3034 { 249, {'V','E',0}, {'V','E','N',0}, 31396, 862 }, /* Bolivarian Republic of Venezuela */
3035 { 251, {'V','N',0}, {'V','N','M',0}, 47599, 704 }, /* Vietnam */
3036 { 252, {'V','I',0}, {'V','I','R',0}, 10039880, 850 }, /* Virgin Islands */
3037 { 253, {'V','A',0}, {'V','A','T',0}, 47610, 336 }, /* Vatican City */
3038 { 254, {'N','A',0}, {'N','A','M',0}, 10039883, 516 }, /* Namibia */
3039 { 257, {'E','H',0}, {'E','S','H',0}, 42487, 732 }, /* Western Sahara (disputed) */
3040 { 258, {'X','X',0}, {'X','X',0}, 161832256 }, /* Wake Island */
3041 { 259, {'W','S',0}, {'W','S','M',0}, 26286, 882 }, /* Samoa */
3042 { 260, {'S','Z',0}, {'S','W','Z',0}, 10039883, 748 }, /* Swaziland */
3043 { 261, {'Y','E',0}, {'Y','E','M',0}, 47611, 887 }, /* Yemen */
3044 { 263, {'Z','M',0}, {'Z','M','B',0}, 47603, 894 }, /* Zambia */
3045 { 264, {'Z','W',0}, {'Z','W','E',0}, 47603, 716 }, /* Zimbabwe */
3046 { 269, {'C','S',0}, {'S','C','G',0}, 47610, 891 }, /* Serbia and Montenegro (Former) */
3047 { 270, {'M','E',0}, {'M','N','E',0}, 47610, 499 }, /* Montenegro */
3048 { 271, {'R','S',0}, {'S','R','B',0}, 47610, 688 }, /* Serbia */
3049 { 273, {'C','W',0}, {'C','U','W',0}, 10039880, 531 }, /* Curaçao */
3050 { 276, {'S','S',0}, {'S','S','D',0}, 42487, 728 }, /* South Sudan */
3051 { 300, {'A','I',0}, {'A','I','A',0}, 10039880, 660 }, /* Anguilla */
3052 { 301, {'A','Q',0}, {'A','T','A',0}, 39070, 10 }, /* Antarctica */
3053 { 302, {'A','W',0}, {'A','B','W',0}, 10039880, 533 }, /* Aruba */
3054 { 303, {'X','X',0}, {'X','X',0}, 39070 }, /* Ascension Island */
3055 { 304, {'X','X',0}, {'X','X',0}, 10210825 }, /* Ashmore and Cartier Islands */
3056 { 305, {'X','X',0}, {'X','X',0}, 161832256 }, /* Baker Island */
3057 { 306, {'B','V',0}, {'B','V','T',0}, 39070, 74 }, /* Bouvet Island */
3058 { 307, {'K','Y',0}, {'C','Y','M',0}, 10039880, 136 }, /* Cayman Islands */
3059 { 308, {'X','X',0}, {'X','X',0}, 10210824, 0, LOCATION_BOTH }, /* Channel Islands */
3060 { 309, {'C','X',0}, {'C','X','R',0}, 12, 162 }, /* Christmas Island */
3061 { 310, {'X','X',0}, {'X','X',0}, 27114 }, /* Clipperton Island */
3062 { 311, {'C','C',0}, {'C','C','K',0}, 10210825, 166 }, /* Cocos (Keeling) Islands */
3063 { 312, {'C','K',0}, {'C','O','K',0}, 26286, 184 }, /* Cook Islands */
3064 { 313, {'X','X',0}, {'X','X',0}, 10210825 }, /* Coral Sea Islands */
3065 { 314, {'X','X',0}, {'X','X',0}, 114 }, /* Diego Garcia */
3066 { 315, {'F','K',0}, {'F','L','K',0}, 31396, 238 }, /* Falkland Islands (Islas Malvinas) */
3067 { 317, {'G','F',0}, {'G','U','F',0}, 31396, 254 }, /* French Guiana */
3068 { 318, {'P','F',0}, {'P','Y','F',0}, 26286, 258 }, /* French Polynesia */
3069 { 319, {'T','F',0}, {'A','T','F',0}, 39070, 260 }, /* French Southern and Antarctic Lands */
3070 { 321, {'G','P',0}, {'G','L','P',0}, 10039880, 312 }, /* Guadeloupe */
3071 { 322, {'G','U',0}, {'G','U','M',0}, 21206, 316 }, /* Guam */
3072 { 323, {'X','X',0}, {'X','X',0}, 39070 }, /* Guantanamo Bay */
3073 { 324, {'G','G',0}, {'G','G','Y',0}, 308, 831 }, /* Guernsey */
3074 { 325, {'H','M',0}, {'H','M','D',0}, 39070, 334 }, /* Heard Island and McDonald Islands */
3075 { 326, {'X','X',0}, {'X','X',0}, 161832256 }, /* Howland Island */
3076 { 327, {'X','X',0}, {'X','X',0}, 161832256 }, /* Jarvis Island */
3077 { 328, {'J','E',0}, {'J','E','Y',0}, 308, 832 }, /* Jersey */
3078 { 329, {'X','X',0}, {'X','X',0}, 161832256 }, /* Kingman Reef */
3079 { 330, {'M','Q',0}, {'M','T','Q',0}, 10039880, 474 }, /* Martinique */
3080 { 331, {'Y','T',0}, {'M','Y','T',0}, 47603, 175 }, /* Mayotte */
3081 { 332, {'M','S',0}, {'M','S','R',0}, 10039880, 500 }, /* Montserrat */
3082 { 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530, LOCATION_BOTH }, /* Netherlands Antilles (Former) */
3083 { 334, {'N','C',0}, {'N','C','L',0}, 20900, 540 }, /* New Caledonia */
3084 { 335, {'N','U',0}, {'N','I','U',0}, 26286, 570 }, /* Niue */
3085 { 336, {'N','F',0}, {'N','F','K',0}, 10210825, 574 }, /* Norfolk Island */
3086 { 337, {'M','P',0}, {'M','N','P',0}, 21206, 580 }, /* Northern Mariana Islands */
3087 { 338, {'X','X',0}, {'X','X',0}, 161832256 }, /* Palmyra Atoll */
3088 { 339, {'P','N',0}, {'P','C','N',0}, 26286, 612 }, /* Pitcairn Islands */
3089 { 340, {'X','X',0}, {'X','X',0}, 337 }, /* Rota Island */
3090 { 341, {'X','X',0}, {'X','X',0}, 337 }, /* Saipan */
3091 { 342, {'G','S',0}, {'S','G','S',0}, 39070, 239 }, /* South Georgia and the South Sandwich Islands */
3092 { 343, {'S','H',0}, {'S','H','N',0}, 42483, 654 }, /* St. Helena */
3093 { 346, {'X','X',0}, {'X','X',0}, 337 }, /* Tinian Island */
3094 { 347, {'T','K',0}, {'T','K','L',0}, 26286, 772 }, /* Tokelau */
3095 { 348, {'X','X',0}, {'X','X',0}, 39070 }, /* Tristan da Cunha */
3096 { 349, {'T','C',0}, {'T','C','A',0}, 10039880, 796 }, /* Turks and Caicos Islands */
3097 { 351, {'V','G',0}, {'V','G','B',0}, 10039880, 92 }, /* Virgin Islands, British */
3098 { 352, {'W','F',0}, {'W','L','F',0}, 26286, 876 }, /* Wallis and Futuna */
3099 { 742, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Africa */
3100 { 2129, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Asia */
3101 { 10541, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Europe */
3102 { 15126, {'I','M',0}, {'I','M','N',0}, 10039882, 833 }, /* Man, Isle of */
3103 { 19618, {'M','K',0}, {'M','K','D',0}, 47610, 807 }, /* Macedonia, Former Yugoslav Republic of */
3104 { 20900, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Melanesia */
3105 { 21206, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Micronesia */
3106 { 21242, {'X','X',0}, {'X','X',0}, 161832256 }, /* Midway Islands */
3107 { 23581, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Northern America */
3108 { 26286, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Polynesia */
3109 { 27082, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Central America */
3110 { 27114, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Oceania */
3111 { 30967, {'S','X',0}, {'S','X','M',0}, 10039880, 534 }, /* Sint Maarten (Dutch part) */
3112 { 31396, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* South America */
3113 { 31706, {'M','F',0}, {'M','A','F',0}, 10039880, 663 }, /* Saint Martin (French part) */
3114 { 39070, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* World */
3115 { 42483, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Western Africa */
3116 { 42484, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Middle Africa */
3117 { 42487, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Northern Africa */
3118 { 47590, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Central Asia */
3119 { 47599, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* South-Eastern Asia */
3120 { 47600, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Eastern Asia */
3121 { 47603, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Eastern Africa */
3122 { 47609, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Eastern Europe */
3123 { 47610, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Southern Europe */
3124 { 47611, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Middle East */
3125 { 47614, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Southern Asia */
3126 { 7299303, {'T','L',0}, {'T','L','S',0}, 47599, 626 }, /* Democratic Republic of Timor-Leste */
3127 { 10026358, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Americas */
3128 { 10028789, {'A','X',0}, {'A','L','A',0}, 10039882, 248 }, /* Åland Islands */
3129 { 10039880, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Caribbean */
3130 { 10039882, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Northern Europe */
3131 { 10039883, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Southern Africa */
3132 { 10210824, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Western Europe */
3133 { 10210825, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Australia and New Zealand */
3134 { 161832015, {'B','L',0}, {'B','L','M',0}, 10039880, 652 }, /* Saint Barthélemy */
3135 { 161832256, {'U','M',0}, {'U','M','I',0}, 27114, 581 }, /* U.S. Minor Outlying Islands */
3136 { 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Latin America and the Caribbean */
3137};
3138
3139/******************************************************************************
3140 * EnumLanguageGroupLocalesA (KERNEL32.@)
3141 *
3142 * Call a users function for every locale in a language group available on the system.
3143 *
3144 * PARAMS
3145 * pLangGrpLcEnumProc [I] Callback function to call for each locale
3146 * lgrpid [I] Language group (LGRPID_ values from "winnls.h")
3147 * dwFlags [I] Reserved, set to 0
3148 * lParam [I] User parameter to pass to pLangGrpLcEnumProc
3149 *
3150 * RETURNS
3151 * Success: TRUE.
3152 * Failure: FALSE. Use GetLastError() to determine the cause.
3153 */
3156{
3158
3159 TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
3160
3161 callbacks.procA = pLangGrpLcEnumProc;
3162 callbacks.procW = NULL;
3163 callbacks.dwFlags = dwFlags;
3164 callbacks.lgrpid = lgrpid;
3165 callbacks.lParam = lParam;
3166
3167 return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
3168}
3169
3170/******************************************************************************
3171 * EnumLanguageGroupLocalesW (KERNEL32.@)
3172 *
3173 * See EnumLanguageGroupLocalesA.
3174 */
3177{
3179
3180 TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
3181
3182 callbacks.procA = NULL;
3183 callbacks.procW = pLangGrpLcEnumProc;
3184 callbacks.dwFlags = dwFlags;
3185 callbacks.lgrpid = lgrpid;
3186 callbacks.lParam = lParam;
3187
3188 return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
3189}
3190
3191/* Callback function ptrs for EnumSystemCodePagesA/W */
3192typedef struct
3193{
3198
3199/* Internal implementation of EnumSystemCodePagesA/W */
3201{
3202 WCHAR szNumber[5 + 1], szValue[MAX_PATH];
3203 HANDLE hKey;
3204 BOOL bContinue = TRUE;
3205 ULONG ulIndex = 0;
3206
3207 if (!lpProcs)
3208 {
3210 return FALSE;
3211 }
3212
3213 switch (lpProcs->dwFlags)
3214 {
3215 case CP_INSTALLED:
3216 case CP_SUPPORTED:
3217 break;
3218 default:
3220 return FALSE;
3221 }
3222
3223 hKey = NLS_RegOpenKey(0, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
3224 if (!hKey)
3225 {
3226 WARN("NLS_RegOpenKey() failed\n");
3227 return FALSE;
3228 }
3229
3230 while (bContinue)
3231 {
3232 if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber),
3233 szValue, sizeof(szValue)))
3234 {
3235 if ((lpProcs->dwFlags == CP_SUPPORTED)||
3236 ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) > 2)))
3237 {
3238 if (lpProcs->procW)
3239 {
3240 bContinue = lpProcs->procW(szNumber);
3241 }
3242 else
3243 {
3244 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
3245
3246 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
3247 bContinue = lpProcs->procA(szNumberA);
3248 }
3249 }
3250
3251 ulIndex++;
3252
3253 } else bContinue = FALSE;
3254
3255 if (!bContinue)
3256 break;
3257 }
3258
3259 if (hKey)
3260 NtClose(hKey);
3261
3262 return TRUE;
3263}
3264
3265/*
3266 * @implemented
3267 */
3268BOOL
3269WINAPI
3271 CODEPAGE_ENUMPROCW lpCodePageEnumProc,
3273 )
3274{
3276
3277 TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
3278
3279 procs.procA = NULL;
3280 procs.procW = lpCodePageEnumProc;
3281 procs.dwFlags = dwFlags;
3282
3283 return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
3284}
3285
3286
3287/*
3288 * @implemented
3289 */
3290BOOL
3291WINAPI
3293 CODEPAGE_ENUMPROCA lpCodePageEnumProc,
3295 )
3296{
3298
3299 TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
3300
3301 procs.procA = lpCodePageEnumProc;
3302 procs.procW = NULL;
3303 procs.dwFlags = dwFlags;
3304
3305 return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
3306}
3307
3308/******************************************************************************
3309 * EnumSystemGeoID (KERNEL32.@)
3310 *
3311 * Call a users function for every location available on the system.
3312 *
3313 * PARAMS
3314 * geoclass [I] Type of information desired (SYSGEOTYPE enum from "winnls.h")
3315 * parent [I] GEOID for the parent
3316 * enumproc [I] Callback function to call for each location
3317 *
3318 * RETURNS
3319 * Success: TRUE.
3320 * Failure: FALSE. Use GetLastError() to determine the cause.
3321 */
3323{
3324 INT i;
3325
3326 TRACE("(%d, %d, %p)\n", geoclass, parent, enumproc);
3327
3328 if (!enumproc) {
3330 return FALSE;
3331 }
3332
3333 if (geoclass != GEOCLASS_NATION && geoclass != GEOCLASS_REGION) {
3335 return FALSE;
3336 }
3337
3338 for (i = 0; i < sizeof(geoinfodata)/sizeof(struct geoinfo_t); i++) {
3339 const struct geoinfo_t *ptr = &geoinfodata[i];
3340
3341 if (geoclass == GEOCLASS_NATION && (ptr->kind == LOCATION_REGION))
3342 continue;
3343
3344 if (geoclass == GEOCLASS_REGION && (ptr->kind == LOCATION_NATION))
3345 continue;
3346
3347 if (parent && ptr->parent != parent)
3348 continue;
3349
3350 if (!enumproc(ptr->id))
3351 return TRUE;
3352 }
3353
3354 return TRUE;
3355}
3356
3357/******************************************************************************
3358 * InvalidateNLSCache (KERNEL32.@)
3359 *
3360 * Invalidate the cache of NLS values.
3361 *
3362 * PARAMS
3363 * None.
3364 *
3365 * RETURNS
3366 * Success: TRUE.
3367 * Failure: FALSE.
3368 */
3370{
3371#ifdef __REACTOS__
3373 return TRUE;
3374#else
3375 FIXME("() stub\n");
3376 return FALSE;
3377#endif
3378}
3379
3380/******************************************************************************
3381 * GetUserGeoID (KERNEL32.@)
3382 */
3384{
3386 static const WCHAR geoW[] = {'G','e','o',0};
3387 static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
3388 WCHAR bufferW[40], *end;
3389 DWORD count;
3390 HANDLE hkey, hSubkey = 0;
3391 UNICODE_STRING keyW;
3393 RtlInitUnicodeString( &keyW, nationW );
3394 count = sizeof(bufferW);
3395
3396 if(!(hkey = create_registry_key())) return ret;
3397
3398 switch( GeoClass ){
3399 case GEOCLASS_NATION:
3400 if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
3401 {
3402 if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
3403 bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength)
3404 ret = strtolW((LPCWSTR)info->Data, &end, 10);
3405 }
3406 break;
3407 case GEOCLASS_REGION:
3408 FIXME("GEOCLASS_REGION not handled yet\n");
3409 break;
3410 }
3411
3412 NtClose(hkey);
3413 if (hSubkey) NtClose(hSubkey);
3414 return ret;
3415}
3416
3417/******************************************************************************
3418 * SetUserGeoID (KERNEL32.@)
3419 */
3421{
3422 static const WCHAR geoW[] = {'G','e','o',0};
3423 static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
3424 static const WCHAR formatW[] = {'%','i',0};
3425 UNICODE_STRING nameW,keyW;
3426 WCHAR bufferW[10];
3428 HANDLE hkey;
3429
3430 if(!(hkey = create_registry_key())) return FALSE;
3431
3432 attr.Length = sizeof(attr);
3433 attr.RootDirectory = hkey;
3434 attr.ObjectName = &nameW;
3435 attr.Attributes = 0;
3436 attr.SecurityDescriptor = NULL;
3437 attr.SecurityQualityOfService = NULL;
3438 RtlInitUnicodeString( &nameW, geoW );
3439 RtlInitUnicodeString( &keyW, nationW );
3440
3441 if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
3442
3443 {
3444 NtClose(attr.RootDirectory);
3445 return FALSE;
3446 }
3447
3448 sprintfW(bufferW, formatW, GeoID);
3449 NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
3450 NtClose(attr.RootDirectory);
3451 NtClose(hkey);
3452 return TRUE;
3453}
3454
3455typedef struct
3456{
3457 union
3458 {
3461 } u;
3465
3468{
3470 char buf[20];
3471
3472 sprintf(buf, "%08x", (UINT)LangID);
3473 return enum_uilang->u.procA( buf, enum_uilang->param );
3474}
3475
3478{
3479 static const WCHAR formatW[] = {'%','0','8','x',0};
3481 WCHAR buf[20];
3482
3483 sprintfW( buf, formatW, (UINT)LangID );
3484 return enum_uilang->u.procW( buf, enum_uilang->param );
3485}
3486
3487/******************************************************************************
3488 * EnumUILanguagesA (KERNEL32.@)
3489 */
3491{
3492 ENUM_UILANG_CALLBACK enum_uilang;
3493
3494 TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
3495
3496 if(!pUILangEnumProc) {
3498 return FALSE;
3499 }
3500 if(dwFlags) {
3502 return FALSE;
3503 }
3504
3505 enum_uilang.u.procA = pUILangEnumProc;
3506 enum_uilang.flags = dwFlags;
3507 enum_uilang.param = lParam;
3508
3511 (LONG_PTR)&enum_uilang);
3512 return TRUE;
3513}
3514
3515/******************************************************************************
3516 * EnumUILanguagesW (KERNEL32.@)
3517 */
3519{
3520 ENUM_UILANG_CALLBACK enum_uilang;
3521
3522 TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
3523
3524
3525 if(!pUILangEnumProc) {
3527 return FALSE;
3528 }
3529 if(dwFlags) {
3531 return FALSE;
3532 }
3533
3534 enum_uilang.u.procW = pUILangEnumProc;
3535 enum_uilang.flags = dwFlags;
3536 enum_uilang.param = lParam;
3537
3540 (LONG_PTR)&enum_uilang);
3541 return TRUE;
3542}
3543
3544static int
3545#ifdef __REACTOS__
3546NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData, LANGID lang)
3547#else
3548NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
3549#endif
3550{
3551 /* FIXME: move *.nls resources out of kernel32 into locale.nls */
3552 Location += NLSRC_OFFSET;
3553 Location &= 0xFFFF;
3554
3555 if (cchData == 0)
3556#ifdef __REACTOS__
3557 return GetLocalisedText(Location, NULL, 0, lang);
3558#else
3559 return GetLocalisedText(Location, NULL, 0);
3560#endif
3561
3562#ifdef __REACTOS__
3563 if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData, lang))
3564#else
3565 if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData))
3566#endif
3567 return strlenW(szFriendlyName) + 1;
3568
3569 return 0;
3570}
3571
3572static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
3573{
3574 int min, max;
3575
3576 min = 0;
3577 max = sizeof(geoinfodata)/sizeof(struct geoinfo_t)-1;
3578
3579 while (min <= max) {
3580 const struct geoinfo_t *ptr;
3581 int n = (min+max)/2;
3582
3583 ptr = &geoinfodata[n];
3584 if (geoid == ptr->id)
3585 /* we don't need empty entry */
3586 return *ptr->iso2W ? ptr : NULL;
3587
3588 if (ptr->id > geoid)
3589 max = n-1;
3590 else
3591 min = n+1;
3592 }
3593
3594 return NULL;
3595}
3596
3597/******************************************************************************
3598 * GetGeoInfoW (KERNEL32.@)
3599 */
3600INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
3601{
3602 const struct geoinfo_t *ptr;
3603 const WCHAR *str = NULL;
3604 WCHAR buffW[12];
3605 LONG val = 0;
3606 INT len;
3607
3608 TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
3609
3610 if (!(ptr = get_geoinfo_dataptr(geoid))) {
3612 return 0;
3613 }
3614
3615 switch (geotype) {
3616 case GEO_FRIENDLYNAME:
3617 {
3618#ifdef __REACTOS__
3619 return NLS_GetGeoFriendlyName(geoid, data, data_len, lang);
3620#else
3621 return NLS_GetGeoFriendlyName(geoid, data, data_len);
3622#endif
3623 }
3624 case GEO_NATION:
3625 val = geoid;
3626 break;
3627 case GEO_ISO_UN_NUMBER:
3628 val = ptr->uncode;
3629 break;
3630 case GEO_PARENT:
3631 val = ptr->parent;
3632 break;
3633 case GEO_ISO2:
3634 case GEO_ISO3:
3635 {
3636 str = geotype == GEO_ISO2 ? ptr->iso2W : ptr->iso3W;
3637 break;
3638 }
3639 case GEO_RFC1766:
3640 case GEO_LCID:
3641 case GEO_OFFICIALNAME:
3642 case GEO_TIMEZONES:
3644 case GEO_LATITUDE:
3645 case GEO_LONGITUDE:
3646 FIXME("type %d is not supported\n", geotype);
3648 return 0;
3649 default:
3650 WARN("unrecognized type %d\n", geotype);
3652 return 0;
3653 }
3654
3655 if (val) {
3656 static const WCHAR fmtW[] = {'%','d',0};
3657 sprintfW(buffW, fmtW, val);
3658 str = buffW;
3659 }
3660
3661 len = strlenW(str) + 1;
3662 if (!data || !data_len)
3663 return len;
3664
3665 memcpy(data, str, min(len, data_len)*sizeof(WCHAR));
3666 if (data_len < len)
3668 return data_len < len ? 0 : len;
3669}
3670
3671/******************************************************************************
3672 * GetGeoInfoA (KERNEL32.@)
3673 */
3674INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
3675{
3676 WCHAR *buffW;
3677 INT len;
3678
3679 TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
3680
3681 len = GetGeoInfoW(geoid, geotype, NULL, 0, lang);
3682 if (!len)
3683 return 0;
3684
3685 buffW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
3686 if (!buffW)
3687 return 0;
3688
3689 GetGeoInfoW(geoid, geotype, buffW, len, lang);
3690 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, NULL, 0, NULL, NULL);
3691 if (!data || !data_len) {
3692 HeapFree(GetProcessHeap(), 0, buffW);
3693 return len;
3694 }
3695
3696 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, data, data_len, NULL, NULL);
3697 HeapFree(GetProcessHeap(), 0, buffW);
3698
3699 if (data_len < len)
3701 return data_len < len ? 0 : len;
3702}
WCHAR lpszDest[260]
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:46
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define ARRAY_SIZE(A)
Definition: main.h:33
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
return
Definition: dirsup.c:529
CFF_Charset charset
Definition: cffcmap.c:138
Definition: _locale.h:75
LPARAM lParam
Definition: combotst.c:139
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HMODULE hModule
Definition: animate.c:44
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
static const WCHAR valueW[]
Definition: object.c:48
BOOL WINAPI WriteProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string)
Definition: profile.c:1287
BOOL WINAPI FreeResource(HGLOBAL handle)
Definition: res.c:559
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
BOOL WINAPI EnumResourceLanguagesA(HMODULE hmod, LPCSTR type, LPCSTR name, ENUMRESLANGPROCA lpfun, LONG_PTR lparam)
Definition: res.c:428
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang)
Definition: res.c:164
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
BOOL WINAPI EnumResourceLanguagesW(HMODULE hmod, LPCWSTR type, LPCWSTR name, ENUMRESLANGPROCW lpfun, LONG_PTR lparam)
Definition: res.c:480
unsigned char
Definition: typeof.h:29
r parent
Definition: btrfs.c:3010
r reserved
Definition: btrfs.c:3006
#define strcasecmp
Definition: fake.h:9
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxAutoRegKey hKey
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
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
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 * u
Definition: glfuncs.h:240
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 GLint GLint j
Definition: glfuncs.h:250
#define WINBASEAPI
Definition: green.h:8
#define C1_PUNCT
Definition: unicode.h:35
#define C1_SPACE
Definition: unicode.h:34
#define C1_ALPHA
Definition: unicode.h:39
#define MB_COMPOSITE
Definition: unicode.h:40
WINE_UNICODE_INLINE unsigned short get_char_typeW(WCHAR ch)
Definition: unicode.h:149
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
void JapaneseEra_ClearCache(void)
Definition: japanese.c:38
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define nls
Definition: kernel32.h:13
GEOID WINAPI GetUserGeoID(GEOCLASS GeoClass)
Definition: lang.c:3383