ReactOS 0.4.16-dev-1409-g71b6fab
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 2003 Jon Griffiths
8 * Copyright 2005 Dmitry Timoshkov
9 * Copyright 2002, 2019 Alexandre Julliard
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <stdarg.h>
27#include <stdlib.h>
28
29#include "ntstatus.h"
30#define WIN32_NO_STATUS
31#define WINNORMALIZEAPI
32#include "windef.h"
33#include "winbase.h"
34#include "winreg.h"
35#include "winnls.h"
36#include "winuser.h"
37#include "winternl.h"
38#include "kernelbase.h"
39#include "wine/debug.h"
40
42
43#define CALINFO_MAX_YEAR 2029
44
46
48{
49 const WCHAR *value;
50 const WCHAR *subkey;
53};
54
55static const WCHAR world_subkey[] = { 0xd83c, 0xdf0e, 0xd83c, 0xdf0f, 0xd83c, 0xdf0d, 0 }; /* 🌎🌏🌍 */
56
57static struct registry_entry entry_icalendartype = { L"iCalendarType" };
58static struct registry_entry entry_icountry = { L"iCountry" };
59static struct registry_entry entry_icurrdigits = { L"iCurrDigits" };
60static struct registry_entry entry_icurrency = { L"iCurrency" };
61static struct registry_entry entry_idigits = { L"iDigits" };
62static struct registry_entry entry_idigitsubstitution = { L"NumShape" };
63static struct registry_entry entry_ifirstdayofweek = { L"iFirstDayOfWeek" };
64static struct registry_entry entry_ifirstweekofyear = { L"iFirstWeekOfYear" };
65static struct registry_entry entry_ilzero = { L"iLZero" };
66static struct registry_entry entry_imeasure = { L"iMeasure" };
67static struct registry_entry entry_inegcurr = { L"iNegCurr" };
68static struct registry_entry entry_inegnumber = { L"iNegNumber" };
69static struct registry_entry entry_ipapersize = { L"iPaperSize" };
70static struct registry_entry entry_s1159 = { L"s1159" };
71static struct registry_entry entry_s2359 = { L"s2359" };
72static struct registry_entry entry_scurrency = { L"sCurrency" };
73static struct registry_entry entry_sdecimal = { L"sDecimal" };
74static struct registry_entry entry_sgrouping = { L"sGrouping" };
75static struct registry_entry entry_sintlsymbol = { L"Currencies", world_subkey };
76static struct registry_entry entry_slist = { L"sList" };
77static struct registry_entry entry_slongdate = { L"sLongDate" };
78static struct registry_entry entry_smondecimalsep = { L"sMonDecimalSep" };
79static struct registry_entry entry_smongrouping = { L"sMonGrouping" };
80static struct registry_entry entry_smonthousandsep = { L"sMonThousandSep" };
81static struct registry_entry entry_snativedigits = { L"sNativeDigits" };
82static struct registry_entry entry_snegativesign = { L"sNegativeSign" };
83static struct registry_entry entry_spositivesign = { L"sPositiveSign" };
84static struct registry_entry entry_sshortdate = { L"sShortDate" };
85static struct registry_entry entry_sshorttime = { L"sShortTime" };
86static struct registry_entry entry_sthousand = { L"sThousand" };
87static struct registry_entry entry_stimeformat = { L"sTimeFormat" };
88static struct registry_entry entry_syearmonth = { L"sYearMonth" };
89
90
91static const struct { UINT cp; const WCHAR *name; } codepage_names[] =
92{
93 { 37, L"IBM EBCDIC US Canada" },
94 { 424, L"IBM EBCDIC Hebrew" },
95 { 437, L"OEM United States" },
96 { 500, L"IBM EBCDIC International" },
97 { 708, L"Arabic ASMO" },
98 { 720, L"Arabic (Transparent ASMO)" },
99 { 737, L"OEM Greek 437G" },
100 { 775, L"OEM Baltic" },
101 { 850, L"OEM Multilingual Latin 1" },
102 { 852, L"OEM Slovak Latin 2" },
103 { 855, L"OEM Cyrillic" },
104 { 856, L"Hebrew PC" },
105 { 857, L"OEM Turkish" },
106 { 860, L"OEM Portuguese" },
107 { 861, L"OEM Icelandic" },
108 { 862, L"OEM Hebrew" },
109 { 863, L"OEM Canadian French" },
110 { 864, L"OEM Arabic" },
111 { 865, L"OEM Nordic" },
112 { 866, L"OEM Russian" },
113 { 869, L"OEM Greek" },
114 { 874, L"ANSI/OEM Thai" },
115 { 875, L"IBM EBCDIC Greek" },
116 { 878, L"Russian KOI8" },
117 { 932, L"ANSI/OEM Japanese Shift-JIS" },
118 { 936, L"ANSI/OEM Simplified Chinese GBK" },
119 { 949, L"ANSI/OEM Korean Unified Hangul" },
120 { 950, L"ANSI/OEM Traditional Chinese Big5" },
121 { 1006, L"IBM Arabic" },
122 { 1026, L"IBM EBCDIC Latin 5 Turkish" },
123 { 1250, L"ANSI Eastern Europe" },
124 { 1251, L"ANSI Cyrillic" },
125 { 1252, L"ANSI Latin 1" },
126 { 1253, L"ANSI Greek" },
127 { 1254, L"ANSI Turkish" },
128 { 1255, L"ANSI Hebrew" },
129 { 1256, L"ANSI Arabic" },
130 { 1257, L"ANSI Baltic" },
131 { 1258, L"ANSI/OEM Viet Nam" },
132 { 1361, L"Korean Johab" },
133 { 10000, L"Mac Roman" },
134 { 10001, L"Mac Japanese" },
135 { 10002, L"Mac Traditional Chinese" },
136 { 10003, L"Mac Korean" },
137 { 10004, L"Mac Arabic" },
138 { 10005, L"Mac Hebrew" },
139 { 10006, L"Mac Greek" },
140 { 10007, L"Mac Cyrillic" },
141 { 10008, L"Mac Simplified Chinese" },
142 { 10010, L"Mac Romanian" },
143 { 10017, L"Mac Ukrainian" },
144 { 10021, L"Mac Thai" },
145 { 10029, L"Mac Latin 2" },
146 { 10079, L"Mac Icelandic" },
147 { 10081, L"Mac Turkish" },
148 { 10082, L"Mac Croatian" },
149 { 20127, L"US-ASCII (7bit)" },
150 { 20866, L"Russian KOI8" },
151 { 20932, L"EUC-JP" },
152 { 20949, L"Korean Wansung" },
153 { 21866, L"Ukrainian KOI8" },
154 { 28591, L"ISO 8859-1 Latin 1" },
155 { 28592, L"ISO 8859-2 Latin 2 (East European)" },
156 { 28593, L"ISO 8859-3 Latin 3 (South European)" },
157 { 28594, L"ISO 8859-4 Latin 4 (Baltic old)" },
158 { 28595, L"ISO 8859-5 Cyrillic" },
159 { 28596, L"ISO 8859-6 Arabic" },
160 { 28597, L"ISO 8859-7 Greek" },
161 { 28598, L"ISO 8859-8 Hebrew" },
162 { 28599, L"ISO 8859-9 Latin 5 (Turkish)" },
163 { 28600, L"ISO 8859-10 Latin 6 (Nordic)" },
164 { 28601, L"ISO 8859-11 Latin (Thai)" },
165 { 28603, L"ISO 8859-13 Latin 7 (Baltic)" },
166 { 28604, L"ISO 8859-14 Latin 8 (Celtic)" },
167 { 28605, L"ISO 8859-15 Latin 9 (Euro)" },
168 { 28606, L"ISO 8859-16 Latin 10 (Balkan)" },
169 { 65000, L"65000 (UTF-7)" },
170 { 65001, L"65001 (UTF-8)" }
172
173/* Unicode expanded ligatures */
174static const WCHAR ligatures[][5] =
175{
176 { 0x00c6, 'A','E',0 },
177 { 0x00de, 'T','H',0 },
178 { 0x00df, 's','s',0 },
179 { 0x00e6, 'a','e',0 },
180 { 0x00fe, 't','h',0 },
181 { 0x0132, 'I','J',0 },
182 { 0x0133, 'i','j',0 },
183 { 0x0152, 'O','E',0 },
184 { 0x0153, 'o','e',0 },
185 { 0x01c4, 'D',0x017d,0 },
186 { 0x01c5, 'D',0x017e,0 },
187 { 0x01c6, 'd',0x017e,0 },
188 { 0x01c7, 'L','J',0 },
189 { 0x01c8, 'L','j',0 },
190 { 0x01c9, 'l','j',0 },
191 { 0x01ca, 'N','J',0 },
192 { 0x01cb, 'N','j',0 },
193 { 0x01cc, 'n','j',0 },
194 { 0x01e2, 0x0100,0x0112,0 },
195 { 0x01e3, 0x0101,0x0113,0 },
196 { 0x01f1, 'D','Z',0 },
197 { 0x01f2, 'D','z',0 },
198 { 0x01f3, 'd','z',0 },
199 { 0x01fc, 0x00c1,0x00c9,0 },
200 { 0x01fd, 0x00e1,0x00e9,0 },
201 { 0x05f0, 0x05d5,0x05d5,0 },
202 { 0x05f1, 0x05d5,0x05d9,0 },
203 { 0x05f2, 0x05d9,0x05d9,0 },
204 { 0xfb00, 'f','f',0 },
205 { 0xfb01, 'f','i',0 },
206 { 0xfb02, 'f','l',0 },
207 { 0xfb03, 'f','f','i',0 },
208 { 0xfb04, 'f','f','l',0 },
209 { 0xfb05, 0x017f,'t',0 },
210 { 0xfb06, 's','t',0 },
211};
212
214{
217 UINT sshortdate; /* 04 */
218 UINT syearmonth; /* 08 */
219 UINT slongdate; /* 0c */
220 UINT serastring; /* 10 */
222 UINT sdayname; /* 18 */
224 UINT smonthname; /* 20 */
226 UINT scalname; /* 28 */
227 UINT smonthday; /* 2c */
231 UINT unused[3]; /* 3c */
232};
233
234static const struct geo_id
235{
239 GEOCLASS class;
248
249static const struct geo_index
250{
254
255static unsigned int geo_ids_count;
256static unsigned int geo_index_count;
257
259{
270
272
273/* NLS normalization file */
275{
276 WCHAR name[13]; /* 00 file name */
277 USHORT checksum[3]; /* 1a checksum? */
278 USHORT version[4]; /* 20 Unicode version */
279 USHORT form; /* 28 normalization form */
280 USHORT len_factor; /* 2a factor for length estimates */
281 USHORT unknown1; /* 2c */
282 USHORT decomp_size; /* 2e decomposition hash size */
283 USHORT comp_size; /* 30 composition hash size */
284 USHORT unknown2; /* 32 */
285 USHORT classes; /* 34 combining classes table offset */
286 USHORT props_level1; /* 36 char properties table level 1 offset */
287 USHORT props_level2; /* 38 char properties table level 2 offset */
288 USHORT decomp_hash; /* 3a decomposition hash table offset */
289 USHORT decomp_map; /* 3c decomposition character map table offset */
290 USHORT decomp_seq; /* 3e decomposition character sequences offset */
291 USHORT comp_hash; /* 40 composition hash table offset */
292 USHORT comp_seq; /* 42 composition character sequences offset */
293 /* BYTE[] combining class values */
294 /* BYTE[0x2200] char properties index level 1 */
295 /* BYTE[] char properties index level 2 */
296 /* WORD[] decomposition hash table */
297 /* WORD[] decomposition character map */
298 /* WORD[] decomposition character sequences */
299 /* WORD[] composition hash table */
300 /* WORD[] composition character sequences */
301};
302
311static const NLS_LOCALE_LCID_INDEX *lcids_index;
312static const NLS_LOCALE_LCNAME_INDEX *lcnames_index;
313static const NLS_LOCALE_HEADER *locale_table;
314static const WCHAR *locale_strings;
315static const NLS_LOCALE_DATA *system_locale;
316static const NLS_LOCALE_DATA *user_locale;
317
319static unsigned int nb_codepages;
320
321static struct norm_table *norm_info;
322
324{
325 GUID id; /* sort GUID */
326 UINT flags; /* flags */
327 UINT compr; /* offset to compression table */
328 UINT except; /* exception table offset in sortkey table */
329 UINT ling_except; /* exception table offset for linguistic casing */
330 UINT casemap; /* linguistic casemap table offset */
331};
332
333/* flags for sortguid */
334#define FLAG_HAS_3_BYTE_WEIGHTS 0x01
335#define FLAG_REVERSEDIACRITICS 0x10
336#define FLAG_DOUBLECOMPRESSION 0x20
337#define FLAG_INVERSECASING 0x40
338
340{
342};
343
345{
352};
353
355{
359};
360
361static inline int compression_size( int len ) { return 2 + len + (len & 1); }
362
364{
367};
368
369/* bits for case weights */
370#define CASE_FULLWIDTH 0x01 /* full width kana (vs. half width) */
371#define CASE_FULLSIZE 0x02 /* full size kana (vs. small) */
372#define CASE_SUBSCRIPT 0x08 /* sub/super script */
373#define CASE_UPPER 0x10 /* upper case */
374#define CASE_KATAKANA 0x20 /* katakana (vs. hiragana) */
375#define CASE_COMPR_2 0x40 /* compression exists for >= 2 chars */
376#define CASE_COMPR_4 0x80 /* compression exists for >= 4 chars */
377#define CASE_COMPR_6 0xc0 /* compression exists for >= 6 chars */
378
380{
405};
406
407static const struct sortguid **locale_sorts;
408static const struct sortguid *current_locale_sort;
409
410static struct
411{
412 UINT version; /* NLS version */
413 UINT guid_count; /* number of sort GUIDs */
414 UINT exp_count; /* number of character expansions */
415 UINT compr_count; /* number of compression tables */
416 const UINT *keys; /* sortkey table, indexed by char */
417 const USHORT *casemap; /* casemap table, in l_intl.nls format */
418 const WORD *ctypes; /* CT_CTYPE1,2,3 values */
419 const BYTE *ctype_idx; /* index to map char to ctypes array entry */
420 const struct sortguid *guids; /* table of sort GUIDs */
421 const struct sort_expansion *expansions; /* character expansions */
422 const struct sort_compression *compressions; /* character compression tables */
423 const WCHAR *compr_data; /* data for individual compressions */
424 const struct jamo_sort *jamo; /* table for Jamo compositions */
426
429{
430 0, 0, &locale_section,
432 0, 0, { (DWORD_PTR)(__FILE__ ": locale_section") }
433};
434static CRITICAL_SECTION locale_section = { &critsect_debug, -1, 0, 0, 0, 0 };
435
436
437static void load_locale_nls(void)
438{
439 struct
440 {
441 UINT ctypes;
442 UINT unknown1;
443 UINT unknown2;
444 UINT unknown3;
445 UINT locales;
447 UINT geoids;
448 UINT scripts;
449 } *header;
450 struct geo_header
451 {
452 WCHAR signature[4]; /* L"geo" */
453 UINT total_size;
454 UINT ids_offset;
455 UINT ids_count;
456 UINT index_offset;
457 UINT index_count;
458 } *geo_header;
459
461 const USHORT *map_ptr;
462 unsigned int i;
463
465 locale_table = (const NLS_LOCALE_HEADER *)((char *)header + header->locales);
466 lcids_index = (const NLS_LOCALE_LCID_INDEX *)((char *)locale_table + locale_table->lcids_offset);
467 lcnames_index = (const NLS_LOCALE_LCNAME_INDEX *)((char *)locale_table + locale_table->lcnames_offset);
468 locale_strings = (const WCHAR *)((char *)locale_table + locale_table->strings_offset);
469 geo_header = (struct geo_header *)((char *)header + header->geoids);
470 geo_ids = (const struct geo_id *)((char *)geo_header + geo_header->ids_offset);
471 geo_index = (const struct geo_index *)((char *)geo_header + geo_header->index_offset);
472 geo_ids_count = geo_header->ids_count;
473 geo_index_count = geo_header->index_count;
474 map_ptr = (const USHORT *)((char *)header + header->charmaps);
475 for (i = 0; i < NB_CHARMAPS; i++, map_ptr += *map_ptr) charmaps[i] = map_ptr + 1;
476}
477
478
479static void load_sortdefault_nls(void)
480{
481 const struct
482 {
483 UINT sortkeys;
484 UINT casemaps;
485 UINT ctypes;
486 UINT sortids;
487 } *header;
488
489 const WORD *ctype;
490 const UINT *table;
491 UINT i;
492 SIZE_T size;
493 const struct sort_compression *last_compr;
494
495 NtGetNlsSectionPtr( 9, 0, NULL, (void **)&header, &size );
496
497 sort.keys = (UINT *)((char *)header + header->sortkeys);
498 sort.casemap = (USHORT *)((char *)header + header->casemaps);
499
500 ctype = (WORD *)((char *)header + header->ctypes);
501 sort.ctypes = ctype + 2;
502 sort.ctype_idx = (BYTE *)ctype + ctype[1] + 2;
503
504 table = (UINT *)((char *)header + header->sortids);
505 sort.version = table[0];
506 sort.guid_count = table[1];
507 sort.guids = (struct sortguid *)(table + 2);
508
509 table = (UINT *)(sort.guids + sort.guid_count);
510 sort.exp_count = table[0];
511 sort.expansions = (struct sort_expansion *)(table + 1);
512
513 table = (UINT *)(sort.expansions + sort.exp_count);
514 sort.compr_count = table[0];
515 sort.compressions = (struct sort_compression *)(table + 1);
516 sort.compr_data = (WCHAR *)(sort.compressions + sort.compr_count);
517
518 last_compr = sort.compressions + sort.compr_count - 1;
519 table = (UINT *)(sort.compr_data + last_compr->offset);
520 for (i = 0; i < 7; i++) table += last_compr->len[i] * ((i + 5) / 2);
521 table += 1 + table[0] / 2; /* skip multiple weights */
522 sort.jamo = (struct jamo_sort *)(table + 1);
523
525 locale_table->nb_lcnames * sizeof(*locale_sorts) );
526}
527
528
529static const struct sortguid *find_sortguid( const GUID *guid )
530{
531 int pos, ret, min = 0, max = sort.guid_count - 1;
532
533 while (min <= max)
534 {
535 pos = (min + max) / 2;
536 ret = memcmp( guid, &sort.guids[pos].id, sizeof(*guid) );
537 if (!ret) return &sort.guids[pos];
538 if (ret > 0) min = pos + 1;
539 else max = pos - 1;
540 }
541 ERR( "no sort found for %s\n", debugstr_guid( guid ));
542 return NULL;
543}
544
545
546static const NLS_LOCALE_DATA *get_locale_data( UINT idx )
547{
548 ULONG offset = locale_table->locales_offset + idx * locale_table->locale_size;
549 return (const NLS_LOCALE_DATA *)((const char *)locale_table + offset);
550}
551
552
553static const struct calendar *get_calendar_data( const NLS_LOCALE_DATA *locale, UINT id )
554{
555 if (id == CAL_HIJRI && locale->islamic_cal[0]) id = locale->islamic_cal[0];
556 else if (id == CAL_PERSIAN && locale->islamic_cal[1]) id = locale->islamic_cal[1];
557
558 if (!id || id > locale_table->nb_calendars) return NULL;
559 return (const struct calendar *)((const char *)locale_table + locale_table->calendars_offset +
560 (id - 1) * locale_table->calendar_size);
561}
562
563
564static int compare_locale_names( const WCHAR *n1, const WCHAR *n2 )
565{
566 for (;;)
567 {
568 WCHAR ch1 = *n1++;
569 WCHAR ch2 = *n2++;
570 if (ch1 >= 'a' && ch1 <= 'z') ch1 -= 'a' - 'A';
571 else if (ch1 == '_') ch1 = '-';
572 if (ch2 >= 'a' && ch2 <= 'z') ch2 -= 'a' - 'A';
573 else if (ch2 == '_') ch2 = '-';
574 if (!ch1 || ch1 != ch2) return ch1 - ch2;
575 }
576}
577
578
579static const NLS_LOCALE_LCNAME_INDEX *find_lcname_entry( const WCHAR *name )
580{
581 int min = 0, max = locale_table->nb_lcnames - 1;
582
583 while (min <= max)
584 {
585 int res, pos = (min + max) / 2;
586 const WCHAR *str = locale_strings + lcnames_index[pos].name;
588 if (res < 0) max = pos - 1;
589 else if (res > 0) min = pos + 1;
590 else return &lcnames_index[pos];
591 }
592 return NULL;
593}
594
595
596static const NLS_LOCALE_LCID_INDEX *find_lcid_entry( LCID lcid )
597{
598 int min = 0, max = locale_table->nb_lcids - 1;
599
600 while (min <= max)
601 {
602 int pos = (min + max) / 2;
603 if (lcid < lcids_index[pos].id) max = pos - 1;
604 else if (lcid > lcids_index[pos].id) min = pos + 1;
605 else return &lcids_index[pos];
606 }
607 return NULL;
608}
609
610
611static const struct geo_id *find_geo_id_entry( GEOID id )
612{
613 int min = 0, max = geo_ids_count - 1;
614
615 while (min <= max)
616 {
617 int pos = (min + max) / 2;
618 if (id < geo_ids[pos].id) max = pos - 1;
619 else if (id > geo_ids[pos].id) min = pos + 1;
620 else return &geo_ids[pos];
621 }
622 return NULL;
623}
624
625
626static const struct geo_id *find_geo_name_entry( const WCHAR *name )
627{
628 int min = 0, max = geo_index_count - 1;
629
630 while (min <= max)
631 {
632 int res, pos = (min + max) / 2;
634 if (res < 0) max = pos - 1;
635 else if (res > 0) min = pos + 1;
636 else return &geo_ids[geo_index[pos].idx];
637 }
638 return NULL;
639}
640
641
642static const NLS_LOCALE_DATA *get_locale_by_name( const WCHAR *name, LCID *lcid )
643{
644 const NLS_LOCALE_LCNAME_INDEX *entry;
645
647 {
648 *lcid = user_lcid;
649 return user_locale;
650 }
651 if (name[0] == '!' && !compare_locale_names( name, LOCALE_NAME_SYSTEM_DEFAULT ))
652 {
653 *lcid = system_lcid;
654 return system_locale;
655 }
656 if (!(entry = find_lcname_entry( name ))) return NULL;
657 *lcid = entry->id;
658 return get_locale_data( entry->idx );
659}
660
661
662static const struct sortguid *get_language_sort( const WCHAR *name )
663{
664 const NLS_LOCALE_LCNAME_INDEX *entry;
665 const NLS_LOCALE_DATA *locale;
666 WCHAR guidstr[39];
667 const struct sortguid *ret;
669 LCID lcid;
670 GUID guid;
671 HKEY key = 0;
672 DWORD size, type;
673
675 {
677 name = locale_strings + user_locale->sname + 1;
678 }
679 else if (name[0] == '!' && !compare_locale_names( name, LOCALE_NAME_SYSTEM_DEFAULT ))
680 {
681 name = locale_strings + system_locale->sname + 1;
682 }
683
684 if (!(entry = find_lcname_entry( name )))
685 {
686 WARN( "unknown locale %s\n", debugstr_w(name) );
688 return NULL;
689 }
690 if ((ret = locale_sorts[entry - lcnames_index])) return ret;
691
692 lcid = entry->id;
693 name = locale_strings + entry->name + 1;
694 locale = get_locale_data( entry->idx );
695 if (!RegOpenKeyExW( nls_key, L"Sorting\\Ids", 0, KEY_READ, &key ))
696 {
697 for (;;)
698 {
699 size = sizeof(guidstr);
700 if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)guidstr, &size ) && type == REG_SZ)
701 {
702 RtlInitUnicodeString( &str, guidstr );
704 break;
705 }
706 if (!name[0]) break;
707 name = locale_strings + (SORTIDFROMLCID( lcid ) ? locale->sname : locale->sparent) + 1;
708 if (!(locale = get_locale_by_name( name, &lcid ))) break;
709 }
710 RegCloseKey( key );
711 }
712 if (!ret) ret = &sort.guids[0];
714 return ret;
715}
716
717
718/******************************************************************************
719 * NlsValidateLocale (kernelbase.@)
720 *
721 * Note: it seems to return some internal data on Windows, we simply return the locale.nls data pointer.
722 */
723const NLS_LOCALE_DATA * WINAPI NlsValidateLocale( LCID *lcid, ULONG flags )
724{
725 const NLS_LOCALE_LCNAME_INDEX *name_entry;
726 const NLS_LOCALE_LCID_INDEX *entry;
727 const NLS_LOCALE_DATA *locale;
728
729 switch (*lcid)
730 {
732 *lcid = system_lcid;
733 return system_locale;
734 case LOCALE_NEUTRAL:
739 *lcid = user_lcid;
740 return user_locale;
741 default:
742 if (!(entry = find_lcid_entry( *lcid ))) return NULL;
743 locale = get_locale_data( entry->idx );
744 if ((flags & LOCALE_ALLOW_NEUTRAL_NAMES) || locale->inotneutral) return locale;
745 if ((name_entry = find_lcname_entry( locale_strings + locale->ssortlocale + 1 )))
747 return locale;
748 }
749}
750
751
752static int locale_return_data( const WCHAR *data, int datalen, LCTYPE type, WCHAR *buffer, int len )
753{
754 if (type & LOCALE_RETURN_NUMBER)
755 {
757 return 0;
758 }
759
760 if (!len) return datalen;
761 if (datalen > len)
762 {
764 return 0;
765 }
766 memcpy( buffer, data, datalen * sizeof(WCHAR) );
767 return datalen;
768}
769
770
772{
773 DWORD size = (wcslen(data) + 1) * sizeof(WCHAR);
774 LSTATUS ret;
775
776 if (size > sizeof(entry->data))
777 {
779 return FALSE;
780 }
781 TRACE( "setting %s to %s\n", debugstr_w(entry->value), debugstr_w(data) );
782
784 if (!(ret = RegSetKeyValueW( intl_key, entry->subkey, entry->value, REG_SZ, (BYTE *)data, size )))
785 {
786 wcscpy( entry->data, data );
787 entry->status = CACHED;
788 }
790 if (ret) SetLastError( ret );
791 return !ret;
792}
793
794
796{
797 DWORD size;
798 LRESULT res;
799 int ret = -1;
800
801 if (type & LOCALE_NOUSEROVERRIDE) return -1;
802
804 switch (entry->status)
805 {
806 case NOT_CACHED:
807 size = sizeof(entry->data);
808 if (entry->subkey)
809 {
810 HKEY key;
811 if (!(res = RegOpenKeyExW( intl_key, entry->subkey, 0, KEY_READ, &key )))
812 {
813 res = RegQueryValueExW( key, entry->value, NULL, NULL, (BYTE *)entry->data, &size );
814 RegCloseKey( key );
815 }
816 }
817 else res = RegQueryValueExW( intl_key, entry->value, NULL, NULL, (BYTE *)entry->data, &size );
818
819 if (res)
820 {
821 entry->status = MISSING;
822 break;
823 }
824 entry->status = CACHED;
825 /* fall through */
826 case CACHED:
827 ret = locale_return_data( entry->data, wcslen(entry->data) + 1, type, buffer, len );
828 break;
829 case MISSING:
830 break;
831 }
833 return ret;
834}
835
836
838{
840}
841
842
844{
845 int ret;
846 WCHAR tmp[80];
847
848 if (!(type & LOCALE_RETURN_NUMBER))
849 {
850 switch (LOWORD(type))
851 {
852 case LOCALE_ILANGUAGE:
854 ret = swprintf( tmp, ARRAY_SIZE(tmp), L"%04x", val ) + 1;
855 break;
856 case LOCALE_IDEFAULTEBCDICCODEPAGE:
857 ret = swprintf( tmp, ARRAY_SIZE(tmp), L"%03u", val ) + 1;
858 break;
859 default:
860 ret = swprintf( tmp, ARRAY_SIZE(tmp), L"%u", val ) + 1;
861 break;
862 }
863 }
864 else ret = sizeof(UINT) / sizeof(WCHAR);
865
866 if (!len) return ret;
867 if (ret > len)
868 {
870 return 0;
871 }
872
873 if (type & LOCALE_RETURN_NUMBER) memcpy( buffer, &val, sizeof(val) );
874 else wcscpy( buffer, tmp );
875
876 return ret;
877}
878
879
881{
882 int ret, val;
883 WCHAR *end, tmp[80];
884
885 if (type & LOCALE_RETURN_NUMBER)
886 {
887 ret = locale_return_reg_string( entry, type & ~LOCALE_RETURN_NUMBER, tmp, ARRAY_SIZE( tmp ));
888 if (ret == -1) return ret;
889 val = wcstol( tmp, &end, 10 );
890 if (*end) /* invalid number */
891 {
893 return 0;
894 }
896 }
898}
899
900
902{
904 const WCHAR *str = locale_strings + pos + 1;
905 int ret;
906
907 if (type & LOCALE_RETURN_NUMBER)
908 {
910 return 0;
911 }
912 ret = 2 * count;
913 if (str[count - 1]) ret += 2; /* for final zero */
914
915 if (!len) return ret;
916 if (ret > len)
917 {
919 return 0;
920 }
921 for (i = 0; i < count; i++)
922 {
923 if (!str[i]) /* explicit null termination */
924 {
925 buffer[-1] = 0;
926 return ret;
927 }
928 *buffer++ = '0' + str[i];
929 *buffer++ = ';';
930 }
931 *buffer++ = '0';
932 *buffer = 0;
933 return ret;
934}
935
936
938{
939 const DWORD *array = (const DWORD *)(locale_strings + pos + 1);
941
942 return locale_return_string( idx < count ? array[idx] : 0, type, buffer, len );
943}
944
945
947{
949 const DWORD *array = (const DWORD *)(locale_strings + pos + 1);
950 int ret;
951
952 if (type & LOCALE_RETURN_NUMBER)
953 {
955 return 0;
956 }
957 for (i = 0, ret = 1; i < count; i++) ret += locale_strings[array[i]];
958
959 if (!len) return ret;
960 if (ret > len)
961 {
963 return 0;
964 }
965 for (i = 0; i < count; i++)
966 {
967 memcpy( buffer, locale_strings + array[i] + 1, locale_strings[array[i]] * sizeof(WCHAR) );
969 }
970 *buffer = 0;
971 return ret;
972}
973
974
976{
977 WCHAR tmp[12];
978 int ret;
979
980 if (type & CAL_RETURN_NUMBER)
981 {
982 *value = val;
983 return sizeof(UINT) / sizeof(WCHAR);
984 }
985 ret = swprintf( tmp, ARRAY_SIZE(tmp), L"%u", val );
986 return locale_return_data( tmp, ret + 1, 0, buffer, len );
987}
988
989
990/* find the first format char in a format string */
992{
993 for ( ; *str; str++)
994 {
995 if (*str == '\'')
996 {
997 if (!(str = wcschr( str + 1, '\'' ))) return NULL;
998 }
999 else if (wcschr( accept, *str ))
1000 {
1001 /* ignore "ddd" and "dddd" */
1002 if (str[0] != 'd' || str[1] != 'd' || str[2] != 'd') return str;
1003 str += 2;
1004 while (str[1] == 'd') str++;
1005 }
1006 }
1007 return NULL;
1008}
1009
1010
1011/* replace the separator in a date/time format string */
1013{
1014 UINT pos = 0;
1015 WCHAR res[80];
1016 WCHAR *next, *str = find_format( buffer, L"dMyHhms" );
1017
1018 if (!str) return buffer;
1019 pos = str - buffer;
1020 memcpy( res, buffer, pos * sizeof(WCHAR) );
1021 for (;;)
1022 {
1023 res[pos++] = *str++;
1024 while (str[0] == str[-1]) res[pos++] = *str++; /* copy repeated chars */
1025 if (!(next = find_format( str, L"dMyHhms" ))) break;
1026 wcscpy( res + pos, sep );
1027 pos += wcslen(sep);
1028 str = next;
1029 }
1030 wcscpy( res + pos, str );
1031 return wcscpy( buffer, res );
1032}
1033
1034
1035/* FIXME: hardcoded, sortname is apparently not available in locale.nls */
1037{
1038 switch (PRIMARYLANGID( lcid ))
1039 {
1040 case LANG_CHINESE:
1041 switch (SORTIDFROMLCID( lcid ))
1042 {
1043 case SORT_CHINESE_PRCP:
1044 switch (SUBLANGID( lcid ))
1045 {
1048 case 0x1f:
1049 return L"Stroke Count";
1050 default:
1051 return L"Pronunciation";
1052 }
1053 case SORT_CHINESE_UNICODE: return L"Unicode";
1054 case SORT_CHINESE_PRC: return L"Stroke Count";
1055 case SORT_CHINESE_BOPOMOFO: return L"Bopomofo";
1056 case SORT_CHINESE_RADICALSTROKE: return L"Radical/Stroke";
1057 case 5: return L"Surname";
1058 }
1059 break;
1060
1061 case LANG_GEORGIAN:
1062 if (SORTIDFROMLCID( lcid ) == SORT_GEORGIAN_MODERN) return L"Modern";
1063 return L"Traditional";
1064
1065 case LANG_GERMAN:
1066 switch (SUBLANGID( lcid ))
1067 {
1068 case SUBLANG_NEUTRAL:
1069 case SUBLANG_DEFAULT:
1070 if (SORTIDFROMLCID( lcid ) == SORT_GERMAN_PHONE_BOOK) return L"Phone Book (DIN)";
1071 return L"Dictionary";
1072 }
1073 break;
1074
1075 case LANG_HUNGARIAN:
1076 if (SORTIDFROMLCID( lcid ) == SORT_HUNGARIAN_TECHNICAL) return L"Technical";
1077 break;
1078
1079 case LANG_INVARIANT:
1080 if (SORTIDFROMLCID( lcid ) == SORT_INVARIANT_MATH) return L"Default";
1081 return L"Maths Alphanumerics";
1082
1083 case LANG_JAPANESE:
1084 switch (SORTIDFROMLCID( lcid ))
1085 {
1086 case SORT_JAPANESE_XJIS: return L"XJIS";
1087 case SORT_JAPANESE_UNICODE: return L"Unicode";
1088 case SORT_JAPANESE_RADICALSTROKE: return L"Radical/Stroke";
1089 }
1090 break;
1091
1092 case LANG_KOREAN:
1093 if (SORTIDFROMLCID( lcid ) == SORT_KOREAN_UNICODE) return L"Unicode";
1094 return L"Dictionary";
1095
1096 case LANG_SPANISH:
1097 switch (SUBLANGID( lcid ))
1098 {
1099 case SUBLANG_NEUTRAL:
1101 return L"International";
1102 case SUBLANG_DEFAULT:
1103 return L"Traditional";
1104 }
1105 break;
1106 }
1107 return L"Default";
1108}
1109
1110
1111/* get locale information from the locale.nls file */
1112static int get_locale_info( const NLS_LOCALE_DATA *locale, LCID lcid, LCTYPE type,
1113 WCHAR *buffer, int len )
1114{
1115 static const WCHAR spermille[] = { 0x2030, 0 }; /* this one seems hardcoded */
1116 static const BYTE ipossignposn[] = { 3, 3, 4, 2, 1, 1, 3, 4, 1, 3, 4, 2, 4, 3, 3, 1 };
1117 static const BYTE inegsignposn[] = { 0, 3, 4, 2, 0, 1, 3, 4, 1, 3, 4, 2, 4, 3, 0, 0 };
1118 static const BYTE inegsymprecedes[] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, };
1119 const WCHAR *sort;
1120 WCHAR *str, *end, tmp[80];
1121 UINT val;
1122 int ret;
1123
1125
1126 switch (LOWORD(type))
1127 {
1128 case LOCALE_ILANGUAGE:
1129 /* return default language for neutral locales */
1130 val = locale->inotneutral ? locale->ilanguage : locale->idefaultlanguage;
1131 return locale_return_number( val, type, buffer, len );
1132
1134 /* FIXME: localization */
1135 return locale_return_string( locale->sengdisplayname, type, buffer, len );
1136
1138 return locale_return_string( locale->sabbrevlangname, type, buffer, len );
1139
1141 return locale_return_string( locale->snativelangname, type, buffer, len );
1142
1143 case LOCALE_ICOUNTRY:
1144 if ((ret = locale_return_reg_number( &entry_icountry, type, buffer, len )) != -1) return ret;
1145 return locale_return_number( locale->icountry, type, buffer, len );
1146
1147 case LOCALE_SLOCALIZEDCOUNTRYNAME:
1148 /* FIXME: localization */
1149 return locale_return_string( locale->sengcountry, type, buffer, len );
1150
1152 return locale_return_string( locale->sabbrevctryname, type, buffer, len );
1153
1155 return locale_return_string( locale->snativectryname, type, buffer, len );
1156
1158 return locale_return_number( locale->idefaultlanguage, type, buffer, len );
1159
1161 return locale_return_number( locale->icountry, type, buffer, len );
1162
1164 val = locale->idefaultcodepage == CP_UTF8 ? CP_OEMCP : locale->idefaultcodepage;
1165 return locale_return_number( val, type, buffer, len );
1166
1167 case LOCALE_SLIST:
1168 if ((ret = locale_return_reg_string( &entry_slist, type, buffer, len )) != -1) return ret;
1169 return locale_return_string( locale->slist, type, buffer, len );
1170
1171 case LOCALE_IMEASURE:
1172 if ((ret = locale_return_reg_number( &entry_imeasure, type, buffer, len )) != -1) return ret;
1173 return locale_return_number( locale->imeasure, type, buffer, len );
1174
1175 case LOCALE_SDECIMAL:
1176 if ((ret = locale_return_reg_string( &entry_sdecimal, type, buffer, len )) != -1) return ret;
1177 return locale_return_string( locale->sdecimal, type, buffer, len );
1178
1179 case LOCALE_STHOUSAND:
1180 if ((ret = locale_return_reg_string( &entry_sthousand, type, buffer, len )) != -1) return ret;
1181 return locale_return_string( locale->sthousand, type, buffer, len );
1182
1183 case LOCALE_SGROUPING:
1184 if ((ret = locale_return_reg_string( &entry_sgrouping, type, buffer, len )) != -1) return ret;
1185 return locale_return_grouping( locale->sgrouping, type, buffer, len );
1186
1187 case LOCALE_IDIGITS:
1188 if ((ret = locale_return_reg_number( &entry_idigits, type, buffer, len )) != -1) return ret;
1189 return locale_return_number( locale->idigits, type, buffer, len );
1190
1191 case LOCALE_ILZERO:
1192 if ((ret = locale_return_reg_number( &entry_ilzero, type, buffer, len )) != -1) return ret;
1193 return locale_return_number( locale->ilzero, type, buffer, len );
1194
1196 if ((ret = locale_return_reg_string( &entry_snativedigits, type, buffer, len )) != -1) return ret;
1197 return locale_return_strarray_concat( locale->snativedigits, type, buffer, len );
1198
1199 case LOCALE_SCURRENCY:
1200 if ((ret = locale_return_reg_string( &entry_scurrency, type, buffer, len )) != -1) return ret;
1201 return locale_return_string( locale->scurrency, type, buffer, len );
1202
1203 case LOCALE_SINTLSYMBOL:
1204 if ((ret = locale_return_reg_string( &entry_sintlsymbol, type, buffer, len )) != -1) return ret;
1205 return locale_return_string( locale->sintlsymbol, type, buffer, len );
1206
1208 if ((ret = locale_return_reg_string( &entry_smondecimalsep, type, buffer, len )) != -1) return ret;
1209 return locale_return_string( locale->smondecimalsep, type, buffer, len );
1210
1213 return locale_return_string( locale->smonthousandsep, type, buffer, len );
1214
1216 if ((ret = locale_return_reg_string( &entry_smongrouping, type, buffer, len )) != -1) return ret;
1217 return locale_return_grouping( locale->smongrouping, type, buffer, len );
1218
1219 case LOCALE_ICURRDIGITS:
1221 if ((ret = locale_return_reg_number( &entry_icurrdigits, type, buffer, len )) != -1) return ret;
1222 return locale_return_number( locale->icurrdigits, type, buffer, len );
1223
1224 case LOCALE_ICURRENCY:
1225 if ((ret = locale_return_reg_number( &entry_icurrency, type, buffer, len )) != -1) return ret;
1226 return locale_return_number( locale->icurrency, type, buffer, len );
1227
1228 case LOCALE_INEGCURR:
1229 if ((ret = locale_return_reg_number( &entry_inegcurr, type, buffer, len )) != -1) return ret;
1230 return locale_return_number( locale->inegcurr, type, buffer, len );
1231
1232 case LOCALE_SDATE:
1234 tmp, ARRAY_SIZE( tmp ))) break;
1235 if (!(str = find_format( tmp, L"dMy" ))) break;
1236 while (str[1] == str[0]) str++; /* skip repeated chars */
1237 if (!(end = find_format( ++str, L"dMy" ))) break;
1238 *end++ = 0;
1239 return locale_return_data( str, end - str, type, buffer, len );
1240
1241 case LOCALE_STIME:
1243 tmp, ARRAY_SIZE( tmp ))) break;
1244 if (!(str = find_format( tmp, L"Hhms" ))) break;
1245 while (str[1] == str[0]) str++; /* skip repeated chars */
1246 if (!(end = find_format( ++str, L"Hhms" ))) break;
1247 *end++ = 0;
1248 return locale_return_data( str, end - str, type, buffer, len );
1249
1250 case LOCALE_SSHORTDATE:
1251 if ((ret = locale_return_reg_string( &entry_sshortdate, type, buffer, len )) != -1) return ret;
1252 return locale_return_strarray( locale->sshortdate, 0, type, buffer, len );
1253
1254 case LOCALE_SLONGDATE:
1255 if ((ret = locale_return_reg_string( &entry_slongdate, type, buffer, len )) != -1) return ret;
1256 return locale_return_strarray( locale->slongdate, 0, type, buffer, len );
1257
1258 case LOCALE_IDATE:
1260 tmp, ARRAY_SIZE( tmp ))) break;
1261 /* if both year and day are found before month, the last one takes precedence */
1262 for (val = 0, str = find_format( tmp, L"dMy" ); str; str = find_format( str + 1, L"dMy" ))
1263 {
1264 if (*str == 'M') break;
1265 val = (*str == 'y' ? 2 : 1);
1266 }
1267 return locale_return_number( val, type, buffer, len );
1268
1269 case LOCALE_ILDATE:
1271 tmp, ARRAY_SIZE( tmp ))) break;
1272 /* if both year and day are found before month, the last one takes precedence */
1273 for (val = 0, str = find_format( tmp, L"dMy" ); str; str = find_format( str + 1, L"dMy" ))
1274 {
1275 if (*str == 'M') break;
1276 val = (*str == 'y' ? 2 : 1);
1277 }
1278 return locale_return_number( val, type, buffer, len );
1279
1280 case LOCALE_ITIME:
1282 tmp, ARRAY_SIZE( tmp ))) break;
1283 if (!(str = find_format( tmp, L"Hh" ))) break;
1284 return locale_return_number( *str == 'H', type, buffer, len );
1285
1286 case LOCALE_ICENTURY:
1288 tmp, ARRAY_SIZE( tmp ))) break;
1289 if (!(str = find_format( tmp, L"y" ))) break;
1290 return locale_return_number( !wcsncmp( str, L"yyyy", 4 ), type, buffer, len );
1291
1292 case LOCALE_ITLZERO:
1294 tmp, ARRAY_SIZE( tmp ))) break;
1295 if (!(str = find_format( tmp, L"Hh" ))) break;
1296 return locale_return_number( str[1] == str[0], type, buffer, len );
1297
1298 case LOCALE_IDAYLZERO:
1300 tmp, ARRAY_SIZE( tmp ))) break;
1301 if (!(str = find_format( tmp, L"d" ))) break;
1302 return locale_return_number( str[1] == 'd', type, buffer, len );
1303
1304 case LOCALE_IMONLZERO:
1306 tmp, ARRAY_SIZE( tmp ))) break;
1307 if (!(str = find_format( tmp, L"M" ))) break;
1308 return locale_return_number( str[1] == 'M', type, buffer, len );
1309
1310 case LOCALE_S1159:
1311 if ((ret = locale_return_reg_string( &entry_s1159, type, buffer, len )) != -1) return ret;
1312 return locale_return_string( locale->s1159, type, buffer, len );
1313
1314 case LOCALE_S2359:
1315 if ((ret = locale_return_reg_string( &entry_s2359, type, buffer, len )) != -1) return ret;
1316 return locale_return_string( locale->s2359, type, buffer, len );
1317
1318 case LOCALE_SDAYNAME1:
1319 case LOCALE_SDAYNAME2:
1320 case LOCALE_SDAYNAME3:
1321 case LOCALE_SDAYNAME4:
1322 case LOCALE_SDAYNAME5:
1323 case LOCALE_SDAYNAME6:
1324 case LOCALE_SDAYNAME7:
1325 return locale_return_strarray( locale->sdayname,
1326 LOWORD(type - LOCALE_SDAYNAME1 + 1) % 7, type, buffer, len );
1327
1335 return locale_return_strarray( locale->sabbrevdayname,
1337
1338 case LOCALE_SMONTHNAME1:
1339 case LOCALE_SMONTHNAME2:
1340 case LOCALE_SMONTHNAME3:
1341 case LOCALE_SMONTHNAME4:
1342 case LOCALE_SMONTHNAME5:
1343 case LOCALE_SMONTHNAME6:
1344 case LOCALE_SMONTHNAME7:
1345 case LOCALE_SMONTHNAME8:
1346 case LOCALE_SMONTHNAME9:
1350 return locale_return_strarray( ((type & LOCALE_RETURN_GENITIVE_NAMES) && locale->sgenitivemonth) ?
1351 locale->sgenitivemonth : locale->smonthname,
1353
1366 return locale_return_strarray( ((type & LOCALE_RETURN_GENITIVE_NAMES) && locale->sabbrevgenitivemonth) ?
1367 locale->sabbrevgenitivemonth : locale->sabbrevmonthname,
1369
1371 if ((ret = locale_return_reg_string( &entry_spositivesign, type, buffer, len )) != -1) return ret;
1372 return locale_return_string( locale->spositivesign, type, buffer, len );
1373
1375 if ((ret = locale_return_reg_string( &entry_snegativesign, type, buffer, len )) != -1) return ret;
1376 return locale_return_string( locale->snegativesign, type, buffer, len );
1377
1380 LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1381 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1382 return locale_return_number( ipossignposn[val], type, buffer, len );
1383
1386 LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1387 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1388 return locale_return_number( inegsignposn[val], type, buffer, len );
1389
1392 LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1393 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1394 return locale_return_number( !(val & 1), type, buffer, len );
1395
1398 LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1399 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1400 return locale_return_number( !!(val & 2), type, buffer, len );
1401
1404 LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1405 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1406 return locale_return_number( inegsymprecedes[val], type, buffer, len );
1407
1410 LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | (type & LOCALE_NOUSEROVERRIDE),
1411 (WCHAR *)&val, sizeof(val)/sizeof(WCHAR) )) break;
1412 return locale_return_number( (val >= 8), type, buffer, len );
1413
1415 return locale_return_data( locale_strings + locale->fontsignature + 1,
1416 locale_strings[locale->fontsignature], type, buffer, len );
1417
1419 return locale_return_string( locale->siso639langname, type, buffer, len );
1420
1422 return locale_return_string( locale->siso3166ctryname, type, buffer, len );
1423
1424 case LOCALE_IGEOID:
1425 return locale_return_number( locale->igeoid, type, buffer, len );
1426
1427 case LOCALE_SNAME:
1428 if (SORTIDFROMLCID(lcid)) /* custom sort locale */
1429 {
1430 const NLS_LOCALE_LCID_INDEX *entry = find_lcid_entry( lcid & ~0x80000000 );
1431 if (entry) return locale_return_string( entry->name, type, buffer, len );
1432 }
1433 return locale_return_string( locale->sname, type, buffer, len );
1434
1435 case LOCALE_SDURATION:
1436 return locale_return_strarray( locale->sduration, 0, type, buffer, len );
1437
1438 case LOCALE_SKEYBOARDSTOINSTALL:
1439 return locale_return_string( locale->skeyboardstoinstall, type, buffer, len );
1440
1441 case LOCALE_SSHORTESTDAYNAME1:
1442 case LOCALE_SSHORTESTDAYNAME2:
1443 case LOCALE_SSHORTESTDAYNAME3:
1444 case LOCALE_SSHORTESTDAYNAME4:
1445 case LOCALE_SSHORTESTDAYNAME5:
1446 case LOCALE_SSHORTESTDAYNAME6:
1447 case LOCALE_SSHORTESTDAYNAME7:
1448 return locale_return_strarray( locale->sshortestdayname,
1449 LOWORD(type - LOCALE_SSHORTESTDAYNAME1 + 1) % 7, type, buffer, len );
1450
1451 case LOCALE_SISO639LANGNAME2:
1452 return locale_return_string( locale->siso639langname2, type, buffer, len );
1453
1454 case LOCALE_SISO3166CTRYNAME2:
1455 return locale_return_string( locale->siso3166ctryname2, type, buffer, len );
1456
1457 case LOCALE_SNAN:
1458 return locale_return_string( locale->snan, type, buffer, len );
1459
1460 case LOCALE_SPOSINFINITY:
1461 return locale_return_string( locale->sposinfinity, type, buffer, len );
1462
1463 case LOCALE_SNEGINFINITY:
1464 return locale_return_string( locale->sneginfinity, type, buffer, len );
1465
1466 case LOCALE_SSCRIPTS:
1467 return locale_return_string( locale->sscripts, type, buffer, len );
1468
1469 case LOCALE_SPARENT:
1470 return locale_return_string( locale->sparent, type, buffer, len );
1471
1472 case LOCALE_SCONSOLEFALLBACKNAME:
1473 return locale_return_string( locale->sconsolefallbackname, type, buffer, len );
1474
1476 /* FIXME: localization */
1477 return locale_return_string( locale->senglanguage, type, buffer, len );
1478
1480 return locale_return_number( locale->ireadinglayout, type, buffer, len );
1481
1482 case LOCALE_INEUTRAL:
1483 return locale_return_number( !locale->inotneutral, type, buffer, len );
1484
1485 case LOCALE_SENGLISHDISPLAYNAME:
1486 return locale_return_string( locale->sengdisplayname, type, buffer, len );
1487
1489 return locale_return_string( locale->snativedisplayname, type, buffer, len );
1490
1492 return locale_return_number( locale->inegativepercent, type, buffer, len );
1493
1495 return locale_return_number( locale->ipositivepercent, type, buffer, len );
1496
1497 case LOCALE_SPERCENT:
1498 return locale_return_string( locale->spercent, type, buffer, len );
1499
1500 case LOCALE_SPERMILLE:
1501 return locale_return_data( spermille, ARRAY_SIZE(spermille), type, buffer, len );
1502
1503 case LOCALE_SMONTHDAY:
1504 return locale_return_strarray( locale->smonthday, 0, type, buffer, len );
1505
1506 case LOCALE_SSHORTTIME:
1507 if ((ret = locale_return_reg_string( &entry_sshorttime, type, buffer, len )) != -1) return ret;
1508 return locale_return_strarray( locale->sshorttime, 0, type, buffer, len );
1509
1511 return locale_return_string( locale->sopentypelanguagetag, type, buffer, len );
1512
1513 case LOCALE_SSORTLOCALE:
1514 if (SORTIDFROMLCID(lcid)) /* custom sort locale */
1515 {
1516 const NLS_LOCALE_LCID_INDEX *entry = find_lcid_entry( lcid & ~0x80000000 );
1517 if (entry) return locale_return_string( entry->name, type, buffer, len );
1518 }
1519 return locale_return_string( locale->ssortlocale, type, buffer, len );
1520
1522 return locale_return_string( locale->srelativelongdate, type, buffer, len );
1523
1524 case 0x007d: /* undocumented */
1525 return locale_return_number( 0, type, buffer, len );
1526
1527 case LOCALE_SSHORTESTAM:
1528 return locale_return_string( locale->sshortestam, type, buffer, len );
1529
1530 case LOCALE_SSHORTESTPM:
1531 return locale_return_string( locale->sshortestpm, type, buffer, len );
1532
1534 return locale_return_string( locale->senglanguage, type, buffer, len );
1535
1536 case LOCALE_SENGCOUNTRY:
1537 return locale_return_string( locale->sengcountry, type, buffer, len );
1538
1539 case LOCALE_STIMEFORMAT:
1540 if ((ret = locale_return_reg_string( &entry_stimeformat, type, buffer, len )) != -1) return ret;
1541 return locale_return_strarray( locale->stimeformat, 0, type, buffer, len );
1542
1544 val = locale->idefaultansicodepage == CP_UTF8 ? CP_ACP : locale->idefaultansicodepage;
1545 return locale_return_number( val, type, buffer, len );
1546
1549 tmp, ARRAY_SIZE( tmp ))) break;
1550 if (!(str = find_format( tmp, L"Hhmst" ))) break;
1551 return locale_return_number( *str == 't', type, buffer, len );
1552
1553 case LOCALE_SYEARMONTH:
1554 if ((ret = locale_return_reg_string( &entry_syearmonth, type, buffer, len )) != -1) return ret;
1555 return locale_return_strarray( locale->syearmonth, 0, type, buffer, len );
1556
1557 case LOCALE_SENGCURRNAME:
1558 return locale_return_string( locale->sengcurrname, type, buffer, len );
1559
1560 case LOCALE_SNATIVECURRNAME:
1561 return locale_return_string( locale->snativecurrname, type, buffer, len );
1562
1564 if ((ret = locale_return_reg_number( &entry_icalendartype, type, buffer, len )) != -1) return ret;
1565 return locale_return_number( locale_strings[locale->scalendartype + 1], type, buffer, len );
1566
1567 case LOCALE_IPAPERSIZE:
1568 if ((ret = locale_return_reg_number( &entry_ipapersize, type, buffer, len )) != -1) return ret;
1569 return locale_return_number( locale->ipapersize, type, buffer, len );
1570
1572 return locale_return_number( locale_strings[locale->scalendartype + 2], type, buffer, len );
1573
1576 return locale_return_number( (locale->ifirstdayofweek + 6) % 7, type, buffer, len );
1577
1580 return locale_return_number( locale->ifirstweekofyear, type, buffer, len );
1581
1583 return locale_return_strarray( ((type & LOCALE_RETURN_GENITIVE_NAMES) && locale->sgenitivemonth) ?
1584 locale->sgenitivemonth : locale->smonthname,
1585 12, type, buffer, len );
1586
1588 return locale_return_strarray( ((type & LOCALE_RETURN_GENITIVE_NAMES) && locale->sabbrevgenitivemonth) ?
1589 locale->sabbrevgenitivemonth : locale->sabbrevmonthname,
1590 12, type, buffer, len );
1591
1592 case LOCALE_INEGNUMBER:
1593 if ((ret = locale_return_reg_number( &entry_inegnumber, type, buffer, len )) != -1) return ret;
1594 return locale_return_number( locale->inegnumber, type, buffer, len );
1595
1597 val = locale->idefaultmaccodepage == CP_UTF8 ? CP_MACCP : locale->idefaultmaccodepage;
1598 return locale_return_number( val, type, buffer, len );
1599
1600 case LOCALE_IDEFAULTEBCDICCODEPAGE:
1601 return locale_return_number( locale->idefaultebcdiccodepage, type, buffer, len );
1602
1603 case LOCALE_SSORTNAME:
1605 return locale_return_data( sort, wcslen(sort) + 1, type, buffer, len );
1606
1607 case LOCALE_IDIGITSUBSTITUTION:
1609 return locale_return_number( locale->idigitsubstitution, type, buffer, len );
1610 }
1612 return 0;
1613}
1614
1615
1616/* get calendar information from the locale.nls file */
1617static int get_calendar_info( const NLS_LOCALE_DATA *locale, CALID id, CALTYPE type,
1618 WCHAR *buffer, int len, DWORD *value )
1619{
1620 unsigned int i, val = 0;
1621 const struct calendar *cal;
1622
1623 if (type & CAL_RETURN_NUMBER)
1624 {
1625 if (buffer || len || !value) goto invalid;
1626 }
1627 else if (len < 0 || value) goto invalid;
1628
1629 if (id != CAL_GREGORIAN && type != CAL_ITWODIGITYEARMAX)
1630 {
1631 const USHORT *ids = locale_strings + locale->scalendartype;
1632 for (i = 0; i < ids[0]; i++) if (ids[1 + i] == id) break;
1633 if (i == ids[0]) goto invalid;
1634 }
1635 if (!(cal = get_calendar_data( locale, id ))) goto invalid;
1636
1637 switch (LOWORD(type))
1638 {
1639 case CAL_ICALINTVALUE:
1641
1642 case CAL_SCALNAME:
1643 return locale_return_strarray( locale->calnames, id - 1, type, buffer, len );
1644
1646 if (cal->iyearoffsetrange)
1647 {
1648 const DWORD *array = (const DWORD *)(locale_strings + cal->iyearoffsetrange + 1);
1649 const short *info = (const short *)locale_strings + array[0];
1650 val = (info[5] < 0) ? -info[5] : info[5] + 1; /* year zero */
1651 }
1652 return cal_return_number( val, type, buffer, len, value );
1653
1654 case CAL_SERASTRING:
1655 if (id == CAL_GREGORIAN) return locale_return_string( locale->serastring, type, buffer, len );
1656 if (cal->iyearoffsetrange)
1657 {
1658 const DWORD *array = (const DWORD *)(locale_strings + cal->iyearoffsetrange + 1);
1659 const short *info = (const short *)locale_strings + array[0];
1660 val = info[1] - 1;
1661 }
1663
1664 case CAL_SSHORTDATE:
1665 val = (id == CAL_GREGORIAN) ? locale->sshortdate : cal->sshortdate;
1666 return locale_return_strarray( val, 0, type, buffer, len );
1667
1668 case CAL_SLONGDATE:
1669 val = (id == CAL_GREGORIAN) ? locale->slongdate : cal->slongdate;
1670 return locale_return_strarray( val, 0, type, buffer, len );
1671
1672 case CAL_SDAYNAME1:
1673 case CAL_SDAYNAME2:
1674 case CAL_SDAYNAME3:
1675 case CAL_SDAYNAME4:
1676 case CAL_SDAYNAME5:
1677 case CAL_SDAYNAME6:
1678 case CAL_SDAYNAME7:
1679 val = (id == CAL_GREGORIAN) ? locale->sdayname : cal->sdayname;
1680 return locale_return_strarray( val, (LOWORD(type) - CAL_SDAYNAME1 + 1) % 7, type, buffer, len );
1681
1689 val = (id == CAL_GREGORIAN) ? locale->sabbrevdayname : cal->sabbrevdayname;
1691 case CAL_SMONTHNAME1:
1692 case CAL_SMONTHNAME2:
1693 case CAL_SMONTHNAME3:
1694 case CAL_SMONTHNAME4:
1695 case CAL_SMONTHNAME5:
1696 case CAL_SMONTHNAME6:
1697 case CAL_SMONTHNAME7:
1698 case CAL_SMONTHNAME8:
1699 case CAL_SMONTHNAME9:
1700 case CAL_SMONTHNAME10:
1701 case CAL_SMONTHNAME11:
1702 case CAL_SMONTHNAME12:
1703 case CAL_SMONTHNAME13:
1704 if (id != CAL_GREGORIAN) val = cal->smonthname;
1705 else if ((type & CAL_RETURN_GENITIVE_NAMES) && locale->sgenitivemonth) val = locale->sgenitivemonth;
1706 else val = locale->smonthname;
1708
1722 if (id != CAL_GREGORIAN) val = cal->sabbrevmonthname;
1723 else if ((type & CAL_RETURN_GENITIVE_NAMES) && locale->sabbrevgenitivemonth) val = locale->sabbrevgenitivemonth;
1724 else val = locale->sabbrevmonthname;
1726
1727 case CAL_SYEARMONTH:
1728 val = (id == CAL_GREGORIAN) ? locale->syearmonth : cal->syearmonth;
1729 return locale_return_strarray( val, 0, type, buffer, len );
1730
1731 case CAL_ITWODIGITYEARMAX:
1733
1734 case CAL_SSHORTESTDAYNAME1:
1735 case CAL_SSHORTESTDAYNAME2:
1736 case CAL_SSHORTESTDAYNAME3:
1737 case CAL_SSHORTESTDAYNAME4:
1738 case CAL_SSHORTESTDAYNAME5:
1739 case CAL_SSHORTESTDAYNAME6:
1740 case CAL_SSHORTESTDAYNAME7:
1741 val = (id == CAL_GREGORIAN) ? locale->sshortestdayname : cal->sshortestdayname;
1742 return locale_return_strarray( val, (LOWORD(type) - CAL_SSHORTESTDAYNAME1 + 1) % 7, type, buffer, len );
1743
1744 case CAL_SMONTHDAY:
1745 val = (id == CAL_GREGORIAN) ? locale->smonthday : cal->smonthday;
1746 return locale_return_strarray( val, 0, type, buffer, len );
1747
1749 if (id == CAL_GREGORIAN) return locale_return_string( locale->sabbreverastring, type, buffer, len );
1750 if (cal->iyearoffsetrange)
1751 {
1752 const DWORD *array = (const DWORD *)(locale_strings + cal->iyearoffsetrange + 1);
1753 const short *info = (const short *)locale_strings + array[0];
1754 val = info[1] - 1;
1755 }
1757
1758 case CAL_SRELATIVELONGDATE:
1759 val = (id == CAL_GREGORIAN) ? locale->srelativelongdate : cal->srelativelongdate;
1760 return locale_return_string( val, type, buffer, len );
1761
1762 case CAL_SENGLISHERANAME:
1763 case CAL_SENGLISHABBREVERANAME:
1764 /* not supported on Windows */
1765 break;
1766 }
1768 return 0;
1769
1770invalid:
1772 return 0;
1773}
1774
1775
1776/* get geo information from the locale.nls file */
1777static int get_geo_info( const struct geo_id *geo, enum SYSGEOTYPE type,
1778 WCHAR *buffer, int len, LANGID lang )
1779{
1780 WCHAR tmp[12];
1781 const WCHAR *str = tmp;
1782 int ret;
1783
1784 switch (type)
1785 {
1786 case GEO_NATION:
1787 if (geo->class != GEOCLASS_NATION) return 0;
1788 /* fall through */
1789 case GEO_ID:
1790 swprintf( tmp, ARRAY_SIZE(tmp), L"%u", geo->id );
1791 break;
1792 case GEO_ISO_UN_NUMBER:
1793 swprintf( tmp, ARRAY_SIZE(tmp), L"%03u", geo->uncode );
1794 break;
1795 case GEO_PARENT:
1796 swprintf( tmp, ARRAY_SIZE(tmp), L"%u", geo->parent );
1797 break;
1798 case GEO_DIALINGCODE:
1799 swprintf( tmp, ARRAY_SIZE(tmp), L"%u", geo->dialcode );
1800 break;
1801 case GEO_ISO2:
1802 str = geo->iso2;
1803 break;
1804 case GEO_ISO3:
1805 str = geo->iso3;
1806 break;
1807 case GEO_LATITUDE:
1808 str = geo->latitude;
1809 break;
1810 case GEO_LONGITUDE:
1811 str = geo->longitude;
1812 break;
1813 case GEO_CURRENCYCODE:
1814 str = geo->currcode;
1815 break;
1816 case GEO_CURRENCYSYMBOL:
1817 str = geo->currsymbol;
1818 break;
1819 case GEO_RFC1766:
1820 case GEO_LCID:
1821 case GEO_FRIENDLYNAME:
1822 case GEO_OFFICIALNAME:
1823 case GEO_TIMEZONES:
1825 case GEO_NAME:
1826 FIXME( "type %u is not supported\n", type );
1828 return 0;
1829 default:
1831 return 0;
1832 }
1833
1834 ret = lstrlenW(str) + 1;
1835 if (!buffer || !len) return ret;
1836
1837 memcpy( buffer, str, min( ret, len ) * sizeof(WCHAR) );
1839 return len < ret ? 0 : ret;
1840}
1841
1842
1843/* update a registry value based on the current user locale info */
1844static void update_registry_value( UINT type, const WCHAR *subkey, const WCHAR *value )
1845{
1846 WCHAR buffer[80];
1848 if (len) RegSetKeyValueW( intl_key, subkey, value, REG_SZ, (BYTE *)buffer, len * sizeof(WCHAR) );
1849}
1850
1851
1852/* update all registry values upon user locale change */
1853static void update_locale_registry(void)
1854{
1855 WCHAR buffer[80];
1856 UINT len;
1857
1859 RegSetValueExW( intl_key, L"Locale", 0, REG_SZ, (BYTE *)buffer, (len + 1) * sizeof(WCHAR) );
1860
1861#define UPDATE(val,entry) update_registry_value( LOCALE_NOUSEROVERRIDE | (val), (entry).subkey, (entry).value )
1867 UPDATE( LOCALE_IDIGITSUBSTITUTION, entry_idigitsubstitution );
1874 UPDATE( LOCALE_IPAPERSIZE, entry_ipapersize );
1893 UPDATE( LOCALE_SYEARMONTH, entry_syearmonth );
1894#undef UPDATE
1904 SetUserGeoID( user_locale->igeoid );
1905}
1906
1907
1908/***********************************************************************
1909 * init_locale
1910 */
1912{
1913 USHORT utf8[2] = { 0, CP_UTF8 };
1914 USHORT *ansi_ptr, *oem_ptr;
1917 const WCHAR *user_locale_name;
1918 DWORD count;
1919 SIZE_T size;
1920 HKEY hkey;
1921
1925
1928
1930 if (!(user_locale = NlsValidateLocale( &user_lcid, 0 )))
1931 {
1932 if (GetEnvironmentVariableW( L"WINEUSERLOCALE", bufferW, ARRAY_SIZE(bufferW) ))
1935 }
1936 user_lcid = user_locale->ilanguage;
1938
1939 if (GetEnvironmentVariableW( L"WINEUNIXCP", bufferW, ARRAY_SIZE(bufferW) ))
1940 unix_cp = wcstoul( bufferW, NULL, 10 );
1941
1943
1944 ansi_ptr = NtCurrentTeb()->Peb->AnsiCodePageData ? NtCurrentTeb()->Peb->AnsiCodePageData : utf8;
1945 oem_ptr = NtCurrentTeb()->Peb->OemCodePageData ? NtCurrentTeb()->Peb->OemCodePageData : utf8;
1946 RtlInitCodePageTable( ansi_ptr, &ansi_cpinfo );
1947 RtlInitCodePageTable( oem_ptr, &oem_cpinfo );
1948
1949 RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Nls",
1951 RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
1953 RegCreateKeyExW( HKEY_CURRENT_USER, L"Control Panel\\International",
1955
1957
1959 !RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\TimeZoneInformation",
1961 {
1962 RegSetValueExW( hkey, L"StandardName", 0, REG_SZ, (BYTE *)timezone.StandardName,
1963 (lstrlenW(timezone.StandardName) + 1) * sizeof(WCHAR) );
1964 RegSetValueExW( hkey, L"TimeZoneKeyName", 0, REG_SZ, (BYTE *)timezone.TimeZoneKeyName,
1965 (lstrlenW(timezone.TimeZoneKeyName) + 1) * sizeof(WCHAR) );
1966 RegCloseKey( hkey );
1967 }
1968
1969 /* Update registry contents if the user locale has changed.
1970 * This simulates the action of the Windows control panel. */
1971
1972 user_locale_name = locale_strings + user_locale->sname + 1;
1973 count = sizeof(bufferW);
1974 if (!RegQueryValueExW( intl_key, L"LocaleName", NULL, NULL, (BYTE *)bufferW, &count ))
1975 {
1976 if (!wcscmp( bufferW, user_locale_name )) return; /* unchanged */
1977 TRACE( "updating registry, locale changed %s -> %s\n",
1978 debugstr_w(bufferW), debugstr_w(user_locale_name) );
1979 }
1980 else TRACE( "updating registry, locale changed none -> %s\n", debugstr_w(user_locale_name) );
1981
1983
1984 if (!RegCreateKeyExW( nls_key, L"Codepage",
1986 {
1987 count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", GetACP() );
1988 RegSetValueExW( hkey, L"ACP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) );
1989 count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", GetOEMCP() );
1990 RegSetValueExW( hkey, L"OEMCP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) );
1991 count = swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03d", system_locale->idefaultmaccodepage );
1992 RegSetValueExW( hkey, L"MACCP", 0, REG_SZ, (BYTE *)bufferW, (count + 1) * sizeof(WCHAR) );
1993 RegCloseKey( hkey );
1994 }
1995}
1996
1997
1998static inline WCHAR casemap( const USHORT *table, WCHAR ch )
1999{
2000 return ch + table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)];
2001}
2002
2003
2004static inline unsigned int casemap_high( const USHORT *table, WCHAR high, WCHAR low )
2005{
2006 unsigned int off = table[table[256 + (high - 0xd800)] + ((low >> 5) & 0x1f)] + 2 * (low & 0x1f);
2007 return 0x10000 + ((high - 0xd800) << 10) + (low - 0xdc00) + MAKELONG( table[off], table[off+1] );
2008}
2009
2010
2012{
2013 return table[0] >= 0x500;
2014}
2015
2016
2017static inline int put_utf16( WCHAR *dst, int pos, int dstlen, unsigned int ch )
2018{
2019 if (ch >= 0x10000)
2020 {
2021 if (pos < dstlen - 1)
2022 {
2023 ch -= 0x10000;
2024 dst[pos] = 0xd800 | (ch >> 10);
2025 dst[pos + 1] = 0xdc00 | (ch & 0x3ff);
2026 }
2027 return 2;
2028 }
2029 if (pos < dstlen) dst[pos] = ch;
2030 return 1;
2031}
2032
2033
2034static inline WORD get_char_type( DWORD type, WCHAR ch )
2035{
2036 const BYTE *ptr = sort.ctype_idx + ((const WORD *)sort.ctype_idx)[ch >> 8];
2037 ptr = sort.ctype_idx + ((const WORD *)ptr)[(ch >> 4) & 0x0f] + (ch & 0x0f);
2038 return sort.ctypes[*ptr * 3 + type / 2];
2039}
2040
2041
2042static inline void map_byterev( const WCHAR *src, int len, WCHAR *dst )
2043{
2044 while (len--) *dst++ = RtlUshortByteSwap( *src++ );
2045}
2046
2047
2048static int casemap_string( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
2049{
2051 {
2052 unsigned int ch;
2053 int pos = 0;
2054
2055 while (srclen)
2056 {
2057 if (srclen > 1 && IS_SURROGATE_PAIR( src[0], src[1] ))
2058 {
2059 ch = casemap_high( table, src[0], src[1] );
2060 src += 2;
2061 srclen -= 2;
2062 }
2063 else
2064 {
2065 ch = casemap( table, *src );
2066 src++;
2067 srclen--;
2068 }
2069 pos += put_utf16( dst, pos, dstlen, ch );
2070 }
2071 return pos;
2072 }
2073 else
2074 {
2075 int pos, ret = srclen;
2076
2077 for (pos = 0; pos < dstlen && srclen; pos++, src++, srclen--)
2078 dst[pos] = casemap( table, *src );
2079 return ret;
2080 }
2081}
2082
2083
2085{
2086 union char_weights ret;
2087
2088 ret.val = except ? sort.keys[sort.keys[except + (c >> 8)] + (c & 0xff)] : sort.keys[c];
2089 return ret;
2090}
2091
2092
2094{
2095 return (val << count) | (val >> (8 - count));
2096}
2097
2098
2099static BYTE get_char_props( const struct norm_table *info, unsigned int ch )
2100{
2101 const BYTE *level1 = (const BYTE *)((const USHORT *)info + info->props_level1);
2102 const BYTE *level2 = (const BYTE *)((const USHORT *)info + info->props_level2);
2103 BYTE off = level1[ch / 128];
2104
2105 if (!off || off >= 0xfb) return rol( off, 5 );
2106 return level2[(off - 1) * 128 + ch % 128];
2107}
2108
2109
2110static const WCHAR *get_decomposition( WCHAR ch, unsigned int *ret_len )
2111{
2112 const struct pair { WCHAR src; USHORT dst; } *pairs;
2113 const USHORT *hash_table = (const USHORT *)norm_info + norm_info->decomp_hash;
2114 const WCHAR *ret;
2115 unsigned int i, pos, end, len, hash;
2116
2117 *ret_len = 1;
2118 hash = ch % norm_info->decomp_size;
2119 pos = hash_table[hash];
2120 if (pos >> 13)
2121 {
2122 if (get_char_props( norm_info, ch ) != 0xbf) return NULL;
2123 ret = (const USHORT *)norm_info + norm_info->decomp_seq + (pos & 0x1fff);
2124 len = pos >> 13;
2125 }
2126 else
2127 {
2128 pairs = (const struct pair *)((const USHORT *)norm_info + norm_info->decomp_map);
2129
2130 /* find the end of the hash bucket */
2131 for (i = hash + 1; i < norm_info->decomp_size; i++) if (!(hash_table[i] >> 13)) break;
2132 if (i < norm_info->decomp_size) end = hash_table[i];
2133 else for (end = pos; pairs[end].src; end++) ;
2134
2135 for ( ; pos < end; pos++)
2136 {
2137 if (pairs[pos].src != (WCHAR)ch) continue;
2138 ret = (const USHORT *)norm_info + norm_info->decomp_seq + (pairs[pos].dst & 0x1fff);
2139 len = pairs[pos].dst >> 13;
2140 break;
2141 }
2142 if (pos >= end) return NULL;
2143 }
2144
2145 if (len == 7) while (ret[len]) len++;
2146 if (!ret[0]) len = 0; /* ignored char */
2147 *ret_len = len;
2148 return ret;
2149}
2150
2151
2152static WCHAR compose_chars( WCHAR ch1, WCHAR ch2 )
2153{
2154 const USHORT *table = (const USHORT *)norm_info + norm_info->comp_hash;
2155 const WCHAR *chars = (const USHORT *)norm_info + norm_info->comp_seq;
2156 unsigned int hash, start, end, i;
2157 WCHAR ch[3];
2158
2159 hash = (ch1 + 95 * ch2) % norm_info->comp_size;
2160 start = table[hash];
2161 end = table[hash + 1];
2162 while (start < end)
2163 {
2164 for (i = 0; i < 3; i++, start++)
2165 {
2166 ch[i] = chars[start];
2167 if (IS_HIGH_SURROGATE( ch[i] )) start++;
2168 }
2169 if (ch[0] == ch1 && ch[1] == ch2) return ch[2];
2170 }
2171 return 0;
2172}
2173
2174
2175static UINT get_locale_codepage( const NLS_LOCALE_DATA *locale, ULONG flags )
2176{
2177 UINT ret = locale->idefaultansicodepage;
2179 return ret;
2180}
2181
2182
2184{
2186
2187 if (!(flags & LOCALE_USE_CP_ACP) && lcid != system_lcid)
2188 {
2189 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
2190 if (locale) ret = locale->idefaultansicodepage;
2191 }
2192 return ret;
2193}
2194
2195
2197{
2198 static const CPTABLEINFO utf7_cpinfo = { CP_UTF7, 5, '?', 0xfffd, '?', '?' };
2199 static const CPTABLEINFO utf8_cpinfo = { CP_UTF8, 4, '?', 0xfffd, '?', '?' };
2200 unsigned int i;
2201 USHORT *ptr;
2202 SIZE_T size;
2203
2204 switch (codepage)
2205 {
2206 case CP_ACP:
2207 return &ansi_cpinfo;
2208 case CP_OEMCP:
2209 return &oem_cpinfo;
2210 case CP_MACCP:
2211 codepage = system_locale->idefaultmaccodepage;
2212 break;
2213 case CP_THREAD_ACP:
2214 codepage = get_lcid_codepage( NtCurrentTeb()->CurrentLocale, 0 );
2215 break;
2216 }
2217 if (codepage == ansi_cpinfo.CodePage) return &ansi_cpinfo;
2218 if (codepage == oem_cpinfo.CodePage) return &oem_cpinfo;
2219 if (codepage == CP_UTF8) return &utf8_cpinfo;
2220 if (codepage == CP_UTF7) return &utf7_cpinfo;
2221
2223
2224 for (i = 0; i < nb_codepages; i++) if (codepages[i].CodePage == codepage) goto done;
2225
2226 if (i == ARRAY_SIZE( codepages ))
2227 {
2229 ERR( "too many codepages\n" );
2230 return NULL;
2231 }
2232 if (NtGetNlsSectionPtr( 11, codepage, NULL, (void **)&ptr, &size ))
2233 {
2236 return NULL;
2237 }
2239 nb_codepages++;
2240done:
2242 return &codepages[i];
2243}
2244
2245
2246static const WCHAR *get_ligature( WCHAR wc )
2247{
2248 int low = 0, high = ARRAY_SIZE( ligatures ) -1;
2249 while (low <= high)
2250 {
2251 int pos = (low + high) / 2;
2252 if (ligatures[pos][0] < wc) low = pos + 1;
2253 else if (ligatures[pos][0] > wc) high = pos - 1;
2254 else return ligatures[pos] + 1;
2255 }
2256 return NULL;
2257}
2258
2259
2261{
2262 int i, len, pos = 0;
2264 const WCHAR *expand;
2265
2266 for (i = 0; i < srclen; i++)
2267 {
2268 if (!(expand = get_ligature( src[i] )))
2269 {
2270 expand = src + i;
2271 len = 1;
2272 }
2273 else len = lstrlenW( expand );
2274
2275 if (*dstlen && ret == STATUS_SUCCESS)
2276 {
2277 if (pos + len <= *dstlen) memcpy( dst + pos, expand, len * sizeof(WCHAR) );
2279 }
2280 pos += len;
2281 }
2282 *dstlen = pos;
2283 return ret;
2284}
2285
2286
2287static NTSTATUS fold_digits( const WCHAR *src, int srclen, WCHAR *dst, int *dstlen )
2288{
2291
2293 *dstlen = len;
2294 return ret;
2295}
2296
2297
2299{
2300 NTSTATUS ret;
2301 WCHAR *tmp;
2302
2303 switch (flags)
2304 {
2305 case MAP_PRECOMPOSED:
2306 return RtlNormalizeString( NormalizationC, src, srclen, dst, dstlen );
2307 case MAP_FOLDCZONE:
2309 return RtlNormalizeString( NormalizationKC, src, srclen, dst, dstlen );
2310 case MAP_COMPOSITE:
2311 return RtlNormalizeString( NormalizationD, src, srclen, dst, dstlen );
2313 return RtlNormalizeString( NormalizationKD, src, srclen, dst, dstlen );
2314 case MAP_FOLDDIGITS:
2315 return fold_digits( src, srclen, dst, dstlen );
2316 case MAP_EXPAND_LIGATURES:
2317 case MAP_EXPAND_LIGATURES | MAP_FOLDCZONE:
2318 return expand_ligatures( src, srclen, dst, dstlen );
2320 if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
2321 return STATUS_NO_MEMORY;
2322 fold_digits( src, srclen, tmp, &srclen );
2323 ret = RtlNormalizeString( NormalizationC, tmp, srclen, dst, dstlen );
2324 break;
2327 if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
2328 return STATUS_NO_MEMORY;
2329 fold_digits( src, srclen, tmp, &srclen );
2330 ret = RtlNormalizeString( NormalizationKC, tmp, srclen, dst, dstlen );
2331 break;
2333 if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
2334 return STATUS_NO_MEMORY;
2335 fold_digits( src, srclen, tmp, &srclen );
2336 ret = RtlNormalizeString( NormalizationD, tmp, srclen, dst, dstlen );
2337 break;
2339 if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
2340 return STATUS_NO_MEMORY;
2341 fold_digits( src, srclen, tmp, &srclen );
2342 ret = RtlNormalizeString( NormalizationKD, tmp, srclen, dst, dstlen );
2343 break;
2344 case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS:
2345 case MAP_EXPAND_LIGATURES | MAP_FOLDDIGITS | MAP_FOLDCZONE:
2346 if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0, srclen * sizeof(WCHAR) )))
2347 return STATUS_NO_MEMORY;
2348 fold_digits( src, srclen, tmp, &srclen );
2349 ret = expand_ligatures( tmp, srclen, dst, dstlen );
2350 break;
2351 default:
2353 }
2354 RtlFreeHeap( GetProcessHeap(), 0, tmp );
2355 return ret;
2356}
2357
2358
2359static int mbstowcs_cpsymbol( DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen )
2360{
2361 int len, i;
2362
2363 if (flags)
2364 {
2366 return 0;
2367 }
2368 if (!dstlen) return srclen;
2369 len = min( srclen, dstlen );
2370 for (i = 0; i < len; i++)
2371 {
2372 unsigned char c = src[i];
2373 dst[i] = (c < 0x20) ? c : c + 0xf000;
2374 }
2375 if (len < srclen)
2376 {
2378 return 0;
2379 }
2380 return len;
2381}
2382
2383
2384static int mbstowcs_utf7( DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen )
2385{
2386 static const signed char base64_decoding_table[] =
2387 {
2388 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
2389 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
2390 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20-0x2F */
2391 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
2392 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40-0x4F */
2393 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50-0x5F */
2394 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60-0x6F */
2395 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70-0x7F */
2396 };
2397
2398 const char *source_end = src + srclen;
2399 int offset = 0, pos = 0;
2400 DWORD byte_pair = 0;
2401
2402 if (flags)
2403 {
2405 return 0;
2406 }
2407#define OUTPUT(ch) \
2408 do { \
2409 if (dstlen > 0) \
2410 { \
2411 if (pos >= dstlen) goto overflow; \
2412 dst[pos] = (ch); \
2413 } \
2414 pos++; \
2415 } while(0)
2416
2417 while (src < source_end)
2418 {
2419 if (*src == '+')
2420 {
2421 src++;
2422 if (src >= source_end) break;
2423 if (*src == '-')
2424 {
2425 /* just a plus sign escaped as +- */
2426 OUTPUT( '+' );
2427 src++;
2428 continue;
2429 }
2430
2431 do
2432 {
2433 signed char sextet = *src;
2434 if (sextet == '-')
2435 {
2436 /* skip over the dash and end base64 decoding
2437 * the current, unfinished byte pair is discarded */
2438 src++;
2439 offset = 0;
2440 break;
2441 }
2442 if (sextet < 0)
2443 {
2444 /* the next character of src is < 0 and therefore not part of a base64 sequence
2445 * the current, unfinished byte pair is NOT discarded in this case
2446 * this is probably a bug in Windows */
2447 break;
2448 }
2449 sextet = base64_decoding_table[sextet];
2450 if (sextet == -1)
2451 {
2452 /* -1 means that the next character of src is not part of a base64 sequence
2453 * in other words, all sextets in this base64 sequence have been processed
2454 * the current, unfinished byte pair is discarded */
2455 offset = 0;
2456 break;
2457 }
2458
2459 byte_pair = (byte_pair << 6) | sextet;
2460 offset += 6;
2461 if (offset >= 16)
2462 {
2463 /* this byte pair is done */
2464 OUTPUT( byte_pair >> (offset - 16) );
2465 offset -= 16;
2466 }
2467 src++;
2468 }
2469 while (src < source_end);
2470 }
2471 else
2472 {
2473 OUTPUT( (unsigned char)*src );
2474 src++;
2475 }
2476 }
2477 return pos;
2478
2479overflow:
2481 return 0;
2482#undef OUTPUT
2483}
2484
2485
2486static int mbstowcs_utf8( DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen )
2487{
2488 DWORD reslen;
2490
2491 if (!dstlen) dst = NULL;
2494 {
2496 {
2498 return 0;
2499 }
2500 }
2501 else if (!set_ntstatus( status )) reslen = 0;
2502
2503 return reslen / sizeof(WCHAR);
2504}
2505
2506
2508{
2509 return (code >= 0xe000 && code <= 0xf8ff);
2510}
2511
2512
2513static int check_invalid_chars( const CPTABLEINFO *info, const unsigned char *src, int srclen )
2514{
2515 if (info->DBCSOffsets)
2516 {
2517 for ( ; srclen; src++, srclen-- )
2518 {
2519 USHORT off = info->DBCSOffsets[*src];
2520 if (off)
2521 {
2522 if (srclen == 1) break; /* partial char, error */
2523 if (info->DBCSOffsets[off + src[1]] == info->UniDefaultChar &&
2524 ((src[0] << 8) | src[1]) != info->TransUniDefaultChar) break;
2525 src++;
2526 srclen--;
2527 continue;
2528 }
2529 if (info->MultiByteTable[*src] == info->UniDefaultChar && *src != info->TransUniDefaultChar)
2530 break;
2531 if (is_private_use_area_char( info->MultiByteTable[*src] )) break;
2532 }
2533 }
2534 else
2535 {
2536 for ( ; srclen; src++, srclen-- )
2537 {
2538 if (info->MultiByteTable[*src] == info->UniDefaultChar && *src != info->TransUniDefaultChar)
2539 break;
2540 if (is_private_use_area_char( info->MultiByteTable[*src] )) break;
2541 }
2542 }
2543 return !!srclen;
2544
2545}
2546
2547
2548static int mbstowcs_decompose( const CPTABLEINFO *info, const unsigned char *src, int srclen,
2549 WCHAR *dst, int dstlen )
2550{
2551 WCHAR ch;
2552 USHORT off;
2553 int len;
2554 const WCHAR *decomp;
2555 unsigned int decomp_len;
2556
2557 if (info->DBCSOffsets)
2558 {
2559 if (!dstlen) /* compute length */
2560 {
2561 for (len = 0; srclen; srclen--, src++, len += decomp_len)
2562 {
2563 if ((off = info->DBCSOffsets[*src]))
2564 {
2565 if (srclen > 1 && src[1])
2566 {
2567 src++;
2568 srclen--;
2569 ch = info->DBCSOffsets[off + *src];
2570 }
2571 else ch = info->UniDefaultChar;
2572 }
2573 else ch = info->MultiByteTable[*src];
2574 get_decomposition( ch, &decomp_len );
2575 }
2576 return len;
2577 }
2578
2579 for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
2580 {
2581 if ((off = info->DBCSOffsets[*src]))
2582 {
2583 if (srclen > 1 && src[1])
2584 {
2585 src++;
2586 srclen--;
2587 ch = info->DBCSOffsets[off + *src];
2588 }
2589 else ch = info->UniDefaultChar;
2590 }
2591 else ch = info->MultiByteTable[*src];
2592
2593 if ((decomp = get_decomposition( ch, &decomp_len )))
2594 {
2595 if (len < decomp_len) break;
2596 memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
2597 }
2598 else *dst = ch;
2599 }
2600 }
2601 else
2602 {
2603 if (!dstlen) /* compute length */
2604 {
2605 for (len = 0; srclen; srclen--, src++, len += decomp_len)
2606 get_decomposition( info->MultiByteTable[*src], &decomp_len );
2607 return len;
2608 }
2609
2610 for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
2611 {
2612 ch = info->MultiByteTable[*src];
2613 if ((decomp = get_decomposition( ch, &decomp_len )))
2614 {
2615 if (len < decomp_len) break;
2616 memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
2617 }
2618 else *dst = ch;
2619 }
2620 }
2621
2622 if (srclen)
2623 {
2625 return 0;
2626 }
2627 return dstlen - len;
2628}
2629
2630
2631static int mbstowcs_sbcs( const CPTABLEINFO *info, const unsigned char *src, int srclen,
2632 WCHAR *dst, int dstlen )
2633{
2634 const USHORT *table = info->MultiByteTable;
2635 int ret = srclen;
2636
2637 if (!dstlen) return srclen;
2638
2639 if (dstlen < srclen) /* buffer too small: fill it up to dstlen and return error */
2640 {
2641 srclen = dstlen;
2643 ret = 0;
2644 }
2645
2646 while (srclen >= 16)
2647 {
2648 dst[0] = table[src[0]];
2649 dst[1] = table[src[1]];
2650 dst[2] = table[src[2]];
2651 dst[3] = table[src[3]];
2652 dst[4] = table[src[4]];
2653 dst[5] = table[src[5]];
2654 dst[6] = table[src[6]];
2655 dst[7] = table[src[7]];
2656 dst[8] = table[src[8]];
2657 dst[9] = table[src[9]];
2658 dst[10] = table[src[10]];
2659 dst[11] = table[src[11]];
2660 dst[12] = table[src[12]];
2661 dst[13] = table[src[13]];
2662 dst[14] = table[src[14]];
2663 dst[15] = table[src[15]];
2664 src += 16;
2665 dst += 16;
2666 srclen -= 16;
2667 }
2668
2669 /* now handle the remaining characters */
2670 src += srclen;
2671 dst += srclen;
2672 switch (srclen)
2673 {
2674 case 15: dst[-15] = table[src[-15]];
2675 case 14: dst[-14] = table[src[-14]];
2676 case 13: dst[-13] = table[src[-13]];
2677 case 12: dst[-12] = table[src[-12]];
2678 case 11: dst[-11] = table[src[-11]];
2679 case 10: dst[-10] = table[src[-10]];
2680 case 9: dst[-9] = table[src[-9]];
2681 case 8: dst[-8] = table[src[-8]];
2682 case 7: dst[-7] = table[src[-7]];
2683 case 6: dst[-6] = table[src[-6]];
2684 case 5: dst[-5] = table[src[-5]];
2685 case 4: dst[-4] = table[src[-4]];
2686 case 3: dst[-3] = table[src[-3]];
2687 case 2: dst[-2] = table[src[-2]];
2688 case 1: dst[-1] = table[src[-1]];
2689 case 0: break;
2690 }
2691 return ret;
2692}
2693
2694
2695static int mbstowcs_dbcs( const CPTABLEINFO *info, const unsigned char *src, int srclen,
2696 WCHAR *dst, int dstlen )
2697{
2698 USHORT off;
2699 int i;
2700
2701 if (!dstlen)
2702 {
2703 for (i = 0; srclen; i++, src++, srclen--)
2704 if (info->DBCSOffsets[*src] && srclen > 1 && src[1]) { src++; srclen--; }
2705 return i;
2706 }
2707
2708 for (i = dstlen; srclen && i; i--, srclen--, src++, dst++)
2709 {
2710 if ((off = info->DBCSOffsets[*src]))
2711 {
2712 if (srclen > 1 && src[1])
2713 {
2714 src++;
2715 srclen--;
2716 *dst = info->DBCSOffsets[off + *src];
2717 }
2718 else *dst = info->UniDefaultChar;
2719 }
2720 else *dst = info->MultiByteTable[*src];
2721 }
2722 if (srclen)
2723 {
2725 return 0;
2726 }
2727 return dstlen - i;
2728}
2729
2730
2731static int mbstowcs_codepage( const CPTABLEINFO *info, DWORD flags, const char *src, int srclen,
2732 WCHAR *dst, int dstlen )
2733{
2734 CPTABLEINFO local_info;
2735 const unsigned char *str = (const unsigned char *)src;
2736
2737 if ((flags & MB_USEGLYPHCHARS) && info->MultiByteTable[256] == 256)
2738 {
2739 local_info = *info;
2740 local_info.MultiByteTable += 257;
2741 info = &local_info;
2742 }
2744 {
2746 return 0;
2747 }
2748
2750
2751 if (info->DBCSOffsets)
2752 return mbstowcs_dbcs( info, str, srclen, dst, dstlen );
2753 else
2754 return mbstowcs_sbcs( info, str, srclen, dst, dstlen );
2755}
2756
2757
2758static int wcstombs_cpsymbol( DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen,
2759 const char *defchar, BOOL *used )
2760{
2761 int len, i;
2762
2763 if (flags)
2764 {
2766 return 0;
2767 }
2768 if (defchar || used)
2769 {
2771 return 0;
2772 }
2773 if (!dstlen) return srclen;
2774 len = min( srclen, dstlen );
2775 for (i = 0; i < len; i++)
2776 {
2777 if (src[i] < 0x20) dst[i] = src[i];
2778 else if (src[i] >= 0xf020 && src[i] < 0xf100) dst[i] = src[i] - 0xf000;
2779 else
2780 {
2782 return 0;
2783 }
2784 }
2785 if (srclen > len)
2786 {
2788 return 0;
2789 }
2790 return len;
2791}
2792
2793
2794static int wcstombs_utf7( DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen,
2795 const char *defchar, BOOL *used )
2796{
2797 static const char directly_encodable[] =
2798 {
2799 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0x00 - 0x0f */
2800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
2801 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 0x20 - 0x2f */
2802 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x30 - 0x3f */
2803 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
2804 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
2805 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
2806 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* 0x70 - 0x7a */
2807 };
2808#define ENCODABLE(ch) ((ch) <= 0x7a && directly_encodable[(ch)])
2809
2810 static const char base64_encoding_table[] =
2811 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2812
2813 const WCHAR *source_end = src + srclen;
2814 int pos = 0;
2815
2816 if (defchar || used)
2817 {
2819 return 0;
2820 }
2821 if (flags)
2822 {
2824 return 0;
2825 }
2826
2827#define OUTPUT(ch) \
2828 do { \
2829 if (dstlen > 0) \
2830 { \
2831 if (pos >= dstlen) goto overflow; \
2832 dst[pos] = (ch); \
2833 } \
2834 pos++; \
2835 } while (0)
2836
2837 while (src < source_end)
2838 {
2839 if (*src == '+')
2840 {
2841 OUTPUT( '+' );
2842 OUTPUT( '-' );
2843 src++;
2844 }
2845 else if (ENCODABLE(*src))
2846 {
2847 OUTPUT( *src );
2848 src++;
2849 }
2850 else
2851 {
2852 unsigned int offset = 0, byte_pair = 0;
2853
2854 OUTPUT( '+' );
2855 while (src < source_end && !ENCODABLE(*src))
2856 {
2857 byte_pair = (byte_pair << 16) | *src;
2858 offset += 16;
2859 while (offset >= 6)
2860 {
2861 offset -= 6;
2862 OUTPUT( base64_encoding_table[(byte_pair >> offset) & 0x3f] );
2863 }
2864 src++;
2865 }
2866 if (offset)
2867 {
2868 /* Windows won't create a padded base64 character if there's no room for the - sign
2869 * as well ; this is probably a bug in Windows */
2870 if (dstlen > 0 && pos + 1 >= dstlen) goto overflow;
2871 byte_pair <<= (6 - offset);
2872 OUTPUT( base64_encoding_table[byte_pair & 0x3f] );
2873 }
2874 /* Windows always explicitly terminates the base64 sequence
2875 even though RFC 2152 (page 3, rule 2) does not require this */
2876 OUTPUT( '-' );
2877 }
2878 }
2879 return pos;
2880
2881overflow:
2883 return 0;
2884#undef OUTPUT
2885#undef ENCODABLE
2886}
2887
2888
2889static int wcstombs_utf8( DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen,
2890 const char *defchar, BOOL *used )
2891{
2892 DWORD reslen;
2894
2895 if (used) *used = FALSE;
2896 if (!dstlen) dst = NULL;
2899 {
2901 {
2903 return 0;
2904 }
2905 if (used) *used = TRUE;
2906 }
2907 else if (!set_ntstatus( status )) reslen = 0;
2908 return reslen;
2909}
2910
2911
2912static int wcstombs_sbcs( const CPTABLEINFO *info, const WCHAR *src, unsigned int srclen,
2913 char *dst, unsigned int dstlen )
2914{
2915 const char *table = info->WideCharTable;
2916 int ret = srclen;
2917
2918 if (!dstlen) return srclen;
2919
2920 if (dstlen < srclen)
2921 {
2922 /* buffer too small: fill it up to dstlen and return error */
2923 srclen = dstlen;
2925 ret = 0;
2926 }
2927
2928 while (srclen >= 16)
2929 {
2930 dst[0] = table[src[0]];
2931 dst[1] = table[src[1]];
2932 dst[2] = table[src[2]];
2933 dst[3] = table[src[3]];
2934 dst[4] = table[src[4]];
2935 dst[5] = table[src[5]];
2936 dst[6] = table[src[6]];
2937 dst[7] = table[src[7]];
2938 dst[8] = table[src[8]];
2939 dst[9] = table[src[9]];
2940 dst[10] = table[src[10]];
2941 dst[11] = table[src[11]];
2942 dst[12] = table[src[12]];
2943 dst[13] = table[src[13]];
2944 dst[14] = table[src[14]];
2945 dst[15] = table[src[15]];
2946 src += 16;
2947 dst += 16;
2948 srclen -= 16;
2949 }
2950
2951 /* now handle remaining characters */
2952 src += srclen;
2953 dst += srclen;
2954 switch(srclen)
2955 {
2956 case 15: dst[-15] = table[src[-15]];
2957 case 14: dst[-14] = table[src[-14]];
2958 case 13: dst[-13] = table[src[-13]];
2959 case 12: dst[-12] = table[src[-12]];
2960 case 11: dst[-11] = table[src[-11]];
2961 case 10: dst[-10] = table[src[-10]];
2962 case 9: dst[-9] = table[src[-9]];
2963 case 8: dst[-8] = table[src[-8]];
2964 case 7: dst[-7] = table[src[-7]];
2965 case 6: dst[-6] = table[src[-6]];
2966 case 5: dst[-5] = table[src[-5]];
2967 case 4: dst[-4] = table[src[-4]];
2968 case 3: dst[-3] = table[src[-3]];
2969 case 2: dst[-2] = table[src[-2]];
2970 case 1: dst[-1] = table[src[-1]];
2971 case 0: break;
2972 }
2973 return ret;
2974}
2975
2976
2977static int wcstombs_dbcs( const CPTABLEINFO *info, const WCHAR *src, unsigned int srclen,
2978 char *dst, unsigned int dstlen )
2979{
2980 const USHORT *table = info->WideCharTable;
2981 int i;
2982
2983 if (!dstlen)
2984 {
2985 for (i = 0; srclen; src++, srclen--, i++) if (table[*src] & 0xff00) i++;
2986 return i;
2987 }
2988
2989 for (i = dstlen; srclen && i; i--, srclen--, src++)
2990 {
2991 if (table[*src] & 0xff00)
2992 {
2993 if (i == 1) break; /* do not output a partial char */
2994 i--;
2995 *dst++ = table[*src] >> 8;
2996 }
2997 *dst++ = (char)table[*src];
2998 }
2999 if (srclen)
3000 {
3002 return 0;
3003 }
3004 return dstlen - i;
3005}
3006
3007
3008static inline int is_valid_sbcs_mapping( const CPTABLEINFO *info, DWORD flags, unsigned int wch )
3009{
3010 const unsigned char *table = info->WideCharTable;
3011
3012 if (wch >= 0x10000) return 0;
3013 if ((flags & WC_NO_BEST_FIT_CHARS) || table[wch] == info->DefaultChar)
3014 return (info->MultiByteTable[table[wch]] == wch);
3015 return 1;
3016}
3017
3018
3019static inline int is_valid_dbcs_mapping( const CPTABLEINFO *info, DWORD flags, unsigned int wch )
3020{
3021 const unsigned short *table = info->WideCharTable;
3022 unsigned short ch;
3023
3024 if (wch >= 0x10000) return 0;
3025 ch = table[wch];
3026 if ((flags & WC_NO_BEST_FIT_CHARS) || ch == info->DefaultChar)
3027 {
3028 if (ch >> 8) return info->DBCSOffsets[info->DBCSOffsets[ch >> 8] + (ch & 0xff)] == wch;
3029 return info->MultiByteTable[ch] == wch;
3030 }
3031 return 1;
3032}
3033
3034
3035static int wcstombs_sbcs_slow( const CPTABLEINFO *info, DWORD flags, const WCHAR *src, unsigned int srclen,
3036 char *dst, unsigned int dstlen, const char *defchar, BOOL *used )
3037{
3038 const char *table = info->WideCharTable;
3039 const char def = defchar ? *defchar : (char)info->DefaultChar;
3040 int i;
3041 BOOL tmp;
3042 WCHAR wch;
3043 unsigned int composed;
3044
3045 if (!used) used = &tmp; /* avoid checking on every char */
3046 *used = FALSE;
3047
3048 if (!dstlen)
3049 {
3050 for (i = 0; srclen; i++, src++, srclen--)
3051 {
3052 wch = *src;
3053 if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose_chars( src[0], src[1] )))
3054 {
3055 /* now check if we can use the composed char */
3056 if (is_valid_sbcs_mapping( info, flags, composed ))
3057 {
3058 /* we have a good mapping, use it */
3059 src++;
3060 srclen--;
3061 continue;
3062 }
3063 /* no mapping for the composed char, check the other flags */
3064 if (flags & WC_DEFAULTCHAR) /* use the default char instead */
3065 {
3066 *used = TRUE;
3067 src++; /* skip the non-spacing char */
3068 srclen--;
3069 continue;
3070 }
3071 if (flags & WC_DISCARDNS) /* skip the second char of the composition */
3072 {
3073 src++;
3074 srclen--;
3075 }
3076 /* WC_SEPCHARS is the default */
3077 }
3078 if (!*used) *used = !is_valid_sbcs_mapping( info, flags, wch );
3079 }
3080 return i;
3081 }
3082
3083 for (i = dstlen; srclen && i; dst++, i--, src++, srclen--)
3084 {
3085 wch = *src;
3086 if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose_chars( src[0], src[1] )))
3087 {
3088 /* now check if we can use the composed char */
3089 if (is_valid_sbcs_mapping( info, flags, composed ))
3090 {
3091 /* we have a good mapping, use it */
3092 *dst = table[composed];
3093 src++;
3094 srclen--;
3095 continue;
3096 }
3097 /* no mapping for the composed char, check the other flags */
3098 if (flags & WC_DEFAULTCHAR) /* use the default char instead */
3099 {
3100 *dst = def;
3101 *used = TRUE;
3102 src++; /* skip the non-spacing char */
3103 srclen--;
3104 continue;
3105 }
3106 if (flags & WC_DISCARDNS) /* skip the second char of the composition */
3107 {
3108 src++;
3109 srclen--;
3110 }
3111 /* WC_SEPCHARS is the default */
3112 }
3113
3114 *dst = table[wch];
3115 if (!is_valid_sbcs_mapping( info, flags, wch ))
3116 {
3117 *dst = def;
3118 *used = TRUE;
3119 }
3120 }
3121 if (srclen)
3122 {
3124 return 0;
3125 }
3126 return dstlen - i;
3127}
3128
3129
3130static int wcstombs_dbcs_slow( const CPTABLEINFO *info, DWORD flags, const WCHAR *src, unsigned int srclen,
3131 char *dst, unsigned int dstlen, const char *defchar, BOOL *used )
3132{
3133 const USHORT *table = info->WideCharTable;
3134 WCHAR wch, defchar_value;
3135 unsigned int composed;
3136 unsigned short res;
3137 BOOL tmp;
3138 int i;
3139
3140 if (!defchar[1]) defchar_value = (unsigned char)defchar[0];
3141 else defchar_value = ((unsigned char)defchar[0] << 8) | (unsigned char)defchar[1];
3142
3143 if (!used) used = &tmp; /* avoid checking on every char */
3144 *used = FALSE;
3145
3146 if (!dstlen)
3147 {
3148 if (!defchar && !used && !(flags & WC_COMPOSITECHECK))
3149 {
3150 for (i = 0; srclen; srclen--, src++, i++) if (table[*src] & 0xff00) i++;
3151 return i;
3152 }
3153 for (i = 0; srclen; srclen--, src++, i++)
3154 {
3155 wch = *src;
3156 if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose_chars( src[0], src[1] )))
3157 {
3158 /* now check if we can use the composed char */
3159 if (is_valid_dbcs_mapping( info, flags, composed ))
3160 {
3161 /* we have a good mapping for the composed char, use it */
3162 res = table[composed];
3163 if (res & 0xff00) i++;
3164 src++;
3165 srclen--;
3166 continue;
3167 }
3168 /* no mapping for the composed char, check the other flags */
3169 if (flags & WC_DEFAULTCHAR) /* use the default char instead */
3170 {
3171 if (defchar_value & 0xff00) i++;
3172 *used = TRUE;
3173 src++; /* skip the non-spacing char */
3174 srclen--;
3175 continue;
3176 }
3177 if (flags & WC_DISCARDNS) /* skip the second char of the composition */
3178 {
3179 src++;
3180 srclen--;
3181 }
3182 /* WC_SEPCHARS is the default */
3183 }
3184
3185 res = table[wch];
3186 if (!is_valid_dbcs_mapping( info, flags, wch ))
3187 {
3188 res = defchar_value;
3189 *used = TRUE;
3190 }
3191 if (res & 0xff00) i++;
3192 }
3193 return i;
3194 }
3195
3196
3197 for (i = dstlen; srclen && i; i--, srclen--, src++)
3198 {
3199 wch = *src;
3200 if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose_chars( src[0], src[1] )))
3201 {
3202 /* now check if we can use the composed char */
3203 if (is_valid_dbcs_mapping( info, flags, composed ))
3204 {
3205 /* we have a good mapping for the composed char, use it */
3206 res = table[composed];
3207 src++;
3208 srclen--;
3209 goto output_char;
3210 }
3211 /* no mapping for the composed char, check the other flags */
3212 if (flags & WC_DEFAULTCHAR) /* use the default char instead */
3213 {
3214 res = defchar_value;
3215 *used = TRUE;
3216 src++; /* skip the non-spacing char */
3217 srclen--;
3218 goto output_char;
3219 }
3220 if (flags & WC_DISCARDNS) /* skip the second char of the composition */
3221 {
3222 src++;
3223 srclen--;
3224 }
3225 /* WC_SEPCHARS is the default */
3226 }
3227
3228 res = table[wch];
3229 if (!is_valid_dbcs_mapping( info, flags, wch ))
3230 {
3231 res = defchar_value;
3232 *used = TRUE;
3233 }
3234
3235 output_char:
3236 if (res & 0xff00)
3237 {
3238 if (i == 1) break; /* do not output a partial char */
3239 i--;
3240 *dst++ = res >> 8;
3241 }
3242 *dst++ = (char)res;
3243 }
3244 if (srclen)
3245 {
3247 return 0;
3248 }
3249 return dstlen - i;
3250}
3251
3252
3253static int wcstombs_codepage( const CPTABLEINFO *info, DWORD flags, const WCHAR *src, int srclen,
3254 char *dst, int dstlen, const char *defchar, BOOL *used )
3255{
3256 if (flags || defchar || used)
3257 {
3258 if (!defchar) defchar = (const char *)&info->DefaultChar;
3259 if (info->DBCSOffsets)
3260 return wcstombs_dbcs_slow( info, flags, src, srclen, dst, dstlen, defchar, used );
3261 else
3262 return wcstombs_sbcs_slow( info, flags, src, srclen, dst, dstlen, defchar, used );
3263 }
3264 if (info->DBCSOffsets)
3265 return wcstombs_dbcs( info, src, srclen, dst, dstlen );
3266 else
3267 return wcstombs_sbcs( info, src, srclen, dst, dstlen );
3268}
3269
3270
3272{
3274 BYTE *new_buf; /* allocated buf if static buf is not large enough */
3275 UINT size; /* buffer size */
3276 UINT max; /* max possible size */
3277 UINT len; /* current key length */
3278};
3279
3280static void append_sortkey( struct sortkey *key, BYTE val )
3281{
3282 if (key->len >= key->max) return;
3283 if (key->len >= key->size)
3284 {
3285 key->new_buf = RtlAllocateHeap( GetProcessHeap(), 0, key->max );
3286 if (key->new_buf) memcpy( key->new_buf, key->buf, key->len );
3287 else key->max = 0;
3288 key->buf = key->new_buf;
3289 key->size = key->max;
3290 }
3291 key->buf[key->len++] = val;
3292}
3293
3294static void reverse_sortkey( struct sortkey *key )
3295{
3296 int i;
3297
3298 for (i = 0; i < key->len / 2; i++)
3299 {
3300 BYTE tmp = key->buf[key->len - i - 1];
3301 key->buf[key->len - i - 1] = key->buf[i];
3302 key->buf[i] = tmp;
3303 }
3304}
3305
3306static int compare_sortkeys( const struct sortkey *key1, const struct sortkey *key2, BOOL shorter_wins )
3307{
3308 int ret = memcmp( key1->buf, key2->buf, min( key1->len, key2->len ));
3309 if (!ret) ret = shorter_wins ? key2->len - key1->len : key1->len - key2->len;
3310 return ret;
3311}
3312
3313static void append_normal_weights( const struct sortguid *sortid, struct sortkey *key_primary,
3314 struct sortkey *key_diacritic, struct sortkey *key_case,
3316{
3317 append_sortkey( key_primary, weights.script );
3318 append_sortkey( key_primary, weights.primary );
3319
3320 if ((weights.script >= SCRIPT_PUA_FIRST && weights.script <= SCRIPT_PUA_LAST) ||
3321 ((sortid->flags & FLAG_HAS_3_BYTE_WEIGHTS) &&
3322 (weights.script >= SCRIPT_CJK_FIRST && weights.script <= SCRIPT_CJK_LAST)))
3323 {
3324 append_sortkey( key_primary, weights.diacritic );
3325 append_sortkey( key_case, weights._case );
3326 return;
3327 }
3328 if (weights.script <= SCRIPT_ARABIC && weights.script != SCRIPT_HEBREW)
3329 {
3330 if (flags & LINGUISTIC_IGNOREDIACRITIC) weights.diacritic = 2;
3331 if (flags & LINGUISTIC_IGNORECASE) weights._case = 2;
3332 }
3333 append_sortkey( key_diacritic, weights.diacritic );
3334 append_sortkey( key_case, weights._case );
3335}
3336
3338{
3339 if (flags & LINGUISTIC_IGNOREDIACRITIC) weights.diacritic = 2;
3340 if (key->len) key->buf[key->len - 1] += weights.diacritic;
3341 else append_sortkey( key, weights.diacritic );
3342}
3343
3344static void append_expansion_weights( const struct sortguid *sortid, struct sortkey *key_primary,
3345 struct sortkey *key_diacritic, struct sortkey *key_case,
3346 union char_weights weights, DWORD flags, BOOL is_compare )
3347{
3348 /* sortkey and comparison behave differently here */
3349 if (is_compare)
3350 {
3351 if (weights.script == SCRIPT_UNSORTABLE) return;
3352 if (weights.script == SCRIPT_NONSPACE_MARK)
3353 {
3354 append_nonspace_weights( key_diacritic, weights, flags );
3355 return;
3356 }
3357 }
3358 append_normal_weights( sortid, key_primary, key_diacritic, key_case, weights, flags );
3359}
3360
3361static const UINT *find_compression( const WCHAR *src, const WCHAR *table, int count, int len )
3362{
3363 int elem_size = compression_size( len ), min = 0, max = count - 1;
3364
3365 while (min <= max)
3366 {
3367 int pos = (min + max) / 2;
3368 int res = wcsncmp( src, table + pos * elem_size, len );
3369 if (!res) return (UINT *)(table + (pos + 1) * elem_size) - 1;
3370 if (res > 0) min = pos + 1;
3371 else max = pos - 1;
3372 }
3373 return NULL;
3374}
3375
3376/* find a compression for a char sequence */
3377/* return the number of extra chars to skip */
3378static int get_compression_weights( UINT compression, const WCHAR *compr_tables[8],
3379 const WCHAR *src, int srclen, union char_weights *weights )
3380{
3381 const struct sort_compression *compr = sort.compressions + compression;
3382 const UINT *ret;
3383 BYTE size = weights->_case & CASE_COMPR_6;
3384 int i, maxlen = 1;
3385
3386 if (compression >= sort.compr_count) return 0;
3387 if (size == CASE_COMPR_6) maxlen = 8;
3388 else if (size == CASE_COMPR_4) maxlen = 5;
3389 else if (size == CASE_COMPR_2) maxlen = 3;
3390 maxlen = min( maxlen, srclen );
3391 for (i = 0; i < maxlen; i++) if (src[i] < compr->minchar || src[i] > compr->maxchar) break;
3392 maxlen = i;
3393 if (!compr_tables[0])
3394 {
3395 compr_tables[0] = sort.compr_data + compr->offset;
3396 for (i = 1; i < 8; i++)
3397 compr_tables[i] = compr_tables[i - 1] + compr->len[i - 1] * compression_size( i + 1 );
3398 }
3399 for (i = maxlen - 2; i >= 0; i--)
3400 {
3401 if (!(ret = find_compression( src, compr_tables[i], compr->len[i], i + 2 ))) continue;
3402 weights->val = *ret;
3403 return i + 1;
3404 }
3405 return 0;
3406}
3407
3408/* get the zero digit for the digit character range that contains 'ch' */
3410{
3411 static const WCHAR zeroes[] =
3412 {
3413 0x0030, 0x0660, 0x06f0, 0x0966, 0x09e6, 0x0a66, 0x0ae6, 0x0b66, 0x0be6, 0x0c66,
3414 0x0ce6, 0x0d66, 0x0e50, 0x0ed0, 0x0f20, 0x1040, 0x1090, 0x17e0, 0x1810, 0x1946,
3415 0x1bb0, 0x1c40, 0x1c50, 0xa620, 0xa8d0, 0xa900, 0xaa50, 0xff10
3416 };
3417 int min = 0, max = ARRAY_SIZE( zeroes ) - 1;
3418
3419 while (min <= max)
3420 {
3421 int pos = (min + max) / 2;
3422 if (zeroes[pos] <= ch && zeroes[pos] + 9 >= ch) return zeroes[pos];
3423 if (zeroes[pos] < ch) min = pos + 1;
3424 else max = pos - 1;
3425 }
3426 return 0;
3427}
3428
3429/* append weights for digits when using SORT_DIGITSASNUMBERS */
3430/* return the number of extra chars to skip */
3431static int append_digit_weights( struct sortkey *key, const WCHAR *src, UINT srclen )
3432{
3433 UINT i, zero, len, lzero;
3434 BYTE val, values[19];
3435
3436 if (!(zero = get_digit_zero_char( *src ))) return -1;
3437
3438 values[0] = *src - zero;
3439 for (len = 1; len < ARRAY_SIZE(values) && len < srclen; len++)
3440 {
3441 if (src[len] < zero || src[len] > zero + 9) break;
3442 values[len] = src[len] - zero;
3443 }
3444 for (lzero = 0; lzero < len; lzero++) if (values[lzero]) break;
3445
3447 append_sortkey( key, 2 );
3448 append_sortkey( key, 2 + len - lzero );
3449 for (i = lzero, val = 2; i < len; i++)
3450 {
3451 if ((len - i) % 2) append_sortkey( key, (val << 4) + values[i] + 2 );
3452 else val = values[i] + 2;
3453 }
3454 append_sortkey( key, 0xfe - lzero );
3455 return len - 1;
3456}
3457
3458/* append the extra weights for kana prolonged sound / repeat marks */
3459static int append_extra_kana_weights( struct sortkey keys[4], const WCHAR *src, int pos, UINT except,
3460 BYTE case_mask, union char_weights *weights )
3461{
3462 BYTE extra1 = 3, case_weight = weights->_case;
3463
3464 if (weights->primary <= 1)
3465 {
3466 while (pos > 0)
3467 {
3468 union char_weights prev = get_char_weights( src[--pos], except );
3469 if (prev.script == SCRIPT_UNSORTABLE || prev.script == SCRIPT_NONSPACE_MARK) continue;
3470 if (prev.script == SCRIPT_EXPANSION) return 0;
3471 if (prev.script != SCRIPT_EASTASIA_SPECIAL)
3472 {
3473 *weights = prev;
3474 return 1;
3475 }
3476 if (prev.primary <= 1) continue;
3477
3478 case_weight = prev._case & case_mask;
3479 if (weights->primary == 1) /* prolonged sound mark */
3480 {
3481 prev.primary &= 0x87;
3482 case_weight &= ~CASE_FULLWIDTH;
3483 case_weight |= weights->_case & CASE_FULLWIDTH;
3484 }
3485 extra1 = 4 + weights->primary;
3486 weights->primary = prev.primary;
3487 goto done;
3488 }
3489 return 0;
3490 }
3491done:
3492 append_sortkey( &keys[0], 0xc4 | (case_weight & CASE_FULLSIZE) );
3493 append_sortkey( &keys[1], extra1 );
3494 append_sortkey( &keys[2], 0xc4 | (case_weight & CASE_KATAKANA) );
3495 append_sortkey( &keys[3], 0xc4 | (case_weight & CASE_FULLWIDTH) );
3496 weights->script = SCRIPT_KANA;
3497 return 1;
3498}
3499
3500
3501#define HANGUL_SBASE 0xac00
3502#define HANGUL_LCOUNT 19
3503#define HANGUL_VCOUNT 21
3504#define HANGUL_TCOUNT 28
3505
3506static int append_hangul_weights( struct sortkey *key, const WCHAR *src, int srclen, UINT except )
3507{
3508 int leading_idx = 0x115f - 0x1100; /* leading filler */
3509 int vowel_idx = 0x1160 - 0x1100; /* vowel filler */
3510 int trailing_idx = -1;
3511 BYTE leading_off, vowel_off, trailing_off;
3512 union char_weights weights;
3513 WCHAR composed;
3514 BYTE filler_mask = 0;
3515 int pos = 0;
3516
3517 /* leading */
3518 if (src[pos] >= 0x1100 && src[pos] <= 0x115f) leading_idx = src[pos++] - 0x1100;
3519 else if (src[pos] >= 0xa960 && src[pos] <= 0xa97c) leading_idx = src[pos++] - (0xa960 - 0x100);
3520
3521 /* vowel */
3522 if (srclen > pos)
3523 {
3524 if (src[pos] >= 0x1160 && src[pos] <= 0x11a7) vowel_idx = src[pos++] - 0x1100;
3525 else if (src[pos] >= 0xd7b0 && src[pos] <= 0xd7c6) vowel_idx = src[pos++] - (0xd7b0 - 0x11d);
3526 }
3527
3528 /* trailing */
3529 if (srclen > pos)
3530 {
3531 if (src[pos] >= 0x11a8 && src[pos] <= 0x11ff) trailing_idx = src[pos++] - 0x1100;
3532 else if (src[pos] >= 0xd7cb && src[pos] <= 0xd7fb) trailing_idx = src[pos++] - (0xd7cb - 0x134);
3533 }
3534
3535 if (!sort.jamo[leading_idx].is_old && !sort.jamo[vowel_idx].is_old &&
3536 (trailing_idx == -1 || !sort.jamo[trailing_idx].is_old))
3537 {
3538 /* not old Hangul, only use leading char; vowel and trailing will be handled in the next pass */
3539 pos = 1;
3540 vowel_idx = 0x1160 - 0x1100;
3541 trailing_idx = -1;
3542 }
3543
3544 leading_off = max( sort.jamo[leading_idx].leading, sort.jamo[vowel_idx].leading );
3545 vowel_off = max( sort.jamo[leading_idx].vowel, sort.jamo[vowel_idx].vowel );
3546 trailing_off = max( sort.jamo[leading_idx].trailing, sort.jamo[vowel_idx].trailing );
3547 if (trailing_idx != -1) trailing_off = max( trailing_off, sort.jamo[trailing_idx].trailing );
3548 composed = HANGUL_SBASE + (leading_off * HANGUL_VCOUNT + vowel_off) * HANGUL_TCOUNT + trailing_off;
3549
3550 if (leading_idx == 0x115f - 0x1100 || vowel_idx == 0x1160 - 0x1100)
3551 {
3552 filler_mask = 0x80;
3553 composed--;
3554 }
3555 if (composed < HANGUL_SBASE) composed = 0x3260;
3556
3557 weights = get_char_weights( composed, except );
3558 append_sortkey( key, weights.script );
3559 append_sortkey( key, weights.primary );
3560 append_sortkey( key, 0xff );
3561 append_sortkey( key, sort.jamo[leading_idx].weight | filler_mask );
3562 append_sortkey( key, 0xff );
3563 append_sortkey( key, sort.jamo[vowel_idx].weight );
3564 append_sortkey( key, 0xff );
3565 append_sortkey( key, trailing_idx != -1 ? sort.jamo[trailing_idx].weight : 2 );
3566 return pos - 1;
3567}
3568
3569/* put one of the elements of a sortkey into the dst buffer */
3570static int put_sortkey( BYTE *dst, int dstlen, int pos, const struct sortkey *key, BYTE terminator )
3571{
3572 if (dstlen > pos + key->len)
3573 {
3574 memcpy( dst + pos, key->buf, key->len );
3575 dst[pos + key->len] = terminator;
3576 }
3577 return pos + key->len + 1;
3578}
3579
3580
3582{
3589 BYTE buffer[3 * 128];
3590};
3591
3593 BYTE *primary_buf, UINT primary_size )
3594{
3595 /* buffer for secondary weights */
3596 BYTE *secondary_buf = s->buffer;
3597 UINT secondary_size;
3598
3599 memset( s, 0, offsetof( struct sortkey_state, buffer ));
3600
3601 s->key_primary.buf = primary_buf;
3602 s->key_primary.size = primary_size;
3603
3604 if (!(flags & NORM_IGNORENONSPACE)) /* reserve space for diacritics */
3605 {
3606 secondary_size = sizeof(s->buffer) / 3;
3607 s->key_diacritic.buf = secondary_buf;
3608 s->key_diacritic.size = secondary_size;
3609 secondary_buf += secondary_size;
3610 }
3611 else secondary_size = sizeof(s->buffer) / 2;
3612
3613 s->key_case.buf = secondary_buf;
3614 s->key_case.size = secondary_size;
3615 s->key_special.buf = secondary_buf + secondary_size;
3616 s->key_special.size = secondary_size;
3617
3618 s->key_primary.max = srclen * 8;
3619 s->key_case.max = srclen * 3;
3620 s->key_special.max = srclen * 4;
3621 s->key_extra[2].max = s->key_extra[3].max = srclen;
3622 if (!(flags & NORM_IGNORENONSPACE))
3623 {
3624 s->key_diacritic.max = srclen * 3;
3625 s->key_extra[0].max = s->key_extra[1].max = srclen;
3626 }
3627}
3628
3629static BOOL remove_unneeded_weights( const struct sortguid *sortid, struct sortkey_state *s )
3630{
3631 const BYTE ignore[4] = { 0xc4 | CASE_FULLSIZE, 0x03, 0xc4 | CASE_KATAKANA, 0xc4 | CASE_FULLWIDTH };
3632 int i, j;
3633
3634 if (sortid->flags & FLAG_REVERSEDIACRITICS) reverse_sortkey( &s->key_diacritic );
3635
3636 for (i = s->key_diacritic.len; i > 0; i--) if (s->key_diacritic.buf[i - 1] > 2) break;
3637 s->key_diacritic.len = i;
3638
3639 for (i = s->key_case.len; i > 0; i--) if (s->key_case.buf[i - 1] > 2) break;
3640 s->key_case.len = i;
3641
3642 if (!s->key_extra[2].len) return FALSE;
3643
3644 for (i = 0; i < 4; i++)
3645 {
3646 for (j = s->key_extra[i].len; j > 0; j--) if (s->key_extra[i].buf[j - 1] != ignore[i]) break;
3647 s->key_extra[i].len = j;
3648 }
3649 return TRUE;
3650}
3651
3652static void free_sortkey_state( struct sortkey_state *s )
3653{
3654 RtlFreeHeap( GetProcessHeap(), 0, s->key_primary.new_buf );
3655 RtlFreeHeap( GetProcessHeap(), 0, s->key_diacritic.new_buf );
3656 RtlFreeHeap( GetProcessHeap(), 0, s->key_case.new_buf );
3657 RtlFreeHeap( GetProcessHeap(), 0, s->key_special.new_buf );
3658 RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[0].new_buf );
3659 RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[1].new_buf );
3660 RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[2].new_buf );
3661 RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[3].new_buf );
3662}
3663
3664static int append_weights( const struct sortguid *sortid, DWORD flags,
3665 const WCHAR *src, int srclen, int pos, BYTE case_mask, UINT except,
3666 const WCHAR *compr_tables[8], struct sortkey_state *s, BOOL is_compare )
3667{
3669 WCHAR idx = (weights.val >> 16) & ~(CASE_COMPR_6 << 8); /* expansion index */
3670 int ret = 1;
3671
3672 if (weights._case & CASE_COMPR_6)
3673 ret += get_compression_weights( sortid->compr, compr_tables, src + pos, srclen - pos, &weights );
3674
3675 weights._case &= case_mask;
3676
3677 switch (weights.script)
3678 {
3679 case SCRIPT_UNSORTABLE:
3680 break;
3681
3683 append_nonspace_weights( &s->key_diacritic, weights, flags );
3684 break;
3685
3686 case SCRIPT_EXPANSION:
3687 while (weights.script == SCRIPT_EXPANSION)
3688 {
3689 weights = get_char_weights( sort.expansions[idx].exp[0], except );
3690 weights._case &= case_mask;
3691 append_expansion_weights( sortid, &s->key_primary, &s->key_diacritic,
3692 &s->key_case, weights, flags, is_compare );
3693 weights = get_char_weights( sort.expansions[idx].exp[1], except );
3694 idx = weights.val >> 16;
3695 weights._case &= case_mask;
3696 }
3697 append_expansion_weights( sortid, &s->key_primary, &s->key_diacritic,
3698 &s->key_case, weights, flags, is_compare );
3699 break;
3700
3702 if (!append_extra_kana_weights( s->key_extra, src, pos, except, case_mask, &weights ))
3703 {
3704 append_sortkey( &s->key_primary, 0xff );
3705 append_sortkey( &s->key_primary, 0xff );
3706 break;
3707 }
3708 weights._case = 2;
3709 append_normal_weights( sortid, &s->key_primary, &s->key_diacritic, &s->key_case, weights, flags );
3710 break;
3711
3713 ret += append_hangul_weights( &s->key_primary, src + pos, srclen - pos, except );
3714 append_sortkey( &s->key_diacritic, 2 );
3715 append_sortkey( &s->key_case, 2 );
3716 break;
3717
3718 case SCRIPT_EXTENSION_A:
3719 append_sortkey( &s->key_primary, 0xfd );
3720 append_sortkey( &s->key_primary, 0xff );
3721 append_sortkey( &s->key_primary, weights.primary );
3722 append_sortkey( &s->key_primary, weights.diacritic );
3723 append_sortkey( &s->key_diacritic, 2 );
3724 append_sortkey( &s->key_case, 2 );
3725 break;
3726
3727 case SCRIPT_PUNCTUATION:
3728 if (flags & NORM_IGNORESYMBOLS) break;
3729 if (!(flags & SORT_STRINGSORT))
3730 {
3731 short len = -((s->key_primary.len + s->primary_pos) / 2) - 1;
3732 if (flags & LINGUISTIC_IGNORECASE) weights._case = 2;
3733 if (flags & LINGUISTIC_IGNOREDIACRITIC) weights.diacritic = 2;
3734 append_sortkey( &s->key_special, len >> 8 );
3735 append_sortkey( &s->key_special, len & 0xff );
3736 append_sortkey( &s->key_special, weights.primary );
3737 append_sortkey( &s->key_special, weights._case | (weights.diacritic << 3) );
3738 break;
3739 }
3740 /* fall through */
3741 case SCRIPT_SYMBOL_1:
3742 case SCRIPT_SYMBOL_2:
3743 case SCRIPT_SYMBOL_3:
3744 case SCRIPT_SYMBOL_4:
3745 case SCRIPT_SYMBOL_5:
3746 case SCRIPT_SYMBOL_6:
3747 if (flags & NORM_IGNORESYMBOLS) break;
3748 append_sortkey( &s->key_primary, weights.script );
3749 append_sortkey( &s->key_primary, weights.primary );
3750 append_sortkey( &s->key_diacritic, weights.diacritic );
3751 append_sortkey( &s->key_case, weights._case );
3752 break;
3753
3754 case SCRIPT_DIGIT:
3756 {
3757 int len = append_digit_weights( &s->key_primary, src + pos, srclen - pos );
3758 if (len >= 0)
3759 {
3760 ret += len;
3761 append_sortkey( &s->key_diacritic, weights.diacritic );
3762 append_sortkey( &s->key_case, weights._case );
3763 break;
3764 }
3765 }
3766 /* fall through */
3767 default:
3768 append_normal_weights( sortid, &s->key_primary, &s->key_diacritic, &s->key_case, weights, flags );
3769 break;
3770 }
3771
3772 return ret;
3773}
3774
3775/* implementation of LCMAP_SORTKEY */
3776static int get_sortkey( const struct sortguid *sortid, DWORD flags,
3777 const WCHAR *src, int srclen, BYTE *dst, int dstlen )
3778{
3779 struct sortkey_state s;
3780 BYTE primary_buf[256];
3781 int ret = 0, pos = 0;
3782 BOOL have_extra;
3783 BYTE case_mask = 0x3f;
3784 UINT except = sortid->except;
3785 const WCHAR *compr_tables[8];
3786
3787 compr_tables[0] = NULL;
3788 if (flags & NORM_IGNORECASE) case_mask &= ~(CASE_UPPER | CASE_SUBSCRIPT);
3789 if (flags & NORM_IGNOREWIDTH) case_mask &= ~CASE_FULLWIDTH;
3790 if (flags & NORM_IGNOREKANATYPE) case_mask &= ~CASE_KATAKANA;
3791 if ((flags & NORM_LINGUISTIC_CASING) && except && sortid->ling_except) except = sortid->ling_except;
3792
3793 init_sortkey_state( &s, flags, srclen, primary_buf, sizeof(primary_buf) );
3794
3795 while (pos < srclen)
3796 pos += append_weights( sortid, flags, src, srclen, pos, case_mask, except, compr_tables, &s, FALSE );
3797
3798 have_extra = remove_unneeded_weights( sortid, &s );
3799
3800 ret = put_sortkey( dst, dstlen, ret, &s.key_primary, 0x01 );
3801 ret = put_sortkey( dst, dstlen, ret, &s.key_diacritic, 0x01 );
3802 ret = put_sortkey( dst, dstlen, ret, &s.key_case, 0x01 );
3803
3804 if (have_extra)
3805 {
3806 ret = put_sortkey( dst, dstlen, ret, &s.key_extra[0], 0xff );
3807 ret = put_sortkey( dst, dstlen, ret, &s.key_extra[1], 0x02 );
3808 ret = put_sortkey( dst, dstlen, ret, &s.key_extra[2], 0xff );
3809 ret = put_sortkey( dst, dstlen, ret, &s.key_extra[3], 0xff );
3810 }
3811 if (dstlen > ret) dst[ret] = 0x01;
3812 ret++;
3813
3814 ret = put_sortkey( dst, dstlen, ret, &s.key_special, 0 );
3815
3817
3818 if (dstlen && dstlen < ret)
3819 {
3821 return 0;
3822 }
3823 if (flags & LCMAP_BYTEREV)
3824 map_byterev( (WCHAR *)dst, min( ret, dstlen ) / sizeof(WCHAR), (WCHAR *)dst );
3825 return ret;
3826}
3827
3828
3829/* implementation of CompareStringEx */
3830static int compare_string( const struct sortguid *sortid, DWORD flags,
3831 const WCHAR *src1, int srclen1, const WCHAR *src2, int srclen2 )
3832{
3833 struct sortkey_state s1;
3834 struct sortkey_state s2;
3835 BYTE primary1[32];
3836 BYTE primary2[32];
3837 int i, ret, len, pos1 = 0, pos2 = 0;
3838 BOOL have_extra1, have_extra2;
3839 BYTE case_mask = 0x3f;
3840 UINT except = sortid->except;
3841 const WCHAR *compr_tables[8];
3842
3843 compr_tables[0] = NULL;
3844 if (flags & NORM_IGNORECASE) case_mask &= ~(CASE_UPPER | CASE_SUBSCRIPT);
3845 if (flags & NORM_IGNOREWIDTH) case_mask &= ~CASE_FULLWIDTH;
3846 if (flags & NORM_IGNOREKANATYPE) case_mask &= ~CASE_KATAKANA;
3847 if ((flags & NORM_LINGUISTIC_CASING) && except && sortid->ling_except) except = sortid->ling_except;
3848
3849 init_sortkey_state( &s1, flags, srclen1, primary1, sizeof(primary1) );
3850 init_sortkey_state( &s2, flags, srclen2, primary2, sizeof(primary2) );
3851
3852 while (pos1 < srclen1 || pos2 < srclen2)
3853 {
3854 while (pos1 < srclen1 && !s1.key_primary.len)
3855 pos1 += append_weights( sortid, flags, src1, srclen1, pos1,
3856 case_mask, except, compr_tables, &s1, TRUE );
3857
3858 while (pos2 < srclen2 && !s2.key_primary.len)
3859 pos2 += append_weights( sortid, flags, src2, srclen2, pos2,
3860 case_mask, except, compr_tables, &s2, TRUE );
3861
3862 if (!(len = min( s1.key_primary.len, s2.key_primary.len ))) break;
3863 if ((ret = memcmp( primary1, primary2, len ))) goto done;
3864 memmove( primary1, primary1 + len, s1.key_primary.len - len );
3865 memmove( primary2, primary2 + len, s2.key_primary.len - len );
3866 s1.key_primary.len -= len;
3867 s2.key_primary.len -= len;
3868 s1.primary_pos += len;
3869 s2.primary_pos += len;
3870 }
3871
3872 if ((ret = s1.key_primary.len - s2.key_primary.len)) goto done;
3873
3874 have_extra1 = remove_unneeded_weights( sortid, &s1 );
3875 have_extra2 = remove_unneeded_weights( sortid, &s2 );
3876
3877 if ((ret = compare_sortkeys( &s1.key_diacritic, &s2.key_diacritic, FALSE ))) goto done;
3878 if ((ret = compare_sortkeys( &s1.key_case, &s2.key_case, FALSE ))) goto done;
3879
3880 if (have_extra1 && have_extra2)
3881 {
3882 for (i = 0; i < 4; i++)
3883 if ((ret = compare_sortkeys( &s1.key_extra[i], &s2.key_extra[i], i != 1 ))) goto done;
3884 }
3885 else if ((ret = have_extra1 - have_extra2)) goto done;
3886
3887 ret = compare_sortkeys( &s1.key_special, &s2.key_special, FALSE );
3888
3889done:
3892 return ret;
3893}
3894
3895
3896/* implementation of FindNLSStringEx */
3897static int find_substring( const struct sortguid *sortid, DWORD flags, const WCHAR *src, int srclen,
3898 const WCHAR *value, int valuelen, int *reslen )
3899{
3900 struct sortkey_state s;
3901 struct sortkey_state val;
3902 BYTE primary[32];
3903 BYTE primary_val[256];
3904 int i, start, len, found = -1, foundlen = 0, pos = 0;
3905 BOOL have_extra, have_extra_val;
3906 BYTE case_mask = 0x3f;
3907 UINT except = sortid->except;
3908 const WCHAR *compr_tables[8];
3909
3910 compr_tables[0] = NULL;
3911 if (flags & NORM_IGNORECASE) case_mask &= ~(CASE_UPPER | CASE_SUBSCRIPT);
3912 if (flags & NORM_IGNOREWIDTH) case_mask &= ~CASE_FULLWIDTH;
3913 if (flags & NORM_IGNOREKANATYPE) case_mask &= ~CASE_KATAKANA;
3914 if ((flags & NORM_LINGUISTIC_CASING) && except && sortid->ling_except) except = sortid->ling_except;
3915
3916 init_sortkey_state( &s, flags, srclen, primary, sizeof(primary) );
3917
3918 /* build the value sortkey just once */
3919 init_sortkey_state( &val, flags, valuelen, primary_val, sizeof(primary_val) );
3920 while (pos < valuelen)
3921 pos += append_weights( sortid, flags, value, valuelen, pos,
3922 case_mask, except, compr_tables, &val, TRUE );
3923 have_extra_val = remove_unneeded_weights( sortid, &val );
3924
3925 for (start = 0; start < srclen; start++)
3926 {
3927 pos = start;
3928 for (len = start + 1; len <= srclen; len++)
3929 {
3930 while (pos < len && s.primary_pos <= val.key_primary.len)
3931 {
3932 while (pos < len && !s.key_primary.len)
3933 pos += append_weights( sortid, flags, src, srclen, pos,
3934 case_mask, except, compr_tables, &s, TRUE );
3935
3936 if (s.primary_pos + s.key_primary.len > val.key_primary.len ||
3937 memcmp( primary, val.key_primary.buf + s.primary_pos, s.key_primary.len ))
3938 {
3939 len = srclen + 1;
3940 goto next;
3941 }
3942 s.primary_pos += s.key_primary.len;
3943 s.key_primary.len = 0;
3944 }
3945 if (s.primary_pos < val.key_primary.len) continue;
3946
3947 have_extra = remove_unneeded_weights( sortid, &s );
3948 if (compare_sortkeys( &s.key_diacritic, &val.key_diacritic, FALSE )) goto next;
3949 if (compare_sortkeys( &s.key_case, &val.key_case, FALSE )) goto next;
3950
3951 if (have_extra && have_extra_val)
3952 {
3953 for (i = 0; i < 4; i++)
3954 if (compare_sortkeys( &s.key_extra[i], &val.key_extra[i], i != 1 )) goto next;
3955 }
3956 else if (have_extra || have_extra_val) goto next;
3957
3958 if (compare_sortkeys( &s.key_special, &val.key_special, FALSE )) goto next;
3959
3960 found = start;
3961 foundlen = pos - start;
3962 len = srclen; /* no need to continue checking longer strings */
3963
3964 next:
3965 /* reset state */
3966 s.key_primary.len = s.key_diacritic.len = s.key_case.len = s.key_special.len = 0;
3967 s.key_extra[0].len = s.key_extra[1].len = s.key_extra[2].len = s.key_extra[3].len = 0;
3968 s.primary_pos = 0;
3969 pos = start;
3970 }
3971 if (flags & FIND_STARTSWITH) break;
3972 if (flags & FIND_FROMSTART && found != -1) break;
3973 }
3974
3975 if (found != -1)
3976 {
3977 if ((flags & FIND_ENDSWITH) && found + foundlen != srclen) found = -1;
3978 else if (reslen) *reslen = foundlen;
3979 }
3982 return found;
3983}
3984
3985
3986/* map buffer to full-width katakana */
3987static int map_to_fullwidth( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
3988{
3989 int pos, len;
3990
3991 for (pos = 0; srclen; pos++, src += len, srclen -= len)
3992 {
3993 unsigned int wch = casemap( charmaps[CHARMAP_FULLWIDTH], *src );
3994
3995 len = 1;
3996 if (srclen > 1)
3997 {
3999 {
4000 len = 2;
4001 wch = casemap_high( charmaps[CHARMAP_FULLWIDTH], src[0], src[1] );
4002 if (wch >= 0x10000)
4003 {
4004 put_utf16( dst, pos, dstlen, wch );
4005 pos++;
4006 continue;
4007 }
4008 }
4009 else if (src[1] == 0xff9e) /* dakuten (voiced sound) */
4010 {
4011 len = 2;
4012 if ((*src >= 0xff76 && *src <= 0xff84) ||
4013 (*src >= 0xff8a && *src <= 0xff8e) ||
4014 *src == 0x30fd)
4015 wch++;
4016 else if (*src == 0xff73)
4017 wch = 0x30f4; /* KATAKANA LETTER VU */
4018 else if (*src == 0xff9c)
4019 wch = 0x30f7; /* KATAKANA LETTER VA */
4020 else if (*src == 0x30f0)
4021 wch = 0x30f8; /* KATAKANA LETTER VI */
4022 else if (*src == 0x30f1)
4023 wch = 0x30f9; /* KATAKANA LETTER VE */
4024 else if (*src == 0xff66)
4025 wch = 0x30fa; /* KATAKANA LETTER VO */
4026 else
4027 len = 1;
4028 }
4029 else if (src[1] == 0xff9f) /* handakuten (semi-voiced sound) */
4030 {
4031 if (*src >= 0xff8a && *src <= 0xff8e)
4032 {
4033 wch += 2;
4034 len = 2;
4035 }
4036 }
4037 }
4038
4039 if (pos < dstlen) dst[pos] = table ? casemap( table, wch ) : wch;
4040 }
4041 return pos;
4042}
4043
4044
4045static inline int nonspace_ignored( WCHAR ch )
4046{
4047 if (get_char_type( CT_CTYPE2, ch ) != C2_OTHERNEUTRAL) return FALSE;
4048 return (get_char_type( CT_CTYPE3, ch ) & (C3_NONSPACING | C3_DIACRITIC));
4049}
4050
4051/* remove ignored chars for NORM_IGNORENONSPACE/NORM_IGNORESYMBOLS */
4052static int map_remove_ignored( DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
4053{
4054 int pos;
4055
4056 for (pos = 0; srclen; src++, srclen--)
4057 {
4059 {
4060 if (get_char_type( CT_CTYPE1, *src ) & C1_PUNCT) continue;
4061 if (get_char_type( CT_CTYPE3, *src ) & C3_SYMBOL) continue;
4062 }
4064 {
4065 WCHAR buffer[8];
4066 const WCHAR *decomp;
4067 unsigned int i, j, len;
4068
4069 if ((decomp = get_decomposition( *src, &len )) && len > 1)
4070 {
4071 for (i = j = 0; i < len; i++)
4072 if (!nonspace_ignored( decomp[i] )) buffer[j++] = decomp[i];
4073
4074 if (i > j) /* something was removed */
4075 {
4076 if (pos + j <= dstlen) memcpy( dst + pos, buffer, j * sizeof(WCHAR) );
4077 pos += j;
4078 continue;
4079 }
4080 }
4081 else if (nonspace_ignored( *src )) continue;
4082 }
4083 if (pos < dstlen) dst[pos] = *src;
4084 pos++;
4085 }
4086 return pos;
4087}
4088
4089
4090/* map full-width characters to single or double half-width characters. */
4091static int map_to_halfwidth( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
4092{
4093 static const BYTE katakana_map[] =
4094 {
4095 0x01, 0x00, 0x01, 0x00, /* U+30a8- */
4096 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, /* U+30b0- */
4097 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, /* U+30b8- */
4098 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, /* U+30c0- */
4099 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+30c8- */
4100 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, /* U+30d0- */
4101 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x00, /* U+30d8- */
4102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+30e0- */
4103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+30e8- */
4104 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x08, /* U+30f0- */
4105 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01 /* U+30f8- */
4106 };
4107 int pos;
4108
4109 for (pos = 0; srclen; src++, srclen--)
4110 {
4111 WCHAR ch = table ? casemap( table, *src ) : *src;
4112 USHORT shift = ch - 0x30ac;
4113 BYTE k;
4114
4115 if (shift < ARRAY_SIZE(katakana_map) && (k = katakana_map[shift]))
4116 {
4117 if (pos < dstlen - 1)
4118 {
4120 dst[pos + 1] = (k == 2) ? 0xff9f : 0xff9e;
4121 }
4122 pos += 2;
4123 }
4124 else
4125 {
4127 pos++;
4128 }
4129 }
4130 return pos;
4131}
4132
4133
4134static int lcmap_string( const struct sortguid *sortid, DWORD flags,
4135 const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
4136{
4137 const USHORT *case_table = NULL;
4138 int ret;
4139
4141 {
4142 if ((flags & LCMAP_TITLECASE) == LCMAP_TITLECASE) /* FIXME */
4143 {
4145 return 0;
4146 }
4147 case_table = sort.casemap + (flags & LCMAP_LINGUISTIC_CASING ? sortid->casemap : 0);
4148 case_table = case_table + 2 + (flags & LCMAP_LOWERCASE ? case_table[1] : 0);
4149 }
4150
4152 {
4153 case LCMAP_HIRAGANA:
4155 break;
4156 case LCMAP_KATAKANA:
4158 break;
4159 case LCMAP_HALFWIDTH:
4161 break;
4164 break;
4167 break;
4168 case LCMAP_FULLWIDTH:
4170 break;
4173 break;
4176 break;
4179 break;
4182 break;
4184 case NORM_IGNORESYMBOLS:
4187 {
4189 return 0;
4190 }
4192 break;
4193 case 0:
4194 if (case_table)
4195 {
4196 ret = casemap_string( case_table, src, srclen, dst, dstlen );
4197 case_table = NULL;
4198 break;
4199 }
4200 if (flags & LCMAP_BYTEREV)
4201 {
4202 ret = min( srclen, dstlen );
4203 memcpy( dst, src, ret * sizeof(WCHAR) );
4204 break;
4205 }
4206 /* fall through */
4207 default:
4209 return 0;
4210 }
4211
4212 if (dstlen && case_table) ret = casemap_string( case_table, dst, ret, dst, dstlen );
4214
4215 if (dstlen && dstlen < ret)
4216 {
4218 return 0;
4219 }
4220 return ret;
4221}
4222
4223
4224static int compare_tzdate( const TIME_FIELDS *tf, const SYSTEMTIME *compare )
4225{
4226 static const int month_lengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
4227 int first, last, limit, dayinsecs;
4228
4229 if (tf->Month < compare->wMonth) return -1; /* We are in a month before the date limit. */
4230 if (tf->Month > compare->wMonth) return 1; /* We are in a month after the date limit. */
4231
4232 /* if year is 0 then date is in day-of-week format, otherwise
4233 * it's absolute date.
4234 */
4235 if (!compare->wYear)
4236 {
4237 /* wDay is interpreted as number of the week in the month
4238 * 5 means: the last week in the month */
4239 /* calculate the day of the first DayOfWeek in the month */
4240 first = (6 + compare->wDayOfWeek - tf->Weekday + tf->Day) % 7 + 1;
4241 /* check needed for the 5th weekday of the month */
4242 last = month_lengths[tf->Month - 1] +
4243 (tf->Month == 2 && (!(tf->Year % 4) && (tf->Year % 100 || !(tf->Year % 400))));
4244 limit = first + 7 * (compare->wDay - 1);
4245 if (limit > last) limit -= 7;
4246 }
4247 else limit = compare->wDay;
4248
4249 limit = ((limit * 24 + compare->wHour) * 60 + compare->wMinute) * 60;
4250 dayinsecs = ((tf->Day * 24 + tf->Hour) * 60 + tf->Minute) * 60 + tf->Second;
4251 return dayinsecs - limit;
4252}
4253
4254
4256{
4257 int year;
4258 BOOL before_standard_date, after_daylight_date;
4259 LARGE_INTEGER t2;
4261
4262 if (!info->DaylightDate.wMonth) return TIME_ZONE_ID_UNKNOWN;
4263
4264 /* if year is 0 then date is in day-of-week format, otherwise it's absolute date */
4265 if (info->StandardDate.wMonth == 0 ||
4266 (info->StandardDate.wYear == 0 &&
4267 (info->StandardDate.wDay < 1 || info->StandardDate.wDay > 5 ||
4268 info->DaylightDate.wDay < 1 || info->DaylightDate.wDay > 5)))
4269 {
4271 return TIME_ZONE_ID_INVALID;
4272 }
4273
4274 if (!is_local) time.QuadPart -= info->Bias * (LONGLONG)600000000;
4276 year = tf.Year;
4277 if (!is_local)
4278 {
4279 t2.QuadPart = time.QuadPart - info->DaylightBias * (LONGLONG)600000000;
4280 RtlTimeToTimeFields( &t2, &tf );
4281 }
4282 if (tf.Year == year)
4283 before_standard_date = compare_tzdate( &tf, &info->StandardDate ) < 0;
4284 else
4285 before_standard_date = tf.Year < year;
4286
4287 if (!is_local)
4288 {
4289 t2.QuadPart = time.QuadPart - info->StandardBias * (LONGLONG)600000000;
4290 RtlTimeToTimeFields( &t2, &tf );
4291 }
4292 if (tf.Year == year)
4293 after_daylight_date = compare_tzdate( &tf, &info->DaylightDate ) >= 0;
4294 else
4295 after_daylight_date = tf.Year > year;
4296
4297 if (info->DaylightDate.wMonth < info->StandardDate.wMonth) /* Northern hemisphere */
4298 {
4299 if (before_standard_date && after_daylight_date) return TIME_ZONE_ID_DAYLIGHT;
4300 }
4301 else /* Down south */
4302 {
4303 if (before_standard_date || after_daylight_date) return TIME_ZONE_ID_DAYLIGHT;
4304 }
4305 return TIME_ZONE_ID_STANDARD;
4306}
4307
4308
4309/* Note: the Internal_ functions are not documented. The number of parameters
4310 * should be correct, but their exact meaning may not.
4311 */
4312
4313/******************************************************************************
4314 * Internal_EnumCalendarInfo (kernelbase.@)
4315 */
4317 const NLS_LOCALE_DATA *locale, CALID id,
4318 CALTYPE type, BOOL unicode, BOOL ex,
4319 BOOL exex, LPARAM lparam )
4320{
4321 const USHORT *calendars;
4322 USHORT cal = id;
4323 WCHAR buffer[256];
4324 INT ret, i, count = 1;
4325
4326 if (!proc || !locale)
4327 {
4329 return FALSE;
4330 }
4331
4332 if (id == ENUM_ALL_CALENDARS)
4333 {
4334 count = locale_strings[locale->scalendartype];
4335 calendars = locale_strings + locale->scalendartype + 1;
4336 }
4337 else if (id <= CAL_UMALQURA)
4338 {
4339 calendars = &cal;
4340 count = 1;
4341 }
4342 else
4343 {
4345 return FALSE;
4346 }
4347
4348 type &= ~CAL_RETURN_NUMBER;
4349
4350 for (i = 0; i < count; i++)
4351 {
4352 id = calendars[i];
4353 if (unicode)
4354 {
4356 }
4357 else
4358 {
4359 WCHAR bufW[256];
4360 ret = get_calendar_info( locale, id, type, bufW, ARRAY_SIZE(bufW), NULL );
4362 bufW, -1, (char *)buffer, sizeof(buffer), NULL, NULL );
4363 }
4364
4365 if (ret)
4366 {
4367 if (exex) ret = ((CALINFO_ENUMPROCEXEX)proc)( buffer, id, NULL, lparam );
4368 else if (ex) ret = ((CALINFO_ENUMPROCEXW)proc)( buffer, id );
4369 else ret = proc( buffer );
4370 }
4371 if (!ret) break;
4372 }
4373 return TRUE;
4374}
4375
4376
4378 DWORD str, WCHAR *buffer, CALID id, BOOL unicode,
4379 BOOL ex, BOOL exex, LPARAM lparam )
4380{
4381 char buffA[256];
4382
4383 if (str) memcpy( buffer, locale_strings + str + 1, (locale_strings[str] + 1) * sizeof(WCHAR) );
4384 if (exex) return ((DATEFMT_ENUMPROCEXEX)proc)( buffer, id, lparam );
4385 if (ex) return ((DATEFMT_ENUMPROCEXW)proc)( buffer, id );
4386 if (unicode) return proc( buffer );
4388 buffA, ARRAY_SIZE(buffA), NULL, NULL );
4389 return proc( (WCHAR *)buffA );
4390}
4391
4392
4393/**************************************************************************
4394 * Internal_EnumDateFormats (kernelbase.@)
4395 */
4397 const NLS_LOCALE_DATA *locale, DWORD flags,
4398 BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam )
4399{
4400 WCHAR buffer[256];
4401 INT i, j, ret;
4402 DWORD pos;
4403 const struct calendar *cal;
4404 const USHORT *calendars;
4405 const DWORD *array;
4406
4407 if (!proc || !locale)
4408 {
4410 return FALSE;
4411 }
4412
4413 calendars = locale_strings + locale->scalendartype;
4414
4415 switch (flags & ~LOCALE_USE_CP_ACP)
4416 {
4417 case 0:
4418 case DATE_SHORTDATE:
4420 pos = locale->sshortdate;
4421 break;
4422 case DATE_LONGDATE:
4424 pos = locale->slongdate;
4425 break;
4426 case DATE_YEARMONTH:
4427 if (!get_locale_info( locale, 0, LOCALE_SYEARMONTH, buffer, ARRAY_SIZE(buffer) )) return FALSE;
4428 pos = locale->syearmonth;
4429 break;
4430 default:
4432 return FALSE;
4433 }
4434
4435 /* first the user override data */
4436
4437 ret = call_enum_date_func( proc, locale, flags, 0, buffer, 1, unicode, ex, exex, lparam );
4438
4439 /* then the remaining locale data */
4440
4441 array = (const DWORD *)(locale_strings + pos + 1);
4442 for (i = 1; ret && i < locale_strings[pos]; i++)
4443 ret = call_enum_date_func( proc, locale, flags, array[i], buffer, 1, unicode, ex, exex, lparam );
4444
4445 /* then the extra calendars */
4446
4447 for (i = 0; ret && i < calendars[0]; i++)
4448 {
4449 if (calendars[i + 1] == 1) continue;
4450 if (!(cal = get_calendar_data( locale, calendars[i + 1] ))) continue;
4451 switch (flags & ~LOCALE_USE_CP_ACP)
4452 {
4453 case 0:
4454 case DATE_SHORTDATE:
4455 pos = cal->sshortdate;
4456 break;
4457 case DATE_LONGDATE:
4458 pos = cal->slongdate;
4459 break;
4460 case DATE_YEARMONTH:
4461 pos = cal->syearmonth;
4462 break;
4463 }
4464 array = (const DWORD *)(locale_strings + pos + 1);
4465 for (j = 0; ret && j < locale_strings[pos]; j++)
4467 calendars[i + 1], unicode, ex, exex, lparam );
4468 }
4469 return TRUE;
4470}
4471
4472
4473/******************************************************************************
4474 * Internal_EnumLanguageGroupLocales (kernelbase.@)
4475 */
4477 DWORD flags, LONG_PTR param, BOOL unicode )
4478{
4479 WCHAR name[10], value[10];
4480 DWORD name_len, value_len, type, index = 0, alt = 0;
4481 HKEY key, altkey;
4482 LCID lcid;
4483
4484 if (!proc || id < LGRPID_WESTERN_EUROPE || id > LGRPID_ARMENIAN)
4485 {
4487 return FALSE;
4488 }
4489
4490 if (RegOpenKeyExW( nls_key, L"Locale", 0, KEY_READ, &key )) return FALSE;
4491 if (RegOpenKeyExW( key, L"Alternate Sorts", 0, KEY_READ, &altkey )) altkey = 0;
4492
4493 for (;;)
4494 {
4495 name_len = ARRAY_SIZE(name);
4496 value_len = sizeof(value);
4497 if (RegEnumValueW( alt ? altkey : key, index++, name, &name_len, NULL,
4498 &type, (BYTE *)value, &value_len ))
4499 {
4500 if (alt++) break;
4501 index = 0;
4502 continue;
4503 }
4504 if (type != REG_SZ) continue;
4505 if (id != wcstoul( value, NULL, 16 )) continue;
4506 lcid = wcstoul( name, NULL, 16 );
4507 if (!unicode)
4508 {
4509 char nameA[10];
4510 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
4511 if (!((LANGGROUPLOCALE_ENUMPROCA)proc)( id, lcid, nameA, param )) break;
4512 }
4513 else if (!proc( id, lcid, name, param )) break;
4514 }
4515 RegCloseKey( altkey );
4516 RegCloseKey( key );
4517 return TRUE;
4518}
4519
4520
4521/***********************************************************************
4522 * Internal_EnumSystemCodePages (kernelbase.@)
4523 */
4525 BOOL unicode )
4526{
4527 WCHAR name[10];
4528 DWORD name_len, type, index = 0;
4529 HKEY key;
4530
4531 if (RegOpenKeyExW( nls_key, L"Codepage", 0, KEY_READ, &key )) return FALSE;
4532
4533 for (;;)
4534 {
4535 name_len = ARRAY_SIZE(name);
4536 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, NULL, NULL )) break;
4537 if (type != REG_SZ) continue;
4538 if (!wcstoul( name, NULL, 10 )) continue;
4539 if (!unicode)
4540 {
4541 char nameA[10];
4542 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
4543 if (!((CODEPAGE_ENUMPROCA)proc)( nameA )) break;
4544 }
4545 else if (!proc( name )) break;
4546 }
4547 RegCloseKey( key );
4548 return TRUE;
4549}
4550
4551
4552/******************************************************************************
4553 * Internal_EnumSystemLanguageGroups (kernelbase.@)
4554 */
4556 DWORD flags, LONG_PTR param, BOOL unicode )
4557{
4558 WCHAR name[10], value[10], descr[80];
4559 DWORD name_len, value_len, type, index = 0;
4560 HKEY key;
4561 LGRPID id;
4562
4563 if (!proc)
4564 {
4566 return FALSE;
4567 }
4568
4569 switch (flags)
4570 {
4571 case 0:
4573 break;
4574 case LGRPID_INSTALLED:
4575 case LGRPID_SUPPORTED:
4576 break;
4577 default:
4579 return FALSE;
4580 }
4581
4582 if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE;
4583
4584 for (;;)
4585 {
4586 name_len = ARRAY_SIZE(name);
4587 value_len = sizeof(value);
4588 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, (BYTE *)value, &value_len )) break;
4589 if (type != REG_SZ) continue;
4590
4591 id = wcstoul( name, NULL, 16 );
4592
4593 if (!(flags & LGRPID_SUPPORTED) && !wcstoul( value, NULL, 10 )) continue;
4595 TRACE( "%p: %lu %s %s %lx %Ix\n", proc, id, debugstr_w(name), debugstr_w(descr), flags, param );
4596 if (!unicode)
4597 {
4598 char nameA[10], descrA[80];
4599 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
4600 WideCharToMultiByte( CP_ACP, 0, descr, -1, descrA, sizeof(descrA), NULL, NULL );
4601 if (!((LANGUAGEGROUP_ENUMPROCA)proc)( id, nameA, descrA, flags, param )) break;
4602 }
4603 else if (!proc( id, name, descr, flags, param )) break;
4604 }
4605 RegCloseKey( key );
4606 return TRUE;
4607}
4608
4609
4610/**************************************************************************
4611 * Internal_EnumTimeFormats (kernelbase.@)
4612 */
4614 const NLS_LOCALE_DATA *locale, DWORD flags,
4615 BOOL unicode, BOOL ex, LPARAM lparam )
4616{
4617 WCHAR buffer[256];
4618 INT ret = TRUE;
4619 const DWORD *array;
4620 DWORD pos, i;
4621
4622 if (!proc || !locale)
4623 {
4625 return FALSE;
4626 }
4627 switch (flags & ~LOCALE_USE_CP_ACP)
4628 {
4629 case 0:
4631 pos = locale->stimeformat;
4632 break;
4633 case TIME_NOSECONDS:
4635 pos = locale->sshorttime;
4636 break;
4637 default:
4638 FIXME( "Unknown time format %lx\n", flags );
4640 return FALSE;
4641 }
4642
4643 array = (const DWORD *)(locale_strings + pos + 1);
4644 for (i = 0; ret && i < locale_strings[pos]; i++)
4645 {
4646 if (i) memcpy( buffer, locale_strings + array[i] + 1,
4647 (locale_strings[array[i]] + 1) * sizeof(WCHAR) );
4648
4649 if (ex) ret = ((TIMEFMT_ENUMPROCEX)proc)( buffer, lparam );
4650 else if (unicode) ret = proc( buffer );
4651 else
4652 {
4653 char buffA[256];
4655 buffA, ARRAY_SIZE(buffA), NULL, NULL );
4656 ret = proc( (WCHAR *)buffA );
4657 }
4658 }
4659 return TRUE;
4660}
4661
4662
4663/******************************************************************************
4664 * Internal_EnumUILanguages (kernelbase.@)
4665 */
4667 LONG_PTR param, BOOL unicode )
4668{
4670 char nameA[LOCALE_NAME_MAX_LENGTH];
4671 DWORD i;
4672
4673 if (!proc)
4674 {
4676 return FALSE;
4677 }
4678 if (flags & ~(MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME))
4679 {
4681 return FALSE;
4682 }
4683
4684 for (i = 0; i < locale_table->nb_lcnames; i++)
4685 {
4686 if (!lcnames_index[i].name) continue; /* skip invariant locale */
4687 if (lcnames_index[i].id & 0x80000000) continue; /* skip aliases */
4688 if (!get_locale_data( lcnames_index[i].idx )->inotneutral) continue; /* skip neutral locales */
4689 if (SORTIDFROMLCID( lcnames_index[i].id )) continue; /* skip alternate sorts */
4690 if (flags & MUI_LANGUAGE_NAME)
4691 {
4692 const WCHAR *str = locale_strings + lcnames_index[i].name;
4693
4694 if (unicode)
4695 {
4696 memcpy( nameW, str + 1, (*str + 1) * sizeof(WCHAR) );
4697 if (!proc( nameW, param )) break;
4698 }
4699 else
4700 {
4701 WideCharToMultiByte( CP_ACP, 0, str + 1, -1, nameA, sizeof(nameA), NULL, NULL );
4702 if (!((UILANGUAGE_ENUMPROCA)proc)( nameA, param )) break;
4703 }
4704 }
4705 else
4706 {
4707 if (lcnames_index[i].id == LOCALE_CUSTOM_UNSPECIFIED) continue; /* skip locales with no lcid */
4708 if (unicode)
4709 {
4710 swprintf( nameW, ARRAY_SIZE(nameW), L"%04lx", lcnames_index[i].id );
4711 if (!proc( nameW, param )) break;
4712 }
4713 else
4714 {
4715 sprintf( nameA, "%04x", lcnames_index[i].id );
4716 if (!((UILANGUAGE_ENUMPROCA)proc)( nameA, param )) break;
4717 }
4718 }
4719 }
4720 return TRUE;
4721}
4722
4723
4724/******************************************************************************
4725 * CompareStringEx (kernelbase.@)
4726 */
4727INT WINAPI CompareStringEx( const WCHAR *locale, DWORD flags, const WCHAR *str1, int len1,
4728 const WCHAR *str2, int len2, NLSVERSIONINFO *version,
4729 void *reserved, LPARAM handle )
4730{
4731 const struct sortguid *sortid;
4732 const DWORD supported_flags = NORM_IGNORECASE | NORM_IGNORENONSPACE | NORM_IGNORESYMBOLS |
4736 0x10000000 | LOCALE_USE_CP_ACP;
4737 /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
4738 int ret;
4739
4740 if (version) FIXME( "unexpected version parameter\n" );
4741 if (reserved) FIXME( "unexpected reserved value\n" );
4742 if (handle) FIXME( "unexpected handle\n" );
4743
4744 if (flags & ~supported_flags)
4745 {
4747 return 0;
4748 }
4749
4750 if (!(sortid = get_language_sort( locale ))) return 0;
4751
4752 if (!str1 || !str2)
4753 {
4755 return 0;
4756 }
4757
4758 if (len1 < 0) len1 = lstrlenW(str1);
4759 if (len2 < 0) len2 = lstrlenW(str2);
4760
4761 ret = compare_string( sortid, flags, str1, len1, str2, len2 );
4762 if (ret < 0) return CSTR_LESS_THAN;
4763 if (ret > 0) return CSTR_GREATER_THAN;
4764 return CSTR_EQUAL;
4765}
4766
4767
4768/******************************************************************************
4769 * CompareStringA (kernelbase.@)
4770 */
4772 const char *str2, int len2 )
4773{
4774 WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
4775 WCHAR *buf2W = buf1W + 130;
4776 LPWSTR str1W, str2W;
4777 INT len1W = 0, len2W = 0, ret;
4778 UINT locale_cp = CP_ACP;
4779
4780 if (!str1 || !str2)
4781 {
4783 return 0;
4784 }
4785
4787 {
4789 return 0;
4790 }
4791
4792 if (len1 < 0) len1 = strlen(str1);
4793 if (len2 < 0) len2 = strlen(str2);
4794
4795 locale_cp = get_lcid_codepage( lcid, flags );
4796 if (len1)
4797 {
4798 if (len1 <= 130) len1W = MultiByteToWideChar( locale_cp, 0, str1, len1, buf1W, 130 );
4799 if (len1W) str1W = buf1W;
4800 else
4801 {
4802 len1W = MultiByteToWideChar( locale_cp, 0, str1, len1, NULL, 0 );
4803 str1W = HeapAlloc( GetProcessHeap(), 0, len1W * sizeof(WCHAR) );
4804 if (!str1W)
4805 {
4807 return 0;
4808 }
4809 MultiByteToWideChar( locale_cp, 0, str1, len1, str1W, len1W );
4810 }
4811 }
4812 else
4813 {
4814 len1W = 0;
4815 str1W = buf1W;
4816 }
4817
4818 if (len2)
4819 {
4820 if (len2 <= 130) len2W = MultiByteToWideChar( locale_cp, 0, str2, len2, buf2W, 130 );
4821 if (len2W) str2W = buf2W;
4822 else
4823 {
4824 len2W = MultiByteToWideChar( locale_cp, 0, str2, len2, NULL, 0 );
4825 str2W = HeapAlloc( GetProcessHeap(), 0, len2W * sizeof(WCHAR) );
4826 if (!str2W)
4827 {
4828 if (str1W != buf1W) HeapFree( GetProcessHeap(), 0, str1W );
4830 return 0;
4831 }
4832 MultiByteToWideChar( locale_cp, 0, str2, len2, str2W, len2W );
4833 }
4834 }
4835 else
4836 {
4837 len2W = 0;
4838 str2W = buf2W;
4839 }
4840
4841 ret = CompareStringW( lcid, flags, str1W, len1W, str2W, len2W );
4842
4843 if (str1W != buf1W) HeapFree( GetProcessHeap(), 0, str1W );
4844 if (str2W != buf2W) HeapFree( GetProcessHeap(), 0, str2W );
4845 return ret;
4846}
4847
4848
4849/******************************************************************************
4850 * CompareStringW (kernelbase.@)
4851 */
4853 const WCHAR *str2, int len2 )
4854{
4856 const NLS_LOCALE_LCID_INDEX *entry;
4857
4858 switch (lcid)
4859 {
4860 case LOCALE_NEUTRAL:
4866 break;
4867 default:
4868 if (lcid == user_lcid || lcid == system_lcid) break;
4869 if (!(entry = find_lcid_entry( lcid )))
4870 {
4871 WARN( "unknown locale %04lx\n", lcid );
4873 return 0;
4874 }
4875 locale = locale_strings + entry->name + 1;
4876 break;
4877 }
4878
4879 return CompareStringEx( locale, flags, str1, len1, str2, len2, NULL, NULL, 0 );
4880}
4881
4882
4883/******************************************************************************
4884 * CompareStringOrdinal (kernelbase.@)
4885 */
4887 const WCHAR *str2, INT len2, BOOL ignore_case )
4888{
4889 int ret;
4890
4891 if (!str1 || !str2)
4892 {
4894 return 0;
4895 }
4896 if (len1 < 0) len1 = lstrlenW( str1 );
4897 if (len2 < 0) len2 = lstrlenW( str2 );
4898
4899 ret = RtlCompareUnicodeStrings( str1, len1, str2, len2, ignore_case );
4900 if (ret < 0) return CSTR_LESS_THAN;
4901 if (ret > 0) return CSTR_GREATER_THAN;
4902 return CSTR_EQUAL;
4903}
4904
4905
4906/******************************************************************************
4907 * ConvertDefaultLocale (kernelbase.@)
4908 */
4910{
4911 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
4912 if (locale) lcid = locale->ilanguage;
4913 return lcid;
4914}
4915
4916
4917/******************************************************************************
4918 * EnumCalendarInfoW (kernelbase.@)
4919 */
4921 CALID id, CALTYPE type )
4922{
4924 id, type, TRUE, FALSE, FALSE, 0 );
4925}
4926
4927
4928/******************************************************************************
4929 * EnumCalendarInfoExW (kernelbase.@)
4930 */
4932 CALID id, CALTYPE type )
4933{
4935 id, type, TRUE, TRUE, FALSE, 0 );
4936}
4937
4938/******************************************************************************
4939 * EnumCalendarInfoExEx (kernelbase.@)
4940 */
4943{
4944 LCID lcid;
4946 id, type, TRUE, TRUE, TRUE, lparam );
4947}
4948
4949
4950/**************************************************************************
4951 * EnumDateFormatsW (kernelbase.@)
4952 */
4954{
4956 flags, TRUE, FALSE, FALSE, 0 );
4957}
4958
4959
4960/**************************************************************************
4961 * EnumDateFormatsExW (kernelbase.@)
4962 */
4964{
4966 flags, TRUE, TRUE, FALSE, 0 );
4967}
4968
4969
4970/**************************************************************************
4971 * EnumDateFormatsExEx (kernelbase.@)
4972 */
4975{
4976 LCID lcid;
4978 flags, TRUE, TRUE, TRUE, lparam );
4979}
4980
4981
4982
4983/******************************************************************************
4984 * EnumDynamicTimeZoneInformation (kernelbase.@)
4985 */
4988{
4990 LSTATUS ret;
4991 DWORD size;
4992
4993 if (!info) return ERROR_INVALID_PARAMETER;
4994
4995 size = ARRAY_SIZE(tz.TimeZoneKeyName);
4996 ret = RegEnumKeyExW( tz_key, index, tz.TimeZoneKeyName, &size, NULL, NULL, NULL, NULL );
4997 if (ret) return ret;
4998
4999 tz.DynamicDaylightTimeDisabled = TRUE;
5001
5002 lstrcpyW( info->TimeZoneKeyName, tz.TimeZoneKeyName );
5003 info->DynamicDaylightTimeDisabled = FALSE;
5004 return 0;
5005}
5006
5007
5008/******************************************************************************
5009 * EnumLanguageGroupLocalesW (kernelbase.@)
5010 */
5013{
5015}
5016
5017
5018/******************************************************************************
5019 * EnumUILanguagesW (kernelbase.@)
5020 */
5022{
5024}
5025
5026
5027/***********************************************************************
5028 * EnumSystemCodePagesW (kernelbase.@)
5029 */
5031{
5033}
5034
5035
5036/******************************************************************************
5037 * EnumSystemGeoID (kernelbase.@)
5038 */
5040{
5041 INT i;
5042
5043 TRACE( "(%ld, %ld, %p)\n", class, parent, proc );
5044
5045 if (!proc)
5046 {
5048 return FALSE;
5049 }
5050 if (class != GEOCLASS_NATION && class != GEOCLASS_REGION && class != GEOCLASS_ALL)
5051 {
5053 return FALSE;
5054 }
5055
5056 for (i = 0; i < geo_ids_count; i++)
5057 {
5058 if (class != GEOCLASS_ALL && geo_ids[i].class != class) continue;
5059 if (parent && geo_ids[i].parent != parent) continue;
5060 if (!proc( geo_ids[i].id )) break;
5061 }
5062 return TRUE;
5063}
5064
5065
5066/******************************************************************************
5067 * EnumSystemLanguageGroupsW (kernelbase.@)
5068 */
5071{
5073}
5074
5075
5076/******************************************************************************
5077 * EnumSystemLocalesA (kernelbase.@)
5078 */
5080{
5081 char name[10];
5082 DWORD i;
5083
5084 if (!flags)
5086
5087 for (i = 0; i < locale_table->nb_lcnames; i++)
5088 {
5089 if (!lcnames_index[i].name) continue; /* skip invariant locale */
5090 if (lcnames_index[i].id == LOCALE_CUSTOM_UNSPECIFIED) continue; /* skip locales with no lcid */
5091 if (lcnames_index[i].id & 0x80000000) continue; /* skip aliases */
5092 if (!get_locale_data( lcnames_index[i].idx )->inotneutral) continue; /* skip neutral locales */
5094 continue; /* skip alternate sorts if not requested */
5096 continue; /* skip default sorts if not requested */
5097 sprintf( name, "%08x", lcnames_index[i].id );
5098 if (!proc( name )) break;
5099 }
5100 return TRUE;
5101}
5102
5103
5104/******************************************************************************
5105 * EnumSystemLocalesW (kernelbase.@)
5106 */
5108{
5109 WCHAR name[10];
5110 DWORD i;
5111
5112 if (!flags)
5114
5115 for (i = 0; i < locale_table->nb_lcnames; i++)
5116 {
5117 if (!lcnames_index[i].name) continue; /* skip invariant locale */
5118 if (lcnames_index[i].id == LOCALE_CUSTOM_UNSPECIFIED) continue; /* skip locales with no lcid */
5119 if (lcnames_index[i].id & 0x80000000) continue; /* skip aliases */
5120 if (!get_locale_data( lcnames_index[i].idx )->inotneutral) continue; /* skip neutral locales */
5122 continue; /* skip alternate sorts if not requested */
5124 continue; /* skip default sorts if not requested */
5125 swprintf( name, ARRAY_SIZE(name), L"%08lx", lcnames_index[i].id );
5126 if (!proc( name )) break;
5127 }
5128 return TRUE;
5129}
5130
5131
5132/******************************************************************************
5133 * EnumSystemLocalesEx (kernelbase.@)
5134 */
5136 LPARAM param, void *reserved )
5137{
5139 DWORD i, flags;
5140
5141 if (reserved)
5142 {
5144 return FALSE;
5145 }
5146
5147 for (i = 0; i < locale_table->nb_lcnames; i++)
5148 {
5149 const NLS_LOCALE_DATA *locale = get_locale_data( lcnames_index[i].idx );
5150 const WCHAR *str = locale_strings + lcnames_index[i].name;
5151
5152 if (lcnames_index[i].id & 0x80000000) continue; /* skip aliases */
5153 memcpy( buffer, str + 1, (*str + 1) * sizeof(WCHAR) );
5154 if (SORTIDFROMLCID( lcnames_index[i].id ) || wcschr( str + 1, '_' ))
5156 else
5158 if (wanted_flags && !(flags & wanted_flags)) continue;
5159 if (!proc( buffer, flags, param )) break;
5160 }
5161 return TRUE;
5162}
5163
5164
5165/**************************************************************************
5166 * EnumTimeFormatsW (kernelbase.@)
5167 */
5169{
5171}
5172
5173
5174/**************************************************************************
5175 * EnumTimeFormatsEx (kernelbase.@)
5176 */
5179{
5180 LCID lcid;
5182 flags, TRUE, TRUE, lparam );
5183}
5184
5185
5186/**************************************************************************
5187 * FindNLSString (kernelbase.@)
5188 */
5190 int srclen, const WCHAR *value, int valuelen, int *found )
5191{
5193 const NLS_LOCALE_LCID_INDEX *entry;
5194
5195 switch (lcid)
5196 {
5197 case LOCALE_NEUTRAL:
5203 break;
5204 default:
5205 if (lcid == user_lcid || lcid == system_lcid) break;
5206 if (!(entry = find_lcid_entry( lcid )))
5207 {
5208 WARN( "unknown locale %04lx\n", lcid );
5210 return 0;
5211 }
5212 locale = locale_strings + entry->name + 1;
5213 break;
5214 }
5215
5216 return FindNLSStringEx( locale, flags, src, srclen, value, valuelen, found, NULL, NULL, 0 );
5217}
5218
5219
5220/**************************************************************************
5221 * FindNLSStringEx (kernelbase.@)
5222 */
5224 int srclen, const WCHAR *value, int valuelen, int *found,
5226{
5227 const struct sortguid *sortid;
5228
5229 TRACE( "%s %lx %s %d %s %d %p %p %p %Id\n", wine_dbgstr_w(locale), flags,
5230 wine_dbgstr_w(src), srclen, wine_dbgstr_w(value), valuelen, found,
5232
5233 if (version) FIXME( "unexpected version parameter\n" );
5234 if (reserved) FIXME( "unexpected reserved value\n" );
5235 if (handle) FIXME( "unexpected handle\n" );
5236
5237 if (!src || !srclen || srclen < -1 || !value || !valuelen || valuelen < -1)
5238 {
5240 return -1;
5241 }
5242 if (!(sortid = get_language_sort( locale ))) return -1;
5243
5244 if (srclen == -1) srclen = lstrlenW(src);
5245 if (valuelen == -1) valuelen = lstrlenW(value);
5246
5247 return find_substring( sortid, flags, src, srclen, value, valuelen, found );
5248}
5249
5250
5251/******************************************************************************
5252 * FindStringOrdinal (kernelbase.@)
5253 */
5255 const WCHAR *val, INT val_size, BOOL ignore_case )
5256{
5257 INT offset, inc, count;
5258
5259 TRACE( "%#lx %s %d %s %d %d\n", flag, wine_dbgstr_w(src), src_size,
5260 wine_dbgstr_w(val), val_size, ignore_case );
5261
5262 if (!src || !val)
5263 {
5265 return -1;
5266 }
5267
5269 {
5271 return -1;
5272 }
5273
5274 if (src_size == -1) src_size = lstrlenW( src );
5275 if (val_size == -1) val_size = lstrlenW( val );
5276
5278 src_size -= val_size;
5279 if (src_size < 0) return -1;
5280
5281 count = flag & (FIND_FROMSTART | FIND_FROMEND) ? src_size + 1 : 1;
5282 offset = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : src_size;
5283 inc = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
5284 while (count--)
5285 {
5286 if (CompareStringOrdinal( src + offset, val_size, val, val_size, ignore_case ) == CSTR_EQUAL)
5287 return offset;
5288 offset += inc;
5289 }
5290 return -1;
5291}
5292
5293
5294/******************************************************************************
5295 * FoldStringW (kernelbase.@)
5296 */
5298{
5300 WCHAR *buf = dst;
5301 int len = dstlen;
5302
5303 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
5304 {
5306 return 0;
5307 }
5308 if (srclen == -1) srclen = lstrlenW(src) + 1;
5309
5311 {
5312 len = srclen * 4;
5313 if (!(buf = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
5314 {
5316 return 0;
5317 }
5318 }
5319
5320 for (;;)
5321 {
5323 if (buf != dst) RtlFreeHeap( GetProcessHeap(), 0, buf );
5324 if (status != STATUS_BUFFER_TOO_SMALL) break;
5325 if (!(buf = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
5326 {
5328 return 0;
5329 }
5330 }
5332 {
5334 return 0;
5335 }
5336 if (!set_ntstatus( status )) return 0;
5337
5339 return len;
5340}
5341
5342
5343static const WCHAR *get_message( DWORD flags, const void *src, UINT id, UINT lang,
5344 BOOL ansi, WCHAR **buffer )
5345{
5346 DWORD len;
5347
5349 {
5352
5354 {
5356 if (!module) module = GetModuleHandleW( 0 );
5358 }
5360 {
5361 /* Fold win32 hresult to its embedded error code. */
5363 id = HRESULT_CODE( id );
5365 }
5366 if (!set_ntstatus( status )) return NULL;
5367
5368 src = entry->Text;
5369 ansi = !(entry->Flags & MESSAGE_RESOURCE_UNICODE);
5370 }
5371
5372 if (!ansi) return src;
5373 len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
5374 if (!(*buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
5375 MultiByteToWideChar( CP_ACP, 0, src, -1, *buffer, len );
5376 return *buffer;
5377}
5378
5379
5380/***********************************************************************
5381 * FormatMessageA (kernelbase.@)
5382 */
5384 char *buffer, DWORD size, va_list *args )
5385{
5386 DWORD ret = 0;
5387 ULONG len, retsize = 0;
5389 const WCHAR *src;
5390 WCHAR *result, *message = NULL;
5392
5393 TRACE( "(0x%lx,%p,%#lx,0x%lx,%p,%lu,%p)\n", flags, source, msgid, langid, buffer, size, args );
5394
5396 {
5397 if (!buffer)
5398 {
5400 return 0;
5401 }
5402 *(char **)buffer = NULL;
5403 }
5404 if (size >= 32768)
5405 {
5407 return 0;
5408 }
5409
5410 if (width == 0xff) width = ~0u;
5411
5412 if (!(src = get_message( flags, source, msgid, langid, TRUE, &message ))) return 0;
5413
5414 if (!(result = HeapAlloc( GetProcessHeap(), 0, 65536 )))
5416 else
5419 result, 65536, &retsize );
5420
5422
5424 {
5426 goto done;
5427 }
5428 if (!set_ntstatus( status )) goto done;
5429
5430 len = WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), NULL, 0, NULL, NULL );
5431 if (len <= 1)
5432 {
5433 SetLastError( ERROR_NO_WORK_DONE );
5434 goto done;
5435 }
5436
5438 {
5439 char *buf = LocalAlloc( LMEM_ZEROINIT, max( size, len ));
5440 if (!buf)
5441 {
5443 goto done;
5444 }
5445 *(char **)buffer = buf;
5446 WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), buf, max( size, len ), NULL, NULL );
5447 }
5448 else if (len > size)
5449 {
5451 goto done;
5452 }
5453 else WideCharToMultiByte( CP_ACP, 0, result, retsize / sizeof(WCHAR), buffer, size, NULL, NULL );
5454
5455 ret = len - 1;
5456
5457done:
5459 return ret;
5460}
5461
5462
5463/***********************************************************************
5464 * FormatMessageW (kernelbase.@)
5465 */
5468{
5469 ULONG retsize = 0;
5471 const WCHAR *src;
5472 WCHAR *message = NULL;
5474
5475 TRACE( "(0x%lx,%p,%#lx,0x%lx,%p,%lu,%p)\n", flags, source, msgid, langid, buffer, size, args );
5476
5477 if (!buffer)
5478 {
5480 return 0;
5481 }
5482
5483 if (width == 0xff) width = ~0u;
5484
5486
5487 if (!(src = get_message( flags, source, msgid, langid, FALSE, &message ))) return 0;
5488
5490 {
5491 WCHAR *result;
5492 va_list args_copy;
5493 ULONG alloc = max( size * sizeof(WCHAR), 65536 );
5494
5495 for (;;)
5496 {
5497 if (!(result = HeapAlloc( GetProcessHeap(), 0, alloc )))
5498 {
5500 break;
5501 }
5503 {
5504 va_copy( args_copy, *args );
5506 FALSE, FALSE, &args_copy, result, alloc, &retsize );
5507 va_end( args_copy );
5508 }
5509 else
5511 FALSE, TRUE, args, result, alloc, &retsize );
5512
5513 if (!status)
5514 {
5515 if (retsize <= sizeof(WCHAR)) HeapFree( GetProcessHeap(), 0, result );
5517 result, max( retsize, size * sizeof(WCHAR) ));
5518 break;
5519 }
5521 if (status != STATUS_BUFFER_OVERFLOW) break;
5522 alloc *= 2;
5523 }
5524 }
5527 buffer, size * sizeof(WCHAR), &retsize );
5528
5530
5532 {
5533 if (size) buffer[size - 1] = 0;
5535 return 0;
5536 }
5537 if (!set_ntstatus( status )) return 0;
5538 if (retsize <= sizeof(WCHAR)) SetLastError( ERROR_NO_WORK_DONE );
5539 return retsize / sizeof(WCHAR) - 1;
5540}
5541
5542
5543/******************************************************************************
5544 * GetACP (kernelbase.@)
5545 */
5547{
5548 return ansi_cpinfo.CodePage;
5549}
5550
5551
5552/***********************************************************************
5553 * GetCPInfo (kernelbase.@)
5554 */
5556{
5557 const CPTABLEINFO *table;
5558
5559 if (!cpinfo || !(table = get_codepage_table( codepage )))
5560 {
5562 return FALSE;
5563 }
5564 cpinfo->MaxCharSize = table->MaximumCharacterSize;
5565 memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) );
5566 memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) );
5567 return TRUE;
5568}
5569
5570
5571/***********************************************************************
5572 * GetCPInfoExW (kernelbase.@)
5573 */
5575{
5576 const CPTABLEINFO *table;
5577 int min, max, pos;
5578
5579 if (!cpinfo || !(table = get_codepage_table( codepage )))
5580 {
5582 return FALSE;
5583 }
5584 cpinfo->MaxCharSize = table->MaximumCharacterSize;
5585 memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) );
5586 memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) );
5587 cpinfo->CodePage = table->CodePage;
5588 cpinfo->UnicodeDefaultChar = table->UniDefaultChar;
5589
5590 min = 0;
5592 cpinfo->CodePageName[0] = 0;
5593 while (min <= max)
5594 {
5595 pos = (min + max) / 2;
5596 if (codepage_names[pos].cp < cpinfo->CodePage) min = pos + 1;
5597 else if (codepage_names[pos].cp > cpinfo->CodePage) max = pos - 1;
5598 else
5599 {
5600 wcscpy( cpinfo->CodePageName, codepage_names[pos].name );
5601 break;
5602 }
5603 }
5604 return TRUE;
5605}
5606
5607
5608/***********************************************************************
5609 * GetCalendarInfoW (kernelbase.@)
5610 */
5613{
5614 const NLS_LOCALE_DATA *locale;
5615
5616 TRACE( "%04lx %lu 0x%lx %p %d %p\n", lcid, calendar, type, buffer, len, value );
5617
5618 if (!(locale = NlsValidateLocale( &lcid, 0 )))
5619 {
5621 return 0;
5622 }
5624}
5625
5626
5627/***********************************************************************
5628 * GetCalendarInfoEx (kernelbase.@)
5629 */
5632{
5633 LCID lcid;
5634 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
5635
5636 TRACE( "%s %lu 0x%lx %p %d %p\n", debugstr_w(name), calendar, type, buffer, len, value );
5637
5638 if (!locale)
5639 {
5641 return 0;
5642 }
5644}
5645
5646
5649{
5650 0, 0, &tzname_section,
5652 0, 0, { (DWORD_PTR)(__FILE__ ": tzname_section") }
5653};
5654static CRITICAL_SECTION tzname_section = { &tzname_section_debug, -1, 0, 0, 0, 0 };
5655static struct {
5661
5662/***********************************************************************
5663 * GetDynamicTimeZoneInformation (kernelbase.@)
5664 */
5666{
5667 HKEY key;
5669
5671 return TIME_ZONE_ID_INVALID;
5672
5674 if (cached_tzname.lcid == GetThreadLocale() &&
5675 !wcscmp( info->TimeZoneKeyName, cached_tzname.key_name ))
5676 {
5677 wcscpy( info->StandardName, cached_tzname.standard_name );
5678 wcscpy( info->DaylightName, cached_tzname.daylight_name );
5680 }
5681 else
5682 {
5684 if (!RegOpenKeyExW( tz_key, info->TimeZoneKeyName, 0, KEY_ALL_ACCESS, &key ))
5685 {
5686 RegLoadMUIStringW( key, L"MUI_Std", info->StandardName,
5687 sizeof(info->StandardName), NULL, 0, system_dir );
5688 RegLoadMUIStringW( key, L"MUI_Dlt", info->DaylightName,
5689 sizeof(info->DaylightName), NULL, 0, system_dir );
5690 RegCloseKey( key );
5691 }
5692 else return TIME_ZONE_ID_INVALID;
5693
5696 wcscpy( cached_tzname.key_name, info->TimeZoneKeyName );
5697 wcscpy( cached_tzname.standard_name, info->StandardName );
5698 wcscpy( cached_tzname.daylight_name, info->DaylightName );
5700 }
5701
5704}
5705
5706
5707/******************************************************************************
5708 * GetDynamicTimeZoneInformationEffectiveYears (kernelbase.@)
5709 */
5711 DWORD *first, DWORD *last )
5712{
5713 HKEY key, dst_key = 0;
5715
5716 if (RegOpenKeyExW( tz_key, info->TimeZoneKeyName, 0, KEY_ALL_ACCESS, &key )) return ret;
5717
5718 if (RegOpenKeyExW( key, L"Dynamic DST", 0, KEY_ALL_ACCESS, &dst_key )) goto done;
5719 count = sizeof(DWORD);
5720 if (RegQueryValueExW( dst_key, L"FirstEntry", NULL, &type, (BYTE *)first, &count )) goto done;
5721 if (type != REG_DWORD) goto done;
5722 count = sizeof(DWORD);
5723 if (RegQueryValueExW( dst_key, L"LastEntry", NULL, &type, (BYTE *)last, &count )) goto done;
5724 if (type != REG_DWORD) goto done;
5725 ret = 0;
5726
5727done:
5728 RegCloseKey( dst_key );
5729 RegCloseKey( key );
5730 return ret;
5731}
5732
5733
5734#define MUI_SIGNATURE 0xfecdfecd
5736{
5762};
5763
5764
5766{
5767 if (size >= sizeof(DWORD) && mui->signature != MUI_SIGNATURE)
5768 {
5770 return FALSE;
5771 }
5772
5773 size = min( size, mui->size );
5774 if (size < sizeof(*mui) ||
5775 mui->ln_type_name_off >= size || mui->ln_type_name_size > size - mui->ln_type_name_off ||
5776 mui->ln_type_id_off >= size || mui->ln_type_id_size > size - mui->ln_type_id_off ||
5778 mui->mui_type_id_off >= size || mui->mui_type_id_size > size - mui->mui_type_id_off ||
5779 mui->lang_off >= size || mui->lang_size > size - mui->lang_off ||
5781 {
5783 return FALSE;
5784 }
5785 return TRUE;
5786}
5787
5788
5789/******************************************************************************
5790 * GetFileMUIInfo (kernelbase.@)
5791 */
5794{
5795 DWORD off, mui_size, type = MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL;
5796 struct mui_resource *mui = NULL;
5797 HMODULE hmod;
5798 HRSRC hrsrc;
5799
5800 TRACE( "%lu, %s, %p, %p\n", flags, debugstr_w(path), info, size );
5801
5802 if (!path || !size || (*size && !info) ||
5803 (info && (*size < sizeof(*info) || info->dwSize != *size ||
5804 info->dwVersion != MUI_FILEINFO_VERSION)))
5805 {
5806 if (size) *size = 0;
5808 return FALSE;
5809 }
5810
5811 if (!flags) flags = MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM;
5812
5814 if (!hmod) return FALSE;
5815
5816 hrsrc = FindResourceW( hmod, MAKEINTRESOURCEW(1), L"MUI" );
5817 if (hrsrc)
5818 {
5819 mui = LockResource( LoadResource(hmod, hrsrc) );
5820 if (mui) mui_size = SizeofResource( hmod, hrsrc );
5821 if (!mui || !validate_mui_resource( mui, mui_size ))
5822 {
5823 FreeLibrary( hmod );
5824 return FALSE;
5825 }
5826 if (mui->file_type & (MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN >> 1))
5827 type = MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN;
5828 else if (mui->file_type & (MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI >> 1))
5829 type = MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI;
5830 }
5831 if (type == MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL)
5832 {
5833 FreeLibrary( hmod );
5834
5835 if (!info)
5836 {
5837 *size = sizeof(*info);
5838 return TRUE;
5839 }
5840 if (info->dwSize < sizeof(*info))
5841 {
5843 return FALSE;
5844 }
5845
5846 memset( info, 0, sizeof(*info) );
5847 info->dwSize = *size;
5848 info->dwVersion = MUI_FILEINFO_VERSION;
5849 if (flags & MUI_QUERY_TYPE) info->dwFileType = type;
5850 return TRUE;
5851 }
5852
5853 off = offsetof(FILEMUIINFO, abBuffer);
5854 if (flags & MUI_QUERY_LANGUAGE_NAME)
5855 {
5856 off += type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN ?
5857 mui->fallback_lang_size : mui->lang_size;
5858 }
5859 if (flags & MUI_QUERY_RESOURCE_TYPES)
5860 {
5861 if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN)
5862 off += mui->ln_type_name_size + mui->ln_type_id_size;
5863 off += mui->mui_type_name_size + mui->mui_type_id_size;
5864 }
5865 if (off < sizeof(*info)) off = sizeof(*info);
5866
5867 if (!info || info->dwSize < off)
5868 {
5869 FreeLibrary( hmod );
5870 *size = off;
5872 return FALSE;
5873 }
5874
5875 off = 0;
5876 memset( info, 0, sizeof(*info) );
5877 info->dwSize = *size;
5878 info->dwVersion = MUI_FILEINFO_VERSION;
5879 if (flags & MUI_QUERY_TYPE) info->dwFileType = type;
5880 if (flags & MUI_QUERY_CHECKSUM)
5881 {
5882 memcpy( info->pChecksum, mui->checksum, sizeof(info->pChecksum) );
5883 memcpy( info->pServiceChecksum, mui->service_checksum, sizeof(info->pServiceChecksum) );
5884 }
5885 if (flags & MUI_QUERY_LANGUAGE_NAME)
5886 {
5887 if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN && mui->fallback_lang_off)
5888 {
5889 info->dwLanguageNameOffset = offsetof(FILEMUIINFO, abBuffer);
5890 memcpy(info->abBuffer, ((BYTE *)mui) + mui->fallback_lang_off,
5891 mui->fallback_lang_size);
5892 off += mui->fallback_lang_size;
5893 }
5894 if (type == MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI && mui->lang_off)
5895 {
5896 info->dwLanguageNameOffset = offsetof(FILEMUIINFO, abBuffer);
5897 memcpy(info->abBuffer, ((BYTE *)mui) + mui->lang_off, mui->lang_size);
5898 off += mui->lang_size;
5899 }
5900 }
5901 if (flags & MUI_QUERY_RESOURCE_TYPES && type & MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN)
5902 {
5903 if (mui->ln_type_id_size && mui->ln_type_id_off)
5904 {
5905 info->dwTypeIDMainSize = mui->ln_type_id_size / sizeof(DWORD);
5906 info->dwTypeIDMainOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5907 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_id_off, mui->ln_type_id_size);
5908 off += mui->ln_type_id_size;
5909 }
5910 if (mui->ln_type_name_off)
5911 {
5912 info->dwTypeNameMainOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5913 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_name_off, mui->ln_type_name_size);
5914 off += mui->ln_type_name_size;
5915 }
5916 if (mui->mui_type_id_size && mui->mui_type_id_off)
5917 {
5918 info->dwTypeIDMUISize = mui->mui_type_id_size / sizeof(DWORD);
5919 info->dwTypeIDMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5920 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->mui_type_id_off, mui->mui_type_id_size);
5921 off += mui->mui_type_id_size;
5922 }
5923 if (mui->mui_type_name_off)
5924 {
5925 info->dwTypeNameMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5926 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->mui_type_name_off, mui->mui_type_name_size);
5927 off += mui->mui_type_name_size;
5928 }
5929 }
5930 else if(flags & MUI_QUERY_RESOURCE_TYPES)
5931 {
5932 if (mui->ln_type_id_size && mui->ln_type_id_off)
5933 {
5934 info->dwTypeIDMUISize = mui->ln_type_id_size / sizeof(DWORD);
5935 info->dwTypeIDMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5936 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_id_off, mui->ln_type_id_size);
5937 off += mui->ln_type_id_size;
5938 }
5939 if (mui->ln_type_name_off)
5940 {
5941 info->dwTypeNameMUIOffset = offsetof(FILEMUIINFO, abBuffer[off]);
5942 memcpy(info->abBuffer + off, ((BYTE *)mui) + mui->ln_type_name_off, mui->ln_type_name_size);
5943 off += mui->ln_type_name_size;
5944 }
5945 }
5946
5947 FreeLibrary( hmod );
5948 return TRUE;
5949}
5950
5951
5952/******************************************************************************
5953 * GetFileMUIPath (kernelbase.@)
5954 */
5955BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetFileMUIPath( DWORD flags, const WCHAR *filepath,
5956 WCHAR *language, ULONG *languagelen,
5957 WCHAR *muipath, ULONG *muipathlen,
5958 ULONGLONG *enumerator )
5959{
5960 FIXME( "stub: 0x%lx, %s, %s, %p, %p, %p, %p\n", flags, debugstr_w(filepath),
5961 debugstr_w(language), languagelen, muipath, muipathlen, enumerator );
5963 return FALSE;
5964}
5965
5966
5967/******************************************************************************
5968 * GetGeoInfoW (kernelbase.@)
5969 */
5971{
5972 const struct geo_id *ptr = find_geo_id_entry( id );
5973
5974 TRACE( "%ld %ld %p %d %d\n", id, type, data, count, lang );
5975
5976 if (!ptr)
5977 {
5979 return 0;
5980 }
5981 return get_geo_info( ptr, type, data, count, lang );
5982}
5983
5984
5986{
5987 const struct geo_id *ptr = find_geo_name_entry( location );
5988
5989 TRACE( "%s %lx %p %d\n", wine_dbgstr_w(location), type, data, data_count );
5990
5991 if (!ptr)
5992 {
5994 return 0;
5995 }
5996
5997 if (type == GEO_LCID || type == GEO_NATION || type == GEO_RFC1766)
5998 {
6000 return 0;
6001 }
6002
6003 return get_geo_info( ptr, type, data, data_count, 0 );
6004}
6005
6006
6007/******************************************************************************
6008 * GetLocaleInfoA (kernelbase.@)
6009 */
6011{
6012 const NLS_LOCALE_DATA *locale;
6013 WCHAR *bufferW;
6014 INT lenW, ret;
6015
6016 TRACE( "lcid=0x%lx lctype=0x%lx %p %d\n", lcid, lctype, buffer, len );
6017
6018 if (len < 0 || (len && !buffer))
6019 {
6021 return 0;
6022 }
6023 if (LOWORD(lctype) == LOCALE_SSHORTTIME || (lctype & LOCALE_RETURN_GENITIVE_NAMES))
6024 {
6026 return 0;
6027 }
6028 if (!(locale = NlsValidateLocale( &lcid, 0 )))
6029 {
6031 return 0;
6032 }
6033 if (LOWORD(lctype) == LOCALE_FONTSIGNATURE || (lctype & LOCALE_RETURN_NUMBER))
6034 {
6035 ret = get_locale_info( locale, lcid, lctype, (WCHAR *)buffer, len / sizeof(WCHAR) );
6036 return ret * sizeof(WCHAR);
6037 }
6038
6039 if (!(lenW = get_locale_info( locale, lcid, lctype, NULL, 0 ))) return 0;
6040
6041 if (!(bufferW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
6042 {
6044 return 0;
6045 }
6046 ret = get_locale_info( locale, lcid, lctype, bufferW, lenW );
6048 bufferW, ret, buffer, len, NULL, NULL );
6049 RtlFreeHeap( GetProcessHeap(), 0, bufferW );
6050 return ret;
6051}
6052
6053
6054/******************************************************************************
6055 * GetLocaleInfoW (kernelbase.@)
6056 */
6058{
6059 const NLS_LOCALE_DATA *locale;
6060
6061 if (len < 0 || (len && !buffer))
6062 {
6064 return 0;
6065 }
6066
6067 TRACE( "(lcid=0x%lx,lctype=0x%lx,%p,%d)\n", lcid, lctype, buffer, len );
6068
6069 if (!(locale = NlsValidateLocale( &lcid, 0 )))
6070 {
6072 return 0;
6073 }
6074 return get_locale_info( locale, lcid, lctype, buffer, len );
6075}
6076
6077
6078/******************************************************************************
6079 * GetLocaleInfoEx (kernelbase.@)
6080 */
6082{
6083 LCID lcid;
6084 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
6085
6086 TRACE( "%s 0x%lx %p %d\n", debugstr_w(name), info, buffer, len );
6087
6088 if (!locale)
6089 {
6091 return 0;
6092 }
6093 return get_locale_info( locale, lcid, info, buffer, len );
6094}
6095
6096
6097/******************************************************************************
6098 * GetNLSVersion (kernelbase.@)
6099 */
6101{
6103
6104 if (info->dwNLSVersionInfoSize < offsetof( NLSVERSIONINFO, dwEffectiveId ))
6105 {
6107 return FALSE;
6108 }
6110 {
6112 return FALSE;
6113 }
6115}
6116
6117
6118/******************************************************************************
6119 * GetNLSVersionEx (kernelbase.@)
6120 */
6123{
6124 const struct sortguid *sortid;
6125
6126 if (func != COMPARE_STRING)
6127 {
6129 return FALSE;
6130 }
6131 if (info->dwNLSVersionInfoSize < sizeof(*info) &&
6132 (info->dwNLSVersionInfoSize != offsetof( NLSVERSIONINFO, dwEffectiveId )))
6133 {
6135 return FALSE;
6136 }
6137
6138 if (!(sortid = get_language_sort( locale ))) return FALSE;
6139
6140 info->dwNLSVersion = info->dwDefinedVersion = sort.version;
6141 if (info->dwNLSVersionInfoSize >= sizeof(*info))
6142 {
6143 info->dwEffectiveId = LocaleNameToLCID( locale, 0 );
6144 info->guidCustomVersion = sortid->id;
6145 }
6146 return TRUE;
6147}
6148
6149
6150/******************************************************************************
6151 * GetOEMCP (kernelbase.@)
6152 */
6154{
6155 return oem_cpinfo.CodePage;
6156}
6157
6158
6159/***********************************************************************
6160 * GetProcessPreferredUILanguages (kernelbase.@)
6161 */
6163 WCHAR *buffer, ULONG *size )
6164{
6165 return set_ntstatus( RtlGetProcessPreferredUILanguages( flags, count, buffer, size ));
6166}
6167
6168
6169/***********************************************************************
6170 * GetStringTypeA (kernelbase.@)
6171 */
6173 WORD *chartype )
6174{
6175 UINT cp;
6176 INT countW;
6177 LPWSTR srcW;
6178 BOOL ret = FALSE;
6179
6180 if (count == -1) count = strlen(src) + 1;
6181
6182 cp = get_lcid_codepage( locale, 0 );
6183 countW = MultiByteToWideChar(cp, 0, src, count, NULL, 0);
6184 if((srcW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
6185 {
6186 MultiByteToWideChar(cp, 0, src, count, srcW, countW);
6187 /*
6188 * NOTE: the target buffer has 1 word for each CHARACTER in the source
6189 * string, with multibyte characters there maybe be more bytes in count
6190 * than character space in the buffer!
6191 */
6192 ret = GetStringTypeW(type, srcW, countW, chartype);
6193 HeapFree(GetProcessHeap(), 0, srcW);
6194 }
6195 return ret;
6196}
6197
6198
6199/***********************************************************************
6200 * GetStringTypeW (kernelbase.@)
6201 */
6203{
6204 if (!src)
6205 {
6207 return FALSE;
6208 }
6209 if (type != CT_CTYPE1 && type != CT_CTYPE2 && type != CT_CTYPE3)
6210 {
6212 return FALSE;
6213 }
6214
6215 if (count == -1) count = lstrlenW(src) + 1;
6216
6217 while (count--) *chartype++ = get_char_type( type, *src++ );
6218
6219 return TRUE;
6220}
6221
6222
6223/***********************************************************************
6224 * GetStringTypeExW (kernelbase.@)
6225 */
6227 WORD *chartype )
6228{
6229 /* locale is ignored for Unicode */
6230 return GetStringTypeW( type, src, count, chartype );
6231}
6232
6233
6234/***********************************************************************
6235 * GetSystemDefaultLCID (kernelbase.@)
6236 */
6238{
6239 return system_lcid;
6240}
6241
6242
6243/***********************************************************************
6244 * GetSystemDefaultLangID (kernelbase.@)
6245 */
6247{
6249}
6250
6251
6252/***********************************************************************
6253 * GetSystemDefaultLocaleName (kernelbase.@)
6254 */
6256{
6258}
6259
6260
6261/***********************************************************************
6262 * GetSystemDefaultUILanguage (kernelbase.@)
6263 */
6265{
6266 LANGID lang;
6268 return lang;
6269}
6270
6271
6272/***********************************************************************
6273 * GetSystemPreferredUILanguages (kernelbase.@)
6274 */
6276 WCHAR *buffer, ULONG *size )
6277{
6278 return set_ntstatus( RtlGetSystemPreferredUILanguages( flags, 0, count, buffer, size ));
6279}
6280
6281
6282/***********************************************************************
6283 * GetThreadPreferredUILanguages (kernelbase.@)
6284 */
6286 WCHAR *buffer, ULONG *size )
6287{
6288 return set_ntstatus( RtlGetThreadPreferredUILanguages( flags, count, buffer, size ));
6289}
6290
6291
6292/***********************************************************************
6293 * GetTimeZoneInformation (kernelbase.@)
6294 */
6296{
6299
6300 memcpy( info, &tzinfo, sizeof(*info) );
6301 return ret;
6302}
6303
6304
6305/***********************************************************************
6306 * GetTimeZoneInformationForYear (kernelbase.@)
6307 */
6311{
6313 HKEY key = 0, dst_key;
6314 DWORD count;
6315 LRESULT ret;
6316 struct
6317 {
6318 LONG bias;
6319 LONG std_bias;
6320 LONG dlt_bias;
6321 SYSTEMTIME std_date;
6322 SYSTEMTIME dlt_date;
6323 } data;
6324
6325 TRACE( "(%u,%p)\n", year, info );
6326
6327 if (!dynamic)
6328 {
6329 if (GetDynamicTimeZoneInformation( &local_info ) == TIME_ZONE_ID_INVALID) return FALSE;
6330 dynamic = &local_info;
6331 }
6332
6333 if ((ret = RegOpenKeyExW( tz_key, dynamic->TimeZoneKeyName, 0, KEY_ALL_ACCESS, &key ))) goto done;
6334 if (RegLoadMUIStringW( key, L"MUI_Std", info->StandardName,
6335 sizeof(info->StandardName), NULL, 0, system_dir ))
6336 {
6337 count = sizeof(info->StandardName);
6338 if ((ret = RegQueryValueExW( key, L"Std", NULL, NULL, (BYTE *)info->StandardName, &count )))
6339 goto done;
6340 }
6341 if (RegLoadMUIStringW( key, L"MUI_Dlt", info->DaylightName,
6342 sizeof(info->DaylightName), NULL, 0, system_dir ))
6343 {
6344 count = sizeof(info->DaylightName);
6345 if ((ret = RegQueryValueExW( key, L"Dlt", NULL, NULL, (BYTE *)info->DaylightName, &count )))
6346 goto done;
6347 }
6348
6350 if (!dynamic->DynamicDaylightTimeDisabled &&
6351 !RegOpenKeyExW( key, L"Dynamic DST", 0, KEY_ALL_ACCESS, &dst_key ))
6352 {
6353 WCHAR yearW[16];
6354 swprintf( yearW, ARRAY_SIZE(yearW), L"%u", year );
6355 count = sizeof(data);
6356 ret = RegQueryValueExW( dst_key, yearW, NULL, NULL, (BYTE *)&data, &count );
6357 RegCloseKey( dst_key );
6358 }
6359 if (ret)
6360 {
6361 count = sizeof(data);
6362 ret = RegQueryValueExW( key, L"TZI", NULL, NULL, (BYTE *)&data, &count );
6363 }
6364
6365 if (!ret)
6366 {
6367 info->Bias = data.bias;
6368 info->StandardBias = data.std_bias;
6369 info->DaylightBias = data.dlt_bias;
6370 info->StandardDate = data.std_date;
6371 info->DaylightDate = data.dlt_date;
6372 }
6373
6374done:
6375 RegCloseKey( key );
6376 if (ret) SetLastError( ret );
6377 return !ret;
6378}
6379
6380
6381/***********************************************************************
6382 * GetUserDefaultLCID (kernelbase.@)
6383 */
6385{
6386 return user_lcid;
6387}
6388
6389
6390/***********************************************************************
6391 * GetUserDefaultLangID (kernelbase.@)
6392 */
6394{
6396}
6397
6398
6399/***********************************************************************
6400 * GetUserDefaultLocaleName (kernelbase.@)
6401 */
6403{
6405}
6406
6407
6408/***********************************************************************
6409 * GetUserDefaultUILanguage (kernelbase.@)
6410 */
6412{
6414}
6415
6416
6417/******************************************************************************
6418 * GetUserGeoID (kernelbase.@)
6419 */
6421{
6422 GEOID ret = 39070;
6423 const WCHAR *name;
6424 WCHAR bufferW[40];
6425 HKEY hkey;
6426
6427 switch (geoclass)
6428 {
6429 case GEOCLASS_NATION:
6430 name = L"Nation";
6431 break;
6432 case GEOCLASS_REGION:
6433 name = L"Region";
6434 break;
6435 default:
6436 WARN("Unknown geoclass %ld\n", geoclass);
6437 return GEOID_NOT_AVAILABLE;
6438 }
6439 if (!RegOpenKeyExW( intl_key, L"Geo", 0, KEY_ALL_ACCESS, &hkey ))
6440 {
6441 DWORD count = sizeof(bufferW);
6442 if (!RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)bufferW, &count ))
6443 ret = wcstol( bufferW, NULL, 10 );
6444 RegCloseKey( hkey );
6445 }
6446 return ret;
6447}
6448
6449
6450/******************************************************************************
6451 * GetUserPreferredUILanguages (kernelbase.@)
6452 */
6454 WCHAR *buffer, ULONG *size )
6455{
6456 return set_ntstatus( RtlGetUserPreferredUILanguages( flags, 0, count, buffer, size ));
6457}
6458
6459
6460/******************************************************************************
6461 * IdnToAscii (kernelbase.@)
6462 */
6464 WCHAR *dst, INT dstlen )
6465{
6467 if (!set_ntstatus( status )) return 0;
6468 return dstlen;
6469}
6470
6471
6472/******************************************************************************
6473 * IdnToNameprepUnicode (kernelbase.@)
6474 */
6476 WCHAR *dst, INT dstlen )
6477{
6479 if (!set_ntstatus( status )) return 0;
6480 return dstlen;
6481}
6482
6483
6484/******************************************************************************
6485 * IdnToUnicode (kernelbase.@)
6486 */
6488 WCHAR *dst, INT dstlen )
6489{
6491 if (!set_ntstatus( status )) return 0;
6492 return dstlen;
6493}
6494
6495
6496/******************************************************************************
6497 * IsCharAlphaA (kernelbase.@)
6498 */
6500{
6501 WCHAR wc;
6502 DWORD reslen;
6503 RtlMultiByteToUnicodeN( &wc, sizeof(WCHAR), &reslen, &c, 1 );
6504 return reslen && (get_char_type( CT_CTYPE1, wc ) & C1_ALPHA);
6505}
6506
6507
6508/******************************************************************************
6509 * IsCharAlphaW (kernelbase.@)
6510 */
6512{
6513 return !!(get_char_type( CT_CTYPE1, wc ) & C1_ALPHA);
6514}
6515
6516
6517/******************************************************************************
6518 * IsCharAlphaNumericA (kernelbase.@)
6519 */
6521{
6522 WCHAR wc;
6523 DWORD reslen;
6524 RtlMultiByteToUnicodeN( &wc, sizeof(WCHAR), &reslen, &c, 1 );
6525 return reslen && (get_char_type( CT_CTYPE1, wc ) & (C1_ALPHA | C1_DIGIT));
6526}
6527
6528
6529/******************************************************************************
6530 * IsCharAlphaNumericW (kernelbase.@)
6531 */
6533{
6534 return !!(get_char_type( CT_CTYPE1, wc ) & (C1_ALPHA | C1_DIGIT));
6535}
6536
6537
6538/******************************************************************************
6539 * IsCharBlankW (kernelbase.@)
6540 */
6542{
6543 return !!(get_char_type( CT_CTYPE1, wc ) & C1_BLANK);
6544}
6545
6546
6547/******************************************************************************
6548 * IsCharCntrlW (kernelbase.@)
6549 */
6551{
6552 return !!(get_char_type( CT_CTYPE1, wc ) & C1_CNTRL);
6553}
6554
6555
6556/******************************************************************************
6557 * IsCharDigitW (kernelbase.@)
6558 */
6560{
6561 return !!(get_char_type( CT_CTYPE1, wc ) & C1_DIGIT);
6562}
6563
6564
6565/******************************************************************************
6566 * IsCharLowerA (kernelbase.@)
6567 */
6569{
6570 WCHAR wc;
6571 DWORD reslen;
6572 RtlMultiByteToUnicodeN( &wc, sizeof(WCHAR), &reslen, &c, 1 );
6573 return reslen && (get_char_type( CT_CTYPE1, wc ) & C1_LOWER);
6574}
6575
6576
6577/******************************************************************************
6578 * IsCharLowerW (kernelbase.@)
6579 */
6581{
6582 return !!(get_char_type( CT_CTYPE1, wc ) & C1_LOWER);
6583}
6584
6585
6586/******************************************************************************
6587 * IsCharPunctW (kernelbase.@)
6588 */
6590{
6591 return !!(get_char_type( CT_CTYPE1, wc ) & C1_PUNCT);
6592}
6593
6594
6595/******************************************************************************
6596 * IsCharSpaceA (kernelbase.@)
6597 */
6599{
6600 WCHAR wc;
6601 DWORD reslen;
6602 RtlMultiByteToUnicodeN( &wc, sizeof(WCHAR), &reslen, &c, 1 );
6603 return reslen && (get_char_type( CT_CTYPE1, wc ) & C1_SPACE);
6604}
6605
6606
6607/******************************************************************************
6608 * IsCharSpaceW (kernelbase.@)
6609 */
6611{
6612 return !!(get_char_type( CT_CTYPE1, wc ) & C1_SPACE);
6613}
6614
6615
6616/******************************************************************************
6617 * IsCharUpperA (kernelbase.@)
6618 */
6620{
6621 WCHAR wc;
6622 DWORD reslen;
6623 RtlMultiByteToUnicodeN( &wc, sizeof(WCHAR), &reslen, &c, 1 );
6624 return reslen && (get_char_type( CT_CTYPE1, wc ) & C1_UPPER);
6625}
6626
6627
6628/******************************************************************************
6629 * IsCharUpperW (kernelbase.@)
6630 */
6632{
6633 return !!(get_char_type( CT_CTYPE1, wc ) & C1_UPPER);
6634}
6635
6636
6637/******************************************************************************
6638 * IsCharXDigitW (kernelbase.@)
6639 */
6641{
6642 return !!(get_char_type( CT_CTYPE1, wc ) & C1_XDIGIT);
6643}
6644
6645
6646/******************************************************************************
6647 * IsDBCSLeadByte (kernelbase.@)
6648 */
6650{
6651 return ansi_cpinfo.DBCSCodePage && ansi_cpinfo.DBCSOffsets[testchar];
6652}
6653
6654
6655/******************************************************************************
6656 * IsDBCSLeadByteEx (kernelbase.@)
6657 */
6659{
6661 return table && table->DBCSCodePage && table->DBCSOffsets[testchar];
6662}
6663
6664
6665/******************************************************************************
6666 * IsNormalizedString (kernelbase.@)
6667 */
6669{
6670 BOOLEAN res;
6672 return res;
6673}
6674
6675
6676/******************************************************************************
6677 * IsValidCodePage (kernelbase.@)
6678 */
6680{
6681 switch (codepage)
6682 {
6683 case CP_ACP:
6684 case CP_OEMCP:
6685 case CP_MACCP:
6686 case CP_THREAD_ACP:
6687 return FALSE;
6688 default:
6689 return get_codepage_table( codepage ) != NULL;
6690 }
6691}
6692
6693
6694/******************************************************************************
6695 * IsValidLanguageGroup (kernelbase.@)
6696 */
6698{
6699 WCHAR name[10], value[10];
6700 DWORD type, value_len = sizeof(value);
6701 BOOL ret = FALSE;
6702 HKEY key;
6703
6704 if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE;
6705
6706 swprintf( name, ARRAY_SIZE(name), L"%x", id );
6707 if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)value, &value_len ) && type == REG_SZ)
6708 ret = (flags & LGRPID_SUPPORTED) || wcstoul( value, NULL, 10 );
6709
6710 RegCloseKey( key );
6711 return ret;
6712}
6713
6714
6715/******************************************************************************
6716 * IsValidLocale (kernelbase.@)
6717 */
6719{
6720 switch (lcid)
6721 {
6722 case LOCALE_NEUTRAL:
6725 return FALSE;
6726 default:
6728 }
6729}
6730
6731
6732/******************************************************************************
6733 * IsValidLocaleName (kernelbase.@)
6734 */
6736{
6737 if (locale == LOCALE_NAME_USER_DEFAULT) return FALSE;
6738 return !!find_lcname_entry( locale );
6739}
6740
6741
6742/******************************************************************************
6743 * IsNLSDefinedString (kernelbase.@)
6744 */
6746 const WCHAR *str, int len )
6747{
6748 int i;
6749
6750 if (func != COMPARE_STRING)
6751 {
6753 return FALSE;
6754 }
6755 if (info)
6756 {
6757 if (info->dwNLSVersionInfoSize != sizeof(*info) &&
6758 (info->dwNLSVersionInfoSize != offsetof( NLSVERSIONINFO, dwEffectiveId )))
6759 {
6761 return FALSE;
6762 }
6763 }
6764
6765 if (len < 0) len = lstrlenW( str ) + 1;
6766
6767 for (i = 0; i < len; i++)
6768 {
6769 if (is_private_use_area_char( str[i] )) return FALSE;
6770 if (IS_LOW_SURROGATE( str[i] )) return FALSE;
6771 if (IS_HIGH_SURROGATE( str[i] ))
6772 {
6773 if (++i == len) return FALSE;
6774 if (!IS_LOW_SURROGATE( str[i] )) return FALSE;
6775 continue;
6776 }
6777 if (!(get_char_type( CT_CTYPE1, str[i] ) & C1_DEFINED)) return FALSE;
6778 }
6779 return TRUE;
6780}
6781
6782
6783/******************************************************************************
6784 * IsValidNLSVersion (kernelbase.@)
6785 */
6788{
6789 static const GUID GUID_NULL;
6790 NLSVERSIONINFOEX infoex;
6791 DWORD ret;
6792
6793 if (func != COMPARE_STRING)
6794 {
6796 return FALSE;
6797 }
6798 if (info->dwNLSVersionInfoSize < sizeof(*info) &&
6799 (info->dwNLSVersionInfoSize != offsetof( NLSVERSIONINFO, dwEffectiveId )))
6800 {
6802 return FALSE;
6803 }
6804 infoex.dwNLSVersionInfoSize = sizeof(infoex);
6805 if (!GetNLSVersionEx( func, locale, &infoex )) return FALSE;
6806
6807 ret = (infoex.dwNLSVersion & ~0xff) == (info->dwNLSVersion & ~0xff);
6808 if (ret && !IsEqualGUID( &info->guidCustomVersion, &GUID_NULL ))
6809 ret = find_sortguid( &info->guidCustomVersion ) != NULL;
6810
6812 return ret;
6813}
6814
6815
6816/***********************************************************************
6817 * LCIDToLocaleName (kernelbase.@)
6818 */
6820{
6821 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, flags );
6822
6823 if (!locale)
6824 {
6826 return 0;
6827 }
6829}
6830
6831
6832/***********************************************************************
6833 * LCMapStringEx (kernelbase.@)
6834 */
6837 void *reserved, LPARAM handle )
6838{
6839 const struct sortguid *sortid = NULL;
6840
6841 if (version) FIXME( "unsupported version structure %p\n", version );
6842 if (reserved) FIXME( "unsupported reserved pointer %p\n", reserved );
6843 if (handle)
6844 {
6845 static int once;
6846 if (!once++) FIXME( "unsupported lparam %Ix\n", handle );
6847 }
6848
6849 if (!src || !srclen || dstlen < 0)
6850 {
6852 return 0;
6853 }
6854
6855 if (srclen < 0) srclen = lstrlenW(src) + 1;
6856
6857 TRACE( "(%s,0x%08lx,%s,%d,%p,%d)\n",
6859
6860 flags &= ~LOCALE_USE_CP_ACP;
6861
6862 if (src == dst && (flags & ~(LCMAP_LOWERCASE | LCMAP_UPPERCASE)))
6863 {
6865 return 0;
6866 }
6868 {
6869 if (!(sortid = get_language_sort( locale ))) return 0;
6870 }
6871 if (flags & LCMAP_HASH)
6872 {
6873 FIXME( "LCMAP_HASH %s not supported\n", debugstr_wn( src, srclen ));
6874 return 0;
6875 }
6876 if (flags & LCMAP_SORTHANDLE)
6877 {
6878 FIXME( "LCMAP_SORTHANDLE not supported\n" );
6879 return 0;
6880 }
6881 if (flags & LCMAP_SORTKEY) return get_sortkey( sortid, flags, src, srclen, (BYTE *)dst, dstlen );
6882
6883 return lcmap_string( sortid, flags, src, srclen, dst, dstlen );
6884}
6885
6886
6887/***********************************************************************
6888 * LCMapStringA (kernelbase.@)
6889 */
6891 char *dst, int dstlen )
6892{
6893 WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
6894 LPWSTR srcW, dstW;
6895 INT ret = 0, srclenW, dstlenW;
6896 UINT locale_cp = CP_ACP;
6897
6898 if (!src || !srclen || dstlen < 0)
6899 {
6901 return 0;
6902 }
6903
6904 locale_cp = get_lcid_codepage( lcid, flags );
6905
6906 srclenW = MultiByteToWideChar( locale_cp, 0, src, srclen, bufW, 260 );
6907 if (srclenW) srcW = bufW;
6908 else
6909 {
6910 srclenW = MultiByteToWideChar( locale_cp, 0, src, srclen, NULL, 0 );
6911 srcW = HeapAlloc( GetProcessHeap(), 0, srclenW * sizeof(WCHAR) );
6912 if (!srcW)
6913 {
6915 return 0;
6916 }
6917 MultiByteToWideChar( locale_cp, 0, src, srclen, srcW, srclenW );
6918 }
6919
6920 if (flags & LCMAP_SORTKEY)
6921 {
6922 if (src == dst)
6923 {
6925 goto done;
6926 }
6927 ret = LCMapStringW( lcid, flags, srcW, srclenW, (WCHAR *)dst, dstlen );
6928 goto done;
6929 }
6930
6931 if (flags & SORT_STRINGSORT)
6932 {
6934 goto done;
6935 }
6936
6937 dstlenW = LCMapStringW( lcid, flags, srcW, srclenW, NULL, 0 );
6938 if (!dstlenW) goto done;
6939
6940 dstW = HeapAlloc( GetProcessHeap(), 0, dstlenW * sizeof(WCHAR) );
6941 if (!dstW)
6942 {
6944 goto done;
6945 }
6946 LCMapStringW( lcid, flags, srcW, srclenW, dstW, dstlenW );
6947 ret = WideCharToMultiByte( locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL );
6948 HeapFree( GetProcessHeap(), 0, dstW );
6949
6950done:
6951 if (srcW != bufW) HeapFree( GetProcessHeap(), 0, srcW );
6952 return ret;
6953}
6954
6955
6956/***********************************************************************
6957 * LCMapStringW (kernelbase.@)
6958 */
6960 WCHAR *dst, int dstlen )
6961{
6963 const NLS_LOCALE_LCID_INDEX *entry;
6964
6965 switch (lcid)
6966 {
6967 case LOCALE_NEUTRAL:
6973 break;
6974 default:
6975 if (lcid == user_lcid || lcid == system_lcid) break;
6976 if (!(entry = find_lcid_entry( lcid )))
6977 {
6978 WARN( "unknown locale %04lx\n", lcid );
6980 return 0;
6981 }
6982 locale = locale_strings + entry->name + 1;
6983 break;
6984 }
6985
6986 return LCMapStringEx( locale, flags, src, srclen, dst, dstlen, NULL, NULL, 0 );
6987}
6988
6989
6990/***********************************************************************
6991 * LocaleNameToLCID (kernelbase.@)
6992 */
6994{
6995 LCID lcid;
6996 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
6997
6998 if (!locale)
6999 {
7001 return 0;
7002 }
7003 if (!(flags & LOCALE_ALLOW_NEUTRAL_NAMES) && !locale->inotneutral)
7004 lcid = locale->idefaultlanguage;
7005 return lcid;
7006}
7007
7008
7009/******************************************************************************
7010 * MultiByteToWideChar (kernelbase.@)
7011 */
7013 WCHAR *dst, INT dstlen )
7014{
7015 const CPTABLEINFO *info;
7016 int ret;
7017
7018 if (!src || !srclen || (!dst && dstlen) || dstlen < 0)
7019 {
7021 return 0;
7022 }
7023 if (srclen < 0) srclen = strlen(src) + 1;
7024
7025 switch (codepage)
7026 {
7027 case CP_SYMBOL:
7029 break;
7030 case CP_UTF7:
7032 break;
7033 case CP_UNIXCP:
7034 codepage = unix_cp;
7035 /* fall through */
7036 default:
7037 if (!(info = get_codepage_table( codepage )))
7038 {
7040 return 0;
7041 }
7043 {
7045 return 0;
7046 }
7047 if (info->CodePage == CP_UTF8)
7049 else
7051 break;
7052 }
7053 TRACE( "cp %d %s -> %s, ret = %d\n", codepage, debugstr_an(src, srclen), debugstr_wn(dst, ret), ret );
7054 return ret;
7055}
7056
7057
7058/******************************************************************************
7059 * NormalizeString (kernelbase.@)
7060 */
7062 WCHAR *dst, INT dst_len)
7063{
7064 NTSTATUS status = RtlNormalizeString( form, src, src_len, dst, &dst_len );
7065
7066 switch (status)
7067 {
7070 break;
7073 dst_len = -dst_len;
7074 break;
7075 }
7077 return dst_len;
7078}
7079
7080
7081/******************************************************************************
7082 * ResolveLocaleName (kernelbase.@)
7083 */
7085{
7086 LCID lcid;
7087 UINT pos, datalen;
7088 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
7089
7090 if (!locale)
7091 {
7092 static const WCHAR valid[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
7094
7095 if (wcsspn( name, valid ) < wcslen( name ))
7096 {
7098 return 0;
7099 }
7101 while (!locale)
7102 {
7103 for (p = tmp + wcslen(tmp) - 1; p >= tmp; p--) if (*p == '-' || *p == '_') break;
7104 if (p <= tmp) break;
7105 *p = 0;
7106 locale = get_locale_by_name( tmp, &lcid );
7107 }
7108 }
7109
7110 pos = locale ? (locale->inotneutral ? locale->sname : locale->ssortlocale) : 0;
7111 datalen = locale_strings[pos] + 1;
7112
7113 if (!len) return datalen;
7115 if (datalen > len)
7116 {
7118 return 0;
7119 }
7120 return datalen;
7121}
7122
7123
7124/******************************************************************************
7125 * SetLocaleInfoW (kernelbase.@)
7126 */
7128{
7129 WCHAR *str, tmp[80];
7130
7131 if (!data)
7132 {
7134 return FALSE;
7135 }
7136
7137 switch (LOWORD(lctype))
7138 {
7143 case LOCALE_IDIGITSUBSTITUTION: return set_registry_entry( &entry_idigitsubstitution, data );
7150 case LOCALE_IPAPERSIZE: return set_registry_entry( &entry_ipapersize, data );
7166 case LOCALE_SYEARMONTH: return set_registry_entry( &entry_syearmonth, data );
7167
7168 case LOCALE_SDATE:
7171 /* fall through */
7172 case LOCALE_SSHORTDATE:
7176 return TRUE;
7177
7178 case LOCALE_STIME:
7181 /* fall through */
7182 case LOCALE_STIMEFORMAT:
7188 return TRUE;
7189
7190 case LOCALE_ITIME:
7192 if (!(str = find_format( tmp, L"Hh" ))) break;
7193 while (*str == 'h' || *str == 'H') *str++ = (*data == '0' ? 'h' : 'H');
7194 if (!set_registry_entry( &entry_stimeformat, tmp )) break;
7196 return TRUE;
7197
7198 case LOCALE_SINTLSYMBOL:
7200 /* if restoring the original value, restore the original LOCALE_SCURRENCY as well */
7201 if (!wcsicmp( data, locale_strings + user_locale->sintlsymbol + 1 ))
7202 data = locale_strings + user_locale->scurrency + 1;
7204 return TRUE;
7205 }
7207 return FALSE;
7208}
7209
7210
7211/***********************************************************************
7212 * SetCalendarInfoW (kernelbase.@)
7213 */
7215{
7216 FIXME( "(%08lx,%08lx,%08lx,%s): stub\n", lcid, calendar, type, debugstr_w(data) );
7217 return 0;
7218}
7219
7220
7221/***********************************************************************
7222 * SetProcessPreferredUILanguages (kernelbase.@)
7223 */
7225{
7226 return set_ntstatus( RtlSetProcessPreferredUILanguages( flags, buffer, count ));
7227}
7228
7229
7230/***********************************************************************
7231 * SetThreadPreferredUILanguages (kernelbase.@)
7232 */
7234{
7235 return set_ntstatus( RtlSetThreadPreferredUILanguages( flags, buffer, count ));
7236}
7237
7238
7239/***********************************************************************
7240 * SetTimeZoneInformation (kernelbase.@)
7241 */
7243{
7245}
7246
7247
7248/******************************************************************************
7249 * SetUserGeoID (kernelbase.@)
7250 */
7252{
7253 const struct geo_id *geo = find_geo_id_entry( id );
7254 WCHAR bufferW[10];
7255 HKEY hkey;
7256
7257 if (!geo)
7258 {
7260 return FALSE;
7261 }
7262 if (!RegCreateKeyExW( intl_key, L"Geo", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
7263 {
7264 const WCHAR *name = geo->class == GEOCLASS_NATION ? L"Nation" : L"Region";
7265 swprintf( bufferW, ARRAY_SIZE(bufferW), L"%u", geo->id );
7266 RegSetValueExW( hkey, name, 0, REG_SZ, (BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR) );
7267
7268 if (geo->class == GEOCLASS_NATION || wcscmp( geo->iso2, L"XX" ))
7269 lstrcpyW( bufferW, geo->iso2 );
7270 else
7271 swprintf( bufferW, ARRAY_SIZE(bufferW), L"%03u", geo->uncode );
7272 RegSetValueExW( hkey, L"Name", 0, REG_SZ, (BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR) );
7273 RegCloseKey( hkey );
7274 }
7275 return TRUE;
7276}
7277
7278
7279/***********************************************************************
7280 * SystemTimeToTzSpecificLocalTime (kernelbase.@)
7281 */
7283 const SYSTEMTIME *system,
7284 SYSTEMTIME *local )
7285{
7286 TIME_ZONE_INFORMATION tzinfo;
7287 LARGE_INTEGER ft;
7288
7289 if (!info)
7290 {
7292 info = &tzinfo;
7293 }
7294
7295 if (!SystemTimeToFileTime( system, (FILETIME *)&ft )) return FALSE;
7296 switch (get_timezone_id( info, ft, FALSE ))
7297 {
7299 ft.QuadPart -= info->Bias * (LONGLONG)600000000;
7300 break;
7302 ft.QuadPart -= (info->Bias + info->StandardBias) * (LONGLONG)600000000;
7303 break;
7305 ft.QuadPart -= (info->Bias + info->DaylightBias) * (LONGLONG)600000000;
7306 break;
7307 default:
7308 return FALSE;
7309 }
7310 return FileTimeToSystemTime( (FILETIME *)&ft, local );
7311}
7312
7313
7314/***********************************************************************
7315 * TzSpecificLocalTimeToSystemTime (kernelbase.@)
7316 */
7318 const SYSTEMTIME *local,
7320{
7321 TIME_ZONE_INFORMATION tzinfo;
7322 LARGE_INTEGER ft;
7323
7324 if (!info)
7325 {
7327 info = &tzinfo;
7328 }
7329
7330 if (!SystemTimeToFileTime( local, (FILETIME *)&ft )) return FALSE;
7331 switch (get_timezone_id( info, ft, TRUE ))
7332 {
7334 ft.QuadPart += info->Bias * (LONGLONG)600000000;
7335 break;
7337 ft.QuadPart += (info->Bias + info->StandardBias) * (LONGLONG)600000000;
7338 break;
7340 ft.QuadPart += (info->Bias + info->DaylightBias) * (LONGLONG)600000000;
7341 break;
7342 default:
7343 return FALSE;
7344 }
7345 return FileTimeToSystemTime( (FILETIME *)&ft, system );
7346}
7347
7348
7349/***********************************************************************
7350 * VerLanguageNameA (kernelbase.@)
7351 */
7353{
7355}
7356
7357
7358/***********************************************************************
7359 * VerLanguageNameW (kernelbase.@)
7360 */
7362{
7364}
7365
7366
7367/***********************************************************************
7368 * WideCharToMultiByte (kernelbase.@)
7369 */
7371 LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
7372{
7373 const CPTABLEINFO *info;
7374 int ret;
7375
7376 if (!src || !srclen || (!dst && dstlen) || dstlen < 0)
7377 {
7379 return 0;
7380 }
7381
7382 if (srclen < 0) srclen = lstrlenW(src) + 1;
7383
7384 switch (codepage)
7385 {
7386 case CP_SYMBOL:
7387 ret = wcstombs_cpsymbol( flags, src, srclen, dst, dstlen, defchar, used );
7388 break;
7389 case CP_UTF7:
7390 ret = wcstombs_utf7( flags, src, srclen, dst, dstlen, defchar, used );
7391 break;
7392 case CP_UNIXCP:
7393 codepage = unix_cp;
7394 /* fall through */
7395 default:
7396 if (!(info = get_codepage_table( codepage )))
7397 {
7399 return 0;
7400 }
7403 {
7405 return 0;
7406 }
7407 if (info->CodePage == CP_UTF8)
7408 ret = wcstombs_utf8( flags, src, srclen, dst, dstlen, defchar, used );
7409 else
7410 ret = wcstombs_codepage( info, flags, src, srclen, dst, dstlen, defchar, used );
7411 break;
7412 }
7413 TRACE( "cp %d %s -> %s, ret = %d\n", codepage, debugstr_wn(src, srclen), debugstr_an(dst, ret), ret );
7414 return ret;
7415}
7416
7417
7418/***********************************************************************
7419 * GetUserDefaultGeoName (kernelbase.@)
7420 */
7422{
7423 WCHAR buffer[32];
7425 DWORD size;
7426 HKEY key;
7427
7428 TRACE( "geo_name %p, count %d.\n", geo_name, count );
7429
7430 if (count && !geo_name)
7431 {
7433 return 0;
7434 }
7435 if (!(status = RegOpenKeyExW( intl_key, L"Geo", 0, KEY_ALL_ACCESS, &key )))
7436 {
7437 size = sizeof(buffer);
7438 status = RegQueryValueExW( key, L"Name", NULL, NULL, (BYTE *)buffer, &size );
7439 RegCloseKey( key );
7440 }
7441 if (status)
7442 {
7443 const struct geo_id *geo = find_geo_id_entry( GetUserGeoID( GEOCLASS_NATION ));
7444 if (geo && geo->id != 39070)
7445 lstrcpyW( buffer, geo->iso2 );
7446 else
7447 lstrcpyW( buffer, L"001" );
7448 }
7449 size = lstrlenW( buffer ) + 1;
7450 if (count < size)
7451 {
7452 if (!count)
7453 return size;
7455 return 0;
7456 }
7457 lstrcpyW( geo_name, buffer );
7458 return size;
7459}
7460
7461
7462/***********************************************************************
7463 * SetUserDefaultGeoName (kernelbase.@)
7464 */
7466{
7467 const struct geo_id *geo;
7468
7469 TRACE( "geo_name %s.\n", debugstr_w( geo_name ));
7470
7471 if (!geo_name || !(geo = find_geo_name_entry( geo_name )))
7472 {
7474 return FALSE;
7475 }
7476 return SetUserGeoID( geo->id );
7477}
7478
7479
7480static void grouping_to_string( UINT grouping, WCHAR *buffer )
7481{
7482 UINT last_digit = grouping % 10;
7483 WCHAR tmp[10], *p = tmp;
7484
7485 /* The string is confusingly different when it comes to repetitions (trailing zeros). For a string,
7486 * a 0 signals that the format needs to be repeated, which is the opposite of the grouping integer. */
7487 if (last_digit == 0)
7488 {
7489 grouping /= 10;
7490
7491 /* Special case: two or more trailing zeros result in zero-sided groupings, with no repeats */
7492 if (grouping % 10 == 0)
7493 last_digit = ~0;
7494 }
7495
7496 while (grouping)
7497 {
7498 *p++ = '0' + grouping % 10;
7499 grouping /= 10;
7500 }
7501 while (p > tmp)
7502 {
7503 *buffer++ = *(--p);
7504 if (p > tmp) *buffer++ = ';';
7505 }
7506 if (last_digit != 0)
7507 {
7508 *buffer++ = ';';
7509 *buffer++ = '0';
7510 if (last_digit == ~0)
7511 {
7512 /* Add another trailing zero due to the weird way trailing zeros work in grouping string */
7513 *buffer++ = ';';
7514 *buffer++ = '0';
7515 }
7516 }
7517 *buffer = 0;
7518}
7519
7520
7521static WCHAR *prepend_str( WCHAR *end, const WCHAR *str )
7522{
7523 UINT len = wcslen( str );
7524 return memcpy( end - len, str, len * sizeof(WCHAR) );
7525}
7526
7527
7528/* format a positive number with decimal part; helper for get_number_format */
7529static WCHAR *format_number( WCHAR *end, const WCHAR *value, const WCHAR *decimal_sep,
7530 const WCHAR *thousand_sep, const WCHAR *grouping, UINT digits, BOOL lzero )
7531{
7533 UINT i, len = 0, prev = ~0;
7534 const WCHAR *frac = NULL;
7535
7536 *(--end) = 0;
7537
7538 for (i = 0; value[i]; i++)
7539 {
7540 if (value[i] >= '0' && value[i] <= '9') continue;
7541 if (value[i] != '.') return NULL;
7542 if (frac) return NULL;
7543 frac = value + i + 1;
7544 }
7545
7546 /* format fractional part */
7547
7548 len = frac ? wcslen( frac ) : 0;
7549
7550 if (len > digits)
7551 {
7552 round = frac[digits] >= '5';
7553 len = digits;
7554 }
7555 while (digits > len)
7556 {
7557 (*--end) = '0';
7558 digits--;
7559 }
7560 while (len)
7561 {
7562 WCHAR ch = frac[--len];
7563 if (round)
7564 {
7565 if (ch != '9')
7566 {
7567 ch++;
7568 round = FALSE;
7569 }
7570 else ch = '0';
7571 }
7572 *(--end) = ch;
7573 }
7574 if (*end) end = prepend_str( end, decimal_sep );
7575
7576 /* format integer part */
7577
7578 len = frac ? frac - value - 1 : wcslen( value );
7579
7580 while (len && *value == '0')
7581 {
7582 value++;
7583 len--;
7584 }
7585 if (len) lzero = FALSE;
7586
7587 /* leading 0s are ignored */
7588 while (grouping[0] == '0' && grouping[1] == ';')
7589 grouping += 2;
7590
7591 while (len)
7592 {
7593 UINT limit = prev;
7594
7595 if (!repeat)
7596 {
7597 limit = *grouping - '0';
7598 if (grouping[1] == ';')
7599 {
7600 grouping += 2;
7601 if (limit)
7602 prev = limit;
7603 else
7604 {
7605 /* Trailing 0;0 is a special case */
7606 prev = ~0;
7607 if (grouping[0] == '0' && grouping[1] != ';')
7608 {
7609 repeat = TRUE;
7610 limit = prev;
7611 }
7612 }
7613 }
7614 else
7615 {
7616 repeat = TRUE;
7617 if (!limit)
7618 limit = prev;
7619 else
7620 prev = ~0;
7621 }
7622 }
7623
7624 while (len && limit--)
7625 {
7626 WCHAR ch = value[--len];
7627 if (round)
7628 {
7629 if (ch != '9')
7630 {
7631 ch++;
7632 round = FALSE;
7633 }
7634 else ch = '0';
7635 }
7636 *(--end) = ch;
7637 }
7638 if (len) end = prepend_str( end, thousand_sep );
7639 }
7640 if (round) *(--end) = '1';
7641 else if (lzero) *(--end) = '0';
7642 return end;
7643}
7644
7645
7646static int get_number_format( const NLS_LOCALE_DATA *locale, DWORD flags, const WCHAR *value,
7647 const NUMBERFMTW *format, WCHAR *buffer, int len )
7648{
7649 WCHAR *num, fmt_decimal[4], fmt_thousand[4], fmt_neg[5], grouping[24], output[256];
7650 const WCHAR *decimal_sep = fmt_decimal, *thousand_sep = fmt_thousand;
7651 DWORD digits, lzero, order;
7652 int ret = 0;
7653 BOOL negative = (*value == '-');
7654
7656
7657 if (!format)
7658 {
7659 get_locale_info( locale, 0, LOCALE_SGROUPING | flags, grouping, ARRAY_SIZE(grouping) );
7660 get_locale_info( locale, 0, LOCALE_SDECIMAL | flags, fmt_decimal, ARRAY_SIZE(fmt_decimal) );
7661 get_locale_info( locale, 0, LOCALE_STHOUSAND | flags, fmt_thousand, ARRAY_SIZE(fmt_thousand) );
7662 get_locale_info( locale, 0, LOCALE_IDIGITS | LOCALE_RETURN_NUMBER | flags,
7663 (WCHAR *)&digits, sizeof(DWORD)/sizeof(WCHAR) );
7664 get_locale_info( locale, 0, LOCALE_ILZERO | LOCALE_RETURN_NUMBER | flags,
7665 (WCHAR *)&lzero, sizeof(DWORD)/sizeof(WCHAR) );
7666 get_locale_info( locale, 0, LOCALE_INEGNUMBER | LOCALE_RETURN_NUMBER | flags,
7667 (WCHAR *)&order, sizeof(DWORD)/sizeof(WCHAR) );
7668 }
7669 else
7670 {
7671 if (flags)
7672 {
7674 return 0;
7675 }
7676 decimal_sep = format->lpDecimalSep;
7677 thousand_sep = format->lpThousandSep;
7678 grouping_to_string( format->Grouping, grouping );
7679 digits = format->NumDigits;
7680 lzero = format->LeadingZero;
7681 order = format->NegativeOrder;
7682 if (!decimal_sep || !thousand_sep)
7683 {
7685 return 0;
7686 }
7687 }
7688
7689 if (negative)
7690 {
7691 value++;
7692 get_locale_info( locale, 0, LOCALE_SNEGATIVESIGN | flags, fmt_neg, ARRAY_SIZE(fmt_neg) );
7693 }
7694
7695 if (!(num = format_number( output + ARRAY_SIZE(output) - 6, value,
7696 decimal_sep, thousand_sep, grouping, digits, lzero )))
7697 {
7699 return 0;
7700 }
7701
7702 if (negative)
7703 {
7704 switch (order)
7705 {
7706 case 0: /* (1.1) */
7707 num = prepend_str( num, L"(" );
7708 wcscat( num, L")" );
7709 break;
7710 case 2: /* - 1.1 */
7711 num = prepend_str( num, L" " );
7712 /* fall through */
7713 case 1: /* -1.1 */
7714 num = prepend_str( num, fmt_neg );
7715 break;
7716 case 4: /* 1.1 - */
7717 wcscat( num, L" " );
7718 /* fall through */
7719 case 3: /* 1.1- */
7720 wcscat( num, fmt_neg );
7721 break;
7722 default:
7724 return 0;
7725 }
7726 }
7727
7728 ret = wcslen( num ) + 1;
7729 if (!len) return ret;
7730 lstrcpynW( buffer, num, len );
7731 if (ret > len)
7732 {
7734 return 0;
7735 }
7736 return ret;
7737}
7738
7739
7740static int get_currency_format( const NLS_LOCALE_DATA *locale, DWORD flags, const WCHAR *value,
7741 const CURRENCYFMTW *format, WCHAR *buffer, int len )
7742{
7743 WCHAR *num, fmt_decimal[4], fmt_thousand[4], fmt_symbol[13], fmt_neg[5], grouping[20], output[256];
7744 const WCHAR *decimal_sep = fmt_decimal, *thousand_sep = fmt_thousand, *symbol = fmt_symbol;
7745 DWORD digits, lzero, pos_order, neg_order;
7746 int ret = 0;
7747 BOOL negative = (*value == '-');
7748
7750
7751 if (!format)
7752 {
7753 get_locale_info( locale, 0, LOCALE_SCURRENCY | flags, fmt_symbol, ARRAY_SIZE(fmt_symbol) );
7754 get_locale_info( locale, 0, LOCALE_SMONGROUPING | flags, grouping, ARRAY_SIZE(grouping) );
7755 get_locale_info( locale, 0, LOCALE_SMONDECIMALSEP | flags, fmt_decimal, ARRAY_SIZE(fmt_decimal) );
7756 get_locale_info( locale, 0, LOCALE_SMONTHOUSANDSEP | flags, fmt_thousand, ARRAY_SIZE(fmt_thousand) );
7757 get_locale_info( locale, 0, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER | flags,
7758 (WCHAR *)&digits, sizeof(DWORD)/sizeof(WCHAR) );
7759 get_locale_info( locale, 0, LOCALE_ILZERO | LOCALE_RETURN_NUMBER | flags,
7760 (WCHAR *)&lzero, sizeof(DWORD)/sizeof(WCHAR) );
7761 get_locale_info( locale, 0, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER | flags,
7762 (WCHAR *)&pos_order, sizeof(DWORD)/sizeof(WCHAR) );
7763 get_locale_info( locale, 0, LOCALE_INEGCURR | LOCALE_RETURN_NUMBER | flags,
7764 (WCHAR *)&neg_order, sizeof(DWORD)/sizeof(WCHAR) );
7765 }
7766 else
7767 {
7768 if (flags)
7769 {
7771 return 0;
7772 }
7773 decimal_sep = format->lpDecimalSep;
7774 thousand_sep = format->lpThousandSep;
7775 symbol = format->lpCurrencySymbol;
7776 grouping_to_string( format->Grouping, grouping );
7777 digits = format->NumDigits;
7778 lzero = format->LeadingZero;
7779 pos_order = format->PositiveOrder;
7780 neg_order = format->NegativeOrder;
7781 if (!decimal_sep || !thousand_sep || !symbol)
7782 {
7784 return 0;
7785 }
7786 }
7787
7788 if (negative)
7789 {
7790 value++;
7791 get_locale_info( locale, 0, LOCALE_SNEGATIVESIGN | flags, fmt_neg, ARRAY_SIZE(fmt_neg) );
7792 }
7793
7794 if (!(num = format_number( output + ARRAY_SIZE(output) - 20, value,
7795 decimal_sep, thousand_sep, grouping, digits, lzero )))
7796 {
7798 return 0;
7799 }
7800
7801 if (negative)
7802 {
7803 switch (neg_order)
7804 {
7805 case 14: /* ($ 1.1) */
7806 num = prepend_str( num, L" " );
7807 /* fall through */
7808 case 0: /* ($1.1) */
7809 num = prepend_str( num, symbol );
7810 num = prepend_str( num, L"(" );
7811 wcscat( num, L")" );
7812 break;
7813 case 9: /* -$ 1.1 */
7814 num = prepend_str( num, L" " );
7815 /* fall through */
7816 case 1: /* -$1.1 */
7817 num = prepend_str( num, symbol );
7818 num = prepend_str( num, fmt_neg );
7819 break;
7820 case 2: /* $-1.1 */
7821 num = prepend_str( num, fmt_neg );
7822 num = prepend_str( num, symbol );
7823 break;
7824 case 11: /* $ 1.1- */
7825 num = prepend_str( num, L" " );
7826 /* fall through */
7827 case 3: /* $1.1- */
7828 num = prepend_str( num, symbol );
7829 wcscat( num, fmt_neg );
7830 break;
7831 case 15: /* (1.1 $) */
7832 wcscat( num, L" " );
7833 /* fall through */
7834 case 4: /* (1.1$) */
7835 wcscat( num, symbol );
7836 num = prepend_str( num, L"(" );
7837 wcscat( num, L")" );
7838 break;
7839 case 8: /* -1.1 $ */
7840 wcscat( num, L" " );
7841 /* fall through */
7842 case 5: /* -1.1$ */
7843 num = prepend_str( num, fmt_neg );
7844 wcscat( num, symbol );
7845 break;
7846 case 6: /* 1.1-$ */
7847 wcscat( num, fmt_neg );
7848 wcscat( num, symbol );
7849 break;
7850 case 10: /* 1.1 $- */
7851 wcscat( num, L" " );
7852 /* fall through */
7853 case 7: /* 1.1$- */
7854 wcscat( num, symbol );
7855 wcscat( num, fmt_neg );
7856 break;
7857 case 12: /* $ -1.1 */
7858 num = prepend_str( num, fmt_neg );
7859 num = prepend_str( num, L" " );
7860 num = prepend_str( num, symbol );
7861 break;
7862 case 13: /* 1.1- $ */
7863 wcscat( num, fmt_neg );
7864 wcscat( num, L" " );
7865 wcscat( num, symbol );
7866 break;
7867 default:
7869 return 0;
7870 }
7871 }
7872 else
7873 {
7874 switch (pos_order)
7875 {
7876 case 2: /* $ 1.1 */
7877 num = prepend_str( num, L" " );
7878 /* fall through */
7879 case 0: /* $1.1 */
7880 num = prepend_str( num, symbol );
7881 break;
7882 case 3: /* 1.1 $ */
7883 wcscat( num, L" " );
7884 /* fall through */
7885 case 1: /* 1.1$ */
7886 wcscat( num, symbol );
7887 break;
7888 default:
7890 return 0;
7891 }
7892 }
7893
7894 ret = wcslen( num ) + 1;
7895 if (!len) return ret;
7896 lstrcpynW( buffer, num, len );
7897 if (ret > len)
7898 {
7900 return 0;
7901 }
7902 return ret;
7903}
7904
7905
7906/* get the length of a date/time formatting pattern */
7907static int get_pattern_len( const WCHAR *pattern, const WCHAR *accept )
7908{
7909 int i;
7910
7911 if (*pattern == '\'')
7912 {
7913 for (i = 1; pattern[i]; i++)
7914 {
7915 if (pattern[i] != '\'') continue;
7916 if (pattern[++i] != '\'') return i;
7917 }
7918 return i;
7919 }
7920 if (!wcschr( accept, *pattern )) return 1;
7921 for (i = 1; pattern[i]; i++) if (pattern[i] != pattern[0]) break;
7922 return i;
7923}
7924
7925
7926static int get_date_format( const NLS_LOCALE_DATA *locale, DWORD flags, const SYSTEMTIME *systime,
7927 const WCHAR *format, WCHAR *buffer, int len )
7928{
7929 DWORD override = flags & LOCALE_NOUSEROVERRIDE;
7930 DWORD genitive = 0;
7931 WCHAR *p, fmt[80], output[256];
7933 int ret, val, count, i;
7934
7935 if (!format)
7936 {
7937 if (flags & DATE_USE_ALT_CALENDAR) FIXME( "alt calendar not supported\n" );
7938 switch (flags & (DATE_SHORTDATE | DATE_LONGDATE | DATE_YEARMONTH | DATE_MONTHDAY))
7939 {
7940 case 0:
7941 case DATE_SHORTDATE:
7943 break;
7944 case DATE_LONGDATE:
7946 break;
7947 case DATE_YEARMONTH:
7948 get_locale_info( locale, 0, LOCALE_SYEARMONTH | override, fmt, ARRAY_SIZE(fmt) );
7949 break;
7950 case DATE_MONTHDAY:
7952 break;
7953 default:
7955 return 0;
7956 }
7957 format = fmt;
7958 }
7959 else if (override || (flags & (DATE_SHORTDATE | DATE_LONGDATE | DATE_YEARMONTH | DATE_MONTHDAY)))
7960 {
7962 return 0;
7963 }
7964
7965 if (systime)
7966 {
7967 FILETIME ft;
7968
7969 time = *systime;
7970 time.wHour = time.wMinute = time.wSecond = time.wMilliseconds = 0;
7971 if (!SystemTimeToFileTime( &time, &ft ) || !FileTimeToSystemTime( &ft, &time )) return 0;
7972 }
7973 else GetLocalTime( &time );
7974
7975 for (p = output; *format; format += count)
7976 {
7977 count = get_pattern_len( format, L"yMd" );
7978
7979 switch (*format)
7980 {
7981 case '\'':
7982 for (i = 1; i < count; i++)
7983 {
7984 if (format[i] == '\'') i++;
7985 if (i < count) *p++ = format[i];
7986 }
7987 break;
7988
7989 case 'y':
7990 p += swprintf( p, output + ARRAY_SIZE(output) - p, L"%02u",
7991 (count <= 2) ? time.wYear % 100 : time.wYear );
7992 break;
7993
7994 case 'M':
7995 if (count <= 2)
7996 {
7997 p += swprintf( p, output + ARRAY_SIZE(output) - p, L"%.*u", count, time.wMonth );
7998 break;
7999 }
8000 val = (count == 3 ? LOCALE_SABBREVMONTHNAME1 : LOCALE_SMONTHNAME1) + time.wMonth - 1;
8001 if (!genitive)
8002 {
8003 for (i = count; format[i]; i += get_pattern_len( format + i, L"yMd" ))
8004 {
8005 if (format[i] != 'd') continue;
8006 if (format[i + 1] != 'd' || format[i + 2] != 'd')
8008 break;
8009 }
8010 }
8011 p += get_locale_info( locale, 0, val | override | genitive,
8012 p, output + ARRAY_SIZE(output) - p ) - 1;
8013 break;
8014
8015 case 'd':
8016 if (count <= 2)
8017 {
8019 p += swprintf( p, output + ARRAY_SIZE(output) - p, L"%.*u", count, time.wDay );
8020 break;
8021 }
8022 genitive = 0;
8023 val = (count == 3 ? LOCALE_SABBREVDAYNAME1 : LOCALE_SDAYNAME1) + (time.wDayOfWeek + 6) % 7;
8024 p += get_locale_info( locale, 0, val | override, p, output + ARRAY_SIZE(output) - p ) - 1;
8025 break;
8026
8027 case 'g':
8028 p += locale_return_string( count >= 2 ? locale->serastring : locale->sabbreverastring,
8029 override, p, output + ARRAY_SIZE(output) - p ) - 1;
8030 break;
8031
8032 default:
8033 *p++ = *format;
8034 break;
8035 }
8036 }
8037 *p++ = 0;
8038 ret = p - output;
8039
8040 if (!len) return ret;
8041 lstrcpynW( buffer, output, len );
8042 if (ret > len)
8043 {
8045 return 0;
8046 }
8047 return ret;
8048}
8049
8050
8051static int get_time_format( const NLS_LOCALE_DATA *locale, DWORD flags, const SYSTEMTIME *systime,
8052 const WCHAR *format, WCHAR *buffer, int len )
8053{
8054 DWORD override = flags & LOCALE_NOUSEROVERRIDE;
8055 WCHAR *p, *last, fmt[80], output[256];
8057 int i, ret, val, count;
8058 BOOL skip = FALSE;
8059
8060 if (!format)
8061 {
8063 format = fmt;
8064 }
8065 else if (override)
8066 {
8068 return 0;
8069 }
8070
8071 if (systime)
8072 {
8073 time = *systime;
8074 if (time.wMilliseconds > 999 || time.wSecond > 59 || time.wMinute > 59 || time.wHour > 23)
8075 {
8077 return 0;
8078 }
8079 }
8080 else GetLocalTime( &time );
8081
8082 for (p = last = output; *format; format += count)
8083 {
8084 count = get_pattern_len( format, L"Hhmst" );
8085
8086 switch (*format)
8087 {
8088 case '\'':
8089 for (i = 1; i < count; i++)
8090 {
8091 if (format[i] == '\'') i++;
8092 if (!skip && i < count) *p++ = format[i];
8093 }
8094 continue;
8095
8096 case 'H':
8097 val = time.wHour;
8098 break;
8099
8100 case 'h':
8101 val = time.wHour;
8103 {
8104 val %= 12;
8105 if (!val) val = 12;
8106 }
8107 break;
8108
8109 case 'm':
8111 {
8112 p = last;
8113 skip = TRUE;
8114 continue;
8115 }
8116 val = time.wMinute;
8117 break;
8118
8119 case 's':
8121 {
8122 p = last;
8123 skip = TRUE;
8124 continue;
8125 }
8126 val = time.wSecond;
8127 break;
8128
8129 case 't':
8131 {
8132 p = last;
8133 skip = TRUE;
8134 continue;
8135 }
8136 val = time.wHour < 12 ? LOCALE_S1159 : LOCALE_S2359;
8137 ret = get_locale_info( locale, 0, val | override, p, output + ARRAY_SIZE(output) - p );
8138 p += (count > 1) ? ret - 1 : 1;
8139 skip = FALSE;
8140 continue;
8141
8142 default:
8143 if (!skip || *format == ' ') *p++ = *format;
8144 continue;
8145 }
8146
8147 p += swprintf( p, output + ARRAY_SIZE(output) - p, L"%.*u", min( 2, count ), val );
8148 last = p;
8149 skip = FALSE;
8150 }
8151 *p++ = 0;
8152 ret = p - output;
8153
8154 if (!len) return ret;
8155 lstrcpynW( buffer, output, len );
8156 if (ret > len)
8157 {
8159 return 0;
8160 }
8161 return ret;
8162}
8163
8164
8165/**************************************************************************
8166 * GetNumberFormatW (kernelbase.@)
8167 */
8169 const NUMBERFMTW *format, WCHAR *buffer, int len )
8170{
8171 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
8172
8173 if (len < 0 || (len && !buffer) || !value || !locale)
8174 {
8176 return 0;
8177 }
8178
8179 TRACE( "(%04lx,%lx,%s,%p,%p,%d)\n", lcid, flags, debugstr_w(value), format, buffer, len );
8181}
8182
8183
8184/**************************************************************************
8185 * GetNumberFormatEx (kernelbase.@)
8186 */
8188 const NUMBERFMTW *format, WCHAR *buffer, int len )
8189{
8190 LCID lcid;
8191 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
8192
8193 if (len < 0 || (len && !buffer) || !value || !locale)
8194 {
8196 return 0;
8197 }
8198
8199 TRACE( "(%s,%lx,%s,%p,%p,%d)\n", debugstr_w(name), flags, debugstr_w(value), format, buffer, len );
8201}
8202
8203
8204/***********************************************************************
8205 * GetCurrencyFormatW (kernelbase.@)
8206 */
8208 const CURRENCYFMTW *format, WCHAR *buffer, int len )
8209{
8210 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
8211
8212 if (len < 0 || (len && !buffer) || !value || !locale)
8213 {
8215 return 0;
8216 }
8217
8218 TRACE( "(%04lx,%lx,%s,%p,%p,%d)\n", lcid, flags, debugstr_w(value), format, buffer, len );
8220}
8221
8222
8223/***********************************************************************
8224 * GetCurrencyFormatEx (kernelbase.@)
8225 */
8227 const CURRENCYFMTW *format, WCHAR *buffer, int len )
8228{
8229 LCID lcid;
8230 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
8231
8232 if (len < 0 || (len && !buffer) || !value || !locale)
8233 {
8235 return 0;
8236 }
8237
8238 TRACE( "(%s,%lx,%s,%p,%p,%d)\n", debugstr_w(name), flags, debugstr_w(value), format, buffer, len );
8240}
8241
8242
8243/******************************************************************************
8244 * GetDateFormatA (KERNEL32.@)
8245 */
8247 const char *format, char *buffer, int len )
8248{
8250 WCHAR formatW[128], output[128];
8251 int ret;
8252
8253 TRACE( "(0x%04lx,0x%08lx,%p,%s,%p,%d)\n", lcid, flags, time, debugstr_a(format), buffer, len );
8254
8255 if (len < 0 || (len && !buffer))
8256 {
8258 return 0;
8259 }
8260 if (format)
8261 {
8262 MultiByteToWideChar( cp, 0, format, -1, formatW, ARRAY_SIZE(formatW) );
8263 ret = GetDateFormatW( lcid, flags, time, formatW, output, ARRAY_SIZE(output) );
8264 }
8265 else ret = GetDateFormatW( lcid, flags, time, NULL, output, ARRAY_SIZE(output) );
8266
8267 if (ret) ret = WideCharToMultiByte( cp, 0, output, -1, buffer, len, 0, 0 );
8268 return ret;
8269}
8270
8271
8272/***********************************************************************
8273 * GetDateFormatW (kernelbase.@)
8274 */
8276 const WCHAR *format, WCHAR *buffer, int len )
8277{
8278 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
8279
8280 if (len < 0 || (len && !buffer) || !locale)
8281 {
8283 return 0;
8284 }
8285
8286 TRACE( "(%04lx,%lx,%p,%s,%p,%d)\n", lcid, flags, systime, debugstr_w(format), buffer, len );
8287 return get_date_format( locale, flags, systime, format, buffer, len );
8288}
8289
8290
8291/***********************************************************************
8292 * GetDateFormatEx (kernelbase.@)
8293 */
8295 const WCHAR *format, WCHAR *buffer, int len, const WCHAR *calendar )
8296{
8297 LCID lcid;
8298 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
8299
8300 if (len < 0 || (len && !buffer) || !locale || calendar)
8301 {
8303 return 0;
8304 }
8305
8306 TRACE( "(%s,%lx,%p,%s,%p,%d)\n", debugstr_w(name), flags, systime, debugstr_w(format), buffer, len );
8307 return get_date_format( locale, flags, systime, format, buffer, len );
8308}
8309
8310
8311/******************************************************************************
8312 * GetTimeFormatA (kernelbase.@)
8313 */
8315 const char *format, char *buffer, int len )
8316{
8318 WCHAR formatW[128], output[128];
8319 int ret;
8320
8321 TRACE( "(0x%04lx,0x%08lx,%p,%s,%p,%d)\n", lcid, flags, time, debugstr_a(format), buffer, len );
8322
8323 if (len < 0 || (len && !buffer))
8324 {
8326 return 0;
8327 }
8328 if (format)
8329 {
8330 MultiByteToWideChar( cp, 0, format, -1, formatW, ARRAY_SIZE(formatW) );
8331 ret = GetTimeFormatW( lcid, flags, time, formatW, output, ARRAY_SIZE(output) );
8332 }
8333 else ret = GetTimeFormatW( lcid, flags, time, NULL, output, ARRAY_SIZE(output) );
8334
8335 if (ret) ret = WideCharToMultiByte( cp, 0, output, -1, buffer, len, 0, 0 );
8336 return ret;
8337}
8338
8339
8340/***********************************************************************
8341 * GetTimeFormatW (kernelbase.@)
8342 */
8344 const WCHAR *format, WCHAR *buffer, int len )
8345{
8346 const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 );
8347
8348 if (len < 0 || (len && !buffer) || !locale)
8349 {
8351 return 0;
8352 }
8353
8354 TRACE( "(%04lx,%lx,%p,%s,%p,%d)\n", lcid, flags, systime, debugstr_w(format), buffer, len );
8355 return get_time_format( locale, flags, systime, format, buffer, len );
8356}
8357
8358
8359/***********************************************************************
8360 * GetTimeFormatEx (kernelbase.@)
8361 */
8363 const WCHAR *format, WCHAR *buffer, int len )
8364{
8365 LCID lcid;
8366 const NLS_LOCALE_DATA *locale = get_locale_by_name( name, &lcid );
8367
8368 if (len < 0 || (len && !buffer) || !locale)
8369 {
8371 return 0;
8372 }
8373
8374 TRACE( "(%s,%lx,%p,%s,%p,%d)\n", debugstr_w(name), flags, systime, debugstr_w(format), buffer, len );
8375 return get_time_format( locale, flags, systime, format, buffer, len );
8376}
BOOL WINAPI EnumSystemLocalesEx(LOCALE_ENUMPROCEX proc, DWORD flags, LPARAM lparam, LPVOID reserved)
INT WINAPI GetLocaleInfoEx(LPCWSTR locale, LCTYPE info, LPWSTR buffer, INT len)
#define CAL_SABBREVERASTRING
int WINAPI LCIDToLocaleName(_In_ LCID Locale, _Out_writes_opt_(cchName) LPWSTR lpName, _In_ int cchName, _In_ DWORD dwFlags)
unsigned char BOOLEAN
@ lparam
Definition: SystemMenu.c:31
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
static int used
Definition: adh-main.c:39
#define skip(...)
Definition: atltest.h:64
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:49
#define ARRAY_SIZE(A)
Definition: main.h:20
static BOOL expand(LPINT ac, LPTSTR **arg, LPCTSTR pattern)
Definition: misc.c:228
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
#define RegCloseKey(hKey)
Definition: registry.h:49
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1365
#define except(x)
Definition: btrfs_drv.h:136
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Definition: _ctype.h:58
Definition: _locale.h:75
wcscat
wcscpy
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
LONG RegLoadMUIStringW(IN HKEY hKey, IN LPCWSTR pszValue OPTIONAL, OUT LPWSTR pszOutBuf, IN DWORD cbOutBuf, OUT LPDWORD pcbData OPTIONAL, IN DWORD Flags, IN LPCWSTR pszDirectory OPTIONAL)
Definition: muireg.c:53
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define frac(x)
Definition: texture.c:364
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegSetKeyValueW(IN HKEY hKey, IN LPCWSTR lpSubKey OPTIONAL, IN LPCWSTR lpValueName OPTIONAL, IN DWORD dwType, IN LPCVOID lpData OPTIONAL, IN DWORD cbData)
Definition: reg.c:2139
static __inline BOOL set_ntstatus(NTSTATUS status)
Definition: security.c:227
#define wcschr
Definition: compat.h:17
#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 GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#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 FreeLibrary(x)
Definition: compat.h:748
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
LCID WINAPI LocaleNameToLCID(_In_ LPCWSTR lpName, _In_ DWORD dwFlags)
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
GEOID WINAPI GetUserGeoID(GEOCLASS GeoClass)
Definition: locale.c:4841
#define LOCALE_NAME_USER_DEFAULT
Definition: locale.c:43
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2803
BOOL WINAPI EnumSystemLocalesW(LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:3001
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, LPSTR dst, INT dstlen)
Definition: locale.c:3834
BOOL WINAPI GetFileMUIInfo(DWORD flags, PCWSTR path, FILEMUIINFO *info, DWORD *size)
Definition: locale.c:6231
INT WINAPI ResolveLocaleName(LPCWSTR name, LPWSTR localename, INT len)
Definition: locale.c:6243
BOOL WINAPI IsDBCSLeadByte(BYTE testchar)
Definition: locale.c:2126
UINT WINAPI GetACP(void)
Definition: locale.c:2023
static UINT get_lcid_codepage(LCID lcid)
Definition: locale.c:288
BOOL WINAPI GetStringTypeA(LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype)
Definition: locale.c:3212
BOOL WINAPI EnumSystemLanguageGroupsW(LANGUAGEGROUP_ENUMPROCW pLangGrpEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4599
BOOL WINAPI IsValidLanguageGroup(LGRPID lgrpid, DWORD dwFlags)
Definition: locale.c:4627
BOOL WINAPI EnumSystemCodePagesW(CODEPAGE_ENUMPROCW lpfnCodePageEnum, DWORD flags)
Definition: locale.c:2297
BOOL WINAPI GetFileMUIPath(DWORD flags, PCWSTR filepath, PWSTR language, PULONG languagelen, PWSTR muipath, PULONG muipathlen, PULONGLONG enumerator)
Definition: locale.c:6216
INT WINAPI NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, INT cwSrcLength, LPWSTR lpDstString, INT cwDstLength)
Definition: locale.c:5662
LANGID WINAPI GetSystemDefaultLangID(void)
Definition: locale.c:1199
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2081
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4086
INT WINAPI IdnToUnicode(DWORD dwFlags, LPCWSTR lpASCIICharStr, INT cchASCIIChar, LPWSTR lpUnicodeCharStr, INT cchUnicodeChar)
Definition: locale.c:6059
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4017
BOOL WINAPI SetUserGeoID(GEOID GeoID)
Definition: locale.c:4878
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: locale.c:1380
DWORD WINAPI VerLanguageNameW(DWORD wLang, LPWSTR szLang, DWORD nSize)
Definition: locale.c:3087
BOOL WINAPI GetSystemPreferredUILanguages(DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size)
Definition: locale.c:1301
BOOL WINAPI GetCPInfoExW(UINT codepage, DWORD dwFlags, LPCPINFOEXW cpinfo)
Definition: locale.c:2222
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1609
BOOL WINAPI GetCPInfo(UINT codepage, LPCPINFO cpinfo)
Definition: locale.c:2146
static const union cptable * get_codepage_table(unsigned int codepage)
Definition: locale.c:302
INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
Definition: locale.c:5495
BOOL WINAPI IsValidLocaleName(LPCWSTR locale)
Definition: locale.c:2936
INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpASCIICharStr, INT cchASCIIChar)
Definition: locale.c:5706
BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4976
BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2986
DWORD WINAPI VerLanguageNameA(DWORD wLang, LPSTR szLang, DWORD nSize)
Definition: locale.c:3076
INT WINAPI LCMapStringEx(LPCWSTR locale, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM handle)
Definition: locale.c:3746
LANGID WINAPI GetSystemDefaultUILanguage(void)
Definition: locale.c:1400
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3098
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: locale.c:2925
INT WINAPI GetSystemDefaultLocaleName(LPWSTR localename, INT len)
Definition: locale.c:1246
BOOL WINAPI IsDBCSLeadByteEx(UINT codepage, BYTE testchar)
Definition: locale.c:2106
INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3982
BOOL WINAPI GetThreadPreferredUILanguages(DWORD flags, ULONG *count, WCHAR *buf, ULONG *size)
Definition: locale.c:1334
LCID WINAPI GetUserDefaultLCID(void)
Definition: locale.c:1216
INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lParam)
Definition: locale.c:4026
BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc, LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam)
Definition: locale.c:4799
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1182
LCID WINAPI GetSystemDefaultLCID(void)
Definition: locale.c:1235
BOOL WINAPI GetStringTypeExW(LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3188
BOOL WINAPI IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpString, INT cwLength)
Definition: locale.c:5673
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3808
BOOL WINAPI SetThreadPreferredUILanguages(DWORD flags, PCZZWSTR buffer, PULONG count)
Definition: locale.c:1325
BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumproc)
Definition: locale.c:5613
UINT WINAPI GetOEMCP(void)
Definition: locale.c:2062
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1675
#define REG_SZ
Definition: locale.c:45
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: locale.c:2879
BOOL WINAPI SetLocaleInfoW(LCID lcid, LCTYPE lctype, LPCWSTR data)
Definition: locale.c:1923
INT WINAPI IdnToNameprepUnicode(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar, LPWSTR lpNameprepCharStr, INT cchNameprepChar)
Definition: locale.c:5844
INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
Definition: locale.c:5649
const WCHAR system_dir[]
Definition: file.c:68
static HKEY tz_key
Definition: locale.c:310
#define CASE_FULLWIDTH
Definition: locale.c:370
#define ENCODABLE(ch)
BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsExEx(DATEFMT_ENUMPROCEXEX proc, const WCHAR *locale, DWORD flags, LPARAM lparam)
Definition: locale.c:4973
static int mbstowcs_codepage(const CPTABLEINFO *info, DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2731
static struct registry_entry entry_idigits
Definition: locale.c:61
static LCID system_lcid
Definition: locale.c:306
static const NLS_LOCALE_DATA * get_locale_data(UINT idx)
Definition: locale.c:546
static BOOL remove_unneeded_weights(const struct sortguid *sortid, struct sortkey_state *s)
Definition: locale.c:3629
BOOL WINAPI DECLSPEC_HOTPATCH IsNLSDefinedString(NLS_FUNCTION func, DWORD flags, NLSVERSIONINFO *info, const WCHAR *str, int len)
Definition: locale.c:6745
static int mbstowcs_decompose(const CPTABLEINFO *info, const unsigned char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2548
static int get_compression_weights(UINT compression, const WCHAR *compr_tables[8], const WCHAR *src, int srclen, union char_weights *weights)
Definition: locale.c:3378
static int wcstombs_sbcs(const CPTABLEINFO *info, const WCHAR *src, unsigned int srclen, char *dst, unsigned int dstlen)
Definition: locale.c:2912
WCHAR daylight_name[32]
Definition: locale.c:5659
static int compare_locale_names(const WCHAR *n1, const WCHAR *n2)
Definition: locale.c:564
static int put_utf16(WCHAR *dst, int pos, int dstlen, unsigned int ch)
Definition: locale.c:2017
static void load_locale_nls(void)
Definition: locale.c:437
static int locale_return_data(const WCHAR *data, int datalen, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:752
sortkey_script
Definition: locale.c:380
@ SCRIPT_DIGIT
Definition: locale.c:394
@ SCRIPT_JAMO_SPECIAL
Definition: locale.c:385
@ SCRIPT_GREEK
Definition: locale.c:396
@ SCRIPT_PUNCTUATION
Definition: locale.c:387
@ SCRIPT_ARABIC
Definition: locale.c:400
@ SCRIPT_SYMBOL_6
Definition: locale.c:393
@ SCRIPT_CJK_LAST
Definition: locale.c:404
@ SCRIPT_SYMBOL_4
Definition: locale.c:391
@ SCRIPT_SYMBOL_5
Definition: locale.c:392
@ SCRIPT_UNSORTABLE
Definition: locale.c:381
@ SCRIPT_KANA
Definition: locale.c:398
@ SCRIPT_EXPANSION
Definition: locale.c:383
@ SCRIPT_LATIN
Definition: locale.c:395
@ SCRIPT_PUA_LAST
Definition: locale.c:402
@ SCRIPT_HEBREW
Definition: locale.c:399
@ SCRIPT_CYRILLIC
Definition: locale.c:397
@ SCRIPT_PUA_FIRST
Definition: locale.c:401
@ SCRIPT_SYMBOL_1
Definition: locale.c:388
@ SCRIPT_EXTENSION_A
Definition: locale.c:386
@ SCRIPT_SYMBOL_2
Definition: locale.c:389
@ SCRIPT_CJK_FIRST
Definition: locale.c:403
@ SCRIPT_SYMBOL_3
Definition: locale.c:390
@ SCRIPT_NONSPACE_MARK
Definition: locale.c:382
@ SCRIPT_EASTASIA_SPECIAL
Definition: locale.c:384
static HMODULE kernelbase_handle
Definition: locale.c:45
INT WINAPI SetCalendarInfoW(LCID lcid, CALID calendar, CALTYPE type, const WCHAR *data)
Definition: locale.c:7214
static void reverse_sortkey(struct sortkey *key)
Definition: locale.c:3294
static struct registry_entry entry_inegcurr
Definition: locale.c:67
static struct registry_entry entry_smonthousandsep
Definition: locale.c:80
BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExW(CALINFO_ENUMPROCEXW proc, LCID lcid, CALID id, CALTYPE type)
Definition: locale.c:4931
static int check_invalid_chars(const CPTABLEINFO *info, const unsigned char *src, int srclen)
Definition: locale.c:2513
static int get_geo_info(const struct geo_id *geo, enum SYSGEOTYPE type, WCHAR *buffer, int len, LANGID lang)
Definition: locale.c:1777
static int wcstombs_cpsymbol(DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:2758
static struct registry_entry entry_imeasure
Definition: locale.c:66
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemLanguageGroups(LANGUAGEGROUP_ENUMPROCW proc, DWORD flags, LONG_PTR param, BOOL unicode)
Definition: locale.c:4555
static int mbstowcs_sbcs(const CPTABLEINFO *info, const unsigned char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2631
static const struct sortguid ** locale_sorts
Definition: locale.c:407
static int get_pattern_len(const WCHAR *pattern, const WCHAR *accept)
Definition: locale.c:7907
static struct registry_entry entry_inegnumber
Definition: locale.c:68
static int mbstowcs_utf8(DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2486
static const NLS_LOCALE_LCNAME_INDEX * lcnames_index
Definition: locale.c:312
#define CASE_COMPR_2
Definition: locale.c:375
static int get_locale_info(const NLS_LOCALE_DATA *locale, LCID lcid, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:1112
static struct registry_entry entry_scurrency
Definition: locale.c:72
static int append_extra_kana_weights(struct sortkey keys[4], const WCHAR *src, int pos, UINT except, BYTE case_mask, union char_weights *weights)
Definition: locale.c:3459
int WINAPI GetNumberFormatW(LCID lcid, DWORD flags, const WCHAR *value, const NUMBERFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:8168
#define HANGUL_VCOUNT
Definition: locale.c:3503
BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsExW(DATEFMT_ENUMPROCEXW proc, LCID lcid, DWORD flags)
Definition: locale.c:4963
static struct registry_entry entry_sgrouping
Definition: locale.c:74
static int wcstombs_codepage(const CPTABLEINFO *info, DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:3253
#define CASE_KATAKANA
Definition: locale.c:374
INT WINAPI DECLSPEC_HOTPATCH GetGeoInfoEx(WCHAR *location, GEOTYPE type, WCHAR *data, int data_count)
Definition: locale.c:5985
DWORD WINAPI DECLSPEC_HOTPATCH FormatMessageA(DWORD flags, const void *source, DWORD msgid, DWORD langid, char *buffer, DWORD size, va_list *args)
Definition: locale.c:5383
BOOL WINAPI DECLSPEC_HOTPATCH SetProcessPreferredUILanguages(DWORD flags, PCZZWSTR buffer, ULONG *count)
Definition: locale.c:7224
BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsW(DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: locale.c:4953
static const struct geo_id * geo_ids
static BYTE get_char_props(const struct norm_table *info, unsigned int ch)
Definition: locale.c:2099
BOOL WINAPI DECLSPEC_HOTPATCH GetTimeZoneInformationForYear(USHORT year, DYNAMIC_TIME_ZONE_INFORMATION *dynamic, TIME_ZONE_INFORMATION *info)
Definition: locale.c:6308
#define UPDATE(val, entry)
static int mbstowcs_dbcs(const CPTABLEINFO *info, const unsigned char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2695
static void append_normal_weights(const struct sortguid *sortid, struct sortkey *key_primary, struct sortkey *key_diacritic, struct sortkey *key_case, union char_weights weights, DWORD flags)
Definition: locale.c:3313
static const NLS_LOCALE_LCID_INDEX * find_lcid_entry(LCID lcid)
Definition: locale.c:596
static int find_substring(const struct sortguid *sortid, DWORD flags, const WCHAR *src, int srclen, const WCHAR *value, int valuelen, int *reslen)
Definition: locale.c:3897
static BOOL validate_mui_resource(struct mui_resource *mui, DWORD size)
Definition: locale.c:5765
UINT cp
Definition: locale.c:91
BOOL WINAPI DECLSPEC_HOTPATCH IsCharPunctW(WCHAR wc)
Definition: locale.c:6589
static int map_to_fullwidth(const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:3987
static struct registry_entry entry_sshortdate
Definition: locale.c:84
int WINAPI GetTimeFormatW(LCID lcid, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len)
Definition: locale.c:8343
static struct registry_entry entry_icurrdigits
Definition: locale.c:59
#define CASE_SUBSCRIPT
Definition: locale.c:372
int WINAPI GetNumberFormatEx(const WCHAR *name, DWORD flags, const WCHAR *value, const NUMBERFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:8187
BOOL WINAPI DECLSPEC_HOTPATCH IsCharSpaceW(WCHAR wc)
Definition: locale.c:6610
LCID lcid
Definition: locale.c:5656
int WINAPI GetDateFormatEx(const WCHAR *name, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len, const WCHAR *calendar)
Definition: locale.c:8294
static void update_registry_value(UINT type, const WCHAR *subkey, const WCHAR *value)
Definition: locale.c:1844
static BOOL set_registry_entry(struct registry_entry *entry, const WCHAR *data)
Definition: locale.c:771
BOOL WINAPI DECLSPEC_HOTPATCH IsCharAlphaW(WCHAR wc)
Definition: locale.c:6511
static BOOL call_enum_date_func(DATEFMT_ENUMPROCW proc, const NLS_LOCALE_DATA *locale, DWORD flags, DWORD str, WCHAR *buffer, CALID id, BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam)
Definition: locale.c:4377
DWORD WINAPI DECLSPEC_HOTPATCH GetTimeZoneInformation(TIME_ZONE_INFORMATION *info)
Definition: locale.c:6295
BOOL WINAPI DECLSPEC_HOTPATCH IsCharDigitW(WCHAR wc)
Definition: locale.c:6559
INT WINAPI GetUserDefaultGeoName(LPWSTR geo_name, int count)
Definition: locale.c:7421
BOOL WINAPI DECLSPEC_HOTPATCH IsCharLowerA(CHAR c)
Definition: locale.c:6568
static CPTABLEINFO ansi_cpinfo
Definition: locale.c:303
static struct registry_entry entry_icountry
Definition: locale.c:58
static HKEY intl_key
Definition: locale.c:308
static struct registry_entry entry_smondecimalsep
Definition: locale.c:78
static int append_weights(const struct sortguid *sortid, DWORD flags, const WCHAR *src, int srclen, int pos, BYTE case_mask, UINT except, const WCHAR *compr_tables[8], struct sortkey_state *s, BOOL is_compare)
Definition: locale.c:3664
static void grouping_to_string(UINT grouping, WCHAR *buffer)
Definition: locale.c:7480
static int compare_tzdate(const TIME_FIELDS *tf, const SYSTEMTIME *compare)
Definition: locale.c:4224
static struct registry_entry entry_smongrouping
Definition: locale.c:79
static const UINT * find_compression(const WCHAR *src, const WCHAR *table, int count, int len)
Definition: locale.c:3361
BOOL WINAPI DECLSPEC_HOTPATCH IsCharXDigitW(WCHAR wc)
Definition: locale.c:6640
static int wcstombs_sbcs_slow(const CPTABLEINFO *info, DWORD flags, const WCHAR *src, unsigned int srclen, char *dst, unsigned int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:3035
static const WCHAR ligatures[][5]
Definition: locale.c:174
static int append_digit_weights(struct sortkey *key, const WCHAR *src, UINT srclen)
Definition: locale.c:3431
const BYTE * ctype_idx
Definition: locale.c:419
static int cal_return_number(UINT val, CALTYPE type, WCHAR *buffer, int len, DWORD *value)
Definition: locale.c:975
static int map_remove_ignored(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:4052
UINT exp_count
Definition: locale.c:414
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: locale.c:428
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumCalendarInfo(CALINFO_ENUMPROCW proc, const NLS_LOCALE_DATA *locale, CALID id, CALTYPE type, BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam)
Definition: locale.c:4316
INT WINAPI DECLSPEC_HOTPATCH FindStringOrdinal(DWORD flag, const WCHAR *src, INT src_size, const WCHAR *val, INT val_size, BOOL ignore_case)
Definition: locale.c:5254
int WINAPI GetCurrencyFormatEx(const WCHAR *name, DWORD flags, const WCHAR *value, const CURRENCYFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:8226
static int locale_return_grouping(DWORD pos, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:901
static const WCHAR world_subkey[]
Definition: locale.c:55
static int get_calendar_info(const NLS_LOCALE_DATA *locale, CALID id, CALTYPE type, WCHAR *buffer, int len, DWORD *value)
Definition: locale.c:1617
static struct registry_entry entry_sdecimal
Definition: locale.c:73
static int is_valid_dbcs_mapping(const CPTABLEINFO *info, DWORD flags, unsigned int wch)
Definition: locale.c:3019
BOOL WINAPI DECLSPEC_HOTPATCH GetNLSVersion(NLS_FUNCTION func, LCID lcid, NLSVERSIONINFO *info)
Definition: locale.c:6100
DWORD WINAPI DECLSPEC_HOTPATCH GetDynamicTimeZoneInformation(DYNAMIC_TIME_ZONE_INFORMATION *info)
Definition: locale.c:5665
static int map_to_halfwidth(const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:4091
static WCHAR compose_chars(WCHAR ch1, WCHAR ch2)
Definition: locale.c:2152
static NTSTATUS expand_ligatures(const WCHAR *src, int srclen, WCHAR *dst, int *dstlen)
Definition: locale.c:2260
UINT guid_count
Definition: locale.c:413
static void load_sortdefault_nls(void)
Definition: locale.c:479
static const struct sortguid * get_language_sort(const WCHAR *name)
Definition: locale.c:662
static int wcstombs_dbcs(const CPTABLEINFO *info, const WCHAR *src, unsigned int srclen, char *dst, unsigned int dstlen)
Definition: locale.c:2977
static int compare_sortkeys(const struct sortkey *key1, const struct sortkey *key2, BOOL shorter_wins)
Definition: locale.c:3306
static struct registry_entry entry_slist
Definition: locale.c:76
static int compare_string(const struct sortguid *sortid, DWORD flags, const WCHAR *src1, int srclen1, const WCHAR *src2, int srclen2)
Definition: locale.c:3830
const NLS_LOCALE_DATA *WINAPI NlsValidateLocale(LCID *lcid, ULONG flags)
Definition: locale.c:723
static const NLS_LOCALE_DATA * get_locale_by_name(const WCHAR *name, LCID *lcid)
Definition: locale.c:642
const WORD * ctypes
Definition: locale.c:418
charmaps
Definition: locale.c:259
@ CHARMAP_SIMPLIFIED
Definition: locale.c:267
@ CHARMAP_FULLWIDTH
Definition: locale.c:265
@ CHARMAP_FOLDDIGITS
Definition: locale.c:260
@ NB_CHARMAPS
Definition: locale.c:268
@ CHARMAP_TRADITIONAL
Definition: locale.c:266
@ CHARMAP_HIRAGANA
Definition: locale.c:262
@ CHARMAP_KATAKANA
Definition: locale.c:263
@ CHARMAP_HALFWIDTH
Definition: locale.c:264
@ CHARMAP_COMPAT
Definition: locale.c:261
static const NLS_LOCALE_LCNAME_INDEX * find_lcname_entry(const WCHAR *name)
Definition: locale.c:579
static struct registry_entry entry_spositivesign
Definition: locale.c:83
BOOL WINAPI DECLSPEC_HOTPATCH IsCharAlphaNumericW(WCHAR wc)
Definition: locale.c:6532
static int wcstombs_utf7(DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:2794
static WCHAR * prepend_str(WCHAR *end, const WCHAR *str)
Definition: locale.c:7521
BOOL WINAPI DECLSPEC_HOTPATCH IsCharSpaceA(CHAR c)
Definition: locale.c:6598
static struct registry_entry entry_snativedigits
Definition: locale.c:81
static const struct sortguid * current_locale_sort
Definition: locale.c:408
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumDateFormats(DATEFMT_ENUMPROCW proc, const NLS_LOCALE_DATA *locale, DWORD flags, BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam)
Definition: locale.c:4396
static void append_nonspace_weights(struct sortkey *key, union char_weights weights, DWORD flags)
Definition: locale.c:3337
static const WCHAR * get_decomposition(WCHAR ch, unsigned int *ret_len)
Definition: locale.c:2110
const WCHAR * compr_data
Definition: locale.c:423
static NTSTATUS fold_string(DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int *dstlen)
Definition: locale.c:2298
#define OUTPUT(ch)
static CRITICAL_SECTION_DEBUG tzname_section_debug
Definition: locale.c:5648
const struct jamo_sort * jamo
Definition: locale.c:424
#define HANGUL_TCOUNT
Definition: locale.c:3504
static struct @514 cached_tzname
static unsigned int casemap_high(const USHORT *table, WCHAR high, WCHAR low)
Definition: locale.c:2004
#define MUI_SIGNATURE
Definition: locale.c:5734
BOOL WINAPI DECLSPEC_HOTPATCH IsCharAlphaNumericA(CHAR c)
Definition: locale.c:6520
#define CASE_COMPR_6
Definition: locale.c:377
static const struct calendar * get_calendar_data(const NLS_LOCALE_DATA *locale, UINT id)
Definition: locale.c:553
const struct sortguid * guids
Definition: locale.c:420
BOOL WINAPI DECLSPEC_HOTPATCH GetNLSVersionEx(NLS_FUNCTION func, const WCHAR *locale, NLSVERSIONINFOEX *info)
Definition: locale.c:6121
static struct registry_entry entry_s2359
Definition: locale.c:71
BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExEx(CALINFO_ENUMPROCEXEX proc, LPCWSTR locale, CALID id, LPCWSTR reserved, CALTYPE type, LPARAM lparam)
Definition: locale.c:4941
static struct registry_entry entry_sthousand
Definition: locale.c:86
static const struct @512 codepage_names[]
BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoW(CALINFO_ENUMPROCW proc, LCID lcid, CALID id, CALTYPE type)
Definition: locale.c:4920
static struct registry_entry entry_ifirstdayofweek
Definition: locale.c:63
static int locale_return_number(UINT val, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:843
const WCHAR * name
Definition: locale.c:91
static BOOL table_has_high_planes(const USHORT *table)
Definition: locale.c:2011
#define FLAG_HAS_3_BYTE_WEIGHTS
Definition: locale.c:334
static CRITICAL_SECTION tzname_section
Definition: locale.c:5647
static unsigned int geo_ids_count
Definition: locale.c:255
static DWORD get_timezone_id(const TIME_ZONE_INFORMATION *info, LARGE_INTEGER time, BOOL is_local)
Definition: locale.c:4255
static int locale_return_reg_number(struct registry_entry *entry, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:880
static int mbstowcs_cpsymbol(DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2359
static int get_currency_format(const NLS_LOCALE_DATA *locale, DWORD flags, const WCHAR *value, const CURRENCYFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:7740
void init_locale(HMODULE module)
Definition: locale.c:1911
static int is_valid_sbcs_mapping(const CPTABLEINFO *info, DWORD flags, unsigned int wch)
Definition: locale.c:3008
#define FLAG_REVERSEDIACRITICS
Definition: locale.c:335
static void append_sortkey(struct sortkey *key, BYTE val)
Definition: locale.c:3280
static HKEY nls_key
Definition: locale.c:309
int WINAPI GetTimeFormatEx(const WCHAR *name, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len)
Definition: locale.c:8362
const struct sort_expansion * expansions
Definition: locale.c:421
static NTSTATUS fold_digits(const WCHAR *src, int srclen, WCHAR *dst, int *dstlen)
Definition: locale.c:2287
static const WCHAR * get_ligature(WCHAR wc)
Definition: locale.c:2246
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemCodePages(CODEPAGE_ENUMPROCW proc, DWORD flags, BOOL unicode)
Definition: locale.c:4524
#define CASE_UPPER
Definition: locale.c:373
static int mbstowcs_utf7(DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2384
static unsigned int nb_codepages
Definition: locale.c:319
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumTimeFormats(TIMEFMT_ENUMPROCW proc, const NLS_LOCALE_DATA *locale, DWORD flags, BOOL unicode, BOOL ex, LPARAM lparam)
Definition: locale.c:4613
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumUILanguages(UILANGUAGE_ENUMPROCW proc, DWORD flags, LONG_PTR param, BOOL unicode)
Definition: locale.c:4666
static struct registry_entry entry_idigitsubstitution
Definition: locale.c:62
static struct registry_entry entry_slongdate
Definition: locale.c:77
static WCHAR * format_number(WCHAR *end, const WCHAR *value, const WCHAR *decimal_sep, const WCHAR *thousand_sep, const WCHAR *grouping, UINT digits, BOOL lzero)
Definition: locale.c:7529
static void free_sortkey_state(struct sortkey_state *s)
Definition: locale.c:3652
static const struct sortguid * find_sortguid(const GUID *guid)
Definition: locale.c:529
static struct registry_entry entry_icurrency
Definition: locale.c:60
DWORD WINAPI DECLSPEC_HOTPATCH GetDynamicTimeZoneInformationEffectiveYears(const DYNAMIC_TIME_ZONE_INFORMATION *info, DWORD *first, DWORD *last)
Definition: locale.c:5710
BOOL WINAPI DECLSPEC_HOTPATCH SystemTimeToTzSpecificLocalTime(const TIME_ZONE_INFORMATION *info, const SYSTEMTIME *system, SYSTEMTIME *local)
Definition: locale.c:7282
static CPTABLEINFO codepages[128]
Definition: locale.c:318
static int get_sortkey(const struct sortguid *sortid, DWORD flags, const WCHAR *src, int srclen, BYTE *dst, int dstlen)
Definition: locale.c:3776
INT WINAPI DECLSPEC_HOTPATCH GetCalendarInfoW(LCID lcid, CALID calendar, CALTYPE type, WCHAR *buffer, INT len, DWORD *value)
Definition: locale.c:5611
static struct registry_entry entry_icalendartype
Definition: locale.c:57
const USHORT * casemap
Definition: locale.c:417
static int get_number_format(const NLS_LOCALE_DATA *locale, DWORD flags, const WCHAR *value, const NUMBERFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:7646
static void map_byterev(const WCHAR *src, int len, WCHAR *dst)
Definition: locale.c:2042
DWORD WINAPI DECLSPEC_HOTPATCH FormatMessageW(DWORD flags, const void *source, DWORD msgid, DWORD langid, WCHAR *buffer, DWORD size, va_list *args)
Definition: locale.c:5466
static UINT unix_cp
Definition: locale.c:305
static int compression_size(int len)
Definition: locale.c:361
BOOL WINAPI DECLSPEC_HOTPATCH EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX proc, const WCHAR *locale, DWORD flags, LPARAM lparam)
Definition: locale.c:5177
static struct registry_entry entry_sintlsymbol
Definition: locale.c:75
static WCHAR * locale_replace_separator(WCHAR *buffer, const WCHAR *sep)
Definition: locale.c:1012
static CRITICAL_SECTION locale_section
Definition: locale.c:427
static int wcstombs_dbcs_slow(const CPTABLEINFO *info, DWORD flags, const WCHAR *src, unsigned int srclen, char *dst, unsigned int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:3130
#define HANGUL_SBASE
Definition: locale.c:3501
static const NLS_LOCALE_HEADER * locale_table
Definition: locale.c:313
static int locale_return_string(DWORD pos, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:837
UINT compr_count
Definition: locale.c:415
static struct registry_entry entry_ipapersize
Definition: locale.c:69
static int locale_return_strarray_concat(DWORD pos, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:946
static int lcmap_string(const struct sortguid *sortid, DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:4134
static WCHAR get_digit_zero_char(WCHAR ch)
Definition: locale.c:3409
static struct registry_entry entry_ilzero
Definition: locale.c:65
BOOL WINAPI DECLSPEC_HOTPATCH IsCharUpperW(WCHAR wc)
Definition: locale.c:6631
static const struct geo_id * find_geo_name_entry(const WCHAR *name)
Definition: locale.c:626
const struct sort_compression * compressions
Definition: locale.c:422
static int get_time_format(const NLS_LOCALE_DATA *locale, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len)
Definition: locale.c:8051
static const WCHAR * locale_strings
Definition: locale.c:314
BOOL WINAPI DECLSPEC_HOTPATCH IsCharLowerW(WCHAR wc)
Definition: locale.c:6580
static struct registry_entry entry_syearmonth
Definition: locale.c:88
BOOL WINAPI DECLSPEC_HOTPATCH IsCharUpperA(CHAR c)
Definition: locale.c:6619
BOOL WINAPI SetUserGeoName(PWSTR geo_name)
Definition: locale.c:7465
static struct @513 sort
static void update_locale_registry(void)
Definition: locale.c:1853
static const struct geo_id * find_geo_id_entry(GEOID id)
Definition: locale.c:611
static const NLS_LOCALE_DATA * system_locale
Definition: locale.c:315
static struct registry_entry entry_snegativesign
Definition: locale.c:82
int WINAPI GetCurrencyFormatW(LCID lcid, DWORD flags, const WCHAR *value, const CURRENCYFMTW *format, WCHAR *buffer, int len)
Definition: locale.c:8207
static void append_expansion_weights(const struct sortguid *sortid, struct sortkey *key_primary, struct sortkey *key_diacritic, struct sortkey *key_case, union char_weights weights, DWORD flags, BOOL is_compare)
Definition: locale.c:3344
static struct registry_entry entry_sshorttime
Definition: locale.c:85
INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal(const WCHAR *str1, INT len1, const WCHAR *str2, INT len2, BOOL ignore_case)
Definition: locale.c:4886
INT WINAPI DECLSPEC_HOTPATCH GetCalendarInfoEx(const WCHAR *name, CALID calendar, const WCHAR *reserved, CALTYPE type, WCHAR *buffer, INT len, DWORD *value)
Definition: locale.c:5630
static WORD get_char_type(DWORD type, WCHAR ch)
Definition: locale.c:2034
static CPTABLEINFO oem_cpinfo
Definition: locale.c:304
INT WINAPI DECLSPEC_HOTPATCH FindNLSStringEx(const WCHAR *locale, DWORD flags, const WCHAR *src, int srclen, const WCHAR *value, int valuelen, int *found, NLSVERSIONINFO *version, void *reserved, LPARAM handle)
Definition: locale.c:5223
static int put_sortkey(BYTE *dst, int dstlen, int pos, const struct sortkey *key, BYTE terminator)
Definition: locale.c:3570
BOOL WINAPI DECLSPEC_HOTPATCH IsCharCntrlW(WCHAR wc)
Definition: locale.c:6550
static const WCHAR * get_message(DWORD flags, const void *src, UINT id, UINT lang, BOOL ansi, WCHAR **buffer)
Definition: locale.c:5343
static struct registry_entry entry_ifirstweekofyear
Definition: locale.c:64
#define CASE_COMPR_4
Definition: locale.c:376
static int nonspace_ignored(WCHAR ch)
Definition: locale.c:4045
BOOL WINAPI DECLSPEC_HOTPATCH SetTimeZoneInformation(const TIME_ZONE_INFORMATION *info)
Definition: locale.c:7242
static struct registry_entry entry_stimeformat
Definition: locale.c:87
int WINAPI GetDateFormatW(LCID lcid, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len)
Definition: locale.c:8275
int WINAPI GetDateFormatA(LCID lcid, DWORD flags, const SYSTEMTIME *time, const char *format, char *buffer, int len)
Definition: locale.c:8246
#define CASE_FULLSIZE
Definition: locale.c:371
static int locale_return_strarray(DWORD pos, WORD idx, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:937
static struct norm_table * norm_info
Definition: locale.c:321
static WCHAR * find_format(WCHAR *str, const WCHAR *accept)
Definition: locale.c:991
static int wcstombs_utf8(DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, BOOL *used)
Definition: locale.c:2889
BOOL WINAPI DECLSPEC_HOTPATCH IsCharAlphaA(CHAR c)
Definition: locale.c:6499
const UINT * keys
Definition: locale.c:416
BOOL WINAPI DECLSPEC_HOTPATCH TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION *info, const SYSTEMTIME *local, SYSTEMTIME *system)
Definition: locale.c:7317
INT WINAPI DECLSPEC_HOTPATCH FindNLSString(LCID lcid, DWORD flags, const WCHAR *src, int srclen, const WCHAR *value, int valuelen, int *found)
Definition: locale.c:5189
static unsigned int geo_index_count
Definition: locale.c:256
static LCID user_lcid
Definition: locale.c:307
DWORD WINAPI DECLSPEC_HOTPATCH IsValidNLSVersion(NLS_FUNCTION func, const WCHAR *locale, NLSVERSIONINFOEX *info)
Definition: locale.c:6786
static int is_private_use_area_char(WCHAR code)
Definition: locale.c:2507
static union char_weights get_char_weights(WCHAR c, UINT except)
Definition: locale.c:2084
BOOL WINAPI DECLSPEC_HOTPATCH IsCharBlankW(WCHAR wc)
Definition: locale.c:6541
static const WCHAR * get_locale_sortname(LCID lcid)
Definition: locale.c:1036
int WINAPI GetTimeFormatA(LCID lcid, DWORD flags, const SYSTEMTIME *time, const char *format, char *buffer, int len)
Definition: locale.c:8314
static void init_sortkey_state(struct sortkey_state *s, DWORD flags, UINT srclen, BYTE *primary_buf, UINT primary_size)
Definition: locale.c:3592
static int get_date_format(const NLS_LOCALE_DATA *locale, DWORD flags, const SYSTEMTIME *systime, const WCHAR *format, WCHAR *buffer, int len)
Definition: locale.c:7926
static struct registry_entry entry_s1159
Definition: locale.c:70
static UINT get_locale_codepage(const NLS_LOCALE_DATA *locale, ULONG flags)
Definition: locale.c:2175
BOOL WINAPI DECLSPEC_HOTPATCH GetProcessPreferredUILanguages(DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size)
Definition: locale.c:6162
DWORD WINAPI DECLSPEC_HOTPATCH EnumDynamicTimeZoneInformation(DWORD index, DYNAMIC_TIME_ZONE_INFORMATION *info)
Definition: locale.c:4986
WCHAR standard_name[32]
Definition: locale.c:5658
BOOL WINAPI DECLSPEC_HOTPATCH EnumTimeFormatsW(TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: locale.c:5168
static int append_hangul_weights(struct sortkey *key, const WCHAR *src, int srclen, UINT except)
Definition: locale.c:3506
static const NLS_LOCALE_LCID_INDEX * lcids_index
Definition: locale.c:311
static int locale_return_reg_string(struct registry_entry *entry, LCTYPE type, WCHAR *buffer, int len)
Definition: locale.c:795
static int casemap_string(const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen)
Definition: locale.c:2048
static const NLS_LOCALE_DATA * user_locale
Definition: locale.c:316
BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumLanguageGroupLocales(LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id, DWORD flags, LONG_PTR param, BOOL unicode)
Definition: locale.c:4476
INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
Definition: string.c:1220
GUID guid
Definition: version.c:147
unsigned char
Definition: typeof.h:29
#define swprintf
Definition: precomp.h:40
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
r reserved
Definition: btrfs.c:3006
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
time_t now
Definition: finger.c:65
#define local
Definition: zutil.h:30
int form
Definition: main.c:89
BOOLEAN valid
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei width
Definition: gl.h:1546
GLbyte GLbyte tz
Definition: glext.h:8756
GLenum func
Definition: glext.h:6028
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint * ids
Definition: glext.h:5907
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLfloat bias
Definition: glext.h:7909
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLubyte * pattern
Definition: glext.h:7787
GLint limit
Definition: glext.h:10326
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
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
const GLbyte * weights
Definition: glext.h:6523
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLuint GLenum GLuint GLuint key1
Definition: glext.h:10608
GLuint GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
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 flag
Definition: glfuncs.h:52
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
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
#define C1_CNTRL
Definition: unicode.h:36
#define C1_DIGIT
Definition: unicode.h:33
#define C1_PUNCT
Definition: unicode.h:35
#define C1_SPACE
Definition: unicode.h:34
#define C1_ALPHA
Definition: unicode.h:39
#define WC_DEFAULTCHAR
Definition: unicode.h:45
#define MB_COMPOSITE
Definition: unicode.h:40
#define WC_COMPOSITECHECK
Definition: unicode.h:43
#define WC_DISCARDNS
Definition: unicode.h:44
#define MB_USEGLYPHCHARS
Definition: unicode.h:42
#define WC_ERR_INVALID_CHARS
Definition: unicode.h:47
#define C1_BLANK
Definition: unicode.h:37
#define MB_ERR_INVALID_CHARS
Definition: unicode.h:41
#define C1_LOWER
Definition: unicode.h:32
#define C1_UPPER
Definition: unicode.h:31
#define C1_XDIGIT
Definition: unicode.h:38
#define WC_NO_BEST_FIT_CHARS
Definition: unicode.h:46
HFONT tf
Definition: icontest.c:17
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI NTSTATUS WINAPI RtlGetLocaleFileMappingAddress(void **, LCID *, LARGE_INTEGER *)
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
NTSYSAPI NTSTATUS WINAPI RtlQueryDynamicTimeZoneInformation(RTL_DYNAMIC_TIME_ZONE_INFORMATION *)
NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPWSTR, UCHAR, BOOLEAN, BOOLEAN, BOOLEAN, __ms_va_list *, LPWSTR, ULONG)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
NTSYSAPI NTSTATUS WINAPI NtGetNlsSectionPtr(ULONG, ULONG, void *, void **, SIZE_T *)
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
static const int digits[]
Definition: decode.c:71
#define c
Definition: ke_i.h:80
BOOL WINAPI GetUserPreferredUILanguages(DWORD dwFlags, PULONG pulNumLanguages, PZZWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer)
Definition: vista.c:698
#define debugstr_guid
Definition: kernel32.h:35
#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
#define GUID_NULL
Definition: ks.h:106
USHORT LANGID
Definition: mui.h:9
ULONG GEOID
Definition: mui.h:28
NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max, ULONG *utf8_bytes_written, const WCHAR *uni_src, ULONG uni_bytes)
Definition: utf8.c:20
if(dx< 0)
Definition: linetemp.h:194
POINT cp
Definition: magnifier.c:59
struct S1 s1
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:143
static UINT UINT last
Definition: font.c:45
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: directory.c:52
static DWORD LPDWORD reslen
Definition: directory.c:51
static DWORD dstlen
Definition: directory.c:51
static const WCHAR invalid[]
Definition: assoc.c:39
#define shift
Definition: input.c:1755
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
LANGID langid
Definition: msctf.idl:626
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define name_entry(pos)
Definition: name_cache.c:399
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlSetTimeZoneInformation(_In_ PRTL_TIME_ZONE_INFORMATION TimeZoneInformation)
_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 RtlQueryTimeZoneInformation(_Out_ PRTL_TIME_ZONE_INFORMATION TimeZoneInformation)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlFindMessage(_In_ PVOID BaseAddress, _In_ ULONG Type, _In_ ULONG Language, _In_ ULONG MessageId, _Out_ PMESSAGE_RESOURCE_ENTRY *MessageResourceEntry)
#define MESSAGE_RESOURCE_UNICODE
Definition: rtltypes.h:1926
#define TIME_ZONE_ID_UNKNOWN
Definition: rtltypes.h:252
#define TIME_ZONE_ID_STANDARD
Definition: rtltypes.h:253
#define TIME_ZONE_ID_DAYLIGHT
Definition: rtltypes.h:254
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:62
#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)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define DWORD
Definition: nt_native.h:44
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
#define LOCALE_NEUTRAL
#define LOCALE_NAME_MAX_LENGTH
#define SORT_CHINESE_PRCP
#define SORT_JAPANESE_UNICODE
#define LOCALE_CUSTOM_UNSPECIFIED
#define LOCALE_USER_DEFAULT
#define LOCALE_CUSTOM_DEFAULT
#define SORTIDFROMLCID(lcid)
#define SORT_CHINESE_UNICODE
#define SORT_JAPANESE_RADICALSTROKE
#define LOCALE_SYSTEM_DEFAULT
#define SORT_HUNGARIAN_TECHNICAL
#define SORT_CHINESE_PRC
#define SORT_DEFAULT
#define SORT_KOREAN_UNICODE
#define SORT_CHINESE_BOPOMOFO
#define SORT_JAPANESE_XJIS
#define MAKELCID(lgid, srtid)
#define SORT_INVARIANT_MATH
#define SORT_GERMAN_PHONE_BOOK
#define SORT_GEORGIAN_MODERN
#define SORT_CHINESE_RADICALSTROKE
#define LOCALE_CUSTOM_UI_DEFAULT
_NullNull_terminated_ CONST WCHAR * PCZZWSTR
Definition: ntbasedef.h:433
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 NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:569
#define STATUS_NO_UNICODE_TRANSLATION
Definition: ntstatus.h:1125
#define STATUS_SOME_NOT_MAPPED
Definition: ntstatus.h:86
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define round(x)
Definition: opentype.c:47
static HANDLE proc()
Definition: pdb.c:34
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
#define RT_MESSAGETABLE
Definition: pedump.c:373
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
static unsigned __int64 next
Definition: rand_nt.c:6
#define RtlUTF8ToUnicodeN
Definition: reactos.cpp:12
#define alloc
Definition: rosglue.h:13
int n2
Definition: dwarfget.c:147
int n1
Definition: dwarfget.c:147
const WCHAR * str
#define REG_DWORD
Definition: sdbapi.c:596
#define offsetof(TYPE, MEMBER)
int __cdecl system(_In_opt_z_ const char *_Command)
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP size_t __cdecl wcsspn(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define MAKELANGID(p, s)
Definition: nls.h:15
#define SUBLANGID(l)
Definition: nls.h:17
#define LANG_SPANISH
Definition: nls.h:123
#define LANG_GERMAN
Definition: nls.h:62
#define LANG_GEORGIAN
Definition: nls.h:61
#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_DEFAULT
Definition: nls.h:168
#define LANG_HUNGARIAN
Definition: nls.h:69
#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 LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define SUBLANG_SPANISH_MODERN
Definition: nls.h:338
#define LANG_INVARIANT
Definition: nls.h:23
#define LANG_KOREAN
Definition: nls.h:84
#define DECLSPEC_HOTPATCH
Definition: config.h:9
#define rol(value, bits)
Definition: sha1.c:24
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
VOID NTAPI RtlInitCodePageTable(IN PUSHORT TableBase, OUT PCPTABLEINFO CodePageTable)
Definition: nls.c:155
int is_local(const attr_list_t *a)
Definition: header.c:938
int zero
Definition: sehframes.cpp:29
PCWSTR s2
Definition: shell32_main.h:38
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
#define TRACE(s)
Definition: solgame.cpp:4
USHORT DBCSCodePage
Definition: precomp.h:38
PUSHORT MultiByteTable
Definition: precomp.h:40
USHORT CodePage
Definition: precomp.h:32
PUSHORT DBCSOffsets
Definition: precomp.h:43
LIST_ENTRY ProcessLocksList
Definition: winbase.h:918
Definition: rtltypes.h:1932
BYTE LeadByte[MAX_LEADBYTES]
Definition: winnls.h:603
BYTE DefaultChar[MAX_DEFAULTCHAR]
Definition: winnls.h:602
UINT MaxCharSize
Definition: winnls.h:601
WCHAR UnicodeDefaultChar
Definition: winnls.h:617
BYTE DefaultChar[MAX_DEFAULTCHAR]
Definition: winnls.h:615
WCHAR CodePageName[MAX_PATH]
Definition: winnls.h:619
UINT MaxCharSize
Definition: winnls.h:614
BYTE LeadByte[MAX_LEADBYTES]
Definition: winnls.h:616
UINT CodePage
Definition: winnls.h:618
DWORD dwNLSVersionInfoSize
Definition: winnls.h:647
DWORD dwNLSVersion
Definition: winnls.h:648
Definition: match.c:390
UINT sabbrevdayname
Definition: locale.c:223
UINT syearmonth
Definition: locale.c:218
USHORT icalintvalue
Definition: locale.c:215
UINT scalname
Definition: locale.c:226
UINT sdayname
Definition: locale.c:222
UINT srelativelongdate
Definition: locale.c:230
UINT smonthname
Definition: locale.c:224
UINT sshortdate
Definition: locale.c:217
UINT sabbreverastring
Definition: locale.c:228
UINT sshortestdayname
Definition: locale.c:229
UINT serastring
Definition: locale.c:220
UINT unused[3]
Definition: locale.c:231
UINT iyearoffsetrange
Definition: locale.c:221
UINT sabbrevmonthname
Definition: locale.c:225
UINT slongdate
Definition: locale.c:219
USHORT itwodigityearmax
Definition: locale.c:216
UINT smonthday
Definition: locale.c:227
Definition: inflate.c:139
Definition: bug.cpp:8
Definition: comerr.c:44
Definition: dsound.c:943
Definition: format.c:58
Definition: locale.c:235
GEOID id
Definition: locale.c:236
GEOID parent
Definition: locale.c:240
WCHAR currcode[4]
Definition: locale.c:245
WCHAR iso2[4]
Definition: locale.c:241
WCHAR currsymbol[8]
Definition: locale.c:246
WCHAR longitude[12]
Definition: locale.c:238
USHORT dialcode
Definition: locale.c:244
WCHAR iso3[4]
Definition: locale.c:242
USHORT uncode
Definition: locale.c:243
GEOCLASS class
Definition: locale.c:239
WCHAR latitude[12]
Definition: locale.c:237
UINT idx
Definition: locale.c:252
Definition: _hash_fun.h:40
BYTE pad[3]
Definition: locale.c:351
BYTE weight
Definition: locale.c:350
BYTE is_old
Definition: locale.c:346
BYTE leading
Definition: locale.c:347
BYTE vowel
Definition: locale.c:348
BYTE trailing
Definition: locale.c:349
Definition: copy.c:22
Definition: tftpd.h:60
DWORD system_attributes
Definition: locale.c:5742
BYTE checksum[16]
Definition: locale.c:5745
DWORD ln_type_id_off
Definition: locale.c:5752
BYTE service_checksum[16]
Definition: locale.c:5744
DWORD mui_path_size
Definition: locale.c:5748
DWORD ln_type_name_size
Definition: locale.c:5751
DWORD unk1[2]
Definition: locale.c:5746
DWORD lang_size
Definition: locale.c:5759
DWORD lang_off
Definition: locale.c:5758
DWORD path_type
Definition: locale.c:5740
DWORD ln_type_id_size
Definition: locale.c:5753
DWORD fallback_lang_off
Definition: locale.c:5760
DWORD version
Definition: locale.c:5739
DWORD unk2[2]
Definition: locale.c:5749
DWORD mui_type_id_off
Definition: locale.c:5756
DWORD ln_type_name_off
Definition: locale.c:5750
DWORD mui_path_off
Definition: locale.c:5747
DWORD size
Definition: locale.c:5738
DWORD mui_type_name_size
Definition: locale.c:5755
DWORD file_type
Definition: locale.c:5741
DWORD fallback_lang_size
Definition: locale.c:5761
DWORD mui_type_name_off
Definition: locale.c:5754
DWORD signature
Definition: locale.c:5737
DWORD fallback_location
Definition: locale.c:5743
DWORD mui_type_id_size
Definition: locale.c:5757
Definition: name.c:39
USHORT version[4]
Definition: locale.c:278
USHORT decomp_seq
Definition: locale.c:290
USHORT comp_size
Definition: locale.c:283
USHORT checksum[3]
Definition: locale.c:277
USHORT props_level1
Definition: locale.c:286
USHORT props_level2
Definition: locale.c:287
USHORT decomp_map
Definition: locale.c:289
USHORT decomp_size
Definition: locale.c:282
USHORT form
Definition: locale.c:279
USHORT classes
Definition: locale.c:285
USHORT unknown1
Definition: locale.c:281
USHORT comp_hash
Definition: locale.c:291
USHORT len_factor
Definition: locale.c:280
USHORT decomp_hash
Definition: locale.c:288
USHORT unknown2
Definition: locale.c:284
USHORT comp_seq
Definition: locale.c:292
Definition: _pair.h:47
Definition: locale.c:48
const WCHAR * subkey
Definition: locale.c:50
const WCHAR * value
Definition: locale.c:49
@ NOT_CACHED
Definition: locale.c:51
@ MISSING
Definition: locale.c:51
@ CACHED
Definition: locale.c:51
enum registry_entry::@515 status
WCHAR minchar
Definition: locale.c:357
WORD len[8]
Definition: locale.c:358
WCHAR maxchar
Definition: locale.c:357
WCHAR exp[2]
Definition: locale.c:341
UINT compr
Definition: locale.c:327
UINT ling_except
Definition: locale.c:329
UINT casemap
Definition: locale.c:330
UINT flags
Definition: locale.c:326
UINT except
Definition: locale.c:328
GUID id
Definition: locale.c:325
struct sortkey key_special
Definition: locale.c:3586
UINT primary_pos
Definition: locale.c:3588
struct sortkey key_case
Definition: locale.c:3585
struct sortkey key_diacritic
Definition: locale.c:3584
struct sortkey key_primary
Definition: locale.c:3583
struct sortkey key_extra[4]
Definition: locale.c:3587
UINT max
Definition: locale.c:3276
BYTE * new_buf
Definition: locale.c:3274
UINT size
Definition: locale.c:3275
UINT len
Definition: locale.c:3277
BYTE * buf
Definition: locale.c:3273
Definition: ps.c:97
Definition: fake.h:14
#define max(a, b)
Definition: svc.c:63
#define DWORD_PTR
Definition: treelist.c:76
uint16_t * PWSTR
Definition: typedefs.h:56
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
HANDLE HMODULE
Definition: typedefs.h:77
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
LONGLONG QuadPart
Definition: typedefs.h:114
BYTE script
Definition: locale.c:366
UINT val
Definition: locale.c:365
BYTE primary
Definition: locale.c:366
BYTE _case
Definition: locale.c:366
BYTE diacritic
Definition: locale.c:366
Definition: pdh_main.c:96
static int __cdecl compr(const void *a, const void *b)
Definition: bidi.c:641
#define va_copy(d, s)
Definition: vadefs.h:120
static const WCHAR lang[]
Definition: wbemdisp.c:287
static UINT WPARAM LPARAM BOOL ansi
Definition: misc.c:135
int codepage
Definition: win_iconv.c:156
#define LMEM_ZEROINIT
Definition: winbase.h:408
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:454
#define FORMAT_MESSAGE_MAX_WIDTH_MASK
Definition: winbase.h:458
#define LOAD_LIBRARY_AS_IMAGE_RESOURCE
Definition: winbase.h:380
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:375
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:453
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:456
#define TIME_ZONE_ID_INVALID
Definition: winbase.h:319
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:452
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:457
#define FORMAT_MESSAGE_FROM_HMODULE
Definition: winbase.h:455
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
#define WINAPI
Definition: msvc.h:6
#define HRESULT_FACILITY(hr)
Definition: winerror.h:79
#define HRESULT_SEVERITY(hr)
Definition: winerror.h:82
#define ERROR_BAD_EXE_FORMAT
Definition: winerror.h:251
#define ERROR_MUI_INVALID_RC_CONFIG
Definition: winerror.h:2256
#define SEVERITY_ERROR
Definition: winerror.h:65
#define ERROR_NO_UNICODE_TRANSLATION
Definition: winerror.h:649
#define FACILITY_WIN32
Definition: winerror.h:27
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define HRESULT_CODE(hr)
Definition: winerror.h:76
#define LOCALE_IREADINGLAYOUT
Definition: winnls.h:162
#define IS_SURROGATE_PAIR(high, low)
Definition: winnls.h:701
#define LGRPID_INSTALLED
Definition: winnls.h:478
#define LOCALE_USE_CP_ACP
Definition: winnls.h:20
#define LCMAP_LINGUISTIC_CASING
Definition: winnls.h:205
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:120
#define LOCALE_SMONTHNAME12
Definition: winnls.h:109
#define CP_THREAD_ACP
Definition: winnls.h:251
#define LOCALE_ICURRDIGITS
Definition: winnls.h:61
#define LOCALE_SPERCENT
Definition: winnls.h:167
#define CAL_SMONTHNAME9
Definition: winnls.h:443
#define LOCALE_INEGATIVEPERCENT
Definition: winnls.h:165
#define LOCALE_IDEFAULTCODEPAGE
Definition: winnls.h:44
#define LCID_ALTERNATE_SORTS
Definition: winnls.h:216
#define NORM_IGNORECASE
Definition: winnls.h:187
#define LOCALE_ALLOW_NEUTRAL_NAMES
Definition: winnls.h:25
#define LOCALE_SMONTHNAME5
Definition: winnls.h:102
#define CAL_SDAYNAME5
Definition: winnls.h:425
#define CP_OEMCP
Definition: winnls.h:249
#define CAL_SABBREVMONTHNAME8
Definition: winnls.h:455
#define LOCALE_SCOUNTRY
Definition: winnls.h:37
#define LOCALE_SDATE
Definition: winnls.h:65
#define LOCALE_SDAYNAME5
Definition: winnls.h:88
#define LOCALE_SNATIVEDISPLAYNAME
Definition: winnls.h:164
#define CAL_SABBREVMONTHNAME6
Definition: winnls.h:453
@ NormalizationKC
Definition: winnls.h:674
@ NormalizationKD
Definition: winnls.h:675
@ NormalizationD
Definition: winnls.h:673
@ NormalizationC
Definition: winnls.h:672
DWORD LGRPID
Definition: winnls.h:540
#define CAL_SABBREVMONTHNAME12
Definition: winnls.h:459
#define LOCALE_SOPENTYPELANGUAGETAG
Definition: winnls.h:171
#define LOCALE_SABBREVMONTHNAME9
Definition: winnls.h:119
BOOL(CALLBACK * LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM)
Definition: winnls.h:559
BOOL(CALLBACK * LANGGROUPLOCALE_ENUMPROCA)(LGRPID, LCID, LPSTR, LONG_PTR)
Definition: winnls.h:553
enum _NORM_FORM NORM_FORM
#define LOCALE_SPERMILLE
Definition: winnls.h:168
#define LOCALE_NEUTRALDATA
Definition: winnls.h:228
#define LOCALE_SABBREVMONTHNAME11
Definition: winnls.h:121
DWORD CALID
Definition: winnls.h:539
#define LOCALE_SABBREVDAYNAME5
Definition: winnls.h:95
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:92
#define LOCALE_INEGSEPBYSPACE
Definition: winnls.h:131
#define LOCALE_SABBREVMONTHNAME2
Definition: winnls.h:112
#define LOCALE_INEGSIGNPOSN
Definition: winnls.h:127
#define MAP_FOLDDIGITS
Definition: winnls.h:232
#define CAL_SMONTHNAME6
Definition: winnls.h:440
#define CAL_SCALNAME
Definition: winnls.h:416
#define CAL_HIJRI
Definition: winnls.h:466
BOOL(CALLBACK * CALINFO_ENUMPROCW)(LPWSTR)
Definition: winnls.h:548
#define C2_OTHERNEUTRAL
Definition: winnls.h:278
#define LOCALE_SMONTHNAME13
Definition: winnls.h:110
#define LCID_INSTALLED
Definition: winnls.h:214
#define CAL_SERASTRING
Definition: winnls.h:418
#define CAL_SABBREVMONTHNAME9
Definition: winnls.h:456
#define LOCALE_SGROUPING
Definition: winnls.h:51
#define CAL_SABBREVMONTHNAME10
Definition: winnls.h:457
#define LOCALE_SMONTHNAME3
Definition: winnls.h:100
#define CT_CTYPE2
Definition: winnls.h:256
#define SORT_STRINGSORT
Definition: winnls.h:195
#define C3_DIACRITIC
Definition: winnls.h:281
#define LOCALE_SSHORTTIME
Definition: winnls.h:170
#define LOCALE_ICOUNTRY
Definition: winnls.h:36
#define CAL_UMALQURA
Definition: winnls.h:474
#define LINGUISTIC_IGNORECASE
Definition: winnls.h:192
#define LCMAP_SIMPLIFIED_CHINESE
Definition: winnls.h:206
#define CP_SYMBOL
Definition: winnls.h:252
#define LOCALE_SDECIMAL
Definition: winnls.h:49
#define LOCALE_SMONTHNAME11
Definition: winnls.h:108
#define LOCALE_SMONTHNAME8
Definition: winnls.h:105
#define FIND_ENDSWITH
Definition: winnls.h:219
#define CAL_SABBREVMONTHNAME7
Definition: winnls.h:454
SYSGEOTYPE
Definition: winnls.h:581
@ GEO_ISO3
Definition: winnls.h:586
@ GEO_OFFICIALLANGUAGES
Definition: winnls.h:592
@ GEO_CURRENCYCODE
Definition: winnls.h:596
@ GEO_OFFICIALNAME
Definition: winnls.h:590
@ GEO_CURRENCYSYMBOL
Definition: winnls.h:597
@ GEO_TIMEZONES
Definition: winnls.h:591
@ GEO_FRIENDLYNAME
Definition: winnls.h:589
@ GEO_LONGITUDE
Definition: winnls.h:584
@ GEO_ISO_UN_NUMBER
Definition: winnls.h:593
@ GEO_DIALINGCODE
Definition: winnls.h:595
@ GEO_PARENT
Definition: winnls.h:594
@ GEO_ISO2
Definition: winnls.h:585
@ GEO_LATITUDE
Definition: winnls.h:583
@ GEO_NATION
Definition: winnls.h:582
@ GEO_LCID
Definition: winnls.h:588
@ GEO_RFC1766
Definition: winnls.h:587
#define LCMAP_TRADITIONAL_CHINESE
Definition: winnls.h:207
#define LGRPID_ARMENIAN
Definition: winnls.h:496
#define CT_CTYPE3
Definition: winnls.h:257
#define CT_CTYPE1
Definition: winnls.h:255
#define IS_HIGH_SURROGATE(ch)
Definition: winnls.h:699
#define LOCALE_IDATE
Definition: winnls.h:70
#define LOCALE_SMONTHNAME4
Definition: winnls.h:101
#define LOCALE_FONTSIGNATURE
Definition: winnls.h:132
BOOL(CALLBACK * TIMEFMT_ENUMPROCEX)(LPWSTR, LPARAM)
Definition: winnls.h:546
#define CAL_PERSIAN
Definition: winnls.h:473
#define LOCALE_SNATIVECTRYNAME
Definition: winnls.h:41
BOOL(CALLBACK * UILANGUAGE_ENUMPROCW)(LPWSTR, LONG_PTR)
Definition: winnls.h:555
#define LOCALE_SENGLANGUAGE
Definition: winnls.h:32
#define MAP_PRECOMPOSED
Definition: winnls.h:233
#define CAL_SABBREVDAYNAME7
Definition: winnls.h:434
#define LOCALE_SABBREVMONTHNAME13
Definition: winnls.h:123
#define CAL_SABBREVDAYNAME5
Definition: winnls.h:432
#define LOCALE_IFIRSTWEEKOFYEAR
Definition: winnls.h:83
#define LCMAP_HALFWIDTH
Definition: winnls.h:203
#define LOCALE_SDAYNAME1
Definition: winnls.h:84
#define LOCALE_IMEASURE
Definition: winnls.h:48
#define C3_NONSPACING
Definition: winnls.h:280
#define LOCALE_IPOSITIVEPERCENT
Definition: winnls.h:166
#define LCMAP_HIRAGANA
Definition: winnls.h:201
#define CAL_SABBREVMONTHNAME11
Definition: winnls.h:458
#define LOCALE_ILANGUAGE
Definition: winnls.h:30
#define CAL_SMONTHNAME4
Definition: winnls.h:438
#define C3_SYMBOL
Definition: winnls.h:283
#define LOCALE_SNAME
Definition: winnls.h:137
#define LCMAP_UPPERCASE
Definition: winnls.h:198
#define LOCALE_SLOCALIZEDDISPLAYNAME
Definition: winnls.h:26
BOOL(CALLBACK * DATEFMT_ENUMPROCW)(LPWSTR)
Definition: winnls.h:563
#define LOCALE_SNATIVELANGNAME
Definition: winnls.h:35
#define LOCALE_SLONGDATE
Definition: winnls.h:68
#define CAL_SABBREVMONTHNAME1
Definition: winnls.h:448
#define LOCALE_SMONTHNAME7
Definition: winnls.h:104
#define CAL_SMONTHNAME8
Definition: winnls.h:442
#define CAL_ICALINTVALUE
Definition: winnls.h:415
BOOL(CALLBACK * DATEFMT_ENUMPROCEXEX)(LPWSTR, CALID, LPARAM)
Definition: winnls.h:545
#define LOCALE_SSORTLOCALE
Definition: winnls.h:172
#define NORM_IGNOREKANATYPE
Definition: winnls.h:188
#define NORM_LINGUISTIC_CASING
Definition: winnls.h:194
#define LOCALE_ALTERNATE_SORTS
Definition: winnls.h:226
DWORD CALTYPE
Definition: winnls.h:538
#define LOCALE_IINTLCURRDIGITS
Definition: winnls.h:62
#define CAL_SDAYNAME3
Definition: winnls.h:423
#define LOCALE_S1159
Definition: winnls.h:78
#define CAL_SABBREVMONTHNAME3
Definition: winnls.h:450
#define LOCALE_SSHORTDATE
Definition: winnls.h:67
#define WC_SEPCHARS
Definition: winnls.h:237
#define CSTR_EQUAL
Definition: winnls.h:476
#define GEOID_NOT_AVAILABLE
Definition: winnls.h:13
BOOL(CALLBACK * GEO_ENUMPROC)(GEOID)
Definition: winnls.h:568
BOOL(CALLBACK * LANGGROUPLOCALE_ENUMPROCW)(LGRPID, LCID, LPWSTR, LONG_PTR)
Definition: winnls.h:554
#define NORM_IGNORENONSPACE
Definition: winnls.h:189
#define CAL_SMONTHNAME12
Definition: winnls.h:446
#define LOCALE_SRELATIVELONGDATE
Definition: winnls.h:174
BOOL(CALLBACK * CODEPAGE_ENUMPROCA)(LPSTR)
Definition: winnls.h:560
#define LOCALE_SPECIFICDATA
Definition: winnls.h:229
#define TIME_NOTIMEMARKER
Definition: winnls.h:297
#define TIME_NOMINUTESORSECONDS
Definition: winnls.h:295
#define LOCALE_IPOSSYMPRECEDES
Definition: winnls.h:128
#define LOCALE_IDAYLZERO
Definition: winnls.h:76
#define CP_UTF7
Definition: winnls.h:253
#define CAL_SDAYNAME4
Definition: winnls.h:424
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:114
#define CP_MACCP
Definition: winnls.h:250
#define C1_DEFINED
Definition: winnls.h:267
#define LOCALE_SPOSITIVESIGN
Definition: winnls.h:124
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCW)(LGRPID, LPWSTR, LPWSTR, DWORD, LONG_PTR)
Definition: winnls.h:552
#define NORM_IGNORESYMBOLS
Definition: winnls.h:190
#define LOCALE_INEUTRAL
Definition: winnls.h:163
#define FIND_FROMEND
Definition: winnls.h:221
#define LOCALE_IDEFAULTLANGUAGE
Definition: winnls.h:42
#define CAL_GREGORIAN
Definition: winnls.h:461
#define CAL_SABBREVMONTHNAME5
Definition: winnls.h:452
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:94
#define CAL_SDAYNAME1
Definition: winnls.h:421
#define LOCALE_SMONDECIMALSEP
Definition: winnls.h:58
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:133
#define LCMAP_SORTKEY
Definition: winnls.h:199
#define LOCALE_SLOCALIZEDLANGUAGENAME
Definition: winnls.h:28
#define LINGUISTIC_IGNOREDIACRITIC
Definition: winnls.h:193
#define MAP_COMPOSITE
Definition: winnls.h:234
#define LCMAP_LOWERCASE
Definition: winnls.h:197
#define LOCALE_ITIME
Definition: winnls.h:72
#define CAL_SMONTHNAME7
Definition: winnls.h:441
#define CAL_SSHORTDATE
Definition: winnls.h:419
#define MB_PRECOMPOSED
Definition: winnls.h:299
#define LOCALE_ICURRENCY
Definition: winnls.h:63
#define LOCALE_SMONTHNAME1
Definition: winnls.h:98
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:113
#define LOCALE_ITLZERO
Definition: winnls.h:75
#define CAL_SMONTHNAME11
Definition: winnls.h:445
#define FIND_STARTSWITH
Definition: winnls.h:218
#define LOCALE_INEGSYMPRECEDES
Definition: winnls.h:130
BOOL(CALLBACK * LOCALE_ENUMPROCA)(LPSTR)
Definition: winnls.h:557
#define CAL_SMONTHNAME2
Definition: winnls.h:436
#define LOCALE_SMONTHOUSANDSEP
Definition: winnls.h:59
#define LOCALE_SDAYNAME7
Definition: winnls.h:90
#define LOCALE_IPOSSIGNPOSN
Definition: winnls.h:126
#define LOCALE_SDAYNAME2
Definition: winnls.h:85
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:111
DWORD GEOCLASS
Definition: winnls.h:543
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
#define LOCALE_IOPTIONALCALENDAR
Definition: winnls.h:81
#define CAL_SDAYNAME7
Definition: winnls.h:427
#define LOCALE_IDIGITS
Definition: winnls.h:52
#define MAP_FOLDCZONE
Definition: winnls.h:231
#define CAL_SABBREVDAYNAME6
Definition: winnls.h:433
#define CAL_SLONGDATE
Definition: winnls.h:420
DWORD GEOTYPE
Definition: winnls.h:542
#define CAL_SABBREVDAYNAME4
Definition: winnls.h:431
#define LCID_SUPPORTED
Definition: winnls.h:215
#define LOCALE_STHOUSAND
Definition: winnls.h:50
#define CAL_SMONTHNAME10
Definition: winnls.h:444
#define FIND_FROMSTART
Definition: winnls.h:220
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:45
#define CAL_SDAYNAME6
Definition: winnls.h:426
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:134
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:96
#define LOCALE_SMONTHNAME2
Definition: winnls.h:99
#define LOCALE_STIMEFORMAT
Definition: winnls.h:69
#define IS_LOW_SURROGATE(ch)
Definition: winnls.h:700
BOOL(CALLBACK * LANGUAGEGROUP_ENUMPROCA)(LGRPID, LPSTR, LPSTR, DWORD, LONG_PTR)
Definition: winnls.h:551
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:91
#define LOCALE_SMONTHDAY
Definition: winnls.h:169
#define ENUM_ALL_CALENDARS
Definition: winnls.h:208
#define LOCALE_IFIRSTDAYOFWEEK
Definition: winnls.h:82
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:116
#define LOCALE_SMONTHNAME6
Definition: winnls.h:103
#define LOCALE_STIME
Definition: winnls.h:66
#define SORT_DIGITSASNUMBERS
Definition: winnls.h:196
#define NORM_IGNOREWIDTH
Definition: winnls.h:191
#define LOCALE_SABBREVLANGNAME
Definition: winnls.h:34
#define LOCALE_SENGCOUNTRY
Definition: winnls.h:38
BOOL(CALLBACK * DATEFMT_ENUMPROCEXW)(LPWSTR, CALID)
Definition: winnls.h:565
BOOL(CALLBACK * UILANGUAGE_ENUMPROCA)(LPSTR, LONG_PTR)
Definition: winnls.h:556
#define LOCALE_SABBREVCTRYNAME
Definition: winnls.h:40
#define LOCALE_INEGNUMBER
Definition: winnls.h:54
#define LOCALE_SNEGATIVESIGN
Definition: winnls.h:125
#define LOCALE_IDEFAULTCOUNTRY
Definition: winnls.h:43
#define LOCALE_WINDOWS
Definition: winnls.h:224
BOOL(CALLBACK * TIMEFMT_ENUMPROCW)(LPWSTR)
Definition: winnls.h:567
DWORD LCTYPE
Definition: winnls.h:537
#define LOCALE_SSHORTESTPM
Definition: winnls.h:176
#define TIME_FORCE24HOURFORMAT
Definition: winnls.h:298
#define LOCALE_SDAYNAME3
Definition: winnls.h:86
#define CSTR_LESS_THAN
Definition: winnls.h:475
#define LOCALE_S2359
Definition: winnls.h:79
#define LOCALE_SNATIVEDIGITS
Definition: winnls.h:55
#define LOCALE_SSHORTESTAM
Definition: winnls.h:175
#define LOCALE_SLIST
Definition: winnls.h:47
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:93
#define DATE_USE_ALT_CALENDAR
Definition: winnls.h:211
#define CAL_SMONTHNAME3
Definition: winnls.h:437
#define CAL_SMONTHNAME13
Definition: winnls.h:447
#define LOCALE_ILZERO
Definition: winnls.h:53
#define CAL_IYEAROFFSETRANGE
Definition: winnls.h:417
BOOL(CALLBACK * CALINFO_ENUMPROCEXEX)(LPWSTR, CALID, LPWSTR, LPARAM)
Definition: winnls.h:544
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:115
#define CAL_SABBREVMONTHNAME2
Definition: winnls.h:449
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:117
#define LOCALE_ICALENDARTYPE
Definition: winnls.h:80
#define LOCALE_SINTLSYMBOL
Definition: winnls.h:57
BOOL(CALLBACK * LOCALE_ENUMPROCW)(LPWSTR)
Definition: winnls.h:558
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:118
#define LCMAP_KATAKANA
Definition: winnls.h:202
#define CSTR_GREATER_THAN
Definition: winnls.h:477
#define LOCALE_SMONGROUPING
Definition: winnls.h:60
#define CAL_SABBREVDAYNAME2
Definition: winnls.h:429
#define LOCALE_SDAYNAME4
Definition: winnls.h:87
#define TIME_NOSECONDS
Definition: winnls.h:296
#define LOCALE_SCURRENCY
Definition: winnls.h:56
#define LOCALE_SMONTHNAME10
Definition: winnls.h:107
#define LOCALE_INEGCURR
Definition: winnls.h:64
#define LOCALE_ILDATE
Definition: winnls.h:71
#define LCMAP_FULLWIDTH
Definition: winnls.h:204
#define LCMAP_BYTEREV
Definition: winnls.h:200
#define LOCALE_SMONTHNAME9
Definition: winnls.h:106
BOOL(CALLBACK * CALINFO_ENUMPROCEXW)(LPWSTR, CALID)
Definition: winnls.h:550
BOOL(CALLBACK * CODEPAGE_ENUMPROCW)(LPWSTR)
Definition: winnls.h:561
#define CAL_SMONTHNAME1
Definition: winnls.h:435
#define DATE_LONGDATE
Definition: winnls.h:210
#define LOCALE_IPOSSEPBYSPACE
Definition: winnls.h:129
#define LOCALE_ICENTURY
Definition: winnls.h:74
#define CAL_SABBREVMONTHNAME13
Definition: winnls.h:460
#define CAL_SMONTHNAME5
Definition: winnls.h:439
#define LOCALE_IMONLZERO
Definition: winnls.h:77
@ GEOCLASS_REGION
Definition: winnls.h:576
@ GEOCLASS_NATION
Definition: winnls.h:575
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:122
#define LOCALE_IDEFAULTMACCODEPAGE
Definition: winnls.h:46
#define LGRPID_SUPPORTED
Definition: winnls.h:479
NLS_FUNCTION
Definition: winnls.h:570
@ COMPARE_STRING
Definition: winnls.h:571
#define LOCALE_SDAYNAME6
Definition: winnls.h:89
#define LOCALE_ITIMEMARKPOSN
Definition: winnls.h:73
#define CAL_SABBREVMONTHNAME4
Definition: winnls.h:451
#define CAL_SABBREVDAYNAME3
Definition: winnls.h:430
#define CAL_SABBREVDAYNAME1
Definition: winnls.h:428
#define LOCALE_RETURN_GENITIVE_NAMES
Definition: winnls.h:24
#define CAL_SDAYNAME2
Definition: winnls.h:422
#define DATE_SHORTDATE
Definition: winnls.h:209
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:97
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
NTSYSAPI NTSTATUS NTAPI RtlIsNormalizedString(_In_ ULONG NormForm, _In_ PCWSTR SourceString, _In_ LONG SourceStringLength, _Out_ PBOOLEAN Normalized)
NTSYSAPI NTSTATUS NTAPI RtlIdnToUnicode(IN ULONG Flags, IN PCWSTR SourceString, IN LONG SourceStringLength, OUT PWSTR DestinationString, IN OUT PLONG DestinationStringLength)
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3214
NTSYSAPI NTSTATUS NTAPI RtlIdnToAscii(_In_ ULONG Flags, _In_ PCWSTR SourceString, _In_ LONG SourceStringLength, _Out_writes_to_(*DestinationStringLength, *DestinationStringLength) PWSTR DestinationString, _Inout_ PLONG DestinationStringLength)
NTSYSAPI NTSTATUS NTAPI RtlIdnToNameprepUnicode(_In_ ULONG Flags, _In_ PCWSTR SourceString, _In_ LONG SourceStringLength, _Out_writes_to_(*DestinationStringLength, *DestinationStringLength) PWSTR DestinationString, _Inout_ PLONG DestinationStringLength)
static int repeat
Definition: xmllint.c:137
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
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193