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