ReactOS  0.4.15-dev-4872-g8a3db97
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
36 extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen);
37 extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen);
38 extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2);
39 #ifdef __REACTOS__
40 extern UINT GetLocalisedText(IN UINT uID, IN LPWSTR lpszDest, IN UINT cchDest, IN LANGID lang);
41 #else
42 extern UINT GetLocalisedText(IN UINT uID, IN LPWSTR lpszDest, IN UINT cchDest);
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 
51 static 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 
58 static 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. */
68 static const struct charset_entry
69 {
70  const char *charset_name;
71  UINT codepage;
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 
152 static const WCHAR iCalendarTypeW[] = {'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
153 static const WCHAR iCountryW[] = {'i','C','o','u','n','t','r','y',0};
154 static const WCHAR iCurrDigitsW[] = {'i','C','u','r','r','D','i','g','i','t','s',0};
155 static const WCHAR iCurrencyW[] = {'i','C','u','r','r','e','n','c','y',0};
156 static const WCHAR iDateW[] = {'i','D','a','t','e',0};
157 static const WCHAR iDigitsW[] = {'i','D','i','g','i','t','s',0};
158 static const WCHAR iFirstDayOfWeekW[] = {'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
159 static const WCHAR iFirstWeekOfYearW[] = {'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
160 static const WCHAR iLDateW[] = {'i','L','D','a','t','e',0};
161 static const WCHAR iLZeroW[] = {'i','L','Z','e','r','o',0};
162 static const WCHAR iMeasureW[] = {'i','M','e','a','s','u','r','e',0};
163 static const WCHAR iNegCurrW[] = {'i','N','e','g','C','u','r','r',0};
164 static const WCHAR iNegNumberW[] = {'i','N','e','g','N','u','m','b','e','r',0};
165 static const WCHAR iPaperSizeW[] = {'i','P','a','p','e','r','S','i','z','e',0};
166 static const WCHAR iTLZeroW[] = {'i','T','L','Z','e','r','o',0};
167 static const WCHAR iTimePrefixW[] = {'i','T','i','m','e','P','r','e','f','i','x',0};
168 static const WCHAR iTimeW[] = {'i','T','i','m','e',0};
169 static const WCHAR s1159W[] = {'s','1','1','5','9',0};
170 static const WCHAR s2359W[] = {'s','2','3','5','9',0};
171 static const WCHAR sCountryW[] = {'s','C','o','u','n','t','r','y',0};
172 static const WCHAR sCurrencyW[] = {'s','C','u','r','r','e','n','c','y',0};
173 static const WCHAR sDateW[] = {'s','D','a','t','e',0};
174 static const WCHAR sDecimalW[] = {'s','D','e','c','i','m','a','l',0};
175 static const WCHAR sGroupingW[] = {'s','G','r','o','u','p','i','n','g',0};
176 static const WCHAR sLanguageW[] = {'s','L','a','n','g','u','a','g','e',0};
177 static const WCHAR sListW[] = {'s','L','i','s','t',0};
178 static const WCHAR sLongDateW[] = {'s','L','o','n','g','D','a','t','e',0};
179 static const WCHAR sMonDecimalSepW[] = {'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
180 static const WCHAR sMonGroupingW[] = {'s','M','o','n','G','r','o','u','p','i','n','g',0};
181 static const WCHAR sMonThousandSepW[] = {'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
182 static const WCHAR sNativeDigitsW[] = {'s','N','a','t','i','v','e','D','i','g','i','t','s',0};
183 static const WCHAR sNegativeSignW[] = {'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
184 static const WCHAR sPositiveSignW[] = {'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
185 static const WCHAR sShortDateW[] = {'s','S','h','o','r','t','D','a','t','e',0};
186 static const WCHAR sThousandW[] = {'s','T','h','o','u','s','a','n','d',0};
187 static const WCHAR sTimeFormatW[] = {'s','T','i','m','e','F','o','r','m','a','t',0};
188 static const WCHAR sTimeW[] = {'s','T','i','m','e',0};
189 static const WCHAR sYearMonthW[] = {'s','Y','e','a','r','M','o','n','t','h',0};
190 static const WCHAR NumShapeW[] = {'N','u','m','s','h','a','p','e',0};
191 
192 static struct registry_value
193 {
195  const WCHAR *name;
197 } registry_values[] =
198 {
205  { LOCALE_ILZERO, iLZeroW },
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 },
234  { LOCALE_ILDATE, iLDateW },
238  /* The following are used in XP and later */
239  { LOCALE_IDIGITSUBSTITUTION, NumShapeW },
242 };
243 
244 static RTL_CRITICAL_SECTION cache_section = { NULL, -1, 0, 0, 0, 0 };
245 
246 #ifndef __REACTOS__
247 /* Copy Ascii string to Unicode without using codepages */
248 static 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  */
264 static 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  */
276 static 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  */
285 static 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 
302 static LANGID get_default_sublang( LANGID lang )
303 {
304  switch (lang)
305  {
315  }
317  return lang;
318 }
319 
320 /***********************************************************************
321  * find_locale_id_callback
322  */
323 static 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 
345  buffer, ARRAY_SIZE( buffer )))
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,
353  buffer, ARRAY_SIZE( buffer )))
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  {
371  buffer, ARRAY_SIZE( buffer )))
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 
395 done:
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  */
412 static 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  }
508 done:
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 {
521  if (lcid == LOCALE_SYSTEM_DEFAULT ||
523  lcid == LOCALE_NEUTRAL)
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 
542  case LOCALE_ICURRDIGITS:
543  case LOCALE_ICURRENCY:
545  case LOCALE_INEGCURR:
547  case LOCALE_INEGSIGNPOSN:
550  case LOCALE_IPOSSIGNPOSN:
552  case LOCALE_SCURRENCY:
553  case LOCALE_SINTLSYMBOL:
555  case LOCALE_SMONGROUPING:
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:
564  case LOCALE_INEGNUMBER:
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:
621  case LOCALE_SMONTHNAME1:
622  case LOCALE_SMONTHNAME2:
623  case LOCALE_SMONTHNAME3:
624  case LOCALE_SMONTHNAME4:
625  case LOCALE_SMONTHNAME5:
626  case LOCALE_SMONTHNAME6:
627  case LOCALE_SMONTHNAME7:
628  case LOCALE_SMONTHNAME8:
629  case LOCALE_SMONTHNAME9:
630  case LOCALE_SMONTHNAME10:
631  case LOCALE_SMONTHNAME11:
632  case LOCALE_SMONTHNAME12:
633  case LOCALE_SMONTHNAME13:
634  case LOCALE_SSHORTDATE:
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:
643  case LOCALE_STIMEFORMAT:
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  {
674  case LOCALE_SMONTHNAME1:
675  case LOCALE_SMONTHNAME2:
676  case LOCALE_SMONTHNAME3:
677  case LOCALE_SMONTHNAME4:
678  case LOCALE_SMONTHNAME5:
679  case LOCALE_SMONTHNAME6:
680  case LOCALE_SMONTHNAME7:
681  case LOCALE_SMONTHNAME8:
682  case LOCALE_SMONTHNAME9:
683  case LOCALE_SMONTHNAME10:
684  case LOCALE_SMONTHNAME11:
685  case LOCALE_SMONTHNAME12:
686  case LOCALE_SMONTHNAME13:
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  */
698 static 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  */
841 LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags )
842 {
843  struct locale_name locale_name;
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  */
875 INT 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  {
948  HeapFree( GetProcessHeap(), 0, info );
951  return 0;
952  }
953 
954  memcpy( cached_value, info->Data, (length-1) * sizeof(WCHAR) );
955  cached_value[length-1] = 0;
956  HeapFree( GetProcessHeap(), 0, info );
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  }
974  HeapFree( GetProcessHeap(), 0, info );
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) ||
1035  (lctype & LOCALE_RETURN_GENITIVE_NAMES))
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  {
1069  UINT codepage = CP_ACP;
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 
1078 static int get_value_base_by_lctype( LCTYPE lctype )
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++)
1092  if (registry_values[i].lctype == lctype)
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 
1129  lcflags = lctype & LOCALE_LOCALEINFOFLAGSMASK;
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);
1183  lpName = MAKEINTRESOURCEW(ULongToPtr((lctype >> 4) + 1));
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)
1264 WINBASEAPI
1265 int
1266 WINAPI
1267 GetLocaleInfoEx(
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 
1277 BOOL
1278 WINAPI
1279 IsValidLocaleName(
1280  LPCWSTR lpLocaleName
1281 )
1282 {
1283  TRACE( "IsValidLocaleName not implemented (lpLocaleName=%s)\n", debugstr_w(lpLocaleName));
1284  return TRUE;
1285 }
1286 
1287 INT
1288 WINAPI
1289 GetUserDefaultLocaleName(
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 {
1325  UINT codepage = CP_ACP;
1326  WCHAR *strW;
1327  DWORD len;
1328  BOOL ret;
1329 
1330  if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
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  }
1343  MultiByteToWideChar( codepage, 0, data, -1, strW, len );
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 };
1360  NTSTATUS status;
1361  HANDLE hkey;
1362 
1363  lctype &= 0xffff;
1365 
1366  if (!data || !value)
1367  {
1369  return FALSE;
1370  }
1371 
1372  if (lctype == LOCALE_IDATE || lctype == LOCALE_ILDATE)
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;
1386  RtlInitUnicodeString( &valueW, value->name );
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 
1418  if (lctype == LOCALE_SSHORTDATE)
1419  lctype = LOCALE_IDATE;
1420  else
1422 
1424 
1425  WriteProfileStringW( intlW, value->name, szBuff );
1426 
1427  RtlInitUnicodeString( &valueW, value->name );
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;
1515  case LOCALE_SYSTEM_DEFAULT:
1516  lcid = GetSystemDefaultLCID();
1517  break;
1518  case LOCALE_USER_DEFAULT:
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 */
1556  (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0;
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 {
1628  struct enum_locale_ex_data *data = (struct enum_locale_ex_data *)lparam;
1629  WCHAR buffer[256];
1630  DWORD neutral;
1631  unsigned int flags;
1632 
1634  buffer, ARRAY_SIZE( buffer ));
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 {
1650  struct enum_locale_ex_data data;
1651 
1652  if (reserved)
1653  {
1655  return FALSE;
1656  }
1657  data.proc = proc;
1658  data.flags = flags;
1659  data.lparam = lparam;
1661  (LPCWSTR)MAKEINTRESOURCE((LOCALE_SNAME >> 4) + 1),
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  */
1965  if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
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;
1977  if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
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;
1988  if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
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;
2004  if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
2005  continue;
2006  *dst_ptr++ = wch;
2007  dstlen--;
2008  }
2009  }
2010 
2011  if (srclen)
2012  {
2014  return 0;
2015  }
2016 
2017  return dst_ptr - dst;
2018 }
2019 
2020 /*************************************************************************
2021  * LCMapStringW (KERNEL32.@)
2022  *
2023  * See LCMapStringA.
2024  */
2026  LPWSTR dst, INT dstlen)
2027 {
2028  TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n",
2029  lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen);
2030 
2031  return LCMapStringEx(NULL, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
2032 }
2033 
2034 /*************************************************************************
2035  * LCMapStringA (KERNEL32.@)
2036  *
2037  * Map characters in a locale sensitive string.
2038  *
2039  * PARAMS
2040  * lcid [I] LCID for the conversion.
2041  * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h").
2042  * src [I] String to map
2043  * srclen [I] Length of src in chars, or -1 if src is NUL terminated
2044  * dst [O] Destination for mapped string
2045  * dstlen [I] Length of dst in characters
2046  *
2047  * RETURNS
2048  * Success: The length of the mapped string in dst, including the NUL terminator.
2049  * Failure: 0. Use GetLastError() to determine the cause.
2050  */
2052  LPSTR dst, INT dstlen)
2053 {
2054  WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
2055  LPWSTR srcW, dstW;
2056  INT ret = 0, srclenW, dstlenW;
2057  UINT locale_cp = CP_ACP;
2058 
2059  if (!src || !srclen || dstlen < 0)
2060  {
2062  return 0;
2063  }
2064 
2065  if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
2066 
2067  srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
2068  if (srclenW)
2069  srcW = bufW;
2070  else
2071  {
2072  srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, NULL, 0);
2073  srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
2074  if (!srcW)
2075  {
2077  return 0;
2078  }
2079  MultiByteToWideChar(locale_cp, 0, src, srclen, srcW, srclenW);
2080  }
2081 
2082  if (flags & LCMAP_SORTKEY)
2083  {
2084  if (src == dst)
2085  {
2087  goto map_string_exit;
2088  }
2089  ret = wine_get_sortkey(flags, srcW, srclenW, dst, dstlen);
2090  if (ret == 0)
2092  else
2093  ret++;
2094  goto map_string_exit;
2095  }
2096 
2097  if (flags & SORT_STRINGSORT)
2098  {
2100  goto map_string_exit;
2101  }
2102 
2103  dstlenW = LCMapStringEx(NULL, flags, srcW, srclenW, NULL, 0, NULL, NULL, 0);
2104  if (!dstlenW)
2105  goto map_string_exit;
2106 
2107  dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
2108  if (!dstW)
2109  {
2111  goto map_string_exit;
2112  }
2113 
2114  LCMapStringEx(NULL, flags, srcW, srclenW, dstW, dstlenW, NULL, NULL, 0);
2115  ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL);
2116  HeapFree(GetProcessHeap(), 0, dstW);
2117 
2118 map_string_exit:
2119  if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW);
2120  return ret;
2121 }
2122 
2123 /*************************************************************************
2124  * FoldStringA (KERNEL32.@)
2125  *
2126  * Map characters in a string.
2127  *
2128  * PARAMS
2129  * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
2130  * src [I] String to map
2131  * srclen [I] Length of src, or -1 if src is NUL terminated
2132  * dst [O] Destination for mapped string
2133  * dstlen [I] Length of dst, or 0 to find the required length for the mapped string
2134  *
2135  * RETURNS
2136  * Success: The length of the string written to dst, including the terminating NUL. If
2137  * dstlen is 0, the value returned is the same, but nothing is written to dst,
2138  * and dst may be NULL.
2139  * Failure: 0. Use GetLastError() to determine the cause.
2140  */
2142  LPSTR dst, INT dstlen)
2143 {
2144  INT ret = 0, srclenW = 0;
2145  WCHAR *srcW = NULL, *dstW = NULL;
2146 
2147  if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
2148  {
2150  return 0;
2151  }
2152 
2154  src, srclen, NULL, 0);
2155  srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
2156 
2157  if (!srcW)
2158  {
2160  goto FoldStringA_exit;
2161  }
2162 
2164  src, srclen, srcW, srclenW);
2165 
2167 
2168  ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0);
2169  if (ret && dstlen)
2170  {
2171  dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
2172 
2173  if (!dstW)
2174  {
2176  goto FoldStringA_exit;
2177  }
2178 
2179  ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret);
2180  if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
2181  {
2182  ret = 0;
2184  }
2185  }
2186 
2187  HeapFree(GetProcessHeap(), 0, dstW);
2188 
2189 FoldStringA_exit:
2190  HeapFree(GetProcessHeap(), 0, srcW);
2191  return ret;
2192 }
2193 
2194 /*************************************************************************
2195  * FoldStringW (KERNEL32.@)
2196  *
2197  * See FoldStringA.
2198  */
2200  LPWSTR dst, INT dstlen)
2201 {
2202  int ret;
2203 
2204  switch (dwFlags & (MAP_COMPOSITE|MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES))
2205  {
2206  case 0:
2207  if (dwFlags)
2208  break;
2209  /* Fall through for dwFlags == 0 */
2211  case MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES:
2212  case MAP_COMPOSITE|MAP_EXPAND_LIGATURES:
2214  return 0;
2215  }
2216 
2217  if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
2218  {
2220  return 0;
2221  }
2222 
2224  if (!ret)
2226  return ret;
2227 }
2228 
2229 /******************************************************************************
2230  * CompareStringEx (KERNEL32.@)
2231  */
2234 {
2237  DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
2238  /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
2239  INT ret;
2240  static int once;
2241 
2242  if (version) FIXME("unexpected version parameter\n");
2243  if (reserved) FIXME("unexpected reserved value\n");
2244  if (lParam) FIXME("unexpected lParam\n");
2245 
2246  if (!str1 || !str2)
2247  {
2249  return 0;
2250  }
2251 
2252  if (flags & ~(supported_flags|semistub_flags))
2253  {
2255  return 0;
2256  }
2257 
2258  if (flags & semistub_flags)
2259  {
2260  if (!once++)
2261  FIXME("semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags);
2262  }
2263 
2264  if (len1 < 0) len1 = strlenW(str1);
2265  if (len2 < 0) len2 = strlenW(str2);
2266 
2267  ret = wine_compare_string(flags, str1, len1, str2, len2);
2268 
2269  if (ret) /* need to translate result */
2270  return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
2271  return CSTR_EQUAL;
2272 }
2273 
2274 /******************************************************************************
2275  * CompareStringW (KERNEL32.@)
2276  *
2277  * See CompareStringA.
2278  */
2280  LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
2281 {
2282  return CompareStringEx(NULL, flags, str1, len1, str2, len2, NULL, NULL, 0);
2283 }
2284 
2285 /******************************************************************************
2286  * CompareStringA (KERNEL32.@)
2287  *
2288  * Compare two locale sensitive strings.
2289  *
2290  * PARAMS
2291  * lcid [I] LCID for the comparison
2292  * flags [I] Flags for the comparison (NORM_ constants from "winnls.h").
2293  * str1 [I] First string to compare
2294  * len1 [I] Length of str1, or -1 if str1 is NUL terminated
2295  * str2 [I] Second string to compare
2296  * len2 [I] Length of str2, or -1 if str2 is NUL terminated
2297  *
2298  * RETURNS
2299  * Success: CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN depending on whether
2300  * str1 is less than, equal to or greater than str2 respectively.
2301  * Failure: FALSE. Use GetLastError() to determine the cause.
2302  */
2304  LPCSTR str1, INT len1, LPCSTR str2, INT len2)
2305 {
2306  WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
2307  WCHAR *buf2W = buf1W + 130;
2308  LPWSTR str1W, str2W;
2309  INT len1W = 0, len2W = 0, ret;
2310  UINT locale_cp = CP_ACP;
2311 
2312  if (!str1 || !str2)
2313  {
2315  return 0;
2316  }
2317  if (len1 < 0) len1 = strlen(str1);
2318  if (len2 < 0) len2 = strlen(str2);
2319 
2320  if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
2321 
2322  if (len1)
2323  {
2324  if (len1 <= 130) len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
2325  if (len1W)
2326  str1W = buf1W;
2327  else
2328  {
2329  len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0);
2330  str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
2331  if (!str1W)
2332  {
2334  return 0;
2335  }
2336  MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
2337  }
2338  }
2339  else
2340  {
2341  len1W = 0;
2342  str1W = buf1W;
2343  }
2344 
2345  if (len2)
2346  {
2347  if (len2 <= 130) len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
2348  if (len2W)
2349  str2W = buf2W;
2350  else
2351  {
2352  len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0);
2353  str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
2354  if (!str2W)
2355  {
2356  if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
2358  return 0;
2359  }
2360  MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W);
2361  }
2362  }
2363  else
2364  {
2365  len2W = 0;
2366  str2W = buf2W;
2367  }
2368 
2369  ret = CompareStringEx(NULL, flags, str1W, len1W, str2W, len2W, NULL, NULL, 0);
2370 
2371  if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
2372  if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
2373  return ret;
2374 }
2375 
2376 #ifdef __REACTOS__
2377 HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
2378 #else
2379 static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
2380 #endif
2381 {
2382  UNICODE_STRING keyName;
2384  HANDLE hkey;
2385 
2386  RtlInitUnicodeString( &keyName, szKeyName );
2387 #ifdef __REACTOS__
2388  InitializeObjectAttributes(&attr, &keyName, OBJ_CASE_INSENSITIVE, hRootKey, NULL);
2389 #else
2390  InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
2391 #endif
2392 
2393  if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
2394  hkey = 0;
2395 
2396  return hkey;
2397 }
2398 
2399 #ifdef __REACTOS__
2401  LPWSTR szValueName, ULONG valueNameSize,
2402  LPWSTR szValueData, ULONG valueDataSize)
2403 #else
2405  LPWSTR szValueName, ULONG valueNameSize,
2406  LPWSTR szValueData, ULONG valueDataSize)
2407 #endif
2408 {
2409  BYTE buffer[80];
2411  DWORD dwLen;
2412 
2414  buffer, sizeof(buffer), &dwLen ) != STATUS_SUCCESS ||
2415  info->NameLength > valueNameSize ||
2416  info->DataLength > valueDataSize)
2417  {
2418  return FALSE;
2419  }
2420 
2421  TRACE("info->Name %s info->DataLength %d\n", debugstr_w(info->Name), info->DataLength);
2422 
2423  memcpy( szValueName, info->Name, info->NameLength);
2424  szValueName[info->NameLength / sizeof(WCHAR)] = '\0';
2425  memcpy( szValueData, buffer + info->DataOffset, info->DataLength );
2426  szValueData[info->DataLength / sizeof(WCHAR)] = '\0';
2427 
2428  TRACE("returning %s %s\n", debugstr_w(szValueName), debugstr_w(szValueData));
2429  return TRUE;
2430 }
2431 
2432 static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
2433 {
2434  BYTE buffer[128];
2436  DWORD dwSize = sizeof(buffer);
2437  UNICODE_STRING valueName;
2438 
2439  RtlInitUnicodeString( &valueName, szValueName );
2440 
2441  TRACE("%p, %s\n", hKey, debugstr_w(szValueName));
2443  buffer, dwSize, &dwSize ) == STATUS_SUCCESS &&
2444  info->DataLength == sizeof(DWORD))
2445  {
2446  memcpy(lpVal, info->Data, sizeof(DWORD));
2447  return TRUE;
2448  }
2449 
2450  return FALSE;
2451 }
2452 
2454 {
2455  LANGID langId;
2456  LPCWSTR szResourceName = MAKEINTRESOURCEW(((lgrpid + 0x2000) >> 4) + 1);
2457  HRSRC hResource;
2458  BOOL bRet = FALSE;
2459 
2460  /* FIXME: Is it correct to use the system default langid? */
2461  langId = GetSystemDefaultLangID();
2462 
2463  if (SUBLANGID(langId) == SUBLANG_NEUTRAL)
2464  langId = MAKELANGID( PRIMARYLANGID(langId), SUBLANG_DEFAULT );
2465 
2466  hResource = FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, szResourceName, langId );
2467 
2468  if (hResource)
2469  {
2470  HGLOBAL hResDir = LoadResource( kernel32_handle, hResource );
2471 
2472  if (hResDir)
2473  {
2474  ULONG iResourceIndex = lgrpid & 0xf;
2475  LPCWSTR lpResEntry = LockResource( hResDir );
2476  ULONG i;
2477 
2478  for (i = 0; i < iResourceIndex; i++)
2479  lpResEntry += *lpResEntry + 1;
2480 
2481  if (*lpResEntry < nameSize)
2482  {
2483  memcpy( szName, lpResEntry + 1, *lpResEntry * sizeof(WCHAR) );
2484  szName[*lpResEntry] = '\0';
2485  bRet = TRUE;
2486  }
2487 
2488  }
2489  FreeResource( hResource );
2490  }
2491  return bRet;
2492 }
2493 
2494 /* Callback function ptrs for EnumSystemLanguageGroupsA/W */
2495 typedef struct
2496 {
2502 
2503 /* Internal implementation of EnumSystemLanguageGroupsA/W */
2505 {
2506  WCHAR szNumber[10], szValue[4];
2507  HANDLE hKey;
2508  BOOL bContinue = TRUE;
2509  ULONG ulIndex = 0;
2510 
2511  if (!lpProcs)
2512  {
2514  return FALSE;
2515  }
2516 
2517  switch (lpProcs->dwFlags)
2518  {
2519  case 0:
2520  /* Default to LGRPID_INSTALLED */
2521  lpProcs->dwFlags = LGRPID_INSTALLED;
2522  /* Fall through... */
2523  case LGRPID_INSTALLED:
2524  case LGRPID_SUPPORTED:
2525  break;
2526  default:
2528  return FALSE;
2529  }
2530 
2532 
2533  if (!hKey)
2534  FIXME("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
2535 
2536  while (bContinue)
2537  {
2538  if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
2539  szValue, sizeof(szValue) ))
2540  {
2541  BOOL bInstalled = szValue[0] == '1';
2542  LGRPID lgrpid = strtoulW( szNumber, NULL, 16 );
2543 
2544  TRACE("grpid %s (%sinstalled)\n", debugstr_w(szNumber),
2545  bInstalled ? "" : "not ");
2546 
2547  if (lpProcs->dwFlags == LGRPID_SUPPORTED || bInstalled)
2548  {
2549  WCHAR szGrpName[48];
2550 
2551  if (!NLS_GetLanguageGroupName( lgrpid, szGrpName, sizeof(szGrpName) / sizeof(WCHAR) ))
2552  szGrpName[0] = '\0';
2553 
2554  if (lpProcs->procW)
2555  bContinue = lpProcs->procW( lgrpid, szNumber, szGrpName, lpProcs->dwFlags,
2556  lpProcs->lParam );
2557  else
2558  {
2559  char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
2560  char szGrpNameA[48];
2561 
2562  /* FIXME: MSDN doesn't say which code page the W->A translation uses,
2563  * or whether the language names are ever localised. Assume CP_ACP.
2564  */
2565 
2566  WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
2567  WideCharToMultiByte(CP_ACP, 0, szGrpName, -1, szGrpNameA, sizeof(szGrpNameA), 0, 0);
2568 
2569  bContinue = lpProcs->procA( lgrpid, szNumberA, szGrpNameA, lpProcs->dwFlags,
2570  lpProcs->lParam );
2571  }
2572  }
2573 
2574  ulIndex++;
2575  }
2576  else
2577  bContinue = FALSE;
2578 
2579  if (!bContinue)
2580  break;
2581  }
2582 
2583  if (hKey)
2584  NtClose( hKey );
2585 
2586  return TRUE;
2587 }
2588 
2589 /******************************************************************************
2590  * EnumSystemLanguageGroupsA (KERNEL32.@)
2591  *
2592  * Call a users function for each language group available on the system.
2593  *
2594  * PARAMS
2595  * pLangGrpEnumProc [I] Callback function to call for each language group
2596  * dwFlags [I] LGRPID_SUPPORTED=All Supported, LGRPID_INSTALLED=Installed only
2597  * lParam [I] User parameter to pass to pLangGrpEnumProc
2598  *
2599  * RETURNS
2600  * Success: TRUE.
2601  * Failure: FALSE. Use GetLastError() to determine the cause.
2602  */
2605 {
2607 
2608  TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
2609 
2610  procs.procA = pLangGrpEnumProc;
2611  procs.procW = NULL;
2612  procs.dwFlags = dwFlags;
2613  procs.lParam = lParam;
2614 
2615  return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
2616 }
2617 
2618 /******************************************************************************
2619  * EnumSystemLanguageGroupsW (KERNEL32.@)
2620  *
2621  * See EnumSystemLanguageGroupsA.
2622  */
2625 {
2627 
2628  TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
2629 
2630  procs.procA = NULL;
2631  procs.procW = pLangGrpEnumProc;
2632  procs.dwFlags = dwFlags;
2633  procs.lParam = lParam;
2634 
2635  return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
2636 }
2637 
2638 /******************************************************************************
2639  * IsValidLanguageGroup (KERNEL32.@)
2640  *
2641  * Determine if a language group is supported and/or installed.
2642  *
2643  * PARAMS
2644  * lgrpid [I] Language Group Id (LGRPID_ values from "winnls.h")
2645  * dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed
2646  *
2647  * RETURNS
2648  * TRUE, if lgrpid is supported and/or installed, according to dwFlags.
2649  * FALSE otherwise.
2650  */
2652 {
2653  static const WCHAR szFormat[] = { '%','x','\0' };
2654  WCHAR szValueName[16], szValue[2];
2655  BOOL bSupported = FALSE, bInstalled = FALSE;
2656  HANDLE hKey;
2657 
2658 
2659  switch (dwFlags)
2660  {
2661  case LGRPID_INSTALLED:
2662  case LGRPID_SUPPORTED:
2663 
2665 
2666  sprintfW( szValueName, szFormat, lgrpid );
2667 
2668  if (NLS_RegGetDword( hKey, szValueName, (LPDWORD)szValue ))
2669  {
2670  bSupported = TRUE;
2671 
2672  if (szValue[0] == '1')
2673  bInstalled = TRUE;
2674  }
2675 
2676  if (hKey)
2677  NtClose( hKey );
2678 
2679  break;
2680  }
2681 
2682  if ((dwFlags == LGRPID_SUPPORTED && bSupported) ||
2683  (dwFlags == LGRPID_INSTALLED && bInstalled))
2684  return TRUE;
2685 
2686  return FALSE;
2687 }
2688 
2689 /* Callback function ptrs for EnumLanguageGrouplocalesA/W */
2690 typedef struct
2691 {
2698 
2699 /* Internal implementation of EnumLanguageGrouplocalesA/W */
2701 {
2702  static const WCHAR szAlternateSortsKeyName[] = {
2703  'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s','\0'
2704  };
2705  WCHAR szNumber[10], szValue[4];
2706  HANDLE hKey;
2707  BOOL bContinue = TRUE, bAlternate = FALSE;
2708  LGRPID lgrpid;
2709  ULONG ulIndex = 1; /* Ignore default entry of 1st key */
2710 
2711  if (!lpProcs || !lpProcs->lgrpid || lpProcs->lgrpid > LGRPID_ARMENIAN)
2712  {
2714  return FALSE;
2715  }
2716 
2717  if (lpProcs->dwFlags)
2718  {
2720  return FALSE;
2721  }
2722 
2724 
2725  if (!hKey)
2726  WARN("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
2727 
2728  while (bContinue)
2729  {
2730  if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
2731  szValue, sizeof(szValue) ))
2732  {
2733  lgrpid = strtoulW( szValue, NULL, 16 );
2734 
2735  TRACE("lcid %s, grpid %d (%smatched)\n", debugstr_w(szNumber),
2736  lgrpid, lgrpid == lpProcs->lgrpid ? "" : "not ");
2737 
2738  if (lgrpid == lpProcs->lgrpid)
2739  {
2740  LCID lcid;
2741 
2742  lcid = strtoulW( szNumber, NULL, 16 );
2743 
2744  /* FIXME: native returns extra text for a few (17/150) locales, e.g:
2745  * '00000437 ;Georgian'
2746  * At present we only pass the LCID string.
2747  */
2748 
2749  if (lpProcs->procW)
2750  bContinue = lpProcs->procW( lgrpid, lcid, szNumber, lpProcs->lParam );
2751  else
2752  {
2753  char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
2754 
2755  WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
2756 
2757  bContinue = lpProcs->procA( lgrpid, lcid, szNumberA, lpProcs->lParam );
2758  }
2759  }
2760 
2761  ulIndex++;
2762  }
2763  else
2764  {
2765  /* Finished enumerating this key */
2766  if (!bAlternate)
2767  {
2768  /* Enumerate alternate sorts also */
2769  hKey = NLS_RegOpenKey( hKey, szAlternateSortsKeyName );
2770  bAlternate = TRUE;
2771  ulIndex = 0;
2772  }
2773  else
2774  bContinue = FALSE; /* Finished both keys */
2775  }
2776 
2777  if (!bContinue)
2778  break;
2779  }
2780 
2781  if (hKey)
2782  NtClose( hKey );
2783 
2784  return TRUE;
2785 }
2786 
2791 };
2792 
2793 struct geoinfo_t {
2800 };
2801 
2802 static const struct geoinfo_t geoinfodata[] = {
2803  { 2, {'A','G',0}, {'A','T','G',0}, 10039880, 28 }, /* Antigua and Barbuda */
2804  { 3, {'A','F',0}, {'A','F','G',0}, 47614, 4 }, /* Afghanistan */
2805  { 4, {'D','Z',0}, {'D','Z','A',0}, 42487, 12 }, /* Algeria */
2806  { 5, {'A','Z',0}, {'A','Z','E',0}, 47611, 31 }, /* Azerbaijan */
2807  { 6, {'A','L',0}, {'A','L','B',0}, 47610, 8 }, /* Albania */
2808  { 7, {'A','M',0}, {'A','R','M',0}, 47611, 51 }, /* Armenia */
2809  { 8, {'A','D',0}, {'A','N','D',0}, 47610, 20 }, /* Andorra */
2810  { 9, {'A','O',0}, {'A','G','O',0}, 42484, 24 }, /* Angola */
2811  { 10, {'A','S',0}, {'A','S','M',0}, 26286, 16 }, /* American Samoa */
2812  { 11, {'A','R',0}, {'A','R','G',0}, 31396, 32 }, /* Argentina */
2813  { 12, {'A','U',0}, {'A','U','S',0}, 10210825, 36 }, /* Australia */
2814  { 14, {'A','T',0}, {'A','U','T',0}, 10210824, 40 }, /* Austria */
2815  { 17, {'B','H',0}, {'B','H','R',0}, 47611, 48 }, /* Bahrain */
2816  { 18, {'B','B',0}, {'B','R','B',0}, 10039880, 52 }, /* Barbados */
2817  { 19, {'B','W',0}, {'B','W','A',0}, 10039883, 72 }, /* Botswana */
2818  { 20, {'B','M',0}, {'B','M','U',0}, 23581, 60 }, /* Bermuda */
2819  { 21, {'B','E',0}, {'B','E','L',0}, 10210824, 56 }, /* Belgium */
2820  { 22, {'B','S',0}, {'B','H','S',0}, 10039880, 44 }, /* Bahamas, The */
2821  { 23, {'B','D',0}, {'B','G','D',0}, 47614, 50 }, /* Bangladesh */
2822  { 24, {'B','Z',0}, {'B','L','Z',0}, 27082, 84 }, /* Belize */
2823  { 25, {'B','A',0}, {'B','I','H',0}, 47610, 70 }, /* Bosnia and Herzegovina */
2824  { 26, {'B','O',0}, {'B','O','L',0}, 31396, 68 }, /* Bolivia */
2825  { 27, {'M','M',0}, {'M','M','R',0}, 47599, 104 }, /* Myanmar */
2826  { 28, {'B','J',0}, {'B','E','N',0}, 42483, 204 }, /* Benin */
2827  { 29, {'B','Y',0}, {'B','L','R',0}, 47609, 112 }, /* Belarus */
2828  { 30, {'S','B',0}, {'S','L','B',0}, 20900, 90 }, /* Solomon Islands */
2829  { 32, {'B','R',0}, {'B','R','A',0}, 31396, 76 }, /* Brazil */
2830  { 34, {'B','T',0}, {'B','T','N',0}, 47614, 64 }, /* Bhutan */
2831  { 35, {'B','G',0}, {'B','G','R',0}, 47609, 100 }, /* Bulgaria */
2832  { 37, {'B','N',0}, {'B','R','N',0}, 47599, 96 }, /* Brunei */
2833  { 38, {'B','I',0}, {'B','D','I',0}, 47603, 108 }, /* Burundi */
2834  { 39, {'C','A',0}, {'C','A','N',0}, 23581, 124 }, /* Canada */
2835  { 40, {'K','H',0}, {'K','H','M',0}, 47599, 116 }, /* Cambodia */
2836  { 41, {'T','D',0}, {'T','C','D',0}, 42484, 148 }, /* Chad */
2837  { 42, {'L','K',0}, {'L','K','A',0}, 47614, 144 }, /* Sri Lanka */
2838  { 43, {'C','G',0}, {'C','O','G',0}, 42484, 178 }, /* Congo */
2839  { 44, {'C','D',0}, {'C','O','D',0}, 42484, 180 }, /* Congo (DRC) */
2840  { 45, {'C','N',0}, {'C','H','N',0}, 47600, 156 }, /* China */
2841  { 46, {'C','L',0}, {'C','H','L',0}, 31396, 152 }, /* Chile */
2842  { 49, {'C','M',0}, {'C','M','R',0}, 42484, 120 }, /* Cameroon */
2843  { 50, {'K','M',0}, {'C','O','M',0}, 47603, 174 }, /* Comoros */
2844  { 51, {'C','O',0}, {'C','O','L',0}, 31396, 170 }, /* Colombia */
2845  { 54, {'C','R',0}, {'C','R','I',0}, 27082, 188 }, /* Costa Rica */
2846  { 55, {'C','F',0}, {'C','A','F',0}, 42484, 140 }, /* Central African Republic */
2847  { 56, {'C','U',0}, {'C','U','B',0}, 10039880, 192 }, /* Cuba */
2848  { 57, {'C','V',0}, {'C','P','V',0}, 42483, 132 }, /* Cape Verde */
2849  { 59, {'C','Y',0}, {'C','Y','P',0}, 47611, 196 }, /* Cyprus */
2850  { 61, {'D','K',0}, {'D','N','K',0}, 10039882, 208 }, /* Denmark */
2851  { 62, {'D','J',0}, {'D','J','I',0}, 47603, 262 }, /* Djibouti */
2852  { 63, {'D','M',0}, {'D','M','A',0}, 10039880, 212 }, /* Dominica */
2853  { 65, {'D','O',0}, {'D','O','M',0}, 10039880, 214 }, /* Dominican Republic */
2854  { 66, {'E','C',0}, {'E','C','U',0}, 31396, 218 }, /* Ecuador */
2855  { 67, {'E','G',0}, {'E','G','Y',0}, 42487, 818 }, /* Egypt */
2856  { 68, {'I','E',0}, {'I','R','L',0}, 10039882, 372 }, /* Ireland */
2857  { 69, {'G','Q',0}, {'G','N','Q',0}, 42484, 226 }, /* Equatorial Guinea */
2858  { 70, {'E','E',0}, {'E','S','T',0}, 10039882, 233 }, /* Estonia */
2859  { 71, {'E','R',0}, {'E','R','I',0}, 47603, 232 }, /* Eritrea */
2860  { 72, {'S','V',0}, {'S','L','V',0}, 27082, 222 }, /* El Salvador */
2861  { 73, {'E','T',0}, {'E','T','H',0}, 47603, 231 }, /* Ethiopia */
2862  { 75, {'C','Z',0}, {'C','Z','E',0}, 47609, 203 }, /* Czech Republic */
2863  { 77, {'F','I',0}, {'F','I','N',0}, 10039882, 246 }, /* Finland */
2864  { 78, {'F','J',0}, {'F','J','I',0}, 20900, 242 }, /* Fiji Islands */
2865  { 80, {'F','M',0}, {'F','S','M',0}, 21206, 583 }, /* Micronesia */
2866  { 81, {'F','O',0}, {'F','R','O',0}, 10039882, 234 }, /* Faroe Islands */
2867  { 84, {'F','R',0}, {'F','R','A',0}, 10210824, 250 }, /* France */
2868  { 86, {'G','M',0}, {'G','M','B',0}, 42483, 270 }, /* Gambia, The */
2869  { 87, {'G','A',0}, {'G','A','B',0}, 42484, 266 }, /* Gabon */
2870  { 88, {'G','E',0}, {'G','E','O',0}, 47611, 268 }, /* Georgia */
2871  { 89, {'G','H',0}, {'G','H','A',0}, 42483, 288 }, /* Ghana */
2872  { 90, {'G','I',0}, {'G','I','B',0}, 47610, 292 }, /* Gibraltar */
2873  { 91, {'G','D',0}, {'G','R','D',0}, 10039880, 308 }, /* Grenada */
2874  { 93, {'G','L',0}, {'G','R','L',0}, 23581, 304 }, /* Greenland */
2875  { 94, {'D','E',0}, {'D','E','U',0}, 10210824, 276 }, /* Germany */
2876  { 98, {'G','R',0}, {'G','R','C',0}, 47610, 300 }, /* Greece */
2877  { 99, {'G','T',0}, {'G','T','M',0}, 27082, 320 }, /* Guatemala */
2878  { 100, {'G','N',0}, {'G','I','N',0}, 42483, 324 }, /* Guinea */
2879  { 101, {'G','Y',0}, {'G','U','Y',0}, 31396, 328 }, /* Guyana */
2880  { 103, {'H','T',0}, {'H','T','I',0}, 10039880, 332 }, /* Haiti */
2881  { 104, {'H','K',0}, {'H','K','G',0}, 47600, 344 }, /* Hong Kong S.A.R. */
2882  { 106, {'H','N',0}, {'H','N','D',0}, 27082, 340 }, /* Honduras */
2883  { 108, {'H','R',0}, {'H','R','V',0}, 47610, 191 }, /* Croatia */
2884  { 109, {'H','U',0}, {'H','U','N',0}, 47609, 348 }, /* Hungary */
2885  { 110, {'I','S',0}, {'I','S','L',0}, 10039882, 352 }, /* Iceland */
2886  { 111, {'I','D',0}, {'I','D','N',0}, 47599, 360 }, /* Indonesia */
2887  { 113, {'I','N',0}, {'I','N','D',0}, 47614, 356 }, /* India */
2888  { 114, {'I','O',0}, {'I','O','T',0}, 39070, 86 }, /* British Indian Ocean Territory */
2889  { 116, {'I','R',0}, {'I','R','N',0}, 47614, 364 }, /* Iran */
2890  { 117, {'I','L',0}, {'I','S','R',0}, 47611, 376 }, /* Israel */
2891  { 118, {'I','T',0}, {'I','T','A',0}, 47610, 380 }, /* Italy */
2892  { 119, {'C','I',0}, {'C','I','V',0}, 42483, 384 }, /* Côte d'Ivoire */
2893  { 121, {'I','Q',0}, {'I','R','Q',0}, 47611, 368 }, /* Iraq */
2894  { 122, {'J','P',0}, {'J','P','N',0}, 47600, 392 }, /* Japan */
2895  { 124, {'J','M',0}, {'J','A','M',0}, 10039880, 388 }, /* Jamaica */
2896  { 125, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Jan Mayen */
2897  { 126, {'J','O',0}, {'J','O','R',0}, 47611, 400 }, /* Jordan */
2898  { 127, {'X','X',0}, {'X','X',0}, 161832256 }, /* Johnston Atoll */
2899  { 129, {'K','E',0}, {'K','E','N',0}, 47603, 404 }, /* Kenya */
2900  { 130, {'K','G',0}, {'K','G','Z',0}, 47590, 417 }, /* Kyrgyzstan */
2901  { 131, {'K','P',0}, {'P','R','K',0}, 47600, 408 }, /* North Korea */
2902  { 133, {'K','I',0}, {'K','I','R',0}, 21206, 296 }, /* Kiribati */
2903  { 134, {'K','R',0}, {'K','O','R',0}, 47600, 410 }, /* Korea */
2904  { 136, {'K','W',0}, {'K','W','T',0}, 47611, 414 }, /* Kuwait */
2905  { 137, {'K','Z',0}, {'K','A','Z',0}, 47590, 398 }, /* Kazakhstan */
2906  { 138, {'L','A',0}, {'L','A','O',0}, 47599, 418 }, /* Laos */
2907  { 139, {'L','B',0}, {'L','B','N',0}, 47611, 422 }, /* Lebanon */
2908  { 140, {'L','V',0}, {'L','V','A',0}, 10039882, 428 }, /* Latvia */
2909  { 141, {'L','T',0}, {'L','T','U',0}, 10039882, 440 }, /* Lithuania */
2910  { 142, {'L','R',0}, {'L','B','R',0}, 42483, 430 }, /* Liberia */
2911  { 143, {'S','K',0}, {'S','V','K',0}, 47609, 703 }, /* Slovakia */
2912  { 145, {'L','I',0}, {'L','I','E',0}, 10210824, 438 }, /* Liechtenstein */
2913  { 146, {'L','S',0}, {'L','S','O',0}, 10039883, 426 }, /* Lesotho */
2914  { 147, {'L','U',0}, {'L','U','X',0}, 10210824, 442 }, /* Luxembourg */
2915  { 148, {'L','Y',0}, {'L','B','Y',0}, 42487, 434 }, /* Libya */
2916  { 149, {'M','G',0}, {'M','D','G',0}, 47603, 450 }, /* Madagascar */
2917  { 151, {'M','O',0}, {'M','A','C',0}, 47600, 446 }, /* Macao S.A.R. */
2918  { 152, {'M','D',0}, {'M','D','A',0}, 47609, 498 }, /* Moldova */
2919  { 154, {'M','N',0}, {'M','N','G',0}, 47600, 496 }, /* Mongolia */
2920  { 156, {'M','W',0}, {'M','W','I',0}, 47603, 454 }, /* Malawi */
2921  { 157, {'M','L',0}, {'M','L','I',0}, 42483, 466 }, /* Mali */
2922  { 158, {'M','C',0}, {'M','C','O',0}, 10210824, 492 }, /* Monaco */
2923  { 159, {'M','A',0}, {'M','A','R',0}, 42487, 504 }, /* Morocco */
2924  { 160, {'M','U',0}, {'M','U','S',0}, 47603, 480 }, /* Mauritius */
2925  { 162, {'M','R',0}, {'M','R','T',0}, 42483, 478 }, /* Mauritania */
2926  { 163, {'M','T',0}, {'M','L','T',0}, 47610, 470 }, /* Malta */
2927  { 164, {'O','M',0}, {'O','M','N',0}, 47611, 512 }, /* Oman */
2928  { 165, {'M','V',0}, {'M','D','V',0}, 47614, 462 }, /* Maldives */
2929  { 166, {'M','X',0}, {'M','E','X',0}, 27082, 484 }, /* Mexico */
2930  { 167, {'M','Y',0}, {'M','Y','S',0}, 47599, 458 }, /* Malaysia */
2931  { 168, {'M','Z',0}, {'M','O','Z',0}, 47603, 508 }, /* Mozambique */
2932  { 173, {'N','E',0}, {'N','E','R',0}, 42483, 562 }, /* Niger */
2933  { 174, {'V','U',0}, {'V','U','T',0}, 20900, 548 }, /* Vanuatu */
2934  { 175, {'N','G',0}, {'N','G','A',0}, 42483, 566 }, /* Nigeria */
2935  { 176, {'N','L',0}, {'N','L','D',0}, 10210824, 528 }, /* Netherlands */
2936  { 177, {'N','O',0}, {'N','O','R',0}, 10039882, 578 }, /* Norway */
2937  { 178, {'N','P',0}, {'N','P','L',0}, 47614, 524 }, /* Nepal */
2938  { 180, {'N','R',0}, {'N','R','U',0}, 21206, 520 }, /* Nauru */
2939  { 181, {'S','R',0}, {'S','U','R',0}, 31396, 740 }, /* Suriname */
2940  { 182, {'N','I',0}, {'N','I','C',0}, 27082, 558 }, /* Nicaragua */
2941  { 183, {'N','Z',0}, {'N','Z','L',0}, 10210825, 554 }, /* New Zealand */
2942  { 184, {'P','S',0}, {'P','S','E',0}, 47611, 275 }, /* Palestinian Authority */
2943  { 185, {'P','Y',0}, {'P','R','Y',0}, 31396, 600 }, /* Paraguay */
2944  { 187, {'P','E',0}, {'P','E','R',0}, 31396, 604 }, /* Peru */
2945  { 190, {'P','K',0}, {'P','A','K',0}, 47614, 586 }, /* Pakistan */
2946  { 191, {'P','L',0}, {'P','O','L',0}, 47609, 616 }, /* Poland */
2947  { 192, {'P','A',0}, {'P','A','N',0}, 27082, 591 }, /* Panama */
2948  { 193, {'P','T',0}, {'P','R','T',0}, 47610, 620 }, /* Portugal */
2949  { 194, {'P','G',0}, {'P','N','G',0}, 20900, 598 }, /* Papua New Guinea */
2950  { 195, {'P','W',0}, {'P','L','W',0}, 21206, 585 }, /* Palau */
2951  { 196, {'G','W',0}, {'G','N','B',0}, 42483, 624 }, /* Guinea-Bissau */
2952  { 197, {'Q','A',0}, {'Q','A','T',0}, 47611, 634 }, /* Qatar */
2953  { 198, {'R','E',0}, {'R','E','U',0}, 47603, 638 }, /* Reunion */
2954  { 199, {'M','H',0}, {'M','H','L',0}, 21206, 584 }, /* Marshall Islands */
2955  { 200, {'R','O',0}, {'R','O','U',0}, 47609, 642 }, /* Romania */
2956  { 201, {'P','H',0}, {'P','H','L',0}, 47599, 608 }, /* Philippines */
2957  { 202, {'P','R',0}, {'P','R','I',0}, 10039880, 630 }, /* Puerto Rico */
2958  { 203, {'R','U',0}, {'R','U','S',0}, 47609, 643 }, /* Russia */
2959  { 204, {'R','W',0}, {'R','W','A',0}, 47603, 646 }, /* Rwanda */
2960  { 205, {'S','A',0}, {'S','A','U',0}, 47611, 682 }, /* Saudi Arabia */
2961  { 206, {'P','M',0}, {'S','P','M',0}, 23581, 666 }, /* St. Pierre and Miquelon */
2962  { 207, {'K','N',0}, {'K','N','A',0}, 10039880, 659 }, /* St. Kitts and Nevis */
2963  { 208, {'S','C',0}, {'S','Y','C',0}, 47603, 690 }, /* Seychelles */
2964  { 209, {'Z','A',0}, {'Z','A','F',0}, 10039883, 710 }, /* South Africa */
2965  { 210, {'S','N',0}, {'S','E','N',0}, 42483, 686 }, /* Senegal */
2966  { 212, {'S','I',0}, {'S','V','N',0}, 47610, 705 }, /* Slovenia */
2967  { 213, {'S','L',0}, {'S','L','E',0}, 42483, 694 }, /* Sierra Leone */
2968  { 214, {'S','M',0}, {'S','M','R',0}, 47610, 674 }, /* San Marino */
2969  { 215, {'S','G',0}, {'S','G','P',0}, 47599, 702 }, /* Singapore */
2970  { 216, {'S','O',0}, {'S','O','M',0}, 47603, 706 }, /* Somalia */
2971  { 217, {'E','S',0}, {'E','S','P',0}, 47610, 724 }, /* Spain */
2972  { 218, {'L','C',0}, {'L','C','A',0}, 10039880, 662 }, /* St. Lucia */
2973  { 219, {'S','D',0}, {'S','D','N',0}, 42487, 736 }, /* Sudan */
2974  { 220, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Svalbard */
2975  { 221, {'S','E',0}, {'S','W','E',0}, 10039882, 752 }, /* Sweden */
2976  { 222, {'S','Y',0}, {'S','Y','R',0}, 47611, 760 }, /* Syria */
2977  { 223, {'C','H',0}, {'C','H','E',0}, 10210824, 756 }, /* Switzerland */
2978  { 224, {'A','E',0}, {'A','R','E',0}, 47611, 784 }, /* United Arab Emirates */
2979  { 225, {'T','T',0}, {'T','T','O',0}, 10039880, 780 }, /* Trinidad and Tobago */
2980  { 227, {'T','H',0}, {'T','H','A',0}, 47599, 764 }, /* Thailand */
2981  { 228, {'T','J',0}, {'T','J','K',0}, 47590, 762 }, /* Tajikistan */
2982  { 231, {'T','O',0}, {'T','O','N',0}, 26286, 776 }, /* Tonga */
2983  { 232, {'T','G',0}, {'T','G','O',0}, 42483, 768 }, /* Togo */
2984  { 233, {'S','T',0}, {'S','T','P',0}, 42484, 678 }, /* São Tomé and Príncipe */
2985  { 234, {'T','N',0}, {'T','U','N',0}, 42487, 788 }, /* Tunisia */
2986  { 235, {'T','R',0}, {'T','U','R',0}, 47611, 792 }, /* Turkey */
2987  { 236, {'T','V',0}, {'T','U','V',0}, 26286, 798 }, /* Tuvalu */
2988  { 237, {'T','W',0}, {'T','W','N',0}, 47600, 158 }, /* Taiwan */
2989  { 238, {'T','M',0}, {'T','K','M',0}, 47590, 795 }, /* Turkmenistan */
2990  { 239, {'T','Z',0}, {'T','Z','A',0}, 47603, 834 }, /* Tanzania */
2991  { 240, {'U','G',0}, {'U','G','A',0}, 47603, 800 }, /* Uganda */
2992  { 241, {'U','A',0}, {'U','K','R',0}, 47609, 804 }, /* Ukraine */
2993  { 242, {'G','B',0}, {'G','B','R',0}, 10039882, 826 }, /* United Kingdom */
2994  { 244, {'U','S',0}, {'U','S','A',0}, 23581, 840 }, /* United States */
2995  { 245, {'B','F',0}, {'B','F','A',0}, 42483, 854 }, /* Burkina Faso */
2996  { 246, {'U','Y',0}, {'U','R','Y',0}, 31396, 858 }, /* Uruguay */
2997  { 247, {'U','Z',0}, {'U','Z','B',0}, 47590, 860 }, /* Uzbekistan */
2998  { 248, {'V','C',0}, {'V','C','T',0}, 10039880, 670 }, /* St. Vincent and the Grenadines */
2999  { 249, {'V','E',0}, {'V','E','N',0}, 31396, 862 }, /* Bolivarian Republic of Venezuela */
3000  { 251, {'V','N',0}, {'V','N','M',0}, 47599, 704 }, /* Vietnam */
3001  { 252, {'V','I',0}, {'V','I','R',0}, 10039880, 850 }, /* Virgin Islands */
3002  { 253, {'V','A',0}, {'V','A','T',0}, 47610, 336 }, /* Vatican City */
3003  { 254, {'N','A',0}, {'N','A','M',0}, 10039883, 516 }, /* Namibia */
3004  { 257, {'E','H',0}, {'E','S','H',0}, 42487, 732 }, /* Western Sahara (disputed) */
3005  { 258, {'X','X',0}, {'X','X',0}, 161832256 }, /* Wake Island */
3006  { 259, {'W','S',0}, {'W','S','M',0}, 26286, 882 }, /* Samoa */
3007  { 260, {'S','Z',0}, {'S','W','Z',0}, 10039883, 748 }, /* Swaziland */
3008  { 261, {'Y','E',0}, {'Y','E','M',0}, 47611, 887 }, /* Yemen */
3009  { 263, {'Z','M',0}, {'Z','M','B',0}, 47603, 894 }, /* Zambia */
3010  { 264, {'Z','W',0}, {'Z','W','E',0}, 47603, 716 }, /* Zimbabwe */
3011  { 269, {'C','S',0}, {'S','C','G',0}, 47610, 891 }, /* Serbia and Montenegro (Former) */
3012  { 270, {'M','E',0}, {'M','N','E',0}, 47610, 499 }, /* Montenegro */
3013  { 271, {'R','S',0}, {'S','R','B',0}, 47610, 688 }, /* Serbia */
3014  { 273, {'C','W',0}, {'C','U','W',0}, 10039880, 531 }, /* Curaçao */
3015  { 276, {'S','S',0}, {'S','S','D',0}, 42487, 728 }, /* South Sudan */
3016  { 300, {'A','I',0}, {'A','I','A',0}, 10039880, 660 }, /* Anguilla */
3017  { 301, {'A','Q',0}, {'A','T','A',0}, 39070, 10 }, /* Antarctica */
3018  { 302, {'A','W',0}, {'A','B','W',0}, 10039880, 533 }, /* Aruba */
3019  { 303, {'X','X',0}, {'X','X',0}, 39070 }, /* Ascension Island */
3020  { 304, {'X','X',0}, {'X','X',0}, 10210825 }, /* Ashmore and Cartier Islands */
3021  { 305, {'X','X',0}, {'X','X',0}, 161832256 }, /* Baker Island */
3022  { 306, {'B','V',0}, {'B','V','T',0}, 39070, 74 }, /* Bouvet Island */
3023  { 307, {'K','Y',0}, {'C','Y','M',0}, 10039880, 136 }, /* Cayman Islands */
3024  { 308, {'X','X',0}, {'X','X',0}, 10210824, 0, LOCATION_BOTH }, /* Channel Islands */
3025  { 309, {'C','X',0}, {'C','X','R',0}, 12, 162 }, /* Christmas Island */
3026  { 310, {'X','X',0}, {'X','X',0}, 27114 }, /* Clipperton Island */
3027  { 311, {'C','C',0}, {'C','C','K',0}, 10210825, 166 }, /* Cocos (Keeling) Islands */
3028  { 312, {'C','K',0}, {'C','O','K',0}, 26286, 184 }, /* Cook Islands */
3029  { 313, {'X','X',0}, {'X','X',0}, 10210825 }, /* Coral Sea Islands */
3030  { 314, {'X','X',0}, {'X','X',0}, 114 }, /* Diego Garcia */
3031  { 315, {'F','K',0}, {'F','L','K',0}, 31396, 238 }, /* Falkland Islands (Islas Malvinas) */
3032  { 317, {'G','F',0}, {'G','U','F',0}, 31396, 254 }, /* French Guiana */
3033  { 318, {'P','F',0}, {'P','Y','F',0}, 26286, 258 }, /* French Polynesia */
3034  { 319, {'T','F',0}, {'A','T','F',0}, 39070, 260 }, /* French Southern and Antarctic Lands */
3035  { 321, {'G','P',0}, {'G','L','P',0}, 10039880, 312 }, /* Guadeloupe */
3036  { 322, {'G','U',0}, {'G','U','M',0}, 21206, 316 }, /* Guam */
3037  { 323, {'X','X',0}, {'X','X',0}, 39070 }, /* Guantanamo Bay */
3038  { 324, {'G','G',0}, {'G','G','Y',0}, 308, 831 }, /* Guernsey */
3039  { 325, {'H','M',0}, {'H','M','D',0}, 39070, 334 }, /* Heard Island and McDonald Islands */
3040  { 326, {'X','X',0}, {'X','X',0}, 161832256 }, /* Howland Island */
3041  { 327, {'X','X',0}, {'X','X',0}, 161832256 }, /* Jarvis Island */
3042  { 328, {'J','E',0}, {'J','E','Y',0}, 308, 832 }, /* Jersey */
3043  { 329, {'X','X',0}, {'X','X',0}, 161832256 }, /* Kingman Reef */
3044  { 330, {'M','Q',0}, {'M','T','Q',0}, 10039880, 474 }, /* Martinique */
3045  { 331, {'Y','T',0}, {'M','Y','T',0}, 47603, 175 }, /* Mayotte */
3046  { 332, {'M','S',0}, {'M','S','R',0}, 10039880, 500 }, /* Montserrat */
3047  { 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530, LOCATION_BOTH }, /* Netherlands Antilles (Former) */
3048  { 334, {'N','C',0}, {'N','C','L',0}, 20900, 540 }, /* New Caledonia */
3049  { 335, {'N','U',0}, {'N','I','U',0}, 26286, 570 }, /* Niue */
3050  { 336, {'N','F',0}, {'N','F','K',0}, 10210825, 574 }, /* Norfolk Island */
3051  { 337, {'M','P',0}, {'M','N','P',0}, 21206, 580 }, /* Northern Mariana Islands */
3052  { 338, {'X','X',0}, {'X','X',0}, 161832256 }, /* Palmyra Atoll */
3053  { 339, {'P','N',0}, {'P','C','N',0}, 26286, 612 }, /* Pitcairn Islands */
3054  { 340, {'X','X',0}, {'X','X',0}, 337 }, /* Rota Island */
3055  { 341, {'X','X',0}, {'X','X',0}, 337 }, /* Saipan */
3056  { 342, {'G','S',0}, {'S','G','S',0}, 39070, 239 }, /* South Georgia and the South Sandwich Islands */
3057  { 343, {'S','H',0}, {'S','H','N',0}, 42483, 654 }, /* St. Helena */
3058  { 346, {'X','X',0}, {'X','X',0}, 337 }, /* Tinian Island */
3059  { 347, {'T','K',0}, {'T','K','L',0}, 26286, 772 }, /* Tokelau */
3060  { 348, {'X','X',0}, {'X','X',0}, 39070 }, /* Tristan da Cunha */
3061  { 349, {'T','C',0}, {'T','C','A',0}, 10039880, 796 }, /* Turks and Caicos Islands */
3062  { 351, {'V','G',0}, {'V','G','B',0}, 10039880, 92 }, /* Virgin Islands, British */
3063  { 352, {'W','F',0}, {'W','L','F',0}, 26286, 876 }, /* Wallis and Futuna */
3064  { 742, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Africa */
3065  { 2129, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Asia */
3066  { 10541, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Europe */
3067  { 15126, {'I','M',0}, {'I','M','N',0}, 10039882, 833 }, /* Man, Isle of */
3068  { 19618, {'M','K',0}, {'M','K','D',0}, 47610, 807 }, /* Macedonia, Former Yugoslav Republic of */
3069  { 20900, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Melanesia */
3070  { 21206, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Micronesia */
3071  { 21242, {'X','X',0}, {'X','X',0}, 161832256 }, /* Midway Islands */
3072  { 23581, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Northern America */
3073  { 26286, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Polynesia */
3074  { 27082, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Central America */
3075  { 27114, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Oceania */
3076  { 30967, {'S','X',0}, {'S','X','M',0}, 10039880, 534 }, /* Sint Maarten (Dutch part) */
3077  { 31396, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* South America */
3078  { 31706, {'M','F',0}, {'M','A','F',0}, 10039880, 663 }, /* Saint Martin (French part) */
3079  { 39070, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* World */
3080  { 42483, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Western Africa */
3081  { 42484, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Middle Africa */
3082  { 42487, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Northern Africa */
3083  { 47590, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Central Asia */
3084  { 47599, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* South-Eastern Asia */
3085  { 47600, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Eastern Asia */
3086  { 47603, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Eastern Africa */
3087  { 47609, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Eastern Europe */
3088  { 47610, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Southern Europe */
3089  { 47611, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Middle East */
3090  { 47614, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Southern Asia */
3091  { 7299303, {'T','L',0}, {'T','L','S',0}, 47599, 626 }, /* Democratic Republic of Timor-Leste */
3092  { 10026358, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Americas */
3093  { 10028789, {'A','X',0}, {'A','L','A',0}, 10039882, 248 }, /* Åland Islands */
3094  { 10039880, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Caribbean */
3095  { 10039882, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Northern Europe */
3096  { 10039883, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Southern Africa */
3097  { 10210824, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Western Europe */
3098  { 10210825, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Australia and New Zealand */
3099  { 161832015, {'B','L',0}, {'B','L','M',0}, 10039880, 652 }, /* Saint Barthélemy */
3100  { 161832256, {'U','M',0}, {'U','M','I',0}, 27114, 581 }, /* U.S. Minor Outlying Islands */
3101  { 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Latin America and the Caribbean */
3102 };
3103 
3104 /******************************************************************************
3105  * EnumLanguageGroupLocalesA (KERNEL32.@)
3106  *
3107  * Call a users function for every locale in a language group available on the system.
3108  *
3109  * PARAMS
3110  * pLangGrpLcEnumProc [I] Callback function to call for each locale
3111  * lgrpid [I] Language group (LGRPID_ values from "winnls.h")
3112  * dwFlags [I] Reserved, set to 0
3113  * lParam [I] User parameter to pass to pLangGrpLcEnumProc
3114  *
3115  * RETURNS
3116  * Success: TRUE.
3117  * Failure: FALSE. Use GetLastError() to determine the cause.
3118  */
3120  LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
3121 {
3123 
3124  TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
3125 
3126  callbacks.procA = pLangGrpLcEnumProc;
3127  callbacks.procW = NULL;
3128  callbacks.dwFlags = dwFlags;
3129  callbacks.lgrpid = lgrpid;
3130  callbacks.lParam = lParam;
3131 
3132  return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
3133 }
3134 
3135 /******************************************************************************
3136  * EnumLanguageGroupLocalesW (KERNEL32.@)
3137  *
3138  * See EnumLanguageGroupLocalesA.
3139  */
3141  LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
3142 {
3144 
3145  TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
3146 
3147  callbacks.procA = NULL;
3148  callbacks.procW = pLangGrpLcEnumProc;
3149  callbacks.dwFlags = dwFlags;
3150  callbacks.lgrpid = lgrpid;
3151  callbacks.lParam = lParam;
3152 
3153  return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
3154 }
3155 
3156 /* Callback function ptrs for EnumSystemCodePagesA/W */
3157 typedef struct
3158 {
3163 
3164 /* Internal implementation of EnumSystemCodePagesA/W */
3166 {
3167  WCHAR szNumber[5 + 1], szValue[MAX_PATH];
3168  HANDLE hKey;
3169  BOOL bContinue = TRUE;
3170  ULONG ulIndex = 0;
3171 
3172  if (!lpProcs)
3173  {
3175  return FALSE;
3176  }
3177 
3178  switch (lpProcs->dwFlags)
3179  {
3180  case CP_INSTALLED:
3181  case CP_SUPPORTED:
3182  break;
3183  default:
3185  return FALSE;
3186  }
3187 
3188  hKey = NLS_RegOpenKey(0, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
3189  if (!hKey)
3190  {
3191  WARN("NLS_RegOpenKey() failed\n");
3192  return FALSE;
3193  }
3194 
3195  while (bContinue)
3196  {
3197  if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber),
3198  szValue, sizeof(szValue)))
3199  {
3200  if ((lpProcs->dwFlags == CP_SUPPORTED)||
3201  ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) > 2)))
3202  {
3203  if (lpProcs->procW)
3204  {
3205  bContinue = lpProcs->procW(szNumber);
3206  }
3207  else
3208  {
3209  char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
3210 
3211  WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
3212  bContinue = lpProcs->procA(szNumberA);
3213  }
3214  }
3215 
3216  ulIndex++;
3217 
3218  } else bContinue = FALSE;
3219 
3220  if (!bContinue)
3221  break;
3222  }
3223 
3224  if (hKey)
3225  NtClose(hKey);
3226 
3227  return TRUE;
3228 }
3229 
3230 /*
3231  * @implemented
3232  */
3233 BOOL
3234 WINAPI
3236  CODEPAGE_ENUMPROCW lpCodePageEnumProc,
3237  DWORD dwFlags
3238  )
3239 {
3241 
3242  TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
3243 
3244  procs.procA = NULL;
3245  procs.procW = lpCodePageEnumProc;
3246  procs.dwFlags = dwFlags;
3247 
3248  return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
3249 }
3250 
3251 
3252 /*
3253  * @implemented
3254  */
3255 BOOL
3256 WINAPI
3258  CODEPAGE_ENUMPROCA lpCodePageEnumProc,
3259  DWORD dwFlags
3260  )
3261 {
3263 
3264  TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
3265 
3266  procs.procA = lpCodePageEnumProc;
3267  procs.procW = NULL;
3268  procs.dwFlags = dwFlags;
3269 
3270  return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
3271 }
3272 
3273 /******************************************************************************
3274  * EnumSystemGeoID (KERNEL32.@)
3275  *
3276  * Call a users function for every location available on the system.
3277  *
3278  * PARAMS
3279  * geoclass [I] Type of information desired (SYSGEOTYPE enum from "winnls.h")
3280  * parent [I] GEOID for the parent
3281  * enumproc [I] Callback function to call for each location
3282  *
3283  * RETURNS
3284  * Success: TRUE.
3285  * Failure: FALSE. Use GetLastError() to determine the cause.
3286  */
3288 {
3289  INT i;
3290 
3291  TRACE("(%d, %d, %p)\n", geoclass, parent, enumproc);
3292 
3293  if (!enumproc) {
3295  return FALSE;
3296  }
3297 
3298  if (geoclass != GEOCLASS_NATION && geoclass != GEOCLASS_REGION) {
3300  return FALSE;
3301  }
3302 
3303  for (i = 0; i < sizeof(geoinfodata)/sizeof(struct geoinfo_t); i++) {
3304  const struct geoinfo_t *ptr = &geoinfodata[i];
3305 
3306  if (geoclass == GEOCLASS_NATION && (ptr->kind == LOCATION_REGION))
3307  continue;
3308 
3309  if (geoclass == GEOCLASS_REGION && (ptr->kind == LOCATION_NATION))
3310  continue;
3311 
3312  if (parent && ptr->parent != parent)
3313  continue;
3314 
3315  if (!enumproc(ptr->id))
3316  return TRUE;
3317  }
3318 
3319  return TRUE;
3320 }
3321 
3322 /******************************************************************************
3323  * InvalidateNLSCache (KERNEL32.@)
3324  *
3325  * Invalidate the cache of NLS values.
3326  *
3327  * PARAMS
3328  * None.
3329  *
3330  * RETURNS
3331  * Success: TRUE.
3332  * Failure: FALSE.
3333  */
3335 {
3336 #ifdef __REACTOS__
3338  return TRUE;
3339 #else
3340  FIXME("() stub\n");
3341  return FALSE;
3342 #endif
3343 }
3344 
3345 /******************************************************************************
3346  * GetUserGeoID (KERNEL32.@)
3347  */
3349 {
3351  static const WCHAR geoW[] = {'G','e','o',0};
3352  static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
3353  WCHAR bufferW[40], *end;
3354  DWORD count;
3355  HANDLE hkey, hSubkey = 0;
3356  UNICODE_STRING keyW;
3358  RtlInitUnicodeString( &keyW, nationW );
3359  count = sizeof(bufferW);
3360 
3361  if(!(hkey = create_registry_key())) return ret;
3362 
3363  switch( GeoClass ){
3364  case GEOCLASS_NATION:
3365  if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
3366  {
3367  if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
3368  bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength)
3369  ret = strtolW((LPCWSTR)info->Data, &end, 10);
3370  }
3371  break;
3372  case GEOCLASS_REGION:
3373  FIXME("GEOCLASS_REGION not handled yet\n");
3374  break;
3375  }
3376 
3377  NtClose(hkey);
3378  if (hSubkey) NtClose(hSubkey);
3379  return ret;
3380 }
3381 
3382 /******************************************************************************
3383  * SetUserGeoID (KERNEL32.@)
3384  */
3386 {
3387  static const WCHAR geoW[] = {'G','e','o',0};
3388  static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
3389  static const WCHAR formatW[] = {'%','i',0};
3390  UNICODE_STRING nameW,keyW;
3391  WCHAR bufferW[10];
3393  HANDLE hkey;
3394 
3395  if(!(hkey = create_registry_key())) return FALSE;
3396 
3397  attr.Length = sizeof(attr);
3398  attr.RootDirectory = hkey;
3399  attr.ObjectName = &nameW;
3400  attr.Attributes = 0;
3401  attr.SecurityDescriptor = NULL;
3402  attr.SecurityQualityOfService = NULL;
3403  RtlInitUnicodeString( &nameW, geoW );
3404  RtlInitUnicodeString( &keyW, nationW );
3405 
3406  if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
3407 
3408  {
3409  NtClose(attr.RootDirectory);
3410  return FALSE;
3411  }
3412 
3413  sprintfW(bufferW, formatW, GeoID);
3414  NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
3415  NtClose(attr.RootDirectory);
3416  NtClose(hkey);
3417  return TRUE;
3418 }
3419 
3420 typedef struct
3421 {
3422  union
3423  {
3426  } u;
3430 
3433 {
3435  char buf[20];
3436 
3437  sprintf(buf, "%08x", (UINT)LangID);
3438  return enum_uilang->u.procA( buf, enum_uilang->param );
3439 }
3440 
3443 {
3444  static const WCHAR formatW[] = {'%','0','8','x',0};
3446  WCHAR buf[20];
3447 
3448  sprintfW( buf, formatW, (UINT)LangID );
3449  return enum_uilang->u.procW( buf, enum_uilang->param );
3450 }
3451 
3452 /******************************************************************************
3453  * EnumUILanguagesA (KERNEL32.@)
3454  */
3456 {
3457  ENUM_UILANG_CALLBACK enum_uilang;
3458 
3459  TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
3460 
3461  if(!pUILangEnumProc) {
3463  return FALSE;
3464  }
3465  if(dwFlags) {
3467  return FALSE;
3468  }
3469 
3470  enum_uilang.u.procA = pUILangEnumProc;
3471  enum_uilang.flags = dwFlags;
3472  enum_uilang.param = lParam;
3473 
3476  (LONG_PTR)&enum_uilang);
3477  return TRUE;
3478 }
3479 
3480 /******************************************************************************
3481  * EnumUILanguagesW (KERNEL32.@)
3482  */
3484 {
3485  ENUM_UILANG_CALLBACK enum_uilang;
3486 
3487  TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
3488 
3489 
3490  if(!pUILangEnumProc) {
3492  return FALSE;
3493  }
3494  if(dwFlags) {
3496  return FALSE;
3497  }
3498 
3499  enum_uilang.u.procW = pUILangEnumProc;
3500  enum_uilang.flags = dwFlags;
3501  enum_uilang.param = lParam;
3502 
3505  (LONG_PTR)&enum_uilang);
3506  return TRUE;
3507 }
3508 
3509 static int
3510 #ifdef __REACTOS__
3511 NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData, LANGID lang)
3512 #else
3513 NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
3514 #endif
3515 {
3516  /* FIXME: move *.nls resources out of kernel32 into locale.nls */
3517  Location += NLSRC_OFFSET;
3518  Location &= 0xFFFF;
3519 
3520  if (cchData == 0)
3521 #ifdef __REACTOS__
3522  return GetLocalisedText(Location, NULL, 0, lang);
3523 #else
3524  return GetLocalisedText(Location, NULL, 0);
3525 #endif
3526 
3527 #ifdef __REACTOS__
3528  if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData, lang))
3529 #else
3530  if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData))
3531 #endif
3532  return strlenW(szFriendlyName) + 1;
3533 
3534  return 0;
3535 }
3536 
3537 static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
3538 {
3539  int min, max;
3540 
3541  min = 0;
3542  max = sizeof(geoinfodata)/sizeof(struct geoinfo_t)-1;
3543 
3544  while (min <= max) {
3545  const struct geoinfo_t *ptr;
3546  int n = (min+max)/2;
3547 
3548  ptr = &geoinfodata[n];
3549  if (geoid == ptr->id)
3550  /* we don't need empty entry */
3551  return *ptr->iso2W ? ptr : NULL;
3552 
3553  if (ptr->id > geoid)
3554  max = n-1;
3555  else
3556  min = n+1;
3557  }
3558 
3559  return NULL;
3560 }
3561 
3562 /******************************************************************************
3563  * GetGeoInfoW (KERNEL32.@)
3564  */
3565 INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
3566 {
3567  const struct geoinfo_t *ptr;
3568  const WCHAR *str = NULL;
3569  WCHAR buffW[12];
3570  LONG val = 0;
3571  INT len;
3572 
3573  TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
3574 
3575  if (!(ptr = get_geoinfo_dataptr(geoid))) {
3577  return 0;
3578  }
3579 
3580  switch (geotype) {
3581  case GEO_FRIENDLYNAME:
3582  {
3583 #ifdef __REACTOS__
3584  return NLS_GetGeoFriendlyName(geoid, data, data_len, lang);
3585 #else
3586  return NLS_GetGeoFriendlyName(geoid, data, data_len);
3587 #endif
3588  }
3589  case GEO_NATION:
3590  val = geoid;
3591  break;
3592  case GEO_ISO_UN_NUMBER:
3593  val = ptr->uncode;
3594  break;
3595  case GEO_PARENT:
3596  val = ptr->parent;
3597  break;
3598  case GEO_ISO2:
3599  case GEO_ISO3:
3600  {
3601  str = geotype == GEO_ISO2 ? ptr->iso2W : ptr->iso3W;
3602  break;
3603  }
3604  case GEO_RFC1766:
3605  case GEO_LCID:
3606  case GEO_OFFICIALNAME:
3607  case GEO_TIMEZONES:
3608  case GEO_OFFICIALLANGUAGES:
3609  case GEO_LATITUDE:
3610  case GEO_LONGITUDE:
3611  FIXME("type %d is not supported\n", geotype);
3613  return 0;
3614  default:
3615  WARN("unrecognized type %d\n", geotype);
3617  return 0;
3618  }
3619 
3620  if (val) {
3621  static const WCHAR fmtW[] = {'%','d',0};
3622  sprintfW(buffW, fmtW, val);
3623  str = buffW;
3624  }
3625 
3626  len = strlenW(str) + 1;
3627  if (!data || !data_len)
3628  return len;
3629 
3630  memcpy(data, str, min(len, data_len)*sizeof(WCHAR));
3631  if (data_len < len)
3633  return data_len < len ? 0 : len;
3634 }
3635 
3636 /******************************************************************************
3637  * GetGeoInfoA (KERNEL32.@)
3638  */
3639 INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
3640 {
3641  WCHAR *buffW;
3642  INT len;
3643 
3644  TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
3645 
3646  len = GetGeoInfoW(geoid, geotype, NULL, 0, lang);
3647  if (!len)
3648  return 0;
3649 
3650  buffW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
3651  if (!buffW)
3652  return 0;
3653 
3654  GetGeoInfoW(geoid, geotype, buffW, len, lang);
3655  len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, NULL, 0, NULL, NULL);
3656  if (!data || !data_len) {
3657  HeapFree(GetProcessHeap(), 0, buffW);
3658  return len;
3659  }
3660 
3661  len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, data, data_len, NULL, NULL);
3662  HeapFree(GetProcessHeap(), 0, buffW);
3663 
3664  if (data_len < len)
3666  return data_len < len ? 0 : len;
3667 }
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
BOOL WINAPI EnumSystemCodePagesW(CODEPAGE_ENUMPROCW lpCodePageEnumProc, DWORD dwFlags)
Definition: lang.c:3235
#define LCMAP_SIMPLIFIED_CHINESE
Definition: winnls.h:193
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
LANGGROUPLOCALE_ENUMPROCW procW
Definition: lang.c:2693
static struct registry_value * get_locale_registry_value(DWORD lctype)
Definition: lang.c:1088
#define LOCALE_SGROUPING
Definition: winnls.h:44
#define C2_LEFTTORIGHT
Definition: winnls.h:250
static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
Definition: lang.c:2432
WCHAR * modifier
Definition: lang.c:136
INT WINAPI FoldStringA(DWORD dwFlags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen)
Definition: lang.c:2141
#define MAKEINTRESOURCE
Definition: winuser.h:591
#define LINGUISTIC_IGNORECASE
Definition: winnls.h:181
#define C3_FULLWIDTH
Definition: winnls.h:269
#define IN
Definition: typedefs.h:39
#define CT_CTYPE2
Definition: winnls.h:238
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:38
static const WCHAR sPositiveSignW[]
Definition: lang.c:184
static const WCHAR szName[]
Definition: powrprof.c:45
return
Definition: dirsup.c:529
#define MAKELCID(lgid, srtid)
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: lang.c:810
#define max(a, b)
Definition: svc.c:63
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:115
Definition: pdh_main.c:93
#define REG_SZ
Definition: lang.c:35
#define SUBLANG_CHINESE_TRADITIONAL
Definition: nls.h:208
DWORD WINAPI VerLanguageNameW(DWORD wLang, LPWSTR szLang, DWORD nSize)
Definition: lang.c:1693
#define LOCALE_LOCALEINFOFLAGSMASK
Definition: lang.c:48
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define LOCALE_SMONGROUPING
Definition: winnls.h:53
void JapaneseEra_ClearCache(void)
Definition: japanese.c:38
BOOL(CALLBACK * LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM)
Definition: winnls.h:539
#define matches(FN)
Definition: match.h:70
static LCID lcid_LC_TELEPHONE
Definition: lang.c:150
union ENUM_UILANG_CALLBACK::@448 u
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
static int get_value_base_by_lctype(LCTYPE lctype)
Definition: lang.c:1078
#define CSTR_GREATER_THAN
Definition: winnls.h:457
#define _In_opt_
Definition: ms_sal.h:309
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static LCID lcid_LC_NUMERIC
Definition: lang.c:146
CFF_Charset charset
Definition: cffcmap.c:138
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:85
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:104
#define C2_RIGHTTOLEFT
Definition: winnls.h:251
#define LOCALE_INEUTRAL
Definition: winnls.h:156
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:126
#define LOCALE_SMONTHNAME5
Definition: winnls.h:95
#define WideCharToMultiByte
Definition: compat.h:111
static const WCHAR iNegNumberW[]
Definition: lang.c:164
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define strcasecmp
Definition: fake.h:9
#define LOCALE_SENGLANGUAGE
Definition: winnls.h:27
INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
Definition: lang.c:3639
#define LOCALE_IPOSSYMPRECEDES
Definition: winnls.h:121
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:109
LANGID WINAPI GetSystemDefaultUILanguage(void)
Definition: lang.c:830
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define LOCALE_SMONTHNAME2
Definition: winnls.h:92
static const WCHAR iCurrDigitsW[]
Definition: lang.c:154
static LCID lcid_LC_MEASUREMENT
Definition: lang.c:149
static const WCHAR sNativeDigitsW[]
Definition: lang.c:182
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define C2_BLOCKSEPARATOR
Definition: winnls.h:257
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:87
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
BOOL WINAPI WriteProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string)
Definition: profile.c:1287
#define LANG_NEUTRAL
Definition: nls.h:22
#define CP_ACP
Definition: compat.h:109
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1022
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:90
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
#define LOCALE_IDATE
Definition: winnls.h:63
#define C2_EUROPENUMBER
Definition: winnls.h:252
#define LOCALE_USER_DEFAULT
INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: lang.c:2199
GLuint GLuint GLsizei count
Definition: gl.h:1545
DWORD LGRPID
Definition: winnls.h:520
#define LOCALE_INEGSYMPRECEDES
Definition: winnls.h:123
#define WARN(fmt,...)
Definition: debug.h:112
WCHAR * cached_value
Definition: lang.c:196
#define strtolW(s, e, b)
Definition: unicode.h:33
#define SORT_STRINGSORT
Definition: winnls.h:183
#define SUBLANG_DEFAULT
Definition: nls.h:168
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2058
LONG NTSTATUS
Definition: precomp.h:26
LANGGROUPLOCALE_ENUMPROCA procA
Definition: lang.c:2692
#define LOCALE_SMONTHNAME13
Definition: winnls.h:103
#define LOCALE_SDAYNAME2
Definition: winnls.h:78
static const WCHAR sListW[]
Definition: lang.c:177
#define LOCALE_IDEFAULTMACCODEPAGE
Definition: winnls.h:39
#define CALLBACK
Definition: compat.h:35
_In_ LPCSTR lpName
Definition: winbase.h:2773
#define SUBLANG_SPANISH_MODERN
Definition: nls.h:338
#define LOCALE_SMONTHNAME6
Definition: winnls.h:96
GLdouble n
Definition: glext.h:7729
#define LOCALE_ICALENDARTYPE
Definition: winnls.h:73
#define LOCALE_ILZERO
Definition: winnls.h:46
static const WCHAR szLangGroupsKeyName[]
Definition: lang.c:58
static HANDLE create_registry_key(void)
Definition: lang.c:698
#define MB_COMPOSITE
Definition: unicode.h:40
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define NORM_IGNORESYMBOLS
Definition: winnls.h:179
#define MAP_COMPOSITE
Definition: winnls.h:216
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static INT get_registry_locale_info(struct registry_value *registry_value, LPWSTR buffer, INT len)
Definition: lang.c:890
static BOOL CALLBACK enum_uilang_proc_w(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD LangID, LONG_PTR lParam)
Definition: lang.c:3441
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
#define SUBLANG_CHINESE_HONGKONG
Definition: nls.h:210
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:110
GLuint buffer
Definition: glext.h:5915
static void strcpynAtoW(WCHAR *dst, const char *src, size_t n)
Definition: lang.c:248
BOOL WINAPI EnumUILanguagesA(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: lang.c:3455
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCA)(LGRPID, LPSTR, LPSTR, DWORD, LONG_PTR)
Definition: winnls.h:531
#define MAP_FOLDCZONE
Definition: winnls.h:213
static const WCHAR sLongDateW[]
Definition: lang.c:178
DWORD LCID
Definition: nls.h:13
WORD LANGID
Definition: typedefs.h:81
#define NORM_IGNORECASE
Definition: winnls.h:176
#define C3_IDEOGRAPH
Definition: winnls.h:270
static HANDLE proc()
Definition: pdb.c:34
LCID WINAPI GetUserDefaultLCID(void)
Definition: lang.c:772
#define LOCALE_ILANGUAGE
Definition: winnls.h:25
Definition: mimeintl.c:43
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define SUBLANG_CHINESE_SINGAPORE
Definition: nls.h:211
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define C3_HALFWIDTH
Definition: winnls.h:268
static const WCHAR sCurrencyW[]
Definition: lang.c:172
int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: fold.c:118
char * LPSTR
Definition: xmlstorage.h:182
BOOL WINAPI IsValidLanguageGroup(LGRPID lgrpid, DWORD dwFlags)
Definition: lang.c:2651
static const WCHAR iPaperSizeW[]
Definition: lang.c:165
#define SUBLANG_NEUTRAL
Definition: nls.h:167
#define NORM_IGNOREKANATYPE
Definition: winnls.h:177
#define LOCALE_IMEASURE
Definition: winnls.h:41
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCW)(LGRPID, LPWSTR, LPWSTR, DWORD, LONG_PTR)
Definition: winnls.h:532
static RTL_CRITICAL_SECTION cache_section
Definition: lang.c:244
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:106
LANGID langid
Definition: msctf.idl:605
static BOOL NLS_EnumLanguageGroupLocales(ENUMLANGUAGEGROUPLOCALE_CALLBACKS *lpProcs)
Definition: lang.c:2700
#define C2_EUROPESEPARATOR
Definition: winnls.h:253
#define lstrlenW
Definition: compat.h:609
BOOL(CALLBACK * CODEPAGE_ENUMPROCW)(LPWSTR)
Definition: winnls.h:541
GEOID id
Definition: lang.c:2794
int32_t INT
Definition: typedefs.h:58
static const WCHAR sNegativeSignW[]
Definition: lang.c:183
#define C2_NOTAPPLICABLE
Definition: winnls.h:261
#define LOCALE_SMONTHNAME8
Definition: winnls.h:98
#define LOCALE_IPOSSEPBYSPACE
Definition: winnls.h:122
#define LOCALE_IDEFAULTLANGUAGE
Definition: winnls.h:35
#define LOCALE_RETURN_GENITIVE_NAMES
Definition: winnls.h:24
static const WCHAR iCalendarTypeW[]
Definition: lang.c:152
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:111
#define LOCALE_SCURRENCY
Definition: winnls.h:49
#define lstrcpynW
Definition: compat.h:597
static LCID lcid_LC_CTYPE
Definition: lang.c:144
#define LOCALE_INEGNUMBER
Definition: winnls.h:47
DEBUG_CHANNEL(nls)
#define LOCALE_SDAYNAME5
Definition: winnls.h:81
INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lparam)
Definition: lang.c:1889
static const WCHAR iTLZeroW[]
Definition: lang.c:166
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1102
static const WCHAR iFirstDayOfWeekW[]
Definition: lang.c:158
BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumproc)
Definition: lang.c:3287
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define NLSRC_OFFSET
Definition: lang.c:44
static BOOL CALLBACK enum_locale_ex_proc(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang, LONG_PTR lparam)
Definition: lang.c:1625
DWORD lctype
Definition: lang.c:194
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define LOCALE_SDAYNAME1
Definition: winnls.h:77
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:86
static BOOL NLS_EnumSystemCodePages(ENUMSYSTEMCODEPAGES_CALLBACKS *lpProcs)
Definition: lang.c:3165
#define NORM_LINGUISTIC_CASING
Definition: winnls.h:182
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:108
DWORD LCTYPE
Definition: winnls.h:517
LCID lcid
Definition: lang.c:137
HMODULE kernel32_handle
Definition: dllmain.c:26
#define LOCALE_SMONTHNAME1
Definition: winnls.h:91
#define L(x)
Definition: ntvdm.h:50
#define LOCALE_STHOUSAND
Definition: winnls.h:43
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
BOOL WINAPI SetThreadLocale(LCID lcid)
Definition: lang.c:1472
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
BOOL(CALLBACK * UILANGUAGE_ENUMPROCA)(LPSTR, LONG_PTR)
Definition: winnls.h:536
BOOL WINAPI EnumSystemLanguageGroupsW(LANGUAGEGROUP_ENUMPROCW pLangGrpEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: lang.c:2623
#define FALSE
Definition: types.h:117
#define CP_UTF8
Definition: nls.h:20
#define CT_CTYPE3
Definition: winnls.h:239
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: lang.c:1506
Definition: _locale.h:75
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: lang.c:1817
LOCALE_ENUMPROCEX proc
Definition: lang.c:1620
unsigned int BOOL
Definition: ntddk_ex.h:94
WCHAR strW[12]
Definition: clipboard.c:2029
long LONG
Definition: pedump.c:60
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:113
static const struct geoinfo_t geoinfodata[]
Definition: lang.c:2802
static size_t double number
Definition: printf.c:71
#define LOCALE_SINTLSYMBOL
Definition: winnls.h:50
static const WCHAR iCurrencyW[]
Definition: lang.c:155
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
static struct _test_info info[]
Definition: SetCursorPos.c:19
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:89
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: lang.c:2025
BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc, LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
Definition: lang.c:3140
#define LOCALE_SLONGDATE
Definition: winnls.h:61
#define MAP_PRECOMPOSED
Definition: winnls.h:215
#define FIXME(fmt,...)
Definition: debug.h:111
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
BOOL WINAPI FreeResource(HGLOBAL handle)
Definition: res.c:559
static PVOID ptr
Definition: dispmode.c:27
WCHAR * script
Definition: lang.c:135
r reserved
Definition: btrfs.c:2975
BOOL WINAPI EnumSystemCodePagesA(CODEPAGE_ENUMPROCA lpCodePageEnumProc, DWORD dwFlags)
Definition: lang.c:3257
#define LOCALE_ITIMEMARKPOSN
Definition: winnls.h:66
static const WCHAR s1159W[]
Definition: lang.c:169
#define LOCALE_IMONLZERO
Definition: winnls.h:70
int codepage
Definition: win_iconv.c:156
#define LCMAP_LOWERCASE
Definition: winnls.h:184
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex, LPWSTR szValueName, ULONG valueNameSize, LPWSTR szValueData, ULONG valueDataSize)
Definition: lang.c:2404
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
Definition: sortkey.c:33
const WCHAR * str
static int NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
Definition: lang.c:3513
#define nls
Definition: kernel32.h:13
static const WCHAR sMonThousandSepW[]
Definition: lang.c:181
#define LOCALE_INEGCURR
Definition: winnls.h:57
BOOL WINAPI GetStringTypeExW(LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: lang.c:1793
static const WCHAR iTimeW[]
Definition: lang.c:168
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:107
static const WCHAR version[]
Definition: asmname.c:66
unsigned char
Definition: typeof.h:29
#define _In_
Definition: ms_sal.h:308
UINT WINAPI GetACP(VOID)
Definition: nls.c:2218
LONG_PTR LPARAM
Definition: windef.h:208
WCHAR lpszDest[260]
static const WCHAR iDateW[]
Definition: lang.c:156
#define LOCALE_SMONTHNAME4
Definition: winnls.h:94
LCID WINAPI GetSystemDefaultLCID(void)
Definition: lang.c:791
#define LOCALE_SABBREVMONTHNAME13
Definition: winnls.h:116
#define LOCALE_SDECIMAL
Definition: winnls.h:42
static const WCHAR sDateW[]
Definition: lang.c:173
BOOL(CALLBACK * LANGGROUPLOCALE_ENUMPROCA)(LGRPID, LCID, LPSTR, LONG_PTR)
Definition: winnls.h:533
static const WCHAR valueW[]
Definition: object.c:48
#define LOCALE_STIME
Definition: winnls.h:59
BOOL WINAPI EnumResourceLanguagesW(HMODULE hmod, LPCWSTR type, LPCWSTR name, ENUMRESLANGPROCW lpfun, LONG_PTR lparam)
Definition: res.c:480
#define LOCALE_NEUTRALDATA
Definition: winnls.h:210
const char * LPCSTR
Definition: xmlstorage.h:183
BOOL WINAPI EnumSystemLocalesW(LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags)
Definition: lang.c:1608
static const WCHAR s2359W[]
Definition: lang.c:170
static LCID lcid_LC_COLLATE
Definition: lang.c:143
static LCID lcid_LC_TIME
Definition: lang.c:147
static const WCHAR sGroupingW[]
Definition: lang.c:175
BOOL(CALLBACK * LOCALE_ENUMPROCA)(LPSTR)
Definition: winnls.h:537
GLuint GLfloat * val
Definition: glext.h:7180
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 GL