ReactOS 0.4.16-dev-2104-gb84fa49
locale.c
Go to the documentation of this file.
1/*
2 * msvcrt.dll locale functions
3 *
4 * Copyright 2000 Jon Griffiths
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <limits.h>
22#include <locale.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <mbctype.h>
27#include <wctype.h>
28
29#include "windef.h"
30#include "winbase.h"
31#include "winuser.h"
32#include "winnls.h"
33
34#include "msvcrt.h"
35#include "mtdll.h"
36
37#include "wine/debug.h"
38
40
41#define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */
42#define MAX_LOCALE_LENGTH 256
44unsigned short *MSVCRT__pctype = NULL;
45unsigned int MSVCRT___lc_codepage = 0;
50
51#define MSVCRT_LEADBYTE 0x8000
52#define MSVCRT_C1_DEFINED 0x200
53
54#if _MSVCR_VER >= 110
55#define LCID_CONVERSION_FLAGS LOCALE_ALLOW_NEUTRAL_NAMES
56#else
57#define LCID_CONVERSION_FLAGS 0
58#endif
59
61{
62 {{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
63 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
64 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
65 "January", "February", "March", "April", "May", "June", "July",
66 "August", "September", "October", "November", "December",
67 "AM", "PM", "MM/dd/yy", "dddd, MMMM dd, yyyy", "HH:mm:ss"}},
68#if _MSVCR_VER < 110
70#endif
71 1, -1,
72#if _MSVCR_VER == 0 || _MSVCR_VER >= 100
73 {{L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat",
74 L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday", L"Friday", L"Saturday",
75 L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec",
76 L"January", L"February", L"March", L"April", L"May", L"June", L"July",
77 L"August", L"September", L"October", L"November", L"December",
78 L"AM", L"PM", L"MM/dd/yy", L"dddd, MMMM dd, yyyy", L"HH:mm:ss"}},
79#endif
80#if _MSVCR_VER >= 110
81 L"en-US",
82#endif
83};
84
85static const unsigned char cloc_clmap[256] =
86{
87 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
88 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
89 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
90 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
91 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
92 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
93 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
94 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
95 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
96 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
97 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
98 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
99 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
100 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
101 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
102 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
103 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
104 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
105 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
106 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
107 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
108 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
109 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
110 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
111 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
112 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
113 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
114 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
115 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
116 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
117 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
118 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
119};
120
121static const unsigned char cloc_cumap[256] =
122{
123 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
124 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
125 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
126 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
127 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
128 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
129 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
130 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
131 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
132 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
133 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
134 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
135 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
136 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
137 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
138 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
139 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
140 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
141 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
142 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
143 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
144 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
145 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
146 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
147 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
148 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
149 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
150 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
151 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
152 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
153 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
154 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
155};
156
157static char empty[] = "";
158static char cloc_dec_point[] = ".";
159#if _MSVCR_VER >= 100
160static wchar_t emptyW[] = L"";
161static wchar_t cloc_dec_pointW[] = L".";
162#endif
163static struct lconv cloc_lconv =
164{
167#if _MSVCR_VER >= 100
168 cloc_dec_pointW, emptyW, emptyW, emptyW, emptyW, emptyW, emptyW, emptyW
169#endif
170};
171
172/* Friendly country strings & language names abbreviations. */
173static const char * const _country_synonyms[] =
174{
175 "american", "en",
176 "american english", "en-US",
177 "american-english", "en-US",
178 "english-american", "en-US",
179 "english-us", "en-US",
180 "english-usa", "en-US",
181 "us", "en-US",
182 "usa", "en-US",
183 "australian", "en-AU",
184 "english-aus", "en-AU",
185 "belgian", "nl-BE",
186 "french-belgian", "fr-BE",
187 "canadian", "en-CA",
188 "english-can", "en-CA",
189 "french-canadian", "fr-CA",
190#if _MSVCR_VER >= 110
191 "chinese", "zh",
192 "chinese-simplified", "zh",
193 "chinese-traditional", "zh-HK",
194 "chs", "zh",
195 "cht", "zh-HK",
196#else
197 "chinese", "zh-CN",
198 "chinese-simplified", "zh-CN",
199 "chinese-traditional", "zh-TW",
200 "chs", "zh-CN",
201 "cht", "zh-TW",
202#endif
203 "dutch-belgian", "nl-BE",
204 "english-nz", "en-NZ",
205 "uk", "en-GB",
206 "english-uk", "en-GB",
207 "french-swiss", "fr-CH",
208 "swiss", "de-CH",
209 "german-swiss", "de-CH",
210 "italian-swiss", "it-CH",
211 "german-austrian", "de-AT",
212 "portuguese", "pt-BR",
213 "portuguese-brazil", "pt-BR",
214 "spanish-mexican", "es-MX",
215 "norwegian-bokmal", "nb",
216 "norwegian-nynorsk", "nn-NO",
217 "spanish-modern", "es-ES"
218};
219
220
221/* INTERNAL: Map a synonym to an ISO code */
223{
224 unsigned int i;
225 for (i = 0; i < ARRAY_SIZE(_country_synonyms); i += 2)
226 {
228 {
229 TRACE(":Mapping synonym %s to %s\n",name,_country_synonyms[i+1]);
231 return TRUE;
232 }
233 }
234
235 return FALSE;
236}
237
238/* Note: Flags are weighted in order of matching importance */
239#define FOUND_SNAME 0x4
240#define FOUND_LANGUAGE 0x2
241#define FOUND_COUNTRY 0x1
242
243typedef struct {
244 WCHAR search_language[MAX_ELEM_LEN];
245 WCHAR search_country[MAX_ELEM_LEN];
246 WCHAR found_lang_sname[LOCALE_NAME_MAX_LENGTH];
247 unsigned int match_flags;
250
251#define CONTINUE_LOOKING TRUE
252#define STOP_LOOKING FALSE
253
254/* INTERNAL: Get and compare locale info with a given string */
255static int compare_info(WCHAR *name, DWORD flags, WCHAR *buff, const WCHAR *cmp, BOOL exact)
256{
257 int len;
258
259 if(!cmp[0])
260 return 0;
261
262 buff[0] = 0;
264 if (!buff[0])
265 return 0;
266
267 /* Partial matches are only allowed on language/country names */
268 len = wcslen(cmp);
269
270 if(exact || len<=3)
271 return !_wcsicmp(cmp, buff);
272 else
273 return !_wcsnicmp(cmp, buff, len);
274}
275
276static BOOL CALLBACK
278{
281 unsigned int flags = 0;
282
283 if (res->allow_sname && compare_info(name,LOCALE_SNAME,buff,res->search_language, TRUE))
284 {
285 TRACE(":Found locale: %s->%s\n", wine_dbgstr_w(res->search_language), wine_dbgstr_w(buff));
286 res->match_flags = FOUND_SNAME;
287 wcscpy(res->found_lang_sname, name);
288 return STOP_LOOKING;
289 }
290
291 /* Check Language */
292 if (compare_info(name,LOCALE_SISO639LANGNAME,buff,res->search_language, TRUE) ||
295 {
296 TRACE(":Found language: %s->%s\n", wine_dbgstr_w(res->search_language), wine_dbgstr_w(buff));
298 }
299 else if (res->match_flags & FOUND_LANGUAGE)
300 {
301 return CONTINUE_LOOKING;
302 }
303
304 /* Check Country */
305 if (compare_info(name,LOCALE_SISO3166CTRYNAME,buff,res->search_country, TRUE) ||
308 {
309 TRACE("Found country:%s->%s\n", wine_dbgstr_w(res->search_country), wine_dbgstr_w(buff));
311 }
312 else if (!flags && (res->match_flags & FOUND_COUNTRY))
313 {
314 return CONTINUE_LOOKING;
315 }
316
317 if (flags > res->match_flags)
318 {
319 /* Found a better match than previously */
320 res->match_flags = flags;
321 wcscpy(res->found_lang_sname, name);
322 }
323 if ((flags & (FOUND_LANGUAGE | FOUND_COUNTRY)) ==
325 {
326 TRACE(":found exact locale match\n");
327 return STOP_LOOKING;
328 }
329 return CONTINUE_LOOKING;
330}
331
332/* Internal: Find the sname for a locale specification.
333 * sname must be at least LOCALE_NAME_MAX_LENGTH characters long
334 */
335BOOL locale_to_sname(const char *locale, unsigned short *codepage, BOOL *sname_match, WCHAR *sname)
336{
338 const char *cp, *region;
339 BOOL is_sname = FALSE;
340 DWORD locale_cp;
341
342 if (!strcmp(locale, data->cached_locale)) {
343 if (codepage)
344 *codepage = data->cached_cp;
345 if (sname_match)
346 *sname_match = data->cached_sname_match;
347 wcscpy(sname, data->cached_sname);
348 return TRUE;
349 }
350
351 cp = strchr(locale, '.');
352 region = strchr(locale, '_');
353
354 if(!locale[0] || (cp == locale && !region)) {
356 } else {
357 char search_language_buf[MAX_ELEM_LEN] = { 0 }, search_country_buf[MAX_ELEM_LEN] = { 0 };
359 BOOL remapped = FALSE;
360
361 memset(&search, 0, sizeof(locale_search_t));
362 lstrcpynA(search_language_buf, locale, MAX_ELEM_LEN);
363 if(region) {
364 lstrcpynA(search_country_buf, region+1, MAX_ELEM_LEN);
365 if(region-locale < MAX_ELEM_LEN)
366 search_language_buf[region-locale] = '\0';
367 } else
368 search_country_buf[0] = '\0';
369
370 if(cp) {
371 if(region && cp-region-1<MAX_ELEM_LEN)
372 search_country_buf[cp-region-1] = '\0';
374 search_language_buf[cp-locale] = '\0';
375 }
376
377 if ((remapped = remap_synonym(search_language_buf)))
378 {
379 search.allow_sname = TRUE;
380 }
381
382#if _MSVCR_VER >= 110
383 if(!cp && !region)
384 {
385 search.allow_sname = TRUE;
386 }
387#endif
388
389 MultiByteToWideChar(CP_ACP, 0, search_language_buf, -1, search.search_language, MAX_ELEM_LEN);
390 if (search.allow_sname && IsValidLocaleName(search.search_language))
391 {
392 search.match_flags = FOUND_SNAME;
393 wcscpy(sname, search.search_language);
394 }
395 else
396 {
397 MultiByteToWideChar(CP_ACP, 0, search_country_buf, -1, search.search_country, MAX_ELEM_LEN);
399
400 if (!search.match_flags)
401 return FALSE;
402
403 /* If we were given something that didn't match, fail */
404 if (search.search_language[0] && !(search.match_flags & (FOUND_SNAME | FOUND_LANGUAGE)))
405 return FALSE;
406 if (search.search_country[0] && !(search.match_flags & FOUND_COUNTRY))
407 return FALSE;
408
409 wcscpy(sname, search.found_lang_sname);
410 }
411
412 is_sname = !remapped && (search.match_flags & FOUND_SNAME) != 0;
413 }
414
415 /* Obtain code page */
416 if (!cp || !cp[1] || !_strnicmp(cp, ".ACP", 4)) {
417 GetLocaleInfoEx(sname, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
418 (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR));
419 if (!locale_cp)
420 locale_cp = GetACP();
421 } else if (!_strnicmp(cp, ".OCP", 4)) {
422 GetLocaleInfoEx(sname, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
423 (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR));
424#if _MSVCR_VER >= 140
425 } else if (!_strnicmp(cp, ".UTF-8", 6)
426 || !_strnicmp(cp, ".UTF8", 5)) {
427 locale_cp = CP_UTF8;
428#endif
429 } else {
430 locale_cp = atoi(cp + 1);
431 }
432 if (!IsValidCodePage(locale_cp))
433 return FALSE;
434
435 if (!locale_cp)
436 return FALSE;
437
438 if (codepage)
439 *codepage = locale_cp;
440 if (sname_match)
441 *sname_match = is_sname;
442
443 if (strlen(locale) < sizeof(data->cached_locale)) {
444 strcpy(data->cached_locale, locale);
445 data->cached_cp = locale_cp;
446 data->cached_sname_match = is_sname;
447 wcscpy(data->cached_sname, sname);
448 }
449
450 return TRUE;
451}
452
454 const threadlocinfo *old_locinfo, int category)
455{
456 locinfo->lc_handle[category] = old_locinfo->lc_handle[category];
457 locinfo->lc_id[category] = old_locinfo->lc_id[category];
458 if(!locinfo->lc_category[category].locale) {
459 locinfo->lc_category[category].locale = old_locinfo->lc_category[category].locale;
460 locinfo->lc_category[category].refcount = old_locinfo->lc_category[category].refcount;
461 InterlockedIncrement((LONG *)locinfo->lc_category[category].refcount);
462 }
463#if _MSVCR_VER >= 110
464 locinfo->lc_name[category] = old_locinfo->lc_name[category];
465 locinfo->lc_category[category].wrefcount = old_locinfo->lc_category[category].wrefcount;
466 if(locinfo->lc_category[category].wrefcount)
467 InterlockedIncrement((LONG *)locinfo->lc_category[category].wrefcount);
468#endif
469}
470
471static BOOL init_category_name(const char *name, int len,
473{
474 locinfo->lc_category[category].locale = malloc(len+1);
475 locinfo->lc_category[category].refcount = malloc(sizeof(int));
476 if(!locinfo->lc_category[category].locale
477 || !locinfo->lc_category[category].refcount) {
478 free(locinfo->lc_category[category].locale);
479 free(locinfo->lc_category[category].refcount);
480 locinfo->lc_category[category].locale = NULL;
481 locinfo->lc_category[category].refcount = NULL;
482 return FALSE;
483 }
484
485 memcpy(locinfo->lc_category[category].locale, name, len);
486 locinfo->lc_category[category].locale[len] = 0;
487 *locinfo->lc_category[category].refcount = 1;
488 return TRUE;
489}
490
491#if _MSVCR_VER >= 110
492static inline BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat, WCHAR *sname)
493{
494 locinfo->lc_category[cat].wrefcount = malloc(sizeof(int));
495 if(!locinfo->lc_category[cat].wrefcount)
496 return FALSE;
497 *locinfo->lc_category[cat].wrefcount = 1;
498
499 if(!(locinfo->lc_name[cat] = wcsdup(sname)))
500 return FALSE;
501
502 return TRUE;
503}
504#else
505static inline BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat, WCHAR *sname)
506{
507 return TRUE;
508}
509#endif
510
511/* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */
512static BOOL update_threadlocinfo_category(WCHAR *sname, unsigned short cp,
514{
515 WCHAR wbuf[256], *p;
516
518 p = wbuf;
519
520 locinfo->lc_id[category].wLanguage = 0;
521 while(*p) {
522 locinfo->lc_id[category].wLanguage *= 16;
523
524 if(*p <= '9')
525 locinfo->lc_id[category].wLanguage += *p-'0';
526 else
527 locinfo->lc_id[category].wLanguage += *p-'a'+10;
528
529 p++;
530 }
531
532 locinfo->lc_id[category].wCountry =
533 locinfo->lc_id[category].wLanguage;
534 }
535
536 locinfo->lc_id[category].wCodePage = cp;
537
539
541
542 if(!locinfo->lc_category[category].locale) {
543 char buf[256];
544 int len = 0;
545
546#if _MSVCR_VER < 110
548 {
549 /* locale.nls contains "Norwegian Nynorsk" instead for LOCALE_SENGLANGUAGE */
550 wcscpy( wbuf, L"Norwegian-Nynorsk" );
551 len = wcslen( wbuf ) + 1;
552 }
553 else
554#endif
556 wbuf[len-1] = '_';
558 |LOCALE_NOUSEROVERRIDE, &wbuf[len], ARRAY_SIZE(wbuf) - len);
559 wbuf[len-1] = '.';
560 swprintf(wbuf+len, ARRAY_SIZE(wbuf) - len,L"%d", cp);
561 len += wcslen(wbuf+len);
562
563 WideCharToMultiByte(cp, 0, wbuf, -1, buf, ARRAY_SIZE(buf), NULL, NULL);
564
566 }
567
568 return TRUE;
569}
570
571/*********************************************************************
572 * _lock_locales (UCRTBASE.@)
573 */
575{
577}
578
579/*********************************************************************
580 * _unlock_locales (UCRTBASE.@)
581 */
583{
585}
586
588{
589 int i;
590
591 InterlockedIncrement((LONG *)&locinfo->refcount);
592 for(i=LC_MIN+1; i<=LC_MAX; i++)
593 {
594 InterlockedIncrement((LONG *)locinfo->lc_category[i].refcount);
595 if(locinfo->lc_category[i].wrefcount)
596 InterlockedIncrement((LONG *)locinfo->lc_category[i].wrefcount);
597 }
598 if(locinfo->lconv_intl_refcount)
599 InterlockedIncrement((LONG *)locinfo->lconv_intl_refcount);
600 if(locinfo->lconv_num_refcount)
601 InterlockedIncrement((LONG *)locinfo->lconv_num_refcount);
602 if(locinfo->lconv_mon_refcount)
603 InterlockedIncrement((LONG *)locinfo->lconv_mon_refcount);
604 if(locinfo->ctype1_refcount)
605 InterlockedIncrement((LONG *)locinfo->ctype1_refcount);
606 InterlockedIncrement(&locinfo->lc_time_curr->refcount);
607}
608
610{
611 if((data->locale_flags & LOCALE_FREE) && ((data->locale_flags & LOCALE_THREAD) ||
612 (data->locinfo == MSVCRT_locale->locinfo && data->mbcinfo == MSVCRT_locale->mbcinfo)))
613 return;
614
615 if(data->locale_flags & LOCALE_FREE)
616 {
617 free_locinfo(data->locinfo);
618 free_mbcinfo(data->mbcinfo);
619 }
620
622 data->locinfo = MSVCRT_locale->locinfo;
623 grab_locinfo(data->locinfo);
625
627 data->mbcinfo = MSVCRT_locale->mbcinfo;
628 InterlockedIncrement(&data->mbcinfo->refcount);
630
631 data->locale_flags |= LOCALE_FREE;
632}
633
634/* INTERNAL: returns threadlocinfo struct */
638 return data->locinfo;
639}
640
641/* INTERNAL: returns pthreadmbcinfo struct */
645 return data->mbcinfo;
646}
647
648/* INTERNAL: constructs string returned by setlocale */
650 static char current_lc_all[MAX_LOCALE_LENGTH];
651
652 int i;
653
654 for(i=LC_MIN+1; i<LC_MAX; i++) {
655 if(strcmp(locinfo->lc_category[i].locale,
656 locinfo->lc_category[i+1].locale))
657 break;
658 }
659
660 if(i==LC_MAX)
661 return locinfo->lc_category[LC_COLLATE].locale;
662
663 sprintf(current_lc_all,
664 "LC_COLLATE=%s;LC_CTYPE=%s;LC_MONETARY=%s;LC_NUMERIC=%s;LC_TIME=%s",
665 locinfo->lc_category[LC_COLLATE].locale,
666 locinfo->lc_category[LC_CTYPE].locale,
667 locinfo->lc_category[LC_MONETARY].locale,
668 locinfo->lc_category[LC_NUMERIC].locale,
669 locinfo->lc_category[LC_TIME].locale);
670
671 return current_lc_all;
672}
673
674
675/*********************************************************************
676 * _Getdays (MSVCRT.@)
677 */
678char* CDECL _Getdays(void)
679{
681 int i, len, size = 0;
682 char *out;
683
684 TRACE("\n");
685
686 for(i=0; i<7; i++) {
687 size += strlen(cur->str.names.short_wday[i]) + 1;
688 size += strlen(cur->str.names.wday[i]) + 1;
689 }
690 out = malloc(size+1);
691 if(!out)
692 return NULL;
693
694 size = 0;
695 for(i=0; i<7; i++) {
696 out[size++] = ':';
697 len = strlen(cur->str.names.short_wday[i]);
698 memcpy(&out[size], cur->str.names.short_wday[i], len);
699 size += len;
700
701 out[size++] = ':';
702 len = strlen(cur->str.names.wday[i]);
703 memcpy(&out[size], cur->str.names.wday[i], len);
704 size += len;
705 }
706 out[size] = '\0';
707
708 return out;
709}
710
711#if _MSVCR_VER >= 110
712/*********************************************************************
713 * _W_Getdays (MSVCR110.@)
714 */
715wchar_t* CDECL _W_Getdays(void)
716{
718 wchar_t *out;
719 int i, len, size = 0;
720
721 TRACE("\n");
722
723 for(i=0; i<7; i++) {
724 size += wcslen(cur->wstr.names.short_wday[i]) + 1;
725 size += wcslen(cur->wstr.names.wday[i]) + 1;
726 }
727 out = malloc((size+1)*sizeof(*out));
728 if(!out)
729 return NULL;
730
731 size = 0;
732 for(i=0; i<7; i++) {
733 out[size++] = ':';
734 len = wcslen(cur->wstr.names.short_wday[i]);
735 memcpy(&out[size], cur->wstr.names.short_wday[i], len*sizeof(*out));
736 size += len;
737
738 out[size++] = ':';
739 len = wcslen(cur->wstr.names.wday[i]);
740 memcpy(&out[size], cur->wstr.names.wday[i], len*sizeof(*out));
741 size += len;
742 }
743 out[size] = '\0';
744
745 return out;
746}
747#endif
748
749/*********************************************************************
750 * _Getmonths (MSVCRT.@)
751 */
752char* CDECL _Getmonths(void)
753{
755 int i, len, size = 0;
756 char *out;
757
758 TRACE("\n");
759
760 for(i=0; i<12; i++) {
761 size += strlen(cur->str.names.short_mon[i]) + 1;
762 size += strlen(cur->str.names.mon[i]) + 1;
763 }
764 out = malloc(size+1);
765 if(!out)
766 return NULL;
767
768 size = 0;
769 for(i=0; i<12; i++) {
770 out[size++] = ':';
771 len = strlen(cur->str.names.short_mon[i]);
772 memcpy(&out[size], cur->str.names.short_mon[i], len);
773 size += len;
774
775 out[size++] = ':';
776 len = strlen(cur->str.names.mon[i]);
777 memcpy(&out[size], cur->str.names.mon[i], len);
778 size += len;
779 }
780 out[size] = '\0';
781
782 return out;
783}
784
785#if _MSVCR_VER >= 110
786/*********************************************************************
787 * _W_Getmonths (MSVCR110.@)
788 */
789wchar_t* CDECL _W_Getmonths(void)
790{
792 wchar_t *out;
793 int i, len, size = 0;
794
795 TRACE("\n");
796
797 for(i=0; i<12; i++) {
798 size += wcslen(cur->wstr.names.short_mon[i]) + 1;
799 size += wcslen(cur->wstr.names.mon[i]) + 1;
800 }
801 out = malloc((size+1)*sizeof(*out));
802 if(!out)
803 return NULL;
804
805 size = 0;
806 for(i=0; i<12; i++) {
807 out[size++] = ':';
808 len = wcslen(cur->wstr.names.short_mon[i]);
809 memcpy(&out[size], cur->wstr.names.short_mon[i], len*sizeof(*out));
810 size += len;
811
812 out[size++] = ':';
813 len = wcslen(cur->wstr.names.mon[i]);
814 memcpy(&out[size], cur->wstr.names.mon[i], len*sizeof(*out));
815 size += len;
816 }
817 out[size] = '\0';
818
819 return out;
820}
821#endif
822
823/*********************************************************************
824 * _Gettnames (MSVCRT.@)
825 */
826void* CDECL _Gettnames(void)
827{
829 unsigned int i, len, size = sizeof(__lc_time_data);
830
831 TRACE("\n");
832
833 for(i=0; i<ARRAY_SIZE(cur->str.str); i++)
834 size += strlen(cur->str.str[i])+1;
835#if _MSVCR_VER >= 110
836 for(i=0; i<ARRAY_SIZE(cur->wstr.wstr); i++)
837 size += (wcslen(cur->wstr.wstr[i]) + 1) * sizeof(wchar_t);
838#endif
839
840 ret = malloc(size);
841 if(!ret)
842 return NULL;
843 memcpy(ret, cur, sizeof(*ret));
844
845 size = 0;
846 for(i=0; i<ARRAY_SIZE(cur->str.str); i++) {
847 len = strlen(cur->str.str[i])+1;
848 memcpy(&ret->data[size], cur->str.str[i], len);
849 ret->str.str[i] = &ret->data[size];
850 size += len;
851 }
852#if _MSVCR_VER >= 110
853 for(i=0; i<ARRAY_SIZE(cur->wstr.wstr); i++) {
854 len = (wcslen(cur->wstr.wstr[i]) + 1) * sizeof(wchar_t);
855 memcpy(&ret->data[size], cur->wstr.wstr[i], len);
856 ret->wstr.wstr[i] = (wchar_t*)&ret->data[size];
857 size += len;
858 }
859#endif
860
861 return ret;
862}
863
864#if _MSVCR_VER >= 110
865/*********************************************************************
866 * _W_Gettnames (MSVCR110.@)
867 */
868void* CDECL _W_Gettnames(void)
869{
870 return _Gettnames();
871}
872#endif
873
874/*********************************************************************
875 * __crtLCMapStringA (MSVCRT.@)
876 */
878 LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst,
879 int dstlen, unsigned int codepage, int xflag
880) {
881 WCHAR buf_in[32], *in = buf_in;
882 WCHAR buf_out[32], *out = buf_out;
883 int in_len, out_len, r;
884
885 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
886 lcid, mapflags, src, srclen, dst, dstlen, codepage, xflag);
887
889 if (!in_len) return 0;
890 if (in_len > ARRAY_SIZE(buf_in))
891 {
892 in = malloc(in_len * sizeof(WCHAR));
893 if (!in) return 0;
894 }
895
897 if (!r) goto done;
898
899 if (mapflags & LCMAP_SORTKEY)
900 {
901 r = LCMapStringW(lcid, mapflags, in, in_len, (WCHAR*)dst, dstlen);
902 goto done;
903 }
904
905 r = LCMapStringW(lcid, mapflags, in, in_len, NULL, 0);
906 if (!r) goto done;
907 out_len = r;
908 if (r > ARRAY_SIZE(buf_out))
909 {
910 out = malloc(r * sizeof(WCHAR));
911 if (!out)
912 {
913 r = 0;
914 goto done;
915 }
916 }
917
918 r = LCMapStringW(lcid, mapflags, in, in_len, out, out_len);
919 if (!r) goto done;
920
921 r = WideCharToMultiByte(codepage, 0, out, out_len, dst, dstlen, NULL, NULL);
922
923done:
924 if (in != buf_in) free(in);
925 if (out != buf_out) free(out);
926 return r;
927}
928
929/*********************************************************************
930 * __crtLCMapStringW (MSVCRT.@)
931 */
932int CDECL __crtLCMapStringW(LCID lcid, DWORD mapflags, const wchar_t *src,
933 int srclen, wchar_t *dst, int dstlen, unsigned int codepage, int xflag)
934{
935 FIXME("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
936 lcid, mapflags, debugstr_w(src), srclen, dst, dstlen, codepage, xflag);
937
938 return LCMapStringW(lcid, mapflags, src, srclen, dst, dstlen);
939}
940
941/*********************************************************************
942 * __crtCompareStringA (MSVCRT.@)
943 */
944int CDECL __crtCompareStringA( LCID lcid, DWORD flags, const char *src1, int len1,
945 const char *src2, int len2 )
946{
947 FIXME("(lcid %lx, flags %lx, %s(%d), %s(%d), partial stub\n",
948 lcid, flags, debugstr_a(src1), len1, debugstr_a(src2), len2 );
949 /* FIXME: probably not entirely right */
950 return CompareStringA( lcid, flags, src1, len1, src2, len2 );
951}
952
953/*********************************************************************
954 * __crtCompareStringW (MSVCRT.@)
955 */
956int CDECL __crtCompareStringW( LCID lcid, DWORD flags, const wchar_t *src1, int len1,
957 const wchar_t *src2, int len2 )
958{
959 FIXME("(lcid %lx, flags %lx, %s(%d), %s(%d), partial stub\n",
960 lcid, flags, debugstr_w(src1), len1, debugstr_w(src2), len2 );
961 /* FIXME: probably not entirely right */
962 return CompareStringW( lcid, flags, src1, len1, src2, len2 );
963}
964
965/*********************************************************************
966 * __crtGetLocaleInfoW (MSVCRT.@)
967 */
969{
970 FIXME("(lcid %lx, type %lx, %p(%d), partial stub\n", lcid, type, buffer, len );
971 /* FIXME: probably not entirely right */
972 return GetLocaleInfoW( lcid, type, buffer, len );
973}
974
975#if _MSVCR_VER >= 110
976/*********************************************************************
977 * __crtGetLocaleInfoEx (MSVC110.@)
978 */
979int CDECL __crtGetLocaleInfoEx( const WCHAR *locale, LCTYPE type, wchar_t *buffer, int len )
980{
981 TRACE("(%s, %lx, %p, %d)\n", debugstr_w(locale), type, buffer, len);
983}
984#endif
985
986/*********************************************************************
987 * __crtGetStringTypeW(MSVCRT.@)
988 *
989 * This function was accepting different number of arguments in older
990 * versions of msvcrt.
991 */
993 wchar_t *buffer, int len, WORD *out)
994{
995 FIXME("(unk %lx, type %lx, wstr %p(%d), %p) partial stub\n",
996 unk, type, buffer, len, out);
997
998 return GetStringTypeW(type, buffer, len, out);
999}
1000
1001/*********************************************************************
1002 * localeconv (MSVCRT.@)
1003 */
1005{
1006 return get_locinfo()->lconv;
1007}
1008
1009/*********************************************************************
1010 * __lconv_init (MSVCRT.@)
1011 */
1013{
1014 /* this is used to make chars unsigned */
1015 cloc_lconv.int_frac_digits = (char)UCHAR_MAX;
1016 cloc_lconv.frac_digits = (char)UCHAR_MAX;
1017 cloc_lconv.p_cs_precedes = (char)UCHAR_MAX;
1018 cloc_lconv.p_sep_by_space = (char)UCHAR_MAX;
1019 cloc_lconv.n_cs_precedes = (char)UCHAR_MAX;
1020 cloc_lconv.n_sep_by_space = (char)UCHAR_MAX;
1021 cloc_lconv.p_sign_posn = (char)UCHAR_MAX;
1022 cloc_lconv.n_sign_posn = (char)UCHAR_MAX;
1023 return 0;
1024}
1025
1026/*********************************************************************
1027 * ___lc_handle_func (MSVCRT.@)
1028 */
1030{
1031 return (LCID *)get_locinfo()->lc_handle;
1032}
1033
1034#if _MSVCR_VER >= 110
1035/*********************************************************************
1036 * ___lc_locale_name_func (MSVCR110.@)
1037 */
1038wchar_t** CDECL ___lc_locale_name_func(void)
1039{
1040 return get_locinfo()->lc_name;
1041}
1042#endif
1043
1044/*********************************************************************
1045 * ___lc_codepage_func (MSVCRT.@)
1046 */
1047unsigned int CDECL ___lc_codepage_func(void)
1048{
1049 return get_locinfo()->lc_codepage;
1050}
1051
1052/*********************************************************************
1053 * ___lc_collate_cp_func (MSVCRT.@)
1054 */
1056{
1057 return get_locinfo()->lc_collate_cp;
1058}
1059
1060/* INTERNAL: frees pthreadlocinfo struct */
1062{
1063 int i;
1064
1065 if(!locinfo)
1066 return;
1067
1068 for(i=LC_MIN+1; i<=LC_MAX; i++) {
1069 if(!locinfo->lc_category[i].refcount
1070 || !InterlockedDecrement((LONG *)locinfo->lc_category[i].refcount)) {
1071 free(locinfo->lc_category[i].locale);
1072 free(locinfo->lc_category[i].refcount);
1073 }
1074 if(!locinfo->lc_category[i].wrefcount
1075 || !InterlockedDecrement((LONG *)locinfo->lc_category[i].wrefcount)) {
1076#if _MSVCR_VER >= 110
1077 free(locinfo->lc_name[i]);
1078#endif
1079 free(locinfo->lc_category[i].wrefcount);
1080 }
1081 }
1082
1083 if(locinfo->lconv_num_refcount
1084 && !InterlockedDecrement((LONG *)locinfo->lconv_num_refcount)) {
1085 free(locinfo->lconv->decimal_point);
1086 free(locinfo->lconv->thousands_sep);
1087 free(locinfo->lconv->grouping);
1088#if _MSVCR_VER >= 100
1089 free(locinfo->lconv->_W_decimal_point);
1090 free(locinfo->lconv->_W_thousands_sep);
1091#endif
1092 free(locinfo->lconv_num_refcount);
1093 }
1094 if(locinfo->lconv_mon_refcount
1095 && !InterlockedDecrement((LONG *)locinfo->lconv_mon_refcount)) {
1096 free(locinfo->lconv->int_curr_symbol);
1097 free(locinfo->lconv->currency_symbol);
1098 free(locinfo->lconv->mon_decimal_point);
1099 free(locinfo->lconv->mon_thousands_sep);
1100 free(locinfo->lconv->mon_grouping);
1101 free(locinfo->lconv->positive_sign);
1102 free(locinfo->lconv->negative_sign);
1103#if _MSVCR_VER >= 100
1104 free(locinfo->lconv->_W_int_curr_symbol);
1105 free(locinfo->lconv->_W_currency_symbol);
1106 free(locinfo->lconv->_W_mon_decimal_point);
1107 free(locinfo->lconv->_W_mon_thousands_sep);
1108 free(locinfo->lconv->_W_positive_sign);
1109 free(locinfo->lconv->_W_negative_sign);
1110#endif
1111 free(locinfo->lconv_mon_refcount);
1112 }
1113 if(locinfo->lconv_intl_refcount
1114 && !InterlockedDecrement((LONG *)locinfo->lconv_intl_refcount)) {
1115 free(locinfo->lconv_intl_refcount);
1116 free(locinfo->lconv);
1117 }
1118
1119 if(locinfo->ctype1_refcount
1120 && !InterlockedDecrement((LONG *)locinfo->ctype1_refcount)) {
1121 free(locinfo->ctype1_refcount);
1122 free(locinfo->ctype1);
1123 free((void*)locinfo->pclmap);
1124 free((void*)locinfo->pcumap);
1125 }
1126
1127 if(locinfo->lc_time_curr && !InterlockedDecrement(&locinfo->lc_time_curr->refcount)
1128 && locinfo->lc_time_curr != &cloc_time_data)
1129 free(locinfo->lc_time_curr);
1130
1131 if(InterlockedDecrement((LONG *)&locinfo->refcount))
1132 return;
1133
1134 free(locinfo);
1135}
1136
1137/* INTERNAL: frees pthreadmbcinfo struct */
1139{
1140 if(!mbcinfo)
1141 return;
1142
1143 if(InterlockedDecrement(&mbcinfo->refcount))
1144 return;
1145
1146 free(mbcinfo);
1147}
1148
1150{
1152
1154 locale->locinfo = data->locinfo;
1155 locale->mbcinfo = data->mbcinfo;
1156
1157 grab_locinfo(locale->locinfo);
1158 InterlockedIncrement(&locale->mbcinfo->refcount);
1159 return locale;
1160}
1161
1163{
1164 free_locinfo(locale->locinfo);
1165 free_mbcinfo(locale->mbcinfo);
1166}
1167
1168/*********************************************************************
1169 * _get_current_locale (MSVCRT.@)
1170 */
1172{
1173 _locale_t loc = malloc(sizeof(_locale_tstruct));
1174 if(!loc)
1175 return NULL;
1176
1177 return get_current_locale_noalloc(loc);
1178}
1179
1180/*********************************************************************
1181 * _free_locale (MSVCRT.@)
1182 */
1184{
1185 if (!locale)
1186 return;
1187
1189 free(locale);
1190}
1191
1192static inline BOOL category_needs_update(int cat,
1193 const threadlocinfo *locinfo, WCHAR *sname, unsigned short cp)
1194{
1195#if _MSVCR_VER < 110
1196 LCID lcid;
1197#endif
1198 if(!locinfo) return TRUE;
1199#if _MSVCR_VER >= 110
1200 if(!locinfo->lc_name[cat] || !sname) return TRUE;
1201 return wcscmp(sname, locinfo->lc_name[cat]) != 0 || cp!=locinfo->lc_id[cat].wCodePage;
1202#else
1203 lcid = sname ? LocaleNameToLCID(sname, 0) : 0;
1204 return lcid!=locinfo->lc_handle[cat] || cp!=locinfo->lc_id[cat].wCodePage;
1205#endif
1206}
1207
1209{
1210 static const DWORD time_data[] = {
1226 };
1227
1229 int i, ret, size;
1231
1232 size = 0;
1233 for(i=0; i<ARRAY_SIZE(time_data); i++) {
1234 ret = GetLocaleInfoA(lcid, time_data[i], NULL, 0);
1235 if(!ret)
1236 return NULL;
1237 size += ret;
1238
1239#if _MSVCR_VER == 0 || _MSVCR_VER >= 100
1240 ret = GetLocaleInfoEx(sname, time_data[i], NULL, 0);
1241 if(!ret)
1242 return NULL;
1243 size += ret*sizeof(wchar_t);
1244#endif
1245 }
1246#if _MSVCR_VER >= 110
1247 size += (wcslen(sname) + 1) * sizeof(wchar_t);
1248#endif
1249
1251 if(!cur)
1252 return NULL;
1253
1254 ret = 0;
1255 for(i=0; i<ARRAY_SIZE(time_data); i++) {
1256 cur->str.str[i] = &cur->data[ret];
1257 ret += GetLocaleInfoA(lcid, time_data[i], &cur->data[ret], size-ret);
1258 }
1259#if _MSVCR_VER == 0 || _MSVCR_VER >= 100
1260 for(i=0; i<ARRAY_SIZE(time_data); i++) {
1261 cur->wstr.wstr[i] = (wchar_t*)&cur->data[ret];
1262 ret += GetLocaleInfoEx(sname, time_data[i], (wchar_t*)&cur->data[ret],
1263 (size - ret) / sizeof(wchar_t)) * sizeof(wchar_t);
1264 }
1265#endif
1266#if _MSVCR_VER >= 110
1267 cur->locname = (wchar_t*)&cur->data[ret];
1268 wcscpy((wchar_t*)&cur->data[ret], sname);
1269#else
1270 cur->lcid = lcid;
1271#endif
1272 cur->unk = 1;
1273 cur->refcount = 1;
1274
1275 return cur;
1276}
1277
1279 const char *locale, const threadlocinfo *old_locinfo)
1280{
1281 static const char collate[] = "COLLATE=";
1282 static const char ctype[] = "CTYPE=";
1283 static const char monetary[] = "MONETARY=";
1284 static const char numeric[] = "NUMERIC=";
1285 static const char time[] = "TIME=";
1286
1288 unsigned short cp[6] = { 0 };
1289 const char *locale_name[6] = { 0 };
1290 WCHAR *locale_sname[6] = { 0 };
1291 int val, locale_len[6] = { 0 };
1292 char buf[256];
1293 BOOL sname_match;
1294 wchar_t wbuf[256], map_buf[256];
1295 int i;
1296
1297 TRACE("(%d %s)\n", category, locale);
1298
1300 return NULL;
1301
1302 if(locale[0]=='C' && !locale[1]) {
1303 locale_sname[0] = NULL;
1304 cp[0] = CP_ACP;
1305 } else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') {
1306 const char *p;
1307
1308 while(1) {
1309 locale += 3; /* LC_ */
1310 if(!memcmp(locale, collate, sizeof(collate)-1)) {
1311 i = LC_COLLATE;
1312 locale += sizeof(collate)-1;
1313 } else if(!memcmp(locale, ctype, sizeof(ctype)-1)) {
1314 i = LC_CTYPE;
1315 locale += sizeof(ctype)-1;
1316 } else if(!memcmp(locale, monetary, sizeof(monetary)-1)) {
1317 i = LC_MONETARY;
1318 locale += sizeof(monetary)-1;
1319 } else if(!memcmp(locale, numeric, sizeof(numeric)-1)) {
1320 i = LC_NUMERIC;
1321 locale += sizeof(numeric)-1;
1322 } else if(!memcmp(locale, time, sizeof(time)-1)) {
1323 i = LC_TIME;
1324 locale += sizeof(time)-1;
1325 } else
1326 goto fail;
1327
1328 p = strchr(locale, ';');
1329 if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0')) {
1330 locale_sname[i] = NULL;
1331 cp[i] = CP_ACP;
1332 } else {
1333 BOOL locale_found = FALSE;
1334
1335 if(p) {
1337 buf[p-locale] = '\0';
1338 locale_found = locale_to_sname(buf, &cp[i], &sname_match, wbuf);
1339 } else {
1340 locale_found = locale_to_sname(locale, &cp[i], &sname_match, wbuf);
1341 }
1342
1343 if(!locale_found || !(locale_sname[i] = wcsdup(wbuf)))
1344 goto fail;
1345 if(sname_match) {
1346 locale_name[i] = locale;
1347 locale_len[i] = p ? p-locale : strlen(locale);
1348 }
1349 }
1350
1351 if(!p || *(p+1)!='L' || *(p+2)!='C' || *(p+3)!='_')
1352 break;
1353
1354 locale = p+1;
1355 }
1356 } else {
1357 BOOL locale_found = locale_to_sname(locale, &cp[0], &sname_match, wbuf);
1358
1359 if(!locale_found)
1360 return NULL;
1361
1362 locale_sname[0] = wcsdup(wbuf);
1363 if(!locale_sname[0])
1364 return NULL;
1365
1366 if(sname_match) {
1367 locale_name[0] = locale;
1368 locale_len[0] = strlen(locale);
1369 }
1370
1371 for(i=1; i<6; i++) {
1372 locale_sname[i] = wcsdup(locale_sname[0]);
1373 if(!locale_sname[i])
1374 goto fail;
1375
1376 cp[i] = cp[0];
1378 locale_len[i] = locale_len[0];
1379 }
1380 }
1381
1382 for(i=1; i<6; i++) {
1383#if _MSVCR_VER < 140
1384 if(i==LC_CTYPE && cp[i]==CP_UTF8) {
1385#if _MSVCR_VER >= 110
1386 if(old_locinfo) {
1387 locale_sname[i] = wcsdup(old_locinfo->lc_name[i]);
1388 if (old_locinfo->lc_name[i] && !locale_sname[i])
1389 goto fail;
1390 }
1391#else
1392 int sname_size;
1393 if(old_locinfo && old_locinfo->lc_handle[i]) {
1394 sname_size = LCIDToLocaleName(old_locinfo->lc_handle[i], NULL, 0, 0);
1395 locale_sname[i] = malloc(sname_size * sizeof(WCHAR));
1396 if(!locale_sname[i])
1397 goto fail;
1398 LCIDToLocaleName(old_locinfo->lc_handle[i], locale_sname[i], sname_size, 0);
1399 } else {
1400 locale_sname[i] = NULL;
1401 }
1402#endif
1403
1404 locale_name[i] = NULL;
1405 locale_len[i] = 0;
1406 cp[i] = old_locinfo ? old_locinfo->lc_id[i].wCodePage : 0;
1407 }
1408#endif
1409 if(category!=LC_ALL && category!=i) {
1410 if(old_locinfo) {
1411#if _MSVCR_VER >= 110
1412 locale_sname[i] = wcsdup(old_locinfo->lc_name[i]);
1413 if(old_locinfo->lc_name[i] && !locale_sname[i])
1414 goto fail;
1415#else
1416 int sname_size;
1417 if(old_locinfo->lc_handle[i]) {
1418 sname_size = LCIDToLocaleName(old_locinfo->lc_handle[i], NULL, 0, 0);
1419 locale_sname[i] = malloc(sname_size * sizeof(WCHAR));
1420 if(!locale_sname[i])
1421 goto fail;
1422 LCIDToLocaleName(old_locinfo->lc_handle[i], locale_sname[i], sname_size, 0);
1423 } else {
1424 locale_sname[i] = NULL;
1425 }
1426#endif
1427 cp[i] = old_locinfo->lc_id[i].wCodePage;
1428 } else {
1429 locale_sname[i] = NULL;
1430 cp[i] = 0;
1431 }
1432 }
1433 }
1434
1435 locinfo = malloc(sizeof(threadlocinfo));
1436 if(!locinfo)
1437 goto fail;
1438
1439 memset(locinfo, 0, sizeof(threadlocinfo));
1440 locinfo->refcount = 1;
1441
1442 if(locale_name[LC_COLLATE] &&
1444 locale_len[LC_COLLATE], locinfo, LC_COLLATE)) {
1445 goto fail;
1446 }
1447
1448 if(!category_needs_update(LC_COLLATE, old_locinfo,
1449 locale_sname[LC_COLLATE], cp[LC_COLLATE])) {
1451 locinfo->lc_collate_cp = old_locinfo->lc_collate_cp;
1452 } else if(locale_sname[LC_COLLATE]) {
1453 if(!update_threadlocinfo_category(locale_sname[LC_COLLATE],
1455 goto fail;
1456 }
1457
1458 locinfo->lc_collate_cp = locinfo->lc_id[LC_COLLATE].wCodePage;
1459 } else {
1460 if(!init_category_name("C", 1, locinfo, LC_COLLATE)) {
1461 goto fail;
1462 }
1463 }
1464
1465 if(locale_name[LC_CTYPE] &&
1467 locale_len[LC_CTYPE], locinfo, LC_CTYPE)) {
1468 goto fail;
1469 }
1470
1471 if(!category_needs_update(LC_CTYPE, old_locinfo,
1472 locale_sname[LC_CTYPE], cp[LC_CTYPE])) {
1474 locinfo->lc_codepage = old_locinfo->lc_codepage;
1475 locinfo->lc_clike = old_locinfo->lc_clike;
1476 locinfo->mb_cur_max = old_locinfo->mb_cur_max;
1477 locinfo->ctype1 = old_locinfo->ctype1;
1478 locinfo->ctype1_refcount = old_locinfo->ctype1_refcount;
1479 locinfo->pctype = old_locinfo->pctype;
1480 locinfo->pclmap = old_locinfo->pclmap;
1481 locinfo->pcumap = old_locinfo->pcumap;
1482 if(locinfo->ctype1_refcount)
1483 InterlockedIncrement((LONG *)locinfo->ctype1_refcount);
1484 } else if(locale_sname[LC_CTYPE]) {
1486 int j;
1487
1488 if(!update_threadlocinfo_category(locale_sname[LC_CTYPE],
1490 goto fail;
1491 }
1492
1493 locinfo->lc_codepage = locinfo->lc_id[LC_CTYPE].wCodePage;
1494 locinfo->lc_clike = 1;
1495 if(!GetCPInfo(locinfo->lc_codepage, &cp_info)) {
1496 goto fail;
1497 }
1498 locinfo->mb_cur_max = cp_info.MaxCharSize;
1499
1500 locinfo->ctype1_refcount = malloc(sizeof(int));
1501 if(!locinfo->ctype1_refcount) {
1502 goto fail;
1503 }
1504 *locinfo->ctype1_refcount = 1;
1505
1506 locinfo->ctype1 = malloc(257 * sizeof(*locinfo->ctype1));
1507 locinfo->pclmap = malloc(256 * sizeof(*locinfo->pclmap));
1508 locinfo->pcumap = malloc(256 * sizeof(*locinfo->pcumap));
1509 if(!locinfo->ctype1 || !locinfo->pclmap || !locinfo->pcumap) {
1510 goto fail;
1511 }
1512
1513 locinfo->ctype1[0] = 0;
1514 locinfo->pctype = locinfo->ctype1+1;
1515
1516 buf[1] = buf[2] = '\0';
1517 for(i=1; i<257; i++) {
1518 buf[0] = i-1;
1519
1520 MultiByteToWideChar(locinfo->lc_codepage, 0, buf, 1, wbuf, 1);
1521 /* builtin GetStringType doesn't set output to 0 on invalid input */
1522 locinfo->ctype1[i] = 0;
1523 GetStringTypeW(CT_CTYPE1, wbuf, 1, &locinfo->ctype1[i]);
1524 }
1525
1526 for(i=0; cp_info.LeadByte[i+1]!=0; i+=2)
1527 for(j=cp_info.LeadByte[i]; j<=cp_info.LeadByte[i+1]; j++)
1528 locinfo->ctype1[j+1] |= _LEADBYTE;
1529
1530 for(i=0; i<256; i++) {
1531 if(locinfo->pctype[i] & _LEADBYTE)
1532 buf[i] = ' ';
1533 else
1534 buf[i] = i;
1535 }
1536
1537 MultiByteToWideChar(locinfo->lc_codepage, 0, buf, 256, wbuf, 256);
1538 LCMapStringW(LOCALE_INVARIANT, LCMAP_LOWERCASE, wbuf, 256, map_buf, 256);
1539 WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, (char *)locinfo->pclmap, 256, NULL, NULL);
1540 LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, wbuf, 256, map_buf, 256);
1541 WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, (char *)locinfo->pcumap, 256, NULL, NULL);
1542 } else {
1543 locinfo->lc_clike = 1;
1544 locinfo->mb_cur_max = 1;
1545 locinfo->pctype = MSVCRT__ctype+1;
1546 locinfo->pclmap = cloc_clmap;
1547 locinfo->pcumap = cloc_cumap;
1548 if(!init_category_name("C", 1, locinfo, LC_CTYPE)) {
1549 goto fail;
1550 }
1551 }
1552
1553 if(!category_needs_update(LC_MONETARY, old_locinfo,
1554 locale_sname[LC_MONETARY], cp[LC_MONETARY]) &&
1555 !category_needs_update(LC_NUMERIC, old_locinfo,
1556 locale_sname[LC_NUMERIC], cp[LC_NUMERIC])) {
1557 locinfo->lconv = old_locinfo->lconv;
1558 locinfo->lconv_intl_refcount = old_locinfo->lconv_intl_refcount;
1559 if(locinfo->lconv_intl_refcount)
1560 InterlockedIncrement((LONG *)locinfo->lconv_intl_refcount);
1561 } else if(locale_sname[LC_MONETARY] || locale_sname[LC_NUMERIC]) {
1562 locinfo->lconv = malloc(sizeof(struct lconv));
1563 locinfo->lconv_intl_refcount = malloc(sizeof(int));
1564 if(!locinfo->lconv || !locinfo->lconv_intl_refcount) {
1565 free(locinfo->lconv);
1566 free(locinfo->lconv_intl_refcount);
1567 locinfo->lconv = NULL;
1568 locinfo->lconv_intl_refcount = NULL;
1569 goto fail;
1570 }
1571 memset(locinfo->lconv, 0, sizeof(struct lconv));
1572 *locinfo->lconv_intl_refcount = 1;
1573 } else {
1574 locinfo->lconv = &cloc_lconv;
1575 }
1576
1579 locale_len[LC_MONETARY], locinfo, LC_MONETARY)) {
1580 goto fail;
1581 }
1582
1583 if(!category_needs_update(LC_MONETARY, old_locinfo,
1584 locale_sname[LC_MONETARY], cp[LC_MONETARY])) {
1586 locinfo->lconv_mon_refcount = old_locinfo->lconv_mon_refcount;
1587 if(locinfo->lconv_mon_refcount)
1588 InterlockedIncrement((LONG *)locinfo->lconv_mon_refcount);
1589 if(locinfo->lconv != &cloc_lconv && locinfo->lconv != old_locinfo->lconv) {
1590 locinfo->lconv->int_curr_symbol = old_locinfo->lconv->int_curr_symbol;
1591 locinfo->lconv->currency_symbol = old_locinfo->lconv->currency_symbol;
1592 locinfo->lconv->mon_decimal_point = old_locinfo->lconv->mon_decimal_point;
1593 locinfo->lconv->mon_thousands_sep = old_locinfo->lconv->mon_thousands_sep;
1594 locinfo->lconv->mon_grouping = old_locinfo->lconv->mon_grouping;
1595 locinfo->lconv->positive_sign = old_locinfo->lconv->positive_sign;
1596 locinfo->lconv->negative_sign = old_locinfo->lconv->negative_sign;
1597 locinfo->lconv->int_frac_digits = old_locinfo->lconv->int_frac_digits;
1598 locinfo->lconv->frac_digits = old_locinfo->lconv->frac_digits;
1599 locinfo->lconv->p_cs_precedes = old_locinfo->lconv->p_cs_precedes;
1600 locinfo->lconv->p_sep_by_space = old_locinfo->lconv->p_sep_by_space;
1601 locinfo->lconv->n_cs_precedes = old_locinfo->lconv->n_cs_precedes;
1602 locinfo->lconv->n_sep_by_space = old_locinfo->lconv->n_sep_by_space;
1603 locinfo->lconv->p_sign_posn = old_locinfo->lconv->p_sign_posn;
1604 locinfo->lconv->n_sign_posn = old_locinfo->lconv->n_sign_posn;
1605#if _MSVCR_VER >= 100
1606 locinfo->lconv->_W_int_curr_symbol = old_locinfo->lconv->_W_int_curr_symbol;
1607 locinfo->lconv->_W_currency_symbol = old_locinfo->lconv->_W_currency_symbol;
1608 locinfo->lconv->_W_mon_decimal_point = old_locinfo->lconv->_W_mon_decimal_point;
1609 locinfo->lconv->_W_mon_thousands_sep = old_locinfo->lconv->_W_mon_thousands_sep;
1610 locinfo->lconv->_W_positive_sign = old_locinfo->lconv->_W_positive_sign;
1611 locinfo->lconv->_W_negative_sign = old_locinfo->lconv->_W_negative_sign;
1612#endif
1613 }
1614 } else if(locale_sname[LC_MONETARY]) {
1617 goto fail;
1618 }
1619
1620 locinfo->lconv_mon_refcount = malloc(sizeof(int));
1621 if(!locinfo->lconv_mon_refcount) {
1622 goto fail;
1623 }
1624
1625 *locinfo->lconv_mon_refcount = 1;
1626
1628 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1629 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1630 if(i && (locinfo->lconv->int_curr_symbol = malloc(i)))
1631 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->int_curr_symbol, i, NULL, NULL);
1632 else {
1633 goto fail;
1634 }
1635
1637 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1638 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1639 if(i && (locinfo->lconv->currency_symbol = malloc(i)))
1640 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->currency_symbol, i, NULL, NULL);
1641 else {
1642 goto fail;
1643 }
1644
1646 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1647 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1648 if(i && (locinfo->lconv->mon_decimal_point = malloc(i)))
1649 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->mon_decimal_point, i, NULL, NULL);
1650 else {
1651 goto fail;
1652 }
1653
1655 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1656 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1657 if(i && (locinfo->lconv->mon_thousands_sep = malloc(i)))
1658 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->mon_thousands_sep, i, NULL, NULL);
1659 else {
1660 goto fail;
1661 }
1662
1664 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1665 WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buf, 256, NULL, NULL);
1666 if(i>1)
1667 i = i/2 + (buf[i-2]=='0'?0:1);
1668 if(i && (locinfo->lconv->mon_grouping = malloc(i))) {
1669 for(i=0; buf[i+1]==';'; i+=2)
1670 locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
1671 locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
1672 if(buf[i] != '0')
1673 locinfo->lconv->mon_grouping[i/2+1] = 127;
1674 } else {
1675 goto fail;
1676 }
1677
1679 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1680 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1681 if(i && (locinfo->lconv->positive_sign = malloc(i)))
1682 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->positive_sign, i, NULL, NULL);
1683 else {
1684 goto fail;
1685 }
1686
1688 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1689 i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL);
1690 if(i && (locinfo->lconv->negative_sign = malloc(i)))
1691 WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->negative_sign, i, NULL, NULL);
1692 else {
1693 goto fail;
1694 }
1695
1697 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1698 locinfo->lconv->int_frac_digits = val;
1699 else {
1700 goto fail;
1701 }
1702
1704 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1705 locinfo->lconv->frac_digits = val;
1706 else {
1707 goto fail;
1708 }
1709
1711 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1712 locinfo->lconv->p_cs_precedes = val;
1713 else {
1714 goto fail;
1715 }
1716
1718 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1719 locinfo->lconv->p_sep_by_space = val;
1720 else {
1721 goto fail;
1722 }
1723
1725 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1726 locinfo->lconv->n_cs_precedes = val;
1727 else {
1728 goto fail;
1729 }
1730
1732 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1733 locinfo->lconv->n_sep_by_space = val;
1734 else {
1735 goto fail;
1736 }
1737
1739 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1740 locinfo->lconv->p_sign_posn = val;
1741 else {
1742 goto fail;
1743 }
1744
1746 |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2))
1747 locinfo->lconv->n_sign_posn = val;
1748 else {
1749 goto fail;
1750 }
1751
1752#if _MSVCR_VER >= 100
1754 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1755 if(i && (locinfo->lconv->_W_int_curr_symbol = malloc(i * sizeof(wchar_t))))
1756 memcpy(locinfo->lconv->_W_int_curr_symbol, wbuf, i * sizeof(wchar_t));
1757 else {
1758 goto fail;
1759 }
1760
1762 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1763 if(i && (locinfo->lconv->_W_currency_symbol = malloc(i * sizeof(wchar_t))))
1764 memcpy(locinfo->lconv->_W_currency_symbol, wbuf, i * sizeof(wchar_t));
1765 else {
1766 goto fail;
1767 }
1768
1770 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1771 if(i && (locinfo->lconv->_W_mon_decimal_point = malloc(i * sizeof(wchar_t))))
1772 memcpy(locinfo->lconv->_W_mon_decimal_point, wbuf, i * sizeof(wchar_t));
1773 else {
1774 goto fail;
1775 }
1776
1778 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1779 if(i && (locinfo->lconv->_W_mon_thousands_sep = malloc(i * sizeof(wchar_t))))
1780 memcpy(locinfo->lconv->_W_mon_thousands_sep, wbuf, i * sizeof(wchar_t));
1781 else {
1782 goto fail;
1783 }
1784
1786 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1787 if(i && (locinfo->lconv->_W_positive_sign = malloc(i * sizeof(wchar_t))))
1788 memcpy(locinfo->lconv->_W_positive_sign, wbuf, i * sizeof(wchar_t));
1789 else {
1790 goto fail;
1791 }
1792
1794 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1795 if(i && (locinfo->lconv->_W_negative_sign = malloc(i * sizeof(wchar_t))))
1796 memcpy(locinfo->lconv->_W_negative_sign, wbuf, i * sizeof(wchar_t));
1797 else {
1798 goto fail;
1799 }
1800#endif
1801 } else {
1802 if (locinfo->lconv != &cloc_lconv) {
1803 locinfo->lconv->int_curr_symbol = cloc_lconv.int_curr_symbol;
1804 locinfo->lconv->currency_symbol = cloc_lconv.currency_symbol;
1805 locinfo->lconv->mon_decimal_point = cloc_lconv.mon_decimal_point;
1806 locinfo->lconv->mon_thousands_sep = cloc_lconv.mon_thousands_sep;
1807 locinfo->lconv->mon_grouping = cloc_lconv.mon_grouping;
1808 locinfo->lconv->positive_sign = cloc_lconv.positive_sign;
1809 locinfo->lconv->negative_sign = cloc_lconv.negative_sign;
1810 locinfo->lconv->int_frac_digits = cloc_lconv.int_frac_digits;
1811 locinfo->lconv->frac_digits = cloc_lconv.frac_digits;
1812 locinfo->lconv->p_cs_precedes = cloc_lconv.p_cs_precedes;
1813 locinfo->lconv->p_sep_by_space = cloc_lconv.p_sep_by_space;
1814 locinfo->lconv->n_cs_precedes = cloc_lconv.n_cs_precedes;
1815 locinfo->lconv->n_sep_by_space = cloc_lconv.n_sep_by_space;
1816 locinfo->lconv->p_sign_posn = cloc_lconv.p_sign_posn;
1817 locinfo->lconv->n_sign_posn = cloc_lconv.n_sign_posn;
1818
1819#if _MSVCR_VER >= 100
1820 locinfo->lconv->_W_int_curr_symbol = cloc_lconv._W_int_curr_symbol;
1821 locinfo->lconv->_W_currency_symbol = cloc_lconv._W_currency_symbol;
1822 locinfo->lconv->_W_mon_decimal_point = cloc_lconv._W_mon_decimal_point;
1823 locinfo->lconv->_W_mon_thousands_sep = cloc_lconv._W_mon_thousands_sep;
1824 locinfo->lconv->_W_positive_sign = cloc_lconv._W_positive_sign;
1825 locinfo->lconv->_W_negative_sign = cloc_lconv._W_negative_sign;
1826#endif
1827 }
1828
1829 if(!init_category_name("C", 1, locinfo, LC_MONETARY)) {
1830 goto fail;
1831 }
1832 }
1833
1834 if(locale_name[LC_NUMERIC] &&
1836 locale_len[LC_NUMERIC], locinfo, LC_NUMERIC)) {
1837 goto fail;
1838 }
1839
1840 if(!category_needs_update(LC_NUMERIC, old_locinfo,
1841 locale_sname[LC_NUMERIC], cp[LC_NUMERIC])) {
1843 locinfo->lconv_num_refcount = old_locinfo->lconv_num_refcount;
1844 if(locinfo->lconv_num_refcount)
1845 InterlockedIncrement((LONG *)locinfo->lconv_num_refcount);
1846 if(locinfo->lconv != &cloc_lconv && locinfo->lconv != old_locinfo->lconv) {
1847 locinfo->lconv->decimal_point = old_locinfo->lconv->decimal_point;
1848 locinfo->lconv->thousands_sep = old_locinfo->lconv->thousands_sep;
1849 locinfo->lconv->grouping = old_locinfo->lconv->grouping;
1850#if _MSVCR_VER >= 100
1851 locinfo->lconv->_W_decimal_point = old_locinfo->lconv->_W_decimal_point;
1852 locinfo->lconv->_W_thousands_sep = old_locinfo->lconv->_W_thousands_sep;
1853#endif
1854 }
1855 } else if(locale_sname[LC_NUMERIC]) {
1856 if(!update_threadlocinfo_category(locale_sname[LC_NUMERIC],
1858 goto fail;
1859 }
1860
1861 locinfo->lconv_num_refcount = malloc(sizeof(int));
1862 if(!locinfo->lconv_num_refcount) {
1863 goto fail;
1864 }
1865
1866 *locinfo->lconv_num_refcount = 1;
1867
1869 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1870 i = WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, NULL, 0, NULL, NULL);
1871 if(i && (locinfo->lconv->decimal_point = malloc(i)))
1872 WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, locinfo->lconv->decimal_point, i, NULL, NULL);
1873 else {
1874 goto fail;
1875 }
1876
1878 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1879 i = WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, NULL, 0, NULL, NULL);
1880 if(i && (locinfo->lconv->thousands_sep = malloc(i)))
1881 WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, locinfo->lconv->thousands_sep, i, NULL, NULL);
1882 else {
1883 goto fail;
1884 }
1885
1887 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1888 WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, buf, 256, NULL, NULL);
1889 if(i>1)
1890 i = i/2 + (buf[i-2]=='0'?0:1);
1891 if(i && (locinfo->lconv->grouping = malloc(i))) {
1892 for(i=0; buf[i+1]==';'; i+=2)
1893 locinfo->lconv->grouping[i/2] = buf[i]-'0';
1894 locinfo->lconv->grouping[i/2] = buf[i]-'0';
1895 if(buf[i] != '0')
1896 locinfo->lconv->grouping[i/2+1] = 127;
1897 } else {
1898 goto fail;
1899 }
1900
1901#if _MSVCR_VER >= 100
1903 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1904 if(i && (locinfo->lconv->_W_decimal_point = malloc(i * sizeof(wchar_t))))
1905 memcpy(locinfo->lconv->_W_decimal_point, wbuf, i * sizeof(wchar_t));
1906 else {
1907 goto fail;
1908 }
1909
1911 |LOCALE_NOUSEROVERRIDE, wbuf, 256);
1912 if(i && (locinfo->lconv->_W_thousands_sep = malloc(i * sizeof(wchar_t))))
1913 memcpy(locinfo->lconv->_W_thousands_sep, wbuf, i * sizeof(wchar_t));
1914 else {
1915 goto fail;
1916 }
1917#endif
1918 } else {
1919 if (locinfo->lconv != &cloc_lconv) {
1920 locinfo->lconv->decimal_point = cloc_lconv.decimal_point;
1921 locinfo->lconv->thousands_sep = cloc_lconv.thousands_sep;
1922 locinfo->lconv->grouping = cloc_lconv.grouping;
1923
1924#if _MSVCR_VER >= 100
1925 locinfo->lconv->_W_decimal_point = cloc_lconv._W_decimal_point;
1926 locinfo->lconv->_W_thousands_sep = cloc_lconv._W_thousands_sep;
1927#endif
1928 }
1929
1930 if (!init_category_name("C", 1, locinfo, LC_NUMERIC)) {
1931 goto fail;
1932 }
1933 }
1934
1935 if(locale_name[LC_TIME] &&
1937 locale_len[LC_TIME], locinfo, LC_TIME)) {
1938 goto fail;
1939 }
1940
1941 if(!category_needs_update(LC_TIME, old_locinfo,
1942 locale_sname[LC_TIME], cp[LC_TIME])) {
1944 locinfo->lc_time_curr = old_locinfo->lc_time_curr;
1945 InterlockedIncrement(&locinfo->lc_time_curr->refcount);
1946 } else if(locale_sname[LC_TIME]) {
1947 if(!update_threadlocinfo_category(locale_sname[LC_TIME],
1948 cp[LC_TIME], locinfo, LC_TIME)) {
1949 goto fail;
1950 }
1951
1952 locinfo->lc_time_curr = create_time_data(locale_sname[LC_TIME]);
1953 if(!locinfo->lc_time_curr) {
1954 goto fail;
1955 }
1956 } else {
1957 if(!init_category_name("C", 1, locinfo, LC_TIME)) {
1958 goto fail;
1959 }
1960 locinfo->lc_time_curr = &cloc_time_data;
1961 InterlockedIncrement(&locinfo->lc_time_curr->refcount);
1962 }
1963
1964 for (i = 0; i < LC_MAX; i++)
1965 free(locale_sname[i]);
1966
1967 return locinfo;
1968
1969fail:
1971
1972 for (i = 0; i < LC_MAX; i++)
1973 free(locale_sname[i]);
1974
1975 return NULL;
1976}
1977
1978/*********************************************************************
1979 * _create_locale (MSVCRT.@)
1980 */
1982{
1983 _locale_t loc;
1984
1985 loc = malloc(sizeof(_locale_tstruct));
1986 if(!loc)
1987 return NULL;
1988
1990 if(!loc->locinfo) {
1991 free(loc);
1992 return NULL;
1993 }
1994
1996 loc->locinfo->lc_handle[LC_CTYPE], NULL);
1997 if(!loc->mbcinfo) {
1998 free_locinfo(loc->locinfo);
1999 free(loc);
2000 return NULL;
2001 }
2002 return loc;
2003}
2004
2005#if _MSVCR_VER >= 110
2006/*********************************************************************
2007 * _wcreate_locale (MSVCR110.@)
2008 */
2009_locale_t CDECL _wcreate_locale(int category, const wchar_t *locale)
2010{
2011 _locale_t loc;
2012 size_t len;
2013 char *str;
2014
2016 return NULL;
2017
2018 len = wcstombs(NULL, locale, 0);
2019 if(len == -1)
2020 return NULL;
2021 if(!(str = malloc(++len)))
2022 return NULL;
2024
2025 loc = _create_locale(category, str);
2026
2027 free(str);
2028 return loc;
2029}
2030#endif
2031
2032/*********************************************************************
2033 * setlocale (MSVCRT.@)
2034 */
2035char* CDECL setlocale(int category, const char* locale)
2036{
2038 pthreadlocinfo locinfo = get_locinfo(), newlocinfo;
2039 int locale_flags;
2040
2042 return NULL;
2043
2044 if(!locale) {
2045 if(category == LC_ALL)
2046 return construct_lc_all(locinfo);
2047
2048 return locinfo->lc_category[category].locale;
2049 }
2050
2051 /* Make sure that locinfo is not updated by e.g. stricmp function */
2052 locale_flags = data->locale_flags;
2053 data->locale_flags |= LOCALE_THREAD;
2054 newlocinfo = create_locinfo(category, locale, locinfo);
2055 data->locale_flags = locale_flags;
2056 if(!newlocinfo) {
2057 WARN("%d %s failed\n", category, locale);
2058 return NULL;
2059 }
2060
2061 if(locale[0] != 'C' || locale[1] != '\0')
2063
2064 if(data->locale_flags & LOCALE_THREAD)
2065 {
2066 if(data->locale_flags & LOCALE_FREE)
2067 free_locinfo(data->locinfo);
2068 data->locinfo = newlocinfo;
2069 }
2070 else
2071 {
2072 int i;
2073
2074 _lock_locales();
2076 MSVCRT_locale->locinfo = newlocinfo;
2077
2078 MSVCRT___lc_codepage = newlocinfo->lc_codepage;
2079 MSVCRT___lc_collate_cp = newlocinfo->lc_collate_cp;
2080 MSVCRT___mb_cur_max = newlocinfo->mb_cur_max;
2081 MSVCRT__pctype = newlocinfo->pctype;
2082 for(i=LC_MIN; i<=LC_MAX; i++)
2086 }
2087
2088 if(category == LC_ALL)
2089 return construct_lc_all(data->locinfo);
2090
2091 return data->locinfo->lc_category[category].locale;
2092}
2093
2094/*********************************************************************
2095 * _wsetlocale (MSVCRT.@)
2096 */
2097wchar_t* CDECL _wsetlocale(int category, const wchar_t* wlocale)
2098{
2099 static wchar_t current_lc_all[MAX_LOCALE_LENGTH];
2100
2101 char *locale = NULL;
2102 const char *ret;
2103 size_t len;
2104
2105 if(wlocale) {
2106 len = wcstombs(NULL, wlocale, 0);
2107 if(len == -1)
2108 return NULL;
2109
2110 locale = malloc(++len);
2111 if(!locale)
2112 return NULL;
2113
2114 wcstombs(locale, wlocale, len);
2115 }
2116
2117 _lock_locales();
2119 free(locale);
2120
2121 if(ret && mbstowcs(current_lc_all, ret, MAX_LOCALE_LENGTH)==-1)
2122 ret = NULL;
2123
2125 return ret ? current_lc_all : NULL;
2126}
2127
2128#if _MSVCR_VER >= 80
2129/*********************************************************************
2130 * _configthreadlocale (MSVCR80.@)
2131 */
2133{
2135 int ret;
2136
2137 ret = (data->locale_flags & LOCALE_THREAD ? _ENABLE_PER_THREAD_LOCALE :
2139
2141 data->locale_flags |= LOCALE_THREAD;
2143 data->locale_flags &= ~LOCALE_THREAD;
2144 else if(type)
2145 ret = -1;
2146
2147 return ret;
2148}
2149#endif
2150
2152{
2153 int i;
2154
2155 _lock_locales();
2156 MSVCRT_locale = _create_locale(0, "C");
2158 if(!MSVCRT_locale)
2159 return FALSE;
2160
2165 for(i=LC_MIN; i<=LC_MAX; i++)
2168 return TRUE;
2169}
2170
2171#if _MSVCR_VER >= 120
2172/*********************************************************************
2173 * wctrans (MSVCR120.@)
2174 */
2175wctrans_t CDECL wctrans(const char *property)
2176{
2177 static const char str_tolower[] = "tolower";
2178 static const char str_toupper[] = "toupper";
2179
2180 if(!strcmp(property, str_tolower))
2181 return 2;
2182 if(!strcmp(property, str_toupper))
2183 return 1;
2184 return 0;
2185}
2186#endif
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)
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define _stricmp
Definition: cat.c:22
Definition: _ctype.h:58
Definition: _locale.h:75
LPARAM lParam
Definition: combotst.c:139
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CDECL
Definition: compat.h:29
#define CP_ACP
Definition: compat.h:109
#define lstrcpynA
Definition: compat.h:751
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
LCID WINAPI LocaleNameToLCID(_In_ LPCWSTR lpName, _In_ DWORD dwFlags)
UINT WINAPI GetACP(void)
Definition: locale.c:2023
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2081
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: locale.c:4086
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4017
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
BOOL WINAPI IsValidLocaleName(LPCWSTR locale)
Definition: locale.c:2936
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: locale.c:3098
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3808
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1675
INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
Definition: locale.c:5649
LCID lcid
Definition: locale.c:5656
WORD MSVCRT__ctype[257]
Definition: ctype.c:34
#define _LEADBYTE
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:195
#define UCHAR_MAX
Definition: limits.h:11
#define CHAR_MAX
Definition: limits.h:18
#define LC_CTYPE
Definition: locale.h:27
#define LC_NUMERIC
Definition: locale.h:29
#define LC_MAX
Definition: locale.h:32
#define LC_MONETARY
Definition: locale.h:28
#define LC_MIN
Definition: locale.h:31
#define LC_ALL
Definition: locale.h:25
#define LC_TIME
Definition: locale.h:30
#define LC_COLLATE
Definition: locale.h:26
#define _DISABLE_PER_THREAD_LOCALE
Definition: locale.h:75
_ACRTIMP int __cdecl _configthreadlocale(int)
Definition: locale.c:1426
#define _ENABLE_PER_THREAD_LOCALE
Definition: locale.h:74
#define _MB_CP_ANSI
Definition: mbctype.h:53
_ACRTIMP int __cdecl _setmbcp(int)
Definition: mbcs.c:400
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
static wchar_t * wcsdup(const wchar_t *str)
Definition: string.h:94
wchar_t wctrans_t
Definition: wctype.h:71
wctrans_t __cdecl wctrans(const char *)
Definition: wctrans.cpp:38
static const char *const _country_synonyms[]
Definition: locale.c:173
unsigned short * MSVCRT__pctype
Definition: locale.c:44
static BOOL category_needs_update(int cat, const threadlocinfo *locinfo, WCHAR *sname, unsigned short cp)
Definition: locale.c:1192
static struct lconv cloc_lconv
Definition: locale.c:163
void free_mbcinfo(pthreadmbcinfo mbcinfo)
Definition: locale.c:1138
#define FOUND_LANGUAGE
Definition: locale.c:240
int CDECL __crtLCMapStringA(LCID lcid, DWORD mapflags, const char *src, int srclen, char *dst, int dstlen, unsigned int codepage, int xflag)
Definition: locale.c:877
pthreadmbcinfo CDECL get_mbcinfo(void)
Definition: locale.c:642
int CDECL __lconv_init(void)
Definition: locale.c:1012
LCID *CDECL ___lc_handle_func(void)
Definition: locale.c:1029
int MSVCRT___lc_collate_cp
Definition: locale.c:46
static __lc_time_data * create_time_data(WCHAR *sname)
Definition: locale.c:1208
static void update_thread_locale(thread_data_t *data)
Definition: locale.c:609
_locale_t CDECL get_current_locale_noalloc(_locale_t locale)
Definition: locale.c:1149
unsigned int MSVCRT___lc_codepage
Definition: locale.c:45
void free_locinfo(pthreadlocinfo locinfo)
Definition: locale.c:1061
void CDECL _lock_locales(void)
Definition: locale.c:574
static void copy_threadlocinfo_category(pthreadlocinfo locinfo, const threadlocinfo *old_locinfo, int category)
Definition: locale.c:453
_locale_t CDECL _create_locale(int category, const char *locale)
Definition: locale.c:1981
static BOOL CALLBACK find_best_locale_proc(WCHAR *name, DWORD locale_flags, LPARAM lParam)
Definition: locale.c:277
int CDECL __crtGetLocaleInfoW(LCID lcid, LCTYPE type, wchar_t *buffer, int len)
Definition: locale.c:968
void CDECL _free_locale(_locale_t locale)
Definition: locale.c:1183
static BOOL remap_synonym(char *name)
Definition: locale.c:222
static char cloc_dec_point[]
Definition: locale.c:158
static BOOL update_threadlocinfo_category(WCHAR *sname, unsigned short cp, pthreadlocinfo locinfo, int category)
Definition: locale.c:512
char *CDECL _Getdays(void)
Definition: locale.c:678
static pthreadlocinfo create_locinfo(int category, const char *locale, const threadlocinfo *old_locinfo)
Definition: locale.c:1278
static int compare_info(WCHAR *name, DWORD flags, WCHAR *buff, const WCHAR *cmp, BOOL exact)
Definition: locale.c:255
static const unsigned char cloc_cumap[256]
Definition: locale.c:121
static char * construct_lc_all(pthreadlocinfo locinfo)
Definition: locale.c:649
char *CDECL _Getmonths(void)
Definition: locale.c:752
int CDECL __crtCompareStringA(LCID lcid, DWORD flags, const char *src1, int len1, const char *src2, int len2)
Definition: locale.c:944
BOOL CDECL __crtGetStringTypeW(DWORD unk, DWORD type, wchar_t *buffer, int len, WORD *out)
Definition: locale.c:992
BOOL initial_locale
Definition: locale.c:49
#define FOUND_SNAME
Definition: locale.c:239
LCID MSVCRT___lc_handle[LC_MAX - LC_MIN+1]
Definition: locale.c:47
void *CDECL _Gettnames(void)
Definition: locale.c:826
BOOL msvcrt_init_locale(void)
Definition: locale.c:2151
wchar_t *CDECL _wsetlocale(int category, const wchar_t *wlocale)
Definition: locale.c:2097
BOOL locale_to_sname(const char *locale, unsigned short *codepage, BOOL *sname_match, WCHAR *sname)
Definition: locale.c:335
int MSVCRT___mb_cur_max
Definition: locale.c:48
static char empty[]
Definition: locale.c:157
#define LCID_CONVERSION_FLAGS
Definition: locale.c:57
__lc_time_data cloc_time_data
Definition: locale.c:60
#define STOP_LOOKING
Definition: locale.c:252
static const unsigned char cloc_clmap[256]
Definition: locale.c:85
#define FOUND_COUNTRY
Definition: locale.c:241
void CDECL _unlock_locales(void)
Definition: locale.c:582
#define MAX_LOCALE_LENGTH
Definition: locale.c:42
_locale_t CDECL _get_current_locale(void)
Definition: locale.c:1171
static void grab_locinfo(pthreadlocinfo locinfo)
Definition: locale.c:587
static BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat, WCHAR *sname)
Definition: locale.c:505
#define CONTINUE_LOOKING
Definition: locale.c:251
int CDECL __crtLCMapStringW(LCID lcid, DWORD mapflags, const wchar_t *src, int srclen, wchar_t *dst, int dstlen, unsigned int codepage, int xflag)
Definition: locale.c:932
int CDECL ___lc_collate_cp_func(void)
Definition: locale.c:1055
pthreadlocinfo CDECL get_locinfo(void)
Definition: locale.c:635
static BOOL init_category_name(const char *name, int len, pthreadlocinfo locinfo, int category)
Definition: locale.c:471
void CDECL free_locale_noalloc(_locale_t locale)
Definition: locale.c:1162
unsigned int CDECL ___lc_codepage_func(void)
Definition: locale.c:1047
int CDECL __crtCompareStringW(LCID lcid, DWORD flags, const wchar_t *src1, int len1, const wchar_t *src2, int len2)
Definition: locale.c:956
struct lconv *CDECL localeconv(void)
Definition: locale.c:1004
_locale_t MSVCRT_locale
Definition: locale.c:43
#define MAX_ELEM_LEN
Definition: locale.c:41
void CDECL _lock(int locknum)
Definition: lock.c:85
void CDECL _unlock(int locknum)
Definition: lock.c:114
thread_data_t *CDECL msvcrt_get_thread_data(void)
Definition: thread.c:45
#define LOCALE_FREE
Definition: msvcrt.h:172
#define LOCALE_THREAD
Definition: msvcrt.h:173
#define _MB_CP_LOCK
Definition: mtdll.h:49
#define _SETLOCALE_LOCK
Definition: mtdll.h:43
else locinfo
Definition: scanf.h:225
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
static unsigned char buff[32768]
Definition: fatten.c:17
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxCollectionEntry * cur
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
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 const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define MB_ERR_INVALID_CHARS
Definition: unicode.h:41
static const WCHAR emptyW[]
Definition: navigate.c:40
wchar_t **__cdecl ___lc_locale_name_func()
Definition: initctype.cpp:326
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
POINT cp
Definition: magnifier.c:59
threadmbcinfo * create_mbcinfo(int cp, LCID lcid, threadmbcinfo *old_mbcinfo)
Definition: mbcs.c:219
LONG_PTR LPARAM
Definition: minwindef.h:175
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf
Definition: sprintf.c:45
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: directory.c:52
static DWORD dstlen
Definition: directory.c:51
#define cmp(status, error)
Definition: error.c:114
static short search(int val, const short *table, int size)
Definition: msg711.c:255
#define LOCALE_NAME_MAX_LENGTH
#define LOCALE_INVARIANT
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
long LONG
Definition: pedump.c:60
const WCHAR * str
#define SUBLANG_NORWEGIAN_NYNORSK
Definition: nls.h:301
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_NORWEGIAN
Definition: nls.h:102
#define LANG_ENGLISH
Definition: nls.h:52
#define LANGIDFROMLCID(l)
Definition: nls.h:18
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
wcscpy
wcstombs
Definition: stdlib.h:1013
mbstowcs
Definition: stdlib.h:925
strcpy
Definition: string.h:131
#define memset(x, y, z)
Definition: compat.h:39
#define setlocale(n, s)
Definition: locale.h:46
#define wchar_t
Definition: wchar.h:102
#define TRACE(s)
Definition: solgame.cpp:4
void *__cdecl _W_Gettnames()
Definition: wcsftime.cpp:83
Definition: locale.h:37
unsigned int match_flags
Definition: locale.c:247
BOOL allow_sname
Definition: locale.c:248
pthreadlocinfo locinfo
Definition: corecrt.h:260
pthreadmbcinfo mbcinfo
Definition: corecrt.h:261
Definition: name.c:39
unsigned short wCodePage
Definition: corecrt.h:268
struct lconv * lconv
Definition: corecrt.h:301
unsigned int lc_collate_cp
Definition: corecrt.h:285
unsigned int lc_codepage
Definition: corecrt.h:278
struct threadlocaleinfostruct::@576 lc_category[6]
unsigned short * ctype1
Definition: corecrt.h:303
wchar_t * lc_name[6]
Definition: corecrt.h:311
struct __lc_time_data * lc_time_curr
Definition: corecrt.h:309
unsigned short * pctype
Definition: corecrt.h:276
const unsigned char * pcumap
Definition: corecrt.h:308
const unsigned char * pclmap
Definition: corecrt.h:307
__msvcrt_ulong lc_handle[6]
Definition: corecrt.h:286
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
wchar_t *__cdecl _W_Getmonths()
Definition: wcsftime.cpp:51
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
wchar_t *__cdecl _W_Getdays()
Definition: wcsftime.cpp:19
int codepage
Definition: win_iconv.c:156
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:120
#define LOCALE_SMONTHNAME12
Definition: winnls.h:109
#define LOCALE_ICURRDIGITS
Definition: winnls.h:61
#define LOCALE_IDEFAULTCODEPAGE
Definition: winnls.h:44
#define LOCALE_SMONTHNAME5
Definition: winnls.h:102
#define LOCALE_SDAYNAME5
Definition: winnls.h:88
#define LOCALE_SABBREVMONTHNAME9
Definition: winnls.h:119
#define LOCALE_SABBREVMONTHNAME11
Definition: winnls.h:121
#define LOCALE_SABBREVDAYNAME5
Definition: winnls.h:95
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:92
#define LOCALE_INEGSEPBYSPACE
Definition: winnls.h:131
#define LOCALE_SABBREVMONTHNAME2
Definition: winnls.h:112
#define LOCALE_INEGSIGNPOSN
Definition: winnls.h:127
#define LOCALE_SGROUPING
Definition: winnls.h:51
#define LOCALE_SMONTHNAME3
Definition: winnls.h:100
#define LOCALE_SDECIMAL
Definition: winnls.h:49
#define LOCALE_SMONTHNAME11
Definition: winnls.h:108
#define LOCALE_SMONTHNAME8
Definition: winnls.h:105
#define CT_CTYPE1
Definition: winnls.h:255
#define LOCALE_SMONTHNAME4
Definition: winnls.h:101
#define LOCALE_SENGLANGUAGE
Definition: winnls.h:32
#define LOCALE_SDAYNAME1
Definition: winnls.h:84
#define LOCALE_ILANGUAGE
Definition: winnls.h:30
#define LOCALE_SNAME
Definition: winnls.h:137
#define LCMAP_UPPERCASE
Definition: winnls.h:198
#define LOCALE_SLONGDATE
Definition: winnls.h:68
#define LOCALE_SMONTHNAME7
Definition: winnls.h:104
#define LOCALE_IINTLCURRDIGITS
Definition: winnls.h:62
#define LOCALE_S1159
Definition: winnls.h:78
#define LOCALE_SSHORTDATE
Definition: winnls.h:67
#define LOCALE_IPOSSYMPRECEDES
Definition: winnls.h:128
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:114
#define LOCALE_SPOSITIVESIGN
Definition: winnls.h:124
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:94
#define LOCALE_SMONDECIMALSEP
Definition: winnls.h:58
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:133
#define LCMAP_SORTKEY
Definition: winnls.h:199
#define LCMAP_LOWERCASE
Definition: winnls.h:197
#define LOCALE_SMONTHNAME1
Definition: winnls.h:98
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:113
#define LOCALE_INEGSYMPRECEDES
Definition: winnls.h:130
#define LOCALE_SMONTHOUSANDSEP
Definition: winnls.h:59
#define LOCALE_SDAYNAME7
Definition: winnls.h:90
#define LOCALE_IPOSSIGNPOSN
Definition: winnls.h:126
#define LOCALE_SDAYNAME2
Definition: winnls.h:85
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:111
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
#define LOCALE_STHOUSAND
Definition: winnls.h:50
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:45
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:134
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:96
#define LOCALE_SMONTHNAME2
Definition: winnls.h:99
#define LOCALE_STIMEFORMAT
Definition: winnls.h:69
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:91
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:116
#define LOCALE_SMONTHNAME6
Definition: winnls.h:103
#define LOCALE_SABBREVLANGNAME
Definition: winnls.h:34
#define LOCALE_SENGCOUNTRY
Definition: winnls.h:38
#define LOCALE_SABBREVCTRYNAME
Definition: winnls.h:40
#define LOCALE_SNEGATIVESIGN
Definition: winnls.h:125
DWORD LCTYPE
Definition: winnls.h:581
#define LOCALE_SDAYNAME3
Definition: winnls.h:86
#define LOCALE_S2359
Definition: winnls.h:79
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:93
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:115
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:117
#define LOCALE_SINTLSYMBOL
Definition: winnls.h:57
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:118
#define LOCALE_SMONGROUPING
Definition: winnls.h:60
#define LOCALE_SDAYNAME4
Definition: winnls.h:87
#define LOCALE_SCURRENCY
Definition: winnls.h:56
#define LOCALE_SMONTHNAME10
Definition: winnls.h:107
#define LOCALE_SMONTHNAME9
Definition: winnls.h:106
#define LOCALE_IPOSSEPBYSPACE
Definition: winnls.h:129
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:122
#define LOCALE_SDAYNAME6
Definition: winnls.h:89
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:97
_locale_t __cdecl _wcreate_locale(int _category, const wchar_t *locale)
Definition: wsetlocale.cpp:340
__wchar_t WCHAR
Definition: xmlstorage.h:180