msvcp90: Hold _LOCK_LOCALE critical section while _Lockinfo object exists.
[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
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcp90);
31
32 char* __cdecl _Getdays(void);
33 char* __cdecl _Getmonths(void);
34 void* __cdecl _Gettnames(void);
35
36 typedef int category;
37
38 typedef struct {
39     MSVCP_size_t id;
40 } locale_id;
41
42 typedef struct {
43     const vtable_ptr *vtable;
44     MSVCP_size_t refs;
45 } locale_facet;
46
47 typedef struct _locale__Locimp {
48     locale_facet facet;
49     locale_facet **facetvec;
50     MSVCP_size_t facet_cnt;
51     category catmask;
52     MSVCP_bool transparent;
53     basic_string_char name;
54 } locale__Locimp;
55
56 typedef struct {
57     void *timeptr;
58 } _Timevec;
59
60 typedef struct {
61     _Lockit lock;
62     basic_string_char days;
63     basic_string_char months;
64     basic_string_char oldlocname;
65     basic_string_char newlocname;
66 } _Locinfo;
67
68 typedef struct {
69     LCID handle;
70     unsigned page;
71 } _Collvec;
72
73 typedef struct {
74     LCID handle;
75     unsigned page;
76     const short *table;
77     int delfl;
78 } _Ctypevec;
79
80 typedef struct {
81     LCID handle;
82     unsigned page;
83 } _Cvtvec;
84
85 typedef struct {
86     locale_facet facet;
87     _Collvec coll;
88 } collate;
89
90 typedef struct {
91     locale_facet facet;
92 } ctype_base;
93
94 typedef struct {
95     ctype_base base;
96     _Ctypevec ctype;
97 } ctype_char;
98
99 typedef struct {
100     ctype_base base;
101     _Ctypevec ctype;
102     _Cvtvec cvt;
103 } ctype_wchar;
104
105 /* ?_Id_cnt@id@locale@std@@0HA */
106 int locale_id__Id_cnt = 0;
107
108 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
109 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
110 locale__Locimp *locale__Locimp__Clocptr = NULL;
111
112 /* ??1facet@locale@std@@UAE@XZ */
113 /* ??1facet@locale@std@@UEAA@XZ */
114 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
115 void __thiscall locale_facet_dtor(locale_facet *this)
116 {
117     TRACE("(%p)\n", this);
118 }
119
120 DEFINE_THISCALL_WRAPPER(MSVCP_locale_facet_vector_dtor, 8)
121 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
122         locale_facet*, (locale_facet*, unsigned int), (this, flags))
123 locale_facet* __thiscall MSVCP_locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
124 {
125     TRACE("(%p %x)\n", this, flags);
126     if(flags & 2) {
127         /* we have an array, with the number of elements stored before the first object */
128         int i, *ptr = (int *)this-1;
129
130         for(i=*ptr-1; i>=0; i--)
131             locale_facet_dtor(this+i);
132         MSVCRT_operator_delete(ptr);
133     } else {
134         locale_facet_dtor(this);
135         if(flags & 1)
136             MSVCRT_operator_delete(this);
137     }
138
139     return this;
140 }
141
142 const vtable_ptr MSVCP_locale_facet_vtable[] = {
143     (vtable_ptr)THISCALL_NAME(MSVCP_locale_facet_vector_dtor)
144 };
145
146 /* ??0id@locale@std@@QAE@I@Z */
147 /* ??0id@locale@std@@QEAA@_K@Z */
148 DEFINE_THISCALL_WRAPPER(locale_id_ctor_id, 8)
149 locale_id* __thiscall locale_id_ctor_id(locale_id *this, MSVCP_size_t id)
150 {
151     TRACE("(%p %lu)\n", this, id);
152
153     this->id = id;
154     return this;
155 }
156
157 /* ??_Fid@locale@std@@QAEXXZ */
158 /* ??_Fid@locale@std@@QEAAXXZ */
159 DEFINE_THISCALL_WRAPPER(locale_id_ctor, 4)
160 locale_id* __thiscall locale_id_ctor(locale_id *this)
161 {
162     TRACE("(%p)\n", this);
163
164     this->id = 0;
165     return this;
166 }
167
168 /* ??Bid@locale@std@@QAEIXZ */
169 /* ??Bid@locale@std@@QEAA_KXZ */
170 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
171 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
172 {
173     _Lockit lock;
174
175     TRACE("(%p)\n", this);
176
177     if(!this->id) {
178         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
179         this->id = ++locale_id__Id_cnt;
180         _Lockit_dtor(&lock);
181     }
182
183     return this->id;
184 }
185
186 /* ?_Id_cnt_func@id@locale@std@@CAAAHXZ */
187 /* ?_Id_cnt_func@id@locale@std@@CAAEAHXZ */
188 int* __cdecl locale_id__Id_cnt_func(void)
189 {
190     TRACE("\n");
191     return &locale_id__Id_cnt;
192 }
193
194 /* ??_Ffacet@locale@std@@QAEXXZ */
195 /* ??_Ffacet@locale@std@@QEAAXXZ */
196 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
197 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
198 {
199     TRACE("(%p)\n", this);
200     this->vtable = MSVCP_locale_facet_vtable;
201     this->refs = 0;
202     return this;
203 }
204
205 /* ??0facet@locale@std@@IAE@I@Z */
206 /* ??0facet@locale@std@@IEAA@_K@Z */
207 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
208 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
209 {
210     TRACE("(%p %lu)\n", this, refs);
211     this->vtable = MSVCP_locale_facet_vtable;
212     this->refs = refs;
213     return this;
214 }
215
216 /* ?_Incref@facet@locale@std@@QAEXXZ */
217 /* ?_Incref@facet@locale@std@@QEAAXXZ */
218 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
219 void __thiscall locale_facet__Incref(locale_facet *this)
220 {
221     _Lockit lock;
222
223     TRACE("(%p)\n", this);
224
225     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
226     this->refs++;
227     _Lockit_dtor(&lock);
228 }
229
230 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
231 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
232 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
233 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
234 {
235     _Lockit lock;
236     locale_facet *ret;
237
238     TRACE("(%p)\n", this);
239
240     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
241     if(this->refs)
242         this->refs--;
243
244     ret = this->refs ? NULL : this;
245     _Lockit_dtor(&lock);
246
247     return ret;
248 }
249
250 /* ?_Getcat@facet@locale@std@@SAIPAPBV123@PBV23@@Z */
251 /* ?_Getcat@facet@locale@std@@SA_KPEAPEBV123@PEBV23@@Z */
252 MSVCP_size_t __cdecl locale_facet__Getcat(const locale_facet **facet, const locale *loc)
253 {
254     TRACE("(%p %p)\n", facet, loc);
255     return -1;
256 }
257
258 /* ??0_Timevec@std@@QAE@ABV01@@Z */
259 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
260 /* This copy constructor modifies copied object */
261 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
262 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
263 {
264     TRACE("(%p %p)\n", this, copy);
265     this->timeptr = copy->timeptr;
266     copy->timeptr = NULL;
267     return this;
268 }
269
270 /* ??0_Timevec@std@@QAE@PAX@Z */
271 /* ??0_Timevec@std@@QEAA@PEAX@Z */
272 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
273 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
274 {
275     TRACE("(%p %p)\n", this, timeptr);
276     this->timeptr = timeptr;
277     return this;
278 }
279
280 /* ??_F_Timevec@std@@QAEXXZ */
281 /* ??_F_Timevec@std@@QEAAXXZ */
282 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
283 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
284 {
285     TRACE("(%p)\n", this);
286     this->timeptr = NULL;
287     return this;
288 }
289
290 /* ??1_Timevec@std@@QAE@XZ */
291 /* ??1_Timevec@std@@QEAA@XZ */
292 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
293 void __thiscall _Timevec_dtor(_Timevec *this)
294 {
295     TRACE("(%p)\n", this);
296     free(this->timeptr);
297 }
298
299 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
300 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
301 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
302 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
303 {
304     TRACE("(%p %p)\n", this, right);
305     this->timeptr = right->timeptr;
306     right->timeptr = NULL;
307     return this;
308 }
309
310 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
311 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
312 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
313 void* __thiscall _Timevec__Getptr(_Timevec *this)
314 {
315     TRACE("(%p)\n", this);
316     return this->timeptr;
317 }
318
319 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
320 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
321 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
322 {
323     const char *locale = NULL;
324
325     /* This function is probably modifying more global objects */
326     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
327
328     if(!locstr)
329         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
330
331     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
332     MSVCP_basic_string_char_ctor_cstr(&locinfo->days, "");
333     MSVCP_basic_string_char_ctor_cstr(&locinfo->months, "");
334     MSVCP_basic_string_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
335
336     if(category)
337         locale = setlocale(LC_ALL, locstr);
338     else
339         locale = setlocale(LC_ALL, NULL);
340
341     if(locale)
342         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
343     else
344         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
345
346     return locinfo;
347 }
348
349 /* ??0_Locinfo@std@@QAE@HPBD@Z */
350 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
351 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
352 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
353 {
354     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
355 }
356
357 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
358 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
359 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_bstr(_Locinfo *locinfo, const basic_string_char *locstr)
360 {
361     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
362 }
363
364 /* ??0_Locinfo@std@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
365 /* ??0_Locinfo@std@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
366 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_bstr, 8)
367 _Locinfo* __thiscall _Locinfo_ctor_bstr(_Locinfo *this, const basic_string_char *locstr)
368 {
369     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
370 }
371
372 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z */
373 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@PEBD@Z */
374 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cstr(_Locinfo *locinfo, const char *locstr)
375 {
376     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, locstr);
377 }
378
379 /* ??0_Locinfo@std@@QAE@PBD@Z */
380 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
381 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
382 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
383 {
384     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
385 }
386
387 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
388 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
389 void __cdecl _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
390 {
391     TRACE("(%p)\n", locinfo);
392
393     setlocale(LC_ALL, MSVCP_basic_string_char_c_str(&locinfo->oldlocname));
394     MSVCP_basic_string_char_dtor(&locinfo->days);
395     MSVCP_basic_string_char_dtor(&locinfo->months);
396     MSVCP_basic_string_char_dtor(&locinfo->oldlocname);
397     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
398     _Lockit_dtor(&locinfo->lock);
399 }
400
401 /* ??_F_Locinfo@std@@QAEXXZ */
402 /* ??_F_Locinfo@std@@QEAAXXZ */
403 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
404 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
405 {
406     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
407 }
408
409 /* ??1_Locinfo@std@@QAE@XZ */
410 /* ??1_Locinfo@std@@QEAA@XZ */
411 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
412 void __thiscall _Locinfo_dtor(_Locinfo *this)
413 {
414     _Locinfo__Locinfo_dtor(this);
415 }
416
417 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
418 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
419 _Locinfo* __cdecl _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
420 {
421     const char *locale = NULL;
422
423     /* This function is probably modifying more global objects */
424     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
425     if(!locstr)
426         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
427
428     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
429
430     if(category)
431         locale = setlocale(LC_ALL, locstr);
432     else
433         locale = setlocale(LC_ALL, NULL);
434
435     if(locale)
436         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
437     else
438         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
439
440     return locinfo;
441 }
442
443 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
444 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
445 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
446 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
447 {
448     return _Locinfo__Locinfo_Addcats(this, category, locstr);
449 }
450
451 /* _Getcoll */
452 _Collvec __cdecl _Getcoll(void)
453 {
454     _Collvec ret;
455     _locale_t locale = _get_current_locale();
456
457     TRACE("\n");
458
459     ret.page = locale->locinfo->lc_collate_cp;
460     ret.handle = locale->locinfo->lc_handle[LC_COLLATE];
461     _free_locale(locale);
462     return ret;
463 }
464
465 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
466 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
467 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 4)
468 _Collvec __thiscall _Locinfo__Getcoll(const _Locinfo *this)
469 {
470     return _Getcoll();
471 }
472
473 /* _Getctype */
474 _Ctypevec __cdecl _Getctype(void)
475 {
476     _Ctypevec ret;
477     _locale_t locale = _get_current_locale();
478     short *table;
479
480     TRACE("\n");
481
482     ret.page = locale->locinfo->lc_codepage;
483     ret.handle = locale->locinfo->lc_handle[LC_COLLATE];
484     ret.delfl = TRUE;
485     table = malloc(sizeof(short[256]));
486     if(!table) {
487         _free_locale(locale);
488         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
489     }
490     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
491     ret.table = table;
492     _free_locale(locale);
493     return ret;
494 }
495
496 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
497 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
498 DEFINE_THISCALL_WRAPPER_RETPTR(_Locinfo__Getctype, 4)
499 _Ctypevec __thiscall _Locinfo__Getctype(const _Locinfo *this)
500 {
501     return _Getctype();
502 }
503
504 /* _Getcvt */
505 _Cvtvec __cdecl _Getcvt(void)
506 {
507     _Cvtvec ret;
508     _locale_t locale = _get_current_locale();
509
510     TRACE("\n");
511
512     ret.page = locale->locinfo->lc_codepage;
513     ret.handle = locale->locinfo->lc_handle[LC_CTYPE];
514     _free_locale(locale);
515     return ret;
516 }
517
518 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
519 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
520 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 4)
521 _Cvtvec __thiscall _Locinfo__Getcvt(const _Locinfo *this)
522 {
523     return _Getcvt();
524 }
525
526 /* ?_Getdateorder@_Locinfo@std@@QBEHXZ */
527 /* ?_Getdateorder@_Locinfo@std@@QEBAHXZ */
528 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdateorder, 4)
529 int __thiscall _Locinfo__Getdateorder(const _Locinfo *this)
530 {
531     FIXME("(%p) stub\n", this);
532     return 0;
533 }
534
535 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
536 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
537 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
538 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
539 {
540     char *days = _Getdays();
541
542     TRACE("(%p)\n", this);
543
544     if(days) {
545         MSVCP_basic_string_char_dtor(&this->days);
546         MSVCP_basic_string_char_ctor_cstr(&this->days, days);
547         free(days);
548     }
549
550     return this->days.size ? MSVCP_basic_string_char_c_str(&this->days) :
551         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
552 }
553
554 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
555 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
556 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
557 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
558 {
559     char *months = _Getmonths();
560
561     TRACE("(%p)\n", this);
562
563     if(months) {
564         MSVCP_basic_string_char_dtor(&this->months);
565         MSVCP_basic_string_char_ctor_cstr(&this->months, months);
566         free(months);
567     }
568
569     return this->months.size ? MSVCP_basic_string_char_c_str(&this->months) :
570         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
571         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
572 }
573
574 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
575 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
576 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
577 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
578 {
579     TRACE("(%p)\n", this);
580     return "false";
581 }
582
583 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
584 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
585 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
586 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
587 {
588     TRACE("(%p)\n", this);
589     return "true";
590 }
591
592 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
593 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
594 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
595 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
596 {
597     TRACE("(%p)\n", this);
598     return localeconv();
599 }
600
601 /* ?_Getname@_Locinfo@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
602 /* ?_Getname@_Locinfo@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
603 DEFINE_THISCALL_WRAPPER_RETPTR(_Locinfo__Getname, 4)
604 basic_string_char __thiscall _Locinfo__Getname(const _Locinfo *this)
605 {
606     basic_string_char ret;
607
608     TRACE("(%p)\n", this);
609
610     MSVCP_basic_string_char_copy_ctor(&ret, &this->newlocname);
611     return ret;
612 }
613
614 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
615 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
616 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 4)
617 _Timevec __thiscall _Locinfo__Gettnames(const _Locinfo *this)
618 {
619     _Timevec ret;
620
621     TRACE("(%p)\n", this);
622
623     _Timevec_ctor_timeptr(&ret, _Gettnames());
624     return ret;
625 }
626
627 static const type_info locale_facet_type_info = {
628     MSVCP_locale_facet_vtable,
629     NULL,
630     ".?AVfacet@locale@std@@"
631 };
632
633 /* ?id@?$collate@D@std@@2V0locale@2@A */
634 locale_id collate_char_id = {0};
635
636 /* ??_7?$collate@D@std@@6B@ */
637 extern const vtable_ptr MSVCP_collate_char_vtable;
638
639 /* ?_Init@?$collate@D@std@@IAEXABV_Locinfo@2@@Z */
640 /* ?_Init@?$collate@D@std@@IEAAXAEBV_Locinfo@2@@Z */
641 DEFINE_THISCALL_WRAPPER(collate_char__Init, 8)
642 void __thiscall collate_char__Init(collate *this, const _Locinfo *locinfo)
643 {
644     TRACE("(%p %p)\n", this, locinfo);
645     this->coll = _Locinfo__Getcoll(locinfo);
646 }
647
648 /* ??0?$collate@D@std@@IAE@PBDI@Z */
649 /* ??0?$collate@D@std@@IEAA@PEBD_K@Z */
650 DEFINE_THISCALL_WRAPPER(collate_char_ctor_name, 12)
651 collate* __thiscall collate_char_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
652 {
653     _Locinfo locinfo;
654
655     TRACE("(%p %s %lu)\n", this, name, refs);
656
657     locale_facet_ctor_refs(&this->facet, refs);
658     this->facet.vtable = &MSVCP_collate_char_vtable;
659
660     _Locinfo_ctor_cstr(&locinfo, name);
661     collate_char__Init(this, &locinfo);
662     _Locinfo_dtor(&locinfo);
663     return this;
664 }
665
666 /* ??0?$collate@D@std@@QAE@ABV_Locinfo@1@I@Z */
667 /* ??0?$collate@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
668 DEFINE_THISCALL_WRAPPER(collate_char_ctor_locinfo, 12)
669 collate* __thiscall collate_char_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
670 {
671     TRACE("(%p %p %lu)\n", this, locinfo, refs);
672
673     locale_facet_ctor_refs(&this->facet, refs);
674     this->facet.vtable = &MSVCP_collate_char_vtable;
675     collate_char__Init(this, locinfo);
676     return this;
677 }
678
679 /* ??0?$collate@D@std@@QAE@I@Z */
680 /* ??0?$collate@D@std@@QEAA@_K@Z */
681 DEFINE_THISCALL_WRAPPER(collate_char_ctor_refs, 8)
682 collate* __thiscall collate_char_ctor_refs(collate *this, MSVCP_size_t refs)
683 {
684     return collate_char_ctor_name(this, "C", refs);
685 }
686
687 /* ??1?$collate@D@std@@MAE@XZ */
688 /* ??1?$collate@D@std@@MEAA@XZ */
689 DEFINE_THISCALL_WRAPPER(collate_char_dtor, 4)
690 void __thiscall collate_char_dtor(collate *this)
691 {
692     TRACE("(%p)\n", this);
693 }
694
695 DEFINE_THISCALL_WRAPPER(MSVCP_collate_char_vector_dtor, 8)
696 collate* __thiscall MSVCP_collate_char_vector_dtor(collate *this, unsigned int flags)
697 {
698     TRACE("(%p %x)\n", this, flags);
699     if(flags & 2) {
700         /* we have an array, with the number of elements stored before the first object */
701         int i, *ptr = (int *)this-1;
702
703         for(i=*ptr-1; i>=0; i--)
704             collate_char_dtor(this+i);
705         MSVCRT_operator_delete(ptr);
706     } else {
707         collate_char_dtor(this);
708         if(flags & 1)
709             MSVCRT_operator_delete(this);
710     }
711
712     return this;
713 }
714
715 /* ??_F?$collate@D@std@@QAEXXZ */
716 /* ??_F?$collate@D@std@@QEAAXXZ */
717 DEFINE_THISCALL_WRAPPER(collate_char_ctor, 4)
718 collate* __thiscall collate_char_ctor(collate *this)
719 {
720     return collate_char_ctor_name(this, "C", 0);
721 }
722
723 /* ?_Getcat@?$collate@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
724 /* ?_Getcat@?$collate@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
725 MSVCP_size_t __cdecl collate_char__Getcat(const locale_facet **facet, const locale *loc)
726 {
727     TRACE("(%p %p)\n", facet, loc);
728
729     if(facet && !*facet) {
730         *facet = MSVCRT_operator_new(sizeof(collate));
731         if(!*facet) {
732             ERR("Out of memory\n");
733             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
734             return 0;
735         }
736         collate_char_ctor_name((collate*)*facet,
737                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
738     }
739
740     return LC_COLLATE;
741 }
742
743 /* _Strcoll */
744 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
745         const char *last2, const _Collvec *coll)
746 {
747     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
748     return CompareStringA(coll->handle, 0, first1, last1-first1, first2, last2-first2)-2;
749 }
750
751 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
752 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
753 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
754 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
755         (const collate*, const char*, const char*, const char*, const char*), \
756         (this, first1, last1, first2, last2))
757 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
758         const char *last1, const char *first2, const char *last2)
759 {
760     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
761     return _Strcoll(first1, last1, first2, last2, &this->coll);
762 }
763
764 /* ?compare@?$collate@D@std@@QBEHPBD000@Z */
765 /* ?compare@?$collate@D@std@@QEBAHPEBD000@Z */
766 DEFINE_THISCALL_WRAPPER(collate_char_compare, 20)
767 int __thiscall collate_char_compare(const collate *this, const char *first1,
768         const char *last1, const char *first2, const char *last2)
769 {
770     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
771     return call_collate_char_do_compare(this, first1, last1, first2, last2);
772 }
773
774 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
775 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
776 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
777 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
778         (const collate*, const char*, const char*), (this, first, last))
779 LONG __thiscall collate_char_do_hash(const collate *this,
780         const char *first, const char *last)
781 {
782     ULONG ret = 0;
783
784     TRACE("(%p %p %p)\n", this, first, last);
785
786     for(; first<last; first++)
787         ret = (ret<<8 | ret>>24) + *first;
788     return ret;
789 }
790
791 /* ?hash@?$collate@D@std@@QBEJPBD0@Z */
792 /* ?hash@?$collate@D@std@@QEBAJPEBD0@Z */
793 DEFINE_THISCALL_WRAPPER(collate_char_hash, 12)
794 LONG __thiscall collate_char_hash(const collate *this,
795         const char *first, const char *last)
796 {
797     TRACE("(%p %p %p)\n", this, first, last);
798     return call_collate_char_do_hash(this, first, last);
799 }
800
801 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
802 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
803 DEFINE_THISCALL_WRAPPER_RETPTR(collate_char_do_transform, 12)
804 basic_string_char __thiscall collate_char_do_transform(const collate *this,
805         const char *first, const char *last)
806 {
807     basic_string_char ret = {0}; /* FIXME */
808     FIXME("(%p %p %p) stub\n", this, first, last);
809     return ret;
810 }
811
812 /* ?transform@?$collate@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
813 /* ?transform@?$collate@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
814 DEFINE_THISCALL_WRAPPER_RETPTR(collate_char_transform, 12)
815 basic_string_char __thiscall collate_char_transform(const collate *this,
816         const char *first, const char *last)
817 {
818     basic_string_char ret = {0}; /* FIXME */
819     FIXME("(%p %p %p) stub\n", this, first, last);
820     return ret;
821 }
822
823 /* ?id@?$collate@_W@std@@2V0locale@2@A */
824 locale_id collate_wchar_id = {0};
825 /* ?id@?$collate@G@std@@2V0locale@2@A */
826 locale_id collate_short_id = {0};
827
828 /* ??_7?$collate@_W@std@@6B@ */
829 extern const vtable_ptr MSVCP_collate_wchar_vtable;
830 /* ??_7?$collate@G@std@@6B@ */
831 extern const vtable_ptr MSVCP_collate_short_vtable;
832
833 /* ?_Init@?$collate@_W@std@@IAEXABV_Locinfo@2@@Z */
834 /* ?_Init@?$collate@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
835 /* ?_Init@?$collate@G@std@@IAEXABV_Locinfo@2@@Z */
836 /* ?_Init@?$collate@G@std@@IEAAXAEBV_Locinfo@2@@Z */
837 DEFINE_THISCALL_WRAPPER(collate_wchar__Init, 8)
838 void __thiscall collate_wchar__Init(collate *this, const _Locinfo *locinfo)
839 {
840     TRACE("(%p %p)\n", this, locinfo);
841     this->coll = _Locinfo__Getcoll(locinfo);
842 }
843
844 /* ??0?$collate@_W@std@@IAE@PBDI@Z */
845 /* ??0?$collate@_W@std@@IEAA@PEBD_K@Z */
846 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_name, 12)
847 collate* __thiscall collate_wchar_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
848 {
849     _Locinfo locinfo;
850
851     TRACE("(%p %s %lu)\n", this, name, refs);
852
853     locale_facet_ctor_refs(&this->facet, refs);
854     this->facet.vtable = &MSVCP_collate_wchar_vtable;
855
856     _Locinfo_ctor_cstr(&locinfo, name);
857     collate_wchar__Init(this, &locinfo);
858     _Locinfo_dtor(&locinfo);
859     return this;
860 }
861
862 /* ??0?$collate@G@std@@IAE@PBDI@Z */
863 /* ??0?$collate@G@std@@IEAA@PEBD_K@Z */
864 DEFINE_THISCALL_WRAPPER(collate_short_ctor_name, 12)
865 collate* __thiscall collate_short_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
866 {
867     collate *ret = collate_wchar_ctor_name(this, name, refs);
868     ret->facet.vtable = &MSVCP_collate_short_vtable;
869     return ret;
870 }
871
872 /* ??0?$collate@_W@std@@QAE@ABV_Locinfo@1@I@Z */
873 /* ??0?$collate@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
874 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_locinfo, 12)
875 collate* __thiscall collate_wchar_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
876 {
877     TRACE("(%p %p %lu)\n", this, locinfo, refs);
878
879     locale_facet_ctor_refs(&this->facet, refs);
880     this->facet.vtable = &MSVCP_collate_wchar_vtable;
881     collate_wchar__Init(this, locinfo);
882     return this;
883 }
884
885 /* ??0?$collate@G@std@@QAE@ABV_Locinfo@1@I@Z */
886 /* ??0?$collate@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
887 DEFINE_THISCALL_WRAPPER(collate_short_ctor_locinfo, 12)
888 collate* __thiscall collate_short_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
889 {
890     collate *ret = collate_wchar_ctor_locinfo(this, locinfo, refs);
891     ret->facet.vtable = &MSVCP_collate_short_vtable;
892     return ret;
893 }
894
895 /* ??0?$collate@_W@std@@QAE@I@Z */
896 /* ??0?$collate@_W@std@@QEAA@_K@Z */
897 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_refs, 8)
898 collate* __thiscall collate_wchar_ctor_refs(collate *this, MSVCP_size_t refs)
899 {
900     return collate_wchar_ctor_name(this, "C", refs);
901 }
902
903 /* ??0?$collate@G@std@@QAE@I@Z */
904 /* ??0?$collate@G@std@@QEAA@_K@Z */
905 DEFINE_THISCALL_WRAPPER(collate_short_ctor_refs, 8)
906 collate* __thiscall collate_short_ctor_refs(collate *this, MSVCP_size_t refs)
907 {
908     collate *ret = collate_wchar_ctor_refs(this, refs);
909     ret->facet.vtable = &MSVCP_collate_short_vtable;
910     return ret;
911 }
912
913 /* ??1?$collate@_W@std@@MAE@XZ */
914 /* ??1?$collate@_W@std@@MEAA@XZ */
915 /* ??1?$collate@G@std@@MAE@XZ */
916 /* ??1?$collate@G@std@@MEAA@XZ */
917 DEFINE_THISCALL_WRAPPER(collate_wchar_dtor, 4)
918 void __thiscall collate_wchar_dtor(collate *this)
919 {
920     TRACE("(%p)\n", this);
921 }
922
923 DEFINE_THISCALL_WRAPPER(MSVCP_collate_wchar_vector_dtor, 8)
924 collate* __thiscall MSVCP_collate_wchar_vector_dtor(collate *this, unsigned int flags)
925 {
926     TRACE("(%p %x)\n", this, flags);
927     if(flags & 2) {
928         /* we have an array, with the number of elements stored before the first object */
929         int i, *ptr = (int *)this-1;
930
931         for(i=*ptr-1; i>=0; i--)
932             collate_wchar_dtor(this+i);
933         MSVCRT_operator_delete(ptr);
934     } else {
935         collate_wchar_dtor(this);
936         if(flags & 1)
937             MSVCRT_operator_delete(this);
938     }
939
940     return this;
941 }
942
943 DEFINE_THISCALL_WRAPPER(MSVCP_collate_short_vector_dtor, 8)
944 collate* __thiscall MSVCP_collate_short_vector_dtor(collate *this, unsigned int flags)
945 {
946     return MSVCP_collate_wchar_vector_dtor(this, flags);
947 }
948
949 /* ??_F?$collate@_W@std@@QAEXXZ */
950 /* ??_F?$collate@_W@std@@QEAAXXZ */
951 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor, 4)
952 collate* __thiscall collate_wchar_ctor(collate *this)
953 {
954     return collate_wchar_ctor_name(this, "C", 0);
955 }
956
957 /* ??_F?$collate@G@std@@QAEXXZ */
958 /* ??_F?$collate@G@std@@QEAAXXZ */
959 DEFINE_THISCALL_WRAPPER(collate_short_ctor, 4)
960 collate* __thiscall collate_short_ctor(collate *this)
961 {
962     collate *ret = collate_wchar_ctor(this);
963     ret->facet.vtable = &MSVCP_collate_short_vtable;
964     return ret;
965 }
966
967 /* ?_Getcat@?$collate@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
968 /* ?_Getcat@?$collate@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
969 /* ?_Getcat@?$collate@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
970 /* ?_Getcat@?$collate@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
971 MSVCP_size_t __cdecl collate_wchar__Getcat(const locale_facet **facet, const locale *loc)
972 {
973     TRACE("(%p %p)\n", facet, loc);
974
975     if(facet && !*facet) {
976         *facet = MSVCRT_operator_new(sizeof(collate));
977         if(!*facet) {
978             ERR("Out of memory\n");
979             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
980             return 0;
981         }
982         collate_wchar_ctor_name((collate*)*facet,
983                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
984     }
985
986     return LC_COLLATE;
987 }
988
989 /* _Wcscoll */
990 int __cdecl _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
991         const wchar_t *last2, const _Collvec *coll)
992 {
993     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
994     return CompareStringW(coll->handle, 0, first1, last1-first1, first2, last2-first2)-2;
995 }
996
997 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
998 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
999 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
1000 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
1001 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
1002 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
1003         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
1004         (this, first1, last1, first2, last2))
1005 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
1006         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1007 {
1008     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1009     return _Wcscoll(first1, last1, first2, last2, &this->coll);
1010 }
1011
1012 /* ?compare@?$collate@_W@std@@QBEHPB_W000@Z */
1013 /* ?compare@?$collate@_W@std@@QEBAHPEB_W000@Z */
1014 /* ?compare@?$collate@G@std@@QBEHPBG000@Z */
1015 /* ?compare@?$collate@G@std@@QEBAHPEBG000@Z */
1016 DEFINE_THISCALL_WRAPPER(collate_wchar_compare, 20)
1017 int __thiscall collate_wchar_compare(const collate *this, const wchar_t *first1,
1018         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1019 {
1020     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1021     return call_collate_wchar_do_compare(this, first1, last1, first2, last2);
1022 }
1023
1024 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
1025 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
1026 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
1027 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
1028 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
1029 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
1030         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
1031 LONG __thiscall collate_wchar_do_hash(const collate *this,
1032         const wchar_t *first, const wchar_t *last)
1033 {
1034     ULONG ret = 0;
1035
1036     TRACE("(%p %p %p)\n", this, first, last);
1037
1038     for(; first<last; first++)
1039         ret = (ret<<8 | ret>>24) + *first;
1040     return ret;
1041 }
1042
1043 /* ?hash@?$collate@_W@std@@QBEJPB_W0@Z */
1044 /* ?hash@?$collate@_W@std@@QEBAJPEB_W0@Z */
1045 /* ?hash@?$collate@G@std@@QBEJPBG0@Z */
1046 /* ?hash@?$collate@G@std@@QEBAJPEBG0@Z */
1047 DEFINE_THISCALL_WRAPPER(collate_wchar_hash, 12)
1048 LONG __thiscall collate_wchar_hash(const collate *this,
1049         const wchar_t *first, const wchar_t *last)
1050 {
1051     TRACE("(%p %p %p)\n", this, first, last);
1052     return call_collate_wchar_do_hash(this, first, last);
1053 }
1054
1055 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1056 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1057 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1058 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1059 DEFINE_THISCALL_WRAPPER_RETPTR(collate_wchar_do_transform, 12)
1060 basic_string_wchar __thiscall collate_wchar_do_transform(const collate *this,
1061         const wchar_t *first, const wchar_t *last)
1062 {
1063     basic_string_wchar ret = {0}; /* FIXME */
1064     FIXME("(%p %p %p) stub\n", this, first, last);
1065     return ret;
1066 }
1067
1068 /* ?transform@?$collate@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1069 /* ?transform@?$collate@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1070 /* ?transform@?$collate@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1071 /* ?transform@?$collate@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1072 DEFINE_THISCALL_WRAPPER_RETPTR(collate_wchar_transform, 12)
1073 basic_string_wchar __thiscall collate_wchar_transform(const collate *this,
1074         const wchar_t *first, const wchar_t *last)
1075 {
1076     basic_string_wchar ret = {0}; /* FIXME */
1077     FIXME("(%p %p %p) stub\n", this, first, last);
1078     return ret;
1079 }
1080
1081 /* ??_7ctype_base@std@@6B@ */
1082 extern const vtable_ptr MSVCP_ctype_base_vtable;
1083
1084 /* ??0ctype_base@std@@QAE@I@Z */
1085 /* ??0ctype_base@std@@QEAA@_K@Z */
1086 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
1087 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
1088 {
1089     TRACE("(%p %lu)\n", this, refs);
1090     locale_facet_ctor_refs(&this->facet, refs);
1091     this->facet.vtable = &MSVCP_ctype_base_vtable;
1092     return this;
1093 }
1094
1095 /* ??_Fctype_base@std@@QAEXXZ */
1096 /* ??_Fctype_base@std@@QEAAXXZ */
1097 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
1098 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
1099 {
1100     TRACE("(%p)\n", this);
1101     locale_facet_ctor_refs(&this->facet, 0);
1102     this->facet.vtable = &MSVCP_ctype_base_vtable;
1103     return this;
1104 }
1105
1106 /* ??1ctype_base@std@@UAE@XZ */
1107 /* ??1ctype_base@std@@UEAA@XZ */
1108 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
1109 void __thiscall ctype_base_dtor(ctype_base *this)
1110 {
1111     TRACE("(%p)\n", this);
1112 }
1113
1114 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_base_vector_dtor, 8)
1115 ctype_base* __thiscall MSVCP_ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
1116 {
1117     TRACE("(%p %x)\n", this, flags);
1118     if(flags & 2) {
1119         /* we have an array, with the number of elements stored before the first object */
1120         int i, *ptr = (int *)this-1;
1121
1122         for(i=*ptr-1; i>=0; i--)
1123             ctype_base_dtor(this+i);
1124         MSVCRT_operator_delete(ptr);
1125     } else {
1126         ctype_base_dtor(this);
1127         if(flags & 1)
1128             MSVCRT_operator_delete(this);
1129     }
1130
1131     return this;
1132 }
1133
1134 /* ?_Xran@ctype_base@std@@KAXXZ */
1135 void __cdecl ctype_base__Xran(void)
1136 {
1137     throw_exception(EXCEPTION_OUT_OF_RANGE, "out of range in ctype<T>");
1138 }
1139
1140 /* ?id@?$ctype@D@std@@2V0locale@2@A */
1141 locale_id ctype_char_id = {0};
1142 /* ?table_size@?$ctype@D@std@@2IB */
1143 /* ?table_size@?$ctype@D@std@@2_KB */
1144 MSVCP_size_t ctype_char_table_size = 256;
1145
1146 /* ??_7?$ctype@D@std@@6B@ */
1147 extern const vtable_ptr MSVCP_ctype_char_vtable;
1148
1149 /* ?_Id_func@?$ctype@D@std@@SAAAVid@locale@2@XZ */
1150 /* ?_Id_func@?$ctype@D@std@@SAAEAVid@locale@2@XZ */
1151 locale_id* __cdecl ctype_char__Id_func(void)
1152 {
1153     TRACE("()\n");
1154     return &ctype_char_id;
1155 }
1156
1157 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
1158 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
1159 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
1160 void __thiscall ctype_char__Init(ctype_char *this, _Locinfo *locinfo)
1161 {
1162     TRACE("(%p %p)\n", this, locinfo);
1163     this->ctype = _Locinfo__Getctype(locinfo);
1164 }
1165
1166 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
1167 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
1168 DEFINE_THISCALL_WRAPPER(ctype_char__Tidy, 4)
1169 void __thiscall ctype_char__Tidy(ctype_char *this)
1170 {
1171     TRACE("(%p)\n", this);
1172
1173     if(this->ctype.delfl)
1174         free((short*)this->ctype.table);
1175 }
1176
1177 /* ?classic_table@?$ctype@D@std@@KAPBFXZ */
1178 /* ?classic_table@?$ctype@D@std@@KAPEBFXZ */
1179 const short* __cdecl ctype_char_classic_table(void)
1180 {
1181     TRACE("()\n");
1182     return &((short*)GetProcAddress(GetModuleHandleA("msvcrt.dll"), "_ctype"))[1];
1183 }
1184
1185 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
1186 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1187 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
1188 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
1189         _Locinfo *locinfo, MSVCP_size_t refs)
1190 {
1191     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1192     ctype_base_ctor_refs(&this->base, refs);
1193     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1194     ctype_char__Init(this, locinfo);
1195     return this;
1196 }
1197
1198 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
1199 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
1200 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
1201 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
1202         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
1203 {
1204     _Locinfo locinfo;
1205
1206     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
1207
1208     ctype_base_ctor_refs(&this->base, refs);
1209     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1210
1211     _Locinfo_ctor(&locinfo);
1212     ctype_char__Init(this, &locinfo);
1213     _Locinfo_dtor(&locinfo);
1214
1215     if(table) {
1216         ctype_char__Tidy(this);
1217         this->ctype.table = table;
1218         this->ctype.delfl = delete;
1219     }
1220     return this;
1221 }
1222
1223 /* ??_F?$ctype@D@std@@QAEXXZ */
1224 /* ??_F?$ctype@D@std@@QEAAXXZ */
1225 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
1226 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
1227 {
1228     return ctype_char_ctor_table(this, NULL, FALSE, 0);
1229 }
1230
1231 /* ??1?$ctype@D@std@@MAE@XZ */
1232 /* ??1?$ctype@D@std@@MEAA@XZ */
1233 DEFINE_THISCALL_WRAPPER(ctype_char_dtor, 4)
1234 void __thiscall ctype_char_dtor(ctype_char *this)
1235 {
1236     TRACE("(%p)\n", this);
1237     ctype_char__Tidy(this);
1238 }
1239
1240 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_char_vector_dtor, 8)
1241 ctype_char* __thiscall MSVCP_ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1242 {
1243     TRACE("(%p %x)\n", this, flags);
1244     if(flags & 2) {
1245         /* we have an array, with the number of elements stored before the first object */
1246         int i, *ptr = (int *)this-1;
1247
1248         for(i=*ptr-1; i>=0; i--)
1249             ctype_char_dtor(this+i);
1250         MSVCRT_operator_delete(ptr);
1251     } else {
1252         ctype_char_dtor(this);
1253         if(flags & 1)
1254             MSVCRT_operator_delete(this);
1255     }
1256
1257     return this;
1258 }
1259
1260 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1261 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1262 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1263 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 36, \
1264         char, (const ctype_char*, char, char), (this, ch, unused))
1265 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1266 {
1267     TRACE("(%p %c %c)\n", this, ch, unused);
1268     return ch;
1269 }
1270
1271 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1272 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1273 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1274 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 32, \
1275         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1276         (this, first, last, unused, dest))
1277 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1278         const char *first, const char *last, char unused, char *dest)
1279 {
1280     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1281     memcpy(dest, first, last-first);
1282     return last;
1283 }
1284
1285 /* ?_Do_narrow_s@?$ctype@D@std@@MBEPBDPBD0DPADI@Z */
1286 /* ?_Do_narrow_s@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD_K@Z */
1287 DEFINE_THISCALL_WRAPPER(ctype_char__Do_narrow_s, 24)
1288 #define call_ctype_char__Do_narrow_s(this, first, last, unused, dest, size) CALL_VTBL_FUNC(this, 40, \
1289         const char*, (const ctype_char*, const char*, const char*, char, char*, MSVCP_size_t), \
1290         (this, first, last, unused, dest, size))
1291 const char* __thiscall ctype_char__Do_narrow_s(const ctype_char *this, const char *first,
1292         const char *last, char unused, char *dest, MSVCP_size_t size)
1293 {
1294     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1295     memcpy_s(dest, size, first, last-first);
1296     return last;
1297 }
1298
1299 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1300 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1301 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1302 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1303 {
1304     TRACE("(%p %c %c)\n", this, ch, dflt);
1305     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1306 }
1307
1308 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1309 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1310 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1311 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1312         const char *first, const char *last, char dflt, char *dest)
1313 {
1314     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1315     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1316 }
1317
1318 /* ?_Narrow_s@?$ctype@D@std@@QBEPBDPBD0DPADI@Z */
1319 /* ?_Narrow_s@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD_K@Z */
1320 DEFINE_THISCALL_WRAPPER(ctype_char__Narrow_s, 24)
1321 const char* __thiscall ctype_char__Narrow_s(const ctype_char *this, const char *first,
1322         const char *last, char dflt, char *dest, MSVCP_size_t size)
1323 {
1324     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1325     return call_ctype_char__Do_narrow_s(this, first, last, dflt, dest, size);
1326 }
1327
1328 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1329 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1330 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1331 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1332         char, (const ctype_char*, char), (this, ch))
1333 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1334 {
1335     TRACE("(%p %c)\n", this, ch);
1336     return ch;
1337 }
1338
1339 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1340 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1341 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1342 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1343         const char*, (const ctype_char*, const char*, const char*, char*), \
1344         (this, first, last, dest))
1345 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1346         const char *first, const char *last, char *dest)
1347 {
1348     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1349     memcpy(dest, first, last-first);
1350     return last;
1351 }
1352
1353 /* ?_Do_widen_s@?$ctype@D@std@@MBEPBDPBD0PADI@Z */
1354 /* ?_Do_widen_s@?$ctype@D@std@@MEBAPEBDPEBD0PEAD_K@Z */
1355 DEFINE_THISCALL_WRAPPER(ctype_char__Do_widen_s, 20)
1356 #define call_ctype_char__Do_widen_s(this, first, last, dest, size) CALL_VTBL_FUNC(this, 28, \
1357         const char*, (const ctype_char*, const char*, const char*, char*, MSVCP_size_t), \
1358         (this, first, last, dest, size))
1359 const char* __thiscall ctype_char__Do_widen_s(const ctype_char *this,
1360         const char *first, const char *last, char *dest, MSVCP_size_t size)
1361 {
1362     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1363     memcpy_s(dest, size, first, last-first);
1364     return last;
1365 }
1366
1367 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1368 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1369 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1370 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1371 {
1372     TRACE("(%p %c)\n", this, ch);
1373     return call_ctype_char_do_widen_ch(this, ch);
1374 }
1375
1376 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1377 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1378 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1379 const char* __thiscall ctype_char_widen(const ctype_char *this,
1380         const char *first, const char *last, char *dest)
1381 {
1382     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1383     return call_ctype_char_do_widen(this, first, last, dest);
1384 }
1385
1386 /* ?_Widen_s@?$ctype@D@std@@QBEPBDPBD0PADI@Z */
1387 /* ?_Widen_s@?$ctype@D@std@@QEBAPEBDPEBD0PEAD_K@Z */
1388 DEFINE_THISCALL_WRAPPER(ctype_char__Widen_s, 20)
1389 const char* __thiscall ctype_char__Widen_s(const ctype_char *this,
1390         const char *first, const char *last, char *dest, MSVCP_size_t size)
1391 {
1392     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1393     return call_ctype_char__Do_widen_s(this, first, last, dest, size);
1394 }
1395
1396 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1397 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1398 MSVCP_size_t __cdecl ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1399 {
1400     FIXME("(%p %p) stub\n", facet, loc);
1401     return 0;
1402 }
1403
1404 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1405 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1406 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1407 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1408 {
1409     FIXME("(%p %c) stub\n", this, ch);
1410     return 0;
1411 }
1412
1413 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1414 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1415 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1416 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1417 {
1418     FIXME("(%p %p %p) stub\n", this, first, last);
1419     return NULL;
1420 }
1421
1422 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1423 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1424 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1425 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1426 {
1427     FIXME("(%p %c) stub\n", this, ch);
1428     return 0;
1429 }
1430
1431 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1432 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1433 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1434 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1435 {
1436     FIXME("(%p %p %p) stub\n", this, first, last);
1437     return NULL;
1438 }
1439
1440 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1441 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1442 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1443 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1444 {
1445     FIXME("(%p %c) stub\n", this, ch);
1446     return 0;
1447 }
1448
1449 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1450 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1451 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1452 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1453         char *first, const char *last)
1454 {
1455     FIXME("(%p %p %p) stub\n", this, first, last);
1456     return NULL;
1457 }
1458
1459 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1460 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1461 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1462 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1463 {
1464     FIXME("(%p %c) stub\n", this, ch);
1465     return 0;
1466 }
1467
1468 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1469 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1470 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1471 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1472 {
1473     FIXME("(%p %p %p) stub\n", this, first, last);
1474     return NULL;
1475 }
1476
1477 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1478 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1479 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1480 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1481 {
1482     FIXME("(%p %x %c) stub\n", this, mask, ch);
1483     return 0;
1484 }
1485
1486 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1487 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1488 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1489 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1490 {
1491     FIXME("(%p %p %p %p) stub\n", this, first, last, dest);
1492     return NULL;
1493 }
1494
1495 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1496 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1497 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1498 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1499 {
1500     FIXME("(%p %x %p %p) stub\n", this, mask, first, last);
1501     return NULL;
1502 }
1503
1504 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1505 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1506 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1507 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1508 {
1509     FIXME("(%p %x %p %p) stub\n", this, mask, first, last);
1510     return NULL;
1511 }
1512
1513 /* ?table@?$ctype@D@std@@IBEPBFXZ */
1514 /* ?table@?$ctype@D@std@@IEBAPEBFXZ */
1515 DEFINE_THISCALL_WRAPPER(ctype_char_table, 4)
1516 const short* __thiscall ctype_char_table(const ctype_char *this)
1517 {
1518     FIXME("(%p) stub\n", this);
1519     return NULL;
1520 }
1521
1522 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1523 locale_id ctype_wchar_id = {0};
1524 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1525 locale_id ctype_short_id = {0};
1526
1527 /* ??_7?$ctype@_W@std@@6B@ */
1528 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1529 /* ??_7?$ctype@G@std@@6B@ */
1530 extern const vtable_ptr MSVCP_ctype_short_vtable;
1531
1532 /* ?_Id_func@?$ctype@_W@std@@SAAAVid@locale@2@XZ */
1533 /* ?_Id_func@?$ctype@_W@std@@SAAEAVid@locale@2@XZ */
1534 locale_id* __cdecl ctype_wchar__Id_func(void)
1535 {
1536     FIXME("() stub\n");
1537     return NULL;
1538 }
1539
1540 /* ?_Id_func@?$ctype@G@std@@SAAAVid@locale@2@XZ */
1541 /* ?_Id_func@?$ctype@G@std@@SAAEAVid@locale@2@XZ */
1542 locale_id* __cdecl ctype_short__Id_func(void)
1543 {
1544     FIXME("() stub\n");
1545     return NULL;
1546 }
1547
1548 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1549 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1550 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1551 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1552 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1553 void __thiscall ctype_wchar__Init(ctype_wchar *this, _Locinfo *locinfo)
1554 {
1555     FIXME("(%p %p) stub\n", this, locinfo);
1556 }
1557
1558 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1559 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1560 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_locinfo, 12)
1561 ctype_wchar* __thiscall ctype_wchar_ctor_locinfo(ctype_wchar *this,
1562         _Locinfo *locinfo, MSVCP_size_t refs)
1563 {
1564     FIXME("(%p %p %lu) stub\n", this, locinfo, refs);
1565     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1566     return NULL;
1567 }
1568
1569 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1570 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1571 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1572 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1573         _Locinfo *locinfo, MSVCP_size_t refs)
1574 {
1575     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1576     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1577     return ret;
1578 }
1579
1580 /* ??0?$ctype@_W@std@@QAE@I@Z */
1581 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1582 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_refs, 8)
1583 ctype_wchar* __thiscall ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1584 {
1585     FIXME("(%p %lu) stub\n", this, refs);
1586     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1587     return NULL;
1588 }
1589
1590 /* ??0?$ctype@G@std@@QAE@I@Z */
1591 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1592 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1593 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1594 {
1595     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1596     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1597     return ret;
1598 }
1599
1600 /* ??0?$ctype@G@std@@IAE@PBDI@Z */
1601 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_name, 12)
1602 ctype_wchar* __thiscall ctype_short_ctor_name(ctype_wchar *this,
1603     const char *name, MSVCP_size_t refs)
1604 {
1605     FIXME("(%p %s %lu) stub\n", this, debugstr_a(name), refs);
1606     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1607     return NULL;
1608 }
1609
1610 /* ??_F?$ctype@_W@std@@QAEXXZ */
1611 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1612 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor, 4)
1613 ctype_wchar* __thiscall ctype_wchar_ctor(ctype_wchar *this)
1614 {
1615     FIXME("(%p) stub\n", this);
1616     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1617     return NULL;
1618 }
1619
1620 /* ??_F?$ctype@G@std@@QAEXXZ */
1621 /* ??_F?$ctype@G@std@@QEAAXXZ */
1622 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1623 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1624 {
1625     ctype_wchar *ret = ctype_wchar_ctor(this);
1626     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1627     return ret;
1628 }
1629
1630 /* ??1?$ctype@_W@std@@MAE@XZ */
1631 /* ??1?$ctype@_W@std@@MEAA@XZ */
1632 /* ??1?$ctype@G@std@@MAE@XZ */
1633 /* ??1?$ctype@G@std@@MEAA@XZ */
1634 DEFINE_THISCALL_WRAPPER(ctype_wchar_dtor, 4)
1635 void __thiscall ctype_wchar_dtor(ctype_wchar *this)
1636 {
1637     FIXME("(%p) stub\n", this);
1638 }
1639
1640 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_wchar_vector_dtor, 8)
1641 ctype_wchar* __thiscall MSVCP_ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
1642 {
1643     TRACE("(%p %x)\n", this, flags);
1644     if(flags & 2) {
1645         /* we have an array, with the number of elements stored before the first object */
1646         int i, *ptr = (int *)this-1;
1647
1648         for(i=*ptr-1; i>=0; i--)
1649             ctype_wchar_dtor(this+i);
1650         MSVCRT_operator_delete(ptr);
1651     } else {
1652         ctype_wchar_dtor(this);
1653         if(flags & 1)
1654             MSVCRT_operator_delete(this);
1655     }
1656
1657     return this;
1658 }
1659
1660 DEFINE_THISCALL_WRAPPER(MSVCP_ctype_short_vector_dtor, 8)
1661 ctype_wchar* __thiscall MSVCP_ctype_short_vector_dtor(ctype_wchar *this, unsigned int flags)
1662 {
1663     return MSVCP_ctype_wchar_vector_dtor(this, flags);
1664 }
1665
1666 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
1667 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
1668 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
1669 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
1670 DEFINE_THISCALL_WRAPPER(ctype_wchar__Donarrow, 12)
1671 char __thiscall ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
1672 {
1673     FIXME("(%p %d %d) stub\n", this, ch, dflt);
1674     return 0;
1675 }
1676
1677 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
1678 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
1679 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
1680 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
1681 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
1682 wchar_t __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1683 {
1684     FIXME("(%p %d %d) stub\n", this, ch, dflt);
1685     return 0;
1686 }
1687
1688 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
1689 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
1690 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
1691 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
1692 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
1693 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
1694         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1695 {
1696     FIXME("(%p %p %p %d %p) stub\n", this, first, last, dflt, dest);
1697     return NULL;
1698 }
1699
1700 /* ?_Do_narrow_s@?$ctype@_W@std@@MBEPB_WPB_W0DPADI@Z */
1701 /* ?_Do_narrow_s@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD_K@Z */
1702 /* ?_Do_narrow_s@?$ctype@G@std@@MBEPBGPBG0DPADI@Z */
1703 /* ?_Do_narrow_s@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD_K@Z */
1704 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_narrow_s, 24)
1705 const wchar_t* __thiscall ctype_wchar__Do_narrow_s(const ctype_wchar *this,
1706         const wchar_t *first, const wchar_t *last, char dflt, char *dest, MSVCP_size_t size)
1707 {
1708     FIXME("(%p %p %p %d %p %lu) stub\n", this, first, last, dflt, dest, size);
1709     return NULL;
1710 }
1711
1712 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
1713 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
1714 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
1715 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
1716 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
1717 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1718 {
1719     FIXME("(%p %d %d) stub\n", this, ch, dflt);
1720     return 0;
1721 }
1722
1723 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
1724 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
1725 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
1726 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
1727 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
1728 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
1729         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1730 {
1731     FIXME("(%p %p %p %d %p) stub\n", this, first, last, dflt, dest);
1732     return NULL;
1733 }
1734
1735 /* ?_Narrow_s@?$ctype@_W@std@@QBEPB_WPB_W0DPADI@Z */
1736 /* ?_Narrow_s@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD_K@Z */
1737 /* ?_Narrow_s@?$ctype@G@std@@QBEPBGPBG0DPADI@Z */
1738 /* ?_Narrow_s@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD_K@Z */
1739 DEFINE_THISCALL_WRAPPER(ctype_wchar__Narrow_s, 24)
1740 const wchar_t* __thiscall ctype_wchar__Narrow_s(const ctype_wchar *this, const wchar_t *first,
1741         const wchar_t *last, char dflt, char *dest, unsigned int size)
1742 {
1743     FIXME("(%p %p %p %d %p %d) stub\n", this, first, last, dflt, dest, size);
1744     return NULL;
1745 }
1746
1747 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
1748 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
1749 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
1750 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
1751 DEFINE_THISCALL_WRAPPER(ctype_wchar__Dowiden, 8)
1752 wchar_t __thiscall ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
1753 {
1754     FIXME("(%p %d) stub\n", this, ch);
1755     return 0;
1756 }
1757
1758 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
1759 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
1760 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
1761 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
1762 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
1763 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
1764 {
1765     FIXME("(%p %d) stub\n", this, ch);
1766     return 0;
1767 }
1768
1769 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
1770 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
1771 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
1772 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
1773 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
1774 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
1775         const char *first, const char *last, wchar_t *dest)
1776 {
1777     FIXME("(%p %p %p %p) stub\n", this, first, last, dest);
1778     return NULL;
1779 }
1780
1781 /* ?_Do_widen_s@?$ctype@_W@std@@MBEPBDPBD0PA_WI@Z */
1782 /* ?_Do_widen_s@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W_K@Z */
1783 /* ?_Do_widen_s@?$ctype@G@std@@MBEPBDPBD0PAGI@Z */
1784 /* ?_Do_widen_s@?$ctype@G@std@@MEBAPEBDPEBD0PEAG_K@Z */
1785 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_widen_s, 20)
1786 const char* __thiscall ctype_wchar__Do_widen_s(const ctype_wchar *this,
1787         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
1788 {
1789     FIXME("(%p %p %p %p %lu) stub\n", this, first, last, dest, size);
1790     return NULL;
1791 }
1792
1793 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
1794 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
1795 /* ?widen@?$ctype@G@std@@QBEGD@Z */
1796 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
1797 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
1798 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
1799 {
1800     FIXME("(%p %d) stub\n", this, ch);
1801     return 0;
1802 }
1803
1804 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
1805 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
1806 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
1807 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
1808 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
1809 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
1810         const char *first, const char *last, wchar_t *dest)
1811 {
1812     FIXME("(%p %p %p %p) stub\n", this, first, last, dest);
1813     return NULL;
1814 }
1815
1816 /* ?_Widen_s@?$ctype@_W@std@@QBEPBDPBD0PA_WI@Z */
1817 /* ?_Widen_s@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W_K@Z */
1818 /* ?_Widen_s@?$ctype@G@std@@QBEPBDPBD0PAGI@Z */
1819 /* ?_Widen_s@?$ctype@G@std@@QEBAPEBDPEBD0PEAG_K@Z */
1820 DEFINE_THISCALL_WRAPPER(ctype_wchar__Widen_s, 20)
1821 const char* __thiscall ctype_wchar__Widen_s(const ctype_wchar *this,
1822         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
1823 {
1824     FIXME("(%p %p %p %p %lu) stub\n", this, first, last, dest, size);
1825     return NULL;
1826 }
1827
1828 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1829 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1830 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1831 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1832 MSVCP_size_t __cdecl ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
1833 {
1834     FIXME("(%p %p) stub\n", facet, loc);
1835     return 0;
1836 }
1837
1838 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
1839 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
1840 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
1841 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
1842 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
1843 char __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
1844 {
1845     FIXME("(%p %d) stub\n", this, ch);
1846     return 0;
1847 }
1848
1849 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
1850 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
1851 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
1852 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
1853 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
1854 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
1855         wchar_t *first, const wchar_t *last)
1856 {
1857     FIXME("(%p %p %p) stub\n", this, first, last);
1858     return NULL;
1859 }
1860
1861 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
1862 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
1863 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
1864 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
1865 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
1866 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
1867 {
1868     FIXME("(%p %d) stub\n", this, ch);
1869     return 0;
1870 }
1871
1872 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
1873 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
1874 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
1875 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
1876 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
1877 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
1878         wchar_t *first, const wchar_t *last)
1879 {
1880     FIXME("(%p %p %p) stub\n", this, first, last);
1881     return NULL;
1882 }
1883
1884 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
1885 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
1886 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
1887 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
1888 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
1889 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
1890 {
1891     FIXME("(%p %d) stub\n", this, ch);
1892     return 0;
1893 }
1894
1895 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
1896 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
1897 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
1898 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
1899 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
1900 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
1901         wchar_t *first, const wchar_t *last)
1902 {
1903     FIXME("(%p %p %p) stub\n", this, first, last);
1904     return NULL;
1905 }
1906
1907 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
1908 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
1909 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
1910 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
1911 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
1912 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
1913 {
1914     FIXME("(%p %d) stub\n", this, ch);
1915     return 0;
1916 }
1917
1918 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
1919 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
1920 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
1921 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
1922 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
1923 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
1924         wchar_t *first, const wchar_t *last)
1925 {
1926     FIXME("(%p %p %p) stub\n", this, first, last);
1927     return NULL;
1928 }
1929
1930 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
1931 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
1932 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
1933 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
1934 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
1935 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
1936 {
1937     FIXME("(%p %x %d) stub\n", this, mask, ch);
1938     return 0;
1939 }
1940
1941 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
1942 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
1943 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
1944 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
1945 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
1946 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
1947         const wchar_t *first, const wchar_t *last, short *dest)
1948 {
1949     FIXME("(%p %p %p %p) stub\n", this, first, last, dest);
1950     return NULL;
1951 }
1952
1953 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
1954 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
1955 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
1956 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
1957 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
1958 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
1959 {
1960     FIXME("(%p %x %d) stub\n", this, mask, ch);
1961     return 0;
1962 }
1963
1964 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
1965 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
1966 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
1967 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
1968 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
1969 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
1970         const wchar_t *first, const wchar_t *last, short *dest)
1971 {
1972     FIXME("(%p %p %p %p) stub\n", this, first, last, dest);
1973     return NULL;
1974 }
1975
1976 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
1977 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
1978 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
1979 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
1980 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
1981 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
1982         short mask, const wchar_t *first, const wchar_t *last)
1983 {
1984     FIXME("(%p %d %p %p) stub\n", this, mask, first, last);
1985     return NULL;
1986 }
1987
1988 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
1989 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
1990 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
1991 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
1992 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
1993 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
1994         short mask, const wchar_t *first, const wchar_t *last)
1995 {
1996     FIXME("(%p %x %p %p) stub\n", this, mask, first, last);
1997     return NULL;
1998 }
1999
2000 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2001 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2002 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2003 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2004 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2005 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2006         short mask, const wchar_t *first, const wchar_t *last)
2007 {
2008     FIXME("(%p %x %p %p) stub\n", this, mask, first, last);
2009     return NULL;
2010 }
2011
2012 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2013 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2014 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2015 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2016 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2017 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2018         short mask, const wchar_t *first, const wchar_t *last)
2019 {
2020     FIXME("(%p %x %p %p) stub\n", this, mask, first, last);
2021     return NULL;
2022 }
2023
2024 /* ??0_Locimp@locale@std@@AAE@_N@Z */
2025 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
2026 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor_transparent, 8)
2027 locale__Locimp* __thiscall locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
2028 {
2029     TRACE("(%p %d)\n", this, transparent);
2030
2031     memset(this, 0, sizeof(locale__Locimp));
2032     locale_facet_ctor_refs(&this->facet, 1);
2033     this->transparent = transparent;
2034     MSVCP_basic_string_char_ctor_cstr(&this->name, "*");
2035     return this;
2036 }
2037
2038 /* ??_F_Locimp@locale@std@@QAEXXZ */
2039 /* ??_F_Locimp@locale@std@@QEAAXXZ */
2040 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor, 4)
2041 locale__Locimp* __thiscall locale__Locimp_ctor(locale__Locimp *this)
2042 {
2043     return locale__Locimp_ctor_transparent(this, FALSE);
2044 }
2045
2046 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
2047 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
2048 DEFINE_THISCALL_WRAPPER(locale__Locimp_copy_ctor, 8)
2049 locale__Locimp* __thiscall locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
2050 {
2051     _Lockit lock;
2052     MSVCP_size_t i;
2053
2054     TRACE("(%p %p)\n", this, copy);
2055
2056     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2057     memcpy(this, copy, sizeof(locale__Locimp));
2058     locale_facet_ctor_refs(&this->facet, 1);
2059     if(copy->facetvec) {
2060         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
2061         if(!this->facetvec) {
2062             _Lockit_dtor(&lock);
2063             ERR("Out of memory\n");
2064             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2065             return NULL;
2066         }
2067         for(i=0; i<this->facet_cnt; i++)
2068             if(this->facetvec[i])
2069                 locale_facet__Incref(this->facetvec[i]);
2070     }
2071     MSVCP_basic_string_char_copy_ctor(&this->name, &copy->name);
2072     _Lockit_dtor(&lock);
2073     return this;
2074 }
2075
2076 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPAV123@ABV123@@Z */
2077 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPEAV123@AEBV123@@Z */
2078 locale__Locimp* __cdecl locale__Locimp__Locimp_ctor(locale__Locimp *this, const locale__Locimp *copy)
2079 {
2080     return locale__Locimp_copy_ctor(this, copy);
2081 }
2082
2083 /* ??1_Locimp@locale@std@@MAE@XZ */
2084 /* ??1_Locimp@locale@std@@MEAA@XZ */
2085 DEFINE_THISCALL_WRAPPER(locale__Locimp_dtor, 4)
2086 void __thiscall locale__Locimp_dtor(locale__Locimp *this)
2087 {
2088     TRACE("(%p)\n", this);
2089
2090     if(locale_facet__Decref(&this->facet)) {
2091         MSVCP_size_t i;
2092         for(i=0; i<this->facet_cnt; i++)
2093             if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
2094                 call_locale_facet_vector_dtor(this->facetvec[i], 0);
2095
2096         MSVCRT_operator_delete(this->facetvec);
2097         MSVCP_basic_string_char_dtor(&this->name);
2098     }
2099 }
2100
2101 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPAV123@@Z */
2102 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPEAV123@@Z */
2103 void __cdecl locale__Locimp__Locimp_dtor(locale__Locimp *this)
2104 {
2105     locale__Locimp_dtor(this);
2106 }
2107
2108 DEFINE_THISCALL_WRAPPER(MSVCP_locale__Locimp_vector_dtor, 8)
2109 locale__Locimp* __thiscall MSVCP_locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
2110 {
2111     TRACE("(%p %x)\n", this, flags);
2112     if(flags & 2) {
2113         /* we have an array, with the number of elements stored before the first object */
2114         int i, *ptr = (int *)this-1;
2115
2116         for(i=*ptr-1; i>=0; i--)
2117             locale__Locimp_dtor(this+i);
2118         MSVCRT_operator_delete(ptr);
2119     } else {
2120         locale__Locimp_dtor(this);
2121         if(flags & 1)
2122             MSVCRT_operator_delete(this);
2123     }
2124
2125     return this;
2126 }
2127
2128 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
2129 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
2130 void __cdecl locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
2131 {
2132     _Lockit lock;
2133
2134     TRACE("(%p %p %lu)\n", locimp, facet, id);
2135
2136     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2137     if(id >= locimp->facet_cnt) {
2138         MSVCP_size_t new_size = id+1;
2139         locale_facet **new_facetvec;
2140
2141         if(new_size < locale_id__Id_cnt+1)
2142             new_size = locale_id__Id_cnt+1;
2143
2144         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
2145         if(!new_facetvec) {
2146             _Lockit_dtor(&lock);
2147             ERR("Out of memory\n");
2148             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2149             return;
2150         }
2151
2152         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
2153         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
2154         MSVCRT_operator_delete(locimp->facetvec);
2155         locimp->facetvec = new_facetvec;
2156         locimp->facet_cnt = new_size;
2157     }
2158
2159     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
2160         call_locale_facet_vector_dtor(locimp->facetvec[id], 0);
2161
2162     locimp->facetvec[id] = facet;
2163     if(facet)
2164         locale_facet__Incref(facet);
2165     _Lockit_dtor(&lock);
2166 }
2167
2168 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
2169 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
2170 DEFINE_THISCALL_WRAPPER(locale__Locimp__Addfac, 12)
2171 void __thiscall locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
2172 {
2173     locale__Locimp__Locimp_Addfac(this, facet, id);
2174 }
2175
2176 /* ?_Clocptr_func@_Locimp@locale@std@@CAAAPAV123@XZ */
2177 /* ?_Clocptr_func@_Locimp@locale@std@@CAAEAPEAV123@XZ */
2178 locale__Locimp** __cdecl locale__Locimp__Clocptr_func(void)
2179 {
2180     FIXME("stub\n");
2181     return NULL;
2182 }
2183
2184 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
2185 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
2186 locale__Locimp* __cdecl locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
2187 {
2188     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
2189     return NULL;
2190 }
2191
2192 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
2193 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
2194 void __cdecl locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
2195 {
2196     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
2197 }
2198
2199 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
2200 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
2201 void __cdecl locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
2202 {
2203     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
2204 }
2205
2206 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
2207 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
2208 void __cdecl locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
2209 {
2210     FIXME("(%p %d %p %p) stub\n", locinfo, cat, locimp, loc);
2211 }
2212
2213 /* ??_7_Locimp@locale@std@@6B@ */
2214 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
2215     (vtable_ptr)THISCALL_NAME(MSVCP_locale__Locimp_vector_dtor)
2216 };
2217
2218 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
2219 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
2220 DEFINE_THISCALL_WRAPPER(locale_ctor_locimp, 8)
2221 locale* __thiscall locale_ctor_locimp(locale *this, locale__Locimp *locimp)
2222 {
2223     TRACE("(%p %p)\n", this, locimp);
2224     /* Don't change locimp reference counter */
2225     this->ptr = locimp;
2226     return this;
2227 }
2228
2229 /* ??0locale@std@@QAE@ABV01@0H@Z */
2230 /* ??0locale@std@@QEAA@AEBV01@0H@Z */
2231 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_locale, 16)
2232 locale* __thiscall locale_ctor_locale_locale(locale *this, const locale *loc, const locale *other, category cat)
2233 {
2234     FIXME("(%p %p %p %d) stub\n", this, loc, other, cat);
2235     return NULL;
2236 }
2237
2238 /* ??0locale@std@@QAE@ABV01@@Z */
2239 /* ??0locale@std@@QEAA@AEBV01@@Z */
2240 DEFINE_THISCALL_WRAPPER(locale_copy_ctor, 8)
2241 locale* __thiscall locale_copy_ctor(locale *this, const locale *copy)
2242 {
2243     TRACE("(%p %p)\n", this, copy);
2244     this->ptr = copy->ptr;
2245     locale_facet__Incref(&this->ptr->facet);
2246     return this;
2247 }
2248
2249 /* ??0locale@std@@QAE@ABV01@PBDH@Z */
2250 /* ??0locale@std@@QEAA@AEBV01@PEBDH@Z */
2251 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_cstr, 16)
2252 locale* __thiscall locale_ctor_locale_cstr(locale *this, const locale *loc, const char *locname, category cat)
2253 {
2254     FIXME("(%p %p %s %d) stub\n", this, loc, locname, cat);
2255     return NULL;
2256 }
2257
2258 /* ??0locale@std@@QAE@PBDH@Z */
2259 /* ??0locale@std@@QEAA@PEBDH@Z */
2260 DEFINE_THISCALL_WRAPPER(locale_ctor_cstr, 12)
2261 locale* __thiscall locale_ctor_cstr(locale *this, const char *locname, category cat)
2262 {
2263     FIXME("(%p %s %d) stub\n", this, locname, cat);
2264     return NULL;
2265 }
2266
2267 /* ??0locale@std@@QAE@W4_Uninitialized@1@@Z */
2268 /* ??0locale@std@@QEAA@W4_Uninitialized@1@@Z */
2269 DEFINE_THISCALL_WRAPPER(locale_ctor_uninitialized, 8)
2270 locale* __thiscall locale_ctor_uninitialized(locale *this, int uninitialized)
2271 {
2272     TRACE("(%p)\n", this);
2273     this->ptr = NULL;
2274     return this;
2275 }
2276
2277 /* ??0locale@std@@QAE@XZ */
2278 /* ??0locale@std@@QEAA@XZ */
2279 DEFINE_THISCALL_WRAPPER(locale_ctor, 4)
2280 locale* __thiscall locale_ctor(locale *this)
2281 {
2282     TRACE("(%p)\n", this);
2283     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
2284     if(!this->ptr) {
2285         ERR("Out of memory\n");
2286         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2287         return NULL;
2288     }
2289
2290     locale__Locimp_ctor(this->ptr);
2291     return this;
2292 }
2293
2294 /* ??1locale@std@@QAE@XZ */
2295 /* ??1locale@std@@QEAA@XZ */
2296 DEFINE_THISCALL_WRAPPER(locale_dtor, 4)
2297 void __thiscall locale_dtor(locale *this)
2298 {
2299     TRACE("(%p)\n", this);
2300     if(this->ptr)
2301         locale__Locimp_dtor(this->ptr);
2302 }
2303
2304 DEFINE_THISCALL_WRAPPER(MSVCP_locale_vector_dtor, 8)
2305 locale* __thiscall MSVCP_locale_vector_dtor(locale *this, unsigned int flags)
2306 {
2307     TRACE("(%p %x)\n", this, flags);
2308     if(flags & 2) {
2309         /* we have an array, with the number of elements stored before the first object */
2310         int i, *ptr = (int *)this-1;
2311
2312         for(i=*ptr-1; i>=0; i--)
2313             locale_dtor(this+i);
2314         MSVCRT_operator_delete(ptr);
2315     } else {
2316         locale_dtor(this);
2317         if(flags & 1)
2318             MSVCRT_operator_delete(this);
2319     }
2320
2321     return this;
2322 }
2323
2324 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
2325 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
2326 DEFINE_THISCALL_WRAPPER(locale_operator_assign, 8)
2327 locale* __thiscall locale_operator_assign(locale *this, const locale *loc)
2328 {
2329     FIXME("(%p %p) stub\n", this, loc);
2330     return NULL;
2331 }
2332
2333 /* ??8locale@std@@QBE_NABV01@@Z */
2334 /* ??8locale@std@@QEBA_NAEBV01@@Z */
2335 DEFINE_THISCALL_WRAPPER(locale_operator_equal, 8)
2336 MSVCP_bool __thiscall locale_operator_equal(const locale *this, const locale *loc)
2337 {
2338     FIXME("(%p %p) stub\n", this, loc);
2339     return 0;
2340 }
2341
2342 /* ??9locale@std@@QBE_NABV01@@Z */
2343 /* ??9locale@std@@QEBA_NAEBV01@@Z */
2344 DEFINE_THISCALL_WRAPPER(locale_operator_not_equal, 8)
2345 MSVCP_bool __thiscall locale_operator_not_equal(const locale *this, locale const *loc)
2346 {
2347     FIXME("(%p %p) stub\n", this, loc);
2348     return 0;
2349 }
2350
2351 /* ?_Addfac@locale@std@@QAEAAV12@PAVfacet@12@II@Z */
2352 /* ?_Addfac@locale@std@@QEAAAEAV12@PEAVfacet@12@_K1@Z */
2353 DEFINE_THISCALL_WRAPPER(locale__Addfac, 16)
2354 locale* __thiscall locale__Addfac(locale *this, locale_facet *facet, MSVCP_size_t id, MSVCP_size_t catmask)
2355 {
2356     TRACE("(%p %p %lu %lu)\n", this, facet, id, catmask);
2357
2358     if(this->ptr->facet.refs > 1) {
2359         locale__Locimp *new_ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
2360         if(!new_ptr) {
2361             ERR("Out of memory\n");
2362             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2363             return NULL;
2364         }
2365         locale__Locimp_copy_ctor(new_ptr, this->ptr);
2366         locale_facet__Decref(&this->ptr->facet);
2367         this->ptr = new_ptr;
2368     }
2369
2370     locale__Locimp__Addfac(this->ptr, facet, id);
2371
2372     if(catmask) {
2373         MSVCP_basic_string_char_dtor(&this->ptr->name);
2374         MSVCP_basic_string_char_ctor_cstr(&this->ptr->name, "*");
2375     }
2376     return this;
2377 }
2378
2379 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
2380 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
2381 DEFINE_THISCALL_WRAPPER(locale__Getfacet, 8)
2382 const locale_facet* __thiscall locale__Getfacet(const locale *this, MSVCP_size_t id)
2383 {
2384     FIXME("(%p %lu) stub\n", this, id);
2385     return NULL;
2386 }
2387
2388 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
2389 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
2390 locale__Locimp* __cdecl locale__Init(void)
2391 {
2392     FIXME("stub\n");
2393     return NULL;
2394 }
2395
2396 /* ?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ */
2397 /* ?_Getgloballocale@locale@std@@CAPEAV_Locimp@12@XZ */
2398 locale__Locimp* __cdecl locale__Getgloballocale(void)
2399 {
2400     FIXME("stub\n");
2401     return NULL;
2402 }
2403
2404 /* ?_Setgloballocale@locale@std@@CAXPAX@Z */
2405 /* ?_Setgloballocale@locale@std@@CAXPEAX@Z */
2406 void __cdecl locale__Setgloballocale(void *locimp)
2407 {
2408     FIXME("(%p) stub\n", locimp);
2409 }
2410
2411 /* ?classic@locale@std@@SAABV12@XZ */
2412 /* ?classic@locale@std@@SAAEBV12@XZ */
2413 const locale* __cdecl locale_classic(void)
2414 {
2415     FIXME("stub\n");
2416     return NULL;
2417 }
2418
2419 /* ?name@locale@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2420 /* ?name@locale@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
2421 DEFINE_THISCALL_WRAPPER_RETPTR(locale_name, 4)
2422 basic_string_char __thiscall locale_name(const locale *this)
2423 {
2424     TRACE( "(%p)\n", this);
2425     return this->ptr->name;
2426 }
2427
2428 static const rtti_base_descriptor locale_facet_rtti_base_descriptor = {
2429     &locale_facet_type_info,
2430     0,
2431     { 0, -1, 0},
2432     64
2433 };
2434
2435 DEFINE_RTTI_DATA(collate_char, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@D@std@@");
2436 DEFINE_RTTI_DATA(collate_wchar, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@_W@std@@");
2437 DEFINE_RTTI_DATA(collate_short, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AV?$collate@G@std@@");
2438 DEFINE_RTTI_DATA(ctype_base, 0, 1, &locale_facet_rtti_base_descriptor, NULL, NULL, ".?AUctype_base@std@@");
2439 DEFINE_RTTI_DATA(ctype_char, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@D@std@@");
2440 DEFINE_RTTI_DATA(ctype_wchar, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@_W@std@@");
2441 DEFINE_RTTI_DATA(ctype_short, 0, 2, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, NULL, ".?AV?$ctype@G@std@@");
2442
2443 #ifndef __GNUC__
2444 void __asm_dummy_vtables(void) {
2445 #endif
2446     __ASM_VTABLE(collate_char,
2447             VTABLE_ADD_FUNC(collate_char_do_compare)
2448             VTABLE_ADD_FUNC(collate_char_do_transform)
2449             VTABLE_ADD_FUNC(collate_char_do_hash));
2450     __ASM_VTABLE(collate_wchar,
2451             VTABLE_ADD_FUNC(collate_wchar_do_compare)
2452             VTABLE_ADD_FUNC(collate_wchar_do_transform)
2453             VTABLE_ADD_FUNC(collate_wchar_do_hash));
2454     __ASM_VTABLE(collate_short,
2455             VTABLE_ADD_FUNC(collate_wchar_do_compare)
2456             VTABLE_ADD_FUNC(collate_wchar_do_transform)
2457             VTABLE_ADD_FUNC(collate_wchar_do_hash));
2458     __ASM_VTABLE(ctype_base, "");
2459     __ASM_VTABLE(ctype_char,
2460             VTABLE_ADD_FUNC(ctype_char_do_tolower)
2461             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
2462             VTABLE_ADD_FUNC(ctype_char_do_toupper)
2463             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
2464             VTABLE_ADD_FUNC(ctype_char_do_widen)
2465             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
2466             VTABLE_ADD_FUNC(ctype_char__Do_widen_s)
2467             VTABLE_ADD_FUNC(ctype_char_do_narrow)
2468             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch)
2469             VTABLE_ADD_FUNC(ctype_char__Do_narrow_s));
2470     __ASM_VTABLE(ctype_wchar,
2471             VTABLE_ADD_FUNC(ctype_wchar_do_is)
2472             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
2473             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
2474             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
2475             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
2476             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
2477             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
2478             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
2479             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
2480             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
2481             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
2482             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
2483             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
2484             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
2485     __ASM_VTABLE(ctype_short,
2486             VTABLE_ADD_FUNC(ctype_wchar_do_is)
2487             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
2488             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
2489             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
2490             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
2491             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
2492             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
2493             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
2494             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
2495             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
2496             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
2497             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
2498             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
2499             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
2500 #ifndef __GNUC__
2501 }
2502 #endif