ReactOS 0.4.15-dev-8096-ga0eec98
locale.c
Go to the documentation of this file.
1/*
2 * Locale support
3 *
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 David Lee Lambert
6 * Copyright 2000 Julio César Gázquez
7 * Copyright 2002 Alexandre Julliard for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <k32.h>
25
26#define NDEBUG
27#include <debug.h>
29
30#include "lcformat_private.h"
31#ifdef __REACTOS__
32 #include "japanese.h"
33#endif
34
37
38#undef WINVER
39#define WINVER DLL_EXPORT_VERSION
40
41/* From winnls.h */
42#define LOCALE_NAME_USER_DEFAULT NULL
43
44#define REG_SZ 1
45extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen);
46extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen);
47extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2);
48#ifdef __REACTOS__
50#else
52#endif
53#define NLSRC_OFFSET 5000 /* FIXME */
54
56
57#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|\
58 LOCALE_RETURN_NUMBER|LOCALE_RETURN_GENITIVE_NAMES)
59#define MB_FLAGSMASK (MB_PRECOMPOSED|MB_COMPOSITE|MB_USEGLYPHCHARS|MB_ERR_INVALID_CHARS)
60#define WC_FLAGSMASK (WC_DISCARDNS|WC_SEPCHARS|WC_DEFAULTCHAR|WC_ERR_INVALID_CHARS|\
61 WC_COMPOSITECHECK|WC_NO_BEST_FIT_CHARS)
62
63/* current code pages */
64static const union cptable *ansi_cptable;
65static const union cptable *oem_cptable;
66static const union cptable *mac_cptable;
67static const union cptable *unix_cptable; /* NULL if UTF8 */
68
69static const WCHAR szLocaleKeyName[] = {
70 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
71 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
72 'C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0
73};
74
75static const WCHAR szLangGroupsKeyName[] = {
76 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
77 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
78 'C','o','n','t','r','o','l','\\','N','l','s','\\',
79 'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0
80};
81
82#if (WINVER >= 0x0600)
83/* Charset to codepage map, sorted by name. */
84static const struct charset_entry
85{
86 const char *charset_name;
88} charset_names[] =
89{
90 { "BIG5", 950 },
91 { "CP1250", 1250 },
92 { "CP1251", 1251 },
93 { "CP1252", 1252 },
94 { "CP1253", 1253 },
95 { "CP1254", 1254 },
96 { "CP1255", 1255 },
97 { "CP1256", 1256 },
98 { "CP1257", 1257 },
99 { "CP1258", 1258 },
100 { "CP932", 932 },
101 { "CP936", 936 },
102 { "CP949", 949 },
103 { "CP950", 950 },
104 { "EUCJP", 20932 },
105 { "GB2312", 936 },
106 { "IBM037", 37 },
107 { "IBM1026", 1026 },
108 { "IBM424", 424 },
109 { "IBM437", 437 },
110 { "IBM500", 500 },
111 { "IBM850", 850 },
112 { "IBM852", 852 },
113 { "IBM855", 855 },
114 { "IBM857", 857 },
115 { "IBM860", 860 },
116 { "IBM861", 861 },
117 { "IBM862", 862 },
118 { "IBM863", 863 },
119 { "IBM864", 864 },
120 { "IBM865", 865 },
121 { "IBM866", 866 },
122 { "IBM869", 869 },
123 { "IBM874", 874 },
124 { "IBM875", 875 },
125 { "ISO88591", 28591 },
126 { "ISO885910", 28600 },
127 { "ISO885913", 28603 },
128 { "ISO885914", 28604 },
129 { "ISO885915", 28605 },
130 { "ISO885916", 28606 },
131 { "ISO88592", 28592 },
132 { "ISO88593", 28593 },
133 { "ISO88594", 28594 },
134 { "ISO88595", 28595 },
135 { "ISO88596", 28596 },
136 { "ISO88597", 28597 },
137 { "ISO88598", 28598 },
138 { "ISO88599", 28599 },
139 { "KOI8R", 20866 },
140 { "KOI8U", 21866 },
141 { "UTF8", CP_UTF8 }
142};
143#endif
144
145
147{
148 WCHAR win_name[128]; /* Windows name ("en-US") */
149 WCHAR lang[128]; /* language ("en") (note: buffer contains the other strings too) */
150 WCHAR *country; /* country ("US") */
151 WCHAR *charset; /* charset ("UTF-8") for Unix format only */
152 WCHAR *script; /* script ("Latn") for Windows format only */
153 WCHAR *modifier; /* modifier or sort order */
154 LCID lcid; /* corresponding LCID */
155 int matches; /* number of elements matching LCID (0..4) */
156 UINT codepage; /* codepage corresponding to charset */
157};
158
159/* locale ids corresponding to the various Unix locale parameters */
169
170static const WCHAR iCalendarTypeW[] = {'i','C','a','l','e','n','d','a','r','T','y','p','e',0};
171static const WCHAR iCountryW[] = {'i','C','o','u','n','t','r','y',0};
172static const WCHAR iCurrDigitsW[] = {'i','C','u','r','r','D','i','g','i','t','s',0};
173static const WCHAR iCurrencyW[] = {'i','C','u','r','r','e','n','c','y',0};
174static const WCHAR iDateW[] = {'i','D','a','t','e',0};
175static const WCHAR iDigitsW[] = {'i','D','i','g','i','t','s',0};
176static const WCHAR iFirstDayOfWeekW[] = {'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0};
177static const WCHAR iFirstWeekOfYearW[] = {'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0};
178static const WCHAR iLDateW[] = {'i','L','D','a','t','e',0};
179static const WCHAR iLZeroW[] = {'i','L','Z','e','r','o',0};
180static const WCHAR iMeasureW[] = {'i','M','e','a','s','u','r','e',0};
181static const WCHAR iNegCurrW[] = {'i','N','e','g','C','u','r','r',0};
182static const WCHAR iNegNumberW[] = {'i','N','e','g','N','u','m','b','e','r',0};
183static const WCHAR iPaperSizeW[] = {'i','P','a','p','e','r','S','i','z','e',0};
184static const WCHAR iTLZeroW[] = {'i','T','L','Z','e','r','o',0};
185static const WCHAR iTimePrefixW[] = {'i','T','i','m','e','P','r','e','f','i','x',0};
186static const WCHAR iTimeW[] = {'i','T','i','m','e',0};
187static const WCHAR s1159W[] = {'s','1','1','5','9',0};
188static const WCHAR s2359W[] = {'s','2','3','5','9',0};
189static const WCHAR sCountryW[] = {'s','C','o','u','n','t','r','y',0};
190static const WCHAR sCurrencyW[] = {'s','C','u','r','r','e','n','c','y',0};
191static const WCHAR sDateW[] = {'s','D','a','t','e',0};
192static const WCHAR sDecimalW[] = {'s','D','e','c','i','m','a','l',0};
193static const WCHAR sGroupingW[] = {'s','G','r','o','u','p','i','n','g',0};
194static const WCHAR sLanguageW[] = {'s','L','a','n','g','u','a','g','e',0};
195static const WCHAR sListW[] = {'s','L','i','s','t',0};
196static const WCHAR sLongDateW[] = {'s','L','o','n','g','D','a','t','e',0};
197static const WCHAR sMonDecimalSepW[] = {'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0};
198static const WCHAR sMonGroupingW[] = {'s','M','o','n','G','r','o','u','p','i','n','g',0};
199static const WCHAR sMonThousandSepW[] = {'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0};
200static const WCHAR sNativeDigitsW[] = {'s','N','a','t','i','v','e','D','i','g','i','t','s',0};
201static const WCHAR sNegativeSignW[] = {'s','N','e','g','a','t','i','v','e','S','i','g','n',0};
202static const WCHAR sPositiveSignW[] = {'s','P','o','s','i','t','i','v','e','S','i','g','n',0};
203static const WCHAR sShortDateW[] = {'s','S','h','o','r','t','D','a','t','e',0};
204static const WCHAR sThousandW[] = {'s','T','h','o','u','s','a','n','d',0};
205static const WCHAR sTimeFormatW[] = {'s','T','i','m','e','F','o','r','m','a','t',0};
206static const WCHAR sTimeW[] = {'s','T','i','m','e',0};
207static const WCHAR sYearMonthW[] = {'s','Y','e','a','r','M','o','n','t','h',0};
208static const WCHAR NumShapeW[] = {'N','u','m','s','h','a','p','e',0};
209
210static struct registry_value
211{
213 const WCHAR *name;
215} registry_values[] =
216{
227 { LOCALE_IPAPERSIZE, iPaperSizeW },
228 { LOCALE_ITIME, iTimeW },
229 { LOCALE_S1159, s1159W },
230 { LOCALE_S2359, s2359W },
232 { LOCALE_SDATE, sDateW },
235 { LOCALE_SLIST, sListW },
244 { LOCALE_STIME, sTimeW },
246 { LOCALE_SYEARMONTH, sYearMonthW },
247 /* The following are not listed under MSDN as supported,
248 * but seem to be used and also stored in the registry.
249 */
251 { LOCALE_IDATE, iDateW },
256 /* The following are used in XP and later */
257 { LOCALE_IDIGITSUBSTITUTION, NumShapeW },
261
262static RTL_CRITICAL_SECTION cache_section = { NULL, -1, 0, 0, 0, 0 };
263
264#ifndef __REACTOS__
265/* Copy Ascii string to Unicode without using codepages */
266static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
267{
268 while (n > 1 && *src)
269 {
270 *dst++ = (unsigned char)*src++;
271 n--;
272 }
273 if (n) *dst = 0;
274}
275
276static inline unsigned short get_table_entry( const unsigned short *table, WCHAR ch )
277{
278 return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
279}
280#endif // !__REACTOS__
281
282/***********************************************************************
283 * get_lcid_codepage
284 *
285 * Retrieve the ANSI codepage for a given locale.
286 */
287static inline UINT get_lcid_codepage( LCID lcid )
288{
289 UINT ret;
290 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
291 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
292 return ret;
293}
294
295#ifndef __REACTOS__
296/***********************************************************************
297 * get_codepage_table
298 *
299 * Find the table for a given codepage, handling CP_ACP etc. pseudo-codepages
300 */
301static const union cptable *get_codepage_table( unsigned int codepage )
302{
303 const union cptable *ret = NULL;
304
305 assert( ansi_cptable ); /* init must have been done already */
306
307 switch(codepage)
308 {
309 case CP_ACP:
310 return ansi_cptable;
311 case CP_OEMCP:
312 return oem_cptable;
313 case CP_MACCP:
314 return mac_cptable;
315 case CP_UTF7:
316 case CP_UTF8:
317 break;
318 case CP_THREAD_ACP:
319 if (NtCurrentTeb()->CurrentLocale == GetUserDefaultLCID()) return ansi_cptable;
320 codepage = get_lcid_codepage( NtCurrentTeb()->CurrentLocale );
321 if (!codepage) return ansi_cptable;
322 /* fall through */
323 default:
324 if (codepage == ansi_cptable->info.codepage) return ansi_cptable;
325 if (codepage == oem_cptable->info.codepage) return oem_cptable;
326 if (codepage == mac_cptable->info.codepage) return mac_cptable;
328 break;
329 }
330 return ret;
331}
332#endif // !__REACTOS__
333
334#if (WINVER >= 0x0600)
335/***********************************************************************
336 * charset_cmp (internal)
337 */
338static int charset_cmp( const void *name, const void *entry )
339{
340 const struct charset_entry *charset = entry;
341 return strcasecmp( name, charset->charset_name );
342}
343
344/***********************************************************************
345 * find_charset
346 */
347static UINT find_charset( const WCHAR *name )
348{
349 const struct charset_entry *entry;
350 char charset_name[16];
351 size_t i, j;
352
353 /* remove punctuation characters from charset name */
354 for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++)
355 if (isalnum((unsigned char)name[i])) charset_name[j++] = name[i];
356 charset_name[j] = 0;
357
358 entry = bsearch( charset_name, charset_names,
359 sizeof(charset_names)/sizeof(charset_names[0]),
360 sizeof(charset_names[0]), charset_cmp );
361 if (entry) return entry->codepage;
362 return 0;
363}
364#endif // (WINVER >= 0x0600)
365
367{
368 switch (lang)
369 {
379 }
381 return lang;
382}
383
384#if (WINVER >= 0x0600)
385/***********************************************************************
386 * find_locale_id_callback
387 */
388static BOOL CALLBACK find_locale_id_callback( HMODULE hModule, LPCWSTR type,
390{
391 struct locale_name *data = (struct locale_name *)lParam;
392 WCHAR buffer[128];
393 int matches = 0;
394 LCID lcid = MAKELCID( lang, SORT_DEFAULT ); /* FIXME: handle sort order */
395
396 if (PRIMARYLANGID(lang) == LANG_NEUTRAL) return TRUE; /* continue search */
397
398 /* first check exact name */
399 if (data->win_name[0] &&
401 buffer, sizeof(buffer)/sizeof(WCHAR) ))
402 {
403 if (!strcmpiW( data->win_name, buffer ))
404 {
405 matches = 4; /* everything matches */
406 goto done;
407 }
408 }
409
411 buffer, sizeof(buffer)/sizeof(WCHAR) ))
412 return TRUE;
413 if (strcmpiW( buffer, data->lang )) return TRUE;
414 matches++; /* language name matched */
415
416 if (data->script)
417 {
418 if (GetLocaleInfoW( lcid, LOCALE_SSCRIPTS | LOCALE_NOUSEROVERRIDE,
419 buffer, sizeof(buffer)/sizeof(WCHAR) ))
420 {
421 const WCHAR *p = buffer;
422 unsigned int len = strlenW( data->script );
423 while (*p)
424 {
425 if (!strncmpiW( p, data->script, len ) && (!p[len] || p[len] == ';')) break;
426 if (!(p = strchrW( p, ';'))) goto done;
427 p++;
428 }
429 if (!*p) goto done;
430 matches++; /* script matched */
431 }
432 }
433
434 if (data->country)
435 {
437 buffer, sizeof(buffer)/sizeof(WCHAR) ))
438 {
439 if (strcmpiW( buffer, data->country )) goto done;
440 matches++; /* country name matched */
441 }
442 }
443 else /* match default language */
444 {
445 LANGID def_lang = data->script ? lang : MAKELANGID( PRIMARYLANGID(lang), LANG_NEUTRAL );
446 if (lang == get_default_sublang( def_lang )) matches++;
447 }
448
449 if (data->codepage)
450 {
451 UINT unix_cp;
452 if (GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER,
453 (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) ))
454 {
455 if (unix_cp == data->codepage) matches++;
456 }
457 }
458
459 /* FIXME: check sort order */
460
461done:
462 if (matches > data->matches)
463 {
464 data->lcid = lcid;
465 data->matches = matches;
466 }
467 return (data->matches < 4); /* no need to continue for perfect match */
468}
469
470
471/***********************************************************************
472 * parse_locale_name
473 *
474 * Parse a locale name into a struct locale_name, handling both Windows and Unix formats.
475 * Unix format is: lang[_country][.charset][@modifier]
476 * Windows format is: lang[-script][-country][_modifier]
477 */
478static void parse_locale_name( const WCHAR *str, struct locale_name *name )
479{
480 static const WCHAR sepW[] = {'-','_','.','@',0};
481 static const WCHAR winsepW[] = {'-','_',0};
482 static const WCHAR posixW[] = {'P','O','S','I','X',0};
483 static const WCHAR cW[] = {'C',0};
484 static const WCHAR latinW[] = {'l','a','t','i','n',0};
485 static const WCHAR latnW[] = {'-','L','a','t','n',0};
486 WCHAR *p;
487
488 TRACE("%s\n", debugstr_w(str));
489
490 name->country = name->charset = name->script = name->modifier = NULL;
492 name->matches = 0;
493 name->codepage = 0;
494 name->win_name[0] = 0;
495 lstrcpynW( name->lang, str, sizeof(name->lang)/sizeof(WCHAR) );
496
497 if (!*name->lang)
498 {
499 name->lcid = LOCALE_INVARIANT;
500 name->matches = 4;
501 return;
502 }
503
504 if (!(p = strpbrkW( name->lang, sepW )))
505 {
506 if (!strcmpW( name->lang, posixW ) || !strcmpW( name->lang, cW ))
507 {
508 name->matches = 4; /* perfect match for default English lcid */
509 return;
510 }
511 strcpyW( name->win_name, name->lang );
512 }
513 else if (*p == '-') /* Windows format */
514 {
515 strcpyW( name->win_name, name->lang );
516 *p++ = 0;
517 name->country = p;
518 if ((p = strpbrkW( p, winsepW )) && *p == '-')
519 {
520 *p++ = 0;
521 name->script = name->country;
522 name->country = p;
523 p = strpbrkW( p, winsepW );
524 }
525 if (p)
526 {
527 *p++ = 0;
528 name->modifier = p;
529 }
530 /* second value can be script or country, check length to resolve the ambiguity */
531 if (!name->script && strlenW( name->country ) == 4)
532 {
533 name->script = name->country;
534 name->country = NULL;
535 }
536 }
537 else /* Unix format */
538 {
539 if (*p == '_')
540 {
541 *p++ = 0;
542 name->country = p;
543 p = strpbrkW( p, sepW + 2 );
544 }
545 if (p && *p == '.')
546 {
547 *p++ = 0;
548 name->charset = p;
549 p = strchrW( p, '@' );
550 }
551 if (p)
552 {
553 *p++ = 0;
554 name->modifier = p;
555 }
556
557 if (name->charset)
558 name->codepage = find_charset( name->charset );
559
560 /* rebuild a Windows name if possible */
561
562 if (name->charset) goto done; /* can't specify charset in Windows format */
563 if (name->modifier && strcmpW( name->modifier, latinW ))
564 goto done; /* only Latn script supported for now */
565 strcpyW( name->win_name, name->lang );
566 if (name->modifier) strcatW( name->win_name, latnW );
567 if (name->country)
568 {
569 p = name->win_name + strlenW(name->win_name);
570 *p++ = '-';
571 strcpyW( p, name->country );
572 }
573 }
574done:
576 find_locale_id_callback, (LPARAM)name );
577}
578#endif
579
580
581/***********************************************************************
582 * convert_default_lcid
583 *
584 * Get the default LCID to use for a given lctype in GetLocaleInfo.
585 */
587{
591 {
592 LCID default_id = 0;
593
594 switch(lctype & 0xffff)
595 {
596 case LOCALE_SSORTNAME:
597 default_id = lcid_LC_COLLATE;
598 break;
599
603 case LOCALE_IDEFAULTEBCDICCODEPAGE:
606 default_id = lcid_LC_CTYPE;
607 break;
608
610 case LOCALE_ICURRENCY:
612 case LOCALE_INEGCURR:
619 case LOCALE_SCURRENCY:
624 case LOCALE_SNATIVECURRNAME:
625 default_id = lcid_LC_MONETARY;
626 break;
627
628 case LOCALE_IDIGITS:
629 case LOCALE_IDIGITSUBSTITUTION:
630 case LOCALE_ILZERO:
632 case LOCALE_SDECIMAL:
633 case LOCALE_SGROUPING:
634 //case LOCALE_SNAN:
637 //case LOCALE_SNEGINFINITY:
638 //case LOCALE_SPOSINFINITY:
640 case LOCALE_STHOUSAND:
641 default_id = lcid_LC_NUMERIC;
642 break;
643
645 case LOCALE_ICENTURY:
646 case LOCALE_IDATE:
647 case LOCALE_IDAYLZERO:
650 case LOCALE_ILDATE:
651 case LOCALE_IMONLZERO:
653 case LOCALE_ITIME:
655 case LOCALE_ITLZERO:
656 case LOCALE_S1159:
657 case LOCALE_S2359:
678 case LOCALE_SDATE:
679 case LOCALE_SDAYNAME1:
680 case LOCALE_SDAYNAME2:
681 case LOCALE_SDAYNAME3:
682 case LOCALE_SDAYNAME4:
683 case LOCALE_SDAYNAME5:
684 case LOCALE_SDAYNAME6:
685 case LOCALE_SDAYNAME7:
686 //case LOCALE_SDURATION:
687 case LOCALE_SLONGDATE:
702 //case LOCALE_SSHORTESTDAYNAME1:
703 //case LOCALE_SSHORTESTDAYNAME2:
704 //case LOCALE_SSHORTESTDAYNAME3:
705 //case LOCALE_SSHORTESTDAYNAME4:
706 //case LOCALE_SSHORTESTDAYNAME5:
707 //case LOCALE_SSHORTESTDAYNAME6:
708 //case LOCALE_SSHORTESTDAYNAME7:
709 case LOCALE_STIME:
711 case LOCALE_SYEARMONTH:
712 default_id = lcid_LC_TIME;
713 break;
714
715 case LOCALE_IPAPERSIZE:
716 default_id = lcid_LC_PAPER;
717 break;
718
719 case LOCALE_IMEASURE:
720 default_id = lcid_LC_MEASUREMENT;
721 break;
722
723 case LOCALE_ICOUNTRY:
724 default_id = lcid_LC_TELEPHONE;
725 break;
726 }
727 if (default_id) lcid = default_id;
728 }
729 return ConvertDefaultLocale( lcid );
730}
731
732/***********************************************************************
733 * is_genitive_name_supported
734 *
735 * Determine could LCTYPE basically support genitive name form or not.
736 */
738{
739 switch(lctype & 0xffff)
740 {
754 return TRUE;
755 default:
756 return FALSE;
757 }
758}
759
760/***********************************************************************
761 * create_registry_key
762 *
763 * Create the Control Panel\\International registry key.
764 */
765static inline HANDLE create_registry_key(void)
766{
767 static const WCHAR cplW[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l',0};
768 static const WCHAR intlW[] = {'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
771 HANDLE cpl_key, hkey = 0;
772
773 if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey ) != STATUS_SUCCESS) return 0;
774
775 attr.Length = sizeof(attr);
776 attr.RootDirectory = hkey;
777 attr.ObjectName = &nameW;
778 attr.Attributes = 0;
779 attr.SecurityDescriptor = NULL;
780 attr.SecurityQualityOfService = NULL;
781 RtlInitUnicodeString( &nameW, cplW );
782
783 if (!NtCreateKey( &cpl_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
784 {
785 NtClose( attr.RootDirectory );
786 attr.RootDirectory = cpl_key;
787 RtlInitUnicodeString( &nameW, intlW );
788 if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) hkey = 0;
789 }
790 NtClose( attr.RootDirectory );
791 return hkey;
792}
793
794
795#ifndef __REACTOS__
796/* update the registry settings for a given locale parameter */
797/* return TRUE if an update was needed */
799 const LCTYPE *values, UINT nb_values )
800{
801 static const WCHAR formatW[] = { '%','0','8','x',0 };
802 WCHAR bufferW[40];
804 DWORD count, i;
805
807 count = sizeof(bufferW);
809 {
811 LPCWSTR text = (LPCWSTR)info->Data;
812
813 if (strtoulW( text, NULL, 16 ) == lcid) return FALSE; /* already set correctly */
814 TRACE( "updating registry, locale %s changed %s -> %08x\n",
816 }
817 else TRACE( "updating registry, locale %s changed none -> %08x\n", debugstr_w(name), lcid );
818 sprintfW( bufferW, formatW, lcid );
819 NtSetValueKey( hkey, &nameW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR) );
820
821 for (i = 0; i < nb_values; i++)
822 {
824 sizeof(bufferW)/sizeof(WCHAR) );
825 SetLocaleInfoW( lcid, values[i], bufferW );
826 }
827 return TRUE;
828}
829
830
831/***********************************************************************
832 * LOCALE_InitRegistry
833 *
834 * Update registry contents on startup if the user locale has changed.
835 * This simulates the action of the Windows control panel.
836 */
838{
839 static const WCHAR acpW[] = {'A','C','P',0};
840 static const WCHAR oemcpW[] = {'O','E','M','C','P',0};
841 static const WCHAR maccpW[] = {'M','A','C','C','P',0};
842 static const WCHAR localeW[] = {'L','o','c','a','l','e',0};
843 static const WCHAR lc_ctypeW[] = { 'L','C','_','C','T','Y','P','E',0 };
844 static const WCHAR lc_monetaryW[] = { 'L','C','_','M','O','N','E','T','A','R','Y',0 };
845 static const WCHAR lc_numericW[] = { 'L','C','_','N','U','M','E','R','I','C',0 };
846 static const WCHAR lc_timeW[] = { 'L','C','_','T','I','M','E',0 };
847 static const WCHAR lc_measurementW[] = { 'L','C','_','M','E','A','S','U','R','E','M','E','N','T',0 };
848 static const WCHAR lc_telephoneW[] = { 'L','C','_','T','E','L','E','P','H','O','N','E',0 };
849 static const WCHAR lc_paperW[] = { 'L','C','_','P','A','P','E','R',0};
850 static const struct
851 {
854 } update_cp_values[] = {
856 { oemcpW, LOCALE_IDEFAULTCODEPAGE },
858 };
859 static const LCTYPE lc_messages_values[] = {
862 LOCALE_SLIST };
863 static const LCTYPE lc_monetary_values[] = {
872 static const LCTYPE lc_numeric_values[] = {
876 LOCALE_IDIGITSUBSTITUTION,
882 static const LCTYPE lc_time_values[] = {
896 LOCALE_SYEARMONTH,
897 LOCALE_IDATE };
898 static const LCTYPE lc_measurement_values[] = { LOCALE_IMEASURE };
899 static const LCTYPE lc_telephone_values[] = { LOCALE_ICOUNTRY };
900 static const LCTYPE lc_paper_values[] = { LOCALE_IPAPERSIZE };
901
903 WCHAR bufferW[80];
904 DWORD count, i;
905 HANDLE hkey;
907
908 if (!(hkey = create_registry_key()))
909 return; /* don't do anything if we can't create the registry key */
910
911 locale_update_registry( hkey, localeW, lcid_LC_MESSAGES, lc_messages_values,
912 sizeof(lc_messages_values)/sizeof(lc_messages_values[0]) );
913 locale_update_registry( hkey, lc_monetaryW, lcid_LC_MONETARY, lc_monetary_values,
914 sizeof(lc_monetary_values)/sizeof(lc_monetary_values[0]) );
915 locale_update_registry( hkey, lc_numericW, lcid_LC_NUMERIC, lc_numeric_values,
916 sizeof(lc_numeric_values)/sizeof(lc_numeric_values[0]) );
917 locale_update_registry( hkey, lc_timeW, lcid_LC_TIME, lc_time_values,
918 sizeof(lc_time_values)/sizeof(lc_time_values[0]) );
919 locale_update_registry( hkey, lc_measurementW, lcid_LC_MEASUREMENT, lc_measurement_values,
920 sizeof(lc_measurement_values)/sizeof(lc_measurement_values[0]) );
921 locale_update_registry( hkey, lc_telephoneW, lcid_LC_TELEPHONE, lc_telephone_values,
922 sizeof(lc_telephone_values)/sizeof(lc_telephone_values[0]) );
923 locale_update_registry( hkey, lc_paperW, lcid_LC_PAPER, lc_paper_values,
924 sizeof(lc_paper_values)/sizeof(lc_paper_values[0]) );
925
926 if (locale_update_registry( hkey, lc_ctypeW, lcid_LC_CTYPE, NULL, 0 ))
927 {
928 static const WCHAR codepageW[] =
929 {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
930 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
931 'C','o','n','t','r','o','l','\\','N','l','s','\\','C','o','d','e','p','a','g','e',0};
932
934 HANDLE nls_key;
935 DWORD len = 14;
936
937 RtlInitUnicodeString( &nameW, codepageW );
939 while (codepageW[len])
940 {
941 nameW.Length = len * sizeof(WCHAR);
942 if (NtCreateKey( &nls_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) break;
943 NtClose( nls_key );
944 len++;
945 while (codepageW[len] && codepageW[len] != '\\') len++;
946 }
947 nameW.Length = len * sizeof(WCHAR);
948 if (!NtCreateKey( &nls_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
949 {
950 for (i = 0; i < sizeof(update_cp_values)/sizeof(update_cp_values[0]); i++)
951 {
952 count = GetLocaleInfoW( lcid, update_cp_values[i].value | LOCALE_NOUSEROVERRIDE,
953 bufferW, sizeof(bufferW)/sizeof(WCHAR) );
954 RtlInitUnicodeString( &nameW, update_cp_values[i].name );
955 NtSetValueKey( nls_key, &nameW, 0, REG_SZ, bufferW, count * sizeof(WCHAR) );
956 }
957 NtClose( nls_key );
958 }
959 }
960
961 NtClose( hkey );
962}
963
964
965#ifdef __APPLE__
966/***********************************************************************
967 * get_mac_locale
968 *
969 * Return a locale identifier string reflecting the Mac locale, in a form
970 * that parse_locale_name() will understand. So, strip out unusual
971 * things like script, variant, etc. Or, rather, just construct it as
972 * <lang>[_<country>].UTF-8.
973 */
974static const char* get_mac_locale(void)
975{
976 static char mac_locale[50];
977
978 if (!mac_locale[0])
979 {
980 CFLocaleRef locale = CFLocaleCopyCurrent();
981 CFStringRef lang = CFLocaleGetValue( locale, kCFLocaleLanguageCode );
982 CFStringRef country = CFLocaleGetValue( locale, kCFLocaleCountryCode );
983 CFStringRef locale_string;
984
985 if (country)
986 locale_string = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@_%@"), lang, country);
987 else
988 locale_string = CFStringCreateCopy(NULL, lang);
989
990 CFStringGetCString(locale_string, mac_locale, sizeof(mac_locale), kCFStringEncodingUTF8);
991 strcat(mac_locale, ".UTF-8");
992
993 CFRelease(locale);
994 CFRelease(locale_string);
995 }
996
997 return mac_locale;
998}
999
1000
1001/***********************************************************************
1002 * has_env
1003 */
1004static BOOL has_env(const char* name)
1005{
1006 const char* value = getenv( name );
1007 return value && value[0];
1008}
1009#endif
1010
1011
1012/***********************************************************************
1013 * get_locale
1014 *
1015 * Get the locale identifier for a given category. On most platforms,
1016 * this is just a thin wrapper around setlocale(). On OS X, though, it
1017 * is common for the Mac locale settings to not be supported by the C
1018 * library. So, we sometimes override the result with the Mac locale.
1019 */
1020static const char* get_locale(int category, const char* category_name)
1021{
1022 const char* ret = setlocale(category, NULL);
1023
1024#ifdef __ANDROID__
1025 if (!strcmp(ret, "C"))
1026 {
1027 ret = getenv( category_name );
1028 if (!ret || !ret[0]) ret = getenv( "LC_ALL" );
1029 if (!ret || !ret[0]) ret = "C";
1030 }
1031#endif
1032
1033#ifdef __APPLE__
1034 /* If LC_ALL is set, respect it as a user override.
1035 If LC_* is set, respect it as a user override, except if it's LC_CTYPE
1036 and equal to UTF-8. That's because, when the Mac locale isn't supported
1037 by the C library, Terminal.app sets LC_CTYPE=UTF-8 and doesn't set LANG.
1038 parse_locale_name() doesn't handle that properly, so we override that
1039 with the Mac locale (which uses UTF-8 for the charset, anyway).
1040 Otherwise:
1041 For LC_MESSAGES, we override the C library because the user language
1042 setting is separate from the locale setting on which LANG was based.
1043 If the C library didn't get anything better from LANG than C or POSIX,
1044 override that. That probably means the Mac locale isn't supported by
1045 the C library. */
1046 if (!has_env( "LC_ALL" ) &&
1047 ((category == LC_CTYPE && !strcmp( ret, "UTF-8" )) ||
1048 (!has_env( category_name ) &&
1049 (category == LC_MESSAGES || !strcmp( ret, "C" ) || !strcmp( ret, "POSIX" )))))
1050 {
1051 const char* override = get_mac_locale();
1052
1053 if (category == LC_MESSAGES)
1054 {
1055 /* Retrieve the preferred language as chosen in System Preferences. */
1056 static char messages_locale[50];
1057
1058 if (!messages_locale[0])
1059 {
1060 CFArrayRef preferred_langs = CFLocaleCopyPreferredLanguages();
1061 if (preferred_langs && CFArrayGetCount( preferred_langs ))
1062 {
1063 CFStringRef preferred_lang = CFArrayGetValueAtIndex( preferred_langs, 0 );
1064 CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier( NULL, preferred_lang );
1065 if (components)
1066 {
1067 CFStringRef lang = CFDictionaryGetValue( components, kCFLocaleLanguageCode );
1068 CFStringRef country = CFDictionaryGetValue( components, kCFLocaleCountryCode );
1069 CFLocaleRef locale = NULL;
1070 CFStringRef locale_string;
1071
1072 if (!country)
1073 {
1074 locale = CFLocaleCopyCurrent();
1075 country = CFLocaleGetValue( locale, kCFLocaleCountryCode );
1076 }
1077
1078 if (country)
1079 locale_string = CFStringCreateWithFormat( NULL, NULL, CFSTR("%@_%@"), lang, country );
1080 else
1081 locale_string = CFStringCreateCopy( NULL, lang );
1082 CFStringGetCString( locale_string, messages_locale, sizeof(messages_locale), kCFStringEncodingUTF8 );
1083 strcat( messages_locale, ".UTF-8" );
1084
1085 CFRelease( locale_string );
1086 if (locale) CFRelease( locale );
1087 CFRelease( components );
1088 }
1089 }
1090 if (preferred_langs)
1091 CFRelease( preferred_langs );
1092 }
1093
1094 if (messages_locale[0])
1095 override = messages_locale;
1096 }
1097
1098 TRACE( "%s is %s; overriding with %s\n", category_name, debugstr_a(ret), debugstr_a(override) );
1099 ret = override;
1100 }
1101#endif
1102
1103 return ret;
1104}
1105
1106
1107/***********************************************************************
1108 * setup_unix_locales
1109 */
1111{
1112 struct locale_name locale_name;
1113 WCHAR buffer[128], ctype_buff[128];
1114 const char *locale;
1115 UINT unix_cp = 0;
1116
1117 if ((locale = get_locale( LC_CTYPE, "LC_CTYPE" )))
1118 {
1119 strcpynAtoW( ctype_buff, locale, sizeof(ctype_buff)/sizeof(WCHAR) );
1120 parse_locale_name( ctype_buff, &locale_name );
1122 unix_cp = locale_name.codepage;
1123 }
1124 if (!lcid_LC_CTYPE) /* this one needs a default value */
1126
1127 TRACE( "got lcid %04x (%d matches) for LC_CTYPE=%s\n",
1129
1130#define GET_UNIX_LOCALE(cat) do \
1131 if ((locale = get_locale( cat, #cat ))) \
1132 { \
1133 strcpynAtoW( buffer, locale, sizeof(buffer)/sizeof(WCHAR) ); \
1134 if (!strcmpW( buffer, ctype_buff )) lcid_##cat = lcid_LC_CTYPE; \
1135 else { \
1136 parse_locale_name( buffer, &locale_name ); \
1137 lcid_##cat = locale_name.lcid; \
1138 TRACE( "got lcid %04x (%d matches) for " #cat "=%s\n", \
1139 locale_name.lcid, locale_name.matches, debugstr_a(locale) ); \
1140 } \
1141 } while (0)
1142
1144 GET_UNIX_LOCALE( LC_MESSAGES );
1148#ifdef LC_PAPER
1149 GET_UNIX_LOCALE( LC_PAPER );
1150#endif
1151#ifdef LC_MEASUREMENT
1152 GET_UNIX_LOCALE( LC_MEASUREMENT );
1153#endif
1154#ifdef LC_TELEPHONE
1155 GET_UNIX_LOCALE( LC_TELEPHONE );
1156#endif
1157
1158#undef GET_UNIX_LOCALE
1159
1160 return unix_cp;
1161}
1162#endif // !__REACTOS__
1163
1164
1165/***********************************************************************
1166 * GetUserDefaultLangID (KERNEL32.@)
1167 *
1168 * Get the default language Id for the current user.
1169 *
1170 * PARAMS
1171 * None.
1172 *
1173 * RETURNS
1174 * The current LANGID of the default language for the current user.
1175 */
1177{
1179}
1180
1181
1182/***********************************************************************
1183 * GetSystemDefaultLangID (KERNEL32.@)
1184 *
1185 * Get the default language Id for the system.
1186 *
1187 * PARAMS
1188 * None.
1189 *
1190 * RETURNS
1191 * The current LANGID of the default language for the system.
1192 */
1194{
1196}
1197
1198
1199/***********************************************************************
1200 * GetUserDefaultLCID (KERNEL32.@)
1201 *
1202 * Get the default locale Id for the current user.
1203 *
1204 * PARAMS
1205 * None.
1206 *
1207 * RETURNS
1208 * The current LCID of the default locale for the current user.
1209 */
1211{
1212 LCID lcid;
1214 return lcid;
1215}
1216
1217
1218/***********************************************************************
1219 * GetSystemDefaultLCID (KERNEL32.@)
1220 *
1221 * Get the default locale Id for the system.
1222 *
1223 * PARAMS
1224 * None.
1225 *
1226 * RETURNS
1227 * The current LCID of the default locale for the system.
1228 */
1230{
1231 LCID lcid;
1233 return lcid;
1234}
1235
1236#ifndef __REACTOS__
1237/***********************************************************************
1238 * GetSystemDefaultLocaleName (KERNEL32.@)
1239 */
1241{
1243 return LCIDToLocaleName(lcid, localename, len, 0);
1244}
1245
1247{
1248 LCTYPE type;
1249 int lsize;
1250
1251 FIXME("(0x%x %p %p %p) returning a dummy value (current locale)\n", flags, count, buffer, size);
1252
1253 if (flags & MUI_LANGUAGE_ID)
1255 else
1257
1259 if (!lsize)
1260 {
1261 /* keep last error from callee */
1262 return FALSE;
1263 }
1264 lsize++;
1265 if (!*size)
1266 {
1267 *size = lsize;
1268 *count = 1;
1269 return TRUE;
1270 }
1271
1272 if (lsize > *size)
1273 {
1275 return FALSE;
1276 }
1277
1279 {
1280 /* keep last error from callee */
1281 return FALSE;
1282 }
1283
1284 buffer[lsize-1] = 0;
1285 *size = lsize;
1286 *count = 1;
1287 TRACE("returned variable content: %d, \"%s\", %d\n", *count, debugstr_w(buffer), *size);
1288 return TRUE;
1289
1290}
1291
1292/***********************************************************************
1293 * GetSystemPreferredUILanguages (KERNEL32.@)
1294 */
1296{
1297 if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID | MUI_MACHINE_LANGUAGE_SETTINGS))
1298 {
1300 return FALSE;
1301 }
1302 if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID))
1303 {
1305 return FALSE;
1306 }
1307 if (*size && !buffer)
1308 {
1310 return FALSE;
1311 }
1312
1314}
1315
1316/***********************************************************************
1317 * SetThreadPreferredUILanguages (KERNEL32.@)
1318 */
1320{
1321 FIXME( "%u, %p, %p\n", flags, buffer, count );
1322 return TRUE;
1323}
1324
1325/***********************************************************************
1326 * GetThreadPreferredUILanguages (KERNEL32.@)
1327 */
1329{
1330 FIXME( "%08x, %p, %p %p\n", flags, count, buf, size );
1332}
1333
1334#if (WINVER >= 0x0600)
1335/******************************************************************************
1336 * GetUserPreferredUILanguages (KERNEL32.@)
1337 */
1339{
1340 TRACE( "%u %p %p %p\n", flags, count, buffer, size );
1341
1342 if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID))
1343 {
1345 return FALSE;
1346 }
1347 if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID))
1348 {
1350 return FALSE;
1351 }
1352 if (*size && !buffer)
1353 {
1355 return FALSE;
1356 }
1357
1359}
1360#endif // (WINVER >= 0x0600)
1361#endif // !__REACTOS__
1362
1363/***********************************************************************
1364 * GetUserDefaultUILanguage (KERNEL32.@)
1365 *
1366 * Get the default user interface language Id for the current user.
1367 *
1368 * PARAMS
1369 * None.
1370 *
1371 * RETURNS
1372 * The current LANGID of the default UI language for the current user.
1373 */
1375{
1376 LANGID lang;
1378 return lang;
1379}
1380
1381
1382/***********************************************************************
1383 * GetSystemDefaultUILanguage (KERNEL32.@)
1384 *
1385 * Get the default user interface language Id for the system.
1386 *
1387 * PARAMS
1388 * None.
1389 *
1390 * RETURNS
1391 * The current LANGID of the default UI language for the system. This is
1392 * typically the same language used during the installation process.
1393 */
1395{
1396 LANGID lang;
1398 return lang;
1399}
1400
1401#if (WINVER >= 0x0600)
1402/***********************************************************************
1403 * LocaleNameToLCID (KERNEL32.@)
1404 */
1405LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags )
1406{
1407 struct locale_name locale_name;
1408
1409 if (flags) FIXME( "unsupported flags %x\n", flags );
1410
1412 return GetUserDefaultLCID();
1413
1414 /* string parsing */
1415 parse_locale_name( name, &locale_name );
1416
1417 TRACE( "found lcid %x for %s, matches %d\n",
1419
1420 if (!locale_name.matches)
1421 {
1423 return 0;
1424 }
1425
1426 if (locale_name.matches == 1)
1427 WARN( "locale %s not recognized, defaulting to %s\n",
1429
1430 return locale_name.lcid;
1431}
1432
1433
1434/***********************************************************************
1435 * LCIDToLocaleName (KERNEL32.@)
1436 */
1437INT WINAPI LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags )
1438{
1439 if (flags) FIXME( "unsupported flags %x\n", flags );
1440
1442}
1443#endif
1444
1445
1446/******************************************************************************
1447 * get_locale_registry_value
1448 *
1449 * Gets the registry value name and cache for a given lctype.
1450 */
1452{
1453 int i;
1454 for (i=0; i < sizeof(registry_values)/sizeof(registry_values[0]); i++)
1456 return &registry_values[i];
1457 return NULL;
1458}
1459
1460
1461/******************************************************************************
1462 * get_registry_locale_info
1463 *
1464 * Retrieve user-modified locale info from the registry.
1465 * Return length, 0 on error, -1 if not found.
1466 */
1468{
1469 DWORD size;
1470 INT ret;
1471 HANDLE hkey;
1475 static const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
1476
1478
1480 {
1481 if (!(hkey = create_registry_key()))
1482 {
1484 return -1;
1485 }
1486
1488 size = info_size + len * sizeof(WCHAR);
1489
1490 if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
1491 {
1492 NtClose( hkey );
1495 return 0;
1496 }
1497
1499
1500 /* try again with a bigger buffer when we have to return the correct size */
1501 if (status == STATUS_BUFFER_OVERFLOW && !buffer && size > info_size)
1502 {
1504 if ((new_info = HeapReAlloc( GetProcessHeap(), 0, info, size )))
1505 {
1506 info = new_info;
1508 }
1509 }
1510
1511 NtClose( hkey );
1512
1513 if (!status)
1514 {
1515 INT length = (size - info_size) / sizeof(WCHAR);
1517
1518 if (!length || ((WCHAR *)&info->Data)[length-1])
1519 length++;
1520
1521 cached_value = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) );
1522
1523 if (!cached_value)
1524 {
1525 HeapFree( GetProcessHeap(), 0, info );
1528 return 0;
1529 }
1530
1531 memcpy( cached_value, info->Data, (length-1) * sizeof(WCHAR) );
1532 cached_value[length-1] = 0;
1533 HeapFree( GetProcessHeap(), 0, info );
1535 }
1536 else
1537 {
1539 {
1540 ret = (size - info_size) / sizeof(WCHAR);
1541 }
1543 {
1544 ret = -1;
1545 }
1546 else
1547 {
1549 ret = 0;
1550 }
1551 HeapFree( GetProcessHeap(), 0, info );
1553 return ret;
1554 }
1555 }
1556
1558
1559 if (buffer)
1560 {
1561 if (ret > len)
1562 {
1564 ret = 0;
1565 }
1566 else
1567 {
1569 }
1570 }
1571
1573
1574 return ret;
1575}
1576
1577
1578/******************************************************************************
1579 * GetLocaleInfoA (KERNEL32.@)
1580 *
1581 * Get information about an aspect of a locale.
1582 *
1583 * PARAMS
1584 * lcid [I] LCID of the locale
1585 * lctype [I] LCTYPE_ flags from "winnls.h"
1586 * buffer [O] Destination for the information
1587 * len [I] Length of buffer in characters
1588 *
1589 * RETURNS
1590 * Success: The size of the data requested. If buffer is non-NULL, it is filled
1591 * with the information.
1592 * Failure: 0. Use GetLastError() to determine the cause.
1593 *
1594 * NOTES
1595 * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
1596 * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE,
1597 * which is a bit string.
1598 */
1600{
1601 WCHAR *bufferW;
1602 INT lenW, ret;
1603
1604 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len );
1605
1606 if (len < 0 || (len && !buffer))
1607 {
1609 return 0;
1610 }
1613 {
1615 return 0;
1616 }
1617
1618 if (!len) buffer = NULL;
1619
1620 if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0;
1621
1622 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
1623 {
1625 return 0;
1626 }
1627 if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW )))
1628 {
1629 if ((lctype & LOCALE_RETURN_NUMBER) ||
1631 {
1632 /* it's not an ASCII string, just bytes */
1633 ret *= sizeof(WCHAR);
1634 if (buffer)
1635 {
1636 if (ret <= len) memcpy( buffer, bufferW, ret );
1637 else
1638 {
1640 ret = 0;
1641 }
1642 }
1643 }
1644 else
1645 {
1648 ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL );
1649 }
1650 }
1651 HeapFree( GetProcessHeap(), 0, bufferW );
1652 return ret;
1653}
1654
1656{
1657 return lctype == LOCALE_ILANGUAGE || lctype == LOCALE_IDEFAULTLANGUAGE ? 16 : 10;
1658}
1659
1660/******************************************************************************
1661 * GetLocaleInfoW (KERNEL32.@)
1662 *
1663 * See GetLocaleInfoA.
1664 */
1666{
1667 LANGID lang_id;
1668 HRSRC hrsrc;
1669 HGLOBAL hmem;
1670 INT ret;
1671 UINT lcflags;
1672 const WCHAR *p;
1673 unsigned int i;
1674
1675 if (len < 0 || (len && !buffer))
1676 {
1678 return 0;
1679 }
1682 {
1684 return 0;
1685 }
1686
1687 if (!len) buffer = NULL;
1688
1689 lcid = convert_default_lcid( lcid, lctype );
1690
1692 lctype &= 0xffff;
1693
1694 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len );
1695
1696 /* first check for overrides in the registry */
1697
1698 if (!(lcflags & LOCALE_NOUSEROVERRIDE) &&
1700 {
1702
1703 if (value)
1704 {
1705 if (lcflags & LOCALE_RETURN_NUMBER)
1706 {
1707 WCHAR tmp[16];
1708 ret = get_registry_locale_info( value, tmp, sizeof(tmp)/sizeof(WCHAR) );
1709 if (ret > 0)
1710 {
1711 WCHAR *end;
1713 if (*end) /* invalid number */
1714 {
1716 return 0;
1717 }
1718 ret = sizeof(UINT)/sizeof(WCHAR);
1719 if (!buffer) return ret;
1720 if (ret > len)
1721 {
1723 return 0;
1724 }
1725 memcpy( buffer, &number, sizeof(number) );
1726 }
1727 }
1729
1730 if (ret != -1) return ret;
1731 }
1732 }
1733
1734 /* now load it from kernel resources */
1735
1736 lang_id = LANGIDFROMLCID( lcid );
1737
1738 /* replace SUBLANG_NEUTRAL by SUBLANG_DEFAULT */
1739 if (SUBLANGID(lang_id) == SUBLANG_NEUTRAL) lang_id = get_default_sublang( lang_id );
1740
1742 ULongToPtr((lctype >> 4) + 1), lang_id )))
1743 {
1744 SetLastError( ERROR_INVALID_FLAGS ); /* no such lctype */
1745 return 0;
1746 }
1747 if (!(hmem = LoadResource( kernel32_handle, hrsrc )))
1748 return 0;
1749
1750 p = LockResource( hmem );
1751 for (i = 0; i < (lctype & 0x0f); i++) p += *p + 1;
1752
1753 if (lcflags & LOCALE_RETURN_NUMBER) ret = sizeof(UINT)/sizeof(WCHAR);
1754 else if (is_genitive_name_supported( lctype ) && *p)
1755 {
1756 /* genitive form's stored after a null separator from a nominative */
1757 for (i = 1; i <= *p; i++) if (!p[i]) break;
1758
1759 if (i <= *p && (lcflags & LOCALE_RETURN_GENITIVE_NAMES))
1760 {
1761 ret = *p - i + 1;
1762 p += i;
1763 }
1764 else ret = i;
1765 }
1766 else
1767 ret = (lctype == LOCALE_FONTSIGNATURE) ? *p : *p + 1;
1768
1769 if (!buffer) return ret;
1770
1771 if (ret > len)
1772 {
1774 return 0;
1775 }
1776
1777 if (lcflags & LOCALE_RETURN_NUMBER)
1778 {
1779 UINT number;
1780 WCHAR *end, *tmp = HeapAlloc( GetProcessHeap(), 0, (*p + 1) * sizeof(WCHAR) );
1781 if (!tmp) return 0;
1782 memcpy( tmp, p + 1, *p * sizeof(WCHAR) );
1783 tmp[*p] = 0;
1785 if (!*end)
1786 memcpy( buffer, &number, sizeof(number) );
1787 else /* invalid number */
1788 {
1790 ret = 0;
1791 }
1792 HeapFree( GetProcessHeap(), 0, tmp );
1793
1794 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning number %d\n",
1795 lcid, lctype, buffer, len, number );
1796 }
1797 else
1798 {
1799 memcpy( buffer, p + 1, ret * sizeof(WCHAR) );
1800 if (lctype != LOCALE_FONTSIGNATURE) buffer[ret-1] = 0;
1801
1802 TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning %d %s\n",
1803 lcid, lctype, buffer, len, ret, debugstr_w(buffer) );
1804 }
1805 return ret;
1806}
1807
1808#if (WINVER >= 0x0600)
1809/******************************************************************************
1810 * GetLocaleInfoEx (KERNEL32.@)
1811 */
1812INT WINAPI GetLocaleInfoEx(LPCWSTR locale, LCTYPE info, LPWSTR buffer, INT len)
1813{
1814 LCID lcid = LocaleNameToLCID(locale, 0);
1815
1816 TRACE("%s, lcid=0x%x, 0x%x\n", debugstr_w(locale), lcid, info);
1817
1818 if (!lcid) return 0;
1819
1820 /* special handling for neutral locale names */
1821 if (locale && strlenW(locale) == 2)
1822 {
1823 switch (info)
1824 {
1825 case LOCALE_SNAME:
1826 if (len && len < 3)
1827 {
1829 return 0;
1830 }
1831 if (len) strcpyW(buffer, locale);
1832 return 3;
1833 case LOCALE_SPARENT:
1834 if (len) buffer[0] = 0;
1835 return 1;
1836 }
1837 }
1838
1839 return GetLocaleInfoW(lcid, info, buffer, len);
1840}
1841
1842BOOL
1843WINAPI
1845 LPCWSTR lpLocaleName
1846)
1847{
1848 TRACE( "IsValidLocaleName not implemented (lpLocaleName=%s)\n", debugstr_w(lpLocaleName));
1849 return TRUE;
1850}
1851
1852INT
1853WINAPI
1855 LPWSTR lpLocaleName,
1856 INT cchLocaleName
1857)
1858{
1859 TRACE( "GetUserDefaultLocaleName not implemented (lpLocaleName=%s, cchLocaleName=%d)\n", debugstr_w(lpLocaleName), cchLocaleName);
1860 return 0;
1861}
1862#endif
1863
1864/******************************************************************************
1865 * SetLocaleInfoA [KERNEL32.@]
1866 *
1867 * Set information about an aspect of a locale.
1868 *
1869 * PARAMS
1870 * lcid [I] LCID of the locale
1871 * lctype [I] LCTYPE_ flags from "winnls.h"
1872 * data [I] Information to set
1873 *
1874 * RETURNS
1875 * Success: TRUE. The information given will be returned by GetLocaleInfoA()
1876 * whenever it is called without LOCALE_NOUSEROVERRIDE.
1877 * Failure: FALSE. Use GetLastError() to determine the cause.
1878 *
1879 * NOTES
1880 * - Values are only be set for the current user locale; the system locale
1881 * settings cannot be changed.
1882 * - Any settings changed by this call are lost when the locale is changed by
1883 * the control panel (in Wine, this happens every time you change LANG).
1884 * - The native implementation of this function does not check that lcid matches
1885 * the current user locale, and simply sets the new values. Wine warns you in
1886 * this case, but behaves the same.
1887 */
1889{
1891 WCHAR *strW;
1892 DWORD len;
1893 BOOL ret;
1894
1896
1897 if (!data)
1898 {
1900 return FALSE;
1901 }
1902 len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 );
1903 if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
1904 {
1906 return FALSE;
1907 }
1909 ret = SetLocaleInfoW( lcid, lctype, strW );
1910 HeapFree( GetProcessHeap(), 0, strW );
1911 return ret;
1912}
1913
1914
1915/******************************************************************************
1916 * SetLocaleInfoW (KERNEL32.@)
1917 *
1918 * See SetLocaleInfoA.
1919 */
1921{
1922 struct registry_value *value;
1923 static const WCHAR intlW[] = {'i','n','t','l',0 };
1926 HANDLE hkey;
1927
1928 lctype &= 0xffff;
1930
1931 if (!data || !value)
1932 {
1934 return FALSE;
1935 }
1936
1938 {
1940 return FALSE;
1941 }
1942
1943 TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value->name), debugstr_w(data) );
1944
1945 /* FIXME: should check that data to set is sane */
1946
1947 /* FIXME: profile functions should map to registry */
1948 WriteProfileStringW( intlW, value->name, data );
1949
1950 if (!(hkey = create_registry_key())) return FALSE;
1952 status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, (PVOID)data, (strlenW(data)+1)*sizeof(WCHAR) );
1953
1955 HeapFree( GetProcessHeap(), 0, value->cached_value );
1956 value->cached_value = NULL;
1958
1960 {
1961 /* Set I-value from S value */
1962 WCHAR *lpD, *lpM, *lpY;
1963 WCHAR szBuff[2];
1964
1965 lpD = strrchrW(data, 'd');
1966 lpM = strrchrW(data, 'M');
1967 lpY = strrchrW(data, 'y');
1968
1969 if (lpD <= lpM)
1970 {
1971 szBuff[0] = '1'; /* D-M-Y */
1972 }
1973 else
1974 {
1975 if (lpY <= lpM)
1976 szBuff[0] = '2'; /* Y-M-D */
1977 else
1978 szBuff[0] = '0'; /* M-D-Y */
1979 }
1980
1981 szBuff[1] = '\0';
1982
1985 else
1987
1989
1990 WriteProfileStringW( intlW, value->name, szBuff );
1991
1993 status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) );
1994
1996 HeapFree( GetProcessHeap(), 0, value->cached_value );
1997 value->cached_value = NULL;
1999 }
2000
2001 NtClose( hkey );
2002
2004 return !status;
2005}
2006
2007
2008#ifndef __REACTOS__
2009/******************************************************************************
2010 * GetACP (KERNEL32.@)
2011 *
2012 * Get the current Ansi code page Id for the system.
2013 *
2014 * PARAMS
2015 * None.
2016 *
2017 * RETURNS
2018 * The current Ansi code page identifier for the system.
2019 */
2021{
2023 return ansi_cptable->info.codepage;
2024}
2025
2026
2027/******************************************************************************
2028 * SetCPGlobal (KERNEL32.@)
2029 *
2030 * Set the current Ansi code page Id for the system.
2031 *
2032 * PARAMS
2033 * acp [I] code page ID to be the new ACP.
2034 *
2035 * RETURNS
2036 * The previous ACP.
2037 */
2039{
2040 UINT ret = GetACP();
2041 const union cptable *new_cptable = wine_cp_get_table( acp );
2042
2043 if (new_cptable) ansi_cptable = new_cptable;
2044 return ret;
2045}
2046
2047
2048/***********************************************************************
2049 * GetOEMCP (KERNEL32.@)
2050 *
2051 * Get the current OEM code page Id for the system.
2052 *
2053 * PARAMS
2054 * None.
2055 *
2056 * RETURNS
2057 * The current OEM code page identifier for the system.
2058 */
2060{
2062 return oem_cptable->info.codepage;
2063}
2064
2065
2066/***********************************************************************
2067 * IsValidCodePage (KERNEL32.@)
2068 *
2069 * Determine if a given code page identifier is valid.
2070 *
2071 * PARAMS
2072 * codepage [I] Code page Id to verify.
2073 *
2074 * RETURNS
2075 * TRUE, If codepage is valid and available on the system,
2076 * FALSE otherwise.
2077 */
2079{
2080 switch(codepage) {
2081 case CP_UTF7:
2082 case CP_UTF8:
2083 return TRUE;
2084 default:
2085 return wine_cp_get_table( codepage ) != NULL;
2086 }
2087}
2088
2089
2090/***********************************************************************
2091 * IsDBCSLeadByteEx (KERNEL32.@)
2092 *
2093 * Determine if a character is a lead byte in a given code page.
2094 *
2095 * PARAMS
2096 * codepage [I] Code page for the test.
2097 * testchar [I] Character to test
2098 *
2099 * RETURNS
2100 * TRUE, if testchar is a lead byte in codepage,
2101 * FALSE otherwise.
2102 */
2104{
2105 const union cptable *table = get_codepage_table( codepage );
2106 return table && wine_is_dbcs_leadbyte( table, testchar );
2107}
2108
2109
2110/***********************************************************************
2111 * IsDBCSLeadByte (KERNEL32.@)
2112 * IsDBCSLeadByte (KERNEL.207)
2113 *
2114 * Determine if a character is a lead byte.
2115 *
2116 * PARAMS
2117 * testchar [I] Character to test
2118 *
2119 * RETURNS
2120 * TRUE, if testchar is a lead byte in the ANSI code page,
2121 * FALSE otherwise.
2122 */
2124{
2125 if (!ansi_cptable) return FALSE;
2126 return wine_is_dbcs_leadbyte( ansi_cptable, testchar );
2127}
2128
2129
2130/***********************************************************************
2131 * GetCPInfo (KERNEL32.@)
2132 *
2133 * Get information about a code page.
2134 *
2135 * PARAMS
2136 * codepage [I] Code page number
2137 * cpinfo [O] Destination for code page information
2138 *
2139 * RETURNS
2140 * Success: TRUE. cpinfo is updated with the information about codepage.
2141 * Failure: FALSE, if codepage is invalid or cpinfo is NULL.
2142 */
2144{
2145 const union cptable *table;
2146
2147 if (!cpinfo)
2148 {
2150 return FALSE;
2151 }
2152
2153 if (!(table = get_codepage_table( codepage )))
2154 {
2155 switch(codepage)
2156 {
2157 case CP_UTF7:
2158 case CP_UTF8:
2159 cpinfo->DefaultChar[0] = 0x3f;
2160 cpinfo->DefaultChar[1] = 0;
2161 cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0;
2162 cpinfo->MaxCharSize = (codepage == CP_UTF7) ? 5 : 4;
2163 return TRUE;
2164 }
2165
2167 return FALSE;
2168 }
2169 if (table->info.def_char & 0xff00)
2170 {
2171 cpinfo->DefaultChar[0] = (table->info.def_char & 0xff00) >> 8;
2172 cpinfo->DefaultChar[1] = table->info.def_char & 0x00ff;
2173 }
2174 else
2175 {
2176 cpinfo->DefaultChar[0] = table->info.def_char & 0xff;
2177 cpinfo->DefaultChar[1] = 0;
2178 }
2179 if ((cpinfo->MaxCharSize = table->info.char_size) == 2)
2180 memcpy( cpinfo->LeadByte, table->dbcs.lead_bytes, sizeof(cpinfo->LeadByte) );
2181 else
2182 cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0;
2183
2184 return TRUE;
2185}
2186
2187/***********************************************************************
2188 * GetCPInfoExA (KERNEL32.@)
2189 *
2190 * Get extended information about a code page.
2191 *
2192 * PARAMS
2193 * codepage [I] Code page number
2194 * dwFlags [I] Reserved, must to 0.
2195 * cpinfo [O] Destination for code page information
2196 *
2197 * RETURNS
2198 * Success: TRUE. cpinfo is updated with the information about codepage.
2199 * Failure: FALSE, if codepage is invalid or cpinfo is NULL.
2200 */
2202{
2203 CPINFOEXW cpinfoW;
2204
2205 if (!GetCPInfoExW( codepage, dwFlags, &cpinfoW ))
2206 return FALSE;
2207
2208 /* the layout is the same except for CodePageName */
2209 memcpy(cpinfo, &cpinfoW, sizeof(CPINFOEXA));
2210 WideCharToMultiByte(CP_ACP, 0, cpinfoW.CodePageName, -1, cpinfo->CodePageName, sizeof(cpinfo->CodePageName), NULL, NULL);
2211 return TRUE;
2212}
2213
2214/***********************************************************************
2215 * GetCPInfoExW (KERNEL32.@)
2216 *
2217 * Unicode version of GetCPInfoExA.
2218 */
2220{
2221 if (!GetCPInfo( codepage, (LPCPINFO)cpinfo ))
2222 return FALSE;
2223
2224 switch(codepage)
2225 {
2226 case CP_UTF7:
2227 {
2228 static const WCHAR utf7[] = {'U','n','i','c','o','d','e',' ','(','U','T','F','-','7',')',0};
2229
2230 cpinfo->CodePage = CP_UTF7;
2231 cpinfo->UnicodeDefaultChar = 0x3f;
2232 strcpyW(cpinfo->CodePageName, utf7);
2233 break;
2234 }
2235
2236 case CP_UTF8:
2237 {
2238 static const WCHAR utf8[] = {'U','n','i','c','o','d','e',' ','(','U','T','F','-','8',')',0};
2239
2240 cpinfo->CodePage = CP_UTF8;
2241 cpinfo->UnicodeDefaultChar = 0x3f;
2242 strcpyW(cpinfo->CodePageName, utf8);
2243 break;
2244 }
2245
2246 default:
2247 {
2248 const union cptable *table = get_codepage_table( codepage );
2249
2250 cpinfo->CodePage = table->info.codepage;
2251 cpinfo->UnicodeDefaultChar = table->info.def_unicode_char;
2252 MultiByteToWideChar( CP_ACP, 0, table->info.name, -1, cpinfo->CodePageName,
2253 sizeof(cpinfo->CodePageName)/sizeof(WCHAR));
2254 break;
2255 }
2256 }
2257 return TRUE;
2258}
2259
2260/***********************************************************************
2261 * EnumSystemCodePagesA (KERNEL32.@)
2262 *
2263 * Call a user defined function for every code page installed on the system.
2264 *
2265 * PARAMS
2266 * lpfnCodePageEnum [I] User CODEPAGE_ENUMPROC to call with each found code page
2267 * flags [I] Reserved, set to 0.
2268 *
2269 * RETURNS
2270 * TRUE, If all code pages have been enumerated, or
2271 * FALSE if lpfnCodePageEnum returned FALSE to stop the enumeration.
2272 */
2274{
2275 const union cptable *table;
2276 char buffer[10];
2277 int index = 0;
2278
2279 for (;;)
2280 {
2281 if (!(table = wine_cp_enum_table( index++ ))) break;
2282 sprintf( buffer, "%d", table->info.codepage );
2283 if (!lpfnCodePageEnum( buffer )) break;
2284 }
2285 return TRUE;
2286}
2287
2288
2289/***********************************************************************
2290 * EnumSystemCodePagesW (KERNEL32.@)
2291 *
2292 * See EnumSystemCodePagesA.
2293 */
2295{
2296 const union cptable *table;
2297 WCHAR buffer[10], *p;
2298 int page, index = 0;
2299
2300 for (;;)
2301 {
2302 if (!(table = wine_cp_enum_table( index++ ))) break;
2303 p = buffer + sizeof(buffer)/sizeof(WCHAR);
2304 *--p = 0;
2305 page = table->info.codepage;
2306 do
2307 {
2308 *--p = '0' + (page % 10);
2309 page /= 10;
2310 } while( page );
2311 if (!lpfnCodePageEnum( p )) break;
2312 }
2313 return TRUE;
2314}
2315
2316
2317/***********************************************************************
2318 * utf7_write_w
2319 *
2320 * Helper for utf7_mbstowcs
2321 *
2322 * RETURNS
2323 * TRUE on success, FALSE on error
2324 */
2325static inline BOOL utf7_write_w(WCHAR *dst, int dstlen, int *index, WCHAR character)
2326{
2327 if (dstlen > 0)
2328 {
2329 if (*index >= dstlen)
2330 return FALSE;
2331
2332 dst[*index] = character;
2333 }
2334
2335 (*index)++;
2336
2337 return TRUE;
2338}
2339
2340/***********************************************************************
2341 * utf7_mbstowcs
2342 *
2343 * UTF-7 to UTF-16 string conversion, helper for MultiByteToWideChar
2344 *
2345 * RETURNS
2346 * On success, the number of characters written
2347 * On dst buffer overflow, -1
2348 */
2349static int utf7_mbstowcs(const char *src, int srclen, WCHAR *dst, int dstlen)
2350{
2351 static const signed char base64_decoding_table[] =
2352 {
2353 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
2354 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
2355 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20-0x2F */
2356 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
2357 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40-0x4F */
2358 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50-0x5F */
2359 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60-0x6F */
2360 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70-0x7F */
2361 };
2362
2363 const char *source_end = src + srclen;
2364 int dest_index = 0;
2365
2366 DWORD byte_pair = 0;
2367 short offset = 0;
2368
2369 while (src < source_end)
2370 {
2371 if (*src == '+')
2372 {
2373 src++;
2374 if (src >= source_end)
2375 break;
2376
2377 if (*src == '-')
2378 {
2379 /* just a plus sign escaped as +- */
2380 if (!utf7_write_w(dst, dstlen, &dest_index, '+'))
2381 return -1;
2382 src++;
2383 continue;
2384 }
2385
2386 do
2387 {
2388 signed char sextet = *src;
2389 if (sextet == '-')
2390 {
2391 /* skip over the dash and end base64 decoding
2392 * the current, unfinished byte pair is discarded */
2393 src++;
2394 offset = 0;
2395 break;
2396 }
2397 if (sextet < 0)
2398 {
2399 /* the next character of src is < 0 and therefore not part of a base64 sequence
2400 * the current, unfinished byte pair is NOT discarded in this case
2401 * this is probably a bug in Windows */
2402 break;
2403 }
2404
2405 sextet = base64_decoding_table[sextet];
2406 if (sextet == -1)
2407 {
2408 /* -1 means that the next character of src is not part of a base64 sequence
2409 * in other words, all sextets in this base64 sequence have been processed
2410 * the current, unfinished byte pair is discarded */
2411 offset = 0;
2412 break;
2413 }
2414
2415 byte_pair = (byte_pair << 6) | sextet;
2416 offset += 6;
2417
2418 if (offset >= 16)
2419 {
2420 /* this byte pair is done */
2421 if (!utf7_write_w(dst, dstlen, &dest_index, (byte_pair >> (offset - 16)) & 0xFFFF))
2422 return -1;
2423 offset -= 16;
2424 }
2425
2426 src++;
2427 }
2428 while (src < source_end);
2429 }
2430 else
2431 {
2432 /* we have to convert to unsigned char in case *src < 0 */
2433 if (!utf7_write_w(dst, dstlen, &dest_index, (unsigned char)*src))
2434 return -1;
2435 src++;
2436 }
2437 }
2438
2439 return dest_index;
2440}
2441
2442/***********************************************************************
2443 * MultiByteToWideChar (KERNEL32.@)
2444 *
2445 * Convert a multibyte character string into a Unicode string.
2446 *
2447 * PARAMS
2448 * page [I] Codepage character set to convert from
2449 * flags [I] Character mapping flags
2450 * src [I] Source string buffer
2451 * srclen [I] Length of src (in bytes), or -1 if src is NUL terminated
2452 * dst [O] Destination buffer
2453 * dstlen [I] Length of dst (in WCHARs), or 0 to compute the required length
2454 *
2455 * RETURNS
2456 * Success: If dstlen > 0, the number of characters written to dst.
2457 * If dstlen == 0, the number of characters needed to perform the
2458 * conversion. In both cases the count includes the terminating NUL.
2459 * Failure: 0. Use GetLastError() to determine the cause. Possible errors are
2460 * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst
2461 * and dstlen != 0; ERROR_INVALID_PARAMETER, if an invalid parameter
2462 * is passed, and ERROR_NO_UNICODE_TRANSLATION if no translation is
2463 * possible for src.
2464 */
2466 LPWSTR dst, INT dstlen )
2467{
2468 const union cptable *table;
2469 int ret;
2470
2471 if (!src || !srclen || (!dst && dstlen) || dstlen < 0)
2472 {
2474 return 0;
2475 }
2476
2477 if (srclen < 0) srclen = strlen(src) + 1;
2478
2479 switch(page)
2480 {
2481 case CP_SYMBOL:
2482 if (flags)
2483 {
2485 return 0;
2486 }
2488 break;
2489 case CP_UTF7:
2490 if (flags)
2491 {
2493 return 0;
2494 }
2496 break;
2497 case CP_UNIXCP:
2498 if (unix_cptable)
2499 {
2501 break;
2502 }
2503#ifdef __APPLE__
2504 flags |= MB_COMPOSITE; /* work around broken Mac OS X filesystem that enforces decomposed Unicode */
2505#endif
2506 /* fall through */
2507 case CP_UTF8:
2508 if (flags & ~MB_FLAGSMASK)
2509 {
2511 return 0;
2512 }
2514 break;
2515 default:
2516 if (!(table = get_codepage_table( page )))
2517 {
2519 return 0;
2520 }
2521 if (flags & ~MB_FLAGSMASK)
2522 {
2524 return 0;
2525 }
2527 break;
2528 }
2529
2530 if (ret < 0)
2531 {
2532 switch(ret)
2533 {
2534 case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break;
2535 case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break;
2536 }
2537 ret = 0;
2538 }
2539 TRACE("cp %d %s -> %s, ret = %d\n",
2541 return ret;
2542}
2543
2544
2545/***********************************************************************
2546 * utf7_can_directly_encode
2547 *
2548 * Helper for utf7_wcstombs
2549 */
2550static inline BOOL utf7_can_directly_encode(WCHAR codepoint)
2551{
2552 static const BOOL directly_encodable_table[] =
2553 {
2554 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0x00 - 0x0F */
2555 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1F */
2556 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 0x20 - 0x2F */
2557 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x30 - 0x3F */
2558 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4F */
2559 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50 - 0x5F */
2560 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6F */
2561 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* 0x70 - 0x7A */
2562 };
2563
2564 return codepoint <= 0x7A ? directly_encodable_table[codepoint] : FALSE;
2565}
2566
2567/***********************************************************************
2568 * utf7_write_c
2569 *
2570 * Helper for utf7_wcstombs
2571 *
2572 * RETURNS
2573 * TRUE on success, FALSE on error
2574 */
2575static inline BOOL utf7_write_c(char *dst, int dstlen, int *index, char character)
2576{
2577 if (dstlen > 0)
2578 {
2579 if (*index >= dstlen)
2580 return FALSE;
2581
2582 dst[*index] = character;
2583 }
2584
2585 (*index)++;
2586
2587 return TRUE;
2588}
2589
2590/***********************************************************************
2591 * utf7_wcstombs
2592 *
2593 * UTF-16 to UTF-7 string conversion, helper for WideCharToMultiByte
2594 *
2595 * RETURNS
2596 * On success, the number of characters written
2597 * On dst buffer overflow, -1
2598 */
2599static int utf7_wcstombs(const WCHAR *src, int srclen, char *dst, int dstlen)
2600{
2601 static const char base64_encoding_table[] =
2602 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2603
2604 const WCHAR *source_end = src + srclen;
2605 int dest_index = 0;
2606
2607 while (src < source_end)
2608 {
2609 if (*src == '+')
2610 {
2611 if (!utf7_write_c(dst, dstlen, &dest_index, '+'))
2612 return -1;
2613 if (!utf7_write_c(dst, dstlen, &dest_index, '-'))
2614 return -1;
2615 src++;
2616 }
2617 else if (utf7_can_directly_encode(*src))
2618 {
2619 if (!utf7_write_c(dst, dstlen, &dest_index, *src))
2620 return -1;
2621 src++;
2622 }
2623 else
2624 {
2625 unsigned int offset = 0;
2626 DWORD byte_pair = 0;
2627
2628 if (!utf7_write_c(dst, dstlen, &dest_index, '+'))
2629 return -1;
2630
2631 while (src < source_end && !utf7_can_directly_encode(*src))
2632 {
2633 byte_pair = (byte_pair << 16) | *src;
2634 offset += 16;
2635 while (offset >= 6)
2636 {
2637 if (!utf7_write_c(dst, dstlen, &dest_index, base64_encoding_table[(byte_pair >> (offset - 6)) & 0x3F]))
2638 return -1;
2639 offset -= 6;
2640 }
2641 src++;
2642 }
2643
2644 if (offset)
2645 {
2646 /* Windows won't create a padded base64 character if there's no room for the - sign
2647 * as well ; this is probably a bug in Windows */
2648 if (dstlen > 0 && dest_index + 1 >= dstlen)
2649 return -1;
2650
2651 byte_pair <<= (6 - offset);
2652 if (!utf7_write_c(dst, dstlen, &dest_index, base64_encoding_table[byte_pair & 0x3F]))
2653 return -1;
2654 }
2655
2656 /* Windows always explicitly terminates the base64 sequence
2657 even though RFC 2152 (page 3, rule 2) does not require this */
2658 if (!utf7_write_c(dst, dstlen, &dest_index, '-'))
2659 return -1;
2660 }
2661 }
2662
2663 return dest_index;
2664}
2665
2666/***********************************************************************
2667 * WideCharToMultiByte (KERNEL32.@)
2668 *
2669 * Convert a Unicode character string into a multibyte string.
2670 *
2671 * PARAMS
2672 * page [I] Code page character set to convert to
2673 * flags [I] Mapping Flags (MB_ constants from "winnls.h").
2674 * src [I] Source string buffer
2675 * srclen [I] Length of src (in WCHARs), or -1 if src is NUL terminated
2676 * dst [O] Destination buffer
2677 * dstlen [I] Length of dst (in bytes), or 0 to compute the required length
2678 * defchar [I] Default character to use for conversion if no exact
2679 * conversion can be made
2680 * used [O] Set if default character was used in the conversion
2681 *
2682 * RETURNS
2683 * Success: If dstlen > 0, the number of characters written to dst.
2684 * If dstlen == 0, number of characters needed to perform the
2685 * conversion. In both cases the count includes the terminating NUL.
2686 * Failure: 0. Use GetLastError() to determine the cause. Possible errors are
2687 * ERROR_INSUFFICIENT_BUFFER, if not enough space is available in dst
2688 * and dstlen != 0, and ERROR_INVALID_PARAMETER, if an invalid
2689 * parameter was given.
2690 */
2692 LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
2693{
2694 const union cptable *table;
2695 int ret, used_tmp;
2696
2697 if (!src || !srclen || (!dst && dstlen) || dstlen < 0)
2698 {
2700 return 0;
2701 }
2702
2703 if (srclen < 0) srclen = strlenW(src) + 1;
2704
2705 switch(page)
2706 {
2707 case CP_SYMBOL:
2708 /* when using CP_SYMBOL, ERROR_INVALID_FLAGS takes precedence */
2709 if (flags)
2710 {
2712 return 0;
2713 }
2714 if (defchar || used)
2715 {
2717 return 0;
2718 }
2720 break;
2721 case CP_UTF7:
2722 /* when using CP_UTF7, ERROR_INVALID_PARAMETER takes precedence */
2723 if (defchar || used)
2724 {
2726 return 0;
2727 }
2728 if (flags)
2729 {
2731 return 0;
2732 }
2734 break;
2735 case CP_UNIXCP:
2736 if (unix_cptable)
2737 {
2739 defchar, used ? &used_tmp : NULL );
2740 break;
2741 }
2742 /* fall through */
2743 case CP_UTF8:
2744 if (defchar || used)
2745 {
2747 return 0;
2748 }
2749 if (flags & ~WC_FLAGSMASK)
2750 {
2752 return 0;
2753 }
2755 break;
2756 default:
2757 if (!(table = get_codepage_table( page )))
2758 {
2760 return 0;
2761 }
2762 if (flags & ~WC_FLAGSMASK)
2763 {
2765 return 0;
2766 }
2768 defchar, used ? &used_tmp : NULL );
2769 if (used) *used = used_tmp;
2770 break;
2771 }
2772
2773 if (ret < 0)
2774 {
2775 switch(ret)
2776 {
2777 case -1: SetLastError( ERROR_INSUFFICIENT_BUFFER ); break;
2778 case -2: SetLastError( ERROR_NO_UNICODE_TRANSLATION ); break;
2779 }
2780 ret = 0;
2781 }
2782 TRACE("cp %d %s -> %s, ret = %d\n",
2784 return ret;
2785}
2786#endif // !__REACTOS__
2787
2788
2789/***********************************************************************
2790 * GetThreadLocale (KERNEL32.@)
2791 *
2792 * Get the current threads locale.
2793 *
2794 * PARAMS
2795 * None.
2796 *
2797 * RETURNS
2798 * The LCID currently associated with the calling thread.
2799 */
2801{
2802 LCID ret = NtCurrentTeb()->CurrentLocale;
2803 if (!ret) NtCurrentTeb()->CurrentLocale = ret = GetUserDefaultLCID();
2804 return ret;
2805}
2806
2807/**********************************************************************
2808 * SetThreadLocale (KERNEL32.@)
2809 *
2810 * Set the current threads locale.
2811 *
2812 * PARAMS
2813 * lcid [I] LCID of the locale to set
2814 *
2815 * RETURNS
2816 * Success: TRUE. The threads locale is set to lcid.
2817 * Failure: FALSE. Use GetLastError() to determine the cause.
2818 */
2820{
2821 TRACE("(0x%04X)\n", lcid);
2822
2823 lcid = ConvertDefaultLocale(lcid);
2824
2825 if (lcid != GetThreadLocale())
2826 {
2827 if (!IsValidLocale(lcid, LCID_SUPPORTED))
2828 {
2830 return FALSE;
2831 }
2832
2833 NtCurrentTeb()->CurrentLocale = lcid;
2834 }
2835 return TRUE;
2836}
2837
2838#ifndef __REACTOS__
2839/**********************************************************************
2840 * SetThreadUILanguage (KERNEL32.@)
2841 *
2842 * Set the current threads UI language.
2843 *
2844 * PARAMS
2845 * langid [I] LANGID of the language to set, or 0 to use
2846 * the available language which is best supported
2847 * for console applications
2848 *
2849 * RETURNS
2850 * Success: The return value is the same as the input value.
2851 * Failure: The return value differs from the input value.
2852 * Use GetLastError() to determine the cause.
2853 */
2855{
2856 TRACE("(0x%04x) stub - returning success\n", langid);
2857 return langid;
2858}
2859#endif // !__REACTOS__
2860
2861/******************************************************************************
2862 * ConvertDefaultLocale (KERNEL32.@)
2863 *
2864 * Convert a default locale identifier into a real identifier.
2865 *
2866 * PARAMS
2867 * lcid [I] LCID identifier of the locale to convert
2868 *
2869 * RETURNS
2870 * lcid unchanged, if not a default locale or its sublanguage is
2871 * not SUBLANG_NEUTRAL.
2872 * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT.
2873 * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL.
2874 * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT.
2875 */
2877{
2878 LANGID langid;
2879
2880 switch (lcid)
2881 {
2882 case LOCALE_INVARIANT:
2883 /* keep as-is */
2884 break;
2886 lcid = GetSystemDefaultLCID();
2887 break;
2889 case LOCALE_NEUTRAL:
2890 lcid = GetUserDefaultLCID();
2891 break;
2892 default:
2893 /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
2894 langid = LANGIDFROMLCID(lcid);
2896 {
2898 lcid = MAKELCID(langid, SORTIDFROMLCID(lcid));
2899 }
2900 }
2901 return lcid;
2902}
2903
2904
2905/******************************************************************************
2906 * IsValidLocale (KERNEL32.@)
2907 *
2908 * Determine if a locale is valid.
2909 *
2910 * PARAMS
2911 * lcid [I] LCID of the locale to check
2912 * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system
2913 *
2914 * RETURNS
2915 * TRUE, if lcid is valid,
2916 * FALSE, otherwise.
2917 *
2918 * NOTES
2919 * Wine does not currently make the distinction between supported and installed. All
2920 * languages supported are installed by default.
2921 */
2923{
2924 /* check if language is registered in the kernel32 resources */
2927}
2928
2929#ifndef __REACTOS__
2930/******************************************************************************
2931 * IsValidLocaleName (KERNEL32.@)
2932 */
2934{
2935 struct locale_name locale_name;
2936
2937 if (!locale)
2938 return FALSE;
2939
2940 /* string parsing */
2941 parse_locale_name( locale, &locale_name );
2942
2943 TRACE( "found lcid %x for %s, matches %d\n",
2945
2946 return locale_name.matches > 0;
2947}
2948#endif // !__REACTOS__
2949
2952{
2953 LOCALE_ENUMPROCA lpfnLocaleEnum = (LOCALE_ENUMPROCA)lParam;
2954 char buf[20];
2955
2956 sprintf(buf, "%08x", (UINT)LangID);
2957 return lpfnLocaleEnum( buf );
2958}
2959
2962{
2963 static const WCHAR formatW[] = {'%','0','8','x',0};
2964 LOCALE_ENUMPROCW lpfnLocaleEnum = (LOCALE_ENUMPROCW)lParam;
2965 WCHAR buf[20];
2966 sprintfW( buf, formatW, (UINT)LangID );
2967 return lpfnLocaleEnum( buf );
2968}
2969
2970/******************************************************************************
2971 * EnumSystemLocalesA (KERNEL32.@)
2972 *
2973 * Call a users function for each locale available on the system.
2974 *
2975 * PARAMS
2976 * lpfnLocaleEnum [I] Callback function to call for each locale
2977 * dwFlags [I] LOCALE_SUPPORTED=All supported, LOCALE_INSTALLED=Installed only
2978 *
2979 * RETURNS
2980 * Success: TRUE.
2981 * Failure: FALSE. Use GetLastError() to determine the cause.
2982 */
2984{
2985 TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags);
2988 (LONG_PTR)lpfnLocaleEnum);
2989 return TRUE;
2990}
2991
2992
2993/******************************************************************************
2994 * EnumSystemLocalesW (KERNEL32.@)
2995 *
2996 * See EnumSystemLocalesA.
2997 */
2999{
3000 TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags);
3003 (LONG_PTR)lpfnLocaleEnum);
3004 return TRUE;
3005}
3006
3007
3009{
3013};
3014
3017{
3019 WCHAR buffer[256];
3020 DWORD neutral;
3021 unsigned int flags;
3022
3024 buffer, sizeof(buffer) / sizeof(WCHAR) );
3026 LOCALE_INEUTRAL | LOCALE_NOUSEROVERRIDE | LOCALE_RETURN_NUMBER,
3027 (LPWSTR)&neutral, sizeof(neutral) / sizeof(WCHAR) ))
3028 neutral = 0;
3031 if (data->flags && !(data->flags & flags)) return TRUE;
3032 return data->proc( buffer, flags, data->lparam );
3033}
3034
3035/******************************************************************************
3036 * EnumSystemLocalesEx (KERNEL32.@)
3037 */
3039{
3041
3042 if (reserved)
3043 {
3045 return FALSE;
3046 }
3047 data.proc = proc;
3048 data.flags = flags;
3049 data.lparam = lparam;
3053 return TRUE;
3054}
3055
3056
3057/***********************************************************************
3058 * VerLanguageNameA (KERNEL32.@)
3059 *
3060 * Get the name of a language.
3061 *
3062 * PARAMS
3063 * wLang [I] LANGID of the language
3064 * szLang [O] Destination for the language name
3065 *
3066 * RETURNS
3067 * Success: The size of the language name. If szLang is non-NULL, it is filled
3068 * with the name.
3069 * Failure: 0. Use GetLastError() to determine the cause.
3070 *
3071 */
3073{
3074 return GetLocaleInfoA( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
3075}
3076
3077
3078/***********************************************************************
3079 * VerLanguageNameW (KERNEL32.@)
3080 *
3081 * See VerLanguageNameA.
3082 */
3084{
3085 return GetLocaleInfoW( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize );
3086}
3087
3088
3089/******************************************************************************
3090 * GetStringTypeW (KERNEL32.@)
3091 *
3092 * See GetStringTypeA.
3093 */
3095{
3096 static const unsigned char type2_map[16] =
3097 {
3098 C2_NOTAPPLICABLE, /* unassigned */
3099 C2_LEFTTORIGHT, /* L */
3100 C2_RIGHTTOLEFT, /* R */
3101 C2_EUROPENUMBER, /* EN */
3102 C2_EUROPESEPARATOR, /* ES */
3103 C2_EUROPETERMINATOR, /* ET */
3104 C2_ARABICNUMBER, /* AN */
3105 C2_COMMONSEPARATOR, /* CS */
3106 C2_BLOCKSEPARATOR, /* B */
3107 C2_SEGMENTSEPARATOR, /* S */
3108 C2_WHITESPACE, /* WS */
3109 C2_OTHERNEUTRAL, /* ON */
3110 C2_RIGHTTOLEFT, /* AL */
3111 C2_NOTAPPLICABLE, /* NSM */
3112 C2_NOTAPPLICABLE, /* BN */
3113 C2_OTHERNEUTRAL /* LRE, LRO, RLE, RLO, PDF */
3114 };
3115
3116 if (!src)
3117 {
3119 return FALSE;
3120 }
3121
3122 if (count == -1) count = strlenW(src) + 1;
3123 switch(type)
3124 {
3125 case CT_CTYPE1:
3126 while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff;
3127 break;
3128 case CT_CTYPE2:
3129 while (count--) *chartype++ = type2_map[get_char_typeW( *src++ ) >> 12];
3130 break;
3131 case CT_CTYPE3:
3132 {
3133 WARN("CT_CTYPE3: semi-stub.\n");
3134 while (count--)
3135 {
3136 int c = *src;
3137 WORD type1, type3 = 0; /* C3_NOTAPPLICABLE */
3138
3139 type1 = get_char_typeW( *src++ ) & 0xfff;
3140 /* try to construct type3 from type1 */
3141 if(type1 & C1_SPACE) type3 |= C3_SYMBOL;
3142 if(type1 & C1_ALPHA) type3 |= C3_ALPHA;
3143 if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA;
3144 if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA;
3145 if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH;
3146 if (c == 0x0640) type3 |= C3_KASHIDA;
3147 if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL;
3148
3149 if ((c>=0xD800)&&(c<=0xDBFF)) type3 |= C3_HIGHSURROGATE;
3150 if ((c>=0xDC00)&&(c<=0xDFFF)) type3 |= C3_LOWSURROGATE;
3151
3152 if ((c>=0xFF00)&&(c<=0xFF60)) type3 |= C3_FULLWIDTH;
3153 if ((c>=0xFF00)&&(c<=0xFF20)) type3 |= C3_SYMBOL;
3154 if ((c>=0xFF3B)&&(c<=0xFF40)) type3 |= C3_SYMBOL;
3155 if ((c>=0xFF5B)&&(c<=0xFF60)) type3 |= C3_SYMBOL;
3156 if ((c>=0xFF21)&&(c<=0xFF3A)) type3 |= C3_ALPHA;
3157 if ((c>=0xFF41)&&(c<=0xFF5A)) type3 |= C3_ALPHA;
3158 if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_FULLWIDTH;
3159 if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_SYMBOL;
3160
3161 if ((c>=0xFF61)&&(c<=0xFFDC)) type3 |= C3_HALFWIDTH;
3162 if ((c>=0xFF61)&&(c<=0xFF64)) type3 |= C3_SYMBOL;
3163 if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_KATAKANA;
3164 if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_ALPHA;
3165 if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_HALFWIDTH;
3166 if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_SYMBOL;
3167 *chartype++ = type3;
3168 }
3169 break;
3170 }
3171 default:
3173 return FALSE;
3174 }
3175 return TRUE;
3176}
3177
3178
3179/******************************************************************************
3180 * GetStringTypeExW (KERNEL32.@)
3181 *
3182 * See GetStringTypeExA.
3183 */
3185{
3186 /* locale is ignored for Unicode */
3187 return GetStringTypeW( type, src, count, chartype );
3188}
3189
3190
3191/******************************************************************************
3192 * GetStringTypeA (KERNEL32.@)
3193 *
3194 * Get characteristics of the characters making up a string.
3195 *
3196 * PARAMS
3197 * locale [I] Locale Id for the string
3198 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
3199 * src [I] String to analyse
3200 * count [I] Length of src in chars, or -1 if src is NUL terminated
3201 * chartype [O] Destination for the calculated characteristics
3202 *
3203 * RETURNS
3204 * Success: TRUE. chartype is filled with the requested characteristics of each char
3205 * in src.
3206 * Failure: FALSE. Use GetLastError() to determine the cause.
3207 */
3209{
3210 UINT cp;
3211 INT countW;
3212 LPWSTR srcW;
3213 BOOL ret = FALSE;
3214
3215 if(count == -1) count = strlen(src) + 1;
3216
3217 if (!(cp = get_lcid_codepage( locale )))
3218 {
3219 FIXME("For locale %04x using current ANSI code page\n", locale);
3220 cp = GetACP();
3221 }
3222
3223 countW = MultiByteToWideChar(cp, 0, src, count, NULL, 0);
3224 if((srcW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
3225 {
3226 MultiByteToWideChar(cp, 0, src, count, srcW, countW);
3227 /*
3228 * NOTE: the target buffer has 1 word for each CHARACTER in the source
3229 * string, with multibyte characters there maybe be more bytes in count
3230 * than character space in the buffer!
3231 */
3232 ret = GetStringTypeW(type, srcW, countW, chartype);
3233 HeapFree(GetProcessHeap(), 0, srcW);
3234 }
3235 return ret;
3236}
3237
3238/******************************************************************************
3239 * GetStringTypeExA (KERNEL32.@)
3240 *
3241 * Get characteristics of the characters making up a string.
3242 *
3243 * PARAMS
3244 * locale [I] Locale Id for the string
3245 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
3246 * src [I] String to analyse
3247 * count [I] Length of src in chars, or -1 if src is NUL terminated
3248 * chartype [O] Destination for the calculated characteristics
3249 *
3250 * RETURNS
3251 * Success: TRUE. chartype is filled with the requested characteristics of each char
3252 * in src.
3253 * Failure: FALSE. Use GetLastError() to determine the cause.
3254 */
3256{
3257 return GetStringTypeA(locale, type, src, count, chartype);
3258}
3259
3260#ifdef __REACTOS__
3261static inline void map_byterev(const WCHAR *src, int len, WCHAR *dst)
3262{
3263 while (len--)
3264 *dst++ = RtlUshortByteSwap(*src++);
3265}
3266
3267static int map_to_hiragana(const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3268{
3269 int pos;
3270 for (pos = 0; srclen; src++, srclen--, pos++)
3271 {
3272 /*
3273 * U+30A1 ... U+30F3: Katakana
3274 * U+30F4: Katakana Letter VU
3275 * U+30F5: Katakana Letter Small KA
3276 * U+30FD: Katakana Iteration Mark
3277 * U+30FE: Katakana Voiced Iteration Mark
3278 */
3279 WCHAR wch = *src;
3280 if ((0x30A1 <= wch && wch <= 0x30F3) ||
3281 wch == 0x30F4 || wch == 0x30F5 || wch == 0x30FD || wch == 0x30FE)
3282 {
3283 wch -= 0x60; /* Katakana to Hiragana */
3284 }
3285 if (pos < dstlen)
3286 dst[pos] = wch;
3287 }
3288 return pos;
3289}
3290
3291static int map_to_katakana(const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3292{
3293 int pos;
3294 for (pos = 0; srclen; src++, srclen--, pos++)
3295 {
3296 /*
3297 * U+3041 ... U+3093: Hiragana
3298 * U+3094: Hiragana Letter VU
3299 * U+3095: Hiragana Letter Small KA
3300 * U+309D: Hiragana Iteration Mark
3301 * U+309E: Hiragana Voiced Iteration Mark
3302 */
3303 WCHAR wch = *src;
3304 if ((0x3041 <= wch && wch <= 0x3093) ||
3305 wch == 3094 || wch == 0x3095 || wch == 0x309D || wch == 0x309E)
3306 {
3307 wch += 0x60; /* Hiragana to Katakana */
3308 }
3309 if (pos < dstlen)
3310 dst[pos] = wch;
3311 }
3312 return pos;
3313}
3314
3315/* The table that contains fullwidth characters and halfwidth characters */
3316typedef WCHAR FULL2HALF_ENTRY[3];
3317static const FULL2HALF_ENTRY full2half_table[] =
3318{
3319#define DEFINE_FULL2HALF(full, half1, half2) { full, half1, half2 },
3320#include "full2half.h"
3321#undef DEFINE_FULL2HALF
3322};
3323#define GET_FULL(table, index) ((table)[index][0])
3324#define GET_HALF1(table, index) ((table)[index][1])
3325#define GET_HALF2(table, index) ((table)[index][2])
3326
3327/* The table that contains dakuten entries */
3328typedef WCHAR DAKUTEN_ENTRY[3];
3329static const DAKUTEN_ENTRY dakuten_table[] =
3330{
3331#define DEFINE_DAKUTEN(voiced, single1, single2, half1, half2) { voiced, single1, single2 },
3332#include "dakuten.h"
3333#undef DEFINE_DAKUTEN
3334};
3335#define GET_VOICED(table, index) ((table)[index][0])
3336#define GET_SINGLE1(table, index) ((table)[index][1])
3337#define GET_SINGLE2(table, index) ((table)[index][2])
3338
3339static int map_to_halfwidth(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3340{
3341 int pos, i;
3342 const int count1 = (int)ARRAY_SIZE(full2half_table);
3343 const FULL2HALF_ENTRY *table1 = full2half_table;
3344
3345 for (pos = 0; srclen; src++, srclen--, pos++)
3346 {
3347 WCHAR ch = *src;
3348
3349 if (flags & LCMAP_KATAKANA)
3350 map_to_katakana(&ch, 1, &ch, 1);
3351 else if (flags & LCMAP_HIRAGANA)
3352 map_to_hiragana(&ch, 1, &ch, 1);
3353
3354 if (ch < 0x3000) /* Quick judgment */
3355 {
3356 if (pos < dstlen)
3357 dst[pos] = ch;
3358 continue;
3359 }
3360
3361 if (0xFF01 <= ch && ch <= 0xFF5E) /* U+FF01 ... U+FF5E */
3362 {
3363 if (pos < dstlen)
3364 dst[pos] = ch - 0xFEE0; /* Fullwidth ASCII to halfwidth ASCII */
3365 continue;
3366 }
3367
3368 /* Search in table1 (full/half) */
3369 for (i = count1 - 1; i >= 0; --i) /* In reverse order */
3370 {
3371 if (GET_FULL(table1, i) != ch)
3372 continue;
3373
3374 if (GET_HALF2(table1, i) == 0)
3375 {
3376 if (pos < dstlen)
3377 dst[pos] = GET_HALF1(table1, i);
3378 }
3379 else if (!dstlen)
3380 {
3381 pos++;
3382 }
3383 else if (pos + 1 < dstlen)
3384 {
3385 dst[pos++] = GET_HALF1(table1, i);
3386 dst[pos ] = GET_HALF2(table1, i);
3387 }
3388 else
3389 {
3390 dst[pos] = ch;
3391 }
3392 break;
3393 }
3394
3395 if (i >= 0)
3396 continue;
3397
3398 if (pos < dstlen)
3399 dst[pos] = ch;
3400 }
3401
3402 return pos;
3403}
3404
3405static int map_to_fullwidth(const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3406{
3407 int pos, i;
3408 const FULL2HALF_ENTRY *table1 = full2half_table;
3409 const DAKUTEN_ENTRY *table2 = dakuten_table;
3410 const int count1 = (int)ARRAY_SIZE(full2half_table);
3411 const int count2 = (int)ARRAY_SIZE(dakuten_table);
3412
3413 for (pos = 0; srclen; src++, srclen--, pos++)
3414 {
3415 WCHAR ch = *src;
3416
3417 if (ch == 0x20) /* U+0020: Space */
3418 {
3419 if (pos < dstlen)
3420 dst[pos] = 0x3000; /* U+3000: Ideographic Space */
3421 continue;
3422 }
3423
3424 if (0x21 <= ch && ch <= 0x7E) /* Mappable halfwidth ASCII */
3425 {
3426 if (pos < dstlen)
3427 dst[pos] = ch + 0xFEE0; /* U+FF01 ... U+FF5E */
3428 continue;
3429 }
3430
3431 if (ch < 0xFF00) /* Quick judgment */
3432 {
3433 if (pos < dstlen)
3434 dst[pos] = ch;
3435 continue;
3436 }
3437
3438 /* Search in table1 (full/half) */
3439 for (i = count1 - 1; i >= 0; --i) /* In reverse order */
3440 {
3441 if (GET_HALF1(table1, i) != ch)
3442 continue; /* Mismatched */
3443
3444 if (GET_HALF2(table1, i) == 0)
3445 {
3446 if (pos < dstlen)
3447 dst[pos] = GET_FULL(table1, i);
3448 break;
3449 }
3450
3451 if (srclen <= 1 || GET_HALF2(table1, i) != src[1])
3452 continue; /* Mismatched */
3453
3454 --srclen;
3455 ++src;
3456
3457 if (pos < dstlen)
3458 dst[pos] = GET_FULL(table1, i);
3459 break;
3460 }
3461
3462 if (i >= 0)
3463 continue;
3464
3465 /* Search in table2 (dakuten) */
3466 for (i = count2 - 1; i >= 0; --i) /* In reverse order */
3467 {
3468 if (GET_SINGLE1(table2, i) != ch)
3469 continue; /* Mismatched */
3470
3471 if (srclen <= 1 || GET_SINGLE2(table2, i) != src[1])
3472 continue; /* Mismatched */
3473
3474 --srclen;
3475 ++src;
3476
3477 if (pos < dstlen)
3478 dst[pos] = GET_VOICED(table2, i);
3479 break;
3480 }
3481
3482 if (i >= 0)
3483 continue;
3484
3485 if (pos < dstlen)
3486 dst[pos] = ch;
3487 }
3488
3489 return pos;
3490}
3491
3492static int map_to_lowercase(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3493{
3494 int pos;
3495 for (pos = 0; srclen; src++, srclen--)
3496 {
3497 WCHAR wch = *src;
3499 continue;
3500 if (pos < dstlen)
3501 dst[pos] = tolowerW(wch);
3502 pos++;
3503 }
3504 return pos;
3505}
3506
3507static int map_to_uppercase(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3508{
3509 int pos;
3510 for (pos = 0; srclen; src++, srclen--)
3511 {
3512 WCHAR wch = *src;
3514 continue;
3515 if (pos < dstlen)
3516 dst[pos] = toupperW(wch);
3517 pos++;
3518 }
3519 return pos;
3520}
3521
3522typedef struct tagWCHAR_PAIR
3523{
3524 WCHAR from, to;
3525} WCHAR_PAIR, *PWCHAR_PAIR;
3526
3527/* The table to convert Simplified Chinese to Traditional Chinese */
3528static const WCHAR_PAIR s_sim2tra[] =
3529{
3530#define DEFINE_SIM2TRA(from, to) { from, to },
3531#include "sim2tra.h"
3532#undef DEFINE_SIM2TRA
3533};
3534
3535/* The table to convert Traditional Chinese to Simplified Chinese */
3536static const WCHAR_PAIR s_tra2sim[] =
3537{
3538#define DEFINE_TRA2SIM(from, to) { from, to },
3539#include "tra2sim.h"
3540#undef DEFINE_TRA2SIM
3541};
3542
3543/* The comparison function to do bsearch */
3544static int compare_wchar_pair(const void *x, const void *y)
3545{
3546 const WCHAR_PAIR *a = x;
3547 const WCHAR_PAIR *b = y;
3548 if (a->from < b->from)
3549 return -1;
3550 if (a->from > b->from)
3551 return +1;
3552 return 0;
3553}
3554
3555static WCHAR find_wchar_pair(const WCHAR_PAIR *pairs, size_t count, WCHAR ch)
3556{
3557 PWCHAR_PAIR found = bsearch(&ch, pairs, count, sizeof(WCHAR_PAIR), compare_wchar_pair);
3558 if (found)
3559 return found->to;
3560 return ch;
3561}
3562
3563static int map_to_simplified_chinese(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3564{
3565 int pos;
3566 for (pos = 0; srclen; src++, srclen--)
3567 {
3568 WCHAR wch = *src;
3569 if (pos < dstlen)
3570 dst[pos] = find_wchar_pair(s_tra2sim, ARRAY_SIZE(s_tra2sim), wch);
3571 pos++;
3572 }
3573 return pos;
3574}
3575
3576static int map_to_traditional_chinese(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3577{
3578 int pos;
3579 for (pos = 0; srclen; src++, srclen--)
3580 {
3581 WCHAR wch = *src;
3582 if (pos < dstlen)
3583 dst[pos] = find_wchar_pair(s_sim2tra, ARRAY_SIZE(s_sim2tra), wch);
3584 pos++;
3585 }
3586 return pos;
3587}
3588
3589static int map_remove_ignored(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3590{
3591 int pos;
3592 WORD wC1, wC2, wC3;
3593 for (pos = 0; srclen; src++, srclen--)
3594 {
3595 WCHAR wch = *src;
3596 GetStringTypeW(CT_CTYPE1, &wch, 1, &wC1);
3597 GetStringTypeW(CT_CTYPE2, &wch, 1, &wC2);
3598 GetStringTypeW(CT_CTYPE3, &wch, 1, &wC3);
3600 {
3601 if ((wC1 & C1_PUNCT) || (wC3 & C3_SYMBOL))
3602 continue;
3603 }
3605 {
3606 if ((wC2 & C2_OTHERNEUTRAL) && (wC3 & (C3_NONSPACING | C3_DIACRITIC)))
3607 continue;
3608 }
3609 if (pos < dstlen)
3610 dst[pos] = wch;
3611 pos++;
3612 }
3613 return pos;
3614}
3615
3616static int lcmap_string(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
3617{
3618 int ret = 0;
3619
3621 {
3623 return 0;
3624 }
3625
3627 {
3628 case LCMAP_HIRAGANA:
3629 ret = map_to_hiragana(src, srclen, dst, dstlen);
3630 break;
3631 case LCMAP_KATAKANA:
3632 ret = map_to_katakana(src, srclen, dst, dstlen);
3633 break;
3634 case LCMAP_HALFWIDTH:
3635 ret = map_to_halfwidth(flags, src, srclen, dst, dstlen);
3636 break;
3638 ret = map_to_halfwidth(flags, src, srclen, dst, dstlen);
3639 break;
3641 ret = map_to_halfwidth(flags, src, srclen, dst, dstlen);
3642 break;
3643 case LCMAP_FULLWIDTH:
3644 ret = map_to_fullwidth(src, srclen, dst, dstlen);
3645 break;
3647 ret = map_to_fullwidth(src, srclen, dst, dstlen);
3648 if (dstlen && ret)
3649 map_to_hiragana(dst, ret, dst, dstlen);
3650 break;
3652 ret = map_to_fullwidth(src, srclen, dst, dstlen);
3653 if (dstlen && ret)
3654 map_to_katakana(dst, ret, dst, dstlen);
3655 break;
3657 ret = map_to_simplified_chinese(flags, src, srclen, dst, dstlen);
3658 break;
3660 ret = map_to_traditional_chinese(flags, src, srclen, dst, dstlen);
3661 break;
3663 case NORM_IGNORESYMBOLS:
3666 {
3668 return 0;
3669 }
3670 ret = map_remove_ignored(flags, src, srclen, dst, dstlen);
3671 break;
3672 case 0:
3673 if (flags & LCMAP_LOWERCASE)
3674 {
3675 ret = map_to_lowercase(flags, src, srclen, dst, dstlen);
3676 flags &= ~LCMAP_LOWERCASE;
3677 break;
3678 }
3679 if (flags & LCMAP_UPPERCASE)
3680 {
3681 ret = map_to_uppercase(flags, src, srclen, dst, dstlen);
3682 flags &= ~LCMAP_UPPERCASE;
3683 break;
3684 }
3685 if (flags & LCMAP_BYTEREV)
3686 {
3687 if (dstlen == 0)
3688 {
3689 ret = srclen;
3690 break;
3691 }
3692 ret = min(srclen, dstlen);
3693 RtlCopyMemory(dst, src, ret * sizeof(WCHAR));
3694 break;
3695 }
3696 /* fall through */
3697 default:
3699 return 0;
3700 }
3701
3702 if (dstlen)
3703 {
3704 if (flags & LCMAP_LOWERCASE)
3705 map_to_lowercase(flags, dst, ret, dst, dstlen);
3706 if (flags & LCMAP_UPPERCASE)
3707 map_to_uppercase(flags, dst, ret, dst, dstlen);
3708 if (flags & LCMAP_BYTEREV)
3709 map_byterev(dst, min(ret, dstlen), dst);
3710
3711 if (dstlen < ret)
3712 {
3714 return 0;
3715 }
3716 }
3717
3718 return ret;
3719}
3720#endif // __REACTOS__
3721
3722/*************************************************************************
3723 * LCMapStringEx (KERNEL32.@)
3724 *
3725 * Map characters in a locale sensitive string.
3726 *
3727 * PARAMS
3728 * locale [I] Locale name for the conversion.
3729 * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h")
3730 * src [I] String to map
3731 * srclen [I] Length of src in chars, or -1 if src is NUL terminated
3732 * dst [O] Destination for mapped string
3733 * dstlen [I] Length of dst in characters
3734 * version [I] reserved, must be NULL
3735 * reserved [I] reserved, must be NULL
3736 * lparam [I] reserved, must be 0
3737 *
3738 * RETURNS
3739 * Success: The length of the mapped string in dst, including the NUL terminator.
3740 * Failure: 0. Use GetLastError() to determine the cause.
3741 */
3744{
3745 if (version) FIXME("unsupported version structure %p\n", version);
3746 if (reserved) FIXME("unsupported reserved pointer %p\n", reserved);
3747 if (handle)
3748 {
3749 static int once;
3750 if (!once++) FIXME("unsupported lparam %Ix\n", handle);
3751 }
3752
3753 if (!src || !srclen || dstlen < 0)
3754 {
3756 return 0;
3757 }
3758
3759 if (srclen < 0) srclen = lstrlenW(src) + 1;
3760
3761 TRACE( "(%s,0x%08lx,%s,%d,%p,%d)\n",
3763
3764 flags &= ~LOCALE_USE_CP_ACP;
3765
3766 if (src == dst && (flags & ~(LCMAP_LOWERCASE | LCMAP_UPPERCASE)))
3767 {
3769 return 0;
3770 }
3771
3772 if (!dstlen) dst = NULL;
3773
3774 if (flags & LCMAP_SORTKEY)
3775 {
3776 INT ret;
3777
3778 if (srclen < 0)
3779 srclen = strlenW(src);
3780
3781 ret = wine_get_sortkey(flags, src, srclen, (char *)dst, dstlen);
3782 if (ret == 0)
3784 else
3785 ret++;
3786 return ret;
3787 }
3788
3789 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
3790 if (flags & SORT_STRINGSORT)
3791 {
3793 return 0;
3794 }
3795
3796 return lcmap_string(flags, src, srclen, dst, dstlen);
3797}
3798
3799/*************************************************************************
3800 * LCMapStringW (KERNEL32.@)
3801 *
3802 * See LCMapStringA.
3803 */
3806{
3807 TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n",
3809
3810 return LCMapStringEx(NULL, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
3811}
3812
3813/*************************************************************************
3814 * LCMapStringA (KERNEL32.@)
3815 *
3816 * Map characters in a locale sensitive string.
3817 *
3818 * PARAMS
3819 * lcid [I] LCID for the conversion.
3820 * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h").
3821 * src [I] String to map
3822 * srclen [I] Length of src in chars, or -1 if src is NUL terminated
3823 * dst [O] Destination for mapped string
3824 * dstlen [I] Length of dst in characters
3825 *
3826 * RETURNS
3827 * Success: The length of the mapped string in dst, including the NUL terminator.
3828 * Failure: 0. Use GetLastError() to determine the cause.
3829 */
3832{
3833 WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
3834 LPWSTR srcW, dstW;
3835 INT ret = 0, srclenW, dstlenW;
3836 UINT locale_cp = CP_ACP;
3837
3838 if (!src || !srclen || dstlen < 0)
3839 {
3841 return 0;
3842 }
3843
3844 if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
3845
3846 srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
3847 if (srclenW)
3848 srcW = bufW;
3849 else
3850 {
3851 srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, NULL, 0);
3852 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
3853 if (!srcW)
3854 {
3856 return 0;
3857 }
3858 MultiByteToWideChar(locale_cp, 0, src, srclen, srcW, srclenW);
3859 }
3860
3861 if (flags & LCMAP_SORTKEY)
3862 {
3863 if (src == dst)
3864 {
3866 goto map_string_exit;
3867 }
3868 ret = wine_get_sortkey(flags, srcW, srclenW, dst, dstlen);
3869 if (ret == 0)
3871 else
3872 ret++;
3873 goto map_string_exit;
3874 }
3875
3876 if (flags & SORT_STRINGSORT)
3877 {
3879 goto map_string_exit;
3880 }
3881
3882 dstlenW = LCMapStringEx(NULL, flags, srcW, srclenW, NULL, 0, NULL, NULL, 0);
3883 if (!dstlenW)
3884 goto map_string_exit;
3885
3886 dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
3887 if (!dstW)
3888 {
3890 goto map_string_exit;
3891 }
3892
3893 LCMapStringEx(NULL, flags, srcW, srclenW, dstW, dstlenW, NULL, NULL, 0);
3894 ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL);
3895 HeapFree(GetProcessHeap(), 0, dstW);
3896
3897map_string_exit:
3898 if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW);
3899 return ret;
3900}
3901
3902/*************************************************************************
3903 * FoldStringA (KERNEL32.@)
3904 *
3905 * Map characters in a string.
3906 *
3907 * PARAMS
3908 * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
3909 * src [I] String to map
3910 * srclen [I] Length of src, or -1 if src is NUL terminated
3911 * dst [O] Destination for mapped string
3912 * dstlen [I] Length of dst, or 0 to find the required length for the mapped string
3913 *
3914 * RETURNS
3915 * Success: The length of the string written to dst, including the terminating NUL. If
3916 * dstlen is 0, the value returned is the same, but nothing is written to dst,
3917 * and dst may be NULL.
3918 * Failure: 0. Use GetLastError() to determine the cause.
3919 */
3922{
3923 INT ret = 0, srclenW = 0;
3924 WCHAR *srcW = NULL, *dstW = NULL;
3925
3926 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
3927 {
3929 return 0;
3930 }
3931
3933 src, srclen, NULL, 0);
3934 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
3935
3936 if (!srcW)
3937 {
3939 goto FoldStringA_exit;
3940 }
3941
3943 src, srclen, srcW, srclenW);
3944
3945 dwFlags = (dwFlags & ~MAP_PRECOMPOSED) | MAP_FOLDCZONE;
3946
3947 ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0);
3948 if (ret && dstlen)
3949 {
3950 dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
3951
3952 if (!dstW)
3953 {
3955 goto FoldStringA_exit;
3956 }
3957
3958 ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret);
3959 if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
3960 {
3961 ret = 0;
3963 }
3964 }
3965
3966 HeapFree(GetProcessHeap(), 0, dstW);
3967
3968FoldStringA_exit:
3969 HeapFree(GetProcessHeap(), 0, srcW);
3970 return ret;
3971}
3972
3973/*************************************************************************
3974 * FoldStringW (KERNEL32.@)
3975 *
3976 * See FoldStringA.
3977 */
3980{
3981 int ret;
3982
3983 switch (dwFlags & (MAP_COMPOSITE|MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES))
3984 {
3985 case 0:
3986 if (dwFlags)
3987 break;
3988 /* Fall through for dwFlags == 0 */
3990 case MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES:
3991 case MAP_COMPOSITE|MAP_EXPAND_LIGATURES:
3993 return 0;
3994 }
3995
3996 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
3997 {
3999 return 0;
4000 }
4001
4003 if (!ret)
4005 return ret;
4006}
4007
4008/******************************************************************************
4009 * CompareStringW (KERNEL32.@)
4010 *
4011 * See CompareStringA.
4012 */
4014 LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
4015{
4016 return CompareStringEx(NULL, flags, str1, len1, str2, len2, NULL, NULL, 0);
4017}
4018
4019/******************************************************************************
4020 * CompareStringEx (KERNEL32.@)
4021 */
4024{
4027 DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
4028 /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
4029 INT ret;
4030 static int once;
4031
4032 if (version) FIXME("unexpected version parameter\n");
4033 if (reserved) FIXME("unexpected reserved value\n");
4034 if (lParam) FIXME("unexpected lParam\n");
4035
4036 if (!str1 || !str2)
4037 {
4039 return 0;
4040 }
4041
4042 if (flags & ~(supported_flags|semistub_flags))
4043 {
4045 return 0;
4046 }
4047
4048 if (flags & semistub_flags)
4049 {
4050 if (!once++)
4051 FIXME("semi-stub behavior for flag(s) 0x%x\n", flags & semistub_flags);
4052 }
4053
4054 if (len1 < 0) len1 = strlenW(str1);
4055 if (len2 < 0) len2 = strlenW(str2);
4056
4057 ret = wine_compare_string(flags, str1, len1, str2, len2);
4058
4059 if (ret) /* need to translate result */
4060 return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
4061 return CSTR_EQUAL;
4062}
4063
4064/******************************************************************************
4065 * CompareStringA (KERNEL32.@)
4066 *
4067 * Compare two locale sensitive strings.
4068 *
4069 * PARAMS
4070 * lcid [I] LCID for the comparison
4071 * flags [I] Flags for the comparison (NORM_ constants from "winnls.h").
4072 * str1 [I] First string to compare
4073 * len1 [I] Length of str1, or -1 if str1 is NUL terminated
4074 * str2 [I] Second string to compare
4075 * len2 [I] Length of str2, or -1 if str2 is NUL terminated
4076 *
4077 * RETURNS
4078 * Success: CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN depending on whether
4079 * str1 is less than, equal to or greater than str2 respectively.
4080 * Failure: FALSE. Use GetLastError() to determine the cause.
4081 */
4083 LPCSTR str1, INT len1, LPCSTR str2, INT len2)
4084{
4085 WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
4086 WCHAR *buf2W = buf1W + 130;
4087 LPWSTR str1W, str2W;
4088 INT len1W = 0, len2W = 0, ret;
4089 UINT locale_cp = CP_ACP;
4090
4091 if (!str1 || !str2)
4092 {
4094 return 0;
4095 }
4096 if (len1 < 0) len1 = strlen(str1);
4097 if (len2 < 0) len2 = strlen(str2);
4098
4099 if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
4100
4101 if (len1)
4102 {
4103 if (len1 <= 130) len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
4104 if (len1W)
4105 str1W = buf1W;
4106 else
4107 {
4108 len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0);
4109 str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
4110 if (!str1W)
4111 {
4113 return 0;
4114 }
4115 MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
4116 }
4117 }
4118 else
4119 {
4120 len1W = 0;
4121 str1W = buf1W;
4122 }
4123
4124 if (len2)
4125 {
4126 if (len2 <= 130) len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
4127 if (len2W)
4128 str2W = buf2W;
4129 else
4130 {
4131 len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0);
4132 str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
4133 if (!str2W)
4134 {
4135 if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
4137 return 0;
4138 }
4139 MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W);
4140 }
4141 }
4142 else
4143 {
4144 len2W = 0;
4145 str2W = buf2W;
4146 }
4147
4148 ret = CompareStringEx(NULL, flags, str1W, len1W, str2W, len2W, NULL, NULL, 0);
4149
4150 if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
4151 if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
4152 return ret;
4153}
4154
4155#if (WINVER >= 0x0600)
4156/******************************************************************************
4157 * CompareStringOrdinal (KERNEL32.@)
4158 */
4159INT WINAPI CompareStringOrdinal(const WCHAR *str1, INT len1, const WCHAR *str2, INT len2, BOOL ignore_case)
4160{
4161 int ret;
4162
4163 if (!str1 || !str2)
4164 {
4166 return 0;
4167 }
4168 if (len1 < 0) len1 = strlenW(str1);
4169 if (len2 < 0) len2 = strlenW(str2);
4170
4171 ret = RtlCompareUnicodeStrings( str1, len1, str2, len2, ignore_case );
4172 if (ret < 0) return CSTR_LESS_THAN;
4173 if (ret > 0) return CSTR_GREATER_THAN;
4174 return CSTR_EQUAL;
4175}
4176#endif // (WINVER >= 0x0600)
4177
4178#ifndef __REACTOS__
4179/*************************************************************************
4180 * lstrcmp (KERNEL32.@)
4181 * lstrcmpA (KERNEL32.@)
4182 *
4183 * Compare two strings using the current thread locale.
4184 *
4185 * PARAMS
4186 * str1 [I] First string to compare
4187 * str2 [I] Second string to compare
4188 *
4189 * RETURNS
4190 * Success: A number less than, equal to or greater than 0 depending on whether
4191 * str1 is less than, equal to or greater than str2 respectively.
4192 * Failure: FALSE. Use GetLastError() to determine the cause.
4193 */
4195{
4196 int ret;
4197
4198 if ((str1 == NULL) && (str2 == NULL)) return 0;
4199 if (str1 == NULL) return -1;
4200 if (str2 == NULL) return 1;
4201
4202 ret = CompareStringA(GetThreadLocale(), LOCALE_USE_CP_ACP, str1, -1, str2, -1);
4203 if (ret) ret -= 2;
4204
4205 return ret;
4206}
4207
4208/*************************************************************************
4209 * lstrcmpi (KERNEL32.@)
4210 * lstrcmpiA (KERNEL32.@)
4211 *
4212 * Compare two strings using the current thread locale, ignoring case.
4213 *
4214 * PARAMS
4215 * str1 [I] First string to compare
4216 * str2 [I] Second string to compare
4217 *
4218 * RETURNS
4219 * Success: A number less than, equal to or greater than 0 depending on whether
4220 * str2 is less than, equal to or greater than str1 respectively.
4221 * Failure: FALSE. Use GetLastError() to determine the cause.
4222 */
4224{
4225 int ret;
4226
4227 if ((str1 == NULL) && (str2 == NULL)) return 0;
4228 if (str1 == NULL) return -1;
4229 if (str2 == NULL) return 1;
4230
4232 if (ret) ret -= 2;
4233
4234 return ret;
4235}
4236
4237/*************************************************************************
4238 * lstrcmpW (KERNEL32.@)
4239 *
4240 * See lstrcmpA.
4241 */
4243{
4244 int ret;
4245
4246 if ((str1 == NULL) && (str2 == NULL)) return 0;
4247 if (str1 == NULL) return -1;
4248 if (str2 == NULL) return 1;
4249
4250 ret = CompareStringW(GetThreadLocale(), 0, str1, -1, str2, -1);
4251 if (ret) ret -= 2;
4252
4253 return ret;
4254}
4255
4256/*************************************************************************
4257 * lstrcmpiW (KERNEL32.@)
4258 *
4259 * See lstrcmpiA.
4260 */
4262{
4263 int ret;
4264
4265 if ((str1 == NULL) && (str2 == NULL)) return 0;
4266 if (str1 == NULL) return -1;
4267 if (str2 == NULL) return 1;
4268
4269 ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, -1, str2, -1);
4270 if (ret) ret -= 2;
4271
4272 return ret;
4273}
4274
4275/******************************************************************************
4276 * LOCALE_Init
4277 */
4278void LOCALE_Init(void)
4279{
4280 extern void CDECL __wine_init_codepages( const union cptable *ansi_cp, const union cptable *oem_cp,
4281 const union cptable *unix_cp );
4282
4283 UINT ansi_cp = 1252, oem_cp = 437, mac_cp = 10000, unix_cp;
4284
4285 setlocale( LC_ALL, "" );
4286
4287#ifdef __APPLE__
4288 /* MacOS doesn't set the locale environment variables so we have to do it ourselves */
4289 if (!has_env("LANG"))
4290 {
4291 const char* mac_locale = get_mac_locale();
4292
4293 setenv( "LANG", mac_locale, 1 );
4294 if (setlocale( LC_ALL, "" ))
4295 TRACE( "setting LANG to '%s'\n", mac_locale );
4296 else
4297 {
4298 /* no C library locale matching Mac locale; don't pass garbage to children */
4299 unsetenv("LANG");
4300 TRACE( "Mac locale %s is not supported by the C library\n", debugstr_a(mac_locale) );
4301 }
4302 }
4303#endif /* __APPLE__ */
4304
4305 unix_cp = setup_unix_locales();
4307
4308#ifdef __APPLE__
4309 if (!unix_cp)
4310 unix_cp = CP_UTF8; /* default to utf-8 even if we don't get a valid locale */
4311#endif
4312
4316
4319 (LPWSTR)&mac_cp, sizeof(mac_cp)/sizeof(WCHAR) );
4321 (LPWSTR)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR) );
4322 if (!unix_cp)
4324 (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) );
4325
4326 if (!(ansi_cptable = wine_cp_get_table( ansi_cp )))
4328 if (!(oem_cptable = wine_cp_get_table( oem_cp )))
4330 if (!(mac_cptable = wine_cp_get_table( mac_cp )))
4331 mac_cptable = wine_cp_get_table( 10000 );
4332 if (unix_cp != CP_UTF8)
4333 {
4334 if (!(unix_cptable = wine_cp_get_table( unix_cp )))
4336 }
4337
4338 __wine_init_codepages( ansi_cptable, oem_cptable, unix_cptable );
4339
4340 TRACE( "ansi=%03d oem=%03d mac=%03d unix=%03d\n",
4341 ansi_cptable->info.codepage, oem_cptable->info.codepage,
4342 mac_cptable->info.codepage, unix_cp );
4343
4344 setlocale(LC_NUMERIC, "C"); /* FIXME: oleaut32 depends on this */
4345}
4346
4347#endif // !__REACTOS__
4348
4349#ifdef __REACTOS__
4350HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
4351#else
4352static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
4353#endif
4354{
4355 UNICODE_STRING keyName;
4357 HANDLE hkey;
4358
4359 RtlInitUnicodeString( &keyName, szKeyName );
4360#ifdef __REACTOS__
4362#else
4363 InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
4364#endif
4365
4366 if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
4367 hkey = 0;
4368
4369 return hkey;
4370}
4371
4372#ifdef __REACTOS__
4374 LPWSTR szValueName, ULONG valueNameSize,
4375 LPWSTR szValueData, ULONG valueDataSize)
4376#else
4378 LPWSTR szValueName, ULONG valueNameSize,
4379 LPWSTR szValueData, ULONG valueDataSize)
4380#endif
4381{
4382 BYTE buffer[80];
4384 DWORD dwLen;
4385
4387 buffer, sizeof(buffer), &dwLen ) != STATUS_SUCCESS ||
4388 info->NameLength > valueNameSize ||
4389 info->DataLength > valueDataSize)
4390 {
4391 return FALSE;
4392 }
4393
4394 TRACE("info->Name %s info->DataLength %d\n", debugstr_w(info->Name), info->DataLength);
4395
4396 memcpy( szValueName, info->Name, info->NameLength);
4397 szValueName[info->NameLength / sizeof(WCHAR)] = '\0';
4398 memcpy( szValueData, buffer + info->DataOffset, info->DataLength );
4399 szValueData[info->DataLength / sizeof(WCHAR)] = '\0';
4400
4401 TRACE("returning %s %s\n", debugstr_w(szValueName), debugstr_w(szValueData));
4402 return TRUE;
4403}
4404
4405static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
4406{
4407 BYTE buffer[128];
4409 DWORD dwSize = sizeof(buffer);
4410 UNICODE_STRING valueName;
4411
4412 RtlInitUnicodeString( &valueName, szValueName );
4413
4414 TRACE("%p, %s\n", hKey, debugstr_w(szValueName));
4417 info->DataLength == sizeof(DWORD))
4418 {
4419 memcpy(lpVal, info->Data, sizeof(DWORD));
4420 return TRUE;
4421 }
4422
4423 return FALSE;
4424}
4425
4427{
4428 LANGID langId;
4429 LPCWSTR szResourceName = MAKEINTRESOURCEW(((lgrpid + 0x2000) >> 4) + 1);
4430 HRSRC hResource;
4431 BOOL bRet = FALSE;
4432
4433 /* FIXME: Is it correct to use the system default langid? */
4434 langId = GetSystemDefaultLangID();
4435
4436 if (SUBLANGID(langId) == SUBLANG_NEUTRAL) langId = get_default_sublang( langId );
4437
4438 hResource = FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, szResourceName, langId );
4439
4440 if (hResource)
4441 {
4442 HGLOBAL hResDir = LoadResource( kernel32_handle, hResource );
4443
4444 if (hResDir)
4445 {
4446 ULONG iResourceIndex = lgrpid & 0xf;
4447 LPCWSTR lpResEntry = LockResource( hResDir );
4448 ULONG i;
4449
4450 for (i = 0; i < iResourceIndex; i++)
4451 lpResEntry += *lpResEntry + 1;
4452
4453 if (*lpResEntry < nameSize)
4454 {
4455 memcpy( szName, lpResEntry + 1, *lpResEntry * sizeof(WCHAR) );
4456 szName[*lpResEntry] = '\0';
4457 bRet = TRUE;
4458 }
4459
4460 }
4461 FreeResource( hResource );
4462 }
4463 return bRet;
4464}
4465
4466/* Callback function ptrs for EnumSystemLanguageGroupsA/W */
4467typedef struct
4468{
4474
4475/* Internal implementation of EnumSystemLanguageGroupsA/W */
4477{
4478 WCHAR szNumber[10], szValue[4];
4479 HANDLE hKey;
4480 BOOL bContinue = TRUE;
4481 ULONG ulIndex = 0;
4482
4483 if (!lpProcs)
4484 {
4486 return FALSE;
4487 }
4488
4489 switch (lpProcs->dwFlags)
4490 {
4491 case 0:
4492 /* Default to LGRPID_INSTALLED */
4493 lpProcs->dwFlags = LGRPID_INSTALLED;
4494 /* Fall through... */
4495 case LGRPID_INSTALLED:
4496 case LGRPID_SUPPORTED:
4497 break;
4498 default:
4500 return FALSE;
4501 }
4502
4504
4505 if (!hKey)
4506 FIXME("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
4507
4508 while (bContinue)
4509 {
4510 if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
4511 szValue, sizeof(szValue) ))
4512 {
4513 BOOL bInstalled = szValue[0] == '1';
4514 LGRPID lgrpid = strtoulW( szNumber, NULL, 16 );
4515
4516 TRACE("grpid %s (%sinstalled)\n", debugstr_w(szNumber),
4517 bInstalled ? "" : "not ");
4518
4519 if (lpProcs->dwFlags == LGRPID_SUPPORTED || bInstalled)
4520 {
4521 WCHAR szGrpName[48];
4522
4523 if (!NLS_GetLanguageGroupName( lgrpid, szGrpName, sizeof(szGrpName) / sizeof(WCHAR) ))
4524 szGrpName[0] = '\0';
4525
4526 if (lpProcs->procW)
4527 bContinue = lpProcs->procW( lgrpid, szNumber, szGrpName, lpProcs->dwFlags,
4528 lpProcs->lParam );
4529 else
4530 {
4531 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
4532 char szGrpNameA[48];
4533
4534 /* FIXME: MSDN doesn't say which code page the W->A translation uses,
4535 * or whether the language names are ever localised. Assume CP_ACP.
4536 */
4537
4538 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
4539 WideCharToMultiByte(CP_ACP, 0, szGrpName, -1, szGrpNameA, sizeof(szGrpNameA), 0, 0);
4540
4541 bContinue = lpProcs->procA( lgrpid, szNumberA, szGrpNameA, lpProcs->dwFlags,
4542 lpProcs->lParam );
4543 }
4544 }
4545
4546 ulIndex++;
4547 }
4548 else
4549 bContinue = FALSE;
4550
4551 if (!bContinue)
4552 break;
4553 }
4554
4555 if (hKey)
4556 NtClose( hKey );
4557
4558 return TRUE;
4559}
4560
4561/******************************************************************************
4562 * EnumSystemLanguageGroupsA (KERNEL32.@)
4563 *
4564 * Call a users function for each language group available on the system.
4565 *
4566 * PARAMS
4567 * pLangGrpEnumProc [I] Callback function to call for each language group
4568 * dwFlags [I] LGRPID_SUPPORTED=All Supported, LGRPID_INSTALLED=Installed only
4569 * lParam [I] User parameter to pass to pLangGrpEnumProc
4570 *
4571 * RETURNS
4572 * Success: TRUE.
4573 * Failure: FALSE. Use GetLastError() to determine the cause.
4574 */
4577{
4579
4580 TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
4581
4582 procs.procA = pLangGrpEnumProc;
4583 procs.procW = NULL;
4584 procs.dwFlags = dwFlags;
4585 procs.lParam = lParam;
4586
4587 return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
4588}
4589
4590/******************************************************************************
4591 * EnumSystemLanguageGroupsW (KERNEL32.@)
4592 *
4593 * See EnumSystemLanguageGroupsA.
4594 */
4597{
4599
4600 TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam);
4601
4602 procs.procA = NULL;
4603 procs.procW = pLangGrpEnumProc;
4604 procs.dwFlags = dwFlags;
4605 procs.lParam = lParam;
4606
4607 return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL);
4608}
4609
4610/******************************************************************************
4611 * IsValidLanguageGroup (KERNEL32.@)
4612 *
4613 * Determine if a language group is supported and/or installed.
4614 *
4615 * PARAMS
4616 * lgrpid [I] Language Group Id (LGRPID_ values from "winnls.h")
4617 * dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed
4618 *
4619 * RETURNS
4620 * TRUE, if lgrpid is supported and/or installed, according to dwFlags.
4621 * FALSE otherwise.
4622 */
4624{
4625 static const WCHAR szFormat[] = { '%','x','\0' };
4626 WCHAR szValueName[16], szValue[2];
4627 BOOL bSupported = FALSE, bInstalled = FALSE;
4628 HANDLE hKey;
4629
4630
4631 switch (dwFlags)
4632 {
4633 case LGRPID_INSTALLED:
4634 case LGRPID_SUPPORTED:
4635
4637
4638 sprintfW( szValueName, szFormat, lgrpid );
4639
4640 if (NLS_RegGetDword( hKey, szValueName, (LPDWORD)szValue ))
4641 {
4642 bSupported = TRUE;
4643
4644 if (szValue[0] == '1')
4645 bInstalled = TRUE;
4646 }
4647
4648 if (hKey)
4649 NtClose( hKey );
4650
4651 break;
4652 }
4653
4654 if ((dwFlags == LGRPID_SUPPORTED && bSupported) ||
4655 (dwFlags == LGRPID_INSTALLED && bInstalled))
4656 return TRUE;
4657
4658 return FALSE;
4659}
4660
4661/* Callback function ptrs for EnumLanguageGrouplocalesA/W */
4662typedef struct
4663{
4670
4671/* Internal implementation of EnumLanguageGrouplocalesA/W */
4673{
4674 static const WCHAR szAlternateSortsKeyName[] = {
4675 'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s','\0'
4676 };
4677 WCHAR szNumber[10], szValue[4];
4678 HANDLE hKey;
4679 BOOL bContinue = TRUE, bAlternate = FALSE;
4680 LGRPID lgrpid;
4681 ULONG ulIndex = 1; /* Ignore default entry of 1st key */
4682
4683 if (!lpProcs || !lpProcs->lgrpid || lpProcs->lgrpid > LGRPID_ARMENIAN)
4684 {
4686 return FALSE;
4687 }
4688
4689 if (lpProcs->dwFlags)
4690 {
4692 return FALSE;
4693 }
4694
4696
4697 if (!hKey)
4698 WARN("NLS registry key not found. Please apply the default registry file 'wine.inf'\n");
4699
4700 while (bContinue)
4701 {
4702 if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber),
4703 szValue, sizeof(szValue) ))
4704 {
4705 lgrpid = strtoulW( szValue, NULL, 16 );
4706
4707 TRACE("lcid %s, grpid %d (%smatched)\n", debugstr_w(szNumber),
4708 lgrpid, lgrpid == lpProcs->lgrpid ? "" : "not ");
4709
4710 if (lgrpid == lpProcs->lgrpid)
4711 {
4712 LCID lcid;
4713
4714 lcid = strtoulW( szNumber, NULL, 16 );
4715
4716 /* FIXME: native returns extra text for a few (17/150) locales, e.g:
4717 * '00000437 ;Georgian'
4718 * At present we only pass the LCID string.
4719 */
4720
4721 if (lpProcs->procW)
4722 bContinue = lpProcs->procW( lgrpid, lcid, szNumber, lpProcs->lParam );
4723 else
4724 {
4725 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
4726
4727 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
4728
4729 bContinue = lpProcs->procA( lgrpid, lcid, szNumberA, lpProcs->lParam );
4730 }
4731 }
4732
4733 ulIndex++;
4734 }
4735 else
4736 {
4737 /* Finished enumerating this key */
4738 if (!bAlternate)
4739 {
4740 /* Enumerate alternate sorts also */
4741 hKey = NLS_RegOpenKey( hKey, szAlternateSortsKeyName );
4742 bAlternate = TRUE;
4743 ulIndex = 0;
4744 }
4745 else
4746 bContinue = FALSE; /* Finished both keys */
4747 }
4748
4749 if (!bContinue)
4750 break;
4751 }
4752
4753 if (hKey)
4754 NtClose( hKey );
4755
4756 return TRUE;
4757}
4758
4759/******************************************************************************
4760 * EnumLanguageGroupLocalesA (KERNEL32.@)
4761 *
4762 * Call a users function for every locale in a language group available on the system.
4763 *
4764 * PARAMS
4765 * pLangGrpLcEnumProc [I] Callback function to call for each locale
4766 * lgrpid [I] Language group (LGRPID_ values from "winnls.h")
4767 * dwFlags [I] Reserved, set to 0
4768 * lParam [I] User parameter to pass to pLangGrpLcEnumProc
4769 *
4770 * RETURNS
4771 * Success: TRUE.
4772 * Failure: FALSE. Use GetLastError() to determine the cause.
4773 */
4776{
4778
4779 TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
4780
4781 callbacks.procA = pLangGrpLcEnumProc;
4782 callbacks.procW = NULL;
4783 callbacks.dwFlags = dwFlags;
4784 callbacks.lgrpid = lgrpid;
4785 callbacks.lParam = lParam;
4786
4787 return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
4788}
4789
4790/******************************************************************************
4791 * EnumLanguageGroupLocalesW (KERNEL32.@)
4792 *
4793 * See EnumLanguageGroupLocalesA.
4794 */
4797{
4799
4800 TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam);
4801
4802 callbacks.procA = NULL;
4803 callbacks.procW = pLangGrpLcEnumProc;
4804 callbacks.dwFlags = dwFlags;
4805 callbacks.lgrpid = lgrpid;
4806 callbacks.lParam = lParam;
4807
4808 return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL );
4809}
4810
4811/******************************************************************************
4812 * InvalidateNLSCache (KERNEL32.@)
4813 *
4814 * Invalidate the cache of NLS values.
4815 *
4816 * PARAMS
4817 * None.
4818 *
4819 * RETURNS
4820 * Success: TRUE.
4821 * Failure: FALSE.
4822 */
4824{
4825#ifdef __REACTOS__
4827 return TRUE;
4828#else
4829 FIXME("() stub\n");
4830 return FALSE;
4831#endif
4832}
4833
4834/******************************************************************************
4835 * GetUserGeoID (KERNEL32.@)
4836 */
4838{
4840 static const WCHAR geoW[] = {'G','e','o',0};
4841 static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
4842 WCHAR bufferW[40], *end;
4843 DWORD count;
4844 HANDLE hkey, hSubkey = 0;
4845 UNICODE_STRING keyW;
4847 RtlInitUnicodeString( &keyW, nationW );
4848 count = sizeof(bufferW);
4849
4850 if(!(hkey = create_registry_key())) return ret;
4851
4852 switch( GeoClass ){
4853 case GEOCLASS_NATION:
4854 if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
4855 {
4856 if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
4857 bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength)
4858 ret = strtolW((LPCWSTR)info->Data, &end, 10);
4859 }
4860 break;
4861 case GEOCLASS_REGION:
4862 FIXME("GEOCLASS_REGION not handled yet\n");
4863 break;
4864 }
4865
4866 NtClose(hkey);
4867 if (hSubkey) NtClose(hSubkey);
4868 return ret;
4869}
4870
4871/******************************************************************************
4872 * SetUserGeoID (KERNEL32.@)
4873 */
4875{
4876 static const WCHAR geoW[] = {'G','e','o',0};
4877 static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
4878 static const WCHAR formatW[] = {'%','i',0};
4879 UNICODE_STRING nameW,keyW;
4880 WCHAR bufferW[10];
4882 HANDLE hkey;
4883
4884 if(!(hkey = create_registry_key())) return FALSE;
4885
4886 attr.Length = sizeof(attr);
4887 attr.RootDirectory = hkey;
4888 attr.ObjectName = &nameW;
4889 attr.Attributes = 0;
4890 attr.SecurityDescriptor = NULL;
4891 attr.SecurityQualityOfService = NULL;
4892 RtlInitUnicodeString( &nameW, geoW );
4893 RtlInitUnicodeString( &keyW, nationW );
4894
4895 if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
4896
4897 {
4898 NtClose(attr.RootDirectory);
4899 return FALSE;
4900 }
4901
4902 sprintfW(bufferW, formatW, GeoID);
4903 NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
4904 NtClose(attr.RootDirectory);
4905 NtClose(hkey);
4906 return TRUE;
4907}
4908
4909typedef struct
4910{
4911 union
4912 {
4915 } u;
4919
4922{
4924 char buf[20];
4925
4926 sprintf(buf, "%08x", (UINT)LangID);
4927 return enum_uilang->u.procA( buf, enum_uilang->param );
4928}
4929
4932{
4933 static const WCHAR formatW[] = {'%','0','8','x',0};
4935 WCHAR buf[20];
4936
4937 sprintfW( buf, formatW, (UINT)LangID );
4938 return enum_uilang->u.procW( buf, enum_uilang->param );
4939}
4940
4941/******************************************************************************
4942 * EnumUILanguagesA (KERNEL32.@)
4943 */
4945{
4946 ENUM_UILANG_CALLBACK enum_uilang;
4947
4948 TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
4949
4950 if(!pUILangEnumProc) {
4952 return FALSE;
4953 }
4954 if(dwFlags) {
4956 return FALSE;
4957 }
4958
4959 enum_uilang.u.procA = pUILangEnumProc;
4960 enum_uilang.flags = dwFlags;
4961 enum_uilang.param = lParam;
4962
4965 (LONG_PTR)&enum_uilang);
4966 return TRUE;
4967}
4968
4969/******************************************************************************
4970 * EnumUILanguagesW (KERNEL32.@)
4971 */
4973{
4974 ENUM_UILANG_CALLBACK enum_uilang;
4975
4976 TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam);
4977
4978
4979 if(!pUILangEnumProc) {
4981 return FALSE;
4982 }
4983 if(dwFlags) {
4985 return FALSE;
4986 }
4987
4988 enum_uilang.u.procW = pUILangEnumProc;
4989 enum_uilang.flags = dwFlags;
4990 enum_uilang.param = lParam;
4991
4994 (LONG_PTR)&enum_uilang);
4995 return TRUE;
4996}
4997
5003
5011};
5012
5013static const struct geoinfo_t geoinfodata[] = {
5014 { 2, {'A','G',0}, {'A','T','G',0}, 10039880, 28 }, /* Antigua and Barbuda */
5015 { 3, {'A','F',0}, {'A','F','G',0}, 47614, 4 }, /* Afghanistan */
5016 { 4, {'D','Z',0}, {'D','Z','A',0}, 42487, 12 }, /* Algeria */
5017 { 5, {'A','Z',0}, {'A','Z','E',0}, 47611, 31 }, /* Azerbaijan */
5018 { 6, {'A','L',0}, {'A','L','B',0}, 47610, 8 }, /* Albania */
5019 { 7, {'A','M',0}, {'A','R','M',0}, 47611, 51 }, /* Armenia */
5020 { 8, {'A','D',0}, {'A','N','D',0}, 47610, 20 }, /* Andorra */
5021 { 9, {'A','O',0}, {'A','G','O',0}, 42484, 24 }, /* Angola */
5022 { 10, {'A','S',0}, {'A','S','M',0}, 26286, 16 }, /* American Samoa */
5023 { 11, {'A','R',0}, {'A','R','G',0}, 31396, 32 }, /* Argentina */
5024 { 12, {'A','U',0}, {'A','U','S',0}, 10210825, 36 }, /* Australia */
5025 { 14, {'A','T',0}, {'A','U','T',0}, 10210824, 40 }, /* Austria */
5026 { 17, {'B','H',0}, {'B','H','R',0}, 47611, 48 }, /* Bahrain */
5027 { 18, {'B','B',0}, {'B','R','B',0}, 10039880, 52 }, /* Barbados */
5028 { 19, {'B','W',0}, {'B','W','A',0}, 10039883, 72 }, /* Botswana */
5029 { 20, {'B','M',0}, {'B','M','U',0}, 23581, 60 }, /* Bermuda */
5030 { 21, {'B','E',0}, {'B','E','L',0}, 10210824, 56 }, /* Belgium */
5031 { 22, {'B','S',0}, {'B','H','S',0}, 10039880, 44 }, /* Bahamas, The */
5032 { 23, {'B','D',0}, {'B','G','D',0}, 47614, 50 }, /* Bangladesh */
5033 { 24, {'B','Z',0}, {'B','L','Z',0}, 27082, 84 }, /* Belize */
5034 { 25, {'B','A',0}, {'B','I','H',0}, 47610, 70 }, /* Bosnia and Herzegovina */
5035 { 26, {'B','O',0}, {'B','O','L',0}, 31396, 68 }, /* Bolivia */
5036 { 27, {'M','M',0}, {'M','M','R',0}, 47599, 104 }, /* Myanmar */
5037 { 28, {'B','J',0}, {'B','E','N',0}, 42483, 204 }, /* Benin */
5038 { 29, {'B','Y',0}, {'B','L','R',0}, 47609, 112 }, /* Belarus */
5039 { 30, {'S','B',0}, {'S','L','B',0}, 20900, 90 }, /* Solomon Islands */
5040 { 32, {'B','R',0}, {'B','R','A',0}, 31396, 76 }, /* Brazil */
5041 { 34, {'B','T',0}, {'B','T','N',0}, 47614, 64 }, /* Bhutan */
5042 { 35, {'B','G',0}, {'B','G','R',0}, 47609, 100 }, /* Bulgaria */
5043 { 37, {'B','N',0}, {'B','R','N',0}, 47599, 96 }, /* Brunei */
5044 { 38, {'B','I',0}, {'B','D','I',0}, 47603, 108 }, /* Burundi */
5045 { 39, {'C','A',0}, {'C','A','N',0}, 23581, 124 }, /* Canada */
5046 { 40, {'K','H',0}, {'K','H','M',0}, 47599, 116 }, /* Cambodia */
5047 { 41, {'T','D',0}, {'T','C','D',0}, 42484, 148 }, /* Chad */
5048 { 42, {'L','K',0}, {'L','K','A',0}, 47614, 144 }, /* Sri Lanka */
5049 { 43, {'C','G',0}, {'C','O','G',0}, 42484, 178 }, /* Congo */
5050 { 44, {'C','D',0}, {'C','O','D',0}, 42484, 180 }, /* Congo (DRC) */
5051 { 45, {'C','N',0}, {'C','H','N',0}, 47600, 156 }, /* China */
5052 { 46, {'C','L',0}, {'C','H','L',0}, 31396, 152 }, /* Chile */
5053 { 49, {'C','M',0}, {'C','M','R',0}, 42484, 120 }, /* Cameroon */
5054 { 50, {'K','M',0}, {'C','O','M',0}, 47603, 174 }, /* Comoros */
5055 { 51, {'C','O',0}, {'C','O','L',0}, 31396, 170 }, /* Colombia */
5056 { 54, {'C','R',0}, {'C','R','I',0}, 27082, 188 }, /* Costa Rica */
5057 { 55, {'C','F',0}, {'C','A','F',0}, 42484, 140 }, /* Central African Republic */
5058 { 56, {'C','U',0}, {'C','U','B',0}, 10039880, 192 }, /* Cuba */
5059 { 57, {'C','V',0}, {'C','P','V',0}, 42483, 132 }, /* Cape Verde */
5060 { 59, {'C','Y',0}, {'C','Y','P',0}, 47611, 196 }, /* Cyprus */
5061 { 61, {'D','K',0}, {'D','N','K',0}, 10039882, 208 }, /* Denmark */
5062 { 62, {'D','J',0}, {'D','J','I',0}, 47603, 262 }, /* Djibouti */
5063 { 63, {'D','M',0}, {'D','M','A',0}, 10039880, 212 }, /* Dominica */
5064 { 65, {'D','O',0}, {'D','O','M',0}, 10039880, 214 }, /* Dominican Republic */
5065 { 66, {'E','C',0}, {'E','C','U',0}, 31396, 218 }, /* Ecuador */
5066 { 67, {'E','G',0}, {'E','G','Y',0}, 42487, 818 }, /* Egypt */
5067 { 68, {'I','E',0}, {'I','R','L',0}, 10039882, 372 }, /* Ireland */
5068 { 69, {'G','Q',0}, {'G','N','Q',0}, 42484, 226 }, /* Equatorial Guinea */
5069 { 70, {'E','E',0}, {'E','S','T',0}, 10039882, 233 }, /* Estonia */
5070 { 71, {'E','R',0}, {'E','R','I',0}, 47603, 232 }, /* Eritrea */
5071 { 72, {'S','V',0}, {'S','L','V',0}, 27082, 222 }, /* El Salvador */
5072 { 73, {'E','T',0}, {'E','T','H',0}, 47603, 231 }, /* Ethiopia */
5073 { 75, {'C','Z',0}, {'C','Z','E',0}, 47609, 203 }, /* Czech Republic */
5074 { 77, {'F','I',0}, {'F','I','N',0}, 10039882, 246 }, /* Finland */
5075 { 78, {'F','J',0}, {'F','J','I',0}, 20900, 242 }, /* Fiji Islands */
5076 { 80, {'F','M',0}, {'F','S','M',0}, 21206, 583 }, /* Micronesia */
5077 { 81, {'F','O',0}, {'F','R','O',0}, 10039882, 234 }, /* Faroe Islands */
5078 { 84, {'F','R',0}, {'F','R','A',0}, 10210824, 250 }, /* France */
5079 { 86, {'G','M',0}, {'G','M','B',0}, 42483, 270 }, /* Gambia, The */
5080 { 87, {'G','A',0}, {'G','A','B',0}, 42484, 266 }, /* Gabon */
5081 { 88, {'G','E',0}, {'G','E','O',0}, 47611, 268 }, /* Georgia */
5082 { 89, {'G','H',0}, {'G','H','A',0}, 42483, 288 }, /* Ghana */
5083 { 90, {'G','I',0}, {'G','I','B',0}, 47610, 292 }, /* Gibraltar */
5084 { 91, {'G','D',0}, {'G','R','D',0}, 10039880, 308 }, /* Grenada */
5085 { 93, {'G','L',0}, {'G','R','L',0}, 23581, 304 }, /* Greenland */
5086 { 94, {'D','E',0}, {'D','E','U',0}, 10210824, 276 }, /* Germany */
5087 { 98, {'G','R',0}, {'G','R','C',0}, 47610, 300 }, /* Greece */
5088 { 99, {'G','T',0}, {'G','T','M',0}, 27082, 320 }, /* Guatemala */
5089 { 100, {'G','N',0}, {'G','I','N',0}, 42483, 324 }, /* Guinea */
5090 { 101, {'G','Y',0}, {'G','U','Y',0}, 31396, 328 }, /* Guyana */
5091 { 103, {'H','T',0}, {'H','T','I',0}, 10039880, 332 }, /* Haiti */
5092 { 104, {'H','K',0}, {'H','K','G',0}, 47600, 344 }, /* Hong Kong S.A.R. */
5093 { 106, {'H','N',0}, {'H','N','D',0}, 27082, 340 }, /* Honduras */
5094 { 108, {'H','R',0}, {'H','R','V',0}, 47610, 191 }, /* Croatia */
5095 { 109, {'H','U',0}, {'H','U','N',0}, 47609, 348 }, /* Hungary */
5096 { 110, {'I','S',0}, {'I','S','L',0}, 10039882, 352 }, /* Iceland */
5097 { 111, {'I','D',0}, {'I','D','N',0}, 47599, 360 }, /* Indonesia */
5098 { 113, {'I','N',0}, {'I','N','D',0}, 47614, 356 }, /* India */
5099 { 114, {'I','O',0}, {'I','O','T',0}, 39070, 86 }, /* British Indian Ocean Territory */
5100 { 116, {'I','R',0}, {'I','R','N',0}, 47614, 364 }, /* Iran */
5101 { 117, {'I','L',0}, {'I','S','R',0}, 47611, 376 }, /* Israel */
5102 { 118, {'I','T',0}, {'I','T','A',0}, 47610, 380 }, /* Italy */
5103 { 119, {'C','I',0}, {'C','I','V',0}, 42483, 384 }, /* Côte d'Ivoire */
5104 { 121, {'I','Q',0}, {'I','R','Q',0}, 47611, 368 }, /* Iraq */
5105 { 122, {'J','P',0}, {'J','P','N',0}, 47600, 392 }, /* Japan */
5106 { 124, {'J','M',0}, {'J','A','M',0}, 10039880, 388 }, /* Jamaica */
5107 { 125, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Jan Mayen */
5108 { 126, {'J','O',0}, {'J','O','R',0}, 47611, 400 }, /* Jordan */
5109 { 127, {'X','X',0}, {'X','X',0}, 161832256 }, /* Johnston Atoll */
5110 { 129, {'K','E',0}, {'K','E','N',0}, 47603, 404 }, /* Kenya */
5111 { 130, {'K','G',0}, {'K','G','Z',0}, 47590, 417 }, /* Kyrgyzstan */
5112 { 131, {'K','P',0}, {'P','R','K',0}, 47600, 408 }, /* North Korea */
5113 { 133, {'K','I',0}, {'K','I','R',0}, 21206, 296 }, /* Kiribati */
5114 { 134, {'K','R',0}, {'K','O','R',0}, 47600, 410 }, /* Korea */
5115 { 136, {'K','W',0}, {'K','W','T',0}, 47611, 414 }, /* Kuwait */
5116 { 137, {'K','Z',0}, {'K','A','Z',0}, 47590, 398 }, /* Kazakhstan */
5117 { 138, {'L','A',0}, {'L','A','O',0}, 47599, 418 }, /* Laos */
5118 { 139, {'L','B',0}, {'L','B','N',0}, 47611, 422 }, /* Lebanon */
5119 { 140, {'L','V',0}, {'L','V','A',0}, 10039882, 428 }, /* Latvia */
5120 { 141, {'L','T',0}, {'L','T','U',0}, 10039882, 440 }, /* Lithuania */
5121 { 142, {'L','R',0}, {'L','B','R',0}, 42483, 430 }, /* Liberia */
5122 { 143, {'S','K',0}, {'S','V','K',0}, 47609, 703 }, /* Slovakia */
5123 { 145, {'L','I',0}, {'L','I','E',0}, 10210824, 438 }, /* Liechtenstein */
5124 { 146, {'L','S',0}, {'L','S','O',0}, 10039883, 426 }, /* Lesotho */
5125 { 147, {'L','U',0}, {'L','U','X',0}, 10210824, 442 }, /* Luxembourg */
5126 { 148, {'L','Y',0}, {'L','B','Y',0}, 42487, 434 }, /* Libya */
5127 { 149, {'M','G',0}, {'M','D','G',0}, 47603, 450 }, /* Madagascar */
5128 { 151, {'M','O',0}, {'M','A','C',0}, 47600, 446 }, /* Macao S.A.R. */
5129 { 152, {'M','D',0}, {'M','D','A',0}, 47609, 498 }, /* Moldova */
5130 { 154, {'M','N',0}, {'M','N','G',0}, 47600, 496 }, /* Mongolia */
5131 { 156, {'M','W',0}, {'M','W','I',0}, 47603, 454 }, /* Malawi */
5132 { 157, {'M','L',0}, {'M','L','I',0}, 42483, 466 }, /* Mali */
5133 { 158, {'M','C',0}, {'M','C','O',0}, 10210824, 492 }, /* Monaco */
5134 { 159, {'M','A',0}, {'M','A','R',0}, 42487, 504 }, /* Morocco */
5135 { 160, {'M','U',0}, {'M','U','S',0}, 47603, 480 }, /* Mauritius */
5136 { 162, {'M','R',0}, {'M','R','T',0}, 42483, 478 }, /* Mauritania */
5137 { 163, {'M','T',0}, {'M','L','T',0}, 47610, 470 }, /* Malta */
5138 { 164, {'O','M',0}, {'O','M','N',0}, 47611, 512 }, /* Oman */
5139 { 165, {'M','V',0}, {'M','D','V',0}, 47614, 462 }, /* Maldives */
5140 { 166, {'M','X',0}, {'M','E','X',0}, 27082, 484 }, /* Mexico */
5141 { 167, {'M','Y',0}, {'M','Y','S',0}, 47599, 458 }, /* Malaysia */
5142 { 168, {'M','Z',0}, {'M','O','Z',0}, 47603, 508 }, /* Mozambique */
5143 { 173, {'N','E',0}, {'N','E','R',0}, 42483, 562 }, /* Niger */
5144 { 174, {'V','U',0}, {'V','U','T',0}, 20900, 548 }, /* Vanuatu */
5145 { 175, {'N','G',0}, {'N','G','A',0}, 42483, 566 }, /* Nigeria */
5146 { 176, {'N','L',0}, {'N','L','D',0}, 10210824, 528 }, /* Netherlands */
5147 { 177, {'N','O',0}, {'N','O','R',0}, 10039882, 578 }, /* Norway */
5148 { 178, {'N','P',0}, {'N','P','L',0}, 47614, 524 }, /* Nepal */
5149 { 180, {'N','R',0}, {'N','R','U',0}, 21206, 520 }, /* Nauru */
5150 { 181, {'S','R',0}, {'S','U','R',0}, 31396, 740 }, /* Suriname */
5151 { 182, {'N','I',0}, {'N','I','C',0}, 27082, 558 }, /* Nicaragua */
5152 { 183, {'N','Z',0}, {'N','Z','L',0}, 10210825, 554 }, /* New Zealand */
5153 { 184, {'P','S',0}, {'P','S','E',0}, 47611, 275 }, /* Palestinian Authority */
5154 { 185, {'P','Y',0}, {'P','R','Y',0}, 31396, 600 }, /* Paraguay */
5155 { 187, {'P','E',0}, {'P','E','R',0}, 31396, 604 }, /* Peru */
5156 { 190, {'P','K',0}, {'P','A','K',0}, 47614, 586 }, /* Pakistan */
5157 { 191, {'P','L',0}, {'P','O','L',0}, 47609, 616 }, /* Poland */
5158 { 192, {'P','A',0}, {'P','A','N',0}, 27082, 591 }, /* Panama */
5159 { 193, {'P','T',0}, {'P','R','T',0}, 47610, 620 }, /* Portugal */
5160 { 194, {'P','G',0}, {'P','N','G',0}, 20900, 598 }, /* Papua New Guinea */
5161 { 195, {'P','W',0}, {'P','L','W',0}, 21206, 585 }, /* Palau */
5162 { 196, {'G','W',0}, {'G','N','B',0}, 42483, 624 }, /* Guinea-Bissau */
5163 { 197, {'Q','A',0}, {'Q','A','T',0}, 47611, 634 }, /* Qatar */
5164 { 198, {'R','E',0}, {'R','E','U',0}, 47603, 638 }, /* Reunion */
5165 { 199, {'M','H',0}, {'M','H','L',0}, 21206, 584 }, /* Marshall Islands */
5166 { 200, {'R','O',0}, {'R','O','U',0}, 47609, 642 }, /* Romania */
5167 { 201, {'P','H',0}, {'P','H','L',0}, 47599, 608 }, /* Philippines */
5168 { 202, {'P','R',0}, {'P','R','I',0}, 10039880, 630 }, /* Puerto Rico */
5169 { 203, {'R','U',0}, {'R','U','S',0}, 47609, 643 }, /* Russia */
5170 { 204, {'R','W',0}, {'R','W','A',0}, 47603, 646 }, /* Rwanda */
5171 { 205, {'S','A',0}, {'S','A','U',0}, 47611, 682 }, /* Saudi Arabia */
5172 { 206, {'P','M',0}, {'S','P','M',0}, 23581, 666 }, /* St. Pierre and Miquelon */
5173 { 207, {'K','N',0}, {'K','N','A',0}, 10039880, 659 }, /* St. Kitts and Nevis */
5174 { 208, {'S','C',0}, {'S','Y','C',0}, 47603, 690 }, /* Seychelles */
5175 { 209, {'Z','A',0}, {'Z','A','F',0}, 10039883, 710 }, /* South Africa */
5176 { 210, {'S','N',0}, {'S','E','N',0}, 42483, 686 }, /* Senegal */
5177 { 212, {'S','I',0}, {'S','V','N',0}, 47610, 705 }, /* Slovenia */
5178 { 213, {'S','L',0}, {'S','L','E',0}, 42483, 694 }, /* Sierra Leone */
5179 { 214, {'S','M',0}, {'S','M','R',0}, 47610, 674 }, /* San Marino */
5180 { 215, {'S','G',0}, {'S','G','P',0}, 47599, 702 }, /* Singapore */
5181 { 216, {'S','O',0}, {'S','O','M',0}, 47603, 706 }, /* Somalia */
5182 { 217, {'E','S',0}, {'E','S','P',0}, 47610, 724 }, /* Spain */
5183 { 218, {'L','C',0}, {'L','C','A',0}, 10039880, 662 }, /* St. Lucia */
5184 { 219, {'S','D',0}, {'S','D','N',0}, 42487, 736 }, /* Sudan */
5185 { 220, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Svalbard */
5186 { 221, {'S','E',0}, {'S','W','E',0}, 10039882, 752 }, /* Sweden */
5187 { 222, {'S','Y',0}, {'S','Y','R',0}, 47611, 760 }, /* Syria */
5188 { 223, {'C','H',0}, {'C','H','E',0}, 10210824, 756 }, /* Switzerland */
5189 { 224, {'A','E',0}, {'A','R','E',0}, 47611, 784 }, /* United Arab Emirates */
5190 { 225, {'T','T',0}, {'T','T','O',0}, 10039880, 780 }, /* Trinidad and Tobago */
5191 { 227, {'T','H',0}, {'T','H','A',0}, 47599, 764 }, /* Thailand */
5192 { 228, {'T','J',0}, {'T','J','K',0}, 47590, 762 }, /* Tajikistan */
5193 { 231, {'T','O',0}, {'T','O','N',0}, 26286, 776 }, /* Tonga */
5194 { 232, {'T','G',0}, {'T','G','O',0}, 42483, 768 }, /* Togo */
5195 { 233, {'S','T',0}, {'S','T','P',0}, 42484, 678 }, /* São Tomé and Príncipe */
5196 { 234, {'T','N',0}, {'T','U','N',0}, 42487, 788 }, /* Tunisia */
5197 { 235, {'T','R',0}, {'T','U','R',0}, 47611, 792 }, /* Turkey */
5198 { 236, {'T','V',0}, {'T','U','V',0}, 26286, 798 }, /* Tuvalu */
5199 { 237, {'T','W',0}, {'T','W','N',0}, 47600, 158 }, /* Taiwan */
5200 { 238, {'T','M',0}, {'T','K','M',0}, 47590, 795 }, /* Turkmenistan */
5201 { 239, {'T','Z',0}, {'T','Z','A',0}, 47603, 834 }, /* Tanzania */
5202 { 240, {'U','G',0}, {'U','G','A',0}, 47603, 800 }, /* Uganda */
5203 { 241, {'U','A',0}, {'U','K','R',0}, 47609, 804 }, /* Ukraine */
5204 { 242, {'G','B',0}, {'G','B','R',0}, 10039882, 826 }, /* United Kingdom */
5205 { 244, {'U','S',0}, {'U','S','A',0}, 23581, 840 }, /* United States */
5206 { 245, {'B','F',0}, {'B','F','A',0}, 42483, 854 }, /* Burkina Faso */
5207 { 246, {'U','Y',0}, {'U','R','Y',0}, 31396, 858 }, /* Uruguay */
5208 { 247, {'U','Z',0}, {'U','Z','B',0}, 47590, 860 }, /* Uzbekistan */
5209 { 248, {'V','C',0}, {'V','C','T',0}, 10039880, 670 }, /* St. Vincent and the Grenadines */
5210 { 249, {'V','E',0}, {'V','E','N',0}, 31396, 862 }, /* Bolivarian Republic of Venezuela */
5211 { 251, {'V','N',0}, {'V','N','M',0}, 47599, 704 }, /* Vietnam */
5212 { 252, {'V','I',0}, {'V','I','R',0}, 10039880, 850 }, /* Virgin Islands */
5213 { 253, {'V','A',0}, {'V','A','T',0}, 47610, 336 }, /* Vatican City */
5214 { 254, {'N','A',0}, {'N','A','M',0}, 10039883, 516 }, /* Namibia */
5215 { 257, {'E','H',0}, {'E','S','H',0}, 42487, 732 }, /* Western Sahara (disputed) */
5216 { 258, {'X','X',0}, {'X','X',0}, 161832256 }, /* Wake Island */
5217 { 259, {'W','S',0}, {'W','S','M',0}, 26286, 882 }, /* Samoa */
5218 { 260, {'S','Z',0}, {'S','W','Z',0}, 10039883, 748 }, /* Swaziland */
5219 { 261, {'Y','E',0}, {'Y','E','M',0}, 47611, 887 }, /* Yemen */
5220 { 263, {'Z','M',0}, {'Z','M','B',0}, 47603, 894 }, /* Zambia */
5221 { 264, {'Z','W',0}, {'Z','W','E',0}, 47603, 716 }, /* Zimbabwe */
5222 { 269, {'C','S',0}, {'S','C','G',0}, 47610, 891 }, /* Serbia and Montenegro (Former) */
5223 { 270, {'M','E',0}, {'M','N','E',0}, 47610, 499 }, /* Montenegro */
5224 { 271, {'R','S',0}, {'S','R','B',0}, 47610, 688 }, /* Serbia */
5225 { 273, {'C','W',0}, {'C','U','W',0}, 10039880, 531 }, /* Curaçao */
5226 { 276, {'S','S',0}, {'S','S','D',0}, 42487, 728 }, /* South Sudan */
5227 { 300, {'A','I',0}, {'A','I','A',0}, 10039880, 660 }, /* Anguilla */
5228 { 301, {'A','Q',0}, {'A','T','A',0}, 39070, 10 }, /* Antarctica */
5229 { 302, {'A','W',0}, {'A','B','W',0}, 10039880, 533 }, /* Aruba */
5230 { 303, {'X','X',0}, {'X','X',0}, 39070 }, /* Ascension Island */
5231 { 304, {'X','X',0}, {'X','X',0}, 10210825 }, /* Ashmore and Cartier Islands */
5232 { 305, {'X','X',0}, {'X','X',0}, 161832256 }, /* Baker Island */
5233 { 306, {'B','V',0}, {'B','V','T',0}, 39070, 74 }, /* Bouvet Island */
5234 { 307, {'K','Y',0}, {'C','Y','M',0}, 10039880, 136 }, /* Cayman Islands */
5235 { 308, {'X','X',0}, {'X','X',0}, 10210824, 0, LOCATION_BOTH }, /* Channel Islands */
5236 { 309, {'C','X',0}, {'C','X','R',0}, 12, 162 }, /* Christmas Island */
5237 { 310, {'X','X',0}, {'X','X',0}, 27114 }, /* Clipperton Island */
5238 { 311, {'C','C',0}, {'C','C','K',0}, 10210825, 166 }, /* Cocos (Keeling) Islands */
5239 { 312, {'C','K',0}, {'C','O','K',0}, 26286, 184 }, /* Cook Islands */
5240 { 313, {'X','X',0}, {'X','X',0}, 10210825 }, /* Coral Sea Islands */
5241 { 314, {'X','X',0}, {'X','X',0}, 114 }, /* Diego Garcia */
5242 { 315, {'F','K',0}, {'F','L','K',0}, 31396, 238 }, /* Falkland Islands (Islas Malvinas) */
5243 { 317, {'G','F',0}, {'G','U','F',0}, 31396, 254 }, /* French Guiana */
5244 { 318, {'P','F',0}, {'P','Y','F',0}, 26286, 258 }, /* French Polynesia */
5245 { 319, {'T','F',0}, {'A','T','F',0}, 39070, 260 }, /* French Southern and Antarctic Lands */
5246 { 321, {'G','P',0}, {'G','L','P',0}, 10039880, 312 }, /* Guadeloupe */
5247 { 322, {'G','U',0}, {'G','U','M',0}, 21206, 316 }, /* Guam */
5248 { 323, {'X','X',0}, {'X','X',0}, 39070 }, /* Guantanamo Bay */
5249 { 324, {'G','G',0}, {'G','G','Y',0}, 308, 831 }, /* Guernsey */
5250 { 325, {'H','M',0}, {'H','M','D',0}, 39070, 334 }, /* Heard Island and McDonald Islands */
5251 { 326, {'X','X',0}, {'X','X',0}, 161832256 }, /* Howland Island */
5252 { 327, {'X','X',0}, {'X','X',0}, 161832256 }, /* Jarvis Island */
5253 { 328, {'J','E',0}, {'J','E','Y',0}, 308, 832 }, /* Jersey */
5254 { 329, {'X','X',0}, {'X','X',0}, 161832256 }, /* Kingman Reef */
5255 { 330, {'M','Q',0}, {'M','T','Q',0}, 10039880, 474 }, /* Martinique */
5256 { 331, {'Y','T',0}, {'M','Y','T',0}, 47603, 175 }, /* Mayotte */
5257 { 332, {'M','S',0}, {'M','S','R',0}, 10039880, 500 }, /* Montserrat */
5258 { 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530, LOCATION_BOTH }, /* Netherlands Antilles (Former) */
5259 { 334, {'N','C',0}, {'N','C','L',0}, 20900, 540 }, /* New Caledonia */
5260 { 335, {'N','U',0}, {'N','I','U',0}, 26286, 570 }, /* Niue */
5261 { 336, {'N','F',0}, {'N','F','K',0}, 10210825, 574 }, /* Norfolk Island */
5262 { 337, {'M','P',0}, {'M','N','P',0}, 21206, 580 }, /* Northern Mariana Islands */
5263 { 338, {'X','X',0}, {'X','X',0}, 161832256 }, /* Palmyra Atoll */
5264 { 339, {'P','N',0}, {'P','C','N',0}, 26286, 612 }, /* Pitcairn Islands */
5265 { 340, {'X','X',0}, {'X','X',0}, 337 }, /* Rota Island */
5266 { 341, {'X','X',0}, {'X','X',0}, 337 }, /* Saipan */
5267 { 342, {'G','S',0}, {'S','G','S',0}, 39070, 239 }, /* South Georgia and the South Sandwich Islands */
5268 { 343, {'S','H',0}, {'S','H','N',0}, 42483, 654 }, /* St. Helena */
5269 { 346, {'X','X',0}, {'X','X',0}, 337 }, /* Tinian Island */
5270 { 347, {'T','K',0}, {'T','K','L',0}, 26286, 772 }, /* Tokelau */
5271 { 348, {'X','X',0}, {'X','X',0}, 39070 }, /* Tristan da Cunha */
5272 { 349, {'T','C',0}, {'T','C','A',0}, 10039880, 796 }, /* Turks and Caicos Islands */
5273 { 351, {'V','G',0}, {'V','G','B',0}, 10039880, 92 }, /* Virgin Islands, British */
5274 { 352, {'W','F',0}, {'W','L','F',0}, 26286, 876 }, /* Wallis and Futuna */
5275 { 742, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Africa */
5276 { 2129, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Asia */
5277 { 10541, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Europe */
5278 { 15126, {'I','M',0}, {'I','M','N',0}, 10039882, 833 }, /* Man, Isle of */
5279 { 19618, {'M','K',0}, {'M','K','D',0}, 47610, 807 }, /* Macedonia, Former Yugoslav Republic of */
5280 { 20900, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Melanesia */
5281 { 21206, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Micronesia */
5282 { 21242, {'X','X',0}, {'X','X',0}, 161832256 }, /* Midway Islands */
5283 { 23581, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Northern America */
5284 { 26286, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Polynesia */
5285 { 27082, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Central America */
5286 { 27114, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Oceania */
5287 { 30967, {'S','X',0}, {'S','X','M',0}, 10039880, 534 }, /* Sint Maarten (Dutch part) */
5288 { 31396, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* South America */
5289 { 31706, {'M','F',0}, {'M','A','F',0}, 10039880, 663 }, /* Saint Martin (French part) */
5290 { 39070, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* World */
5291 { 42483, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Western Africa */
5292 { 42484, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Middle Africa */
5293 { 42487, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Northern Africa */
5294 { 47590, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Central Asia */
5295 { 47599, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* South-Eastern Asia */
5296 { 47600, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Eastern Asia */
5297 { 47603, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Eastern Africa */
5298 { 47609, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Eastern Europe */
5299 { 47610, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Southern Europe */
5300 { 47611, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Middle East */
5301 { 47614, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Southern Asia */
5302 { 7299303, {'T','L',0}, {'T','L','S',0}, 47599, 626 }, /* Democratic Republic of Timor-Leste */
5303 { 10026358, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Americas */
5304 { 10028789, {'A','X',0}, {'A','L','A',0}, 10039882, 248 }, /* Åland Islands */
5305 { 10039880, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Caribbean */
5306 { 10039882, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Northern Europe */
5307 { 10039883, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Southern Africa */
5308 { 10210824, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Western Europe */
5309 { 10210825, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Australia and New Zealand */
5310 { 161832015, {'B','L',0}, {'B','L','M',0}, 10039880, 652 }, /* Saint Barthélemy */
5311 { 161832256, {'U','M',0}, {'U','M','I',0}, 27114, 581 }, /* U.S. Minor Outlying Islands */
5312 { 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Latin America and the Caribbean */
5313};
5314
5315#ifdef __REACTOS__
5316/* Callback function ptrs for EnumSystemCodePagesA/W */
5317typedef struct
5318{
5319 CODEPAGE_ENUMPROCA procA;
5320 CODEPAGE_ENUMPROCW procW;
5321 DWORD dwFlags;
5322} ENUMSYSTEMCODEPAGES_CALLBACKS;
5323
5324/* Internal implementation of EnumSystemCodePagesA/W */
5325static BOOL NLS_EnumSystemCodePages(ENUMSYSTEMCODEPAGES_CALLBACKS *lpProcs)
5326{
5327 WCHAR szNumber[5 + 1], szValue[MAX_PATH];
5328 HANDLE hKey;
5329 BOOL bContinue = TRUE;
5330 ULONG ulIndex = 0;
5331
5332 if (!lpProcs)
5333 {
5335 return FALSE;
5336 }
5337
5338 switch (lpProcs->dwFlags)
5339 {
5340 case CP_INSTALLED:
5341 case CP_SUPPORTED:
5342 break;
5343 default:
5345 return FALSE;
5346 }
5347
5348 hKey = NLS_RegOpenKey(0, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
5349 if (!hKey)
5350 {
5351 WARN("NLS_RegOpenKey() failed\n");
5352 return FALSE;
5353 }
5354
5355 while (bContinue)
5356 {
5357 if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber),
5358 szValue, sizeof(szValue)))
5359 {
5360 if ((lpProcs->dwFlags == CP_SUPPORTED)||
5361 ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) > 2)))
5362 {
5363 if (lpProcs->procW)
5364 {
5365 bContinue = lpProcs->procW(szNumber);
5366 }
5367 else
5368 {
5369 char szNumberA[sizeof(szNumber)/sizeof(WCHAR)];
5370
5371 WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0);
5372 bContinue = lpProcs->procA(szNumberA);
5373 }
5374 }
5375
5376 ulIndex++;
5377
5378 } else bContinue = FALSE;
5379
5380 if (!bContinue)
5381 break;
5382 }
5383
5384 if (hKey)
5385 NtClose(hKey);
5386
5387 return TRUE;
5388}
5389
5390/*
5391 * @implemented
5392 */
5393BOOL
5394WINAPI
5396 CODEPAGE_ENUMPROCW lpCodePageEnumProc,
5398 )
5399{
5400 ENUMSYSTEMCODEPAGES_CALLBACKS procs;
5401
5402 TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
5403
5404 procs.procA = NULL;
5405 procs.procW = lpCodePageEnumProc;
5406 procs.dwFlags = dwFlags;
5407
5408 return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
5409}
5410
5411
5412/*
5413 * @implemented
5414 */
5415BOOL
5416WINAPI
5418 CODEPAGE_ENUMPROCA lpCodePageEnumProc,
5420 )
5421{
5422 ENUMSYSTEMCODEPAGES_CALLBACKS procs;
5423
5424 TRACE("(%p,0x%08X)\n", lpCodePageEnumProc, dwFlags);
5425
5426 procs.procA = lpCodePageEnumProc;
5427 procs.procW = NULL;
5428 procs.dwFlags = dwFlags;
5429
5430 return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
5431}
5432
5433
5434static int
5435#ifdef __REACTOS__
5436NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData, LANGID lang)
5437#else
5438NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
5439#endif
5440{
5441 /* FIXME: move *.nls resources out of kernel32 into locale.nls */
5442 Location += NLSRC_OFFSET;
5443 Location &= 0xFFFF;
5444
5445 if (cchData == 0)
5446#ifdef __REACTOS__
5447 return GetLocalisedText(Location, NULL, 0, lang);
5448#else
5449 return GetLocalisedText(Location, NULL, 0);
5450#endif
5451
5452#ifdef __REACTOS__
5453 if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData, lang))
5454#else
5455 if (GetLocalisedText(Location, szFriendlyName, (UINT)cchData))
5456#endif
5457 return strlenW(szFriendlyName) + 1;
5458
5459 return 0;
5460}
5461#endif // __REACTOS__
5462
5463static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
5464{
5465 int min, max;
5466
5467 min = 0;
5468 max = sizeof(geoinfodata)/sizeof(struct geoinfo_t)-1;
5469
5470 while (min <= max) {
5471 const struct geoinfo_t *ptr;
5472 int n = (min+max)/2;
5473
5474 ptr = &geoinfodata[n];
5475 if (geoid == ptr->id)
5476 /* we don't need empty entries */
5477 return *ptr->iso2W ? ptr : NULL;
5478
5479 if (ptr->id > geoid)
5480 max = n-1;
5481 else
5482 min = n+1;
5483 }
5484
5485 return NULL;
5486}
5487
5488/******************************************************************************
5489 * GetGeoInfoW (KERNEL32.@)
5490 */
5491INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
5492{
5493 const struct geoinfo_t *ptr;
5494 const WCHAR *str = NULL;
5495 WCHAR buffW[12];
5496 LONG val = 0;
5497 INT len;
5498
5499 TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
5500
5501 if (!(ptr = get_geoinfo_dataptr(geoid))) {
5503 return 0;
5504 }
5505
5506 switch (geotype) {
5507 case GEO_FRIENDLYNAME:
5508 {
5509#ifdef __REACTOS__
5510 return NLS_GetGeoFriendlyName(geoid, data, data_len, lang);
5511#else
5512 return NLS_GetGeoFriendlyName(geoid, data, data_len);
5513#endif
5514 }
5515 case GEO_NATION:
5516 val = geoid;
5517 break;
5518 case GEO_ISO_UN_NUMBER:
5519 val = ptr->uncode;
5520 break;
5521 case GEO_PARENT:
5522 val = ptr->parent;
5523 break;
5524 case GEO_ISO2:
5525 case GEO_ISO3:
5526 {
5527 str = geotype == GEO_ISO2 ? ptr->iso2W : ptr->iso3W;
5528 break;
5529 }
5530 case GEO_RFC1766:
5531 case GEO_LCID:
5532 case GEO_OFFICIALNAME:
5533 case GEO_TIMEZONES:
5535 case GEO_LATITUDE:
5536 case GEO_LONGITUDE:
5537 FIXME("type %d is not supported\n", geotype);
5539 return 0;
5540 default:
5541 WARN("unrecognized type %d\n", geotype);
5543 return 0;
5544 }
5545
5546 if (val) {
5547 static const WCHAR fmtW[] = {'%','d',0};
5548 sprintfW(buffW, fmtW, val);
5549 str = buffW;
5550 }
5551
5552 len = strlenW(str) + 1;
5553 if (!data || !data_len)
5554 return len;
5555
5556 memcpy(data, str, min(len, data_len)*sizeof(WCHAR));
5557 if (data_len < len)
5559 return data_len < len ? 0 : len;
5560}
5561
5562/******************************************************************************
5563 * GetGeoInfoA (KERNEL32.@)
5564 */
5565INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
5566{
5567 WCHAR *buffW;
5568 INT len;
5569
5570 TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
5571
5572 len = GetGeoInfoW(geoid, geotype, NULL, 0, lang);
5573 if (!len)
5574 return 0;
5575
5576 buffW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
5577 if (!buffW)
5578 return 0;
5579
5580 GetGeoInfoW(geoid, geotype, buffW, len, lang);
5581 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, NULL, 0, NULL, NULL);
5582 if (!data || !data_len) {
5583 HeapFree(GetProcessHeap(), 0, buffW);
5584 return len;
5585 }
5586
5587 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, data, data_len, NULL, NULL);
5588 HeapFree(GetProcessHeap(), 0, buffW);
5589
5590 if (data_len < len)
5592 return data_len < len ? 0 : len;
5593}
5594
5595/******************************************************************************
5596 * EnumSystemGeoID (KERNEL32.@)
5597 *
5598 * Call a users function for every location available on the system.
5599 *
5600 * PARAMS
5601 * geoclass [I] Type of information desired (SYSGEOTYPE enum from "winnls.h")
5602 * parent [I] GEOID for the parent
5603 * enumproc [I] Callback function to call for each location
5604 *
5605 * RETURNS
5606 * Success: TRUE.
5607 * Failure: FALSE. Use GetLastError() to determine the cause.
5608 */
5610{
5611 INT i;
5612
5613 TRACE("(%d, %d, %p)\n", geoclass, parent, enumproc);
5614
5615 if (!enumproc) {
5617 return FALSE;
5618 }
5619
5620 if (geoclass != GEOCLASS_NATION && geoclass != GEOCLASS_REGION) {
5622 return FALSE;
5623 }
5624
5625 for (i = 0; i < sizeof(geoinfodata)/sizeof(struct geoinfo_t); i++) {
5626 const struct geoinfo_t *ptr = &geoinfodata[i];
5627
5628 if (geoclass == GEOCLASS_NATION && (ptr->kind == LOCATION_REGION))
5629 continue;
5630
5631 if (geoclass == GEOCLASS_REGION && (ptr->kind == LOCATION_NATION))
5632 continue;
5633
5634 if (parent && ptr->parent != parent)
5635 continue;
5636
5637 if (!enumproc(ptr->id))
5638 return TRUE;
5639 }
5640
5641 return TRUE;
5642}
5643
5644#ifndef __REACTOS__
5645INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
5646{
5647 LCID userlcid;
5648
5649 TRACE("%p, %d\n", localename, buffersize);
5650
5651 userlcid = GetUserDefaultLCID();
5652 return LCIDToLocaleName(userlcid, localename, buffersize, 0);
5653}
5654
5655/******************************************************************************
5656 * NormalizeString (KERNEL32.@)
5657 */
5658INT WINAPI NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, INT cwSrcLength,
5659 LPWSTR lpDstString, INT cwDstLength)
5660{
5661 FIXME("%x %p %d %p %d\n", NormForm, lpSrcString, cwSrcLength, lpDstString, cwDstLength);
5663 return 0;
5664}
5665
5666/******************************************************************************
5667 * IsNormalizedString (KERNEL32.@)
5668 */
5669BOOL WINAPI IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpString, INT cwLength)
5670{
5671 FIXME("%x %p %d\n", NormForm, lpString, cwLength);
5673 return FALSE;
5674}
5675
5676enum {
5677 BASE = 36,
5678 TMIN = 1,
5679 TMAX = 26,
5680 SKEW = 38,
5681 DAMP = 700,
5683 INIT_N = 128
5685
5686static inline INT adapt(INT delta, INT numpoints, BOOL firsttime)
5687{
5688 INT k;
5689
5690 delta /= (firsttime ? DAMP : 2);
5691 delta += delta/numpoints;
5692
5693 for(k=0; delta>((BASE-TMIN)*TMAX)/2; k+=BASE)
5694 delta /= BASE-TMIN;
5695 return k+((BASE-TMIN+1)*delta)/(delta+SKEW);
5696}
5697
5698/******************************************************************************
5699 * IdnToAscii (KERNEL32.@)
5700 * Implementation of Punycode based on RFC 3492.
5701 */
5702INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar,
5703 LPWSTR lpASCIICharStr, INT cchASCIIChar)
5704{
5705 static const WCHAR prefixW[] = {'x','n','-','-'};
5706
5707 WCHAR *norm_str;
5708 INT i, label_start, label_end, norm_len, out_label, out = 0;
5709
5710 TRACE("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
5711 lpASCIICharStr, cchASCIIChar);
5712
5713 norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr, cchUnicodeChar, NULL, 0);
5714 if(!norm_len)
5715 return 0;
5716 norm_str = HeapAlloc(GetProcessHeap(), 0, norm_len*sizeof(WCHAR));
5717 if(!norm_str) {
5719 return 0;
5720 }
5721 norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr,
5722 cchUnicodeChar, norm_str, norm_len);
5723 if(!norm_len) {
5724 HeapFree(GetProcessHeap(), 0, norm_str);
5725 return 0;
5726 }
5727
5728 for(label_start=0; label_start<norm_len;) {
5729 INT n = INIT_N, bias = INIT_BIAS;
5730 INT delta = 0, b = 0, h;
5731
5732 out_label = out;
5733 for(i=label_start; i<norm_len && norm_str[i]!='.' &&
5734 norm_str[i]!=0x3002 && norm_str[i]!='\0'; i++)
5735 if(norm_str[i] < 0x80)
5736 b++;
5737 label_end = i;
5738
5739 if(b == label_end-label_start) {
5740 if(label_end < norm_len)
5741 b++;
5742 if(!lpASCIICharStr) {
5743 out += b;
5744 }else if(out+b <= cchASCIIChar) {
5745 memcpy(lpASCIICharStr+out, norm_str+label_start, b*sizeof(WCHAR));
5746 out += b;
5747 }else {
5748 HeapFree(GetProcessHeap(), 0, norm_str);
5750 return 0;
5751 }
5752 label_start = label_end+1;
5753 continue;
5754 }
5755
5756 if(!lpASCIICharStr) {
5757 out += 5+b; /* strlen(xn--...-) */
5758 }else if(out+5+b <= cchASCIIChar) {
5759 memcpy(lpASCIICharStr+out, prefixW, sizeof(prefixW));
5760 out += 4;
5761 for(i=label_start; i<label_end; i++)
5762 if(norm_str[i] < 0x80)
5763 lpASCIICharStr[out++] = norm_str[i];
5764 lpASCIICharStr[out++] = '-';
5765 }else {
5766 HeapFree(GetProcessHeap(), 0, norm_str);
5768 return 0;
5769 }
5770 if(!b)
5771 out--;
5772
5773 for(h=b; h<label_end-label_start;) {
5774 INT m = 0xffff, q, k;
5775
5776 for(i=label_start; i<label_end; i++) {
5777 if(norm_str[i]>=n && m>norm_str[i])
5778 m = norm_str[i];
5779 }
5780 delta += (m-n)*(h+1);
5781 n = m;
5782
5783 for(i=label_start; i<label_end; i++) {
5784 if(norm_str[i] < n) {
5785 delta++;
5786 }else if(norm_str[i] == n) {
5787 for(q=delta, k=BASE; ; k+=BASE) {
5788 INT t = k<=bias ? TMIN : k>=bias+TMAX ? TMAX : k-bias;
5789 INT disp = q<t ? q : t+(q-t)%(BASE-t);
5790 if(!lpASCIICharStr) {
5791 out++;
5792 }else if(out+1 <= cchASCIIChar) {
5793 lpASCIICharStr[out++] = disp<='z'-'a' ?
5794 'a'+disp : '0'+disp-'z'+'a'-1;
5795 }else {
5796 HeapFree(GetProcessHeap(), 0, norm_str);
5798 return 0;
5799 }
5800 if(q < t)
5801 break;
5802 q = (q-t)/(BASE-t);
5803 }
5804 bias = adapt(delta, h+1, h==b);
5805 delta = 0;
5806 h++;
5807 }
5808 }
5809 delta++;
5810 n++;
5811 }
5812
5813 if(out-out_label > 63) {
5814 HeapFree(GetProcessHeap(), 0, norm_str);
5816 return 0;
5817 }
5818
5819 if(label_end < norm_len) {
5820 if(!lpASCIICharStr) {
5821 out++;
5822 }else if(out+1 <= cchASCIIChar) {
5823 lpASCIICharStr[out++] = norm_str[label_end] ? '.' : 0;
5824 }else {
5825 HeapFree(GetProcessHeap(), 0, norm_str);
5827 return 0;
5828 }
5829 }
5830 label_start = label_end+1;
5831 }
5832
5833 HeapFree(GetProcessHeap(), 0, norm_str);
5834 return out;
5835}
5836
5837/******************************************************************************
5838 * IdnToNameprepUnicode (KERNEL32.@)
5839 */
5840INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar,
5841 LPWSTR lpNameprepCharStr, INT cchNameprepChar)
5842{
5843 enum {
5844 UNASSIGNED = 0x1,
5845 PROHIBITED = 0x2,
5846 BIDI_RAL = 0x4,
5847 BIDI_L = 0x8
5848 };
5849
5850 extern const unsigned short nameprep_char_type[] DECLSPEC_HIDDEN;
5851 extern const WCHAR nameprep_mapping[] DECLSPEC_HIDDEN;
5852 const WCHAR *ptr;
5853 WORD flags;
5854 WCHAR buf[64], *map_str, norm_str[64], ch;
5855 DWORD i, map_len, norm_len, mask, label_start, label_end, out = 0;
5856 BOOL have_bidi_ral, prohibit_bidi_ral, ascii_only;
5857
5858 TRACE("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
5859 lpNameprepCharStr, cchNameprepChar);
5860
5861 if(dwFlags & ~(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES)) {
5863 return 0;
5864 }
5865
5866 if(!lpUnicodeCharStr || cchUnicodeChar<-1) {
5868 return 0;
5869 }
5870
5871 if(cchUnicodeChar == -1)
5872 cchUnicodeChar = strlenW(lpUnicodeCharStr)+1;
5873 if(!cchUnicodeChar || (cchUnicodeChar==1 && lpUnicodeCharStr[0]==0)) {
5875 return 0;
5876 }
5877
5878 for(label_start=0; label_start<cchUnicodeChar;) {
5879 ascii_only = TRUE;
5880 for(i=label_start; i<cchUnicodeChar; i++) {
5881 ch = lpUnicodeCharStr[i];
5882
5883 if(i!=cchUnicodeChar-1 && !ch) {
5885 return 0;
5886 }
5887 /* check if ch is one of label separators defined in RFC3490 */
5888 if(!ch || ch=='.' || ch==0x3002 || ch==0xff0e || ch==0xff61)
5889 break;
5890
5891 if(ch > 0x7f) {
5892 ascii_only = FALSE;
5893 continue;
5894 }
5895
5896 if((dwFlags&IDN_USE_STD3_ASCII_RULES) == 0)
5897 continue;
5898 if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z')
5899 || (ch>='0' && ch<='9') || ch=='-')
5900 continue;
5901
5903 return 0;
5904 }
5905 label_end = i;
5906 /* last label may be empty */
5907 if(label_start==label_end && ch) {
5909 return 0;
5910 }
5911
5912 if((dwFlags&IDN_USE_STD3_ASCII_RULES) && (lpUnicodeCharStr[label_start]=='-' ||
5913 lpUnicodeCharStr[label_end-1]=='-')) {
5915 return 0;
5916 }
5917
5918 if(ascii_only) {
5919 /* maximal label length is 63 characters */
5920 if(label_end-label_start > 63) {
5922 return 0;
5923 }
5924 if(label_end < cchUnicodeChar)
5925 label_end++;
5926
5927 if(!lpNameprepCharStr) {
5928 out += label_end-label_start;
5929 }else if(out+label_end-label_start <= cchNameprepChar) {
5930 memcpy(lpNameprepCharStr+out, lpUnicodeCharStr+label_start,
5931 (label_end-label_start)*sizeof(WCHAR));
5932 if(lpUnicodeCharStr[label_end-1] > 0x7f)
5933 lpNameprepCharStr[out+label_end-label_start-1] = '.';
5934 out += label_end-label_start;
5935 }else {
5937 return 0;
5938 }
5939
5940 label_start = label_end;
5941 continue;
5942 }
5943
5944 map_len = 0;
5945 for(i=label_start; i<label_end; i++) {
5946 ch = lpUnicodeCharStr[i];
5948 ptr = nameprep_mapping + ptr[(ch>>4)&0x0f] + 3*(ch&0x0f);
5949
5950 if(!ptr[0]) map_len++;
5951 else if(!ptr[1]) map_len++;
5952 else if(!ptr[2]) map_len += 2;
5953 else if(ptr[0]!=0xffff || ptr[1]!=0xffff || ptr[2]!=0xffff) map_len += 3;
5954 }
5955 if(map_len*sizeof(WCHAR) > sizeof(buf)) {
5956 map_str = HeapAlloc(GetProcessHeap(), 0, map_len*sizeof(WCHAR));
5957 if(!map_str) {
5959 return 0;
5960 }
5961 }else {
5962 map_str = buf;
5963 }
5964 map_len = 0;
5965 for(i=label_start; i<label_end; i++) {
5966 ch = lpUnicodeCharStr[i];
5968 ptr = nameprep_mapping + ptr[(ch>>4)&0x0f] + 3*(ch&0x0f);
5969
5970 if(!ptr[0]) {
5971 map_str[map_len++] = ch;
5972 }else if(!ptr[1]) {
5973 map_str[map_len++] = ptr[0];
5974 }else if(!ptr[2]) {
5975 map_str[map_len++] = ptr[0];
5976 map_str[map_len++] = ptr[1];
5977 }else if(ptr[0]!=0xffff || ptr[1]!=0xffff || ptr[2]!=0xffff) {
5978 map_str[map_len++] = ptr[0];
5979 map_str[map_len++] = ptr[1];
5980 map_str[map_len++] = ptr[2];
5981 }
5982 }
5983
5984 norm_len = FoldStringW(MAP_FOLDCZONE, map_str, map_len,
5985 norm_str, sizeof(norm_str)/sizeof(WCHAR)-1);
5986 if(map_str != buf)
5987 HeapFree(GetProcessHeap(), 0, map_str);
5988 if(!norm_len) {
5991 return 0;
5992 }
5993
5994 if(label_end < cchUnicodeChar) {
5995 norm_str[norm_len++] = lpUnicodeCharStr[label_end] ? '.' : 0;
5996 label_end++;
5997 }
5998
5999 if(!lpNameprepCharStr) {
6000 out += norm_len;
6001 }else if(out+norm_len <= cchNameprepChar) {
6002 memcpy(lpNameprepCharStr+out, norm_str, norm_len*sizeof(WCHAR));
6003 out += norm_len;
6004 }else {
6006 return 0;
6007 }
6008
6009 have_bidi_ral = prohibit_bidi_ral = FALSE;
6010 mask = PROHIBITED;
6011 if((dwFlags&IDN_ALLOW_UNASSIGNED) == 0)
6012 mask |= UNASSIGNED;
6013 for(i=0; i<norm_len; i++) {
6014 ch = norm_str[i];
6016
6017 if(flags & mask) {
6018 SetLastError((flags & PROHIBITED) ? ERROR_INVALID_NAME
6020 return 0;
6021 }
6022
6023 if(flags & BIDI_RAL)
6024 have_bidi_ral = TRUE;
6025 if(flags & BIDI_L)
6026 prohibit_bidi_ral = TRUE;
6027 }
6028
6029 if(have_bidi_ral) {
6030 ch = norm_str[0];
6032 if((flags & BIDI_RAL) == 0)
6033 prohibit_bidi_ral = TRUE;
6034
6035 ch = norm_str[norm_len-1];
6037 if((flags & BIDI_RAL) == 0)
6038 prohibit_bidi_ral = TRUE;
6039 }
6040
6041 if(have_bidi_ral && prohibit_bidi_ral) {
6043 return 0;
6044 }
6045
6046 label_start = label_end;
6047 }
6048
6049 return out;
6050}
6051
6052/******************************************************************************
6053 * IdnToUnicode (KERNEL32.@)
6054 */
6055INT WINAPI IdnToUnicode(DWORD dwFlags, LPCWSTR lpASCIICharStr, INT cchASCIIChar,
6056 LPWSTR lpUnicodeCharStr, INT cchUnicodeChar)
6057{
6058 extern const unsigned short nameprep_char_type[];
6059
6060 INT i, label_start, label_end, out_label, out = 0;
6061 WCHAR ch;
6062
6063 TRACE("%x %p %d %p %d\n", dwFlags, lpASCIICharStr, cchASCIIChar,
6064 lpUnicodeCharStr, cchUnicodeChar);
6065
6066 for(label_start=0; label_start<cchASCIIChar;) {
6067 INT n = INIT_N, pos = 0, old_pos, w, k, bias = INIT_BIAS, delim=0, digit, t;
6068
6069 out_label = out;
6070 for(i=label_start; i<cchASCIIChar; i++) {
6071 ch = lpASCIICharStr[i];
6072
6073 if(ch>0x7f || (i!=cchASCIIChar-1 && !ch)) {
6075 return 0;
6076 }
6077
6078 if(!ch || ch=='.')
6079 break;
6080 if(ch == '-')
6081 delim = i;
6082
6083 if((dwFlags&IDN_USE_STD3_ASCII_RULES) == 0)
6084 continue;
6085 if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z')
6086 || (ch>='0' && ch<='9') || ch=='-')
6087 continue;
6088
6090 return 0;
6091 }
6092 label_end = i;
6093 /* last label may be empty */
6094 if(label_start==label_end && ch) {
6096 return 0;
6097 }
6098
6099 if((dwFlags&IDN_USE_STD3_ASCII_RULES) && (lpASCIICharStr[label_start]=='-' ||
6100 lpASCIICharStr[label_end-1]=='-')) {
6102 return 0;
6103 }
6104 if(label_end-label_start > 63) {
6106 return 0;
6107 }
6108
6109 if(label_end-label_start<4 ||
6110 tolowerW(lpASCIICharStr[label_start])!='x' ||
6111 tolowerW(lpASCIICharStr[label_start+1])!='n' ||
6112 lpASCIICharStr[label_start+2]!='-' || lpASCIICharStr[label_start+3]!='-') {
6113 if(label_end < cchASCIIChar)
6114 label_end++;
6115
6116 if(!lpUnicodeCharStr) {
6117 out += label_end-label_start;
6118 }else if(out+label_end-label_start <= cchUnicodeChar) {
6119 memcpy(lpUnicodeCharStr+out, lpASCIICharStr+label_start,
6120 (label_end-label_start)*sizeof(WCHAR));
6121 out += label_end-label_start;
6122 }else {
6124 return 0;
6125 }
6126
6127 label_start = label_end;
6128 continue;
6129 }
6130
6131 if(delim == label_start+3)
6132 delim++;
6133 if(!lpUnicodeCharStr) {
6134 out += delim-label_start-4;
6135 }else if(out+delim-label_start-4 <= cchUnicodeChar) {
6136 memcpy(lpUnicodeCharStr+out, lpASCIICharStr+label_start+4,
6137 (delim-label_start-4)*sizeof(WCHAR));
6138 out += delim-label_start-4;
6139 }else {
6141 return 0;
6142 }
6143 if(out != out_label)
6144 delim++;
6145
6146 for(i=delim; i<label_end;) {
6147 old_pos = pos;
6148 w = 1;
6149 for(k=BASE; ; k+=BASE) {
6150 ch = i<label_end ? tolowerW(lpASCIICharStr[i++]) : 0;
6151 if((ch<'a' || ch>'z') && (ch<'0' || ch>'9')) {
6153 return 0;
6154 }
6155 digit = ch<='9' ? ch-'0'+'z'-'a'+1 : ch-'a';
6156 pos += digit*w;
6157 t = k<=bias ? TMIN : k>=bias+TMAX ? TMAX : k-bias;
6158 if(digit < t)
6159 break;
6160 w *= BASE-t;
6161 }
6162 bias = adapt(pos-old_pos, out-out_label+1, old_pos==0);
6163 n += pos/(out-out_label+1);
6164 pos %= out-out_label+1;
6165
6166 if((dwFlags&IDN_ALLOW_UNASSIGNED)==0 &&
6167 get_table_entry(nameprep_char_type, n)==1/*UNASSIGNED*/) {
6169 return 0;
6170 }
6171 if(!lpUnicodeCharStr) {
6172 out++;
6173 }else if(out+1 <= cchASCIIChar) {
6174 memmove(lpUnicodeCharStr+out_label+pos+1,
6175 lpUnicodeCharStr+out_label+pos,
6176 (out-out_label-pos)*sizeof(WCHAR));
6177 lpUnicodeCharStr[out_label+pos] = n;
6178 out++;
6179 }else {
6181 return 0;
6182 }
6183 pos++;
6184 }
6185
6186 if(out-out_label > 63) {
6188 return 0;
6189 }
6190
6191 if(label_end < cchASCIIChar) {
6192 if(!lpUnicodeCharStr) {
6193 out++;
6194 }else if(out+1 <= cchUnicodeChar) {
6195 lpUnicodeCharStr[out++] = lpASCIICharStr[label_end];
6196 }else {
6198 return 0;
6199 }
6200 }
6201 label_start = label_end+1;
6202 }
6203
6204 return out;
6205}
6206
6207
6208/******************************************************************************
6209 * GetFileMUIPath (KERNEL32.@)
6210 */
6211
6212BOOL WINAPI GetFileMUIPath(DWORD flags, PCWSTR filepath, PWSTR language, PULONG languagelen,
6213 PWSTR muipath, PULONG muipathlen, PULONGLONG enumerator)
6214{
6215 FIXME("stub: 0x%x, %s, %s, %p, %p, %p, %p\n", flags, debugstr_w(filepath),
6216 debugstr_w(language), languagelen, muipath, muipathlen, enumerator);
6217
6219
6220 return FALSE;
6221}
6222
6223/******************************************************************************
6224 * GetFileMUIInfo (KERNEL32.@)
6225 */
6226
6228{
6229 FIXME("stub: %u, %s, %p, %p\n", flags, debugstr_w(path), info, size);
6230
6232 return FALSE;
6233}
6234
6235/******************************************************************************
6236 * ResolveLocaleName (KERNEL32.@)
6237 */
6238
6240{
6241 FIXME("stub: %s, %p, %d\n", wine_dbgstr_w(name), localename, len);
6242
6244 return 0;
6245}
6246#endif // !__REACTOS__
WCHAR lpszDest[260]
@ lparam
Definition: SystemMenu.c:31
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static int used
Definition: adh-main.c:39
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:46
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
static WCHAR * get_locale(void)
Definition: builtin.c:3937
CFF_Charset charset
Definition: cffcmap.c:138
Definition: _locale.h:75
LPARAM lParam
Definition: combotst.c:139
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
HMODULE hModule
Definition: animate.c:44
#define CDECL
Definition: compat.h:29
#define CP_UNIXCP
Definition: compat.h:79
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_INVALID_NAME
Definition: compat.h:103
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
static const WCHAR valueW[]
Definition: object.c:48
BOOL WINAPI WriteProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string)
Definition: profile.c:1287
BOOL WINAPI FreeResource(HGLOBAL handle)
Definition: res.c:559
BOOL WINAPI EnumResourceLanguagesA(HMODULE hmod, LPCSTR type, LPCSTR name, ENUMRESLANGPROCA lpfun, LONG_PTR lparam)
Definition: res.c:428
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HRSRC WINAPI FindResourceExW(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang)
Definition: res.c:164
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
BOOL WINAPI EnumResourceLanguagesW(HMODULE hmod, LPCWSTR type, LPCWSTR name, ENUMRESLANGPROCW lpfun, LONG_PTR lparam)
Definition: res.c:480
GEOID WINAPI GetUserGeoID(GEOCLASS GeoClass)
Definition: locale.c:4837
#define LOCALE_NAME_USER_DEFAULT
Definition: locale.c:42
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2800
BOOL WINAPI SetThreadLocale(LCID lcid)
Definition: locale.c:2819
static const WCHAR iLZeroW[]
Definition: locale.c:179
locationkind
Definition: locale.c:4998
@ LOCATION_REGION
Definition: locale.c:5000
@ LOCATION_BOTH
Definition: locale.c:5001
@ LOCATION_NATION
Definition: locale.c:4999
static const WCHAR sLanguageW[]
Definition: locale.c:194
static const WCHAR iDateW[]
Definition: locale.c:174
static LANGID get_default_sublang(LANGID lang)
Definition: locale.c:366
static const WCHAR iMeasureW[]
Definition: locale.c:180
static void strcpynAtoW(WCHAR *dst, const char *src, size_t n)
Definition: locale.c:266
static BOOL NLS_EnumSystemLanguageGroups(ENUMLANGUAGEGROUP_CALLBACKS *lpProcs)
Definition: locale.c:4476
static INT adapt(INT delta, INT numpoints, BOOL firsttime)
Definition: locale.c:5686
static const WCHAR sLongDateW[]
Definition: locale.c:196
BOOL WINAPI EnumSystemLocalesW(LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2998
static BOOL CALLBACK enum_lang_proc_w(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD LangID, LONG_PTR lParam)
Definition: locale.c:2960
static const struct geoinfo_t geoinfodata[]
Definition: locale.c:5013
LANGID WINAPI SetThreadUILanguage(LANGID langid)
Definition: locale.c:2854
#define WC_FLAGSMASK
Definition: locale.c:60
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen)
Definition: locale.c:3830
static BOOL utf7_can_directly_encode(WCHAR codepoint)
Definition: locale.c:2550
BOOL WINAPI GetFileMUIInfo(DWORD flags, PCWSTR path, FILEMUIINFO *info, DWORD *size)
Definition: locale.c:6227
static struct registry_value * get_locale_registry_value(DWORD lctype)
Definition: locale.c:1451
static const union cptable * unix_cptable
Definition: locale.c:67
INT WINAPI ResolveLocaleName(LPCWSTR name, LPWSTR localename, INT len)
Definition: locale.c:6239
static const WCHAR iDigitsW[]
Definition: locale.c:175
#define NLSRC_OFFSET
Definition: locale.c:53
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2123
UINT WINAPI GetACP(void)
Definition: locale.c:2020
static const WCHAR iFirstDayOfWeekW[]
Definition: locale.c:176
static UINT get_lcid_codepage(LCID lcid)
Definition: locale.c:287
static const WCHAR sMonDecimalSepW[]
Definition: locale.c:197
static const WCHAR sNegativeSignW[]
Definition: locale.c:201
@ INIT_N
Definition: locale.c:5683
@ DAMP
Definition: locale.c:5681
@ SKEW
Definition: locale.c:5680
@ BASE
Definition: locale.c:5677
@ TMIN
Definition: locale.c:5678
@ TMAX
Definition: locale.c:5679
@ INIT_BIAS
Definition: locale.c:5682
static LCID lcid_LC_MONETARY
Definition: locale.c:163
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3208
static BOOL CALLBACK enum_lang_proc_a(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LONG_PTR lParam)
Definition: locale.c:2950
BOOL WINAPI EnumSystemLanguageGroupsW(LANGUAGEGROUP_ENUMPROCW pLangGrpEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4595
static INT get_registry_locale_info(struct registry_value *registry_value, LPWSTR buffer, INT len)
Definition: locale.c:1467
static LCID convert_default_lcid(LCID lcid, LCTYPE lctype)
Definition: locale.c:586
static const WCHAR szLocaleKeyName[]
Definition: locale.c:69
static const WCHAR sThousandW[]
Definition: locale.c:204
BOOL WINAPI IsValidLanguageGroup(LGRPID lgrpid, DWORD dwFlags)
Definition: locale.c:4623
BOOL WINAPI EnumSystemCodePagesW(CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags)
Definition: locale.c:2294
static BOOL CALLBACK enum_locale_ex_proc(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang, LONG_PTR lparam)
Definition: locale.c:3015
static const WCHAR iFirstWeekOfYearW[]
Definition: locale.c:177
BOOL WINAPI EnumSystemCodePagesA(CODEPAGE_ENUMPROCA lpfnCodePageEnum, DWORD flags)
Definition: locale.c:2273
static const WCHAR szLangGroupsKeyName[]
Definition: locale.c:75
static BOOL utf7_write_c(char *dst, int dstlen, int *index, char character)
Definition: locale.c:2575
static BOOL is_genitive_name_supported(LCTYPE lctype)
Definition: locale.c:737
UINT GetLocalisedText(IN UINT uID, IN LPWSTR lpszDest, IN UINT cchDest)
BOOL WINAPI GetFileMUIPath(DWORD flags, PCWSTR filepath, PWSTR language, PULONG languagelen, PWSTR muipath, PULONG muipathlen, PULONGLONG enumerator)
Definition: locale.c:6212
void LOCALE_InitRegistry(void)
Definition: locale.c:837
INT WINAPI FoldStringA(DWORD dwFlags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen)
Definition: locale.c:3920
#define LOCALE_LOCALEINFOFLAGSMASK
Definition: locale.c:57
INT WINAPI NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, INT cwSrcLength, LPWSTR lpDstString, INT cwDstLength)
Definition: locale.c:5658
static LCID lcid_LC_TIME
Definition: locale.c:165
static const WCHAR sMonGroupingW[]
Definition: locale.c:198
static const WCHAR sTimeW[]
Definition: locale.c:206
static RTL_CRITICAL_SECTION cache_section
Definition: locale.c:262
LANGID WINAPI GetSystemDefaultLangID(void)
Definition: locale.c:1193
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2078
static BOOL get_dummy_preferred_ui_language(DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size)
Definition: locale.c:1246
static BOOL NLS_EnumLanguageGroupLocales(ENUMLANGUAGEGROUPLOCALE_CALLBACKS *lpProcs)
Definition: locale.c:4672
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4082
INT WINAPI IdnToUnicode(DWORD dwFlags, LPCWSTR lpASCIICharStr, INT cchASCIIChar, LPWSTR lpUnicodeCharStr, INT cchUnicodeChar)
Definition: locale.c:6055
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
Definition: sortkey.c:33
static const WCHAR iPaperSizeW[]
Definition: locale.c:183
static const WCHAR iCurrencyW[]
Definition: locale.c:173
static const WCHAR iCountryW[]
Definition: locale.c:171
static LCID lcid_LC_NUMERIC
Definition: locale.c:164
static const struct geoinfo_t * get_geoinfo_dataptr(GEOID geoid)
Definition: locale.c:5463
static const WCHAR s2359W[]
Definition: locale.c:188
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4013
int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: fold.c:118
void LOCALE_Init(void)
Definition: locale.c:4278
BOOL WINAPI SetUserGeoID(GEOID GeoID)
Definition: locale.c:4874
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: locale.c:1374
static const WCHAR s1159W[]
Definition: locale.c:187
BOOL WINAPI GetStringTypeExA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3255
static const WCHAR NumShapeW[]
Definition: locale.c:208
static const WCHAR sCurrencyW[]
Definition: locale.c:190
DWORD WINAPI VerLanguageNameW(DWORD wLang, LPWSTR szLang, DWORD nSize)
Definition: locale.c:3083
static const WCHAR iNegNumberW[]
Definition: locale.c:182
static int utf7_wcstombs(const WCHAR *src, int srclen, char *dst, int dstlen)
Definition: locale.c:2599
static BOOL utf7_write_w(WCHAR *dst, int dstlen, int *index, WCHAR character)
Definition: locale.c:2325
static const WCHAR iCalendarTypeW[]
Definition: locale.c:170
BOOL WINAPI GetSystemPreferredUILanguages(DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size)
Definition: locale.c:1295
static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex, LPWSTR szValueName, ULONG valueNameSize, LPWSTR szValueData, ULONG valueDataSize)
Definition: locale.c:4377
static BOOL NLS_GetLanguageGroupName(LGRPID lgrpid, LPWSTR szName, ULONG nameSize)
Definition: locale.c:4426
static const WCHAR iTLZeroW[]
Definition: locale.c:184
static const WCHAR iLDateW[]
Definition: locale.c:178
BOOL WINAPI GetCPInfoExW(UINT codepage, DWORD dwFlags, LPCPINFOEXW cpinfo)
Definition: locale.c:2219
static LCID lcid_LC_COLLATE
Definition: locale.c:160
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1599
BOOL WINAPI GetCPInfo(UINT codepage, LPCPINFO cpinfo)
Definition: locale.c:2143
static const union cptable * get_codepage_table(unsigned int codepage)
Definition: locale.c:301
#define MB_FLAGSMASK
Definition: locale.c:59
static int get_value_base_by_lctype(LCTYPE lctype)
Definition: locale.c:1655
static const WCHAR iCurrDigitsW[]
Definition: locale.c:172
static struct registry_value registry_values[]
static const WCHAR sCountryW[]
Definition: locale.c:189
static BOOL CALLBACK enum_uilang_proc_a(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LONG_PTR lParam)
Definition: locale.c:4920
INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
Definition: locale.c:5491
BOOL WINAPI IsValidLocaleName(LPCWSTR locale)
Definition: locale.c:2933
INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpASCIICharStr, INT cchASCIIChar)
Definition: locale.c:5702
BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4972
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4194
static int utf7_mbstowcs(const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2349
static const WCHAR sGroupingW[]
Definition: locale.c:193
BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2983
static const WCHAR sTimeFormatW[]
Definition: locale.c:205
static LCID lcid_LC_CTYPE
Definition: locale.c:161
static HANDLE create_registry_key(void)
Definition: locale.c:765
DWORD WINAPI VerLanguageNameA(DWORD wLang, LPSTR szLang, DWORD nSize)
Definition: locale.c:3072
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4261
INT WINAPI LCMapStringEx(LPCWSTR locale, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM handle)
Definition: locale.c:3742
static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal)
Definition: locale.c:4405
LANGID WINAPI GetSystemDefaultUILanguage(void)
Definition: locale.c:1394
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4223
static LCID lcid_LC_MEASUREMENT
Definition: locale.c:167
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3094
UINT WINAPI SetCPGlobal(UINT acp)
Definition: locale.c:2038
static const WCHAR iTimePrefixW[]
Definition: locale.c:185
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: locale.c:2922
INT WINAPI GetSystemDefaultLocaleName(LPWSTR localename, INT len)
Definition: locale.c:1240
BOOL WINAPI IsDBCSLeadByteEx(UINT codepage, BYTE testchar)
Definition: locale.c:2103
INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3978
BOOL WINAPI GetThreadPreferredUILanguages(DWORD flags, ULONG *count, WCHAR *buf, ULONG *size)
Definition: locale.c:1328
static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
Definition: locale.c:4352
static const WCHAR sShortDateW[]
Definition: locale.c:203
LCID WINAPI GetUserDefaultLCID(void)
Definition: locale.c:1210
static UINT setup_unix_locales(void)
Definition: locale.c:1110
INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lParam)
Definition: locale.c:4022
int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2)
Definition: sortkey.c:358
static const WCHAR sMonThousandSepW[]
Definition: locale.c:199
BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc, LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4795
static LCID lcid_LC_TELEPHONE
Definition: locale.c:168
static unsigned short get_table_entry(const unsigned short *table, WCHAR ch)
Definition: locale.c:276
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1176
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1229
static const WCHAR iNegCurrW[]
Definition: locale.c:181
static BOOL locale_update_registry(HKEY hkey, const WCHAR *name, LCID lcid, const LCTYPE *values, UINT nb_values)
Definition: locale.c:798
BOOL WINAPI EnumUILanguagesA(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4944
BOOL WINAPI GetStringTypeExW(LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3184
BOOL WINAPI IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpString, INT cwLength)
Definition: locale.c:5669
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3804
BOOL WINAPI SetThreadPreferredUILanguages(DWORD flags, PCZZWSTR buffer, PULONG count)
Definition: locale.c:1319
BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumproc)
Definition: locale.c:5609
BOOL WINAPI GetCPInfoExA(UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo)
Definition: locale.c:2201
static const union cptable * oem_cptable
Definition: locale.c:65
BOOL WINAPI InvalidateNLSCache(void)
Definition: locale.c:4823
static BOOL CALLBACK enum_uilang_proc_w(HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD LangID, LONG_PTR lParam)
Definition: locale.c:4930
static const WCHAR sDateW[]
Definition: locale.c:191
BOOL WINAPI EnumLanguageGroupLocalesA(LANGGROUPLOCALE_ENUMPROCA pLangGrpLcEnumProc, LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4774
static const WCHAR sPositiveSignW[]
Definition: locale.c:202
#define GET_UNIX_LOCALE(cat)
static const WCHAR sListW[]
Definition: locale.c:195
BOOL WINAPI EnumSystemLanguageGroupsA(LANGUAGEGROUP_ENUMPROCA pLangGrpEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4575
UINT WINAPI GetOEMCP(void)
Definition: locale.c:2059
HMODULE kernel32_handle
Definition: dllmain.c:26
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1665
static const union cptable * ansi_cptable
Definition: locale.c:64
BOOL WINAPI SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data)
Definition: locale.c:1888
static const WCHAR sYearMonthW[]
Definition: locale.c:207
#define REG_SZ
Definition: locale.c:44
static const WCHAR sNativeDigitsW[]
Definition: locale.c:200
INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
Definition: locale.c:5565
static const union cptable * mac_cptable
Definition: locale.c:66
static const WCHAR iTimeW[]
Definition: locale.c:186
static const WCHAR sDecimalW[]
Definition: locale.c:192
static LCID lcid_LC_PAPER
Definition: locale.c:166
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: locale.c:2876
BOOL WINAPI SetLocaleInfoW(LCID lcid, LCTYPE lctype, LPCWSTR data)
Definition: locale.c:1920
BOOL WINAPI EnumSystemLocalesEx(LOCALE_ENUMPROCEX proc, DWORD flags, LPARAM lparam, LPVOID reserved)
Definition: locale.c:3038
INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpNameprepCharStr, INT cchNameprepChar)
Definition: locale.c:5840
INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
Definition: locale.c:5645
static LCID lcid_LC_MESSAGES
Definition: locale.c:162
const WCHAR * text
Definition: package.c:1799
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned char
Definition: typeof.h:29
#define assert(x)
Definition: debug.h:53
r parent
Definition: btrfs.c:3010
r reserved
Definition: btrfs.c:3006
#define strcasecmp
Definition: fake.h:9
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxAutoRegKey hKey
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLenum GLuint components
Definition: glext.h:9620
GLfloat bias
Definition: glext.h:7909
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLintptr offset
Definition: glext.h:5920
const GLfloat * m
Definition: glext.h:10848
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int wine_cpsymbol_wcstombs(const WCHAR *src, int srclen, char *dst, int dstlen)
#define C1_PUNCT
Definition: unicode.h:35
#define C1_SPACE
Definition: unicode.h:34
#define C1_ALPHA
Definition: unicode.h:39
#define MB_COMPOSITE
Definition: unicode.h:40
const union cptable * wine_cp_enum_table(unsigned int index)
Definition: cptable.c:203
int wine_utf8_wcstombs(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
Definition: utf8.c:98
int wine_cp_wcstombs(const union cptable *table, int flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, int *used)
Definition: wctomb.c:411
const union cptable * wine_cp_get_table(unsigned int codepage)
Definition: cptable.c:192
WINE_UNICODE_INLINE int wine_is_dbcs_leadbyte(const union cptable *table, unsigned char ch)
Definition: unicode.h:130
int wine_cpsymbol_mbstowcs(const char *src, int srclen, WCHAR *dst, int dstlen)
int wine_cp_mbstowcs(const union cptable *table, int flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: mbtowc.c:265
int wine_utf8_mbstowcs(int flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: utf8.c:304
WINE_UNICODE_INLINE unsigned short get_char_typeW(WCHAR ch)
Definition: unicode.h:149
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define LC_CTYPE
Definition: locale.h:19
#define LC_NUMERIC
Definition: locale.h:21
#define LC_MONETARY
Definition: locale.h:20
#define LC_ALL
Definition: locale.h:17
#define LC_TIME
Definition: locale.h:22
#define LC_COLLATE
Definition: locale.h:18
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
void JapaneseEra_ClearCache(void)
Definition: japanese.c:38
#define b
Definition: ke_i.h:79
BOOL WINAPI GetUserPreferredUILanguages(DWORD dwFlags, PULONG pulNumLanguages, PZZWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer)
Definition: vista.c:721
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
#define nls
Definition: kernel32.h:13
USHORT LANGID
Definition: mui.h:9
ULONG GEOID
Definition: mui.h:28
if(dx< 0)
Definition: linetemp.h:194
POINT cp
Definition: magnifier.c:59
#define matches(FN)
Definition: match.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static unsigned int number
Definition: dsound.c:1479
static const WCHAR localeW[]
Definition: locale.c:43
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: directory.c:52
static DWORD dstlen
Definition: directory.c:51
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
WCHAR strW[12]
Definition: clipboard.c:2029
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
LANGID langid
Definition: msctf.idl:644
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
const unsigned short nameprep_char_type[4432]
Definition: nameprep.c:5
const unsigned short nameprep_mapping[5856]
Definition: nameprep.c:565
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
_Must_inspect_result_ NTSYSAPI LONG NTAPI RtlCompareUnicodeStrings(_In_reads_(String1Length) PCWCH String1, _In_ SIZE_T String1Length, _In_reads_(String2Length) PCWCH String2, _In_ SIZE_T String2Length, _In_ BOOLEAN CaseInSensitive)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
@ KeyValuePartialInformation
Definition: nt_native.h:1182
@ KeyValueFullInformation
Definition: nt_native.h:1181
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
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)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
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
NTSTATUS NTAPI NtEnumerateValueKey(IN HANDLE KeyHandle, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:542
#define LOCALE_NEUTRAL
#define LOCALE_USER_DEFAULT
#define LOCALE_INVARIANT
#define SORTIDFROMLCID(lcid)
#define LOCALE_SYSTEM_DEFAULT
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
_NullNull_terminated_ CONST WCHAR * PCZZWSTR
Definition: ntbasedef.h:421
NTSTATUS NTAPI NtQueryInstallUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:611
NTSTATUS NTAPI NtQueryDefaultLocale(IN BOOLEAN UserProfile, OUT PLCID DefaultLocaleId)
Definition: locale.c:396
NTSTATUS NTAPI NtSetDefaultUILanguage(IN LANGID LanguageId)
Definition: locale.c:692
NTSTATUS NTAPI NtQueryDefaultUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:645
NTSTATUS NTAPI NtSetDefaultLocale(IN BOOLEAN UserProfile, IN LCID DefaultLocaleId)
Definition: locale.c:437
#define L(x)
Definition: ntvdm.h:50
static HANDLE proc()
Definition: pdb.c:34
#define RT_STRING
Definition: pedump.c:368
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static const WCHAR szName[]
Definition: powrprof.c:45
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define toupperW(n)
Definition: unicode.h:51
#define strcmpW(s1, s2)
Definition: unicode.h:44
#define strchrW(s, c)
Definition: unicode.h:40
#define strcmpiW(s1, s2)
Definition: unicode.h:45
#define tolowerW(n)
Definition: unicode.h:50
#define strlenW(s)
Definition: unicode.h:34
#define strrchrW(s, c)
Definition: unicode.h:41
#define strcatW(d, s)
Definition: unicode.h:36
#define strtoulW(s1, s2, b)
Definition: unicode.h:47
#define sprintfW
Definition: unicode.h:64
#define strtolW(s, e, b)
Definition: unicode.h:39
#define strcpyW(d, s)
Definition: unicode.h:35
#define strpbrkW(str, accept)
Definition: unicode.h:49
static FILE * out
Definition: regtests2xml.c:44
const WCHAR * str
#define LANG_NEUTRAL
Definition: nls.h:22
#define MAKELANGID(p, s)
Definition: nls.h:15
#define SUBLANG_CHINESE_SINGAPORE
Definition: nls.h:211
#define SUBLANGID(l)
Definition: nls.h:17
#define LANG_SPANISH
Definition: nls.h:123
#define SUBLANG_CHINESE_MACAU
Definition: nls.h:212
#define LANG_ENGLISH
Definition: nls.h:52
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define SUBLANG_CHINESE_TRADITIONAL
Definition: nls.h:208
#define SUBLANG_NEUTRAL
Definition: nls.h:167
#define SUBLANG_CHINESE_SIMPLIFIED
Definition: nls.h:209
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define SUBLANG_CHINESE_HONGKONG
Definition: nls.h:210
#define LANG_CHINESE
Definition: nls.h:42
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define SUBLANG_SPANISH_MODERN
Definition: nls.h:338
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
LANGGROUPLOCALE_ENUMPROCW procW
Definition: locale.c:4665
LANGGROUPLOCALE_ENUMPROCA procA
Definition: locale.c:4664
LANGUAGEGROUP_ENUMPROCW procW
Definition: locale.c:4470
LANGUAGEGROUP_ENUMPROCA procA
Definition: locale.c:4469
union ENUM_UILANG_CALLBACK::@469 u
UILANGUAGE_ENUMPROCA procA
Definition: locale.c:4913
UILANGUAGE_ENUMPROCW procW
Definition: locale.c:4914
BYTE LeadByte[MAX_LEADBYTES]
Definition: winnls.h:583
BYTE DefaultChar[MAX_DEFAULTCHAR]
Definition: winnls.h:582
UINT MaxCharSize
Definition: winnls.h:581
CHAR CodePageName[MAX_PATH]
Definition: winnls.h:591
WCHAR UnicodeDefaultChar
Definition: winnls.h:597
WCHAR CodePageName[MAX_PATH]
Definition: winnls.h:599
UINT CodePage
Definition: winnls.h:598
Definition: cookie.c:202
Definition: mimeintl.c:44
LOCALE_ENUMPROCEX proc
Definition: locale.c:3010
INT uncode
Definition: locale.c:5009
enum locationkind kind
Definition: locale.c:5010
GEOID parent
Definition: locale.c:5008
GEOID id
Definition: locale.c:5005
WCHAR iso2W[3]
Definition: locale.c:5006
WCHAR iso3W[4]
Definition: locale.c:5007
WCHAR win_name[128]
Definition: locale.c:148
int matches
Definition: locale.c:155
UINT codepage
Definition: locale.c:156
LCID lcid
Definition: locale.c:154
WCHAR lang[128]
Definition: locale.c:149
WCHAR * country
Definition: locale.c:150
WCHAR * charset
Definition: locale.c:151
WCHAR * modifier
Definition: locale.c:153
WCHAR * script
Definition: locale.c:152
Definition: name.c:39
Definition: module.h:576
WCHAR * cached_value
Definition: locale.c:214
const WCHAR * name
Definition: locale.c:213
DWORD lctype
Definition: locale.c:212
Definition: ps.c:97
const WCHAR * name
#define max(a, b)
Definition: svc.c:63
#define bsearch
#define setlocale(n, s)
Definition: locale.h:46
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint16_t * LPWORD
Definition: typedefs.h:56
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
struct cp_info info
Definition: unicode.h:96
Definition: pdh_main.c:94
static const WCHAR lang[]
Definition: wbemdisp.c:287
int ret
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2084
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
LONG_PTR LPARAM
Definition: windef.h:208
#define WINAPI
Definition: msvc.h:6
#define ERROR_NO_UNICODE_TRANSLATION
Definition: winerror.h:649
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define LGRPID_INSTALLED
Definition: winnls.h:458
#define C2_ARABICNUMBER
Definition: winnls.h:255
#define LOCALE_USE_CP_ACP
Definition: winnls.h:20
#define LCMAP_LINGUISTIC_CASING
Definition: winnls.h:192
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:113
#define LOCALE_SMONTHNAME12
Definition: winnls.h:102
#define CP_THREAD_ACP
Definition: winnls.h:233
#define LOCALE_ICURRDIGITS
Definition: winnls.h:54
#define LOCALE_IDEFAULTCODEPAGE
Definition: winnls.h:37
#define NORM_IGNORECASE
Definition: winnls.h:176
#define LOCALE_SMONTHNAME5
Definition: winnls.h:95
#define C3_FULLWIDTH
Definition: winnls.h:269
#define CP_OEMCP
Definition: winnls.h:231
#define LOCALE_SCOUNTRY
Definition: winnls.h:31
#define LOCALE_SDATE
Definition: winnls.h:58
#define LOCALE_SDAYNAME5
Definition: winnls.h:81
#define C3_ALPHA
Definition: winnls.h:273
DWORD LGRPID
Definition: winnls.h:520
#define LOCALE_SABBREVMONTHNAME9
Definition: winnls.h:112
BOOL(CALLBACK * LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM)
Definition: winnls.h:539
BOOL(CALLBACK * LANGGROUPLOCALE_ENUMPROCA)(LGRPID, LCID, LPSTR, LONG_PTR)
Definition: winnls.h:533
#define LOCALE_NEUTRALDATA
Definition: winnls.h:210
#define LOCALE_SABBREVMONTHNAME11
Definition: winnls.h:114
#define LOCALE_SABBREVDAYNAME5
Definition: winnls.h:88
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:85
#define LOCALE_INEGSEPBYSPACE
Definition: winnls.h:124
#define LOCALE_SABBREVMONTHNAME2
Definition: winnls.h:105
#define LOCALE_INEGSIGNPOSN
Definition: winnls.h:120
#define LOCALE_IDEFAULTUNIXCODEPAGE
Definition: winnls.h:174
#define C2_OTHERNEUTRAL
Definition: winnls.h:260
#define LOCALE_SMONTHNAME13
Definition: winnls.h:103
#define LOCALE_SGROUPING
Definition: winnls.h:44
#define C2_LEFTTORIGHT
Definition: winnls.h:250
#define LOCALE_SMONTHNAME3
Definition: winnls.h:93
#define CT_CTYPE2
Definition: winnls.h:238
#define SORT_STRINGSORT
Definition: winnls.h:183
#define C3_DIACRITIC
Definition: winnls.h:263
#define C3_IDEOGRAPH
Definition: winnls.h:270
#define LOCALE_SSHORTTIME
Definition: winnls.h:163
#define LOCALE_ICOUNTRY
Definition: winnls.h:30
#define LINGUISTIC_IGNORECASE
Definition: winnls.h:181
#define LCMAP_SIMPLIFIED_CHINESE
Definition: winnls.h:193
#define CP_SYMBOL
Definition: winnls.h:234
#define LOCALE_SDECIMAL
Definition: winnls.h:42
#define LOCALE_SMONTHNAME11
Definition: winnls.h:101
#define LOCALE_SMONTHNAME8
Definition: winnls.h:98
@ GEO_ISO3
Definition: winnls.h:566
@ GEO_OFFICIALLANGUAGES
Definition: winnls.h:572
@ GEO_OFFICIALNAME
Definition: winnls.h:570
@ GEO_TIMEZONES
Definition: winnls.h:571
@ GEO_FRIENDLYNAME
Definition: winnls.h:569
@ GEO_LONGITUDE
Definition: winnls.h:564
@ GEO_ISO_UN_NUMBER
Definition: winnls.h:573
@ GEO_PARENT
Definition: winnls.h:574
@ GEO_ISO2
Definition: winnls.h:565
@ GEO_LATITUDE
Definition: winnls.h:563
@ GEO_NATION
Definition: winnls.h:562
@ GEO_LCID
Definition: winnls.h:568
@ GEO_RFC1766
Definition: winnls.h:567
#define LCMAP_TRADITIONAL_CHINESE
Definition: winnls.h:194
#define LGRPID_ARMENIAN
Definition: winnls.h:476
#define CT_CTYPE3
Definition: winnls.h:239
#define CT_CTYPE1
Definition: winnls.h:237
#define LOCALE_IDATE
Definition: winnls.h:63
#define LOCALE_SMONTHNAME4
Definition: winnls.h:94
#define LOCALE_FONTSIGNATURE
Definition: winnls.h:125
BOOL(CALLBACK * UILANGUAGE_ENUMPROCW)(LPWSTR, LONG_PTR)
Definition: winnls.h:535
#define LOCALE_SENGLANGUAGE
Definition: winnls.h:27
#define C3_HALFWIDTH
Definition: winnls.h:268
#define MAP_PRECOMPOSED
Definition: winnls.h:215
#define LOCALE_SABBREVMONTHNAME13
Definition: winnls.h:116
#define C2_EUROPENUMBER
Definition: winnls.h:252
#define LOCALE_IFIRSTWEEKOFYEAR
Definition: winnls.h:76
#define LCMAP_HALFWIDTH
Definition: winnls.h:190
#define LOCALE_SDAYNAME1
Definition: winnls.h:77
#define LOCALE_IMEASURE
Definition: winnls.h:41
#define C3_NONSPACING
Definition: winnls.h:262
#define LCMAP_HIRAGANA
Definition: winnls.h:188
#define LOCALE_ILANGUAGE
Definition: winnls.h:25
#define C3_SYMBOL
Definition: winnls.h:265
#define LOCALE_SNAME
Definition: winnls.h:130
#define LCMAP_UPPERCASE
Definition: winnls.h:185
#define LOCALE_SLONGDATE
Definition: winnls.h:61
#define LOCALE_SMONTHNAME7
Definition: winnls.h:97
#define C3_LOWSURROGATE
Definition: winnls.h:276
#define NORM_IGNOREKANATYPE
Definition: winnls.h:177
#define NORM_LINGUISTIC_CASING
Definition: winnls.h:182
#define LOCALE_IINTLCURRDIGITS
Definition: winnls.h:55
#define C2_COMMONSEPARATOR
Definition: winnls.h:256
#define LOCALE_S1159
Definition: winnls.h:71
#define LOCALE_SSHORTDATE
Definition: winnls.h:60
#define CSTR_EQUAL
Definition: winnls.h:456
#define GEOID_NOT_AVAILABLE
Definition: winnls.h:13
BOOL(CALLBACK * GEO_ENUMPROC)(GEOID)
Definition: winnls.h:548
BOOL(CALLBACK * LANGGROUPLOCALE_ENUMPROCW)(LGRPID, LCID, LPWSTR, LONG_PTR)
Definition: winnls.h:534
#define NORM_IGNORENONSPACE
Definition: winnls.h:178
BOOL(CALLBACK * CODEPAGE_ENUMPROCA)(LPSTR)
Definition: winnls.h:540
#define LOCALE_SPECIFICDATA
Definition: winnls.h:211
#define LOCALE_IPOSSYMPRECEDES
Definition: winnls.h:121
#define LOCALE_IDAYLZERO
Definition: winnls.h:69
#define C3_KATAKANA
Definition: winnls.h:266
#define C2_EUROPESEPARATOR
Definition: winnls.h:253
#define CP_UTF7
Definition: winnls.h:235
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:107
#define CP_MACCP
Definition: winnls.h:232
#define LOCALE_SPOSITIVESIGN
Definition: winnls.h:117
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCW)(LGRPID, LPWSTR, LPWSTR, DWORD, LONG_PTR)
Definition: winnls.h:532
#define NORM_IGNORESYMBOLS
Definition: winnls.h:179
#define LOCALE_INEUTRAL
Definition: winnls.h:156
#define LOCALE_IDEFAULTLANGUAGE
Definition: winnls.h:35
#define C2_EUROPETERMINATOR
Definition: winnls.h:254
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:87
#define LOCALE_SMONDECIMALSEP
Definition: winnls.h:51
#define CP_INSTALLED
Definition: winnls.h:199
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:126
#define LCMAP_SORTKEY
Definition: winnls.h:186
#define MAP_COMPOSITE
Definition: winnls.h:216
#define LCMAP_LOWERCASE
Definition: winnls.h:184
#define LOCALE_ITIME
Definition: winnls.h:65
#define LOCALE_ICURRENCY
Definition: winnls.h:56
#define C2_SEGMENTSEPARATOR
Definition: winnls.h:258
#define C3_KASHIDA
Definition: winnls.h:271
#define LOCALE_SMONTHNAME1
Definition: winnls.h:91
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:106
#define LOCALE_ITLZERO
Definition: winnls.h:68
#define LOCALE_INEGSYMPRECEDES
Definition: winnls.h:123
BOOL(CALLBACK * LOCALE_ENUMPROCA)(LPSTR)
Definition: winnls.h:537
#define LOCALE_SMONTHOUSANDSEP
Definition: winnls.h:52
#define LOCALE_SDAYNAME7
Definition: winnls.h:83
#define LOCALE_IPOSSIGNPOSN
Definition: winnls.h:119
#define C2_RIGHTTOLEFT
Definition: winnls.h:251
#define LOCALE_SDAYNAME2
Definition: winnls.h:78
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:104
DWORD GEOCLASS
Definition: winnls.h:523
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
#define LOCALE_IOPTIONALCALENDAR
Definition: winnls.h:74
#define LOCALE_IDIGITS
Definition: winnls.h:45
#define MAP_FOLDCZONE
Definition: winnls.h:213
DWORD GEOTYPE
Definition: winnls.h:522
#define LCID_SUPPORTED
Definition: winnls.h:202
#define LOCALE_STHOUSAND
Definition: winnls.h:43
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:38
#define C3_HIRAGANA
Definition: winnls.h:267
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:127
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:89
#define LOCALE_SMONTHNAME2
Definition: winnls.h:92
#define LOCALE_STIMEFORMAT
Definition: winnls.h:62
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCA)(LGRPID, LPSTR, LPSTR, DWORD, LONG_PTR)
Definition: winnls.h:531
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
#define LOCALE_IFIRSTDAYOFWEEK
Definition: winnls.h:75
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:109
#define LOCALE_SMONTHNAME6
Definition: winnls.h:96
#define C2_WHITESPACE
Definition: winnls.h:259
#define LOCALE_STIME
Definition: winnls.h:59
#define NORM_IGNOREWIDTH
Definition: winnls.h:180
#define LOCALE_SABBREVLANGNAME
Definition: winnls.h:28
#define C3_HIGHSURROGATE
Definition: winnls.h:275
BOOL(CALLBACK * UILANGUAGE_ENUMPROCA)(LPSTR, LONG_PTR)
Definition: winnls.h:536
#define LOCALE_INEGNUMBER
Definition: winnls.h:47
#define LOCALE_SNEGATIVESIGN
Definition: winnls.h:118
#define LOCALE_WINDOWS
Definition: winnls.h:206
DWORD LCTYPE
Definition: winnls.h:517
#define LOCALE_SDAYNAME3
Definition: winnls.h:79
#define CSTR_LESS_THAN
Definition: winnls.h:455
#define LOCALE_S2359
Definition: winnls.h:72
#define LOCALE_SNATIVEDIGITS
Definition: winnls.h:48
#define LOCALE_SLIST
Definition: winnls.h:40
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:86
#define CP_SUPPORTED
Definition: winnls.h:200
#define C2_NOTAPPLICABLE
Definition: winnls.h:261
#define LOCALE_ILZERO
Definition: winnls.h:46
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:108
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:110
#define LOCALE_ICALENDARTYPE
Definition: winnls.h:73
#define LOCALE_SINTLSYMBOL
Definition: winnls.h:50
BOOL(CALLBACK * LOCALE_ENUMPROCW)(LPWSTR)
Definition: winnls.h:538
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:111
#define LCMAP_KATAKANA
Definition: winnls.h:189
#define CSTR_GREATER_THAN
Definition: winnls.h:457
#define LOCALE_SMONGROUPING
Definition: winnls.h:53
#define LOCALE_SDAYNAME4
Definition: winnls.h:80
#define LOCALE_SCURRENCY
Definition: winnls.h:49
#define LOCALE_SMONTHNAME10
Definition: winnls.h:100
#define LOCALE_INEGCURR
Definition: winnls.h:57
#define LOCALE_ILDATE
Definition: winnls.h:64
#define LCMAP_FULLWIDTH
Definition: winnls.h:191
#define LCMAP_BYTEREV
Definition: winnls.h:187
#define LOCALE_SMONTHNAME9
Definition: winnls.h:99
BOOL(CALLBACK * CODEPAGE_ENUMPROCW)(LPWSTR)
Definition: winnls.h:541
#define LOCALE_IPOSSEPBYSPACE
Definition: winnls.h:122
#define LOCALE_ICENTURY
Definition: winnls.h:67
#define C2_BLOCKSEPARATOR
Definition: winnls.h:257
#define LOCALE_IMONLZERO
Definition: winnls.h:70
@ GEOCLASS_REGION
Definition: winnls.h:556
@ GEOCLASS_NATION
Definition: winnls.h:555
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:115
#define LOCALE_IDEFAULTMACCODEPAGE
Definition: winnls.h:39
#define LGRPID_SUPPORTED
Definition: winnls.h:459
#define LOCALE_SDAYNAME6
Definition: winnls.h:82
#define LOCALE_ITIMEMARKPOSN
Definition: winnls.h:66
#define LOCALE_RETURN_GENITIVE_NAMES
Definition: winnls.h:24
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:90
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define MAKEINTRESOURCE
Definition: winuser.h:591
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3197
static int callbacks
Definition: xmllint.c:838
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193