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