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