msvcp90: Added numpunct<char> class implementation.
[wine] / dlls / msvcp90 / locale.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #include "msvcp90.h"
24 #include "locale.h"
25 #include "errno.h"
26 #include "limits.h"
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msvcp90);
34
35 char* __cdecl _Getdays(void);
36 char* __cdecl _Getmonths(void);
37 void* __cdecl _Gettnames(void);
38 unsigned int __cdecl ___lc_codepage_func(void);
39 LCID* __cdecl ___lc_handle_func(void);
40
41 typedef int category;
42
43 typedef struct {
44     MSVCP_size_t id;
45 } locale_id;
46
47 typedef struct {
48     const vtable_ptr *vtable;
49     MSVCP_size_t refs;
50 } locale_facet;
51
52 typedef struct _locale__Locimp {
53     locale_facet facet;
54     locale_facet **facetvec;
55     MSVCP_size_t facet_cnt;
56     category catmask;
57     MSVCP_bool transparent;
58     basic_string_char name;
59 } locale__Locimp;
60
61 typedef struct {
62     void *timeptr;
63 } _Timevec;
64
65 typedef struct {
66     _Lockit lock;
67     basic_string_char days;
68     basic_string_char months;
69     basic_string_char oldlocname;
70     basic_string_char newlocname;
71 } _Locinfo;
72
73 typedef struct {
74     LCID handle;
75     unsigned page;
76 } _Collvec;
77
78 typedef struct {
79     LCID handle;
80     unsigned page;
81     const short *table;
82     int delfl;
83 } _Ctypevec;
84
85 typedef struct {
86     LCID handle;
87     unsigned page;
88 } _Cvtvec;
89
90 typedef struct {
91     locale_facet facet;
92     _Collvec coll;
93 } collate;
94
95 typedef struct {
96     locale_facet facet;
97 } ctype_base;
98
99 typedef struct {
100     ctype_base base;
101     _Ctypevec ctype;
102 } ctype_char;
103
104 typedef struct {
105     ctype_base base;
106     _Ctypevec ctype;
107     _Cvtvec cvt;
108 } ctype_wchar;
109
110 typedef struct {
111     locale_facet facet;
112     const char *grouping;
113     char dp;
114     char sep;
115     const char *false_name;
116     const char *true_name;
117 } numpunct_char;
118
119 typedef struct {
120     locale_facet facet;
121     const char *grouping;
122     wchar_t dp;
123     wchar_t sep;
124     const wchar_t *false_name;
125     const wchar_t *true_name;
126 } numpunct_wchar;
127
128 /* ?_Id_cnt@id@locale@std@@0HA */
129 int locale_id__Id_cnt = 0;
130
131 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
132 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
133 locale__Locimp *locale__Locimp__Clocptr = NULL;
134
135 /* ??1facet@locale@std@@UAE@XZ */
136 /* ??1facet@locale@std@@UEAA@XZ */
137 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
138 void __thiscall locale_facet_dtor(locale_facet *this)
139 {
140     TRACE("(%p)\n", this);
141 }
142
143 DEFINE_THISCALL_WRAPPER(MSVCP_locale_facet_vector_dtor, 8)
144 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
145         locale_facet*, (locale_facet*, unsigned int), (this, flags))
146 locale_facet* __thiscall MSVCP_locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
147 {
148     TRACE("(%p %x)\n", this, flags);
149     if(flags & 2) {
150         /* we have an array, with the number of elements stored before the first object */
151         int i, *ptr = (int *)this-1;
152
153         for(i=*ptr-1; i>=0; i--)
154             locale_facet_dtor(this+i);
155         MSVCRT_operator_delete(ptr);
156     } else {
157         locale_facet_dtor(this);
158         if(flags & 1)
159             MSVCRT_operator_delete(this);
160     }
161
162     return this;
163 }
164
165 const vtable_ptr MSVCP_locale_facet_vtable[] = {
166     (vtable_ptr)THISCALL_NAME(MSVCP_locale_facet_vector_dtor)
167 };
168
169 /* ??0id@locale@std@@QAE@I@Z */
170 /* ??0id@locale@std@@QEAA@_K@Z */
171 DEFINE_THISCALL_WRAPPER(locale_id_ctor_id, 8)
172 locale_id* __thiscall locale_id_ctor_id(locale_id *this, MSVCP_size_t id)
173 {
174     TRACE("(%p %lu)\n", this, id);
175
176     this->id = id;
177     return this;
178 }
179
180 /* ??_Fid@locale@std@@QAEXXZ */
181 /* ??_Fid@locale@std@@QEAAXXZ */
182 DEFINE_THISCALL_WRAPPER(locale_id_ctor, 4)
183 locale_id* __thiscall locale_id_ctor(locale_id *this)
184 {
185     TRACE("(%p)\n", this);
186
187     this->id = 0;
188     return this;
189 }
190
191 /* ??Bid@locale@std@@QAEIXZ */
192 /* ??Bid@locale@std@@QEAA_KXZ */
193 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
194 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
195 {
196     _Lockit lock;
197
198     TRACE("(%p)\n", this);
199
200     if(!this->id) {
201         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
202         this->id = ++locale_id__Id_cnt;
203         _Lockit_dtor(&lock);
204     }
205
206     return this->id;
207 }
208
209 /* ?_Id_cnt_func@id@locale@std@@CAAAHXZ */
210 /* ?_Id_cnt_func@id@locale@std@@CAAEAHXZ */
211 int* __cdecl locale_id__Id_cnt_func(void)
212 {
213     TRACE("\n");
214     return &locale_id__Id_cnt;
215 }
216
217 /* ??_Ffacet@locale@std@@QAEXXZ */
218 /* ??_Ffacet@locale@std@@QEAAXXZ */
219 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
220 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
221 {
222     TRACE("(%p)\n", this);
223     this->vtable = MSVCP_locale_facet_vtable;
224     this->refs = 0;
225     return this;
226 }
227
228 /* ??0facet@locale@std@@IAE@I@Z */
229 /* ??0facet@locale@std@@IEAA@_K@Z */
230 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
231 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
232 {
233     TRACE("(%p %lu)\n", this, refs);
234     this->vtable = MSVCP_locale_facet_vtable;
235     this->refs = refs;
236     return this;
237 }
238
239 /* ?_Incref@facet@locale@std@@QAEXXZ */
240 /* ?_Incref@facet@locale@std@@QEAAXXZ */
241 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
242 void __thiscall locale_facet__Incref(locale_facet *this)
243 {
244     _Lockit lock;
245
246     TRACE("(%p)\n", this);
247
248     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
249     this->refs++;
250     _Lockit_dtor(&lock);
251 }
252
253 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
254 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
255 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
256 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
257 {
258     _Lockit lock;
259     locale_facet *ret;
260
261     TRACE("(%p)\n", this);
262
263     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
264     if(this->refs)
265         this->refs--;
266
267     ret = this->refs ? NULL : this;
268     _Lockit_dtor(&lock);
269
270     return ret;
271 }
272
273 /* ?_Getcat@facet@locale@std@@SAIPAPBV123@PBV23@@Z */
274 /* ?_Getcat@facet@locale@std@@SA_KPEAPEBV123@PEBV23@@Z */
275 MSVCP_size_t __cdecl locale_facet__Getcat(const locale_facet **facet, const locale *loc)
276 {
277     TRACE("(%p %p)\n", facet, loc);
278     return -1;
279 }
280
281 /* ??0_Timevec@std@@QAE@ABV01@@Z */
282 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
283 /* This copy constructor modifies copied object */
284 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
285 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
286 {
287     TRACE("(%p %p)\n", this, copy);
288     this->timeptr = copy->timeptr;
289     copy->timeptr = NULL;
290     return this;
291 }
292
293 /* ??0_Timevec@std@@QAE@PAX@Z */
294 /* ??0_Timevec@std@@QEAA@PEAX@Z */
295 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
296 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
297 {
298     TRACE("(%p %p)\n", this, timeptr);
299     this->timeptr = timeptr;
300     return this;
301 }
302
303 /* ??_F_Timevec@std@@QAEXXZ */
304 /* ??_F_Timevec@std@@QEAAXXZ */
305 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
306 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
307 {
308     TRACE("(%p)\n", this);
309     this->timeptr = NULL;
310     return this;
311 }
312
313 /* ??1_Timevec@std@@QAE@XZ */
314 /* ??1_Timevec@std@@QEAA@XZ */
315 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
316 void __thiscall _Timevec_dtor(_Timevec *this)
317 {
318     TRACE("(%p)\n", this);
319     free(this->timeptr);
320 }
321
322 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
323 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
324 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
325 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
326 {
327     TRACE("(%p %p)\n", this, right);
328     this->timeptr = right->timeptr;
329     right->timeptr = NULL;
330     return this;
331 }
332
333 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
334 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
335 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
336 void* __thiscall _Timevec__Getptr(_Timevec *this)
337 {
338     TRACE("(%p)\n", this);
339     return this->timeptr;
340 }
341
342 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
343 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
344 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
345 {
346     const char *locale = NULL;
347
348     /* This function is probably modifying more global objects */
349     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
350
351     if(!locstr)
352         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
353
354     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
355     MSVCP_basic_string_char_ctor_cstr(&locinfo->days, "");
356     MSVCP_basic_string_char_ctor_cstr(&locinfo->months, "");
357     MSVCP_basic_string_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
358
359     if(category)
360         locale = setlocale(LC_ALL, locstr);
361     else
362         locale = setlocale(LC_ALL, NULL);
363
364     if(locale)
365         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
366     else
367         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
368
369     return locinfo;
370 }
371
372 /* ??0_Locinfo@std@@QAE@HPBD@Z */
373 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
374 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
375 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
376 {
377     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
378 }
379
380 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
381 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
382 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_bstr(_Locinfo *locinfo, const basic_string_char *locstr)
383 {
384     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
385 }
386
387 /* ??0_Locinfo@std@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
388 /* ??0_Locinfo@std@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
389 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_bstr, 8)
390 _Locinfo* __thiscall _Locinfo_ctor_bstr(_Locinfo *this, const basic_string_char *locstr)
391 {
392     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
393 }
394
395 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z */
396 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@PEBD@Z */
397 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cstr(_Locinfo *locinfo, const char *locstr)
398 {
399     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, locstr);
400 }
401
402 /* ??0_Locinfo@std@@QAE@PBD@Z */
403 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
404 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
405 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
406 {
407     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
408 }
409
410 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
411 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
412 void __cdecl _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
413 {
414     TRACE("(%p)\n", locinfo);
415
416     setlocale(LC_ALL, MSVCP_basic_string_char_c_str(&locinfo->oldlocname));
417     MSVCP_basic_string_char_dtor(&locinfo->days);
418     MSVCP_basic_string_char_dtor(&locinfo->months);
419     MSVCP_basic_string_char_dtor(&locinfo->oldlocname);
420     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
421     _Lockit_dtor(&locinfo->lock);
422 }
423
424 /* ??_F_Locinfo@std@@QAEXXZ */
425 /* ??_F_Locinfo@std@@QEAAXXZ */
426 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
427 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
428 {
429     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
430 }
431
432 /* ??1_Locinfo@std@@QAE@XZ */
433 /* ??1_Locinfo@std@@QEAA@XZ */
434 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
435 void __thiscall _Locinfo_dtor(_Locinfo *this)
436 {
437     _Locinfo__Locinfo_dtor(this);
438 }
439
440 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
441 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
442 _Locinfo* __cdecl _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
443 {
444     const char *locale = NULL;
445
446     /* This function is probably modifying more global objects */
447     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
448     if(!locstr)
449         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
450
451     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
452
453     if(category)
454         locale = setlocale(LC_ALL, locstr);
455     else
456         locale = setlocale(LC_ALL, NULL);
457
458     if(locale)
459         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
460     else
461         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
462
463     return locinfo;
464 }
465
466 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
467 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
468 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
469 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
470 {
471     return _Locinfo__Locinfo_Addcats(this, category, locstr);
472 }
473
474 /* _Getcoll */
475 _Collvec __cdecl _Getcoll(void)
476 {
477     _Collvec ret;
478     _locale_t locale = _get_current_locale();
479
480     TRACE("\n");
481
482     ret.page = locale->locinfo->lc_collate_cp;
483     ret.handle = locale->locinfo->lc_handle[LC_COLLATE];
484     _free_locale(locale);
485     return ret;
486 }
487
488 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
489 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
490 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 8)
491 _Collvec* __thiscall _Locinfo__Getcoll(const _Locinfo *this, _Collvec *ret)
492 {
493     *ret = _Getcoll();
494     return ret;
495 }
496
497 /* _Getctype */
498 _Ctypevec __cdecl _Getctype(void)
499 {
500     _Ctypevec ret;
501     _locale_t locale = _get_current_locale();
502     short *table;
503
504     TRACE("\n");
505
506     ret.page = locale->locinfo->lc_codepage;
507     ret.handle = locale->locinfo->lc_handle[LC_COLLATE];
508     ret.delfl = TRUE;
509     table = malloc(sizeof(short[256]));
510     if(!table) {
511         _free_locale(locale);
512         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
513     }
514     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
515     ret.table = table;
516     _free_locale(locale);
517     return ret;
518 }
519
520 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
521 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
522 DEFINE_THISCALL_WRAPPER(_Locinfo__Getctype, 8)
523 _Ctypevec* __thiscall _Locinfo__Getctype(const _Locinfo *this, _Ctypevec *ret)
524 {
525     *ret = _Getctype();
526     return ret;
527 }
528
529 /* _Getcvt */
530 _Cvtvec __cdecl _Getcvt(void)
531 {
532     _Cvtvec ret;
533     _locale_t locale = _get_current_locale();
534
535     TRACE("\n");
536
537     ret.page = locale->locinfo->lc_codepage;
538     ret.handle = locale->locinfo->lc_handle[LC_CTYPE];
539     _free_locale(locale);
540     return ret;
541 }
542
543 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
544 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
545 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 8)
546 _Cvtvec* __thiscall _Locinfo__Getcvt(const _Locinfo *this, _Cvtvec *ret)
547 {
548     *ret = _Getcvt();
549     return ret;
550 }
551
552 /* ?_Getdateorder@_Locinfo@std@@QBEHXZ */
553 /* ?_Getdateorder@_Locinfo@std@@QEBAHXZ */
554 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdateorder, 4)
555 int __thiscall _Locinfo__Getdateorder(const _Locinfo *this)
556 {
557     FIXME("(%p) stub\n", this);
558     return 0;
559 }
560
561 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
562 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
563 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
564 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
565 {
566     char *days = _Getdays();
567
568     TRACE("(%p)\n", this);
569
570     if(days) {
571         MSVCP_basic_string_char_dtor(&this->days);
572         MSVCP_basic_string_char_ctor_cstr(&this->days, days);
573         free(days);
574     }
575
576     return this->days.size ? MSVCP_basic_string_char_c_str(&this->days) :
577         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
578 }
579
580 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
581 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
582 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
583 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
584 {
585     char *months = _Getmonths();
586
587     TRACE("(%p)\n", this);
588
589     if(months) {
590         MSVCP_basic_string_char_dtor(&this->months);
591         MSVCP_basic_string_char_ctor_cstr(&this->months, months);
592         free(months);
593     }
594
595     return this->months.size ? MSVCP_basic_string_char_c_str(&this->months) :
596         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
597         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
598 }
599
600 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
601 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
602 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
603 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
604 {
605     TRACE("(%p)\n", this);
606     return "false";
607 }
608
609 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
610 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
611 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
612 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
613 {
614     TRACE("(%p)\n", this);
615     return "true";
616 }
617
618 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
619 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
620 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
621 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
622 {
623     TRACE("(%p)\n", this);
624     return localeconv();
625 }
626
627 /* ?_Getname@_Locinfo@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
628 /* ?_Getname@_Locinfo@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
629 DEFINE_THISCALL_WRAPPER(_Locinfo__Getname, 8)
630 basic_string_char* __thiscall _Locinfo__Getname(const _Locinfo *this, basic_string_char *ret)
631 {
632     TRACE("(%p)\n", this);
633
634     MSVCP_basic_string_char_copy_ctor(ret, &this->newlocname);
635     return ret;
636 }
637
638 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
639 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
640 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 8)
641 _Timevec*__thiscall _Locinfo__Gettnames(const _Locinfo *this, _Timevec *ret)
642 {
643     TRACE("(%p)\n", this);
644
645     _Timevec_ctor_timeptr(ret, _Gettnames());
646     return ret;
647 }
648
649 static const type_info locale_facet_type_info = {
650     MSVCP_locale_facet_vtable,
651     NULL,
652     ".?AVfacet@locale@std@@"
653 };
654
655 /* ?id@?$collate@D@std@@2V0locale@2@A */
656 locale_id collate_char_id = {0};
657
658 /* ??_7?$collate@D@std@@6B@ */
659 extern const vtable_ptr MSVCP_collate_char_vtable;
660
661 /* ?_Init@?$collate@D@std@@IAEXABV_Locinfo@2@@Z */
662 /* ?_Init@?$collate@D@std@@IEAAXAEBV_Locinfo@2@@Z */
663 DEFINE_THISCALL_WRAPPER(collate_char__Init, 8)
664 void __thiscall collate_char__Init(collate *this, const _Locinfo *locinfo)
665 {
666     TRACE("(%p %p)\n", this, locinfo);
667     _Locinfo__Getcoll(locinfo, &this->coll);
668 }
669
670 /* ??0?$collate@D@std@@IAE@PBDI@Z */
671 /* ??0?$collate@D@std@@IEAA@PEBD_K@Z */
672 DEFINE_THISCALL_WRAPPER(collate_char_ctor_name, 12)
673 collate* __thiscall collate_char_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
674 {
675     _Locinfo locinfo;
676
677     TRACE("(%p %s %lu)\n", this, name, refs);
678
679     locale_facet_ctor_refs(&this->facet, refs);
680     this->facet.vtable = &MSVCP_collate_char_vtable;
681
682     _Locinfo_ctor_cstr(&locinfo, name);
683     collate_char__Init(this, &locinfo);
684     _Locinfo_dtor(&locinfo);
685     return this;
686 }
687
688 /* ??0?$collate@D@std@@QAE@ABV_Locinfo@1@I@Z */
689 /* ??0?$collate@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
690 DEFINE_THISCALL_WRAPPER(collate_char_ctor_locinfo, 12)
691 collate* __thiscall collate_char_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
692 {
693     TRACE("(%p %p %lu)\n", this, locinfo, refs);
694
695     locale_facet_ctor_refs(&this->facet, refs);
696     this->facet.vtable = &MSVCP_collate_char_vtable;
697     collate_char__Init(this, locinfo);
698     return this;
699 }
700
701 /* ??0?$collate@D@std@@QAE@I@Z */
702 /* ??0?$collate@D@std@@QEAA@_K@Z */
703 DEFINE_THISCALL_WRAPPER(collate_char_ctor_refs, 8)
704 collate* __thiscall collate_char_ctor_refs(collate *this, MSVCP_size_t refs)
705 {
706     return collate_char_ctor_name(this, "C", refs);
707 }
708
709 /* ??1?$collate@D@std@@MAE@XZ */
710 /* ??1?$collate@D@std@@MEAA@XZ */
711 DEFINE_THISCALL_WRAPPER(collate_char_dtor, 4)
712 void __thiscall collate_char_dtor(collate *this)
713 {
714     TRACE("(%p)\n", this);
715 }
716
717 DEFINE_THISCALL_WRAPPER(MSVCP_collate_char_vector_dtor, 8)
718 collate* __thiscall MSVCP_collate_char_vector_dtor(collate *this, unsigned int flags)
719 {
720     TRACE("(%p %x)\n", this, flags);
721     if(flags & 2) {
722         /* we have an array, with the number of elements stored before the first object */
723         int i, *ptr = (int *)this-1;
724
725         for(i=*ptr-1; i>=0; i--)
726             collate_char_dtor(this+i);
727         MSVCRT_operator_delete(ptr);
728     } else {
729         collate_char_dtor(this);
730         if(flags & 1)
731             MSVCRT_operator_delete(this);
732     }
733
734     return this;
735 }
736
737 /* ??_F?$collate@D@std@@QAEXXZ */
738 /* ??_F?$collate@D@std@@QEAAXXZ */
739 DEFINE_THISCALL_WRAPPER(collate_char_ctor, 4)
740 collate* __thiscall collate_char_ctor(collate *this)
741 {
742     return collate_char_ctor_name(this, "C", 0);
743 }
744
745 /* ?_Getcat@?$collate@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
746 /* ?_Getcat@?$collate@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
747 MSVCP_size_t __cdecl collate_char__Getcat(const locale_facet **facet, const locale *loc)
748 {
749     TRACE("(%p %p)\n", facet, loc);
750
751     if(facet && !*facet) {
752         *facet = MSVCRT_operator_new(sizeof(collate));
753         if(!*facet) {
754             ERR("Out of memory\n");
755             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
756             return 0;
757         }
758         collate_char_ctor_name((collate*)*facet,
759                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
760     }
761
762     return LC_COLLATE;
763 }
764
765 /* _Strcoll */
766 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
767         const char *last2, const _Collvec *coll)
768 {
769     LCID lcid;
770
771     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
772
773     if(coll)
774         lcid = coll->handle;
775     else
776         lcid = ___lc_handle_func()[LC_COLLATE];
777     return CompareStringA(lcid, 0, first1, last1-first1, first2, last2-first2)-2;
778 }
779
780 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
781 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
782 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
783 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
784         (const collate*, const char*, const char*, const char*, const char*), \
785         (this, first1, last1, first2, last2))
786 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
787         const char *last1, const char *first2, const char *last2)
788 {
789     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
790     return _Strcoll(first1, last1, first2, last2, &this->coll);
791 }
792
793 /* ?compare@?$collate@D@std@@QBEHPBD000@Z */
794 /* ?compare@?$collate@D@std@@QEBAHPEBD000@Z */
795 DEFINE_THISCALL_WRAPPER(collate_char_compare, 20)
796 int __thiscall collate_char_compare(const collate *this, const char *first1,
797         const char *last1, const char *first2, const char *last2)
798 {
799     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
800     return call_collate_char_do_compare(this, first1, last1, first2, last2);
801 }
802
803 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
804 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
805 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
806 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
807         (const collate*, const char*, const char*), (this, first, last))
808 LONG __thiscall collate_char_do_hash(const collate *this,
809         const char *first, const char *last)
810 {
811     ULONG ret = 0;
812
813     TRACE("(%p %p %p)\n", this, first, last);
814
815     for(; first<last; first++)
816         ret = (ret<<8 | ret>>24) + *first;
817     return ret;
818 }
819
820 /* ?hash@?$collate@D@std@@QBEJPBD0@Z */
821 /* ?hash@?$collate@D@std@@QEBAJPEBD0@Z */
822 DEFINE_THISCALL_WRAPPER(collate_char_hash, 12)
823 LONG __thiscall collate_char_hash(const collate *this,
824         const char *first, const char *last)
825 {
826     TRACE("(%p %p %p)\n", this, first, last);
827     return call_collate_char_do_hash(this, first, last);
828 }
829
830 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
831 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
832 DEFINE_THISCALL_WRAPPER(collate_char_do_transform, 16)
833 basic_string_char* __thiscall collate_char_do_transform(const collate *this,
834         basic_string_char *ret, const char *first, const char *last)
835 {
836     FIXME("(%p %p %p) stub\n", this, first, last);
837     return ret;
838 }
839
840 /* ?transform@?$collate@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
841 /* ?transform@?$collate@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
842 DEFINE_THISCALL_WRAPPER(collate_char_transform, 16)
843 basic_string_char* __thiscall collate_char_transform(const collate *this,
844         basic_string_char *ret, const char *first, const char *last)
845 {
846     FIXME("(%p %p %p) stub\n", this, first, last);
847     return ret;
848 }
849
850 /* ?id@?$collate@_W@std@@2V0locale@2@A */
851 locale_id collate_wchar_id = {0};
852 /* ?id@?$collate@G@std@@2V0locale@2@A */
853 locale_id collate_short_id = {0};
854
855 /* ??_7?$collate@_W@std@@6B@ */
856 extern const vtable_ptr MSVCP_collate_wchar_vtable;
857 /* ??_7?$collate@G@std@@6B@ */
858 extern const vtable_ptr MSVCP_collate_short_vtable;
859
860 /* ?_Init@?$collate@_W@std@@IAEXABV_Locinfo@2@@Z */
861 /* ?_Init@?$collate@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
862 /* ?_Init@?$collate@G@std@@IAEXABV_Locinfo@2@@Z */
863 /* ?_Init@?$collate@G@std@@IEAAXAEBV_Locinfo@2@@Z */
864 DEFINE_THISCALL_WRAPPER(collate_wchar__Init, 8)
865 void __thiscall collate_wchar__Init(collate *this, const _Locinfo *locinfo)
866 {
867     TRACE("(%p %p)\n", this, locinfo);
868     _Locinfo__Getcoll(locinfo, &this->coll);
869 }
870
871 /* ??0?$collate@_W@std@@IAE@PBDI@Z */
872 /* ??0?$collate@_W@std@@IEAA@PEBD_K@Z */
873 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_name, 12)
874 collate* __thiscall collate_wchar_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
875 {
876     _Locinfo locinfo;
877
878     TRACE("(%p %s %lu)\n", this, name, refs);
879
880     locale_facet_ctor_refs(&this->facet, refs);
881     this->facet.vtable = &MSVCP_collate_wchar_vtable;
882
883     _Locinfo_ctor_cstr(&locinfo, name);
884     collate_wchar__Init(this, &locinfo);
885     _Locinfo_dtor(&locinfo);
886     return this;
887 }
888
889 /* ??0?$collate@G@std@@IAE@PBDI@Z */
890 /* ??0?$collate@G@std@@IEAA@PEBD_K@Z */
891 DEFINE_THISCALL_WRAPPER(collate_short_ctor_name, 12)
892 collate* __thiscall collate_short_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
893 {
894     collate *ret = collate_wchar_ctor_name(this, name, refs);
895     ret->facet.vtable = &MSVCP_collate_short_vtable;
896     return ret;
897 }
898
899 /* ??0?$collate@_W@std@@QAE@ABV_Locinfo@1@I@Z */
900 /* ??0?$collate@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
901 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_locinfo, 12)
902 collate* __thiscall collate_wchar_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
903 {
904     TRACE("(%p %p %lu)\n", this, locinfo, refs);
905
906     locale_facet_ctor_refs(&this->facet, refs);
907     this->facet.vtable = &MSVCP_collate_wchar_vtable;
908     collate_wchar__Init(this, locinfo);
909     return this;
910 }
911
912 /* ??0?$collate@G@std@@QAE@ABV_Locinfo@1@I@Z */
913 /* ??0?$collate@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
914 DEFINE_THISCALL_WRAPPER(collate_short_ctor_locinfo, 12)
915 collate* __thiscall collate_short_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
916 {
917     collate *ret = collate_wchar_ctor_locinfo(this, locinfo, refs);
918     ret->facet.vtable = &MSVCP_collate_short_vtable;
919     return ret;
920 }
921
922 /* ??0?$collate@_W@std@@QAE@I@Z */
923 /* ??0?$collate@_W@std@@QEAA@_K@Z */
924 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_refs, 8)
925 collate* __thiscall collate_wchar_ctor_refs(collate *this, MSVCP_size_t refs)
926 {
927     return collate_wchar_ctor_name(this, "C", refs);
928 }
929
930 /* ??0?$collate@G@std@@QAE@I@Z */
931 /* ??0?$collate@G@std@@QEAA@_K@Z */
932 DEFINE_THISCALL_WRAPPER(collate_short_ctor_refs, 8)
933 collate* __thiscall collate_short_ctor_refs(collate *this, MSVCP_size_t refs)
934 {
935     collate *ret = collate_wchar_ctor_refs(this, refs);
936     ret->facet.vtable = &MSVCP_collate_short_vtable;
937     return ret;
938 }
939
940 /* ??1?$collate@_W@std@@MAE@XZ */
941 /* ??1?$collate@_W@std@@MEAA@XZ */
942 /* ??1?$collate@G@std@@MAE@XZ */
943 /* ??1?$collate@G@std@@MEAA@XZ */
944 DEFINE_THISCALL_WRAPPER(collate_wchar_dtor, 4)
945 void __thiscall collate_wchar_dtor(collate *this)
946 {
947     TRACE("(%p)\n", this);
948 }
949
950 DEFINE_THISCALL_WRAPPER(MSVCP_collate_wchar_vector_dtor, 8)
951 collate* __thiscall MSVCP_collate_wchar_vector_dtor(collate *this, unsigned int flags)
952 {
953     TRACE("(%p %x)\n", this, flags);
954     if(flags & 2) {
955         /* we have an array, with the number of elements stored before the first object */
956         int i, *ptr = (int *)this-1;
957
958         for(i=*ptr-1; i>=0; i--)
959             collate_wchar_dtor(this+i);
960         MSVCRT_operator_delete(ptr);
961     } else {
962         collate_wchar_dtor(this);
963         if(flags & 1)
964             MSVCRT_operator_delete(this);
965     }
966
967     return this;
968 }
969
970 DEFINE_THISCALL_WRAPPER(MSVCP_collate_short_vector_dtor, 8)
971 collate* __thiscall MSVCP_collate_short_vector_dtor(collate *this, unsigned int flags)
972 {
973     return MSVCP_collate_wchar_vector_dtor(this, flags);
974 }
975
976 /* ??_F?$collate@_W@std@@QAEXXZ */
977 /* ??_F?$collate@_W@std@@QEAAXXZ */
978 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor, 4)
979 collate* __thiscall collate_wchar_ctor(collate *this)
980 {
981     return collate_wchar_ctor_name(this, "C", 0);
982 }
983
984 /* ??_F?$collate@G@std@@QAEXXZ */
985 /* ??_F?$collate@G@std@@QEAAXXZ */
986 DEFINE_THISCALL_WRAPPER(collate_short_ctor, 4)
987 collate* __thiscall collate_short_ctor(collate *this)
988 {
989     collate *ret = collate_wchar_ctor(this);
990     ret->facet.vtable = &MSVCP_collate_short_vtable;
991     return ret;
992 }
993
994 /* ?_Getcat@?$collate@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
995 /* ?_Getcat@?$collate@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
996 MSVCP_size_t __cdecl collate_wchar__Getcat(const locale_facet **facet, const locale *loc)
997 {
998     TRACE("(%p %p)\n", facet, loc);
999
1000     if(facet && !*facet) {
1001         *facet = MSVCRT_operator_new(sizeof(collate));
1002         if(!*facet) {
1003             ERR("Out of memory\n");
1004             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1005             return 0;
1006         }
1007         collate_wchar_ctor_name((collate*)*facet,
1008                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
1009     }
1010
1011     return LC_COLLATE;
1012 }
1013
1014 /* ?_Getcat@?$collate@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1015 /* ?_Getcat@?$collate@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1016 MSVCP_size_t __cdecl collate_short__Getcat(const locale_facet **facet, const locale *loc)
1017 {
1018     if(facet && !*facet) {
1019         collate_wchar__Getcat(facet, loc);
1020         (*(locale_facet**)facet)->vtable = &MSVCP_collate_short_vtable;
1021     }
1022
1023     return LC_COLLATE;
1024 }
1025
1026 /* _Wcscoll */
1027 int __cdecl _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
1028         const wchar_t *last2, const _Collvec *coll)
1029 {
1030     LCID lcid;
1031
1032     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
1033
1034     if(coll)
1035         lcid = coll->handle;
1036     else
1037         lcid = ___lc_handle_func()[LC_COLLATE];
1038     return CompareStringW(lcid, 0, first1, last1-first1, first2, last2-first2)-2;
1039 }
1040
1041 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
1042 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
1043 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
1044 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
1045 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
1046 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
1047         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
1048         (this, first1, last1, first2, last2))
1049 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
1050         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1051 {
1052     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1053     return _Wcscoll(first1, last1, first2, last2, &this->coll);
1054 }
1055
1056 /* ?compare@?$collate@_W@std@@QBEHPB_W000@Z */
1057 /* ?compare@?$collate@_W@std@@QEBAHPEB_W000@Z */
1058 /* ?compare@?$collate@G@std@@QBEHPBG000@Z */
1059 /* ?compare@?$collate@G@std@@QEBAHPEBG000@Z */
1060 DEFINE_THISCALL_WRAPPER(collate_wchar_compare, 20)
1061 int __thiscall collate_wchar_compare(const collate *this, const wchar_t *first1,
1062         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1063 {
1064     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1065     return call_collate_wchar_do_compare(this, first1, last1, first2, last2);
1066 }
1067
1068 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
1069 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
1070 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
1071 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
1072 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
1073 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
1074         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
1075 LONG __thiscall collate_wchar_do_hash(const collate *this,
1076         const wchar_t *first, const wchar_t *last)
1077 {
1078     ULONG ret = 0;
1079
1080     TRACE("(%p %p %p)\n", this, first, last);
1081
1082     for(; first<last; first++)
1083         ret = (ret<<8 | ret>>24) + *first;
1084     return ret;
1085 }
1086
1087 /* ?hash@?$collate@_W@std@@QBEJPB_W0@Z */
1088 /* ?hash@?$collate@_W@std@@QEBAJPEB_W0@Z */
1089 /* ?hash@?$collate@G@std@@QBEJPBG0@Z */
1090 /* ?hash@?$collate@G@std@@QEBAJPEBG0@Z */
1091 DEFINE_THISCALL_WRAPPER(collate_wchar_hash, 12)
1092 LONG __thiscall collate_wchar_hash(const collate *this,
1093         const wchar_t *first, const wchar_t *last)
1094 {
1095     TRACE("(%p %p %p)\n", this, first, last);
1096     return call_collate_wchar_do_hash(this, first, last);
1097 }
1098
1099 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1100 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1101 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1102 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1103 DEFINE_THISCALL_WRAPPER(collate_wchar_do_transform, 16)
1104 basic_string_wchar* __thiscall collate_wchar_do_transform(const collate *this,
1105         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1106 {
1107     FIXME("(%p %p %p) stub\n", this, first, last);
1108     return ret;
1109 }
1110
1111 /* ?transform@?$collate@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1112 /* ?transform@?$collate@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1113 /* ?transform@?$collate@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1114 /* ?transform@?$collate@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1115 DEFINE_THISCALL_WRAPPER(collate_wchar_transform, 16)
1116 basic_string_wchar* __thiscall collate_wchar_transform(const collate *this,
1117         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1118 {
1119     FIXME("(%p %p %p) stub\n", this, first, last);
1120     return ret;
1121 }
1122
1123 /* ??_7ctype_base@std@@6B@ */
1124 extern const vtable_ptr MSVCP_ctype_base_vtable;
1125
1126 /* ??0ctype_base@std@@QAE@I@Z */
1127 /* ??0ctype_base@std@@QEAA@_K@Z */
1128 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
1129 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
1130 {
1131     TRACE("(%p %lu)\n", this, refs);
1132     locale_facet_ctor_refs(&this->facet, refs);
1133     this->facet.vtable = &MSVCP_ctype_base_vtable;
1134     return this;
1135 }
1136
1137 /* ??_Fctype_base@std@@QAEXXZ */
1138 /* ??_Fctype_base@std@@QEAAXXZ */
1139 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
1140 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
1141 {
1142     TRACE("(%p)\n", this);
1143     locale_facet_ctor_refs(&this->facet, 0);
1144     this->facet.vtable = &MSVCP_ctype_base_vtable;
1145     return this;
1146 }
1147
1148 /* ??1ctype_base@std@@UAE@XZ */
1149 /* ??1ctype_base@std@@UEAA@XZ */
1150 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
1151 void __thiscall ctype_base_dtor(ctype_base *this)
1152 {
1153     TRACE("(%p)\n", this);
1154 }
1155
1156 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_base_vector_dtor, 8)
1157 ctype_base* __thiscall MSVCP_ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
1158 {
1159     TRACE("(%p %x)\n", this, flags);
1160     if(flags & 2) {
1161         /* we have an array, with the number of elements stored before the first object */
1162         int i, *ptr = (int *)this-1;
1163
1164         for(i=*ptr-1; i>=0; i--)
1165             ctype_base_dtor(this+i);
1166         MSVCRT_operator_delete(ptr);
1167     } else {
1168         ctype_base_dtor(this);
1169         if(flags & 1)
1170             MSVCRT_operator_delete(this);
1171     }
1172
1173     return this;
1174 }
1175
1176 /* ?_Xran@ctype_base@std@@KAXXZ */
1177 void __cdecl ctype_base__Xran(void)
1178 {
1179     throw_exception(EXCEPTION_OUT_OF_RANGE, "out of range in ctype<T>");
1180 }
1181
1182 /* ?id@?$ctype@D@std@@2V0locale@2@A */
1183 locale_id ctype_char_id = {0};
1184 /* ?table_size@?$ctype@D@std@@2IB */
1185 /* ?table_size@?$ctype@D@std@@2_KB */
1186 MSVCP_size_t ctype_char_table_size = 256;
1187
1188 /* ??_7?$ctype@D@std@@6B@ */
1189 extern const vtable_ptr MSVCP_ctype_char_vtable;
1190
1191 /* ?_Id_func@?$ctype@D@std@@SAAAVid@locale@2@XZ */
1192 /* ?_Id_func@?$ctype@D@std@@SAAEAVid@locale@2@XZ */
1193 locale_id* __cdecl ctype_char__Id_func(void)
1194 {
1195     TRACE("()\n");
1196     return &ctype_char_id;
1197 }
1198
1199 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
1200 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
1201 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
1202 void __thiscall ctype_char__Init(ctype_char *this, _Locinfo *locinfo)
1203 {
1204     TRACE("(%p %p)\n", this, locinfo);
1205     _Locinfo__Getctype(locinfo, &this->ctype);
1206 }
1207
1208 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
1209 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
1210 DEFINE_THISCALL_WRAPPER(ctype_char__Tidy, 4)
1211 void __thiscall ctype_char__Tidy(ctype_char *this)
1212 {
1213     TRACE("(%p)\n", this);
1214
1215     if(this->ctype.delfl)
1216         free((short*)this->ctype.table);
1217 }
1218
1219 /* ?classic_table@?$ctype@D@std@@KAPBFXZ */
1220 /* ?classic_table@?$ctype@D@std@@KAPEBFXZ */
1221 const short* __cdecl ctype_char_classic_table(void)
1222 {
1223     TRACE("()\n");
1224     return &((short*)GetProcAddress(GetModuleHandleA("msvcrt.dll"), "_ctype"))[1];
1225 }
1226
1227 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
1228 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1229 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
1230 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
1231         _Locinfo *locinfo, MSVCP_size_t refs)
1232 {
1233     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1234     ctype_base_ctor_refs(&this->base, refs);
1235     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1236     ctype_char__Init(this, locinfo);
1237     return this;
1238 }
1239
1240 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
1241 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
1242 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
1243 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
1244         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
1245 {
1246     _Locinfo locinfo;
1247
1248     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
1249
1250     ctype_base_ctor_refs(&this->base, refs);
1251     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1252
1253     _Locinfo_ctor(&locinfo);
1254     ctype_char__Init(this, &locinfo);
1255     _Locinfo_dtor(&locinfo);
1256
1257     if(table) {
1258         ctype_char__Tidy(this);
1259         this->ctype.table = table;
1260         this->ctype.delfl = delete;
1261     }
1262     return this;
1263 }
1264
1265 /* ??_F?$ctype@D@std@@QAEXXZ */
1266 /* ??_F?$ctype@D@std@@QEAAXXZ */
1267 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
1268 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
1269 {
1270     return ctype_char_ctor_table(this, NULL, FALSE, 0);
1271 }
1272
1273 /* ??1?$ctype@D@std@@MAE@XZ */
1274 /* ??1?$ctype@D@std@@MEAA@XZ */
1275 DEFINE_THISCALL_WRAPPER(ctype_char_dtor, 4)
1276 void __thiscall ctype_char_dtor(ctype_char *this)
1277 {
1278     TRACE("(%p)\n", this);
1279     ctype_char__Tidy(this);
1280 }
1281
1282 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_char_vector_dtor, 8)
1283 ctype_char* __thiscall MSVCP_ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1284 {
1285     TRACE("(%p %x)\n", this, flags);
1286     if(flags & 2) {
1287         /* we have an array, with the number of elements stored before the first object */
1288         int i, *ptr = (int *)this-1;
1289
1290         for(i=*ptr-1; i>=0; i--)
1291             ctype_char_dtor(this+i);
1292         MSVCRT_operator_delete(ptr);
1293     } else {
1294         ctype_char_dtor(this);
1295         if(flags & 1)
1296             MSVCRT_operator_delete(this);
1297     }
1298
1299     return this;
1300 }
1301
1302 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1303 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1304 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1305 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 36, \
1306         char, (const ctype_char*, char, char), (this, ch, unused))
1307 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1308 {
1309     TRACE("(%p %c %c)\n", this, ch, unused);
1310     return ch;
1311 }
1312
1313 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1314 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1315 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1316 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 32, \
1317         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1318         (this, first, last, unused, dest))
1319 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1320         const char *first, const char *last, char unused, char *dest)
1321 {
1322     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1323     memcpy(dest, first, last-first);
1324     return last;
1325 }
1326
1327 /* ?_Do_narrow_s@?$ctype@D@std@@MBEPBDPBD0DPADI@Z */
1328 /* ?_Do_narrow_s@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD_K@Z */
1329 DEFINE_THISCALL_WRAPPER(ctype_char__Do_narrow_s, 24)
1330 #define call_ctype_char__Do_narrow_s(this, first, last, unused, dest, size) CALL_VTBL_FUNC(this, 40, \
1331         const char*, (const ctype_char*, const char*, const char*, char, char*, MSVCP_size_t), \
1332         (this, first, last, unused, dest, size))
1333 const char* __thiscall ctype_char__Do_narrow_s(const ctype_char *this, const char *first,
1334         const char *last, char unused, char *dest, MSVCP_size_t size)
1335 {
1336     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1337     memcpy_s(dest, size, first, last-first);
1338     return last;
1339 }
1340
1341 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1342 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1343 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1344 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1345 {
1346     TRACE("(%p %c %c)\n", this, ch, dflt);
1347     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1348 }
1349
1350 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1351 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1352 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1353 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1354         const char *first, const char *last, char dflt, char *dest)
1355 {
1356     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1357     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1358 }
1359
1360 /* ?_Narrow_s@?$ctype@D@std@@QBEPBDPBD0DPADI@Z */
1361 /* ?_Narrow_s@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD_K@Z */
1362 DEFINE_THISCALL_WRAPPER(ctype_char__Narrow_s, 24)
1363 const char* __thiscall ctype_char__Narrow_s(const ctype_char *this, const char *first,
1364         const char *last, char dflt, char *dest, MSVCP_size_t size)
1365 {
1366     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1367     return call_ctype_char__Do_narrow_s(this, first, last, dflt, dest, size);
1368 }
1369
1370 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1371 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1372 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1373 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1374         char, (const ctype_char*, char), (this, ch))
1375 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1376 {
1377     TRACE("(%p %c)\n", this, ch);
1378     return ch;
1379 }
1380
1381 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1382 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1383 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1384 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1385         const char*, (const ctype_char*, const char*, const char*, char*), \
1386         (this, first, last, dest))
1387 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1388         const char *first, const char *last, char *dest)
1389 {
1390     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1391     memcpy(dest, first, last-first);
1392     return last;
1393 }
1394
1395 /* ?_Do_widen_s@?$ctype@D@std@@MBEPBDPBD0PADI@Z */
1396 /* ?_Do_widen_s@?$ctype@D@std@@MEBAPEBDPEBD0PEAD_K@Z */
1397 DEFINE_THISCALL_WRAPPER(ctype_char__Do_widen_s, 20)
1398 #define call_ctype_char__Do_widen_s(this, first, last, dest, size) CALL_VTBL_FUNC(this, 28, \
1399         const char*, (const ctype_char*, const char*, const char*, char*, MSVCP_size_t), \
1400         (this, first, last, dest, size))
1401 const char* __thiscall ctype_char__Do_widen_s(const ctype_char *this,
1402         const char *first, const char *last, char *dest, MSVCP_size_t size)
1403 {
1404     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1405     memcpy_s(dest, size, first, last-first);
1406     return last;
1407 }
1408
1409 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1410 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1411 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1412 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1413 {
1414     TRACE("(%p %c)\n", this, ch);
1415     return call_ctype_char_do_widen_ch(this, ch);
1416 }
1417
1418 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1419 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1420 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1421 const char* __thiscall ctype_char_widen(const ctype_char *this,
1422         const char *first, const char *last, char *dest)
1423 {
1424     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1425     return call_ctype_char_do_widen(this, first, last, dest);
1426 }
1427
1428 /* ?_Widen_s@?$ctype@D@std@@QBEPBDPBD0PADI@Z */
1429 /* ?_Widen_s@?$ctype@D@std@@QEBAPEBDPEBD0PEAD_K@Z */
1430 DEFINE_THISCALL_WRAPPER(ctype_char__Widen_s, 20)
1431 const char* __thiscall ctype_char__Widen_s(const ctype_char *this,
1432         const char *first, const char *last, char *dest, MSVCP_size_t size)
1433 {
1434     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1435     return call_ctype_char__Do_widen_s(this, first, last, dest, size);
1436 }
1437
1438 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1439 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1440 MSVCP_size_t __cdecl ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1441 {
1442     TRACE("(%p %p)\n", facet, loc);
1443
1444     if(facet && !*facet) {
1445         _Locinfo locinfo;
1446
1447         *facet = MSVCRT_operator_new(sizeof(ctype_char));
1448         if(!*facet) {
1449             ERR("Out of memory\n");
1450             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1451             return 0;
1452         }
1453
1454         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
1455         ctype_char_ctor_locinfo((ctype_char*)*facet, &locinfo, 0);
1456         _Locinfo_dtor(&locinfo);
1457     }
1458
1459     return LC_CTYPE;
1460 }
1461
1462 /* _Tolower */
1463 int __cdecl _Tolower(int ch, const _Ctypevec *ctype)
1464 {
1465     unsigned int cp;
1466
1467     TRACE("%d %p\n", ch, ctype);
1468
1469     if(ctype)
1470         cp = ctype->page;
1471     else
1472         cp = ___lc_codepage_func();
1473
1474     /* Don't convert to unicode in case of C locale */
1475     if(!cp) {
1476         if(ch>='A' && ch<='Z')
1477             ch = ch-'A'+'a';
1478         return ch;
1479     } else {
1480         WCHAR wide, lower;
1481         char str[2];
1482         int size;
1483
1484         if(ch > 255) {
1485             str[0] = (ch>>8) & 255;
1486             str[1] = ch & 255;
1487             size = 2;
1488         } else {
1489             str[0] = ch & 255;
1490             size = 1;
1491         }
1492
1493         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1494             return ch;
1495
1496         lower = tolowerW(wide);
1497         if(lower == wide)
1498             return ch;
1499
1500         WideCharToMultiByte(cp, 0, &lower, 1, str, 2, NULL, NULL);
1501
1502         return str[0] + (str[1]<<8);
1503     }
1504 }
1505
1506 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1507 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1508 #define call_ctype_char_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 8, \
1509         char, (const ctype_char*, char), (this, ch))
1510 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1511 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1512 {
1513     TRACE("(%p %c)\n", this, ch);
1514     return _Tolower(ch, &this->ctype);
1515 }
1516
1517 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1518 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1519 #define call_ctype_char_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 4, \
1520         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1521 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1522 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1523 {
1524     TRACE("(%p %p %p)\n", this, first, last);
1525     for(; first<last; first++)
1526         *first = _Tolower(*first, &this->ctype);
1527     return last;
1528 }
1529
1530 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1531 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1532 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1533 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1534 {
1535     TRACE("(%p %c)\n", this, ch);
1536     return call_ctype_char_do_tolower_ch(this, ch);
1537 }
1538
1539 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1540 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1541 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1542 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1543 {
1544     TRACE("(%p %p %p)\n", this, first, last);
1545     return call_ctype_char_do_tolower(this, first, last);
1546 }
1547
1548 /* _Toupper */
1549 int __cdecl _Toupper(int ch, const _Ctypevec *ctype)
1550 {
1551     unsigned int cp;
1552
1553     TRACE("%d %p\n", ch, ctype);
1554
1555     if(ctype)
1556         cp = ctype->page;
1557     else
1558         cp = ___lc_codepage_func();
1559
1560     /* Don't convert to unicode in case of C locale */
1561     if(!cp) {
1562         if(ch>='a' && ch<='z')
1563             ch = ch-'a'+'A';
1564         return ch;
1565     } else {
1566         WCHAR wide, upper;
1567         char str[2];
1568         int size;
1569
1570         if(ch > 255) {
1571             str[0] = (ch>>8) & 255;
1572             str[1] = ch & 255;
1573             size = 2;
1574         } else {
1575             str[0] = ch & 255;
1576             size = 1;
1577         }
1578
1579         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1580             return ch;
1581
1582         upper = toupperW(wide);
1583         if(upper == wide)
1584             return ch;
1585
1586         WideCharToMultiByte(cp, 0, &upper, 1, str, 2, NULL, NULL);
1587
1588         return str[0] + (str[1]<<8);
1589     }
1590 }
1591
1592 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1593 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1594 #define call_ctype_char_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 16, \
1595         char, (const ctype_char*, char), (this, ch))
1596 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1597 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1598 {
1599     TRACE("(%p %c)\n", this, ch);
1600     return _Toupper(ch, &this->ctype);
1601 }
1602
1603 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1604 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1605 #define call_ctype_char_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 12, \
1606         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1607 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1608 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1609         char *first, const char *last)
1610 {
1611     TRACE("(%p %p %p)\n", this, first, last);
1612     for(; first<last; first++)
1613         *first = _Toupper(*first, &this->ctype);
1614     return last;
1615 }
1616
1617 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1618 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1619 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1620 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1621 {
1622     TRACE("(%p %c)\n", this, ch);
1623     return call_ctype_char_do_toupper_ch(this, ch);
1624 }
1625
1626 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1627 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1628 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1629 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1630 {
1631     TRACE("(%p %p %p)\n", this, first, last);
1632     return call_ctype_char_do_toupper(this, first, last);
1633 }
1634
1635 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1636 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1637 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1638 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1639 {
1640     TRACE("(%p %x %c)\n", this, mask, ch);
1641     return (this->ctype.table[(unsigned char)ch] & mask) != 0;
1642 }
1643
1644 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1645 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1646 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1647 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1648 {
1649     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1650     for(; first<last; first++)
1651         *dest++ = this->ctype.table[(unsigned char)*first];
1652     return last;
1653 }
1654
1655 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1656 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1657 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1658 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1659 {
1660     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1661     for(; first<last; first++)
1662         if(!ctype_char_is_ch(this, mask, *first))
1663             break;
1664     return first;
1665 }
1666
1667 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1668 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1669 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1670 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1671 {
1672     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1673     for(; first<last; first++)
1674         if(ctype_char_is_ch(this, mask, *first))
1675             break;
1676     return first;
1677 }
1678
1679 /* ?table@?$ctype@D@std@@IBEPBFXZ */
1680 /* ?table@?$ctype@D@std@@IEBAPEBFXZ */
1681 DEFINE_THISCALL_WRAPPER(ctype_char_table, 4)
1682 const short* __thiscall ctype_char_table(const ctype_char *this)
1683 {
1684     TRACE("(%p)\n", this);
1685     return this->ctype.table;
1686 }
1687
1688 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1689 locale_id ctype_wchar_id = {0};
1690 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1691 locale_id ctype_short_id = {0};
1692
1693 /* ??_7?$ctype@_W@std@@6B@ */
1694 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1695 /* ??_7?$ctype@G@std@@6B@ */
1696 extern const vtable_ptr MSVCP_ctype_short_vtable;
1697
1698 /* ?_Id_func@?$ctype@_W@std@@SAAAVid@locale@2@XZ */
1699 /* ?_Id_func@?$ctype@_W@std@@SAAEAVid@locale@2@XZ */
1700 locale_id* __cdecl ctype_wchar__Id_func(void)
1701 {
1702     TRACE("()\n");
1703     return &ctype_wchar_id;
1704 }
1705
1706 /* ?_Id_func@?$ctype@G@std@@SAAAVid@locale@2@XZ */
1707 /* ?_Id_func@?$ctype@G@std@@SAAEAVid@locale@2@XZ */
1708 locale_id* __cdecl ctype_short__Id_func(void)
1709 {
1710     TRACE("()\n");
1711     return &ctype_short_id;
1712 }
1713
1714 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1715 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1716 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1717 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1718 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1719 void __thiscall ctype_wchar__Init(ctype_wchar *this, _Locinfo *locinfo)
1720 {
1721     TRACE("(%p %p)\n", this, locinfo);
1722     _Locinfo__Getctype(locinfo, &this->ctype);
1723     _Locinfo__Getcvt(locinfo, &this->cvt);
1724 }
1725
1726 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1727 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1728 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_locinfo, 12)
1729 ctype_wchar* __thiscall ctype_wchar_ctor_locinfo(ctype_wchar *this,
1730         _Locinfo *locinfo, MSVCP_size_t refs)
1731 {
1732     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1733     ctype_base_ctor_refs(&this->base, refs);
1734     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1735     ctype_wchar__Init(this, locinfo);
1736     return this;
1737 }
1738
1739 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1740 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1741 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1742 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1743         _Locinfo *locinfo, MSVCP_size_t refs)
1744 {
1745     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1746     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1747     return ret;
1748 }
1749
1750 /* ??0?$ctype@_W@std@@QAE@I@Z */
1751 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1752 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_refs, 8)
1753 ctype_wchar* __thiscall ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1754 {
1755     _Locinfo locinfo;
1756
1757     TRACE("(%p %lu)\n", this, refs);
1758
1759     ctype_base_ctor_refs(&this->base, refs);
1760     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1761
1762     _Locinfo_ctor(&locinfo);
1763     ctype_wchar__Init(this, &locinfo);
1764     _Locinfo_dtor(&locinfo);
1765     return this;
1766 }
1767
1768 /* ??0?$ctype@G@std@@QAE@I@Z */
1769 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1770 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1771 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1772 {
1773     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1774     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1775     return ret;
1776 }
1777
1778 /* ??0?$ctype@G@std@@IAE@PBDI@Z */
1779 /* ??0?$ctype@G@std@@IEAA@PEBD_K@Z */
1780 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_name, 12)
1781 ctype_wchar* __thiscall ctype_short_ctor_name(ctype_wchar *this,
1782     const char *name, MSVCP_size_t refs)
1783 {
1784     _Locinfo locinfo;
1785
1786     TRACE("(%p %s %lu)\n", this, debugstr_a(name), refs);
1787
1788     ctype_base_ctor_refs(&this->base, refs);
1789     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1790
1791     _Locinfo_ctor_cstr(&locinfo, name);
1792     ctype_wchar__Init(this, &locinfo);
1793     _Locinfo_dtor(&locinfo);
1794     return this;
1795 }
1796
1797 /* ??_F?$ctype@_W@std@@QAEXXZ */
1798 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1799 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor, 4)
1800 ctype_wchar* __thiscall ctype_wchar_ctor(ctype_wchar *this)
1801 {
1802     TRACE("(%p)\n", this);
1803     return ctype_short_ctor_refs(this, 0);
1804 }
1805
1806 /* ??_F?$ctype@G@std@@QAEXXZ */
1807 /* ??_F?$ctype@G@std@@QEAAXXZ */
1808 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1809 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1810 {
1811     ctype_wchar *ret = ctype_wchar_ctor(this);
1812     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1813     return ret;
1814 }
1815
1816 /* ??1?$ctype@_W@std@@MAE@XZ */
1817 /* ??1?$ctype@_W@std@@MEAA@XZ */
1818 /* ??1?$ctype@G@std@@MAE@XZ */
1819 /* ??1?$ctype@G@std@@MEAA@XZ */
1820 DEFINE_THISCALL_WRAPPER(ctype_wchar_dtor, 4)
1821 void __thiscall ctype_wchar_dtor(ctype_wchar *this)
1822 {
1823     TRACE("(%p)\n", this);
1824     if(this->ctype.delfl)
1825         free((void*)this->ctype.table);
1826 }
1827
1828 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_wchar_vector_dtor, 8)
1829 ctype_wchar* __thiscall MSVCP_ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
1830 {
1831     TRACE("(%p %x)\n", this, flags);
1832     if(flags & 2) {
1833         /* we have an array, with the number of elements stored before the first object */
1834         int i, *ptr = (int *)this-1;
1835
1836         for(i=*ptr-1; i>=0; i--)
1837             ctype_wchar_dtor(this+i);
1838         MSVCRT_operator_delete(ptr);
1839     } else {
1840         ctype_wchar_dtor(this);
1841         if(flags & 1)
1842             MSVCRT_operator_delete(this);
1843     }
1844
1845     return this;
1846 }
1847
1848 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_short_vector_dtor, 8)
1849 ctype_wchar* __thiscall MSVCP_ctype_short_vector_dtor(ctype_wchar *this, unsigned int flags)
1850 {
1851     return MSVCP_ctype_wchar_vector_dtor(this, flags);
1852 }
1853
1854 /* _Wcrtomb */
1855 int __cdecl _Wcrtomb(char *s, wchar_t wch, int *state, const _Cvtvec *cvt)
1856 {
1857     int cp, size;
1858     BOOL def;
1859
1860     TRACE("%p %d %p %p\n", s, wch, state, cvt);
1861
1862     if(cvt)
1863         cp = cvt->page;
1864     else
1865         cp = ___lc_codepage_func();
1866
1867     if(!cp) {
1868         if(wch > 255) {
1869            *_errno() = EILSEQ;
1870            return -1;
1871         }
1872
1873         *s = wch & 255;
1874         return 1;
1875     }
1876
1877     size = WideCharToMultiByte(cp, 0, &wch, 1, s, MB_LEN_MAX, NULL, &def);
1878     if(!size || def) {
1879         *_errno() = EILSEQ;
1880         return -1;
1881     }
1882
1883     return size;
1884 }
1885
1886 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
1887 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
1888 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
1889 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
1890 DEFINE_THISCALL_WRAPPER(ctype_wchar__Donarrow, 12)
1891 char __thiscall ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
1892 {
1893     char buf[MB_LEN_MAX];
1894
1895     TRACE("(%p %d %d)\n", this, ch, dflt);
1896
1897     return _Wcrtomb(buf, ch, NULL, &this->cvt)==1 ? buf[0] : dflt;
1898 }
1899
1900 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
1901 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
1902 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
1903 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
1904 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
1905 #define call_ctype_wchar_do_narrow_ch(this, ch, dflt) CALL_VTBL_FUNC(this, 52, \
1906         char, (const ctype_wchar*, wchar_t, char), (this, ch, dflt))
1907 char __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1908 {
1909     return ctype_wchar__Donarrow(this, ch, dflt);
1910 }
1911
1912 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
1913 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
1914 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
1915 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
1916 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
1917 #define call_ctype_wchar_do_narrow(this, first, last, dflt, dest) CALL_VTBL_FUNC(this, 48, \
1918         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*), \
1919         (this, first, last, dflt, dest))
1920 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
1921         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1922 {
1923     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1924     for(; first<last; first++)
1925         *dest++ = ctype_wchar__Donarrow(this, *first, dflt);
1926     return last;
1927 }
1928
1929 /* ?_Do_narrow_s@?$ctype@_W@std@@MBEPB_WPB_W0DPADI@Z */
1930 /* ?_Do_narrow_s@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD_K@Z */
1931 /* ?_Do_narrow_s@?$ctype@G@std@@MBEPBGPBG0DPADI@Z */
1932 /* ?_Do_narrow_s@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD_K@Z */
1933 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_narrow_s, 24)
1934 #define call_ctype_wchar__Do_narrow_s(this, first, last, dflt, dest, size) CALL_VTBL_FUNC(this, 56, \
1935         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*, MSVCP_size_t), \
1936         (this, first, last, dflt, dest, size))
1937 const wchar_t* __thiscall ctype_wchar__Do_narrow_s(const ctype_wchar *this,
1938         const wchar_t *first, const wchar_t *last, char dflt, char *dest, MSVCP_size_t size)
1939 {
1940     TRACE("(%p %p %p %d %p %lu)\n", this, first, last, dflt, dest, size);
1941     /* This function converts all multi-byte characters to dflt,
1942      * thanks to it result size is known before converting */
1943     if(last-first > size)
1944         ctype_base__Xran();
1945     return ctype_wchar_do_narrow(this, first, last, dflt, dest);
1946 }
1947
1948 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
1949 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
1950 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
1951 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
1952 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
1953 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1954 {
1955     TRACE("(%p %d %d)\n", this, ch, dflt);
1956     return call_ctype_wchar_do_narrow_ch(this, ch, dflt);
1957 }
1958
1959 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
1960 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
1961 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
1962 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
1963 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
1964 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
1965         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1966 {
1967     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1968     return call_ctype_wchar_do_narrow(this, first, last, dflt, dest);
1969 }
1970
1971 /* ?_Narrow_s@?$ctype@_W@std@@QBEPB_WPB_W0DPADI@Z */
1972 /* ?_Narrow_s@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD_K@Z */
1973 /* ?_Narrow_s@?$ctype@G@std@@QBEPBGPBG0DPADI@Z */
1974 /* ?_Narrow_s@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD_K@Z */
1975 DEFINE_THISCALL_WRAPPER(ctype_wchar__Narrow_s, 24)
1976 const wchar_t* __thiscall ctype_wchar__Narrow_s(const ctype_wchar *this, const wchar_t *first,
1977         const wchar_t *last, char dflt, char *dest, MSVCP_size_t size)
1978 {
1979     TRACE("(%p %p %p %d %p %lu)\n", this, first, last, dflt, dest, size);
1980     return call_ctype_wchar__Do_narrow_s(this, first, last, dflt, dest, size);
1981 }
1982
1983 /* _Mbrtowc */
1984 int __cdecl _Mbrtowc(wchar_t *out, const char *in, MSVCP_size_t len, int *state, const _Cvtvec *cvt)
1985 {
1986     int i, cp;
1987     CPINFO cp_info;
1988     BOOL is_lead;
1989
1990     TRACE("(%p %p %lu %p %p)\n", out, in, len, state, cvt);
1991
1992     if(!len)
1993         return 0;
1994
1995     if(cvt)
1996         cp = cvt->page;
1997     else
1998         cp = ___lc_codepage_func();
1999
2000     if(!cp) {
2001         if(out)
2002             *out = (unsigned char)*in;
2003
2004         *state = 0;
2005         return *in ? 1 : 0;
2006     }
2007
2008     if(*state) {
2009         ((char*)state)[1] = *in;
2010
2011         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, (char*)state, 2, out, out ? 1 : 0)) {
2012             *state = 0;
2013             *_errno() = EILSEQ;
2014             return -1;
2015         }
2016
2017         *state = 0;
2018         return 2;
2019     }
2020
2021     GetCPInfo(cp, &cp_info);
2022     is_lead = FALSE;
2023     for(i=0; i<MAX_LEADBYTES; i+=2) {
2024         if(!cp_info.LeadByte[i+1])
2025             break;
2026         if((unsigned char)*in>=cp_info.LeadByte[i] && (unsigned char)*in<=cp_info.LeadByte[i+1]) {
2027             is_lead = TRUE;
2028             break;
2029         }
2030     }
2031
2032     if(is_lead) {
2033         if(len == 1) {
2034             *state = (unsigned char)*in;
2035             return -2;
2036         }
2037
2038         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 2, out, out ? 1 : 0)) {
2039             *_errno() = EILSEQ;
2040             return -1;
2041         }
2042         return 2;
2043     }
2044
2045     if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 1, out, out ? 1 : 0)) {
2046         *_errno() = EILSEQ;
2047         return -1;
2048     }
2049     return 1;
2050 }
2051
2052 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
2053 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
2054 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
2055 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
2056 DEFINE_THISCALL_WRAPPER(ctype_wchar__Dowiden, 8)
2057 wchar_t __thiscall ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
2058 {
2059     wchar_t ret;
2060     int state = 0;
2061     TRACE("(%p %d)\n", this, ch);
2062     return _Mbrtowc(&ret, &ch, 1, &state, &this->cvt)<0 ? WEOF : ret;
2063 }
2064
2065 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
2066 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
2067 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
2068 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
2069 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
2070 #define call_ctype_wchar_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 40, \
2071         wchar_t, (const ctype_wchar*, char), (this, ch))
2072 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
2073 {
2074     return ctype_wchar__Dowiden(this, ch);
2075 }
2076
2077 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
2078 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
2079 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
2080 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
2081 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
2082 #define call_ctype_wchar_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 36, \
2083         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*), \
2084         (this, first, last, dest))
2085 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
2086         const char *first, const char *last, wchar_t *dest)
2087 {
2088     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2089     for(; first<last; first++)
2090         *dest++ = ctype_wchar__Dowiden(this, *first);
2091     return last;
2092 }
2093
2094 /* ?_Do_widen_s@?$ctype@_W@std@@MBEPBDPBD0PA_WI@Z */
2095 /* ?_Do_widen_s@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W_K@Z */
2096 /* ?_Do_widen_s@?$ctype@G@std@@MBEPBDPBD0PAGI@Z */
2097 /* ?_Do_widen_s@?$ctype@G@std@@MEBAPEBDPEBD0PEAG_K@Z */
2098 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_widen_s, 20)
2099 #define call_ctype_wchar__Do_widen_s(this, first, last, dest, size) CALL_VTBL_FUNC(this, 44, \
2100         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*, MSVCP_size_t), \
2101         (this, first, last, dest, size))
2102 const char* __thiscall ctype_wchar__Do_widen_s(const ctype_wchar *this,
2103         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
2104 {
2105     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
2106     /* This function converts all multi-byte characters to WEOF,
2107      * thanks to it result size is known before converting */
2108     if(size < last-first)
2109         ctype_base__Xran();
2110     return ctype_wchar_do_widen(this, first, last, dest);
2111 }
2112
2113 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
2114 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
2115 /* ?widen@?$ctype@G@std@@QBEGD@Z */
2116 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
2117 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
2118 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
2119 {
2120     TRACE("(%p %d)\n", this, ch);
2121     return call_ctype_wchar_do_widen_ch(this, ch);
2122 }
2123
2124 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
2125 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
2126 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
2127 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
2128 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
2129 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
2130         const char *first, const char *last, wchar_t *dest)
2131 {
2132     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2133     return call_ctype_wchar_do_widen(this, first, last, dest);
2134 }
2135
2136 /* ?_Widen_s@?$ctype@_W@std@@QBEPBDPBD0PA_WI@Z */
2137 /* ?_Widen_s@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W_K@Z */
2138 /* ?_Widen_s@?$ctype@G@std@@QBEPBDPBD0PAGI@Z */
2139 /* ?_Widen_s@?$ctype@G@std@@QEBAPEBDPEBD0PEAG_K@Z */
2140 DEFINE_THISCALL_WRAPPER(ctype_wchar__Widen_s, 20)
2141 const char* __thiscall ctype_wchar__Widen_s(const ctype_wchar *this,
2142         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
2143 {
2144     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
2145     return call_ctype_wchar__Do_widen_s(this, first, last, dest, size);
2146 }
2147
2148 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2149 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2150 MSVCP_size_t __cdecl ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
2151 {
2152     TRACE("(%p %p)\n", facet, loc);
2153
2154     if(facet && !*facet) {
2155         _Locinfo locinfo;
2156
2157         *facet = MSVCRT_operator_new(sizeof(ctype_wchar));
2158         if(!*facet) {
2159             ERR("Out of memory\n");
2160             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2161             return 0;
2162         }
2163
2164         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
2165         ctype_wchar_ctor_locinfo((ctype_wchar*)*facet, &locinfo, 0);
2166         _Locinfo_dtor(&locinfo);
2167     }
2168
2169     return LC_CTYPE;
2170 }
2171
2172 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2173 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2174 MSVCP_size_t __cdecl ctype_short__Getcat(const locale_facet **facet, const locale *loc)
2175 {
2176     if(facet && !*facet) {
2177         ctype_wchar__Getcat(facet, loc);
2178         (*(locale_facet**)facet)->vtable = &MSVCP_ctype_short_vtable;
2179     }
2180
2181     return LC_CTYPE;
2182 }
2183
2184 /* _Towlower */
2185 wchar_t __cdecl _Towlower(wchar_t ch, const _Ctypevec *ctype)
2186 {
2187     TRACE("(%d %p)\n", ch, ctype);
2188     return tolowerW(ch);
2189 }
2190
2191 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
2192 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
2193 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
2194 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
2195 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
2196 #define call_ctype_wchar_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
2197         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2198 wchar_t __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
2199 {
2200     return _Towlower(ch, &this->ctype);
2201 }
2202
2203 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2204 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2205 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2206 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2207 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
2208 #define call_ctype_wchar_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 20, \
2209         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2210         (this, first, last))
2211 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
2212         wchar_t *first, const wchar_t *last)
2213 {
2214     TRACE("(%p %p %p)\n", this, first, last);
2215     for(; first<last; first++)
2216         *first = _Towlower(*first, &this->ctype);
2217     return last;
2218 }
2219
2220 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
2221 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
2222 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
2223 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
2224 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
2225 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
2226 {
2227     TRACE("(%p %d)\n", this, ch);
2228     return call_ctype_wchar_do_tolower_ch(this, ch);
2229 }
2230
2231 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2232 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2233 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2234 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2235 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
2236 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
2237         wchar_t *first, const wchar_t *last)
2238 {
2239     TRACE("(%p %p %p)\n", this, first, last);
2240     return call_ctype_wchar_do_tolower(this, first, last);
2241 }
2242
2243 /* _Towupper */
2244 wchar_t __cdecl _Towupper(wchar_t ch, const _Ctypevec *ctype)
2245 {
2246     TRACE("(%d %p)\n", ch, ctype);
2247     return toupperW(ch);
2248 }
2249
2250 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
2251 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
2252 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
2253 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
2254 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
2255 #define call_ctype_wchar_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 32, \
2256         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2257 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
2258 {
2259     return _Towupper(ch, &this->ctype);
2260 }
2261
2262 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2263 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2264 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2265 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2266 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
2267 #define call_ctype_wchar_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 28, \
2268         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2269         (this, first, last))
2270 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
2271         wchar_t *first, const wchar_t *last)
2272 {
2273     TRACE("(%p %p %p)\n", this, first, last);
2274     for(; first<last; first++)
2275         *first = _Towupper(*first, &this->ctype);
2276     return last;
2277 }
2278
2279 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
2280 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
2281 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
2282 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
2283 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
2284 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
2285 {
2286     TRACE("(%p %d)\n", this, ch);
2287     return call_ctype_wchar_do_toupper_ch(this, ch);
2288 }
2289
2290 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2291 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2292 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2293 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2294 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
2295 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
2296         wchar_t *first, const wchar_t *last)
2297 {
2298     TRACE("(%p %p %p)\n", this, first, last);
2299     return call_ctype_wchar_do_toupper(this, first, last);
2300 }
2301
2302 /* _Getwctypes */
2303 const wchar_t* __cdecl _Getwctypes(const wchar_t *first, const wchar_t *last,
2304         short *mask, const _Ctypevec *ctype)
2305 {
2306     TRACE("(%p %p %p %p)\n", first, last, mask, ctype);
2307     GetStringTypeW(CT_CTYPE1, first, last-first, (WORD*)mask);
2308     return last;
2309 }
2310
2311 /* _Getwctype */
2312 short __cdecl _Getwctype(wchar_t ch, const _Ctypevec *ctype)
2313 {
2314     short mask = 0;
2315     _Getwctypes(&ch, &ch+1, &mask, ctype);
2316     return mask;
2317 }
2318
2319 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
2320 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
2321 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
2322 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
2323 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
2324 #define call_ctype_wchar_do_is_ch(this, mask, ch) CALL_VTBL_FUNC(this, 8, \
2325         MSVCP_bool, (const ctype_wchar*, short, wchar_t), (this, mask, ch))
2326 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2327 {
2328     TRACE("(%p %x %d)\n", this, mask, ch);
2329     return !(_Getwctype(ch, &this->ctype) & mask);
2330 }
2331
2332 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
2333 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
2334 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
2335 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
2336 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
2337 #define call_ctype_wchar_do_is(this, first, last, dest) CALL_VTBL_FUNC(this, 4, \
2338         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, short*), \
2339         (this, first, last, dest))
2340 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
2341         const wchar_t *first, const wchar_t *last, short *dest)
2342 {
2343     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2344     return _Getwctypes(first, last, dest, &this->ctype);
2345 }
2346
2347 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
2348 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
2349 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
2350 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
2351 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
2352 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2353 {
2354     TRACE("(%p %x %d)\n", this, mask, ch);
2355     return call_ctype_wchar_do_is_ch(this, mask, ch);
2356 }
2357
2358 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
2359 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
2360 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
2361 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
2362 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
2363 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
2364         const wchar_t *first, const wchar_t *last, short *dest)
2365 {
2366     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2367     return call_ctype_wchar_do_is(this, first, last, dest);
2368 }
2369
2370 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2371 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2372 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
2373 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2374 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
2375 #define call_ctype_wchar_do_scan_is(this, mask, first, last) CALL_VTBL_FUNC(this, 12, \
2376         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2377         (this, mask, first, last))
2378 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
2379         short mask, const wchar_t *first, const wchar_t *last)
2380 {
2381     TRACE("(%p %d %p %p)\n", this, mask, first, last);
2382     for(; first<last; first++)
2383         if(!ctype_wchar_is_ch(this, mask, *first))
2384             break;
2385     return first;
2386 }
2387
2388 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2389 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2390 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
2391 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2392 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
2393 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
2394         short mask, const wchar_t *first, const wchar_t *last)
2395 {
2396     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2397     return call_ctype_wchar_do_scan_is(this, mask, first, last);
2398 }
2399
2400 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2401 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2402 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2403 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2404 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2405 #define call_ctype_wchar_do_scan_not(this, mask, first, last) CALL_VTBL_FUNC(this, 16, \
2406         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2407         (this, mask, first, last))
2408 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2409         short mask, const wchar_t *first, const wchar_t *last)
2410 {
2411     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2412     for(; first<last; first++)
2413         if(ctype_wchar_is_ch(this, mask, *first))
2414             break;
2415     return first;
2416 }
2417
2418 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2419 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2420 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2421 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2422 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2423 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2424         short mask, const wchar_t *first, const wchar_t *last)
2425 {
2426     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2427     return call_ctype_wchar_do_scan_not(this, mask, first, last);
2428 }
2429
2430 /* ?id@?$numpunct@D@std@@2V0locale@2@A */
2431 locale_id numpunct_char_id = {0};
2432
2433 /* ??_7?$numpunct@D@std@@6B@ */
2434 extern const vtable_ptr MSVCP_numpunct_char_vtable;
2435
2436 /* ?_Init@?$numpunct@D@std@@IAEXABV_Locinfo@2@_N@Z */
2437 /* ?_Init@?$numpunct@D@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2438 DEFINE_THISCALL_WRAPPER(numpunct_char__Init, 12)
2439 void __thiscall numpunct_char__Init(numpunct_char *this, _Locinfo *locinfo, MSVCP_bool isdef)
2440 {
2441     const struct lconv *lc = _Locinfo__Getlconv(locinfo);
2442     int len;
2443
2444     TRACE("(%p %p %d)\n", this, locinfo, isdef);
2445
2446     len = strlen(_Locinfo__Getfalse(locinfo))+1;
2447     this->false_name = MSVCRT_operator_new(len);
2448     if(this->false_name)
2449         memcpy((char*)this->false_name, _Locinfo__Getfalse(locinfo), len);
2450
2451     len = strlen(_Locinfo__Gettrue(locinfo))+1;
2452     this->true_name = MSVCRT_operator_new(len);
2453     if(this->true_name)
2454         memcpy((char*)this->true_name, _Locinfo__Gettrue(locinfo), len);
2455
2456     if(isdef) {
2457         this->grouping = MSVCRT_operator_new(1);
2458         if(this->grouping)
2459             *(char*)this->grouping = 0;
2460
2461         this->dp = '.';
2462         this->sep = ',';
2463     } else {
2464         len = strlen(lc->grouping)+1;
2465         this->grouping = MSVCRT_operator_new(len);
2466         if(this->grouping)
2467             memcpy((char*)this->grouping, lc->grouping, len);
2468
2469         this->dp = lc->decimal_point[0];
2470         this->sep = lc->thousands_sep[0];
2471     }
2472
2473     if(!this->false_name || !this->true_name || !this->grouping) {
2474         MSVCRT_operator_delete((char*)this->grouping);
2475         MSVCRT_operator_delete((char*)this->false_name);
2476         MSVCRT_operator_delete((char*)this->true_name);
2477
2478         ERR("Out of memory\n");
2479         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2480     }
2481 }
2482
2483 /* ?_Tidy@?$numpunct@D@std@@AAEXXZ */
2484 /* ?_Tidy@?$numpunct@D@std@@AEAAXXZ */
2485 DEFINE_THISCALL_WRAPPER(numpunct_char__Tidy, 4)
2486 void __thiscall numpunct_char__Tidy(numpunct_char *this)
2487 {
2488     TRACE("(%p)\n", this);
2489
2490     MSVCRT_operator_delete((char*)this->grouping);
2491     MSVCRT_operator_delete((char*)this->false_name);
2492     MSVCRT_operator_delete((char*)this->true_name);
2493 }
2494
2495 /* ??0?$numpunct@D@std@@QAE@ABV_Locinfo@1@I_N@Z */
2496 /* ??0?$numpunct@D@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
2497 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_locinfo, 16)
2498 numpunct_char* __thiscall numpunct_char_ctor_locinfo(numpunct_char *this,
2499         _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
2500 {
2501     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
2502     locale_facet_ctor_refs(&this->facet, refs);
2503     this->facet.vtable = &MSVCP_numpunct_char_vtable;
2504     numpunct_char__Init(this, locinfo, usedef);
2505     return this;
2506 }
2507
2508 /* ??0?$numpunct@D@std@@IAE@PBDI_N@Z */
2509 /* ??0?$numpunct@D@std@@IEAA@PEBD_K_N@Z */
2510 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_name, 16)
2511 numpunct_char* __thiscall numpunct_char_ctor_name(numpunct_char *this,
2512         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
2513 {
2514     _Locinfo locinfo;
2515
2516     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
2517     locale_facet_ctor_refs(&this->facet, refs);
2518     this->facet.vtable = &MSVCP_numpunct_char_vtable;
2519
2520     _Locinfo_ctor_cstr(&locinfo, name);
2521     numpunct_char__Init(this, &locinfo, usedef);
2522     _Locinfo_dtor(&locinfo);
2523     return this;
2524 }
2525
2526 /* ??0?$numpunct@D@std@@QAE@I@Z */
2527 /* ??0?$numpunct@D@std@@QEAA@_K@Z */
2528 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_refs, 8)
2529 numpunct_char* __thiscall numpunct_char_ctor_refs(numpunct_char *this, MSVCP_size_t refs)
2530 {
2531     TRACE("(%p %lu)\n", this, refs);
2532     return numpunct_char_ctor_name(this, "C", refs, FALSE);
2533 }
2534
2535 /* ??_F?$numpunct@D@std@@QAEXXZ */
2536 /* ??_F?$numpunct@D@std@@QEAAXXZ */
2537 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor, 4)
2538 numpunct_char* __thiscall numpunct_char_ctor(numpunct_char *this)
2539 {
2540     return numpunct_char_ctor_refs(this, 0);
2541 }
2542
2543 /* ??1?$numpunct@D@std@@MAE@XZ */
2544 /* ??1?$numpunct@D@std@@MEAA@XZ */
2545 DEFINE_THISCALL_WRAPPER(numpunct_char_dtor, 4)
2546 void __thiscall numpunct_char_dtor(numpunct_char *this)
2547 {
2548     TRACE("(%p)\n", this);
2549     numpunct_char__Tidy(this);
2550 }
2551
2552 DEFINE_THISCALL_WRAPPER(MSVCP_numpunct_char_vector_dtor, 8)
2553 numpunct_char* __thiscall MSVCP_numpunct_char_vector_dtor(numpunct_char *this, unsigned int flags)
2554 {
2555     TRACE("(%p %x)\n", this, flags);
2556     if(flags & 2) {
2557         /* we have an array, with the number of elements stored before the first object */
2558         int i, *ptr = (int *)this-1;
2559
2560         for(i=*ptr-1; i>=0; i--)
2561             numpunct_char_dtor(this+i);
2562         MSVCRT_operator_delete(ptr);
2563     } else {
2564         numpunct_char_dtor(this);
2565         if(flags & 1)
2566             MSVCRT_operator_delete(this);
2567     }
2568
2569     return this;
2570 }
2571
2572 /* ?_Getcat@?$numpunct@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2573 /* ?_Getcat@?$numpunct@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2574 MSVCP_size_t __cdecl numpunct_char__Getcat(const locale_facet **facet, const locale *loc)
2575 {
2576     TRACE("(%p %p)\n", facet, loc);
2577
2578     if(facet && !*facet) {
2579         *facet = MSVCRT_operator_new(sizeof(numpunct_char));
2580         if(!*facet) {
2581             ERR("Out of memory\n");
2582             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2583             return 0;
2584         }
2585         numpunct_char_ctor_name((numpunct_char*)*facet,
2586                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
2587     }
2588
2589     return LC_NUMERIC;
2590 }
2591
2592 /* ?do_decimal_point@?$numpunct@D@std@@MBEDXZ */
2593 /* ?do_decimal_point@?$numpunct@D@std@@MEBADXZ */
2594 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
2595 #define call_numpunct_char_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
2596         char, (const numpunct_char *this), (this))
2597 char __thiscall numpunct_char_do_decimal_point(const numpunct_char *this)
2598 {
2599     TRACE("(%p)\n", this);
2600     return this->dp;
2601 }
2602
2603 /* ?decimal_point@?$numpunct@D@std@@QBEDXZ */
2604 /* ?decimal_point@?$numpunct@D@std@@QEBADXZ */
2605 DEFINE_THISCALL_WRAPPER(numpunct_char_decimal_point, 4)
2606 char __thiscall numpunct_char_decimal_point(const numpunct_char *this)
2607 {
2608     TRACE("(%p)\n", this);
2609     return call_numpunct_char_do_decimal_point(this);
2610 }
2611
2612 /* ?do_thousands_sep@?$numpunct@D@std@@MBEDXZ */
2613 /* ?do_thousands_sep@?$numpunct@D@std@@MEBADXZ */
2614 DEFINE_THISCALL_WRAPPER(numpunct_char_do_thousands_sep, 4)
2615 #define call_numpunct_char_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
2616         char, (const numpunct_char*), (this))
2617 char __thiscall numpunct_char_do_thousands_sep(const numpunct_char *this)
2618 {
2619     TRACE("(%p)\n", this);
2620     return this->sep;
2621 }
2622
2623 /* ?thousands_sep@?$numpunct@D@std@@QBEDXZ */
2624 /* ?thousands_sep@?$numpunct@D@std@@QEBADXZ */
2625 DEFINE_THISCALL_WRAPPER(numpunct_char_thousands_sep, 4)
2626 char __thiscall numpunct_char_thousands_sep(const numpunct_char *this)
2627 {
2628     TRACE("(%p)\n", this);
2629     return call_numpunct_char_do_thousands_sep(this);
2630 }
2631
2632 /* ?do_grouping@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2633 /* ?do_grouping@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2634 DEFINE_THISCALL_WRAPPER(numpunct_char_do_grouping, 8)
2635 #define call_numpunct_char_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
2636         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
2637 basic_string_char* __thiscall numpunct_char_do_grouping(
2638         const numpunct_char *this, basic_string_char *ret)
2639 {
2640     TRACE("(%p)\n", this);
2641     return MSVCP_basic_string_char_ctor_cstr(ret, this->grouping);
2642 }
2643
2644 /* ?grouping@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2645 /* ?grouping@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2646 DEFINE_THISCALL_WRAPPER(numpunct_char_grouping, 8)
2647 basic_string_char* __thiscall numpunct_char_grouping(const numpunct_char *this, basic_string_char *ret)
2648 {
2649     TRACE("(%p)\n", this);
2650     return call_numpunct_char_do_grouping(this, ret);
2651 }
2652
2653 /* ?do_falsename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2654 /* ?do_falsename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2655 DEFINE_THISCALL_WRAPPER(numpunct_char_do_falsename, 8)
2656 #define call_numpunct_char_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
2657         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
2658 basic_string_char* __thiscall numpunct_char_do_falsename(
2659         const numpunct_char *this, basic_string_char *ret)
2660 {
2661     TRACE("(%p)\n", this);
2662     return MSVCP_basic_string_char_ctor_cstr(ret, this->false_name);
2663 }
2664
2665 /* ?falsename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2666 /* ?falsename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2667 DEFINE_THISCALL_WRAPPER(numpunct_char_falsename, 8)
2668 basic_string_char* __thiscall numpunct_char_falsename(const numpunct_char *this, basic_string_char *ret)
2669 {
2670     TRACE("(%p)\n", this);
2671     return call_numpunct_char_do_falsename(this, ret);
2672 }
2673
2674 /* ?do_truename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2675 /* ?do_truename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2676 DEFINE_THISCALL_WRAPPER(numpunct_char_do_truename, 8)
2677 #define call_numpunct_char_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
2678         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
2679 basic_string_char* __thiscall numpunct_char_do_truename(
2680         const numpunct_char *this, basic_string_char *ret)
2681 {
2682     TRACE("(%p)\n", this);
2683     return MSVCP_basic_string_char_ctor_cstr(ret, this->true_name);
2684 }
2685
2686 /* ?truename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2687 /* ?truename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2688 DEFINE_THISCALL_WRAPPER(numpunct_char_truename, 8)
2689 basic_string_char* __thiscall numpunct_char_truename(const numpunct_char *this, basic_string_char *ret)
2690 {
2691     TRACE("(%p)\n", this);
2692     return call_numpunct_char_do_truename(this, ret);
2693 }
2694
2695 /* ?id@?$numpunct@_W@std@@2V0locale@2@A */
2696 locale_id numpunct_wchar_id = {0};
2697 /* ?id@?$numpunct@G@std@@2V0locale@2@A */
2698 locale_id numpunct_short_id = {0};
2699
2700 /* ??_7?$numpunct@_W@std@@6B@ */
2701 extern const vtable_ptr MSVCP_numpunct_wchar_vtable;
2702 /* ??_7?$numpunct@G@std@@6B@ */
2703 extern const vtable_ptr MSVCP_numpunct_short_vtable;
2704
2705 /* ?_Init@?$numpunct@_W@std@@IAEXABV_Locinfo@2@_N@Z */
2706 /* ?_Init@?$numpunct@_W@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2707 /* ?_Init@?$numpunct@G@std@@IAEXABV_Locinfo@2@_N@Z */
2708 /* ?_Init@?$numpunct@G@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2709 DEFINE_THISCALL_WRAPPER(numpunct_wchar__Init, 12)
2710 void __thiscall numpunct_wchar__Init(numpunct_wchar *this, _Locinfo *locinfo, MSVCP_bool isdef)
2711 {
2712     FIXME("(%p %p %d) stub\n", this, locinfo, isdef);
2713 }
2714
2715 /* ?_Tidy@?$numpunct@_W@std@@AAEXXZ */
2716 /* ?_Tidy@?$numpunct@_W@std@@AEAAXXZ */
2717 /* ?_Tidy@?$numpunct@G@std@@AAEXXZ */
2718 /* ?_Tidy@?$numpunct@G@std@@AEAAXXZ */
2719 DEFINE_THISCALL_WRAPPER(numpunct_wchar__Tidy, 4)
2720 void __thiscall numpunct_wchar__Tidy(numpunct_wchar *this)
2721 {
2722     FIXME("(%p) stub\n", this);
2723 }
2724
2725 /* ??0?$numpunct@_W@std@@QAE@ABV_Locinfo@1@I_N@Z */
2726 /* ??0?$numpunct@_W@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
2727 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_locinfo, 16)
2728 numpunct_wchar* __thiscall numpunct_wchar_ctor_locinfo(numpunct_wchar *this,
2729         _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
2730 {
2731     FIXME("(%p %p %lu %d) stub\n", this, locinfo, refs, usedef);
2732     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
2733     return NULL;
2734 }
2735
2736 /* ??0?$numpunct@G@std@@QAE@ABV_Locinfo@1@I_N@Z */
2737 /* ??0?$numpunct@G@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
2738 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_locinfo, 16)
2739 numpunct_wchar* __thiscall numpunct_short_ctor_locinfo(numpunct_wchar *this,
2740         _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
2741 {
2742     numpunct_wchar_ctor_locinfo(this, locinfo, refs, usedef);
2743     this->facet.vtable = &MSVCP_numpunct_short_vtable;
2744     return this;
2745 }
2746
2747 /* ??0?$numpunct@_W@std@@IAE@PBDI_N@Z */
2748 /* ??0?$numpunct@_W@std@@IEAA@PEBD_K_N@Z */
2749 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_name, 16)
2750 numpunct_wchar* __thiscall numpunct_wchar_ctor_name(numpunct_wchar *this,
2751         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
2752 {
2753     FIXME("(%p %s %lu %d) stub\n", this, debugstr_a(name), refs, usedef);
2754     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
2755     return NULL;
2756 }
2757
2758 /* ??0?$numpunct@G@std@@IAE@PBDI_N@Z */
2759 /* ??0?$numpunct@G@std@@IEAA@PEBD_K_N@Z */
2760 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_name, 16)
2761 numpunct_wchar* __thiscall numpunct_short_ctor_name(numpunct_wchar *this,
2762         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
2763 {
2764     numpunct_wchar_ctor_name(this, name, refs, usedef);
2765     this->facet.vtable = &MSVCP_numpunct_short_vtable;
2766     return this;
2767 }
2768
2769 /* ??0?$numpunct@_W@std@@QAE@I@Z */
2770 /* ??0?$numpunct@_W@std@@QEAA@_K@Z */
2771 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_refs, 8)
2772 numpunct_wchar* __thiscall numpunct_wchar_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
2773 {
2774     FIXME("(%p %lu) stub\n", this, refs);
2775     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
2776     return NULL;
2777 }
2778
2779 /* ??0?$numpunct@G@std@@QAE@I@Z */
2780 /* ??0?$numpunct@G@std@@QEAA@_K@Z */
2781 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_refs, 8)
2782 numpunct_wchar* __thiscall numpunct_short_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
2783 {
2784     numpunct_wchar_ctor_refs(this, refs);
2785     this->facet.vtable = &MSVCP_numpunct_short_vtable;
2786     return this;
2787 }
2788
2789 /* ??_F?$numpunct@_W@std@@QAEXXZ */
2790 /* ??_F?$numpunct@_W@std@@QEAAXXZ */
2791 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor, 4)
2792 numpunct_wchar* __thiscall numpunct_wchar_ctor(numpunct_wchar *this)
2793 {
2794     return numpunct_wchar_ctor_refs(this, 0);
2795 }
2796
2797 /* ??_F?$numpunct@G@std@@QAEXXZ */
2798 /* ??_F?$numpunct@G@std@@QEAAXXZ */
2799 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor, 4)
2800 numpunct_wchar* __thiscall numpunct_short_ctor(numpunct_wchar *this)
2801 {
2802     return numpunct_short_ctor_refs(this, 0);
2803 }
2804
2805 /* ??1?$numpunct@_W@std@@MAE@XZ */
2806 /* ??1?$numpunct@_W@std@@MEAA@XZ */
2807 /* ??1?$numpunct@G@std@@MAE@XZ */
2808 /* ??1?$numpunct@G@std@@MEAA@XZ */
2809 DEFINE_THISCALL_WRAPPER(numpunct_wchar_dtor, 4)
2810 void __thiscall numpunct_wchar_dtor(numpunct_wchar *this)
2811 {
2812     FIXME("(%p) stub\n", this);
2813 }
2814
2815 DEFINE_THISCALL_WRAPPER(MSVCP_numpunct_wchar_vector_dtor, 8)
2816 numpunct_wchar* __thiscall MSVCP_numpunct_wchar_vector_dtor(numpunct_wchar *this, unsigned int flags)
2817 {
2818     TRACE("(%p %x)\n", this, flags);
2819     if(flags & 2) {
2820         /* we have an array, with the number of elements stored before the first object */
2821         int i, *ptr = (int *)this-1;
2822
2823         for(i=*ptr-1; i>=0; i--)
2824             numpunct_wchar_dtor(this+i);
2825         MSVCRT_operator_delete(ptr);
2826     } else {
2827         numpunct_wchar_dtor(this);
2828         if(flags & 1)
2829             MSVCRT_operator_delete(this);
2830     }
2831
2832     return this;
2833 }
2834
2835 DEFINE_THISCALL_WRAPPER(MSVCP_numpunct_short_vector_dtor, 8)
2836 numpunct_wchar* __thiscall MSVCP_numpunct_short_vector_dtor(numpunct_wchar *this, unsigned int flags)
2837 {
2838     return MSVCP_numpunct_wchar_vector_dtor(this, flags);
2839 }
2840
2841 /* ?_Getcat@?$numpunct@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2842 /* ?_Getcat@?$numpunct@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2843 MSVCP_size_t __cdecl numpunct_wchar__Getcat(const locale_facet **facet, const locale *loc)
2844 {
2845     FIXME("(%p %p) stub\n", facet, loc);
2846     return 0;
2847 }
2848
2849 /* ?_Getcat@?$numpunct@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2850 /* ?_Getcat@?$numpunct@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2851 MSVCP_size_t __cdecl numpunct_short__Getcat(const locale_facet **facet, const locale *loc)
2852 {
2853     FIXME("(%p %p) stub\n", facet, loc);
2854     return 0;
2855 }
2856
2857 /* ?do_decimal_point@?$numpunct@_W@std@@MBE_WXZ */
2858 /* ?do_decimal_point@?$numpunct@_W@std@@MEBA_WXZ */
2859 /* ?do_decimal_point@?$numpunct@G@std@@MBEGXZ */
2860 /* ?do_decimal_point@?$numpunct@G@std@@MEBAGXZ */
2861 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_decimal_point, 4)
2862 wchar_t __thiscall numpunct_wchar_do_decimal_point(const numpunct_wchar *this)
2863 {
2864     FIXME("(%p) stub\n", this);
2865     return 0;
2866 }
2867
2868 /* ?decimal_point@?$numpunct@_W@std@@QBE_WXZ */
2869 /* ?decimal_point@?$numpunct@_W@std@@QEBA_WXZ */
2870 /* ?decimal_point@?$numpunct@G@std@@QBEGXZ */
2871 /* ?decimal_point@?$numpunct@G@std@@QEBAGXZ */
2872 DEFINE_THISCALL_WRAPPER(numpunct_wchar_decimal_point, 4)
2873 wchar_t __thiscall numpunct_wchar_decimal_point(const numpunct_wchar *this)
2874 {
2875     FIXME("(%p) stub\n", this);
2876     return 0;
2877 }
2878
2879 /* ?do_thousands_sep@?$numpunct@_W@std@@MBE_WXZ */
2880 /* ?do_thousands_sep@?$numpunct@_W@std@@MEBA_WXZ */
2881 /* ?do_thousands_sep@?$numpunct@G@std@@MBEGXZ */
2882 /* ?do_thousands_sep@?$numpunct@G@std@@MEBAGXZ */
2883 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_thousands_sep, 4)
2884 wchar_t __thiscall numpunct_wchar_do_thousands_sep(const numpunct_wchar *this)
2885 {
2886     FIXME("(%p) stub\n", this);
2887     return 0;
2888 }
2889
2890 /* ?thousands_sep@?$numpunct@_W@std@@QBE_WXZ */
2891 /* ?thousands_sep@?$numpunct@_W@std@@QEBA_WXZ */
2892 /* ?thousands_sep@?$numpunct@G@std@@QBEGXZ */
2893 /* ?thousands_sep@?$numpunct@G@std@@QEBAGXZ */
2894 DEFINE_THISCALL_WRAPPER(numpunct_wchar_thousands_sep, 4)
2895 wchar_t __thiscall numpunct_wchar_thousands_sep(const numpunct_wchar *this)
2896 {
2897     FIXME("(%p) stub\n", this);
2898     return 0;
2899 }
2900
2901 /* ?do_grouping@?$numpunct@_W@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2902 /* ?do_grouping@?$numpunct@_W@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2903 /* ?do_grouping@?$numpunct@G@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2904 /* ?do_grouping@?$numpunct@G@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2905 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_grouping, 8)
2906 basic_string_char* __thiscall numpunct_wchar_do_grouping(const numpunct_wchar *this, basic_string_char *ret)
2907 {
2908     FIXME("(%p) stub\n", this);
2909     return ret;
2910 }
2911
2912 /* ?grouping@?$numpunct@_W@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2913 /* ?grouping@?$numpunct@_W@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2914 /* ?grouping@?$numpunct@G@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2915 /* ?grouping@?$numpunct@G@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2916 DEFINE_THISCALL_WRAPPER(numpunct_wchar_grouping, 8)
2917 basic_string_char* __thiscall numpunct_wchar_grouping(const numpunct_wchar *this, basic_string_char *ret)
2918 {
2919     FIXME("(%p) stub\n", this);
2920     return ret;
2921 }
2922
2923 /* ?do_falsename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2924 /* ?do_falsename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2925 /* ?do_falsename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2926 /* ?do_falsename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2927 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_falsename, 8)
2928 basic_string_wchar* __thiscall numpunct_wchar_do_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
2929 {
2930     FIXME("(%p) stub\n", this);
2931     return ret;
2932 }
2933
2934 /* ?falsename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2935 /* ?falsename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2936 /* ?falsename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2937 /* ?falsename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2938 DEFINE_THISCALL_WRAPPER(numpunct_wchar_falsename, 8)
2939 basic_string_wchar* __thiscall numpunct_wchar_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
2940 {
2941     FIXME("(%p) stub\n", this);
2942     return ret;
2943 }
2944
2945 /* ?do_truename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2946 /* ?do_truename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2947 /* ?do_truename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2948 /* ?do_truename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2949 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_truename, 8)
2950 basic_string_wchar* __thiscall numpunct_wchar_do_truename(const numpunct_wchar *this, basic_string_wchar *ret)
2951 {
2952     FIXME("(%p) stub\n", this);
2953     return ret;
2954 }
2955
2956 /* ?truename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2957 /* ?truename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
2958 /* ?truename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2959 /* ?truename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
2960 DEFINE_THISCALL_WRAPPER(numpunct_wchar_truename, 8)
2961 basic_string_wchar* __thiscall numpunct_wchar_truename(const numpunct_wchar *this, basic_string_wchar *ret)
2962 {
2963     FIXME("(%p) stub\n", this);
2964     return ret;
2965 }
2966
2967 /* ??0_Locimp@locale@std@@AAE@_N@Z */
2968 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
2969 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor_transparent, 8)
2970 locale__Locimp* __thiscall locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
2971 {
2972     TRACE("(%p %d)\n", this, transparent);
2973
2974     memset(this, 0, sizeof(locale__Locimp));
2975     locale_facet_ctor_refs(&this->facet, 1);
2976     this->transparent = transparent;
2977     MSVCP_basic_string_char_ctor_cstr(&this->name, "*");
2978     return this;
2979 }
2980
2981 /* ??_F_Locimp@locale@std@@QAEXXZ */
2982 /* ??_F_Locimp@locale@std@@QEAAXXZ */
2983 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor, 4)
2984 locale__Locimp* __thiscall locale__Locimp_ctor(locale__Locimp *this)
2985 {
2986     return locale__Locimp_ctor_transparent(this, FALSE);
2987 }
2988
2989 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
2990 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
2991 DEFINE_THISCALL_WRAPPER(locale__Locimp_copy_ctor, 8)
2992 locale__Locimp* __thiscall locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
2993 {
2994     _Lockit lock;
2995     MSVCP_size_t i;
2996
2997     TRACE("(%p %p)\n", this, copy);
2998
2999     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3000     memcpy(this, copy, sizeof(locale__Locimp));
3001     locale_facet_ctor_refs(&this->facet, 1);
3002     if(copy->facetvec) {
3003         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
3004         if(!this->facetvec) {
3005             _Lockit_dtor(&lock);
3006             ERR("Out of memory\n");
3007             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3008             return NULL;
3009         }
3010         for(i=0; i<this->facet_cnt; i++)
3011             if(this->facetvec[i])
3012                 locale_facet__Incref(this->facetvec[i]);
3013     }
3014     MSVCP_basic_string_char_copy_ctor(&this->name, &copy->name);
3015     _Lockit_dtor(&lock);
3016     return this;
3017 }
3018
3019 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPAV123@ABV123@@Z */
3020 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPEAV123@AEBV123@@Z */
3021 locale__Locimp* __cdecl locale__Locimp__Locimp_ctor(locale__Locimp *this, const locale__Locimp *copy)
3022 {
3023     return locale__Locimp_copy_ctor(this, copy);
3024 }
3025
3026 /* ??1_Locimp@locale@std@@MAE@XZ */
3027 /* ??1_Locimp@locale@std@@MEAA@XZ */
3028 DEFINE_THISCALL_WRAPPER(locale__Locimp_dtor, 4)
3029 void __thiscall locale__Locimp_dtor(locale__Locimp *this)
3030 {
3031     TRACE("(%p)\n", this);
3032
3033     if(locale_facet__Decref(&this->facet)) {
3034         MSVCP_size_t i;
3035         for(i=0; i<this->facet_cnt; i++)
3036             if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
3037                 call_locale_facet_vector_dtor(this->facetvec[i], 0);
3038
3039         MSVCRT_operator_delete(this->facetvec);
3040         MSVCP_basic_string_char_dtor(&this->name);
3041     }
3042 }
3043
3044 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPAV123@@Z */
3045 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPEAV123@@Z */
3046 void __cdecl locale__Locimp__Locimp_dtor(locale__Locimp *this)
3047 {
3048     locale__Locimp_dtor(this);
3049 }
3050
3051 DEFINE_THISCALL_WRAPPER(MSVCP_locale__Locimp_vector_dtor, 8)
3052 locale__Locimp* __thiscall MSVCP_locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
3053 {
3054     TRACE("(%p %x)\n", this, flags);
3055     if(flags & 2) {
3056         /* we have an array, with the number of elements stored before the first object */
3057         int i, *ptr = (int *)this-1;
3058
3059         for(i=*ptr-1; i>=0; i--)
3060             locale__Locimp_dtor(this+i);
3061         MSVCRT_operator_delete(ptr);
3062     } else {
3063         locale__Locimp_dtor(this);
3064         if(flags & 1)
3065             MSVCRT_operator_delete(this);
3066     }
3067
3068     return this;
3069 }
3070
3071 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
3072 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
3073 void __cdecl locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
3074 {
3075     _Lockit lock;
3076
3077     TRACE("(%p %p %lu)\n", locimp, facet, id);
3078
3079     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3080     if(id >= locimp->facet_cnt) {
3081         MSVCP_size_t new_size = id+1;
3082         locale_facet **new_facetvec;
3083
3084         if(new_size < locale_id__Id_cnt+1)
3085             new_size = locale_id__Id_cnt+1;
3086
3087         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
3088         if(!new_facetvec) {
3089             _Lockit_dtor(&lock);
3090             ERR("Out of memory\n");
3091             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3092             return;
3093         }
3094
3095         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
3096         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
3097         MSVCRT_operator_delete(locimp->facetvec);
3098         locimp->facetvec = new_facetvec;
3099         locimp->facet_cnt = new_size;
3100     }
3101
3102     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
3103         call_locale_facet_vector_dtor(locimp->facetvec[id], 0);
3104
3105     locimp->facetvec[id] = facet;
3106     if(facet)
3107         locale_facet__Incref(facet);
3108     _Lockit_dtor(&lock);
3109 }
3110
3111 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
3112 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
3113 DEFINE_THISCALL_WRAPPER(locale__Locimp__Addfac, 12)
3114 void __thiscall locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
3115 {
3116     locale__Locimp__Locimp_Addfac(this, facet, id);
3117 }
3118
3119 /* ?_Clocptr_func@_Locimp@locale@std@@CAAAPAV123@XZ */
3120 /* ?_Clocptr_func@_Locimp@locale@std@@CAAEAPEAV123@XZ */
3121 locale__Locimp** __cdecl locale__Locimp__Clocptr_func(void)
3122 {
3123     FIXME("stub\n");
3124     return NULL;
3125 }
3126
3127 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
3128 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
3129 locale__Locimp* __cdecl locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
3130 {
3131     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
3132     return NULL;
3133 }
3134
3135 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
3136 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
3137 void __cdecl locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
3138 {
3139     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
3140 }
3141
3142 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
3143 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
3144 void __cdecl locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
3145 {
3146     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
3147 }
3148
3149 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
3150 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
3151 void __cdecl locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
3152 {
3153     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
3154 }
3155
3156 /* ??_7_Locimp@locale@std@@6B@ */
3157 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
3158     (vtable_ptr)THISCALL_NAME(MSVCP_locale__Locimp_vector_dtor)
3159 };
3160
3161 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
3162 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
3163 DEFINE_THISCALL_WRAPPER(locale_ctor_locimp, 8)
3164 locale* __thiscall locale_ctor_locimp(locale *this, locale__Locimp *locimp)
3165 {
3166     TRACE("(%p %p)\n", this, locimp);
3167     /* Don't change locimp reference counter */
3168     this->ptr = locimp;
3169     return this;
3170 }
3171
3172 /* ??0locale@std@@QAE@ABV01@0H@Z */
3173 /* ??0locale@std@@QEAA@AEBV01@0H@Z */
3174 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_locale, 16)
3175 locale* __thiscall locale_ctor_locale_locale(locale *this, const locale *loc, const locale *other, category cat)
3176 {
3177     FIXME("(%p %p %p %d) stub\n", this, loc, other, cat);
3178     return NULL;
3179 }
3180
3181 /* ??0locale@std@@QAE@ABV01@@Z */
3182 /* ??0locale@std@@QEAA@AEBV01@@Z */
3183 DEFINE_THISCALL_WRAPPER(locale_copy_ctor, 8)
3184 locale* __thiscall locale_copy_ctor(locale *this, const locale *copy)
3185 {
3186     TRACE("(%p %p)\n", this, copy);
3187     this->ptr = copy->ptr;
3188     locale_facet__Incref(&this->ptr->facet);
3189     return this;
3190 }
3191
3192 /* ??0locale@std@@QAE@ABV01@PBDH@Z */
3193 /* ??0locale@std@@QEAA@AEBV01@PEBDH@Z */
3194 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_cstr, 16)
3195 locale* __thiscall locale_ctor_locale_cstr(locale *this, const locale *loc, const char *locname, category cat)
3196 {
3197     FIXME("(%p %p %s %d) stub\n", this, loc, locname, cat);
3198     return NULL;
3199 }
3200
3201 /* ??0locale@std@@QAE@PBDH@Z */
3202 /* ??0locale@std@@QEAA@PEBDH@Z */
3203 DEFINE_THISCALL_WRAPPER(locale_ctor_cstr, 12)
3204 locale* __thiscall locale_ctor_cstr(locale *this, const char *locname, category cat)
3205 {
3206     FIXME("(%p %s %d) stub\n", this, locname, cat);
3207     return NULL;
3208 }
3209
3210 /* ??0locale@std@@QAE@W4_Uninitialized@1@@Z */
3211 /* ??0locale@std@@QEAA@W4_Uninitialized@1@@Z */
3212 DEFINE_THISCALL_WRAPPER(locale_ctor_uninitialized, 8)
3213 locale* __thiscall locale_ctor_uninitialized(locale *this, int uninitialized)
3214 {
3215     TRACE("(%p)\n", this);
3216     this->ptr = NULL;
3217     return this;
3218 }
3219
3220 /* ??0locale@std@@QAE@XZ */
3221 /* ??0locale@std@@QEAA@XZ */
3222 DEFINE_THISCALL_WRAPPER(locale_ctor, 4)
3223 locale* __thiscall locale_ctor(locale *this)
3224 {
3225     TRACE("(%p)\n", this);
3226     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
3227     if(!this->ptr) {
3228         ERR("Out of memory\n");
3229         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3230         return NULL;
3231     }
3232
3233     locale__Locimp_ctor(this->ptr);
3234     return this;
3235 }
3236
3237 /* ??1locale@std@@QAE@XZ */
3238 /* ??1locale@std@@QEAA@XZ */
3239 DEFINE_THISCALL_WRAPPER(locale_dtor, 4)
3240 void __thiscall locale_dtor(locale *this)
3241 {
3242     TRACE("(%p)\n", this);
3243     if(this->ptr)
3244         locale__Locimp_dtor(this->ptr);
3245 }
3246
3247 DEFINE_THISCALL_WRAPPER(MSVCP_locale_vector_dtor, 8)
3248 locale* __thiscall MSVCP_locale_vector_dtor(locale *this, unsigned int flags)
3249 {
3250     TRACE("(%p %x)\n", this, flags);
3251     if(flags & 2) {
3252         /* we have an array, with the number of elements stored before the first object */
3253         int i, *ptr = (int *)this-1;
3254
3255         for(i=*ptr-1; i>=0; i--)
3256             locale_dtor(this+i);
3257         MSVCRT_operator_delete(ptr);
3258     } else {
3259         locale_dtor(this);
3260         if(flags & 1)
3261             MSVCRT_operator_delete(this);
3262     }
3263
3264     return this;
3265 }
3266
3267 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
3268 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
3269 DEFINE_THISCALL_WRAPPER(locale_operator_assign, 8)
3270 locale* __thiscall locale_operator_assign(locale *this, const locale *loc)
3271 {
3272     FIXME("(%p %p) stub\n", this, loc);
3273     return NULL;
3274 }
3275
3276 /* ??8locale@std@@QBE_NABV01@@Z */
3277 /* ??8locale@std@@QEBA_NAEBV01@@Z */
3278 DEFINE_THISCALL_WRAPPER(locale_operator_equal, 8)
3279 MSVCP_bool __thiscall locale_operator_equal(const locale *this, const locale *loc)
3280 {
3281     FIXME("(%p %p) stub\n", this, loc);
3282     return 0;
3283 }
3284
3285 /* ??9locale@std@@QBE_NABV01@@Z */
3286 /* ??9locale@std@@QEBA_NAEBV01@@Z */
3287 DEFINE_THISCALL_WRAPPER(locale_operator_not_equal, 8)
3288 MSVCP_bool __thiscall locale_operator_not_equal(const locale *this, locale const *loc)
3289 {
3290     FIXME("(%p %p) stub\n", this, loc);
3291     return 0;
3292 }
3293
3294 /* ?_Addfac@locale@std@@QAEAAV12@PAVfacet@12@II@Z */
3295 /* ?_Addfac@locale@std@@QEAAAEAV12@PEAVfacet@12@_K1@Z */
3296 DEFINE_THISCALL_WRAPPER(locale__Addfac, 16)
3297 locale* __thiscall locale__Addfac(locale *this, locale_facet *facet, MSVCP_size_t id, MSVCP_size_t catmask)
3298 {
3299     TRACE("(%p %p %lu %lu)\n", this, facet, id, catmask);
3300
3301     if(this->ptr->facet.refs > 1) {
3302         locale__Locimp *new_ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
3303         if(!new_ptr) {
3304             ERR("Out of memory\n");
3305             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3306             return NULL;
3307         }
3308         locale__Locimp_copy_ctor(new_ptr, this->ptr);
3309         locale_facet__Decref(&this->ptr->facet);
3310         this->ptr = new_ptr;
3311     }
3312
3313     locale__Locimp__Addfac(this->ptr, facet, id);
3314
3315     if(catmask) {
3316         MSVCP_basic_string_char_dtor(&this->ptr->name);
3317         MSVCP_basic_string_char_ctor_cstr(&this->ptr->name, "*");
3318     }
3319     return this;
3320 }
3321
3322 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
3323 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
3324 DEFINE_THISCALL_WRAPPER(locale__Getfacet, 8)
3325 const locale_facet* __thiscall locale__Getfacet(const locale *this, MSVCP_size_t id)
3326 {
3327     FIXME("(%p %lu) stub\n", this, id);
3328     return NULL;
3329 }
3330
3331 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
3332 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
3333 locale__Locimp* __cdecl locale__Init(void)
3334 {
3335     FIXME("stub\n");
3336     return NULL;
3337 }
3338
3339 /* ?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ */
3340 /* ?_Getgloballocale@locale@std@@CAPEAV_Locimp@12@XZ */
3341 locale__Locimp* __cdecl locale__Getgloballocale(void)
3342 {
3343     FIXME("stub\n");
3344     return NULL;
3345 }
3346
3347 /* ?_Setgloballocale@locale@std@@CAXPAX@Z */
3348 /* ?_Setgloballocale@locale@std@@CAXPEAX@Z */
3349 void __cdecl locale__Setgloballocale(void *locimp)
3350 {
3351     FIXME("(%p) stub\n", locimp);
3352 }
3353
3354 /* ?classic@locale@std@@SAABV12@XZ */
3355 /* ?classic@locale@std@@SAAEBV12@XZ */
3356 const locale* __cdecl locale_classic(void)
3357 {
3358     FIXME("stub\n");
3359     return NULL;
3360 }
3361
3362 /* ?name@locale@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3363 /* ?name@locale@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3364 DEFINE_THISCALL_WRAPPER(locale_name, 8)
3365 basic_string_char* __thiscall locale_name(const locale *this, basic_string_char *ret)
3366 {
3367     TRACE( "(%p)\n", this);
3368     MSVCP_basic_string_char_copy_ctor(ret, &this->ptr->name);
3369     return ret;
3370 }
3371
3372 static const rtti_base_descriptor locale_facet_rtti_base_descriptor = {
3373     &locale_facet_type_info,
3374     0,
3375     { 0, -1, 0},
3376     64
3377 };
3378
3379 DEFINE_RTTI_DATA(collate_char, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@D@std@@");
3380 DEFINE_RTTI_DATA(collate_wchar, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@_W@std@@");
3381 DEFINE_RTTI_DATA(collate_short, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@G@std@@");
3382 DEFINE_RTTI_DATA(ctype_base, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AUctype_base@std@@");
3383 DEFINE_RTTI_DATA(ctype_char, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@D@std@@");
3384 DEFINE_RTTI_DATA(ctype_wchar, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@_W@std@@");
3385 DEFINE_RTTI_DATA(ctype_short, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@G@std@@");
3386 DEFINE_RTTI_DATA(numpunct_char, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$numpunct@D@std@@");
3387 DEFINE_RTTI_DATA(numpunct_wchar, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$numpunct@_W@std@@");
3388 DEFINE_RTTI_DATA(numpunct_short, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$numpunct@G@std@@");
3389
3390 #ifndef __GNUC__
3391 void __asm_dummy_vtables(void) {
3392 #endif
3393     __ASM_VTABLE(collate_char,
3394             VTABLE_ADD_FUNC(collate_char_do_compare)
3395             VTABLE_ADD_FUNC(collate_char_do_transform)
3396             VTABLE_ADD_FUNC(collate_char_do_hash));
3397     __ASM_VTABLE(collate_wchar,
3398             VTABLE_ADD_FUNC(collate_wchar_do_compare)
3399             VTABLE_ADD_FUNC(collate_wchar_do_transform)
3400             VTABLE_ADD_FUNC(collate_wchar_do_hash));
3401     __ASM_VTABLE(collate_short,
3402             VTABLE_ADD_FUNC(collate_wchar_do_compare)
3403             VTABLE_ADD_FUNC(collate_wchar_do_transform)
3404             VTABLE_ADD_FUNC(collate_wchar_do_hash));
3405     __ASM_VTABLE(ctype_base, "");
3406     __ASM_VTABLE(ctype_char,
3407             VTABLE_ADD_FUNC(ctype_char_do_tolower)
3408             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
3409             VTABLE_ADD_FUNC(ctype_char_do_toupper)
3410             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
3411             VTABLE_ADD_FUNC(ctype_char_do_widen)
3412             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
3413             VTABLE_ADD_FUNC(ctype_char__Do_widen_s)
3414             VTABLE_ADD_FUNC(ctype_char_do_narrow)
3415             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch)
3416             VTABLE_ADD_FUNC(ctype_char__Do_narrow_s));
3417     __ASM_VTABLE(ctype_wchar,
3418             VTABLE_ADD_FUNC(ctype_wchar_do_is)
3419             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
3420             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
3421             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
3422             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
3423             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
3424             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
3425             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
3426             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
3427             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
3428             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
3429             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
3430             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
3431             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
3432     __ASM_VTABLE(ctype_short,
3433             VTABLE_ADD_FUNC(ctype_wchar_do_is)
3434             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
3435             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
3436             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
3437             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
3438             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
3439             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
3440             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
3441             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
3442             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
3443             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
3444             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
3445             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
3446             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
3447     __ASM_VTABLE(numpunct_char,
3448             VTABLE_ADD_FUNC(numpunct_char_do_decimal_point)
3449             VTABLE_ADD_FUNC(numpunct_char_do_thousands_sep)
3450             VTABLE_ADD_FUNC(numpunct_char_do_grouping)
3451             VTABLE_ADD_FUNC(numpunct_char_do_falsename)
3452             VTABLE_ADD_FUNC(numpunct_char_do_truename));
3453     __ASM_VTABLE(numpunct_wchar,
3454             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
3455             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
3456             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
3457             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
3458             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
3459     __ASM_VTABLE(numpunct_short,
3460             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
3461             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
3462             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
3463             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
3464             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
3465 #ifndef __GNUC__
3466 }
3467 #endif