msvcp60: Export locale classes destructors.
[wine] / dlls / msvcp60 / 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 "msvcp.h"
24 #include "locale.h"
25 #include "errno.h"
26 #include "limits.h"
27 #include "math.h"
28 #include "stdio.h"
29 #include "wctype.h"
30
31 #include "wine/list.h"
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
39
40 char* __cdecl _Getdays(void);
41 char* __cdecl _Getmonths(void);
42 void* __cdecl _Gettnames(void);
43 unsigned int __cdecl ___lc_codepage_func(void);
44 LCID* __cdecl ___lc_handle_func(void);
45 static const locale_facet* locale__Getfacet(const locale*, MSVCP_size_t);
46
47 typedef int category;
48
49 typedef struct _locale__Locimp {
50     locale_facet facet;
51     locale_facet **facetvec;
52     MSVCP_size_t facet_cnt;
53     category catmask;
54     MSVCP_bool transparent;
55     basic_string_char name;
56 } locale__Locimp;
57
58 typedef struct {
59     void *timeptr;
60 } _Timevec;
61
62 typedef struct {
63     _Lockit lock;
64     basic_string_char days;
65     basic_string_char months;
66     basic_string_char oldlocname;
67     basic_string_char newlocname;
68 } _Locinfo;
69
70 typedef struct {
71     LCID handle;
72     unsigned page;
73 } _Collvec;
74
75 typedef struct {
76     locale_facet facet;
77     _Collvec coll;
78 } collate;
79
80 typedef struct {
81     locale_facet facet;
82     const char *grouping;
83     char dp;
84     char sep;
85     const char *false_name;
86     const char *true_name;
87 } numpunct_char;
88
89 typedef struct {
90     locale_facet facet;
91     const char *grouping;
92     wchar_t dp;
93     wchar_t sep;
94     const wchar_t *false_name;
95     const wchar_t *true_name;
96 } numpunct_wchar;
97
98 /* ?_Id_cnt@id@locale@std@@0HA */
99 int locale_id__Id_cnt = 0;
100
101 static locale__Locimp *global_locale;
102 static locale classic_locale;
103
104 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
105 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
106 locale__Locimp *locale__Locimp__Clocptr = NULL;
107
108 static char istreambuf_iterator_char_val(istreambuf_iterator_char *this)
109 {
110     if(this->strbuf && !this->got) {
111         int c = basic_streambuf_char_sgetc(this->strbuf);
112         if(c == EOF)
113             this->strbuf = NULL;
114         else
115             this->val = c;
116     }
117
118     this->got = TRUE;
119     return this->val;
120 }
121
122 static wchar_t istreambuf_iterator_wchar_val(istreambuf_iterator_wchar *this)
123 {
124     if(this->strbuf && !this->got) {
125         unsigned short c = basic_streambuf_wchar_sgetc(this->strbuf);
126         if(c == WEOF)
127             this->strbuf = NULL;
128         else
129             this->val = c;
130     }
131
132     this->got = TRUE;
133     return this->val;
134 }
135
136 static void istreambuf_iterator_char_inc(istreambuf_iterator_char *this)
137 {
138     if(!this->strbuf || basic_streambuf_char_sbumpc(this->strbuf)==EOF) {
139         this->strbuf = NULL;
140         this->got = TRUE;
141     }else {
142         this->got = FALSE;
143         istreambuf_iterator_char_val(this);
144     }
145 }
146
147 static void istreambuf_iterator_wchar_inc(istreambuf_iterator_wchar *this)
148 {
149     if(!this->strbuf || basic_streambuf_wchar_sbumpc(this->strbuf)==WEOF) {
150         this->strbuf = NULL;
151         this->got = TRUE;
152     }else {
153         this->got = FALSE;
154         istreambuf_iterator_wchar_val(this);
155     }
156 }
157
158 static void ostreambuf_iterator_char_put(ostreambuf_iterator_char *this, char ch)
159 {
160     if(this->failed || basic_streambuf_char_sputc(this->strbuf, ch)==EOF)
161         this->failed = TRUE;
162 }
163
164 static void ostreambuf_iterator_wchar_put(ostreambuf_iterator_wchar *this, wchar_t ch)
165 {
166     if(this->failed || basic_streambuf_wchar_sputc(this->strbuf, ch)==WEOF)
167         this->failed = TRUE;
168 }
169
170 /* ??1facet@locale@std@@UAE@XZ */
171 /* ??1facet@locale@std@@UEAA@XZ */
172 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
173 void __thiscall locale_facet_dtor(locale_facet *this)
174 {
175     TRACE("(%p)\n", this);
176 }
177
178 DEFINE_THISCALL_WRAPPER(locale_facet_vector_dtor, 8)
179 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
180         locale_facet*, (locale_facet*, unsigned int), (this, flags))
181 locale_facet* __thiscall locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
182 {
183     TRACE("(%p %x)\n", this, flags);
184     if(flags & 2) {
185         /* we have an array, with the number of elements stored before the first object */
186         INT_PTR i, *ptr = (INT_PTR *)this-1;
187
188         for(i=*ptr-1; i>=0; i--)
189             locale_facet_dtor(this+i);
190         MSVCRT_operator_delete(ptr);
191     } else {
192         locale_facet_dtor(this);
193         if(flags & 1)
194             MSVCRT_operator_delete(this);
195     }
196
197     return this;
198 }
199
200 typedef struct
201 {
202     locale_facet *fac;
203     struct list entry;
204 } facets_elem;
205 static struct list lazy_facets = LIST_INIT(lazy_facets);
206
207 /* Not exported from msvcp90 */
208 /* ?facet_Register@facet@locale@std@@CAXPAV123@@Z */
209 /* ?facet_Register@facet@locale@std@@CAXPEAV123@@Z */
210 static void locale_facet_register(locale_facet *add)
211 {
212     facets_elem *head = MSVCRT_operator_new(sizeof(*head));
213     if(!head) {
214         ERR("Out of memory\n");
215         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
216     }
217
218     head->fac = add;
219     list_add_head(&lazy_facets, &head->entry);
220 }
221
222 /* Not exported from msvcp90 */
223 /* ??_7facet@locale@std@@6B@ */
224 extern const vtable_ptr MSVCP_locale_facet_vtable;
225
226 /* ??Bid@locale@std@@QAEIXZ */
227 /* ??Bid@locale@std@@QEAA_KXZ */
228 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
229 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
230 {
231     _Lockit lock;
232
233     TRACE("(%p)\n", this);
234
235     if(!this->id) {
236         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
237         this->id = ++locale_id__Id_cnt;
238         _Lockit_dtor(&lock);
239     }
240
241     return this->id;
242 }
243
244 /* ??_Ffacet@locale@std@@QAEXXZ */
245 /* ??_Ffacet@locale@std@@QEAAXXZ */
246 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
247 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
248 {
249     TRACE("(%p)\n", this);
250     this->vtable = &MSVCP_locale_facet_vtable;
251     this->refs = 0;
252     return this;
253 }
254
255 /* ??0facet@locale@std@@IAE@I@Z */
256 /* ??0facet@locale@std@@IEAA@_K@Z */
257 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
258 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
259 {
260     TRACE("(%p %lu)\n", this, refs);
261     this->vtable = &MSVCP_locale_facet_vtable;
262     this->refs = refs;
263     return this;
264 }
265
266 /* ?_Incref@facet@locale@std@@QAEXXZ */
267 /* ?_Incref@facet@locale@std@@QEAAXXZ */
268 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
269 void __thiscall locale_facet__Incref(locale_facet *this)
270 {
271     _Lockit lock;
272
273     TRACE("(%p)\n", this);
274
275     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
276     this->refs++;
277     _Lockit_dtor(&lock);
278 }
279
280 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
281 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
282 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
283 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
284 {
285     _Lockit lock;
286     locale_facet *ret;
287
288     TRACE("(%p)\n", this);
289
290     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
291     if(this->refs)
292         this->refs--;
293
294     ret = this->refs ? NULL : this;
295     _Lockit_dtor(&lock);
296
297     return ret;
298 }
299
300 /* ??0_Timevec@std@@QAE@ABV01@@Z */
301 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
302 /* This copy constructor modifies copied object */
303 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
304 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
305 {
306     TRACE("(%p %p)\n", this, copy);
307     this->timeptr = copy->timeptr;
308     copy->timeptr = NULL;
309     return this;
310 }
311
312 /* ??0_Timevec@std@@QAE@PAX@Z */
313 /* ??0_Timevec@std@@QEAA@PEAX@Z */
314 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
315 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
316 {
317     TRACE("(%p %p)\n", this, timeptr);
318     this->timeptr = timeptr;
319     return this;
320 }
321
322 /* ??_F_Timevec@std@@QAEXXZ */
323 /* ??_F_Timevec@std@@QEAAXXZ */
324 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
325 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
326 {
327     TRACE("(%p)\n", this);
328     this->timeptr = NULL;
329     return this;
330 }
331
332 /* ??1_Timevec@std@@QAE@XZ */
333 /* ??1_Timevec@std@@QEAA@XZ */
334 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
335 void __thiscall _Timevec_dtor(_Timevec *this)
336 {
337     TRACE("(%p)\n", this);
338     free(this->timeptr);
339 }
340
341 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
342 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
343 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
344 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
345 {
346     TRACE("(%p %p)\n", this, right);
347     this->timeptr = right->timeptr;
348     right->timeptr = NULL;
349     return this;
350 }
351
352 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
353 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
354 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
355 void* __thiscall _Timevec__Getptr(_Timevec *this)
356 {
357     TRACE("(%p)\n", this);
358     return this->timeptr;
359 }
360
361 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
362 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
363 static _Locinfo* _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
364 {
365     const char *locale = NULL;
366
367     /* This function is probably modifying more global objects */
368     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
369
370     if(!locstr)
371         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
372
373     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
374     basic_string_char_ctor_cstr(&locinfo->days, "");
375     basic_string_char_ctor_cstr(&locinfo->months, "");
376     basic_string_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
377
378     if(category)
379         locale = setlocale(LC_ALL, locstr);
380     else
381         locale = setlocale(LC_ALL, NULL);
382
383     if(locale)
384         basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
385     else
386         basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
387
388     return locinfo;
389 }
390
391 /* ??0_Locinfo@std@@QAE@HPBD@Z */
392 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
393 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
394 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
395 {
396     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
397 }
398
399 /* ??0_Locinfo@std@@QAE@PBD@Z */
400 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
401 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
402 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
403 {
404     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
405 }
406
407 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
408 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
409 static void _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
410 {
411     TRACE("(%p)\n", locinfo);
412
413     setlocale(LC_ALL, basic_string_char_c_str(&locinfo->oldlocname));
414     basic_string_char_dtor(&locinfo->days);
415     basic_string_char_dtor(&locinfo->months);
416     basic_string_char_dtor(&locinfo->oldlocname);
417     basic_string_char_dtor(&locinfo->newlocname);
418     _Lockit_dtor(&locinfo->lock);
419 }
420
421 /* ??_F_Locinfo@std@@QAEXXZ */
422 /* ??_F_Locinfo@std@@QEAAXXZ */
423 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
424 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
425 {
426     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
427 }
428
429 /* ??1_Locinfo@std@@QAE@XZ */
430 /* ??1_Locinfo@std@@QEAA@XZ */
431 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
432 void __thiscall _Locinfo_dtor(_Locinfo *this)
433 {
434     _Locinfo__Locinfo_dtor(this);
435 }
436
437 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
438 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
439 static _Locinfo* _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
440 {
441     const char *locale = NULL;
442
443     /* This function is probably modifying more global objects */
444     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
445     if(!locstr)
446         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
447
448     basic_string_char_dtor(&locinfo->newlocname);
449
450     if(category)
451         locale = setlocale(LC_ALL, locstr);
452     else
453         locale = setlocale(LC_ALL, NULL);
454
455     if(locale)
456         basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
457     else
458         basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
459
460     return locinfo;
461 }
462
463 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
464 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
465 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
466 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
467 {
468     return _Locinfo__Locinfo_Addcats(this, category, locstr);
469 }
470
471 /* _Getcoll */
472 ULONGLONG __cdecl _Getcoll(void)
473 {
474     union {
475         _Collvec collvec;
476         ULONGLONG ull;
477     } ret;
478     _locale_t locale = _get_current_locale();
479
480     TRACE("\n");
481
482     ret.collvec.page = locale->locinfo->lc_collate_cp;
483     ret.collvec.handle = locale->locinfo->lc_handle[LC_COLLATE];
484     _free_locale(locale);
485     return ret.ull;
486 }
487
488 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
489 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
490 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 8)
491 _Collvec* __thiscall _Locinfo__Getcoll(const _Locinfo *this, _Collvec *ret)
492 {
493     ULONGLONG ull = _Getcoll();
494     memcpy(ret, &ull, sizeof(ull));
495     return ret;
496 }
497
498 /* _Getctype */
499 _Ctypevec* __cdecl _Getctype(_Ctypevec *ret)
500 {
501     _locale_t locale = _get_current_locale();
502     short *table;
503
504     TRACE("\n");
505
506     ret->page = locale->locinfo->lc_codepage;
507     ret->handle = locale->locinfo->lc_handle[LC_COLLATE];
508     ret->delfl = TRUE;
509     table = malloc(sizeof(short[256]));
510     if(!table) {
511         _free_locale(locale);
512         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
513     }
514     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
515     ret->table = table;
516     _free_locale(locale);
517     return ret;
518 }
519
520 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
521 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
522 DEFINE_THISCALL_WRAPPER(_Locinfo__Getctype, 8)
523 _Ctypevec* __thiscall _Locinfo__Getctype(const _Locinfo *this, _Ctypevec *ret)
524 {
525     return _Getctype(ret);
526 }
527
528 /* _Getcvt */
529 ULONGLONG __cdecl _Getcvt(void)
530 {
531     _locale_t locale = _get_current_locale();
532     union {
533         _Cvtvec cvtvec;
534         ULONGLONG ull;
535     } ret;
536
537     TRACE("\n");
538
539     ret.cvtvec.page = locale->locinfo->lc_codepage;
540     ret.cvtvec.handle = locale->locinfo->lc_handle[LC_CTYPE];
541     _free_locale(locale);
542     return ret.ull;
543 }
544
545 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
546 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
547 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 8)
548 _Cvtvec* __thiscall _Locinfo__Getcvt(const _Locinfo *this, _Cvtvec *ret)
549 {
550     ULONGLONG ull = _Getcvt();
551     memcpy(ret, &ull, sizeof(ull));
552     return ret;
553 }
554
555 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
556 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
557 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
558 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
559 {
560     char *days = _Getdays();
561
562     TRACE("(%p)\n", this);
563
564     if(days) {
565         basic_string_char_dtor(&this->days);
566         basic_string_char_ctor_cstr(&this->days, days);
567         free(days);
568     }
569
570     return this->days.size ? basic_string_char_c_str(&this->days) :
571         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
572 }
573
574 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
575 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
576 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
577 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
578 {
579     char *months = _Getmonths();
580
581     TRACE("(%p)\n", this);
582
583     if(months) {
584         basic_string_char_dtor(&this->months);
585         basic_string_char_ctor_cstr(&this->months, months);
586         free(months);
587     }
588
589     return this->months.size ? basic_string_char_c_str(&this->months) :
590         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
591         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
592 }
593
594 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
595 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
596 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
597 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
598 {
599     TRACE("(%p)\n", this);
600     return "false";
601 }
602
603 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
604 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
605 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
606 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
607 {
608     TRACE("(%p)\n", this);
609     return "true";
610 }
611
612 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
613 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
614 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
615 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
616 {
617     TRACE("(%p)\n", this);
618     return localeconv();
619 }
620
621 /* ?_Getname@_Locinfo@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
622 /* ?_Getname@_Locinfo@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
623 DEFINE_THISCALL_WRAPPER(_Locinfo__Getname, 8)
624 basic_string_char* __thiscall _Locinfo__Getname(const _Locinfo *this, basic_string_char *ret)
625 {
626     TRACE("(%p)\n", this);
627
628     basic_string_char_copy_ctor(ret, &this->newlocname);
629     return ret;
630 }
631
632 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
633 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
634 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 8)
635 _Timevec*__thiscall _Locinfo__Gettnames(const _Locinfo *this, _Timevec *ret)
636 {
637     TRACE("(%p)\n", this);
638
639     _Timevec_ctor_timeptr(ret, _Gettnames());
640     return ret;
641 }
642
643 /* ?id@?$collate@D@std@@2V0locale@2@A */
644 locale_id collate_char_id = {0};
645
646 /* ??_7?$collate@D@std@@6B@ */
647 extern const vtable_ptr MSVCP_collate_char_vtable;
648
649 /* ?_Init@?$collate@D@std@@IAEXABV_Locinfo@2@@Z */
650 /* ?_Init@?$collate@D@std@@IEAAXAEBV_Locinfo@2@@Z */
651 DEFINE_THISCALL_WRAPPER(collate_char__Init, 8)
652 void __thiscall collate_char__Init(collate *this, const _Locinfo *locinfo)
653 {
654     TRACE("(%p %p)\n", this, locinfo);
655     _Locinfo__Getcoll(locinfo, &this->coll);
656 }
657
658 /* ??0?$collate@D@std@@IAE@PBDI@Z */
659 /* ??0?$collate@D@std@@IEAA@PEBD_K@Z */
660 static collate* collate_char_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
661 {
662     _Locinfo locinfo;
663
664     TRACE("(%p %s %lu)\n", this, name, refs);
665
666     locale_facet_ctor_refs(&this->facet, refs);
667     this->facet.vtable = &MSVCP_collate_char_vtable;
668
669     _Locinfo_ctor_cstr(&locinfo, name);
670     collate_char__Init(this, &locinfo);
671     _Locinfo_dtor(&locinfo);
672     return this;
673 }
674
675 /* ??0?$collate@D@std@@QAE@ABV_Locinfo@1@I@Z */
676 /* ??0?$collate@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
677 DEFINE_THISCALL_WRAPPER(collate_char_ctor_locinfo, 12)
678 collate* __thiscall collate_char_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
679 {
680     TRACE("(%p %p %lu)\n", this, locinfo, refs);
681
682     locale_facet_ctor_refs(&this->facet, refs);
683     this->facet.vtable = &MSVCP_collate_char_vtable;
684     collate_char__Init(this, locinfo);
685     return this;
686 }
687
688 /* ??0?$collate@D@std@@QAE@I@Z */
689 /* ??0?$collate@D@std@@QEAA@_K@Z */
690 DEFINE_THISCALL_WRAPPER(collate_char_ctor_refs, 8)
691 collate* __thiscall collate_char_ctor_refs(collate *this, MSVCP_size_t refs)
692 {
693     return collate_char_ctor_name(this, "C", refs);
694 }
695
696 /* ??1?$collate@D@std@@UAE@XZ */
697 /* ??1?$collate@D@std@@UEAA@XZ */
698 DEFINE_THISCALL_WRAPPER(collate_char_dtor, 4)
699 void __thiscall collate_char_dtor(collate *this)
700 {
701     TRACE("(%p)\n", this);
702 }
703
704 DEFINE_THISCALL_WRAPPER(collate_char_vector_dtor, 8)
705 collate* __thiscall collate_char_vector_dtor(collate *this, unsigned int flags)
706 {
707     TRACE("(%p %x)\n", this, flags);
708     if(flags & 2) {
709         /* we have an array, with the number of elements stored before the first object */
710         INT_PTR i, *ptr = (INT_PTR *)this-1;
711
712         for(i=*ptr-1; i>=0; i--)
713             collate_char_dtor(this+i);
714         MSVCRT_operator_delete(ptr);
715     } else {
716         collate_char_dtor(this);
717         if(flags & 1)
718             MSVCRT_operator_delete(this);
719     }
720
721     return this;
722 }
723
724 /* ??_F?$collate@D@std@@QAEXXZ */
725 /* ??_F?$collate@D@std@@QEAAXXZ */
726 DEFINE_THISCALL_WRAPPER(collate_char_ctor, 4)
727 collate* __thiscall collate_char_ctor(collate *this)
728 {
729     return collate_char_ctor_name(this, "C", 0);
730 }
731
732 /* _Strcoll */
733 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
734         const char *last2, const _Collvec *coll)
735 {
736     LCID lcid;
737
738     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
739
740     if(coll)
741         lcid = coll->handle;
742     else
743         lcid = ___lc_handle_func()[LC_COLLATE];
744     return CompareStringA(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
745 }
746
747 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
748 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
749 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
750 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
751         (const collate*, const char*, const char*, const char*, const char*), \
752         (this, first1, last1, first2, last2))
753 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
754         const char *last1, const char *first2, const char *last2)
755 {
756     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
757     return _Strcoll(first1, last1, first2, last2, &this->coll);
758 }
759
760 /* ?compare@?$collate@D@std@@QBEHPBD000@Z */
761 /* ?compare@?$collate@D@std@@QEBAHPEBD000@Z */
762 DEFINE_THISCALL_WRAPPER(collate_char_compare, 20)
763 int __thiscall collate_char_compare(const collate *this, const char *first1,
764         const char *last1, const char *first2, const char *last2)
765 {
766     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
767     return call_collate_char_do_compare(this, first1, last1, first2, last2);
768 }
769
770 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
771 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
772 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
773 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
774         (const collate*, const char*, const char*), (this, first, last))
775 LONG __thiscall collate_char_do_hash(const collate *this,
776         const char *first, const char *last)
777 {
778     ULONG ret = 0;
779
780     TRACE("(%p %p %p)\n", this, first, last);
781
782     for(; first<last; first++)
783         ret = (ret<<8 | ret>>24) + *first;
784     return ret;
785 }
786
787 /* ?hash@?$collate@D@std@@QBEJPBD0@Z */
788 /* ?hash@?$collate@D@std@@QEBAJPEBD0@Z */
789 DEFINE_THISCALL_WRAPPER(collate_char_hash, 12)
790 LONG __thiscall collate_char_hash(const collate *this,
791         const char *first, const char *last)
792 {
793     TRACE("(%p %p %p)\n", this, first, last);
794     return call_collate_char_do_hash(this, first, last);
795 }
796
797 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
798 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
799 DEFINE_THISCALL_WRAPPER(collate_char_do_transform, 16)
800 basic_string_char* __thiscall collate_char_do_transform(const collate *this,
801         basic_string_char *ret, const char *first, const char *last)
802 {
803     FIXME("(%p %p %p) stub\n", this, first, last);
804     return ret;
805 }
806
807 /* ?transform@?$collate@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
808 /* ?transform@?$collate@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
809 DEFINE_THISCALL_WRAPPER(collate_char_transform, 16)
810 basic_string_char* __thiscall collate_char_transform(const collate *this,
811         basic_string_char *ret, const char *first, const char *last)
812 {
813     FIXME("(%p %p %p) stub\n", this, first, last);
814     return ret;
815 }
816
817 /* ?id@?$collate@G@std@@2V0locale@2@A */
818 locale_id collate_short_id = {0};
819
820 /* ??_7?$collate@_W@std@@6B@ */
821 extern const vtable_ptr MSVCP_collate_wchar_vtable;
822 /* ??_7?$collate@G@std@@6B@ */
823 extern const vtable_ptr MSVCP_collate_short_vtable;
824
825 /* ?_Init@?$collate@_W@std@@IAEXABV_Locinfo@2@@Z */
826 /* ?_Init@?$collate@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
827 /* ?_Init@?$collate@G@std@@IAEXABV_Locinfo@2@@Z */
828 /* ?_Init@?$collate@G@std@@IEAAXAEBV_Locinfo@2@@Z */
829 DEFINE_THISCALL_WRAPPER(collate_wchar__Init, 8)
830 void __thiscall collate_wchar__Init(collate *this, const _Locinfo *locinfo)
831 {
832     TRACE("(%p %p)\n", this, locinfo);
833     _Locinfo__Getcoll(locinfo, &this->coll);
834 }
835
836 /* ??0?$collate@_W@std@@IAE@PBDI@Z */
837 /* ??0?$collate@_W@std@@IEAA@PEBD_K@Z */
838 static collate* collate_wchar_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
839 {
840     _Locinfo locinfo;
841
842     TRACE("(%p %s %lu)\n", this, name, refs);
843
844     locale_facet_ctor_refs(&this->facet, refs);
845     this->facet.vtable = &MSVCP_collate_wchar_vtable;
846
847     _Locinfo_ctor_cstr(&locinfo, name);
848     collate_wchar__Init(this, &locinfo);
849     _Locinfo_dtor(&locinfo);
850     return this;
851 }
852
853 /* ??0?$collate@_W@std@@QAE@ABV_Locinfo@1@I@Z */
854 /* ??0?$collate@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
855 static collate* collate_wchar_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
856 {
857     TRACE("(%p %p %lu)\n", this, locinfo, refs);
858
859     locale_facet_ctor_refs(&this->facet, refs);
860     this->facet.vtable = &MSVCP_collate_wchar_vtable;
861     collate_wchar__Init(this, locinfo);
862     return this;
863 }
864
865 /* ??0?$collate@G@std@@QAE@ABV_Locinfo@1@I@Z */
866 /* ??0?$collate@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
867 DEFINE_THISCALL_WRAPPER(collate_short_ctor_locinfo, 12)
868 collate* __thiscall collate_short_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
869 {
870     collate *ret = collate_wchar_ctor_locinfo(this, locinfo, refs);
871     ret->facet.vtable = &MSVCP_collate_short_vtable;
872     return ret;
873 }
874
875 /* ??0?$collate@_W@std@@QAE@I@Z */
876 /* ??0?$collate@_W@std@@QEAA@_K@Z */
877 static collate* collate_wchar_ctor_refs(collate *this, MSVCP_size_t refs)
878 {
879     return collate_wchar_ctor_name(this, "C", refs);
880 }
881
882 /* ??0?$collate@G@std@@QAE@I@Z */
883 /* ??0?$collate@G@std@@QEAA@_K@Z */
884 DEFINE_THISCALL_WRAPPER(collate_short_ctor_refs, 8)
885 collate* __thiscall collate_short_ctor_refs(collate *this, MSVCP_size_t refs)
886 {
887     collate *ret = collate_wchar_ctor_refs(this, refs);
888     ret->facet.vtable = &MSVCP_collate_short_vtable;
889     return ret;
890 }
891
892 /* ??1?$collate@G@std@@UAE@XZ */
893 /* ??1?$collate@G@std@@UEAA@XZ */
894 DEFINE_THISCALL_WRAPPER(collate_wchar_dtor, 4)
895 void __thiscall collate_wchar_dtor(collate *this)
896 {
897     TRACE("(%p)\n", this);
898 }
899
900 DEFINE_THISCALL_WRAPPER(collate_wchar_vector_dtor, 8)
901 collate* __thiscall collate_wchar_vector_dtor(collate *this, unsigned int flags)
902 {
903     TRACE("(%p %x)\n", this, flags);
904     if(flags & 2) {
905         /* we have an array, with the number of elements stored before the first object */
906         INT_PTR i, *ptr = (INT_PTR *)this-1;
907
908         for(i=*ptr-1; i>=0; i--)
909             collate_wchar_dtor(this+i);
910         MSVCRT_operator_delete(ptr);
911     } else {
912         collate_wchar_dtor(this);
913         if(flags & 1)
914             MSVCRT_operator_delete(this);
915     }
916
917     return this;
918 }
919
920 /* ??_F?$collate@_W@std@@QAEXXZ */
921 /* ??_F?$collate@_W@std@@QEAAXXZ */
922 static collate* collate_wchar_ctor(collate *this)
923 {
924     return collate_wchar_ctor_name(this, "C", 0);
925 }
926
927 /* ??_F?$collate@G@std@@QAEXXZ */
928 /* ??_F?$collate@G@std@@QEAAXXZ */
929 DEFINE_THISCALL_WRAPPER(collate_short_ctor, 4)
930 collate* __thiscall collate_short_ctor(collate *this)
931 {
932     collate *ret = collate_wchar_ctor(this);
933     ret->facet.vtable = &MSVCP_collate_short_vtable;
934     return ret;
935 }
936
937 /* _Wcscoll */
938 static int _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
939         const wchar_t *last2, const _Collvec *coll)
940 {
941     LCID lcid;
942
943     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
944
945     if(coll)
946         lcid = coll->handle;
947     else
948         lcid = ___lc_handle_func()[LC_COLLATE];
949     return CompareStringW(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
950 }
951
952 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
953 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
954 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
955 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
956 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
957 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
958         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
959         (this, first1, last1, first2, last2))
960 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
961         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
962 {
963     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
964     return _Wcscoll(first1, last1, first2, last2, &this->coll);
965 }
966
967 /* ?compare@?$collate@_W@std@@QBEHPB_W000@Z */
968 /* ?compare@?$collate@_W@std@@QEBAHPEB_W000@Z */
969 /* ?compare@?$collate@G@std@@QBEHPBG000@Z */
970 /* ?compare@?$collate@G@std@@QEBAHPEBG000@Z */
971 DEFINE_THISCALL_WRAPPER(collate_wchar_compare, 20)
972 int __thiscall collate_wchar_compare(const collate *this, const wchar_t *first1,
973         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
974 {
975     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
976     return call_collate_wchar_do_compare(this, first1, last1, first2, last2);
977 }
978
979 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
980 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
981 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
982 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
983 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
984 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
985         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
986 LONG __thiscall collate_wchar_do_hash(const collate *this,
987         const wchar_t *first, const wchar_t *last)
988 {
989     ULONG ret = 0;
990
991     TRACE("(%p %p %p)\n", this, first, last);
992
993     for(; first<last; first++)
994         ret = (ret<<8 | ret>>24) + *first;
995     return ret;
996 }
997
998 /* ?hash@?$collate@_W@std@@QBEJPB_W0@Z */
999 /* ?hash@?$collate@_W@std@@QEBAJPEB_W0@Z */
1000 /* ?hash@?$collate@G@std@@QBEJPBG0@Z */
1001 /* ?hash@?$collate@G@std@@QEBAJPEBG0@Z */
1002 DEFINE_THISCALL_WRAPPER(collate_wchar_hash, 12)
1003 LONG __thiscall collate_wchar_hash(const collate *this,
1004         const wchar_t *first, const wchar_t *last)
1005 {
1006     TRACE("(%p %p %p)\n", this, first, last);
1007     return call_collate_wchar_do_hash(this, first, last);
1008 }
1009
1010 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1011 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1012 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1013 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1014 DEFINE_THISCALL_WRAPPER(collate_wchar_do_transform, 16)
1015 basic_string_wchar* __thiscall collate_wchar_do_transform(const collate *this,
1016         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1017 {
1018     FIXME("(%p %p %p) stub\n", this, first, last);
1019     return ret;
1020 }
1021
1022 /* ?transform@?$collate@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1023 /* ?transform@?$collate@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1024 /* ?transform@?$collate@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1025 /* ?transform@?$collate@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1026 DEFINE_THISCALL_WRAPPER(collate_wchar_transform, 16)
1027 basic_string_wchar* __thiscall collate_wchar_transform(const collate *this,
1028         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1029 {
1030     FIXME("(%p %p %p) stub\n", this, first, last);
1031     return ret;
1032 }
1033
1034 /* ??_7ctype_base@std@@6B@ */
1035 extern const vtable_ptr MSVCP_ctype_base_vtable;
1036
1037 /* ??0ctype_base@std@@QAE@I@Z */
1038 /* ??0ctype_base@std@@QEAA@_K@Z */
1039 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
1040 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
1041 {
1042     TRACE("(%p %lu)\n", this, refs);
1043     locale_facet_ctor_refs(&this->facet, refs);
1044     this->facet.vtable = &MSVCP_ctype_base_vtable;
1045     return this;
1046 }
1047
1048 /* ??_Fctype_base@std@@QAEXXZ */
1049 /* ??_Fctype_base@std@@QEAAXXZ */
1050 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
1051 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
1052 {
1053     TRACE("(%p)\n", this);
1054     locale_facet_ctor_refs(&this->facet, 0);
1055     this->facet.vtable = &MSVCP_ctype_base_vtable;
1056     return this;
1057 }
1058
1059 /* ??1ctype_base@std@@UAE@XZ */
1060 /* ??1ctype_base@std@@UEAA@XZ */
1061 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
1062 void __thiscall ctype_base_dtor(ctype_base *this)
1063 {
1064     TRACE("(%p)\n", this);
1065 }
1066
1067 DEFINE_THISCALL_WRAPPER(ctype_base_vector_dtor, 8)
1068 ctype_base* __thiscall ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
1069 {
1070     TRACE("(%p %x)\n", this, flags);
1071     if(flags & 2) {
1072         /* we have an array, with the number of elements stored before the first object */
1073         INT_PTR i, *ptr = (INT_PTR *)this-1;
1074
1075         for(i=*ptr-1; i>=0; i--)
1076             ctype_base_dtor(this+i);
1077         MSVCRT_operator_delete(ptr);
1078     } else {
1079         ctype_base_dtor(this);
1080         if(flags & 1)
1081             MSVCRT_operator_delete(this);
1082     }
1083
1084     return this;
1085 }
1086
1087 /* ?id@?$ctype@D@std@@2V0locale@2@A */
1088 locale_id ctype_char_id = {0};
1089 /* ?table_size@?$ctype@D@std@@2IB */
1090 /* ?table_size@?$ctype@D@std@@2_KB */
1091 MSVCP_size_t ctype_char_table_size = 256;
1092
1093 /* ??_7?$ctype@D@std@@6B@ */
1094 extern const vtable_ptr MSVCP_ctype_char_vtable;
1095
1096 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
1097 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
1098 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
1099 void __thiscall ctype_char__Init(ctype_char *this, const _Locinfo *locinfo)
1100 {
1101     TRACE("(%p %p)\n", this, locinfo);
1102     _Locinfo__Getctype(locinfo, &this->ctype);
1103 }
1104
1105 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
1106 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
1107 static void ctype_char__Tidy(ctype_char *this)
1108 {
1109     TRACE("(%p)\n", this);
1110
1111     if(this->ctype.delfl)
1112         free((short*)this->ctype.table);
1113 }
1114
1115 /* ?classic_table@?$ctype@D@std@@KAPBFXZ */
1116 /* ?classic_table@?$ctype@D@std@@KAPEBFXZ */
1117 const short* __cdecl ctype_char_classic_table(void)
1118 {
1119     TRACE("()\n");
1120     return &((short*)GetProcAddress(GetModuleHandleA("msvcrt.dll"), "_ctype"))[1];
1121 }
1122
1123 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
1124 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1125 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
1126 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
1127         const _Locinfo *locinfo, MSVCP_size_t refs)
1128 {
1129     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1130     ctype_base_ctor_refs(&this->base, refs);
1131     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1132     ctype_char__Init(this, locinfo);
1133     return this;
1134 }
1135
1136 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
1137 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
1138 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
1139 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
1140         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
1141 {
1142     _Locinfo locinfo;
1143
1144     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
1145
1146     ctype_base_ctor_refs(&this->base, refs);
1147     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1148
1149     _Locinfo_ctor(&locinfo);
1150     ctype_char__Init(this, &locinfo);
1151     _Locinfo_dtor(&locinfo);
1152
1153     if(table) {
1154         ctype_char__Tidy(this);
1155         this->ctype.table = table;
1156         this->ctype.delfl = delete;
1157     }
1158     return this;
1159 }
1160
1161 /* ??_F?$ctype@D@std@@QAEXXZ */
1162 /* ??_F?$ctype@D@std@@QEAAXXZ */
1163 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
1164 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
1165 {
1166     return ctype_char_ctor_table(this, NULL, FALSE, 0);
1167 }
1168
1169 /* ??1?$ctype@D@std@@UAE@XZ */
1170 /* ??1?$ctype@D@std@@UEAA@XZ */
1171 DEFINE_THISCALL_WRAPPER(ctype_char_dtor, 4)
1172 void __thiscall ctype_char_dtor(ctype_char *this)
1173 {
1174     TRACE("(%p)\n", this);
1175     ctype_char__Tidy(this);
1176 }
1177
1178 DEFINE_THISCALL_WRAPPER(ctype_char_vector_dtor, 8)
1179 ctype_char* __thiscall ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1180 {
1181     TRACE("(%p %x)\n", this, flags);
1182     if(flags & 2) {
1183         /* we have an array, with the number of elements stored before the first object */
1184         INT_PTR i, *ptr = (INT_PTR *)this-1;
1185
1186         for(i=*ptr-1; i>=0; i--)
1187             ctype_char_dtor(this+i);
1188         MSVCRT_operator_delete(ptr);
1189     } else {
1190         ctype_char_dtor(this);
1191         if(flags & 1)
1192             MSVCRT_operator_delete(this);
1193     }
1194
1195     return this;
1196 }
1197
1198 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1199 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1200 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1201 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 32, \
1202         char, (const ctype_char*, char, char), (this, ch, unused))
1203 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1204 {
1205     TRACE("(%p %c %c)\n", this, ch, unused);
1206     return ch;
1207 }
1208
1209 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1210 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1211 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1212 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 28, \
1213         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1214         (this, first, last, unused, dest))
1215 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1216         const char *first, const char *last, char unused, char *dest)
1217 {
1218     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1219     memcpy(dest, first, last-first);
1220     return last;
1221 }
1222
1223 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1224 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1225 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1226 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1227 {
1228     TRACE("(%p %c %c)\n", this, ch, dflt);
1229     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1230 }
1231
1232 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1233 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1234 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1235 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1236         const char *first, const char *last, char dflt, char *dest)
1237 {
1238     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1239     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1240 }
1241
1242 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1243 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1244 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1245 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1246         char, (const ctype_char*, char), (this, ch))
1247 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1248 {
1249     TRACE("(%p %c)\n", this, ch);
1250     return ch;
1251 }
1252
1253 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1254 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1255 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1256 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1257         const char*, (const ctype_char*, const char*, const char*, char*), \
1258         (this, first, last, dest))
1259 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1260         const char *first, const char *last, char *dest)
1261 {
1262     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1263     memcpy(dest, first, last-first);
1264     return last;
1265 }
1266
1267 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1268 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1269 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1270 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1271 {
1272     TRACE("(%p %c)\n", this, ch);
1273     return call_ctype_char_do_widen_ch(this, ch);
1274 }
1275
1276 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1277 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1278 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1279 const char* __thiscall ctype_char_widen(const ctype_char *this,
1280         const char *first, const char *last, char *dest)
1281 {
1282     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1283     return call_ctype_char_do_widen(this, first, last, dest);
1284 }
1285
1286 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1287 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1288 static MSVCP_size_t ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1289 {
1290     TRACE("(%p %p)\n", facet, loc);
1291
1292     if(facet && !*facet) {
1293         _Locinfo locinfo;
1294
1295         *facet = MSVCRT_operator_new(sizeof(ctype_char));
1296         if(!*facet) {
1297             ERR("Out of memory\n");
1298             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1299             return 0;
1300         }
1301
1302         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
1303         ctype_char_ctor_locinfo((ctype_char*)*facet, &locinfo, 0);
1304         _Locinfo_dtor(&locinfo);
1305     }
1306
1307     return LC_CTYPE;
1308 }
1309
1310 ctype_char* ctype_char_use_facet(const locale *loc)
1311 {
1312     static ctype_char *obj = NULL;
1313
1314     _Lockit lock;
1315     const locale_facet *fac;
1316
1317     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1318     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_char_id));
1319     if(fac) {
1320         _Lockit_dtor(&lock);
1321         return (ctype_char*)fac;
1322     }
1323
1324     if(obj) {
1325         _Lockit_dtor(&lock);
1326         return obj;
1327     }
1328
1329     ctype_char__Getcat(&fac, loc);
1330     obj = (ctype_char*)fac;
1331     locale_facet__Incref(&obj->base.facet);
1332     locale_facet_register(&obj->base.facet);
1333     _Lockit_dtor(&lock);
1334
1335     return obj;
1336 }
1337
1338 /* _Tolower */
1339 int __cdecl _Tolower(int ch, const _Ctypevec *ctype)
1340 {
1341     unsigned int cp;
1342
1343     TRACE("%d %p\n", ch, ctype);
1344
1345     if(ctype)
1346         cp = ctype->page;
1347     else
1348         cp = ___lc_codepage_func();
1349
1350     /* Don't convert to unicode in case of C locale */
1351     if(!cp) {
1352         if(ch>='A' && ch<='Z')
1353             ch = ch-'A'+'a';
1354         return ch;
1355     } else {
1356         WCHAR wide, lower;
1357         char str[2];
1358         int size;
1359
1360         if(ch > 255) {
1361             str[0] = (ch>>8) & 255;
1362             str[1] = ch & 255;
1363             size = 2;
1364         } else {
1365             str[0] = ch & 255;
1366             size = 1;
1367         }
1368
1369         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1370             return ch;
1371
1372         lower = tolowerW(wide);
1373         if(lower == wide)
1374             return ch;
1375
1376         WideCharToMultiByte(cp, 0, &lower, 1, str, 2, NULL, NULL);
1377
1378         return str[0] + (str[1]<<8);
1379     }
1380 }
1381
1382 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1383 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1384 #define call_ctype_char_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 8, \
1385         char, (const ctype_char*, char), (this, ch))
1386 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1387 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1388 {
1389     TRACE("(%p %c)\n", this, ch);
1390     return _Tolower(ch, &this->ctype);
1391 }
1392
1393 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1394 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1395 #define call_ctype_char_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 4, \
1396         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1397 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1398 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1399 {
1400     TRACE("(%p %p %p)\n", this, first, last);
1401     for(; first<last; first++)
1402         *first = _Tolower(*first, &this->ctype);
1403     return last;
1404 }
1405
1406 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1407 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1408 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1409 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1410 {
1411     TRACE("(%p %c)\n", this, ch);
1412     return call_ctype_char_do_tolower_ch(this, ch);
1413 }
1414
1415 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1416 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1417 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1418 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1419 {
1420     TRACE("(%p %p %p)\n", this, first, last);
1421     return call_ctype_char_do_tolower(this, first, last);
1422 }
1423
1424 /* _Toupper */
1425 int __cdecl _Toupper(int ch, const _Ctypevec *ctype)
1426 {
1427     unsigned int cp;
1428
1429     TRACE("%d %p\n", ch, ctype);
1430
1431     if(ctype)
1432         cp = ctype->page;
1433     else
1434         cp = ___lc_codepage_func();
1435
1436     /* Don't convert to unicode in case of C locale */
1437     if(!cp) {
1438         if(ch>='a' && ch<='z')
1439             ch = ch-'a'+'A';
1440         return ch;
1441     } else {
1442         WCHAR wide, upper;
1443         char str[2];
1444         int size;
1445
1446         if(ch > 255) {
1447             str[0] = (ch>>8) & 255;
1448             str[1] = ch & 255;
1449             size = 2;
1450         } else {
1451             str[0] = ch & 255;
1452             size = 1;
1453         }
1454
1455         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1456             return ch;
1457
1458         upper = toupperW(wide);
1459         if(upper == wide)
1460             return ch;
1461
1462         WideCharToMultiByte(cp, 0, &upper, 1, str, 2, NULL, NULL);
1463
1464         return str[0] + (str[1]<<8);
1465     }
1466 }
1467
1468 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1469 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1470 #define call_ctype_char_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 16, \
1471         char, (const ctype_char*, char), (this, ch))
1472 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1473 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1474 {
1475     TRACE("(%p %c)\n", this, ch);
1476     return _Toupper(ch, &this->ctype);
1477 }
1478
1479 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1480 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1481 #define call_ctype_char_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 12, \
1482         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1483 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1484 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1485         char *first, const char *last)
1486 {
1487     TRACE("(%p %p %p)\n", this, first, last);
1488     for(; first<last; first++)
1489         *first = _Toupper(*first, &this->ctype);
1490     return last;
1491 }
1492
1493 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1494 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1495 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1496 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1497 {
1498     TRACE("(%p %c)\n", this, ch);
1499     return call_ctype_char_do_toupper_ch(this, ch);
1500 }
1501
1502 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1503 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1504 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1505 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1506 {
1507     TRACE("(%p %p %p)\n", this, first, last);
1508     return call_ctype_char_do_toupper(this, first, last);
1509 }
1510
1511 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1512 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1513 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1514 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1515 {
1516     TRACE("(%p %x %c)\n", this, mask, ch);
1517     return (this->ctype.table[(unsigned char)ch] & mask) != 0;
1518 }
1519
1520 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1521 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1522 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1523 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1524 {
1525     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1526     for(; first<last; first++)
1527         *dest++ = this->ctype.table[(unsigned char)*first];
1528     return last;
1529 }
1530
1531 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1532 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1533 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1534 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1535 {
1536     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1537     for(; first<last; first++)
1538         if(!ctype_char_is_ch(this, mask, *first))
1539             break;
1540     return first;
1541 }
1542
1543 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1544 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1545 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1546 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1547 {
1548     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1549     for(; first<last; first++)
1550         if(ctype_char_is_ch(this, mask, *first))
1551             break;
1552     return first;
1553 }
1554
1555 /* ?table@?$ctype@D@std@@IBEPBFXZ */
1556 /* ?table@?$ctype@D@std@@IEBAPEBFXZ */
1557 DEFINE_THISCALL_WRAPPER(ctype_char_table, 4)
1558 const short* __thiscall ctype_char_table(const ctype_char *this)
1559 {
1560     TRACE("(%p)\n", this);
1561     return this->ctype.table;
1562 }
1563
1564 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1565 static locale_id ctype_wchar_id = {0};
1566 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1567 locale_id ctype_short_id = {0};
1568
1569 /* ??_7?$ctype@_W@std@@6B@ */
1570 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1571 /* ??_7?$ctype@G@std@@6B@ */
1572 extern const vtable_ptr MSVCP_ctype_short_vtable;
1573
1574 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1575 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1576 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1577 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1578 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1579 void __thiscall ctype_wchar__Init(ctype_wchar *this, const _Locinfo *locinfo)
1580 {
1581     TRACE("(%p %p)\n", this, locinfo);
1582     _Locinfo__Getctype(locinfo, &this->ctype);
1583     _Locinfo__Getcvt(locinfo, &this->cvt);
1584 }
1585
1586 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1587 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1588 static ctype_wchar* ctype_wchar_ctor_locinfo(ctype_wchar *this,
1589         const _Locinfo *locinfo, MSVCP_size_t refs)
1590 {
1591     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1592     ctype_base_ctor_refs(&this->base, refs);
1593     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1594     ctype_wchar__Init(this, locinfo);
1595     return this;
1596 }
1597
1598 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1599 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1600 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1601 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1602         const _Locinfo *locinfo, MSVCP_size_t refs)
1603 {
1604     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1605     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1606     return ret;
1607 }
1608
1609 /* ??0?$ctype@_W@std@@QAE@I@Z */
1610 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1611 static ctype_wchar* ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1612 {
1613     _Locinfo locinfo;
1614
1615     TRACE("(%p %lu)\n", this, refs);
1616
1617     ctype_base_ctor_refs(&this->base, refs);
1618     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1619
1620     _Locinfo_ctor(&locinfo);
1621     ctype_wchar__Init(this, &locinfo);
1622     _Locinfo_dtor(&locinfo);
1623     return this;
1624 }
1625
1626 /* ??0?$ctype@G@std@@QAE@I@Z */
1627 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1628 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1629 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1630 {
1631     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1632     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1633     return ret;
1634 }
1635
1636 /* ??_F?$ctype@_W@std@@QAEXXZ */
1637 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1638 static ctype_wchar* ctype_wchar_ctor(ctype_wchar *this)
1639 {
1640     TRACE("(%p)\n", this);
1641     return ctype_short_ctor_refs(this, 0);
1642 }
1643
1644 /* ??_F?$ctype@G@std@@QAEXXZ */
1645 /* ??_F?$ctype@G@std@@QEAAXXZ */
1646 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1647 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1648 {
1649     ctype_wchar *ret = ctype_wchar_ctor(this);
1650     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1651     return ret;
1652 }
1653
1654 /* ??1?$ctype@G@std@@UAE@XZ */
1655 /* ??1?$ctype@G@std@@UEAA@XZ */
1656 DEFINE_THISCALL_WRAPPER(ctype_wchar_dtor, 4)
1657 void __thiscall ctype_wchar_dtor(ctype_wchar *this)
1658 {
1659     TRACE("(%p)\n", this);
1660     if(this->ctype.delfl)
1661         free((void*)this->ctype.table);
1662 }
1663
1664 DEFINE_THISCALL_WRAPPER(ctype_wchar_vector_dtor, 8)
1665 ctype_wchar* __thiscall ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
1666 {
1667     TRACE("(%p %x)\n", this, flags);
1668     if(flags & 2) {
1669         /* we have an array, with the number of elements stored before the first object */
1670         INT_PTR i, *ptr = (INT_PTR *)this-1;
1671
1672         for(i=*ptr-1; i>=0; i--)
1673             ctype_wchar_dtor(this+i);
1674         MSVCRT_operator_delete(ptr);
1675     } else {
1676         ctype_wchar_dtor(this);
1677         if(flags & 1)
1678             MSVCRT_operator_delete(this);
1679     }
1680
1681     return this;
1682 }
1683
1684 /* _Wcrtomb */
1685 int __cdecl _Wcrtomb(char *s, wchar_t wch, int *state, const _Cvtvec *cvt)
1686 {
1687     int cp, size;
1688     BOOL def;
1689
1690     TRACE("%p %d %p %p\n", s, wch, state, cvt);
1691
1692     if(cvt)
1693         cp = cvt->page;
1694     else
1695         cp = ___lc_codepage_func();
1696
1697     if(!cp) {
1698         if(wch > 255) {
1699            *_errno() = EILSEQ;
1700            return -1;
1701         }
1702
1703         *s = wch & 255;
1704         return 1;
1705     }
1706
1707     size = WideCharToMultiByte(cp, 0, &wch, 1, s, MB_LEN_MAX, NULL, &def);
1708     if(!size || def) {
1709         *_errno() = EILSEQ;
1710         return -1;
1711     }
1712
1713     return size;
1714 }
1715
1716 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
1717 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
1718 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
1719 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
1720 static char ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
1721 {
1722     char buf[MB_LEN_MAX];
1723
1724     TRACE("(%p %d %d)\n", this, ch, dflt);
1725
1726     return _Wcrtomb(buf, ch, NULL, &this->cvt)==1 ? buf[0] : dflt;
1727 }
1728
1729 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
1730 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
1731 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
1732 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
1733 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
1734 #define call_ctype_wchar_do_narrow_ch(this, ch, dflt) CALL_VTBL_FUNC(this, 48, \
1735         char, (const ctype_wchar*, wchar_t, char), (this, ch, dflt))
1736 char __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1737 {
1738     return ctype_wchar__Donarrow(this, ch, dflt);
1739 }
1740
1741 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
1742 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
1743 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
1744 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
1745 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
1746 #define call_ctype_wchar_do_narrow(this, first, last, dflt, dest) CALL_VTBL_FUNC(this, 44, \
1747         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*), \
1748         (this, first, last, dflt, dest))
1749 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
1750         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1751 {
1752     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1753     for(; first<last; first++)
1754         *dest++ = ctype_wchar__Donarrow(this, *first, dflt);
1755     return last;
1756 }
1757
1758 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
1759 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
1760 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
1761 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
1762 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
1763 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1764 {
1765     TRACE("(%p %d %d)\n", this, ch, dflt);
1766     return call_ctype_wchar_do_narrow_ch(this, ch, dflt);
1767 }
1768
1769 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
1770 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
1771 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
1772 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
1773 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
1774 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
1775         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1776 {
1777     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1778     return call_ctype_wchar_do_narrow(this, first, last, dflt, dest);
1779 }
1780
1781 /* _Mbrtowc */
1782 int __cdecl _Mbrtowc(wchar_t *out, const char *in, MSVCP_size_t len, int *state, const _Cvtvec *cvt)
1783 {
1784     int i, cp;
1785     CPINFO cp_info;
1786     BOOL is_lead;
1787
1788     TRACE("(%p %p %lu %p %p)\n", out, in, len, state, cvt);
1789
1790     if(!len)
1791         return 0;
1792
1793     if(cvt)
1794         cp = cvt->page;
1795     else
1796         cp = ___lc_codepage_func();
1797
1798     if(!cp) {
1799         if(out)
1800             *out = (unsigned char)*in;
1801
1802         *state = 0;
1803         return *in ? 1 : 0;
1804     }
1805
1806     if(*state) {
1807         ((char*)state)[1] = *in;
1808
1809         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, (char*)state, 2, out, out ? 1 : 0)) {
1810             *state = 0;
1811             *_errno() = EILSEQ;
1812             return -1;
1813         }
1814
1815         *state = 0;
1816         return 2;
1817     }
1818
1819     GetCPInfo(cp, &cp_info);
1820     is_lead = FALSE;
1821     for(i=0; i<MAX_LEADBYTES; i+=2) {
1822         if(!cp_info.LeadByte[i+1])
1823             break;
1824         if((unsigned char)*in>=cp_info.LeadByte[i] && (unsigned char)*in<=cp_info.LeadByte[i+1]) {
1825             is_lead = TRUE;
1826             break;
1827         }
1828     }
1829
1830     if(is_lead) {
1831         if(len == 1) {
1832             *state = (unsigned char)*in;
1833             return -2;
1834         }
1835
1836         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 2, out, out ? 1 : 0)) {
1837             *_errno() = EILSEQ;
1838             return -1;
1839         }
1840         return 2;
1841     }
1842
1843     if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 1, out, out ? 1 : 0)) {
1844         *_errno() = EILSEQ;
1845         return -1;
1846     }
1847     return 1;
1848 }
1849
1850 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
1851 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
1852 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
1853 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
1854 static wchar_t ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
1855 {
1856     wchar_t ret;
1857     int state = 0;
1858     TRACE("(%p %d)\n", this, ch);
1859     return _Mbrtowc(&ret, &ch, 1, &state, &this->cvt)<0 ? WEOF : ret;
1860 }
1861
1862 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
1863 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
1864 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
1865 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
1866 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
1867 #define call_ctype_wchar_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 40, \
1868         wchar_t, (const ctype_wchar*, char), (this, ch))
1869 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
1870 {
1871     return ctype_wchar__Dowiden(this, ch);
1872 }
1873
1874 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
1875 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
1876 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
1877 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
1878 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
1879 #define call_ctype_wchar_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 36, \
1880         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*), \
1881         (this, first, last, dest))
1882 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
1883         const char *first, const char *last, wchar_t *dest)
1884 {
1885     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1886     for(; first<last; first++)
1887         *dest++ = ctype_wchar__Dowiden(this, *first);
1888     return last;
1889 }
1890
1891 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
1892 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
1893 /* ?widen@?$ctype@G@std@@QBEGD@Z */
1894 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
1895 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
1896 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
1897 {
1898     TRACE("(%p %d)\n", this, ch);
1899     return call_ctype_wchar_do_widen_ch(this, ch);
1900 }
1901
1902 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
1903 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
1904 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
1905 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
1906 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
1907 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
1908         const char *first, const char *last, wchar_t *dest)
1909 {
1910     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1911     return call_ctype_wchar_do_widen(this, first, last, dest);
1912 }
1913
1914 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1915 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1916 static MSVCP_size_t ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
1917 {
1918     TRACE("(%p %p)\n", facet, loc);
1919
1920     if(facet && !*facet) {
1921         _Locinfo locinfo;
1922
1923         *facet = MSVCRT_operator_new(sizeof(ctype_wchar));
1924         if(!*facet) {
1925             ERR("Out of memory\n");
1926             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1927             return 0;
1928         }
1929
1930         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
1931         ctype_wchar_ctor_locinfo((ctype_wchar*)*facet, &locinfo, 0);
1932         _Locinfo_dtor(&locinfo);
1933     }
1934
1935     return LC_CTYPE;
1936 }
1937
1938 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1939 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1940 static MSVCP_size_t ctype_short__Getcat(const locale_facet **facet, const locale *loc)
1941 {
1942     if(facet && !*facet) {
1943         ctype_wchar__Getcat(facet, loc);
1944         (*(locale_facet**)facet)->vtable = &MSVCP_ctype_short_vtable;
1945     }
1946
1947     return LC_CTYPE;
1948 }
1949
1950 /* _Towlower */
1951 static wchar_t _Towlower(wchar_t ch, const _Ctypevec *ctype)
1952 {
1953     TRACE("(%d %p)\n", ch, ctype);
1954     return tolowerW(ch);
1955 }
1956
1957 ctype_wchar* ctype_wchar_use_facet(const locale *loc)
1958 {
1959     static ctype_wchar *obj = NULL;
1960
1961     _Lockit lock;
1962     const locale_facet *fac;
1963
1964     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1965     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_wchar_id));
1966     if(fac) {
1967         _Lockit_dtor(&lock);
1968         return (ctype_wchar*)fac;
1969     }
1970
1971     if(obj) {
1972         _Lockit_dtor(&lock);
1973         return obj;
1974     }
1975
1976     ctype_wchar__Getcat(&fac, loc);
1977     obj = (ctype_wchar*)fac;
1978     locale_facet__Incref(&obj->base.facet);
1979     locale_facet_register(&obj->base.facet);
1980     _Lockit_dtor(&lock);
1981
1982     return obj;
1983 }
1984
1985 ctype_wchar* ctype_short_use_facet(const locale *loc)
1986 {
1987     static ctype_wchar *obj = NULL;
1988
1989     _Lockit lock;
1990     const locale_facet *fac;
1991
1992     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1993     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_short_id));
1994     if(fac) {
1995         _Lockit_dtor(&lock);
1996         return (ctype_wchar*)fac;
1997     }
1998
1999     if(obj) {
2000         _Lockit_dtor(&lock);
2001         return obj;
2002     }
2003
2004     ctype_short__Getcat(&fac, loc);
2005     obj = (ctype_wchar*)fac;
2006     locale_facet__Incref(&obj->base.facet);
2007     locale_facet_register(&obj->base.facet);
2008     _Lockit_dtor(&lock);
2009
2010     return obj;
2011 }
2012
2013 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
2014 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
2015 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
2016 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
2017 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
2018 #define call_ctype_wchar_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
2019         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2020 wchar_t __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
2021 {
2022     return _Towlower(ch, &this->ctype);
2023 }
2024
2025 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2026 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2027 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2028 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2029 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
2030 #define call_ctype_wchar_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 20, \
2031         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2032         (this, first, last))
2033 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
2034         wchar_t *first, const wchar_t *last)
2035 {
2036     TRACE("(%p %p %p)\n", this, first, last);
2037     for(; first<last; first++)
2038         *first = _Towlower(*first, &this->ctype);
2039     return last;
2040 }
2041
2042 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
2043 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
2044 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
2045 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
2046 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
2047 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
2048 {
2049     TRACE("(%p %d)\n", this, ch);
2050     return call_ctype_wchar_do_tolower_ch(this, ch);
2051 }
2052
2053 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2054 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2055 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2056 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2057 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
2058 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
2059         wchar_t *first, const wchar_t *last)
2060 {
2061     TRACE("(%p %p %p)\n", this, first, last);
2062     return call_ctype_wchar_do_tolower(this, first, last);
2063 }
2064
2065 /* _Towupper */
2066 static wchar_t _Towupper(wchar_t ch, const _Ctypevec *ctype)
2067 {
2068     TRACE("(%d %p)\n", ch, ctype);
2069     return toupperW(ch);
2070 }
2071
2072 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
2073 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
2074 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
2075 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
2076 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
2077 #define call_ctype_wchar_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 32, \
2078         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2079 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
2080 {
2081     return _Towupper(ch, &this->ctype);
2082 }
2083
2084 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2085 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2086 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2087 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2088 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
2089 #define call_ctype_wchar_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 28, \
2090         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2091         (this, first, last))
2092 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
2093         wchar_t *first, const wchar_t *last)
2094 {
2095     TRACE("(%p %p %p)\n", this, first, last);
2096     for(; first<last; first++)
2097         *first = _Towupper(*first, &this->ctype);
2098     return last;
2099 }
2100
2101 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
2102 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
2103 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
2104 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
2105 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
2106 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
2107 {
2108     TRACE("(%p %d)\n", this, ch);
2109     return call_ctype_wchar_do_toupper_ch(this, ch);
2110 }
2111
2112 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2113 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2114 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2115 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2116 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
2117 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
2118         wchar_t *first, const wchar_t *last)
2119 {
2120     TRACE("(%p %p %p)\n", this, first, last);
2121     return call_ctype_wchar_do_toupper(this, first, last);
2122 }
2123
2124 /* _Getwctypes */
2125 static const wchar_t* _Getwctypes(const wchar_t *first, const wchar_t *last,
2126         short *mask, const _Ctypevec *ctype)
2127 {
2128     TRACE("(%p %p %p %p)\n", first, last, mask, ctype);
2129     GetStringTypeW(CT_CTYPE1, first, last-first, (WORD*)mask);
2130     return last;
2131 }
2132
2133 /* _Getwctype */
2134 static short _Getwctype(wchar_t ch, const _Ctypevec *ctype)
2135 {
2136     short mask = 0;
2137     _Getwctypes(&ch, &ch+1, &mask, ctype);
2138     return mask;
2139 }
2140
2141 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
2142 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
2143 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
2144 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
2145 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
2146 #define call_ctype_wchar_do_is_ch(this, mask, ch) CALL_VTBL_FUNC(this, 8, \
2147         MSVCP_bool, (const ctype_wchar*, short, wchar_t), (this, mask, ch))
2148 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2149 {
2150     TRACE("(%p %x %d)\n", this, mask, ch);
2151     return (_Getwctype(ch, &this->ctype) & mask) != 0;
2152 }
2153
2154 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
2155 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
2156 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
2157 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
2158 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
2159 #define call_ctype_wchar_do_is(this, first, last, dest) CALL_VTBL_FUNC(this, 4, \
2160         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, short*), \
2161         (this, first, last, dest))
2162 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
2163         const wchar_t *first, const wchar_t *last, short *dest)
2164 {
2165     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2166     return _Getwctypes(first, last, dest, &this->ctype);
2167 }
2168
2169 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
2170 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
2171 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
2172 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
2173 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
2174 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2175 {
2176     TRACE("(%p %x %d)\n", this, mask, ch);
2177     return call_ctype_wchar_do_is_ch(this, mask, ch);
2178 }
2179
2180 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
2181 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
2182 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
2183 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
2184 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
2185 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
2186         const wchar_t *first, const wchar_t *last, short *dest)
2187 {
2188     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2189     return call_ctype_wchar_do_is(this, first, last, dest);
2190 }
2191
2192 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2193 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2194 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
2195 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2196 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
2197 #define call_ctype_wchar_do_scan_is(this, mask, first, last) CALL_VTBL_FUNC(this, 12, \
2198         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2199         (this, mask, first, last))
2200 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
2201         short mask, const wchar_t *first, const wchar_t *last)
2202 {
2203     TRACE("(%p %d %p %p)\n", this, mask, first, last);
2204     for(; first<last; first++)
2205         if(!ctype_wchar_is_ch(this, mask, *first))
2206             break;
2207     return first;
2208 }
2209
2210 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2211 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2212 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
2213 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2214 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
2215 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
2216         short mask, const wchar_t *first, const wchar_t *last)
2217 {
2218     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2219     return call_ctype_wchar_do_scan_is(this, mask, first, last);
2220 }
2221
2222 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2223 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2224 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2225 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2226 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2227 #define call_ctype_wchar_do_scan_not(this, mask, first, last) CALL_VTBL_FUNC(this, 16, \
2228         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2229         (this, mask, first, last))
2230 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2231         short mask, const wchar_t *first, const wchar_t *last)
2232 {
2233     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2234     for(; first<last; first++)
2235         if(ctype_wchar_is_ch(this, mask, *first))
2236             break;
2237     return first;
2238 }
2239
2240 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2241 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2242 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2243 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2244 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2245 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2246         short mask, const wchar_t *first, const wchar_t *last)
2247 {
2248     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2249     return call_ctype_wchar_do_scan_not(this, mask, first, last);
2250 }
2251
2252 /* ??_7codecvt_base@std@@6B@ */
2253 extern const vtable_ptr MSVCP_codecvt_base_vtable;
2254
2255 /* ??0codecvt_base@std@@QAE@I@Z */
2256 /* ??0codecvt_base@std@@QEAA@_K@Z */
2257 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor_refs, 8)
2258 codecvt_base* __thiscall codecvt_base_ctor_refs(codecvt_base *this, MSVCP_size_t refs)
2259 {
2260     TRACE("(%p %lu)\n", this, refs);
2261     locale_facet_ctor_refs(&this->facet, refs);
2262     this->facet.vtable = &MSVCP_codecvt_base_vtable;
2263     return this;
2264 }
2265
2266 /* ??_Fcodecvt_base@std@@QAEXXZ */
2267 /* ??_Fcodecvt_base@std@@QEAAXXZ */
2268 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor, 4)
2269 codecvt_base* __thiscall codecvt_base_ctor(codecvt_base *this)
2270 {
2271     return codecvt_base_ctor_refs(this, 0);
2272 }
2273
2274 /* ??1codecvt_base@std@@UAE@XZ */
2275 /* ??1codecvt_base@std@@UEAA@XZ */
2276 DEFINE_THISCALL_WRAPPER(codecvt_base_dtor, 4)
2277 void __thiscall codecvt_base_dtor(codecvt_base *this)
2278 {
2279     TRACE("(%p)\n", this);
2280     locale_facet_dtor(&this->facet);
2281 }
2282
2283 DEFINE_THISCALL_WRAPPER(codecvt_base_vector_dtor, 8)
2284 codecvt_base* __thiscall codecvt_base_vector_dtor(codecvt_base *this, unsigned int flags)
2285 {
2286     TRACE("(%p %x)\n", this, flags);
2287     if(flags & 2) {
2288         /* we have an array, with the number of elements stored before the first object */
2289         INT_PTR i, *ptr = (INT_PTR *)this-1;
2290
2291         for(i=*ptr-1; i>=0; i--)
2292             codecvt_base_dtor(this+i);
2293         MSVCRT_operator_delete(ptr);
2294     } else {
2295         codecvt_base_dtor(this);
2296         if(flags & 1)
2297             MSVCRT_operator_delete(this);
2298     }
2299
2300     return this;
2301 }
2302
2303 /* ?do_always_noconv@codecvt_base@std@@MBE_NXZ */
2304 /* ?do_always_noconv@codecvt_base@std@@MEBA_NXZ */
2305 #define call_codecvt_base_do_always_noconv(this) CALL_VTBL_FUNC(this, 4, \
2306         MSVCP_bool, (const codecvt_base*), (this))
2307 DEFINE_THISCALL_WRAPPER(codecvt_base_do_always_noconv, 4)
2308 MSVCP_bool __thiscall codecvt_base_do_always_noconv(const codecvt_base *this)
2309 {
2310     TRACE("(%p)\n", this);
2311     return TRUE;
2312 }
2313
2314 /* ?always_noconv@codecvt_base@std@@QBE_NXZ */
2315 /* ?always_noconv@codecvt_base@std@@QEBA_NXZ */
2316 DEFINE_THISCALL_WRAPPER(codecvt_base_always_noconv, 4)
2317 MSVCP_bool __thiscall codecvt_base_always_noconv(const codecvt_base *this)
2318 {
2319     TRACE("(%p)\n", this);
2320     return call_codecvt_base_do_always_noconv(this);
2321 }
2322
2323 /* ?do_max_length@codecvt_base@std@@MBEHXZ */
2324 /* ?do_max_length@codecvt_base@std@@MEBAHXZ */
2325 #define call_codecvt_base_do_max_length(this) CALL_VTBL_FUNC(this, 8, \
2326         int, (const codecvt_base*), (this))
2327 DEFINE_THISCALL_WRAPPER(codecvt_base_do_max_length, 4)
2328 int __thiscall codecvt_base_do_max_length(const codecvt_base *this)
2329 {
2330     TRACE("(%p)\n", this);
2331     return 1;
2332 }
2333
2334 /* ?max_length@codecvt_base@std@@QBEHXZ */
2335 /* ?max_length@codecvt_base@std@@QEBAHXZ */
2336 DEFINE_THISCALL_WRAPPER(codecvt_base_max_length, 4)
2337 int __thiscall codecvt_base_max_length(const codecvt_base *this)
2338 {
2339     TRACE("(%p)\n", this);
2340     return call_codecvt_base_do_max_length(this);
2341 }
2342
2343 /* ?do_encoding@codecvt_base@std@@MBEHXZ */
2344 /* ?do_encoding@codecvt_base@std@@MEBAHXZ */
2345 #define call_codecvt_base_do_encoding(this) CALL_VTBL_FUNC(this, 12, \
2346         int, (const codecvt_base*), (this))
2347 DEFINE_THISCALL_WRAPPER(codecvt_base_do_encoding, 4)
2348 int __thiscall codecvt_base_do_encoding(const codecvt_base *this)
2349 {
2350     TRACE("(%p)\n", this);
2351     return 1;
2352 }
2353
2354 /* ?encoding@codecvt_base@std@@QBEHXZ */
2355 /* ?encoding@codecvt_base@std@@QEBAHXZ */
2356 DEFINE_THISCALL_WRAPPER(codecvt_base_encoding, 4)
2357 int __thiscall codecvt_base_encoding(const codecvt_base *this)
2358 {
2359     TRACE("(%p)\n", this);
2360     return call_codecvt_base_do_encoding(this);
2361 }
2362
2363 /* ?id@?$codecvt@DDH@std@@2V0locale@2@A */
2364 locale_id codecvt_char_id = {0};
2365
2366 /* ??_7?$codecvt@DDH@std@@6B@ */
2367 extern const vtable_ptr MSVCP_codecvt_char_vtable;
2368
2369 /* ?_Init@?$codecvt@DDH@std@@IAEXABV_Locinfo@2@@Z */
2370 /* ?_Init@?$codecvt@DDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2371 DEFINE_THISCALL_WRAPPER(codecvt_char__Init, 8)
2372 void __thiscall codecvt_char__Init(codecvt_char *this, const _Locinfo *locinfo)
2373 {
2374     TRACE("(%p %p)\n", this, locinfo);
2375 }
2376
2377 /* ??0?$codecvt@DDH@std@@QAE@ABV_Locinfo@1@I@Z */
2378 /* ??0?$codecvt@DDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2379 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_locinfo, 12)
2380 codecvt_char* __thiscall codecvt_char_ctor_locinfo(codecvt_char *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2381 {
2382     TRACE("(%p %p %lu)\n", this, locinfo, refs);
2383     codecvt_base_ctor_refs(&this->base, refs);
2384     this->base.facet.vtable = &MSVCP_codecvt_char_vtable;
2385     return this;
2386 }
2387
2388 /* ??0?$codecvt@DDH@std@@QAE@I@Z */
2389 /* ??0?$codecvt@DDH@std@@QEAA@_K@Z */
2390 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_refs, 8)
2391 codecvt_char* __thiscall codecvt_char_ctor_refs(codecvt_char *this, MSVCP_size_t refs)
2392 {
2393     return codecvt_char_ctor_locinfo(this, NULL, refs);
2394 }
2395
2396 /* ??_F?$codecvt@DDH@std@@QAEXXZ */
2397 /* ??_F?$codecvt@DDH@std@@QEAAXXZ */
2398 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor, 4)
2399 codecvt_char* __thiscall codecvt_char_ctor(codecvt_char *this)
2400 {
2401     return codecvt_char_ctor_locinfo(this, NULL, 0);
2402 }
2403
2404 /* ??1?$codecvt@DDH@std@@UAE@XZ */
2405 /* ??1?$codecvt@DDH@std@@UEAA@XZ */
2406 DEFINE_THISCALL_WRAPPER(codecvt_char_dtor, 4)
2407 void __thiscall codecvt_char_dtor(codecvt_char *this)
2408 {
2409     TRACE("(%p)\n", this);
2410     codecvt_base_dtor(&this->base);
2411 }
2412
2413 DEFINE_THISCALL_WRAPPER(codecvt_char_vector_dtor, 8)
2414 codecvt_char* __thiscall codecvt_char_vector_dtor(codecvt_char *this, unsigned int flags)
2415 {
2416     TRACE("(%p %x)\n", this, flags);
2417     if(flags & 2) {
2418         /* we have an array, with the number of elements stored before the first object */
2419         INT_PTR i, *ptr = (INT_PTR *)this-1;
2420
2421         for(i=*ptr-1; i>=0; i--)
2422             codecvt_char_dtor(this+i);
2423         MSVCRT_operator_delete(ptr);
2424     } else {
2425         codecvt_char_dtor(this);
2426         if(flags & 1)
2427             MSVCRT_operator_delete(this);
2428     }
2429
2430     return this;
2431 }
2432
2433 /* ?_Getcat@?$codecvt@DDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2434 /* ?_Getcat@?$codecvt@DDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2435 static MSVCP_size_t codecvt_char__Getcat(const locale_facet **facet, const locale *loc)
2436 {
2437     TRACE("(%p %p)\n", facet, loc);
2438
2439     if(facet && !*facet) {
2440         *facet = MSVCRT_operator_new(sizeof(codecvt_char));
2441         if(!*facet) {
2442             ERR("Out of memory\n");
2443             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2444             return 0;
2445         }
2446         codecvt_char_ctor((codecvt_char*)*facet);
2447     }
2448
2449     return LC_CTYPE;
2450 }
2451
2452 codecvt_char* codecvt_char_use_facet(const locale *loc)
2453 {
2454     static codecvt_char *obj = NULL;
2455
2456     _Lockit lock;
2457     const locale_facet *fac;
2458
2459     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2460     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_char_id));
2461     if(fac) {
2462         _Lockit_dtor(&lock);
2463         return (codecvt_char*)fac;
2464     }
2465
2466     if(obj) {
2467         _Lockit_dtor(&lock);
2468         return obj;
2469     }
2470
2471     codecvt_char__Getcat(&fac, loc);
2472     obj = (codecvt_char*)fac;
2473     locale_facet__Incref(&obj->base.facet);
2474     locale_facet_register(&obj->base.facet);
2475     _Lockit_dtor(&lock);
2476
2477     return obj;
2478 }
2479
2480 /* ?do_in@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2481 /* ?do_in@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2482 #define call_codecvt_char_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2483     CALL_VTBL_FUNC(this, 16, int, \
2484             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2485             (this, state, from, from_end, from_next, to, to_end, to_next))
2486 DEFINE_THISCALL_WRAPPER(codecvt_char_do_in, 32)
2487 int __thiscall codecvt_char_do_in(const codecvt_char *this, int *state,
2488         const char *from, const char *from_end, const char **from_next,
2489         char *to, char *to_end, char **to_next)
2490 {
2491     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2492             from_next, to, to_end, to_next);
2493     *from_next = from;
2494     *to_next = to;
2495     return CODECVT_noconv;
2496 }
2497
2498 /* ?in@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2499 /* ?in@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2500 DEFINE_THISCALL_WRAPPER(codecvt_char_in, 32)
2501 int __thiscall codecvt_char_in(const codecvt_char *this, int *state,
2502         const char *from, const char *from_end, const char **from_next,
2503         char *to, char *to_end, char **to_next)
2504 {
2505     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2506             from_next, to, to_end, to_next);
2507     return call_codecvt_char_do_in(this, state, from, from_end, from_next,
2508             to, to_end, to_next);
2509 }
2510
2511 /* ?do_out@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2512 /* ?do_out@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2513 #define call_codecvt_char_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2514     CALL_VTBL_FUNC(this, 20, int, \
2515             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2516             (this, state, from, from_end, from_next, to, to_end, to_next))
2517 DEFINE_THISCALL_WRAPPER(codecvt_char_do_out, 32)
2518 int __thiscall codecvt_char_do_out(const codecvt_char *this, int *state,
2519         const char *from, const char *from_end, const char **from_next,
2520         char *to, char *to_end, char **to_next)
2521 {
2522     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2523             from_end, from_next, to, to_end, to_next);
2524     *from_next = from;
2525     *to_next = to;
2526     return CODECVT_noconv;
2527 }
2528
2529 /* ?out@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2530 /* ?out@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2531 DEFINE_THISCALL_WRAPPER(codecvt_char_out, 32)
2532 int __thiscall codecvt_char_out(const codecvt_char *this, int *state,
2533         const char *from, const char *from_end, const char **from_next,
2534         char *to, char *to_end, char **to_next)
2535 {
2536     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2537             from_next, to, to_end, to_next);
2538     return call_codecvt_char_do_out(this, state, from, from_end, from_next,
2539             to, to_end, to_next);
2540 }
2541
2542 /* ?do_unshift@?$codecvt@DDH@std@@MBEHAAHPAD1AAPAD@Z */
2543 /* ?do_unshift@?$codecvt@DDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2544 #define call_codecvt_char_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2545         int, (const codecvt_char*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2546 DEFINE_THISCALL_WRAPPER(codecvt_char_do_unshift, 20)
2547 int __thiscall codecvt_char_do_unshift(const codecvt_char *this,
2548         int *state, char *to, char *to_end, char **to_next)
2549 {
2550     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2551     *to_next = to;
2552     return CODECVT_noconv;
2553 }
2554
2555 /* ?do_length@?$codecvt@DDH@std@@MBEHABHPBD1I@Z */
2556 /* ?do_length@?$codecvt@DDH@std@@MEBAHAEBHPEBD1_K@Z */
2557 #define call_codecvt_char_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2558         int, (const codecvt_char*, const int*, const char*, const char*, MSVCP_size_t), \
2559         (this, state, from, from_end, max))
2560 DEFINE_THISCALL_WRAPPER(codecvt_char_do_length, 20)
2561 int __thiscall codecvt_char_do_length(const codecvt_char *this, const int *state,
2562         const char *from, const char *from_end, MSVCP_size_t max)
2563 {
2564     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2565     return (from_end-from > max ? max : from_end-from);
2566 }
2567
2568 /* ?id@?$codecvt@_WDH@std@@2V0locale@2@A */
2569 static locale_id codecvt_wchar_id = {0};
2570 /* ?id@?$codecvt@GDH@std@@2V0locale@2@A */
2571 locale_id codecvt_short_id = {0};
2572
2573 /* ??_7?$codecvt@_WDH@std@@6B@ */
2574 extern const vtable_ptr MSVCP_codecvt_wchar_vtable;
2575 /* ??_7?$codecvt@GDH@std@@6B@ */
2576 extern const vtable_ptr MSVCP_codecvt_short_vtable;
2577
2578 /* ?_Init@?$codecvt@GDH@std@@IAEXABV_Locinfo@2@@Z */
2579 /* ?_Init@?$codecvt@GDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2580 /* ?_Init@?$codecvt@_WDH@std@@IAEXABV_Locinfo@2@@Z */
2581 /* ?_Init@?$codecvt@_WDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2582 DEFINE_THISCALL_WRAPPER(codecvt_wchar__Init, 8)
2583 void __thiscall codecvt_wchar__Init(codecvt_wchar *this, const _Locinfo *locinfo)
2584 {
2585     TRACE("(%p %p)\n", this, locinfo);
2586     _Locinfo__Getcvt(locinfo, &this->cvt);
2587 }
2588
2589 /* ??0?$codecvt@_WDH@std@@QAE@ABV_Locinfo@1@I@Z */
2590 /* ??0?$codecvt@_WDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2591 static codecvt_wchar* codecvt_wchar_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2592 {
2593     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2594
2595     codecvt_base_ctor_refs(&this->base, refs);
2596     this->base.facet.vtable = &MSVCP_codecvt_wchar_vtable;
2597
2598     codecvt_wchar__Init(this, locinfo);
2599     return this;
2600 }
2601
2602 /* ??0?$codecvt@GDH@std@@QAE@ABV_Locinfo@1@I@Z */
2603 /* ??0?$codecvt@GDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2604 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_locinfo, 12)
2605 codecvt_wchar* __thiscall codecvt_short_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2606 {
2607     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2608
2609     codecvt_wchar_ctor_locinfo(this, locinfo, refs);
2610     this->base.facet.vtable = &MSVCP_codecvt_short_vtable;
2611     return this;
2612 }
2613
2614 /* ??0?$codecvt@GDH@std@@QAE@I@Z */
2615 /* ??0?$codecvt@GDH@std@@QEAA@_K@Z */
2616 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_refs, 8)
2617 codecvt_wchar* __thiscall codecvt_short_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
2618 {
2619     _Locinfo locinfo;
2620
2621     TRACE("(%p %ld)\n", this, refs);
2622
2623     _Locinfo_ctor(&locinfo);
2624     codecvt_short_ctor_locinfo(this, &locinfo, refs);
2625     _Locinfo_dtor(&locinfo);
2626     return this;
2627 }
2628
2629 /* ??_F?$codecvt@GDH@std@@QAEXXZ */
2630 /* ??_F?$codecvt@GDH@std@@QEAAXXZ */
2631 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor, 4)
2632 codecvt_wchar* __thiscall codecvt_short_ctor(codecvt_wchar *this)
2633 {
2634     return codecvt_short_ctor_refs(this, 0);
2635 }
2636
2637 /* ??1?$codecvt@GDH@std@@UAE@XZ */
2638 /* ??1?$codecvt@GDH@std@@UEAA@XZ */
2639 DEFINE_THISCALL_WRAPPER(codecvt_wchar_dtor, 4)
2640 void __thiscall codecvt_wchar_dtor(codecvt_wchar *this)
2641 {
2642     TRACE("(%p)\n", this);
2643     codecvt_base_dtor(&this->base);
2644 }
2645
2646 DEFINE_THISCALL_WRAPPER(codecvt_wchar_vector_dtor, 8)
2647 codecvt_wchar* __thiscall codecvt_wchar_vector_dtor(codecvt_wchar *this, unsigned int flags)
2648 {
2649     TRACE("(%p %x)\n", this, flags);
2650     if(flags & 2) {
2651         /* we have an array, with the number of elements stored before the first object */
2652         INT_PTR i, *ptr = (INT_PTR *)this-1;
2653
2654         for(i=*ptr-1; i>=0; i--)
2655             codecvt_wchar_dtor(this+i);
2656         MSVCRT_operator_delete(ptr);
2657     } else {
2658         codecvt_wchar_dtor(this);
2659         if(flags & 1)
2660             MSVCRT_operator_delete(this);
2661     }
2662
2663     return this;
2664 }
2665
2666 /* ?_Getcat@?$codecvt@_WDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2667 /* ?_Getcat@?$codecvt@_WDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2668 static MSVCP_size_t codecvt_wchar__Getcat(const locale_facet **facet, const locale *loc)
2669 {
2670     TRACE("(%p %p)\n", facet, loc);
2671
2672     if(facet && !*facet) {
2673         _Locinfo locinfo;
2674
2675         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2676         if(!*facet) {
2677             ERR("Out of memory\n");
2678             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2679             return 0;
2680         }
2681
2682         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
2683         codecvt_wchar_ctor_locinfo((codecvt_wchar*)*facet, &locinfo, 0);
2684         _Locinfo_dtor(&locinfo);
2685     }
2686
2687     return LC_CTYPE;
2688 }
2689
2690 static codecvt_wchar* codecvt_wchar_use_facet(const locale *loc)
2691 {
2692     static codecvt_wchar *obj = NULL;
2693
2694     _Lockit lock;
2695     const locale_facet *fac;
2696
2697     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2698     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_wchar_id));
2699     if(fac) {
2700         _Lockit_dtor(&lock);
2701         return (codecvt_wchar*)fac;
2702     }
2703
2704     if(obj) {
2705         _Lockit_dtor(&lock);
2706         return obj;
2707     }
2708
2709     codecvt_wchar__Getcat(&fac, loc);
2710     obj = (codecvt_wchar*)fac;
2711     locale_facet__Incref(&obj->base.facet);
2712     locale_facet_register(&obj->base.facet);
2713     _Lockit_dtor(&lock);
2714
2715     return obj;
2716 }
2717
2718 /* ?_Getcat@?$codecvt@GDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2719 /* ?_Getcat@?$codecvt@GDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2720 static MSVCP_size_t codecvt_short__Getcat(const locale_facet **facet, const locale *loc)
2721 {
2722     TRACE("(%p %p)\n", facet, loc);
2723
2724     if(facet && !*facet) {
2725         _Locinfo locinfo;
2726
2727         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2728         if(!*facet) {
2729             ERR("Out of memory\n");
2730             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2731             return 0;
2732         }
2733
2734         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
2735         codecvt_short_ctor((codecvt_wchar*)*facet);
2736         _Locinfo_dtor(&locinfo);
2737     }
2738
2739     return LC_CTYPE;
2740 }
2741
2742 codecvt_wchar* codecvt_short_use_facet(const locale *loc)
2743 {
2744     static codecvt_wchar *obj = NULL;
2745
2746     _Lockit lock;
2747     const locale_facet *fac;
2748
2749     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2750     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_short_id));
2751     if(fac) {
2752         _Lockit_dtor(&lock);
2753         return (codecvt_wchar*)fac;
2754     }
2755
2756     if(obj) {
2757         _Lockit_dtor(&lock);
2758         return obj;
2759     }
2760
2761     codecvt_short__Getcat(&fac, loc);
2762     obj = (codecvt_wchar*)fac;
2763     locale_facet__Incref(&obj->base.facet);
2764     locale_facet_register(&obj->base.facet);
2765     _Lockit_dtor(&lock);
2766
2767     return obj;
2768 }
2769
2770 /* ?do_always_noconv@?$codecvt@GDH@std@@MBE_NXZ */
2771 /* ?do_always_noconv@?$codecvt@GDH@std@@MEBA_NXZ */
2772 /* ?do_always_noconv@?$codecvt@_WDH@std@@MBE_NXZ */
2773 /* ?do_always_noconv@?$codecvt@_WDH@std@@MEBA_NXZ */
2774 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_always_noconv, 4)
2775 MSVCP_bool __thiscall codecvt_wchar_do_always_noconv(const codecvt_wchar *this)
2776 {
2777     TRACE("(%p)\n", this);
2778     return FALSE;
2779 }
2780
2781 /* ?do_max_length@?$codecvt@GDH@std@@MBEHXZ */
2782 /* ?do_max_length@?$codecvt@GDH@std@@MEBAHXZ */
2783 /* ?do_max_length@?$codecvt@_WDH@std@@MBEHXZ */
2784 /* ?do_max_length@?$codecvt@_WDH@std@@MEBAHXZ */
2785 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_max_length, 4)
2786 int __thiscall codecvt_wchar_do_max_length(const codecvt_wchar *this)
2787 {
2788     TRACE("(%p)\n", this);
2789     return MB_LEN_MAX;
2790 }
2791
2792 /* ?do_in@?$codecvt@GDH@std@@MBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2793 /* ?do_in@?$codecvt@GDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2794 /* ?do_in@?$codecvt@_WDH@std@@MBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2795 /* ?do_in@?$codecvt@_WDH@std@@MEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2796 #define call_codecvt_wchar_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2797     CALL_VTBL_FUNC(this, 16, int, \
2798             (const codecvt_wchar*, int*, const char*, const char*, const char**, wchar_t*, wchar_t*, wchar_t**), \
2799             (this, state, from, from_end, from_next, to, to_end, to_next))
2800 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_in, 32)
2801 int __thiscall codecvt_wchar_do_in(const codecvt_wchar *this, int *state,
2802         const char *from, const char *from_end, const char **from_next,
2803         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2804 {
2805     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2806             from_end, from_next, to, to_end, to_next);
2807
2808     *from_next = from;
2809     *to_next = to;
2810
2811     while(*from_next!=from_end && *to_next!=to_end) {
2812         switch(_Mbrtowc(*to_next, *from_next, from_end-*from_next, state, &this->cvt)) {
2813         case -2:
2814             *from_next = from_end;
2815             return CODECVT_partial;
2816         case -1:
2817             return CODECVT_error;
2818         case 2:
2819             (*from_next)++;
2820             /* fall through */
2821         case 0:
2822         case 1:
2823             (*from_next)++;
2824             (*to_next)++;
2825         }
2826     }
2827
2828     return CODECVT_ok;
2829 }
2830
2831 /* ?in@?$codecvt@GDH@std@@QBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2832 /* ?in@?$codecvt@GDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2833 /* ?in@?$codecvt@_WDH@std@@QBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2834 /* ?in@?$codecvt@_WDH@std@@QEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2835 DEFINE_THISCALL_WRAPPER(codecvt_wchar_in, 32)
2836 int __thiscall codecvt_wchar_in(const codecvt_wchar *this, int *state,
2837         const char *from, const char *from_end, const char **from_next,
2838         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2839 {
2840     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2841             from_end, from_next, to, to_end, to_next);
2842     return call_codecvt_wchar_do_in(this, state, from,
2843             from_end, from_next, to, to_end, to_next);
2844 }
2845
2846 /* ?do_out@?$codecvt@GDH@std@@MBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2847 /* ?do_out@?$codecvt@GDH@std@@MEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2848 /* ?do_out@?$codecvt@_WDH@std@@MBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2849 /* ?do_out@?$codecvt@_WDH@std@@MEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2850 #define call_codecvt_wchar_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2851     CALL_VTBL_FUNC(this, 20, int, \
2852             (const codecvt_wchar*, int*, const wchar_t*, const wchar_t*, const wchar_t**, char*, char*, char**), \
2853             (this, state, from, from_end, from_next, to, to_end, to_next))
2854 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_out, 32)
2855 int __thiscall codecvt_wchar_do_out(const codecvt_wchar *this, int *state,
2856         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2857         char *to, char *to_end, char **to_next)
2858 {
2859     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2860             from_end, from_next, to, to_end, to_next);
2861
2862     *from_next = from;
2863     *to_next = to;
2864
2865     while(*from_next!=from_end && *to_next!=to_end) {
2866         int old_state = *state, size;
2867         char buf[MB_LEN_MAX];
2868
2869         switch((size = _Wcrtomb(buf, **from_next, state, &this->cvt))) {
2870         case -1:
2871             return CODECVT_error;
2872         default:
2873             if(size > from_end-*from_next) {
2874                 *state = old_state;
2875                 return CODECVT_partial;
2876             }
2877
2878             (*from_next)++;
2879             memcpy_s(*to_next, to_end-*to_next, buf, size);
2880             (*to_next) += size;
2881         }
2882     }
2883
2884     return CODECVT_ok;
2885 }
2886
2887 /* ?out@?$codecvt@GDH@std@@QBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2888 /* ?out@?$codecvt@GDH@std@@QEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2889 /* ?out@?$codecvt@_WDH@std@@QBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2890 /* ?out@?$codecvt@_WDH@std@@QEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2891 DEFINE_THISCALL_WRAPPER(codecvt_wchar_out, 32)
2892 int __thiscall codecvt_wchar_out(const codecvt_wchar *this, int *state,
2893         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2894         char *to, char *to_end, char **to_next)
2895 {
2896     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2897             from_end, from_next, to, to_end, to_next);
2898     return call_codecvt_wchar_do_out(this, state, from,
2899             from_end, from_next, to, to_end, to_next);
2900 }
2901
2902 /* ?do_unshift@?$codecvt@GDH@std@@MBEHAAHPAD1AAPAD@Z */
2903 /* ?do_unshift@?$codecvt@GDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2904 /* ?do_unshift@?$codecvt@_WDH@std@@MBEHAAHPAD1AAPAD@Z */
2905 /* ?do_unshift@?$codecvt@_WDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2906 #define call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2907         int, (const codecvt_wchar*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2908 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_unshift, 20)
2909 int __thiscall codecvt_wchar_do_unshift(const codecvt_wchar *this,
2910         int *state, char *to, char *to_end, char **to_next)
2911 {
2912     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2913     if(*state)
2914         WARN("unexpected state: %x\n", *state);
2915
2916     *to_next = to;
2917     return CODECVT_ok;
2918 }
2919
2920 /* ?do_length@?$codecvt@GDH@std@@MBEHABHPBD1I@Z */
2921 /* ?do_length@?$codecvt@GDH@std@@MEBAHAEBHPEBD1_K@Z */
2922 /* ?do_length@?$codecvt@_WDH@std@@MBEHABHPBD1I@Z */
2923 /* ?do_length@?$codecvt@_WDH@std@@MEBAHAEBHPEBD1_K@Z */
2924 #define call_codecvt_wchar_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2925         int, (const codecvt_wchar*, const int*, const char*, const char*, MSVCP_size_t), \
2926         (this, state, from, from_end, max))
2927 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_length, 20)
2928 int __thiscall codecvt_wchar_do_length(const codecvt_wchar *this, const int *state,
2929         const char *from, const char *from_end, MSVCP_size_t max)
2930 {
2931     int tmp_state = *state, ret=0;
2932
2933     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
2934
2935     while(ret<max && from!=from_end) {
2936         switch(_Mbrtowc(NULL, from, from_end-from, &tmp_state, &this->cvt)) {
2937         case -2:
2938         case -1:
2939             return ret;
2940         case 2:
2941             from++;
2942             /* fall through */
2943         case 0:
2944         case 1:
2945             from++;
2946             ret++;
2947         }
2948     }
2949
2950     return ret;
2951 }
2952
2953 /* ?id@?$numpunct@D@std@@2V0locale@2@A */
2954 locale_id numpunct_char_id = {0};
2955
2956 /* ??_7?$numpunct@D@std@@6B@ */
2957 extern const vtable_ptr MSVCP_numpunct_char_vtable;
2958
2959 /* ?_Init@?$numpunct@D@std@@IAEXABV_Locinfo@2@_N@Z */
2960 /* ?_Init@?$numpunct@D@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2961 static void numpunct_char__Init(numpunct_char *this, const _Locinfo *locinfo, MSVCP_bool isdef)
2962 {
2963     int len;
2964
2965     TRACE("(%p %p %d)\n", this, locinfo, isdef);
2966
2967     len = strlen(_Locinfo__Getfalse(locinfo))+1;
2968     this->false_name = MSVCRT_operator_new(len);
2969     if(this->false_name)
2970         memcpy((char*)this->false_name, _Locinfo__Getfalse(locinfo), len);
2971
2972     len = strlen(_Locinfo__Gettrue(locinfo))+1;
2973     this->true_name = MSVCRT_operator_new(len);
2974     if(this->true_name)
2975         memcpy((char*)this->true_name, _Locinfo__Gettrue(locinfo), len);
2976
2977     if(isdef) {
2978         this->grouping = MSVCRT_operator_new(1);
2979         if(this->grouping)
2980             *(char*)this->grouping = 0;
2981
2982         this->dp = '.';
2983         this->sep = ',';
2984     } else {
2985         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
2986
2987         len = strlen(lc->grouping)+1;
2988         this->grouping = MSVCRT_operator_new(len);
2989         if(this->grouping)
2990             memcpy((char*)this->grouping, lc->grouping, len);
2991
2992         this->dp = lc->decimal_point[0];
2993         this->sep = lc->thousands_sep[0];
2994     }
2995
2996     if(!this->false_name || !this->true_name || !this->grouping) {
2997         MSVCRT_operator_delete((char*)this->grouping);
2998         MSVCRT_operator_delete((char*)this->false_name);
2999         MSVCRT_operator_delete((char*)this->true_name);
3000
3001         ERR("Out of memory\n");
3002         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3003     }
3004 }
3005
3006 /* ?_Tidy@?$numpunct@D@std@@AAEXXZ */
3007 /* ?_Tidy@?$numpunct@D@std@@AEAAXXZ */
3008 static void numpunct_char__Tidy(numpunct_char *this)
3009 {
3010     TRACE("(%p)\n", this);
3011
3012     MSVCRT_operator_delete((char*)this->grouping);
3013     MSVCRT_operator_delete((char*)this->false_name);
3014     MSVCRT_operator_delete((char*)this->true_name);
3015 }
3016
3017 /* ??0?$numpunct@D@std@@QAE@ABV_Locinfo@1@I_N@Z */
3018 /* ??0?$numpunct@D@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3019 static numpunct_char* numpunct_char_ctor_locinfo(numpunct_char *this,
3020         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3021 {
3022     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3023     locale_facet_ctor_refs(&this->facet, refs);
3024     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3025     numpunct_char__Init(this, locinfo, usedef);
3026     return this;
3027 }
3028
3029 /* ??0?$numpunct@D@std@@IAE@PBDI_N@Z */
3030 /* ??0?$numpunct@D@std@@IEAA@PEBD_K_N@Z */
3031 static numpunct_char* numpunct_char_ctor_name(numpunct_char *this,
3032         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3033 {
3034     _Locinfo locinfo;
3035
3036     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3037     locale_facet_ctor_refs(&this->facet, refs);
3038     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3039
3040     _Locinfo_ctor_cstr(&locinfo, name);
3041     numpunct_char__Init(this, &locinfo, usedef);
3042     _Locinfo_dtor(&locinfo);
3043     return this;
3044 }
3045
3046 /* ??0?$numpunct@D@std@@QAE@I@Z */
3047 /* ??0?$numpunct@D@std@@QEAA@_K@Z */
3048 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_refs, 8)
3049 numpunct_char* __thiscall numpunct_char_ctor_refs(numpunct_char *this, MSVCP_size_t refs)
3050 {
3051     TRACE("(%p %lu)\n", this, refs);
3052     return numpunct_char_ctor_name(this, "C", refs, FALSE);
3053 }
3054
3055 /* ??_F?$numpunct@D@std@@QAEXXZ */
3056 /* ??_F?$numpunct@D@std@@QEAAXXZ */
3057 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor, 4)
3058 numpunct_char* __thiscall numpunct_char_ctor(numpunct_char *this)
3059 {
3060     return numpunct_char_ctor_refs(this, 0);
3061 }
3062
3063 /* ??1?$numpunct@D@std@@UAE@XZ */
3064 /* ??1?$numpunct@D@std@@UEAA@XZ */
3065 DEFINE_THISCALL_WRAPPER(numpunct_char_dtor, 4)
3066 void __thiscall numpunct_char_dtor(numpunct_char *this)
3067 {
3068     TRACE("(%p)\n", this);
3069     numpunct_char__Tidy(this);
3070 }
3071
3072 DEFINE_THISCALL_WRAPPER(numpunct_char_vector_dtor, 8)
3073 numpunct_char* __thiscall numpunct_char_vector_dtor(numpunct_char *this, unsigned int flags)
3074 {
3075     TRACE("(%p %x)\n", this, flags);
3076     if(flags & 2) {
3077         /* we have an array, with the number of elements stored before the first object */
3078         INT_PTR i, *ptr = (INT_PTR *)this-1;
3079
3080         for(i=*ptr-1; i>=0; i--)
3081             numpunct_char_dtor(this+i);
3082         MSVCRT_operator_delete(ptr);
3083     } else {
3084         numpunct_char_dtor(this);
3085         if(flags & 1)
3086             MSVCRT_operator_delete(this);
3087     }
3088
3089     return this;
3090 }
3091
3092 /* ?_Getcat@?$numpunct@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3093 /* ?_Getcat@?$numpunct@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3094 static MSVCP_size_t numpunct_char__Getcat(const locale_facet **facet, const locale *loc)
3095 {
3096     TRACE("(%p %p)\n", facet, loc);
3097
3098     if(facet && !*facet) {
3099         *facet = MSVCRT_operator_new(sizeof(numpunct_char));
3100         if(!*facet) {
3101             ERR("Out of memory\n");
3102             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3103             return 0;
3104         }
3105         numpunct_char_ctor_name((numpunct_char*)*facet,
3106                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3107     }
3108
3109     return LC_NUMERIC;
3110 }
3111
3112 static numpunct_char* numpunct_char_use_facet(const locale *loc)
3113 {
3114     static numpunct_char *obj = NULL;
3115
3116     _Lockit lock;
3117     const locale_facet *fac;
3118
3119     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3120     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_char_id));
3121     if(fac) {
3122         _Lockit_dtor(&lock);
3123         return (numpunct_char*)fac;
3124     }
3125
3126     if(obj) {
3127         _Lockit_dtor(&lock);
3128         return obj;
3129     }
3130
3131     numpunct_char__Getcat(&fac, loc);
3132     obj = (numpunct_char*)fac;
3133     locale_facet__Incref(&obj->facet);
3134     locale_facet_register(&obj->facet);
3135     _Lockit_dtor(&lock);
3136
3137     return obj;
3138 }
3139
3140 /* ?do_decimal_point@?$numpunct@D@std@@MBEDXZ */
3141 /* ?do_decimal_point@?$numpunct@D@std@@MEBADXZ */
3142 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
3143 #define call_numpunct_char_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3144         char, (const numpunct_char *this), (this))
3145 char __thiscall numpunct_char_do_decimal_point(const numpunct_char *this)
3146 {
3147     TRACE("(%p)\n", this);
3148     return this->dp;
3149 }
3150
3151 /* ?decimal_point@?$numpunct@D@std@@QBEDXZ */
3152 /* ?decimal_point@?$numpunct@D@std@@QEBADXZ */
3153 DEFINE_THISCALL_WRAPPER(numpunct_char_decimal_point, 4)
3154 char __thiscall numpunct_char_decimal_point(const numpunct_char *this)
3155 {
3156     TRACE("(%p)\n", this);
3157     return call_numpunct_char_do_decimal_point(this);
3158 }
3159
3160 /* ?do_thousands_sep@?$numpunct@D@std@@MBEDXZ */
3161 /* ?do_thousands_sep@?$numpunct@D@std@@MEBADXZ */
3162 DEFINE_THISCALL_WRAPPER(numpunct_char_do_thousands_sep, 4)
3163 #define call_numpunct_char_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3164         char, (const numpunct_char*), (this))
3165 char __thiscall numpunct_char_do_thousands_sep(const numpunct_char *this)
3166 {
3167     TRACE("(%p)\n", this);
3168     return this->sep;
3169 }
3170
3171 /* ?thousands_sep@?$numpunct@D@std@@QBEDXZ */
3172 /* ?thousands_sep@?$numpunct@D@std@@QEBADXZ */
3173 DEFINE_THISCALL_WRAPPER(numpunct_char_thousands_sep, 4)
3174 char __thiscall numpunct_char_thousands_sep(const numpunct_char *this)
3175 {
3176     TRACE("(%p)\n", this);
3177     return call_numpunct_char_do_thousands_sep(this);
3178 }
3179
3180 /* ?do_grouping@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3181 /* ?do_grouping@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3182 DEFINE_THISCALL_WRAPPER(numpunct_char_do_grouping, 8)
3183 #define call_numpunct_char_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3184         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3185 basic_string_char* __thiscall numpunct_char_do_grouping(
3186         const numpunct_char *this, basic_string_char *ret)
3187 {
3188     TRACE("(%p)\n", this);
3189     return basic_string_char_ctor_cstr(ret, this->grouping);
3190 }
3191
3192 /* ?grouping@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3193 /* ?grouping@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3194 DEFINE_THISCALL_WRAPPER(numpunct_char_grouping, 8)
3195 basic_string_char* __thiscall numpunct_char_grouping(const numpunct_char *this, basic_string_char *ret)
3196 {
3197     TRACE("(%p)\n", this);
3198     return call_numpunct_char_do_grouping(this, ret);
3199 }
3200
3201 /* ?do_falsename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3202 /* ?do_falsename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3203 DEFINE_THISCALL_WRAPPER(numpunct_char_do_falsename, 8)
3204 #define call_numpunct_char_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3205         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3206 basic_string_char* __thiscall numpunct_char_do_falsename(
3207         const numpunct_char *this, basic_string_char *ret)
3208 {
3209     TRACE("(%p)\n", this);
3210     return basic_string_char_ctor_cstr(ret, this->false_name);
3211 }
3212
3213 /* ?falsename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3214 /* ?falsename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3215 DEFINE_THISCALL_WRAPPER(numpunct_char_falsename, 8)
3216 basic_string_char* __thiscall numpunct_char_falsename(const numpunct_char *this, basic_string_char *ret)
3217 {
3218     TRACE("(%p)\n", this);
3219     return call_numpunct_char_do_falsename(this, ret);
3220 }
3221
3222 /* ?do_truename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3223 /* ?do_truename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3224 DEFINE_THISCALL_WRAPPER(numpunct_char_do_truename, 8)
3225 #define call_numpunct_char_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3226         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3227 basic_string_char* __thiscall numpunct_char_do_truename(
3228         const numpunct_char *this, basic_string_char *ret)
3229 {
3230     TRACE("(%p)\n", this);
3231     return basic_string_char_ctor_cstr(ret, this->true_name);
3232 }
3233
3234 /* ?truename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3235 /* ?truename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3236 DEFINE_THISCALL_WRAPPER(numpunct_char_truename, 8)
3237 basic_string_char* __thiscall numpunct_char_truename(const numpunct_char *this, basic_string_char *ret)
3238 {
3239     TRACE("(%p)\n", this);
3240     return call_numpunct_char_do_truename(this, ret);
3241 }
3242
3243 /* ?id@?$numpunct@_W@std@@2V0locale@2@A */
3244 static locale_id numpunct_wchar_id = {0};
3245 /* ?id@?$numpunct@G@std@@2V0locale@2@A */
3246 locale_id numpunct_short_id = {0};
3247
3248 /* ??_7?$numpunct@_W@std@@6B@ */
3249 extern const vtable_ptr MSVCP_numpunct_wchar_vtable;
3250 /* ??_7?$numpunct@G@std@@6B@ */
3251 extern const vtable_ptr MSVCP_numpunct_short_vtable;
3252
3253 /* ?_Init@?$numpunct@_W@std@@IAEXABV_Locinfo@2@_N@Z */
3254 /* ?_Init@?$numpunct@_W@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3255 /* ?_Init@?$numpunct@G@std@@IAEXABV_Locinfo@2@_N@Z */
3256 /* ?_Init@?$numpunct@G@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3257 static void numpunct_wchar__Init(numpunct_wchar *this,
3258         const _Locinfo *locinfo, MSVCP_bool isdef)
3259 {
3260     const char *to_convert;
3261     _Cvtvec cvt;
3262     int len;
3263
3264     TRACE("(%p %p %d)\n", this, locinfo, isdef);
3265
3266     _Locinfo__Getcvt(locinfo, &cvt);
3267
3268     to_convert = _Locinfo__Getfalse(locinfo);
3269     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3270     this->false_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3271     if(this->false_name)
3272         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3273                 (wchar_t*)this->false_name, len);
3274
3275     to_convert = _Locinfo__Gettrue(locinfo);
3276     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3277     this->true_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3278     if(this->true_name)
3279         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3280                 (wchar_t*)this->true_name, len);
3281
3282     if(isdef) {
3283         this->grouping = MSVCRT_operator_new(1);
3284         if(this->grouping)
3285             *(char*)this->grouping = 0;
3286
3287         this->dp = '.';
3288         this->sep = ',';
3289     } else {
3290         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3291
3292         len = strlen(lc->grouping)+1;
3293         this->grouping = MSVCRT_operator_new(len);
3294         if(this->grouping)
3295             memcpy((char*)this->grouping, lc->grouping, len);
3296
3297         this->dp = lc->decimal_point[0];
3298         this->sep = lc->thousands_sep[0];
3299     }
3300
3301     if(!this->false_name || !this->true_name || !this->grouping) {
3302         MSVCRT_operator_delete((char*)this->grouping);
3303         MSVCRT_operator_delete((wchar_t*)this->false_name);
3304         MSVCRT_operator_delete((wchar_t*)this->true_name);
3305
3306         ERR("Out of memory\n");
3307         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3308     }
3309 }
3310
3311 /* ?_Tidy@?$numpunct@_W@std@@AAEXXZ */
3312 /* ?_Tidy@?$numpunct@_W@std@@AEAAXXZ */
3313 /* ?_Tidy@?$numpunct@G@std@@AAEXXZ */
3314 /* ?_Tidy@?$numpunct@G@std@@AEAAXXZ */
3315 static void numpunct_wchar__Tidy(numpunct_wchar *this)
3316 {
3317     TRACE("(%p)\n", this);
3318
3319     MSVCRT_operator_delete((char*)this->grouping);
3320     MSVCRT_operator_delete((wchar_t*)this->false_name);
3321     MSVCRT_operator_delete((wchar_t*)this->true_name);
3322 }
3323
3324 /* ??0?$numpunct@_W@std@@QAE@ABV_Locinfo@1@I_N@Z */
3325 /* ??0?$numpunct@_W@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3326 static numpunct_wchar* numpunct_wchar_ctor_locinfo(numpunct_wchar *this,
3327         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3328 {
3329     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3330     locale_facet_ctor_refs(&this->facet, refs);
3331     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3332     numpunct_wchar__Init(this, locinfo, usedef);
3333     return this;
3334 }
3335
3336 /* ??0?$numpunct@G@std@@QAE@ABV_Locinfo@1@I_N@Z */
3337 /* ??0?$numpunct@G@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3338 static numpunct_wchar* numpunct_short_ctor_locinfo(numpunct_wchar *this,
3339         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3340 {
3341     numpunct_wchar_ctor_locinfo(this, locinfo, refs, usedef);
3342     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3343     return this;
3344 }
3345
3346 /* ??0?$numpunct@_W@std@@IAE@PBDI_N@Z */
3347 /* ??0?$numpunct@_W@std@@IEAA@PEBD_K_N@Z */
3348 static numpunct_wchar* numpunct_wchar_ctor_name(numpunct_wchar *this,
3349         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3350 {
3351     _Locinfo locinfo;
3352
3353     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3354     locale_facet_ctor_refs(&this->facet, refs);
3355     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3356
3357     _Locinfo_ctor_cstr(&locinfo, name);
3358     numpunct_wchar__Init(this, &locinfo, usedef);
3359     _Locinfo_dtor(&locinfo);
3360     return this;
3361 }
3362
3363 /* ??0?$numpunct@G@std@@IAE@PBDI_N@Z */
3364 /* ??0?$numpunct@G@std@@IEAA@PEBD_K_N@Z */
3365 static numpunct_wchar* numpunct_short_ctor_name(numpunct_wchar *this,
3366         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3367 {
3368     numpunct_wchar_ctor_name(this, name, refs, usedef);
3369     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3370     return this;
3371 }
3372
3373 /* ??0?$numpunct@_W@std@@QAE@I@Z */
3374 /* ??0?$numpunct@_W@std@@QEAA@_K@Z */
3375 static numpunct_wchar* numpunct_wchar_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3376 {
3377     TRACE("(%p %lu)\n", this, refs);
3378     return numpunct_wchar_ctor_name(this, "C", refs, FALSE);
3379 }
3380
3381 /* ??0?$numpunct@G@std@@QAE@I@Z */
3382 /* ??0?$numpunct@G@std@@QEAA@_K@Z */
3383 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_refs, 8)
3384 numpunct_wchar* __thiscall numpunct_short_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3385 {
3386     numpunct_wchar_ctor_refs(this, refs);
3387     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3388     return this;
3389 }
3390
3391 /* ??_F?$numpunct@G@std@@QAEXXZ */
3392 /* ??_F?$numpunct@G@std@@QEAAXXZ */
3393 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor, 4)
3394 numpunct_wchar* __thiscall numpunct_short_ctor(numpunct_wchar *this)
3395 {
3396     return numpunct_short_ctor_refs(this, 0);
3397 }
3398
3399 /* ??1?$numpunct@G@std@@UAE@XZ */
3400 /* ??1?$numpunct@G@std@@UEAA@XZ */
3401 DEFINE_THISCALL_WRAPPER(numpunct_wchar_dtor, 4)
3402 void __thiscall numpunct_wchar_dtor(numpunct_wchar *this)
3403 {
3404     TRACE("(%p)\n", this);
3405     numpunct_wchar__Tidy(this);
3406 }
3407
3408 DEFINE_THISCALL_WRAPPER(numpunct_wchar_vector_dtor, 8)
3409 numpunct_wchar* __thiscall numpunct_wchar_vector_dtor(numpunct_wchar *this, unsigned int flags)
3410 {
3411     TRACE("(%p %x)\n", this, flags);
3412     if(flags & 2) {
3413         /* we have an array, with the number of elements stored before the first object */
3414         INT_PTR i, *ptr = (INT_PTR *)this-1;
3415
3416         for(i=*ptr-1; i>=0; i--)
3417             numpunct_wchar_dtor(this+i);
3418         MSVCRT_operator_delete(ptr);
3419     } else {
3420         numpunct_wchar_dtor(this);
3421         if(flags & 1)
3422             MSVCRT_operator_delete(this);
3423     }
3424
3425     return this;
3426 }
3427
3428 /* ?_Getcat@?$numpunct@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3429 /* ?_Getcat@?$numpunct@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3430 static MSVCP_size_t numpunct_wchar__Getcat(const locale_facet **facet, const locale *loc)
3431 {
3432     TRACE("(%p %p)\n", facet, loc);
3433
3434     if(facet && !*facet) {
3435         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3436         if(!*facet) {
3437             ERR("Out of memory\n");
3438             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3439             return 0;
3440         }
3441         numpunct_wchar_ctor_name((numpunct_wchar*)*facet,
3442                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3443     }
3444
3445     return LC_NUMERIC;
3446 }
3447
3448 static numpunct_wchar* numpunct_wchar_use_facet(const locale *loc)
3449 {
3450     static numpunct_wchar *obj = NULL;
3451
3452     _Lockit lock;
3453     const locale_facet *fac;
3454
3455     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3456     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_wchar_id));
3457     if(fac) {
3458         _Lockit_dtor(&lock);
3459         return (numpunct_wchar*)fac;
3460     }
3461
3462     if(obj) {
3463         _Lockit_dtor(&lock);
3464         return obj;
3465     }
3466
3467     numpunct_wchar__Getcat(&fac, loc);
3468     obj = (numpunct_wchar*)fac;
3469     locale_facet__Incref(&obj->facet);
3470     locale_facet_register(&obj->facet);
3471     _Lockit_dtor(&lock);
3472
3473     return obj;
3474 }
3475
3476 /* ?_Getcat@?$numpunct@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3477 /* ?_Getcat@?$numpunct@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3478 static MSVCP_size_t numpunct_short__Getcat(const locale_facet **facet, const locale *loc)
3479 {
3480     TRACE("(%p %p)\n", facet, loc);
3481
3482     if(facet && !*facet) {
3483         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3484         if(!*facet) {
3485             ERR("Out of memory\n");
3486             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3487             return 0;
3488         }
3489         numpunct_short_ctor_name((numpunct_wchar*)*facet,
3490                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3491     }
3492
3493     return LC_NUMERIC;
3494 }
3495
3496 static numpunct_wchar* numpunct_short_use_facet(const locale *loc)
3497 {
3498     static numpunct_wchar *obj = NULL;
3499
3500     _Lockit lock;
3501     const locale_facet *fac;
3502
3503     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3504     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_short_id));
3505     if(fac) {
3506         _Lockit_dtor(&lock);
3507         return (numpunct_wchar*)fac;
3508     }
3509
3510     if(obj) {
3511         _Lockit_dtor(&lock);
3512         return obj;
3513     }
3514
3515     numpunct_short__Getcat(&fac, loc);
3516     obj = (numpunct_wchar*)fac;
3517     locale_facet__Incref(&obj->facet);
3518     locale_facet_register(&obj->facet);
3519     _Lockit_dtor(&lock);
3520
3521     return obj;
3522 }
3523
3524 /* ?do_decimal_point@?$numpunct@_W@std@@MBE_WXZ */
3525 /* ?do_decimal_point@?$numpunct@_W@std@@MEBA_WXZ */
3526 /* ?do_decimal_point@?$numpunct@G@std@@MBEGXZ */
3527 /* ?do_decimal_point@?$numpunct@G@std@@MEBAGXZ */
3528 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_decimal_point, 4)
3529 #define call_numpunct_wchar_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3530         wchar_t, (const numpunct_wchar *this), (this))
3531 wchar_t __thiscall numpunct_wchar_do_decimal_point(const numpunct_wchar *this)
3532 {
3533     TRACE("(%p)\n", this);
3534     return this->dp;
3535 }
3536
3537 /* ?decimal_point@?$numpunct@_W@std@@QBE_WXZ */
3538 /* ?decimal_point@?$numpunct@_W@std@@QEBA_WXZ */
3539 /* ?decimal_point@?$numpunct@G@std@@QBEGXZ */
3540 /* ?decimal_point@?$numpunct@G@std@@QEBAGXZ */
3541 DEFINE_THISCALL_WRAPPER(numpunct_wchar_decimal_point, 4)
3542 wchar_t __thiscall numpunct_wchar_decimal_point(const numpunct_wchar *this)
3543 {
3544     TRACE("(%p)\n", this);
3545     return call_numpunct_wchar_do_decimal_point(this);
3546 }
3547
3548 /* ?do_thousands_sep@?$numpunct@_W@std@@MBE_WXZ */
3549 /* ?do_thousands_sep@?$numpunct@_W@std@@MEBA_WXZ */
3550 /* ?do_thousands_sep@?$numpunct@G@std@@MBEGXZ */
3551 /* ?do_thousands_sep@?$numpunct@G@std@@MEBAGXZ */
3552 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_thousands_sep, 4)
3553 #define call_numpunct_wchar_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3554         wchar_t, (const numpunct_wchar *this), (this))
3555 wchar_t __thiscall numpunct_wchar_do_thousands_sep(const numpunct_wchar *this)
3556 {
3557     TRACE("(%p)\n", this);
3558     return this->sep;
3559 }
3560
3561 /* ?thousands_sep@?$numpunct@_W@std@@QBE_WXZ */
3562 /* ?thousands_sep@?$numpunct@_W@std@@QEBA_WXZ */
3563 /* ?thousands_sep@?$numpunct@G@std@@QBEGXZ */
3564 /* ?thousands_sep@?$numpunct@G@std@@QEBAGXZ */
3565 DEFINE_THISCALL_WRAPPER(numpunct_wchar_thousands_sep, 4)
3566 wchar_t __thiscall numpunct_wchar_thousands_sep(const numpunct_wchar *this)
3567 {
3568     TRACE("(%p)\n", this);
3569     return call_numpunct_wchar_do_thousands_sep(this);
3570 }
3571
3572 /* ?do_grouping@?$numpunct@_W@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3573 /* ?do_grouping@?$numpunct@_W@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3574 /* ?do_grouping@?$numpunct@G@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3575 /* ?do_grouping@?$numpunct@G@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3576 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_grouping, 8)
3577 #define call_numpunct_wchar_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3578         basic_string_char*, (const numpunct_wchar*, basic_string_char*), (this, ret))
3579 basic_string_char* __thiscall numpunct_wchar_do_grouping(const numpunct_wchar *this, basic_string_char *ret)
3580 {
3581     TRACE("(%p)\n", this);
3582     return basic_string_char_ctor_cstr(ret, this->grouping);
3583 }
3584
3585 /* ?grouping@?$numpunct@_W@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3586 /* ?grouping@?$numpunct@_W@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3587 /* ?grouping@?$numpunct@G@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3588 /* ?grouping@?$numpunct@G@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3589 DEFINE_THISCALL_WRAPPER(numpunct_wchar_grouping, 8)
3590 basic_string_char* __thiscall numpunct_wchar_grouping(const numpunct_wchar *this, basic_string_char *ret)
3591 {
3592     TRACE("(%p)\n", this);
3593     return call_numpunct_wchar_do_grouping(this, ret);
3594 }
3595
3596 /* ?do_falsename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3597 /* ?do_falsename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3598 /* ?do_falsename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3599 /* ?do_falsename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3600 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_falsename, 8)
3601 #define call_numpunct_wchar_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3602         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3603 basic_string_wchar* __thiscall numpunct_wchar_do_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3604 {
3605     TRACE("(%p)\n", this);
3606     return basic_string_wchar_ctor_cstr(ret, this->false_name);
3607 }
3608
3609 /* ?falsename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3610 /* ?falsename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3611 /* ?falsename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3612 /* ?falsename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3613 DEFINE_THISCALL_WRAPPER(numpunct_wchar_falsename, 8)
3614 basic_string_wchar* __thiscall numpunct_wchar_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3615 {
3616     TRACE("(%p)\n", this);
3617     return call_numpunct_wchar_do_falsename(this, ret);
3618 }
3619
3620 /* ?do_truename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3621 /* ?do_truename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3622 /* ?do_truename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3623 /* ?do_truename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3624 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_truename, 8)
3625 #define call_numpunct_wchar_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3626         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3627 basic_string_wchar* __thiscall numpunct_wchar_do_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3628 {
3629     TRACE("(%p)\n", this);
3630     return basic_string_wchar_ctor_cstr(ret, this->true_name);
3631 }
3632
3633 /* ?truename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3634 /* ?truename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3635 /* ?truename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3636 /* ?truename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3637 DEFINE_THISCALL_WRAPPER(numpunct_wchar_truename, 8)
3638 basic_string_wchar* __thiscall numpunct_wchar_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3639 {
3640     TRACE("(%p)\n", this);
3641     return call_numpunct_wchar_do_truename(this, ret);
3642 }
3643
3644 double __cdecl _Stod(const char *buf, char **buf_end, LONG exp)
3645 {
3646     double ret = strtod(buf, buf_end);
3647
3648     if(exp)
3649         ret *= pow(10, exp);
3650     return ret;
3651 }
3652
3653 static double _Stodx(const char *buf, char **buf_end, LONG exp, int *err)
3654 {
3655     double ret;
3656
3657     *err = *_errno();
3658     *_errno() = 0;
3659     ret = _Stod(buf, buf_end, exp);
3660     if(*_errno()) {
3661         *err = *_errno();
3662     }else {
3663         *_errno() = *err;
3664         *err = 0;
3665     }
3666     return ret;
3667 }
3668
3669 float __cdecl _Stof(const char *buf, char **buf_end, LONG exp)
3670 {
3671     return _Stod(buf, buf_end, exp);
3672 }
3673
3674 static float _Stofx(const char *buf, char **buf_end, LONG exp, int *err)
3675 {
3676     return _Stodx(buf, buf_end, exp, err);
3677 }
3678
3679 static __int64 _Stollx(const char *buf, char **buf_end, int base, int *err)
3680 {
3681     __int64 ret;
3682
3683     *err = *_errno();
3684     *_errno() = 0;
3685     ret = _strtoi64(buf, buf_end, base);
3686     if(*_errno()) {
3687         *err = *_errno();
3688     }else {
3689         *_errno() = *err;
3690         *err = 0;
3691     }
3692     return ret;
3693 }
3694
3695 static LONG _Stolx(const char *buf, char **buf_end, int base, int *err)
3696 {
3697     __int64 i = _Stollx(buf, buf_end, base, err);
3698     if(!*err && i!=(__int64)((LONG)i))
3699         *err = ERANGE;
3700     return i;
3701 }
3702
3703 static unsigned __int64 _Stoullx(const char *buf, char **buf_end, int base, int *err)
3704 {
3705     unsigned __int64 ret;
3706
3707     *err = *_errno();
3708     *_errno() = 0;
3709     ret = _strtoui64(buf, buf_end, base);
3710     if(*_errno()) {
3711         *err = *_errno();
3712     }else {
3713         *_errno() = *err;
3714         *err = 0;
3715     }
3716     return ret;
3717 }
3718
3719 static ULONG _Stoulx(const char *buf, char **buf_end, int base, int *err)
3720 {
3721     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, err);
3722     if(!*err && i!=(unsigned __int64)((ULONG)i))
3723         *err = ERANGE;
3724     return buf[0]=='-' ? -i : i;
3725 }
3726
3727 /* ?id@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
3728 static locale_id num_get_wchar_id = {0};
3729 /* ?id@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
3730 locale_id num_get_short_id = {0};
3731
3732 /* ??_7?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
3733 extern const vtable_ptr MSVCP_num_get_wchar_vtable;
3734 /* ??_7?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
3735 extern const vtable_ptr MSVCP_num_get_short_vtable;
3736
3737 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3738 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3739 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3740 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3741 DEFINE_THISCALL_WRAPPER(num_get_wchar__Init, 8)
3742 void __thiscall num_get_wchar__Init(num_get *this, const _Locinfo *locinfo)
3743 {
3744     TRACE("(%p %p)\n", this, locinfo);
3745     _Locinfo__Getcvt(locinfo, &this->cvt);
3746 }
3747
3748 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3749 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3750 static num_get* num_get_wchar_ctor_locinfo(num_get *this,
3751         const _Locinfo *locinfo, MSVCP_size_t refs)
3752 {
3753     TRACE("(%p %p %lu)\n", this, locinfo, refs);
3754
3755     locale_facet_ctor_refs(&this->facet, refs);
3756     this->facet.vtable = &MSVCP_num_get_wchar_vtable;
3757
3758     num_get_wchar__Init(this, locinfo);
3759     return this;
3760 }
3761
3762 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3763 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3764 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_locinfo, 12)
3765 num_get* __thiscall num_get_short_ctor_locinfo(num_get *this,
3766         const _Locinfo *locinfo, MSVCP_size_t refs)
3767 {
3768     num_get_wchar_ctor_locinfo(this, locinfo, refs);
3769     this->facet.vtable = &MSVCP_num_get_short_vtable;
3770     return this;
3771 }
3772
3773 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
3774 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
3775 static num_get* num_get_wchar_ctor_refs(num_get *this, MSVCP_size_t refs)
3776 {
3777     _Locinfo locinfo;
3778
3779     TRACE("(%p %lu)\n", this, refs);
3780
3781     _Locinfo_ctor(&locinfo);
3782     num_get_wchar_ctor_locinfo(this, &locinfo, refs);
3783     _Locinfo_dtor(&locinfo);
3784     return this;
3785 }
3786
3787 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
3788 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
3789 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_refs, 8)
3790 num_get* __thiscall num_get_short_ctor_refs(num_get *this, MSVCP_size_t refs)
3791 {
3792     num_get_wchar_ctor_refs(this, refs);
3793     this->facet.vtable = &MSVCP_num_get_short_vtable;
3794     return this;
3795 }
3796
3797 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
3798 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
3799 DEFINE_THISCALL_WRAPPER(num_get_short_ctor, 4)
3800 num_get* __thiscall num_get_short_ctor(num_get *this)
3801 {
3802     return num_get_short_ctor_refs(this, 0);
3803 }
3804
3805 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@UAE@XZ */
3806 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@UEAA@XZ */
3807 DEFINE_THISCALL_WRAPPER(num_get_wchar_dtor, 4)
3808 void __thiscall num_get_wchar_dtor(num_get *this)
3809 {
3810     TRACE("(%p)\n", this);
3811     locale_facet_dtor(&this->facet);
3812 }
3813
3814 DEFINE_THISCALL_WRAPPER(num_get_wchar_vector_dtor, 8)
3815 num_get* __thiscall num_get_wchar_vector_dtor(num_get *this, unsigned int flags)
3816 {
3817     TRACE("(%p %x)\n", this, flags);
3818     if(flags & 2) {
3819         /* we have an array, with the number of elements stored before the first object */
3820         INT_PTR i, *ptr = (INT_PTR *)this-1;
3821
3822         for(i=*ptr-1; i>=0; i--)
3823             num_get_wchar_dtor(this+i);
3824         MSVCRT_operator_delete(ptr);
3825     } else {
3826         num_get_wchar_dtor(this);
3827         if(flags & 1)
3828             MSVCRT_operator_delete(this);
3829     }
3830
3831     return this;
3832 }
3833
3834 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3835 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3836 static MSVCP_size_t num_get_wchar__Getcat(const locale_facet **facet, const locale *loc)
3837 {
3838     TRACE("(%p %p)\n", facet, loc);
3839
3840     if(facet && !*facet) {
3841         _Locinfo locinfo;
3842
3843         *facet = MSVCRT_operator_new(sizeof(num_get));
3844         if(!*facet) {
3845             ERR("Out of memory\n");
3846             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3847             return 0;
3848         }
3849
3850         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
3851         num_get_wchar_ctor_locinfo((num_get*)*facet, &locinfo, 0);
3852         _Locinfo_dtor(&locinfo);
3853     }
3854
3855     return LC_NUMERIC;
3856 }
3857
3858 static num_get* num_get_wchar_use_facet(const locale *loc)
3859 {
3860         static num_get *obj = NULL;
3861
3862         _Lockit lock;
3863         const locale_facet *fac;
3864
3865         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3866         fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_wchar_id));
3867         if(fac) {
3868             _Lockit_dtor(&lock);
3869             return (num_get*)fac;
3870         }
3871
3872         if(obj) {
3873             _Lockit_dtor(&lock);
3874             return obj;
3875         }
3876
3877         num_get_wchar__Getcat(&fac, loc);
3878         obj = (num_get*)fac;
3879         locale_facet__Incref(&obj->facet);
3880         locale_facet_register(&obj->facet);
3881         _Lockit_dtor(&lock);
3882
3883         return obj;
3884 }
3885
3886 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3887 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3888 static MSVCP_size_t num_get_short__Getcat(const locale_facet **facet, const locale *loc)
3889 {
3890     if(facet && !*facet) {
3891         num_get_wchar__Getcat(facet, loc);
3892         (*(locale_facet**)facet)->vtable = &MSVCP_num_get_short_vtable;
3893     }
3894
3895     return LC_NUMERIC;
3896 }
3897
3898 num_get* num_get_short_use_facet(const locale *loc)
3899 {
3900     static num_get *obj = NULL;
3901
3902     _Lockit lock;
3903     const locale_facet *fac;
3904
3905     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3906     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_short_id));
3907     if(fac) {
3908         _Lockit_dtor(&lock);
3909         return (num_get*)fac;
3910     }
3911
3912     if(obj) {
3913         _Lockit_dtor(&lock);
3914         return obj;
3915     }
3916
3917     num_get_short__Getcat(&fac, loc);
3918     obj = (num_get*)fac;
3919     locale_facet__Incref(&obj->facet);
3920     locale_facet_register(&obj->facet);
3921     _Lockit_dtor(&lock);
3922
3923     return obj;
3924 }
3925
3926 static inline wchar_t mb_to_wc(char ch, const _Cvtvec *cvt)
3927 {
3928     int state = 0;
3929     wchar_t ret;
3930
3931     return _Mbrtowc(&ret, &ch, 1, &state, cvt) == 1 ? ret : 0;
3932 }
3933
3934 static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
3935         istreambuf_iterator_wchar *last, const locale *loc, numpunct_wchar *numpunct)
3936 {
3937     int i, exp = 0;
3938     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
3939     wchar_t digits[11], *digits_pos;
3940     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
3941
3942     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
3943
3944     for(i=0; i<10; i++)
3945         digits[i] = mb_to_wc('0'+i, &this->cvt);
3946     digits[10] = 0;
3947
3948     istreambuf_iterator_wchar_val(first);
3949     /* get sign */
3950     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
3951         *dest++ = '-';
3952         istreambuf_iterator_wchar_inc(first);
3953     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
3954         *dest++ = '+';
3955         istreambuf_iterator_wchar_inc(first);
3956     }
3957
3958     /* read numbers before decimal */
3959     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
3960         if(!(digits_pos = wcschr(digits, first->val))) {
3961             break;
3962         }else {
3963             got_digit = TRUE; /* found a digit, zero or non-zero */
3964             /* write digit to dest if not a leading zero (to not waste dest buffer) */
3965             if(!got_nonzero && first->val == digits[0])
3966                 continue;
3967             got_nonzero = TRUE;
3968             if(dest < num_end)
3969                 *dest++ = '0'+digits_pos-digits;
3970             else
3971                 exp++; /* too many digits, just multiply by 10 */
3972         }
3973     }
3974     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
3975     if(got_digit && !got_nonzero)
3976         *dest++ = '0';
3977
3978     /* get decimal, if any */
3979     if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
3980         if(dest < num_end)
3981             *dest++ = *localeconv()->decimal_point;
3982         istreambuf_iterator_wchar_inc(first);
3983     }
3984
3985     /* read non-grouped after decimal */
3986     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
3987         if(!(digits_pos = wcschr(digits, first->val)))
3988             break;
3989         else if(dest<num_end) {
3990             got_digit = TRUE;
3991             *dest++ = '0'+digits_pos-digits;
3992         }
3993     }
3994
3995     /* read exponent, if any */
3996     if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
3997         *dest++ = 'e';
3998         istreambuf_iterator_wchar_inc(first);
3999
4000         if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4001             *dest++ = '-';
4002             istreambuf_iterator_wchar_inc(first);
4003         }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4004             *dest++ = '+';
4005             istreambuf_iterator_wchar_inc(first);
4006         }
4007
4008         got_digit = got_nonzero = FALSE;
4009         error = TRUE;
4010         /* skip any leading zeroes */
4011         for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
4012             error = FALSE;
4013
4014         for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
4015             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
4016             error = FALSE;
4017             if(dest<exp_end)
4018                 *dest++ = '0'+digits_pos-digits;
4019         }
4020
4021         /* if just found zeroes for exponent, use that */
4022         if(got_digit && !got_nonzero)
4023         {
4024             error = FALSE;
4025             if(dest<exp_end)
4026                 *dest++ = '0';
4027         }
4028     }
4029
4030     if(error) {
4031         *dest_beg = '\0';
4032         return 0;
4033     }
4034     *dest++ = '\0';
4035     return exp;
4036 }
4037
4038 static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4039     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc, numpunct_wchar *numpunct)
4040 {
4041     wchar_t digits[23], *digits_pos;
4042     int i, basefield, base;
4043     char *dest_beg = dest, *dest_end = dest+24;
4044     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
4045
4046     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
4047
4048     for(i=0; i<10; i++)
4049         digits[i] = mb_to_wc('0'+i, &this->cvt);
4050     for(i=0; i<6; i++) {
4051         digits[10+i] = mb_to_wc('a'+i, &this->cvt);
4052         digits[16+i] = mb_to_wc('A'+i, &this->cvt);
4053     }
4054
4055     basefield = fmtflags & FMTFLAG_basefield;
4056     if(basefield == FMTFLAG_oct)
4057         base = 8;
4058     else if(basefield == FMTFLAG_hex)
4059         base = 22; /* equal to the size of digits buffer */
4060     else if(!basefield)
4061         base = 0;
4062     else
4063         base = 10;
4064
4065     istreambuf_iterator_wchar_val(first);
4066     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4067         *dest++ = '-';
4068         istreambuf_iterator_wchar_inc(first);
4069     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4070         *dest++ = '+';
4071         istreambuf_iterator_wchar_inc(first);
4072     }
4073
4074     if(first->strbuf && first->val==digits[0]) {
4075         found_zero = TRUE;
4076         istreambuf_iterator_wchar_inc(first);
4077         if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) {
4078             if(!base || base == 22) {
4079                 found_zero = FALSE;
4080                 istreambuf_iterator_wchar_inc(first);
4081                 base = 22;
4082             }else {
4083                 base = 10;
4084             }
4085         }else {
4086             error = FALSE;
4087             if(!base) base = 8;
4088         }
4089     }else {
4090         if(!base) base = 10;
4091     }
4092     digits[base] = 0;
4093
4094     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4095         if(!(digits_pos = wcschr(digits, first->val))) {
4096             break;
4097         }else {
4098             error = FALSE;
4099             if(dest_empty && first->val == digits[0]) {
4100                 found_zero = TRUE;
4101                 continue;
4102             }
4103             dest_empty = FALSE;
4104             /* skip digits that can't be copied to dest buffer, other
4105              * functions are responsible for detecting overflows */
4106             if(dest < dest_end)
4107                 *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits :
4108                         (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 :
4109                          'A'+digits_pos-digits-16));
4110         }
4111     }
4112
4113     if(error) {
4114         if (found_zero)
4115             *dest++ = '0';
4116         else
4117             dest = dest_beg;
4118     }else if(dest_empty)
4119         *dest++ = '0';
4120     *dest = '\0';
4121
4122     return (base==22 ? 16 : base);
4123 }
4124
4125 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HABVlocale@2@@Z */
4126 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HAEBVlocale@2@@Z */
4127 static int num_get_wchar__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4128     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4129 {
4130     return num_get__Getifld(this, dest, first, last,
4131             fmtflags, loc, numpunct_wchar_use_facet(loc));
4132 }
4133
4134 static istreambuf_iterator_wchar* num_get_do_get_void(const num_get *this,
4135         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4136         istreambuf_iterator_wchar last, ios_base *base, int *state,
4137         void **pval, numpunct_wchar *numpunct)
4138 {
4139     unsigned __int64 v;
4140     char tmp[25], *end;
4141     int err;
4142
4143     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4144
4145     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4146                 &last, FMTFLAG_hex, &base->loc, numpunct), &err);
4147     if(v!=(unsigned __int64)((INT_PTR)v))
4148         *state |= IOSTATE_failbit;
4149     else if(end!=tmp && !err)
4150         *pval = (void*)((INT_PTR)v);
4151     else
4152         *state |= IOSTATE_failbit;
4153
4154     if(!first.strbuf)
4155         *state |= IOSTATE_eofbit;
4156
4157     *ret = first;
4158     return ret;
4159 }
4160
4161 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4162 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4163 #define call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_wchar*, \
4164         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, void**), \
4165         (this, ret, first, last, base, state, pval))
4166 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_void,36)
4167 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4168     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4169 {
4170     return num_get_do_get_void(this, ret, first, last, base,
4171             state, pval, numpunct_wchar_use_facet(&base->loc));
4172 }
4173
4174 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4175 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4176 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_void,36)
4177 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4178     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4179 {
4180     return num_get_do_get_void(this, ret, first, last, base,
4181             state, pval, numpunct_short_use_facet(&base->loc));
4182 }
4183
4184 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4185 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4186 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4187 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4188 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_void,36)
4189 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4190     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4191 {
4192     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4193     return call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval);
4194 }
4195
4196 static istreambuf_iterator_wchar* num_get_do_get_double(const num_get *this,
4197         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4198         istreambuf_iterator_wchar last, ios_base *base, int *state,
4199         double *pval, numpunct_wchar *numpunct)
4200 {
4201     double v;
4202     char tmp[32], *end;
4203     int err;
4204
4205     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4206
4207     v = _Stodx(tmp, &end, num_get__Getffld(this, tmp, &first, &last, &base->loc, numpunct), &err);
4208     if(end!=tmp && !err)
4209         *pval = v;
4210     else
4211         *state |= IOSTATE_failbit;
4212
4213     if(!first.strbuf)
4214         *state |= IOSTATE_eofbit;
4215
4216     *ret = first;
4217     return ret;
4218 }
4219
4220 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4221 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4222 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4223 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4224 #define call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_wchar*, \
4225         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4226         (this, ret, first, last, base, state, pval))
4227 #define call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_wchar*, \
4228         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4229         (this, ret, first, last, base, state, pval))
4230 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_double,36)
4231 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4232     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4233 {
4234     return num_get_do_get_double(this, ret, first, last, base,
4235             state, pval, numpunct_wchar_use_facet(&base->loc));
4236 }
4237
4238 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4239 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4240 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4241 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4242 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_double,36)
4243 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4244     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4245 {
4246     return num_get_do_get_double(this, ret, first, last, base,
4247             state, pval, numpunct_short_use_facet(&base->loc));
4248 }
4249
4250 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4251 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4252 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4253 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4254 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ldouble,36)
4255 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ldouble(const num_get *this, istreambuf_iterator_wchar *ret,
4256         istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4257 {
4258     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4259     return call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval);
4260 }
4261
4262 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4263 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4264 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4265 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4266 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_double,36)
4267 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4268     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4269 {
4270     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4271     return call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval);
4272 }
4273
4274 static istreambuf_iterator_wchar* num_get_do_get_float(const num_get *this,
4275         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4276         istreambuf_iterator_wchar last, ios_base *base, int *state,
4277         float *pval, numpunct_wchar *numpunct)
4278 {
4279     float v;
4280     char tmp[32], *end;
4281     int err;
4282
4283     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4284
4285     v = _Stofx(tmp, &end, num_get__Getffld(this, tmp, &first,
4286                 &last, &base->loc, numpunct), &err);
4287     if(end!=tmp && !err)
4288         *pval = v;
4289     else
4290         *state |= IOSTATE_failbit;
4291
4292     if(!first.strbuf)
4293         *state |= IOSTATE_eofbit;
4294
4295     *ret = first;
4296     return ret;
4297 }
4298
4299 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4300 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4301 #define call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_wchar*, \
4302         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, float*), \
4303         (this, ret, first, last, base, state, pval))
4304 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_float,36)
4305 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4306     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4307 {
4308     return num_get_do_get_float(this, ret, first, last, base,
4309             state, pval, numpunct_wchar_use_facet(&base->loc));
4310 }
4311
4312 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4313 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4314 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_float,36)
4315 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4316     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4317 {
4318     return num_get_do_get_float(this, ret, first, last, base,
4319             state, pval, numpunct_short_use_facet(&base->loc));
4320 }
4321
4322 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4323 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4324 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4325 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4326 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_float,36)
4327 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4328     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4329 {
4330     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4331     return call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval);
4332 }
4333
4334 static istreambuf_iterator_wchar* num_get_do_get_uint64(const num_get *this,
4335         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4336         istreambuf_iterator_wchar last, ios_base *base, int *state,
4337         ULONGLONG *pval, numpunct_wchar *numpunct)
4338 {
4339     unsigned __int64 v;
4340     char tmp[25], *end;
4341     int err;
4342
4343     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4344
4345     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4346                 &last, base->fmtfl, &base->loc, numpunct), &err);
4347     if(end!=tmp && !err)
4348         *pval = v;
4349     else
4350         *state |= IOSTATE_failbit;
4351
4352     if(!first.strbuf)
4353         *state |= IOSTATE_eofbit;
4354
4355     *ret = first;
4356     return ret;
4357 }
4358
4359 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4360 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4361 #define call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_wchar*, \
4362         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONGLONG*), \
4363         (this, ret, first, last, base, state, pval))
4364 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint64,36)
4365 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4366     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4367 {
4368     return num_get_do_get_uint64(this, ret, first, last, base,
4369             state, pval, numpunct_wchar_use_facet(&base->loc));
4370 }
4371
4372 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4373 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4374 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint64,36)
4375 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4376     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4377 {
4378     return num_get_do_get_uint64(this, ret, first, last, base,
4379             state, pval, numpunct_short_use_facet(&base->loc));
4380 }
4381
4382 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4383 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4384 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4385 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4386 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint64,36)
4387 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4388     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4389 {
4390     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4391     return call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval);
4392 }
4393
4394 static istreambuf_iterator_wchar* num_get_do_get_int64(const num_get *this,
4395         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4396         istreambuf_iterator_wchar last, ios_base *base, int *state,
4397         LONGLONG *pval, numpunct_wchar *numpunct)
4398 {
4399     __int64 v;
4400     char tmp[25], *end;
4401     int err;
4402
4403     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4404
4405     v = _Stollx(tmp, &end, num_get__Getifld(this, tmp, &first,
4406                 &last, base->fmtfl, &base->loc, numpunct), &err);
4407     if(end!=tmp && !err)
4408         *pval = v;
4409     else
4410         *state |= IOSTATE_failbit;
4411
4412     if(!first.strbuf)
4413         *state |= IOSTATE_eofbit;
4414
4415     *ret = first;
4416     return ret;
4417 }
4418
4419 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4420 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4421 #define call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_wchar*, \
4422         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONGLONG*), \
4423         (this, ret, first, last, base, state, pval))
4424 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_int64,36)
4425 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4426     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4427 {
4428     return num_get_do_get_int64(this, ret, first, last, base,
4429             state, pval, numpunct_wchar_use_facet(&base->loc));
4430 }
4431
4432 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4433 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4434 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_int64,36)
4435 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4436     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4437 {
4438     return num_get_do_get_int64(this, ret, first, last, base,
4439             state, pval, numpunct_short_use_facet(&base->loc));
4440 }
4441
4442 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4443 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4444 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4445 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4446 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_int64,36)
4447 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4448     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4449 {
4450     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4451     return call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval);
4452 }
4453
4454 static istreambuf_iterator_wchar* num_get_do_get_ulong(const num_get *this,
4455         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4456         istreambuf_iterator_wchar last, ios_base *base, int *state,
4457         ULONG *pval, numpunct_wchar *numpunct)
4458 {
4459     ULONG v;
4460     char tmp[25], *end;
4461     int err;
4462
4463     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4464
4465     v = _Stoulx(tmp, &end, num_get__Getifld(this, tmp, &first,
4466                 &last, base->fmtfl, &base->loc, numpunct), &err);
4467     if(end!=tmp && !err)
4468         *pval = v;
4469     else
4470         *state |= IOSTATE_failbit;
4471
4472     if(!first.strbuf)
4473         *state |= IOSTATE_eofbit;
4474
4475     *ret = first;
4476     return ret;
4477 }
4478
4479 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4480 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4481 #define call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_wchar*, \
4482         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONG*), \
4483         (this, ret, first, last, base, state, pval))
4484 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ulong,36)
4485 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4486     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4487 {
4488     return num_get_do_get_ulong(this, ret, first, last, base,
4489             state, pval, numpunct_wchar_use_facet(&base->loc));
4490 }
4491
4492 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4493 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4494 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ulong,36)
4495 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4496     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4497 {
4498     return num_get_do_get_ulong(this, ret, first, last, base,
4499             state, pval, numpunct_short_use_facet(&base->loc));
4500 }
4501
4502 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4503 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4504 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4505 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4506 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ulong,36)
4507 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4508     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4509 {
4510     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4511     return call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4512 }
4513
4514 static istreambuf_iterator_wchar* num_get_do_get_long(const num_get *this,
4515         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4516         istreambuf_iterator_wchar last, ios_base *base, int *state,
4517         LONG *pval, numpunct_wchar *numpunct)
4518 {
4519     LONG v;
4520     char tmp[25], *end;
4521     int err;
4522
4523     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4524
4525     v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4526                 &last, base->fmtfl, &base->loc, numpunct), &err);
4527     if(end!=tmp && !err)
4528         *pval = v;
4529     else
4530         *state |= IOSTATE_failbit;
4531
4532     if(!first.strbuf)
4533         *state |= IOSTATE_eofbit;
4534
4535     *ret = first;
4536     return ret;
4537 }
4538
4539 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4540 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4541 #define call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_wchar*, \
4542         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONG*), \
4543         (this, ret, first, last, base, state, pval))
4544 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_long,36)
4545 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4546     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4547 {
4548     return num_get_do_get_long(this, ret, first, last, base,
4549             state, pval, numpunct_wchar_use_facet(&base->loc));
4550 }
4551
4552 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4553 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4554 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_long,36)
4555 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4556     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4557 {
4558     return num_get_do_get_long(this, ret, first, last, base,
4559         state, pval, numpunct_short_use_facet(&base->loc));
4560 }
4561
4562 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4563 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4564 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4565 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4566 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_long,36)
4567 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4568     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4569 {
4570     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4571     return call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval);
4572 }
4573
4574 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4575 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4576 #define call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_wchar*, \
4577         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned int*), \
4578         (this, ret, first, last, base, state, pval))
4579 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint,36)
4580 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4581     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4582 {
4583     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4584     return num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4585 }
4586
4587 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4588 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4589 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint,36)
4590 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4591     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4592 {
4593     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4594     return num_get_short_do_get_ulong(this, ret, first, last, base, state, pval);
4595 }
4596
4597 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4598 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4599 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4600 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4601 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint,36)
4602 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4603     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4604 {
4605     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4606     return call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval);
4607 }
4608
4609 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4610 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4611 #define call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_wchar*, \
4612         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned short*), \
4613         (this, ret, first, last, base, state, pval))
4614 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ushort,36)
4615 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4616     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4617 {
4618     ULONG v;
4619     char tmp[25], *beg, *end;
4620     int err, b;
4621
4622     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4623
4624     b = num_get_wchar__Getifld(this, tmp,
4625             &first, &last, base->fmtfl, &base->loc);
4626     beg = tmp + (tmp[0]=='-' ? 1 : 0);
4627     v = _Stoulx(beg, &end, b, &err);
4628
4629     if(v != (ULONG)((unsigned short)v))
4630         *state |= IOSTATE_failbit;
4631     else if(end!=beg && !err)
4632         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
4633     else
4634         *state |= IOSTATE_failbit;
4635
4636     if(!first.strbuf)
4637         *state |= IOSTATE_eofbit;
4638
4639     *ret = first;
4640     return ret;
4641 }
4642
4643 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4644 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4645 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ushort,36)
4646 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4647     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4648 {
4649     FIXME("(%p %p %p %p %p) stub\n", this, ret, base, state, pval);
4650     return ret;
4651 }
4652
4653 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4654 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4655 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@ */
4656 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4657 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ushort,36)
4658 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4659     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4660 {
4661     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4662     return call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval);
4663 }
4664
4665 static istreambuf_iterator_wchar* num_get_do_get_bool(const num_get *this,
4666         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4667         istreambuf_iterator_wchar last, ios_base *base, int *state,
4668         MSVCP_bool *pval, numpunct_wchar *numpunct)
4669 {
4670     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4671
4672     if(base->fmtfl & FMTFLAG_boolalpha) {
4673         basic_string_wchar false_bstr, true_bstr;
4674         const wchar_t *pfalse, *ptrue;
4675
4676         numpunct_wchar_falsename(numpunct, &false_bstr);
4677         numpunct_wchar_truename(numpunct, &true_bstr);
4678         pfalse = basic_string_wchar_c_str(&false_bstr);
4679         ptrue = basic_string_wchar_c_str(&true_bstr);
4680
4681         for(istreambuf_iterator_wchar_val(&first); first.strbuf;
4682                 istreambuf_iterator_wchar_inc(&first)) {
4683             if(pfalse && *pfalse && first.val!=*pfalse)
4684                 pfalse = NULL;
4685             if(ptrue && *ptrue && first.val!=*ptrue)
4686                 ptrue = NULL;
4687
4688             if(pfalse && *pfalse && ptrue && !*ptrue)
4689                 ptrue = NULL;
4690             if(ptrue && *ptrue && pfalse && !*pfalse)
4691                 pfalse = NULL;
4692
4693             if(pfalse)
4694                 pfalse++;
4695             if(ptrue)
4696                 ptrue++;
4697
4698             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
4699                 break;
4700         }
4701
4702         if(ptrue)
4703             *pval = TRUE;
4704         else if(pfalse)
4705             *pval = FALSE;
4706         else
4707             *state |= IOSTATE_failbit;
4708
4709         basic_string_wchar_dtor(&false_bstr);
4710         basic_string_wchar_dtor(&true_bstr);
4711     }else {
4712         char tmp[25], *end;
4713         int err;
4714         LONG v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4715                     &last, base->fmtfl, &base->loc, numpunct), &err);
4716
4717         if(end!=tmp && err==0 && (v==0 || v==1))
4718             *pval = v;
4719         else
4720             *state |= IOSTATE_failbit;
4721     }
4722
4723     if(!first.strbuf)
4724         *state |= IOSTATE_eofbit;
4725     memcpy(ret, &first, sizeof(first));
4726     return ret;
4727 }
4728
4729 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4730 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4731 #define call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_wchar*, \
4732         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, MSVCP_bool*), \
4733         (this, ret, first, last, base, state, pval))
4734 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_bool,36)
4735 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4736     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4737 {
4738     return num_get_do_get_bool(this, ret, first, last, base,
4739             state, pval, numpunct_wchar_use_facet(&base->loc));
4740 }
4741
4742 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4743 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4744 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_bool,36)
4745 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4746     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4747 {
4748     return num_get_do_get_bool(this, ret, first, last, base,
4749             state, pval, numpunct_short_use_facet(&base->loc));
4750 }
4751
4752 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4753 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4754 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4755 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4756 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_bool,36)
4757 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4758     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4759 {
4760     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4761     return call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval);
4762 }
4763
4764 /* ?id@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
4765 locale_id num_get_char_id = {0};
4766
4767 /* ??_7?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
4768 extern const vtable_ptr MSVCP_num_get_char_vtable;
4769
4770 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
4771 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
4772 DEFINE_THISCALL_WRAPPER(num_get_char__Init, 8)
4773 void __thiscall num_get_char__Init(num_get *this, const _Locinfo *locinfo)
4774 {
4775     TRACE("(%p %p)\n", this, locinfo);
4776     _Locinfo__Getcvt(locinfo, &this->cvt);
4777 }
4778
4779 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
4780 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
4781 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_locinfo, 12)
4782 num_get* __thiscall num_get_char_ctor_locinfo(num_get *this,
4783         const _Locinfo *locinfo, MSVCP_size_t refs)
4784 {
4785     TRACE("(%p %p %lu)\n", this, locinfo, refs);
4786
4787     locale_facet_ctor_refs(&this->facet, refs);
4788     this->facet.vtable = &MSVCP_num_get_char_vtable;
4789
4790     num_get_char__Init(this, locinfo);
4791     return this;
4792 }
4793
4794 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
4795 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
4796 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_refs, 8)
4797 num_get* __thiscall num_get_char_ctor_refs(num_get *this, MSVCP_size_t refs)
4798 {
4799     _Locinfo locinfo;
4800
4801     TRACE("(%p %lu)\n", this, refs);
4802
4803     _Locinfo_ctor(&locinfo);
4804     num_get_char_ctor_locinfo(this, &locinfo, refs);
4805     _Locinfo_dtor(&locinfo);
4806     return this;
4807 }
4808
4809 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
4810 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
4811 DEFINE_THISCALL_WRAPPER(num_get_char_ctor, 4)
4812 num_get* __thiscall num_get_char_ctor(num_get *this)
4813 {
4814     return num_get_char_ctor_refs(this, 0);
4815 }
4816
4817 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@UAE@XZ */
4818 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@UEAA@XZ */
4819 DEFINE_THISCALL_WRAPPER(num_get_char_dtor, 4)
4820 void __thiscall num_get_char_dtor(num_get *this)
4821 {
4822     TRACE("(%p)\n", this);
4823     locale_facet_dtor(&this->facet);
4824 }
4825
4826 DEFINE_THISCALL_WRAPPER(num_get_char_vector_dtor, 8)
4827 num_get* __thiscall num_get_char_vector_dtor(num_get *this, unsigned int flags)
4828 {
4829     TRACE("(%p %x)\n", this, flags);
4830     if(flags & 2) {
4831         /* we have an array, with the number of elements stored before the first object */
4832         INT_PTR i, *ptr = (INT_PTR *)this-1;
4833
4834         for(i=*ptr-1; i>=0; i--)
4835             num_get_char_dtor(this+i);
4836         MSVCRT_operator_delete(ptr);
4837     } else {
4838         num_get_char_dtor(this);
4839         if(flags & 1)
4840             MSVCRT_operator_delete(this);
4841     }
4842
4843     return this;
4844 }
4845
4846 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4847 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4848 static MSVCP_size_t num_get_char__Getcat(const locale_facet **facet, const locale *loc)
4849 {
4850     TRACE("(%p %p)\n", facet, loc);
4851
4852     if(facet && !*facet) {
4853         _Locinfo locinfo;
4854
4855         *facet = MSVCRT_operator_new(sizeof(num_get));
4856         if(!*facet) {
4857             ERR("Out of memory\n");
4858             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
4859             return 0;
4860         }
4861
4862         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
4863         num_get_char_ctor_locinfo((num_get*)*facet, &locinfo, 0);
4864         _Locinfo_dtor(&locinfo);
4865     }
4866
4867     return LC_NUMERIC;
4868 }
4869
4870 num_get* num_get_char_use_facet(const locale *loc)
4871 {
4872     static num_get *obj = NULL;
4873
4874     _Lockit lock;
4875     const locale_facet *fac;
4876
4877     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4878     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_char_id));
4879     if(fac) {
4880         _Lockit_dtor(&lock);
4881         return (num_get*)fac;
4882     }
4883
4884     if(obj) {
4885         _Lockit_dtor(&lock);
4886         return obj;
4887     }
4888
4889     num_get_char__Getcat(&fac, loc);
4890     obj = (num_get*)fac;
4891     locale_facet__Incref(&obj->facet);
4892     locale_facet_register(&obj->facet);
4893     _Lockit_dtor(&lock);
4894
4895     return obj;
4896 }
4897
4898 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1ABVlocale@2@@Z */
4899 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1AEBVlocale@2@@Z */
4900 /* Copies number to dest buffer, validates grouping and skips separators.
4901  * Updates first so it points past the number, all digits are skipped.
4902  * Returns how exponent needs to changed.
4903  * Size of dest buffer is not specified, assuming it's not smaller than 32:
4904  * strlen(+0.e+) + 22(digits) + 4(expontent) + 1(nullbyte)
4905  */
4906 static int num_get_char__Getffld(const num_get *this, char *dest, istreambuf_iterator_char *first,
4907         istreambuf_iterator_char *last, const locale *loc)
4908 {
4909     numpunct_char *numpunct = numpunct_char_use_facet(loc);
4910     int exp = 0;
4911     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
4912     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
4913
4914     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
4915
4916     istreambuf_iterator_char_val(first);
4917     /* get sign */
4918     if(first->strbuf && (first->val=='-' || first->val=='+')) {
4919         *dest++ = first->val;
4920         istreambuf_iterator_char_inc(first);
4921     }
4922
4923
4924     /* read numbers before decimal */
4925     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4926         if(first->val<'0' || first->val>'9') {
4927             break;
4928         }else {
4929             got_digit = TRUE; /* found a digit, zero or non-zero */
4930             /* write digit to dest if not a leading zero (to not waste dest buffer) */
4931             if(!got_nonzero && first->val == '0')
4932                 continue;
4933             got_nonzero = TRUE;
4934             if(dest < num_end)
4935                 *dest++ = first->val;
4936             else
4937                 exp++; /* too many digits, just multiply by 10 */
4938         }
4939     }
4940     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
4941     if(got_digit && !got_nonzero)
4942         *dest++ = '0';
4943
4944     /* get decimal, if any */
4945     if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
4946         if(dest < num_end)
4947             *dest++ = *localeconv()->decimal_point;
4948         istreambuf_iterator_char_inc(first);
4949     }
4950
4951     /* read non-grouped after decimal */
4952     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4953         if(first->val<'0' || first->val>'9')
4954             break;
4955         else if(dest<num_end) {
4956             got_digit = TRUE;
4957             *dest++ = first->val;
4958         }
4959     }
4960
4961     /* read exponent, if any */
4962     if(first->strbuf && (first->val=='e' || first->val=='E')) {
4963         *dest++ = first->val;
4964         istreambuf_iterator_char_inc(first);
4965
4966         if(first->strbuf && (first->val=='-' || first->val=='+')) {
4967             *dest++ = first->val;
4968             istreambuf_iterator_char_inc(first);
4969         }
4970
4971         got_digit = got_nonzero = FALSE;
4972         error = TRUE;
4973         /* skip any leading zeroes */
4974         for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
4975             got_digit = TRUE;
4976
4977         for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
4978             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
4979             error = FALSE;
4980             if(dest<exp_end)
4981                 *dest++ = first->val;
4982         }
4983
4984         /* if just found zeroes for exponent, use that */
4985         if(got_digit && !got_nonzero)
4986         {
4987             error = FALSE;
4988             if(dest<exp_end)
4989                 *dest++ = '0';
4990         }
4991     }
4992
4993     if(error) {
4994         *dest_beg = '\0';
4995         return 0;
4996     }
4997     *dest++ = '\0';
4998     return exp;
4999 }
5000
5001 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HABVlocale@2@@Z */
5002 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HAEBVlocale@2@@Z */
5003 /* Copies number to dest buffer, validates grouping and skips separators.
5004  * Updates first so it points past the number, all digits are skipped.
5005  * Returns number base (8, 10 or 16).
5006  * Size of dest buffer is not specified, assuming it's not smaller than 25:
5007  * 22(8^22>2^64)+1(detect overflows)+1(sign)+1(nullbyte) = 25
5008  */
5009 static int num_get_char__Getifld(const num_get *this, char *dest, istreambuf_iterator_char *first,
5010         istreambuf_iterator_char *last, int fmtflags, const locale *loc)
5011 {
5012     static const char digits[] = "0123456789abcdefABCDEF";
5013
5014     int basefield, base;
5015     char *dest_beg = dest, *dest_end = dest+24;
5016     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
5017
5018     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
5019
5020     basefield = fmtflags & FMTFLAG_basefield;
5021     if(basefield == FMTFLAG_oct)
5022         base = 8;
5023     else if(basefield == FMTFLAG_hex)
5024         base = 22; /* equal to the size of digits buffer */
5025     else if(!basefield)
5026         base = 0;
5027     else
5028         base = 10;
5029
5030     istreambuf_iterator_char_val(first);
5031     if(first->strbuf && (first->val=='-' || first->val=='+')) {
5032         *dest++ = first->val;
5033         istreambuf_iterator_char_inc(first);
5034     }
5035
5036     if(first->strbuf && first->val=='0') {
5037         found_zero = TRUE;
5038         istreambuf_iterator_char_inc(first);
5039         if(first->strbuf && (first->val=='x' || first->val=='X')) {
5040             if(!base || base == 22) {
5041                 found_zero = FALSE;
5042                 istreambuf_iterator_char_inc(first);
5043                 base = 22;
5044             }else {
5045                 base = 10;
5046             }
5047         }else {
5048             error = FALSE;
5049             if(!base) base = 8;
5050         }
5051     }else {
5052         if (!base) base = 10;
5053     }
5054
5055     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5056         if(!memchr(digits, first->val, base)) {
5057             break;
5058         }else {
5059             error = FALSE;
5060             if(dest_empty && first->val == '0')
5061             {
5062                 found_zero = TRUE;
5063                 continue;
5064             }
5065             dest_empty = FALSE;
5066             /* skip digits that can't be copied to dest buffer, other
5067              * functions are responsible for detecting overflows */
5068             if(dest < dest_end)
5069                 *dest++ = first->val;
5070         }
5071     }
5072
5073     if(error) {
5074         if (found_zero)
5075             *dest++ = '0';
5076         else
5077             dest = dest_beg;
5078     }else if(dest_empty)
5079         *dest++ = '0';
5080     *dest = '\0';
5081
5082     return (base==22 ? 16 : base);
5083 }
5084
5085 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5086 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5087 #define call_num_get_char_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_char*, \
5088         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, void**), \
5089         (this, ret, first, last, base, state, pval))
5090 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_void,36)
5091 istreambuf_iterator_char *__thiscall num_get_char_do_get_void(const num_get *this, istreambuf_iterator_char *ret,
5092     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5093 {
5094     unsigned __int64 v;
5095     char tmp[25], *end;
5096     int err;
5097
5098     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5099
5100     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5101                 &first, &last, FMTFLAG_hex, &base->loc), &err);
5102     if(v!=(unsigned __int64)((INT_PTR)v))
5103         *state |= IOSTATE_failbit;
5104     else if(end!=tmp && !err)
5105         *pval = (void*)((INT_PTR)v);
5106     else
5107         *state |= IOSTATE_failbit;
5108
5109     if(!first.strbuf)
5110         *state |= IOSTATE_eofbit;
5111
5112     *ret = first;
5113     return ret;
5114 }
5115
5116 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5117 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5118 DEFINE_THISCALL_WRAPPER(num_get_char_get_void,36)
5119 istreambuf_iterator_char *__thiscall num_get_char_get_void(const num_get *this, istreambuf_iterator_char *ret,
5120     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5121 {
5122     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5123     return call_num_get_char_do_get_void(this, ret, first, last, base, state, pval);
5124 }
5125
5126 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5127 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5128 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5129 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
5130 #define call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_char*, \
5131         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5132         (this, ret, first, last, base, state, pval))
5133 #define call_num_get_char_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_char*, \
5134         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5135         (this, ret, first, last, base, state, pval))
5136 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_double,36)
5137 istreambuf_iterator_char *__thiscall num_get_char_do_get_double(const num_get *this, istreambuf_iterator_char *ret,
5138     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5139 {
5140     double v;
5141     char tmp[32], *end;
5142     int err;
5143
5144     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5145
5146     v = _Stodx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, &base->loc), &err);
5147     if(end!=tmp && !err)
5148         *pval = v;
5149     else
5150         *state |= IOSTATE_failbit;
5151
5152     if(!first.strbuf)
5153         *state |= IOSTATE_eofbit;
5154
5155     *ret = first;
5156     return ret;
5157 }
5158
5159 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5160 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5161 DEFINE_THISCALL_WRAPPER(num_get_char_get_ldouble,36)
5162 istreambuf_iterator_char *__thiscall num_get_char_get_ldouble(const num_get *this, istreambuf_iterator_char *ret,
5163         istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5164 {
5165     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5166     return call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval);
5167 }
5168
5169 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5170 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
5171 DEFINE_THISCALL_WRAPPER(num_get_char_get_double,36)
5172 istreambuf_iterator_char *__thiscall num_get_char_get_double(const num_get *this, istreambuf_iterator_char *ret,
5173     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5174 {
5175     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5176     return call_num_get_char_do_get_double(this, ret, first, last, base, state, pval);
5177 }
5178
5179 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5180 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5181 #define call_num_get_char_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_char*, \
5182         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, float*), \
5183         (this, ret, first, last, base, state, pval))
5184 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_float,36)
5185 istreambuf_iterator_char *__thiscall num_get_char_do_get_float(const num_get *this, istreambuf_iterator_char *ret,
5186     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5187 {
5188     float v;
5189     char tmp[32], *end;
5190     int err;
5191
5192     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5193
5194     v = _Stofx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, &base->loc), &err);
5195     if(end!=tmp && !err)
5196         *pval = v;
5197     else
5198         *state |= IOSTATE_failbit;
5199
5200     if(!first.strbuf)
5201         *state |= IOSTATE_eofbit;
5202
5203     *ret = first;
5204     return ret;
5205 }
5206
5207 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5208 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5209 DEFINE_THISCALL_WRAPPER(num_get_char_get_float,36)
5210 istreambuf_iterator_char *__thiscall num_get_char_get_float(const num_get *this, istreambuf_iterator_char *ret,
5211     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5212 {
5213     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5214     return call_num_get_char_do_get_float(this, ret, first, last, base, state, pval);
5215 }
5216
5217 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5218 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5219 #define call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_char*, \
5220         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONGLONG*), \
5221         (this, ret, first, last, base, state, pval))
5222 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint64,36)
5223 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5224     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5225 {
5226     unsigned __int64 v;
5227     char tmp[25], *end;
5228     int err;
5229
5230     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5231
5232     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5233                 &first, &last, base->fmtfl, &base->loc), &err);
5234     if(end!=tmp && !err)
5235         *pval = v;
5236     else
5237         *state |= IOSTATE_failbit;
5238
5239     if(!first.strbuf)
5240         *state |= IOSTATE_eofbit;
5241
5242     *ret = first;
5243     return ret;
5244 }
5245
5246 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5247 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5248 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint64,36)
5249 istreambuf_iterator_char *__thiscall num_get_char_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5250     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5251 {
5252     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5253     return call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval);
5254 }
5255
5256 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5257 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5258 #define call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_char*, \
5259         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONGLONG*), \
5260         (this, ret, first, last, base, state, pval))
5261 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_int64,36)
5262 istreambuf_iterator_char *__thiscall num_get_char_do_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5263     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5264 {
5265     __int64 v;
5266     char tmp[25], *end;
5267     int err;
5268
5269     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5270
5271     v = _Stollx(tmp, &end, num_get_char__Getifld(this, tmp,
5272                 &first, &last, base->fmtfl, &base->loc), &err);
5273     if(end!=tmp && !err)
5274         *pval = v;
5275     else
5276         *state |= IOSTATE_failbit;
5277
5278     if(!first.strbuf)
5279         *state |= IOSTATE_eofbit;
5280
5281     *ret = first;
5282     return ret;
5283 }
5284
5285 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5286 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5287 DEFINE_THISCALL_WRAPPER(num_get_char_get_int64,36)
5288 istreambuf_iterator_char *__thiscall num_get_char_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5289     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5290 {
5291     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5292     return call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval);
5293 }
5294
5295 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5296 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5297 #define call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_char*, \
5298         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONG*), \
5299         (this, ret, first, last, base, state, pval))
5300 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ulong,36)
5301 istreambuf_iterator_char *__thiscall num_get_char_do_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5302     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5303 {
5304     ULONG v;
5305     char tmp[25], *end;
5306     int err;
5307
5308     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5309
5310     v = _Stoulx(tmp, &end, num_get_char__Getifld(this, tmp,
5311                 &first, &last, base->fmtfl, &base->loc), &err);
5312     if(end!=tmp && !err)
5313         *pval = v;
5314     else
5315         *state |= IOSTATE_failbit;
5316
5317     if(!first.strbuf)
5318         *state |= IOSTATE_eofbit;
5319
5320     *ret = first;
5321     return ret;
5322 }
5323
5324 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5325 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5326 DEFINE_THISCALL_WRAPPER(num_get_char_get_ulong,36)
5327 istreambuf_iterator_char *__thiscall num_get_char_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5328     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5329 {
5330     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5331     return call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5332 }
5333
5334 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5335 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5336 #define call_num_get_char_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_char*, \
5337         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONG*), \
5338         (this, ret, first, last, base, state, pval))
5339 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_long,36)
5340 istreambuf_iterator_char *__thiscall num_get_char_do_get_long(const num_get *this, istreambuf_iterator_char *ret,
5341     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5342 {
5343     LONG v;
5344     char tmp[25], *end;
5345     int err;
5346
5347     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5348
5349     v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5350                 &first, &last, base->fmtfl, &base->loc), &err);
5351     if(end!=tmp && !err)
5352         *pval = v;
5353     else
5354         *state |= IOSTATE_failbit;
5355
5356     if(!first.strbuf)
5357         *state |= IOSTATE_eofbit;
5358
5359     *ret = first;
5360     return ret;
5361 }
5362
5363 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5364 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5365 DEFINE_THISCALL_WRAPPER(num_get_char_get_long,36)
5366 istreambuf_iterator_char *__thiscall num_get_char_get_long(const num_get *this, istreambuf_iterator_char *ret,
5367     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5368 {
5369     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5370     return call_num_get_char_do_get_long(this, ret, first, last, base, state, pval);
5371 }
5372
5373 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5374 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5375 #define call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_char*, \
5376         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned int*), \
5377         (this, ret, first, last, base, state, pval))
5378 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint,36)
5379 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5380     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5381 {
5382     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5383     return num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5384 }
5385
5386 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5387 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5388 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint,36)
5389 istreambuf_iterator_char *__thiscall num_get_char_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5390     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5391 {
5392     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5393     return call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval);
5394 }
5395
5396 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5397 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5398 #define call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_char*, \
5399         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned short*), \
5400         (this, ret, first, last, base, state, pval))
5401 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ushort,36)
5402 istreambuf_iterator_char *__thiscall num_get_char_do_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5403     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5404 {
5405     ULONG v;
5406     char tmp[25], *beg, *end;
5407     int err, b;
5408
5409     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5410
5411     b = num_get_char__Getifld(this, tmp,
5412             &first, &last, base->fmtfl, &base->loc);
5413     beg = tmp + (tmp[0]=='-' ? 1 : 0);
5414     v = _Stoulx(beg, &end, b, &err);
5415
5416     if(v != (ULONG)((unsigned short)v))
5417         *state |= IOSTATE_failbit;
5418     else if(end!=beg && !err)
5419         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
5420     else
5421         *state |= IOSTATE_failbit;
5422
5423     if(!first.strbuf)
5424         *state |= IOSTATE_eofbit;
5425
5426     *ret = first;
5427     return ret;
5428 }
5429
5430 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5431 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5432 DEFINE_THISCALL_WRAPPER(num_get_char_get_ushort,36)
5433 istreambuf_iterator_char *__thiscall num_get_char_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5434     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5435 {
5436     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5437     return call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval);
5438 }
5439
5440 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5441 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5442 #define call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_char*, \
5443         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, MSVCP_bool*), \
5444         (this, ret, first, last, base, state, pval))
5445 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_bool,36)
5446 istreambuf_iterator_char *__thiscall num_get_char_do_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5447     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5448 {
5449     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5450
5451     if(base->fmtfl & FMTFLAG_boolalpha) {
5452         numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5453         basic_string_char false_bstr, true_bstr;
5454         const char *pfalse, *ptrue;
5455
5456         numpunct_char_falsename(numpunct, &false_bstr);
5457         numpunct_char_truename(numpunct, &true_bstr);
5458         pfalse = basic_string_char_c_str(&false_bstr);
5459         ptrue = basic_string_char_c_str(&true_bstr);
5460
5461         for(istreambuf_iterator_char_val(&first); first.strbuf;
5462                 istreambuf_iterator_char_inc(&first)) {
5463             if(pfalse && *pfalse && first.val!=*pfalse)
5464                 pfalse = NULL;
5465             if(ptrue && *ptrue && first.val!=*ptrue)
5466                 ptrue = NULL;
5467
5468             if(pfalse && *pfalse && ptrue && !*ptrue)
5469                 ptrue = NULL;
5470             if(ptrue && *ptrue && pfalse && !*pfalse)
5471                 pfalse = NULL;
5472
5473             if(pfalse)
5474                 pfalse++;
5475             if(ptrue)
5476                 ptrue++;
5477
5478             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
5479                 break;
5480         }
5481
5482         if(ptrue)
5483             *pval = TRUE;
5484         else if(pfalse)
5485             *pval = FALSE;
5486         else
5487             *state |= IOSTATE_failbit;
5488
5489         basic_string_char_dtor(&false_bstr);
5490         basic_string_char_dtor(&true_bstr);
5491     }else {
5492         char tmp[25], *end;
5493         int err;
5494         LONG v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5495                     &first, &last, base->fmtfl, &base->loc), &err);
5496
5497         if(end!=tmp && err==0 && (v==0 || v==1))
5498             *pval = v;
5499         else
5500             *state |= IOSTATE_failbit;
5501     }
5502
5503     if(!first.strbuf)
5504         *state |= IOSTATE_eofbit;
5505     memcpy(ret, &first, sizeof(first));
5506     return ret;
5507 }
5508
5509 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5510 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5511 DEFINE_THISCALL_WRAPPER(num_get_char_get_bool,36)
5512 istreambuf_iterator_char *__thiscall num_get_char_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5513     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5514 {
5515     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5516     return call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval);
5517 }
5518
5519 /* ?id@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
5520 locale_id num_put_char_id = {0};
5521
5522 /* num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
5523 extern const vtable_ptr MSVCP_num_put_char_vtable;
5524
5525 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
5526 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
5527 DEFINE_THISCALL_WRAPPER(num_put_char__Init, 8)
5528 void __thiscall num_put_char__Init(num_put *this, const _Locinfo *locinfo)
5529 {
5530     TRACE("(%p %p)\n", this, locinfo);
5531     _Locinfo__Getcvt(locinfo, &this->cvt);
5532 }
5533
5534 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
5535 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
5536 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_locinfo, 12)
5537 num_put* __thiscall num_put_char_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
5538 {
5539     TRACE("(%p %p %ld)\n", this, locinfo, refs);
5540
5541     locale_facet_ctor_refs(&this->facet, refs);
5542     this->facet.vtable = &MSVCP_num_put_char_vtable;
5543
5544     num_put_char__Init(this, locinfo);
5545     return this;
5546 }
5547
5548 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
5549 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
5550 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_refs, 8)
5551 num_put* __thiscall num_put_char_ctor_refs(num_put *this, MSVCP_size_t refs)
5552 {
5553      _Locinfo locinfo;
5554
5555      TRACE("(%p %lu)\n", this, refs);
5556
5557      _Locinfo_ctor(&locinfo);
5558      num_put_char_ctor_locinfo(this, &locinfo, refs);
5559      _Locinfo_dtor(&locinfo);
5560      return this;
5561 }
5562
5563 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
5564 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
5565 DEFINE_THISCALL_WRAPPER(num_put_char_ctor, 4)
5566 num_put* __thiscall num_put_char_ctor(num_put *this)
5567 {
5568     return num_put_char_ctor_refs(this, 0);
5569 }
5570
5571 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@UAE@XZ */
5572 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@UEAA@XZ */
5573 DEFINE_THISCALL_WRAPPER(num_put_char_dtor, 4)
5574 void __thiscall num_put_char_dtor(num_put *this)
5575 {
5576     TRACE("(%p)\n", this);
5577     locale_facet_dtor(&this->facet);
5578 }
5579
5580 DEFINE_THISCALL_WRAPPER(num_put_char_vector_dtor, 8)
5581 num_put* __thiscall num_put_char_vector_dtor(num_put *this, unsigned int flags)
5582 {
5583     TRACE("(%p %x)\n", this, flags);
5584     if(flags & 2) {
5585         /* we have an array, with the number of elements stored before the first object */
5586         INT_PTR i, *ptr = (INT_PTR *)this-1;
5587
5588         for(i=*ptr-1; i>=0; i--)
5589             num_put_char_dtor(this+i);
5590         MSVCRT_operator_delete(ptr);
5591     } else {
5592         num_put_char_dtor(this);
5593         if(flags & 1)
5594             MSVCRT_operator_delete(this);
5595     }
5596
5597     return this;
5598 }
5599
5600 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
5601 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
5602 static MSVCP_size_t num_put_char__Getcat(const locale_facet **facet, const locale *loc)
5603 {
5604     TRACE("(%p %p)\n", facet, loc);
5605
5606     if(facet && !*facet) {
5607         _Locinfo locinfo;
5608
5609         *facet = MSVCRT_operator_new(sizeof(num_put));
5610         if(!*facet) {
5611             ERR("Out of memory\n");
5612             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5613             return 0;
5614         }
5615
5616         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
5617         num_put_char_ctor_locinfo((num_put*)*facet, &locinfo, 0);
5618         _Locinfo_dtor(&locinfo);
5619     }
5620
5621     return LC_NUMERIC;
5622 }
5623
5624 num_put* num_put_char_use_facet(const locale *loc)
5625 {
5626     static num_put *obj = NULL;
5627
5628     _Lockit lock;
5629     const locale_facet *fac;
5630
5631     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
5632     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_char_id));
5633     if(fac) {
5634         _Lockit_dtor(&lock);
5635         return (num_put*)fac;
5636     }
5637
5638     if(obj) {
5639         _Lockit_dtor(&lock);
5640         return obj;
5641     }
5642
5643     num_put_char__Getcat(&fac, loc);
5644     obj = (num_put*)fac;
5645     locale_facet__Incref(&obj->facet);
5646     locale_facet_register(&obj->facet);
5647     _Lockit_dtor(&lock);
5648
5649     return obj;
5650 }
5651
5652 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PBDI@Z */
5653 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PEBD_K@Z */
5654 static ostreambuf_iterator_char* num_put_char__Putc(const num_put *this, ostreambuf_iterator_char *ret,
5655         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
5656 {
5657     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
5658
5659     for(; count>0; count--)
5660         ostreambuf_iterator_char_put(&dest, *ptr++);
5661
5662     *ret = dest;
5663     return ret;
5664 }
5665
5666 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@DI@Z */
5667 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@D_K@Z */
5668 static ostreambuf_iterator_char* num_put_char__Rep(const num_put *this, ostreambuf_iterator_char *ret,
5669         ostreambuf_iterator_char dest, char c, MSVCP_size_t count)
5670 {
5671     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
5672
5673     for(; count>0; count--)
5674         ostreambuf_iterator_char_put(&dest, c);
5675
5676     *ret = dest;
5677     return ret;
5678 }
5679
5680 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADDH@Z */
5681 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADDH@Z */
5682 static char* num_put_char__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
5683 {
5684     int type = fmtfl & FMTFLAG_floatfield;
5685     char *p = fmt;
5686
5687     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
5688
5689     *p++ = '%';
5690     if(fmtfl & FMTFLAG_showpos)
5691         *p++ = '+';
5692     if(fmtfl & FMTFLAG_showbase)
5693         *p++ = '#';
5694     *p++ = '.';
5695     *p++ = '*';
5696     if(spec)
5697         *p++ = spec;
5698
5699     if(type == FMTFLAG_fixed)
5700         *p++ = 'f';
5701     else if(type == FMTFLAG_scientific)
5702         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
5703     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
5704         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
5705     else
5706         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
5707
5708     *p++ = '\0';
5709     return fmt;
5710 }
5711
5712 /* TODO: This function should be removed when num_put_char__Fput is implemented */
5713 static ostreambuf_iterator_char* num_put_char_fput(const num_put *this, ostreambuf_iterator_char *ret,
5714         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5715 {
5716     numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5717     char *p, sep = *localeconv()->decimal_point;
5718     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5719     MSVCP_size_t pad;
5720
5721     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5722
5723     /* Change decimal point */
5724     for(p=buf; p<buf+count; p++) {
5725         if(*p == sep) {
5726             *p = numpunct_char_decimal_point(numpunct);
5727             break;
5728         }
5729     }
5730     p--;
5731
5732     /* Display number with padding */
5733     if(count >= base->wide)
5734         pad = 0;
5735     else
5736         pad = base->wide-count;
5737     base->wide = 0;
5738
5739     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5740         num_put_char__Putc(this, &dest, dest, buf, 1);
5741         buf++;
5742     }
5743     if(adjustfield != FMTFLAG_left) {
5744         num_put_char__Rep(this, ret, dest, fill, pad);
5745         pad = 0;
5746     }
5747     num_put_char__Putc(this, &dest, dest, buf, count);
5748     return num_put_char__Rep(this, ret, dest, fill, pad);
5749 }
5750
5751 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADPBDH@Z */
5752 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
5753 static char* num_put_char__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
5754 {
5755     int base = fmtfl & FMTFLAG_basefield;
5756     char *p = fmt;
5757
5758     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
5759
5760     *p++ = '%';
5761     if(fmtfl & FMTFLAG_showpos)
5762         *p++ = '+';
5763     if(fmtfl & FMTFLAG_showbase)
5764         *p++ = '#';
5765
5766     *p++ = *spec++;
5767     if(*spec == 'l')
5768         *p++ = *spec++;
5769
5770     if(base == FMTFLAG_oct)
5771         *p++ = 'o';
5772     else if(base == FMTFLAG_hex)
5773         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
5774     else
5775         *p++ = *spec;
5776
5777     *p++ = '\0';
5778     return fmt;
5779 }
5780
5781 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPADI@Z */
5782 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEAD_K@Z */
5783 static ostreambuf_iterator_char* num_put_char__Iput(const num_put *this, ostreambuf_iterator_char *ret,
5784         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5785 {
5786     numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5787     basic_string_char grouping_bstr;
5788     const char *grouping;
5789     char *p, sep;
5790     int cur_group = 0, group_size = 0;
5791     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5792     MSVCP_size_t pad;
5793
5794     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5795
5796     /* Add separators to number */
5797     numpunct_char_grouping(numpunct, &grouping_bstr);
5798     grouping = basic_string_char_c_str(&grouping_bstr);
5799     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5800
5801     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
5802         group_size++;
5803         if(group_size == grouping[cur_group]) {
5804             group_size = 0;
5805             if(grouping[cur_group+1])
5806                 cur_group++;
5807
5808             memmove(p+1, p, buf+count-p);
5809             *p = sep;
5810             count++;
5811         }
5812     }
5813     basic_string_char_dtor(&grouping_bstr);
5814
5815     /* Display number with padding */
5816     if(count >= base->wide)
5817         pad = 0;
5818     else
5819         pad = base->wide-count;
5820     base->wide = 0;
5821
5822     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5823         num_put_char__Putc(this, &dest, dest, buf, 1);
5824         buf++;
5825     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
5826         num_put_char__Putc(this, &dest, dest, buf, 2);
5827         buf += 2;
5828     }
5829     if(adjustfield != FMTFLAG_left) {
5830         num_put_char__Rep(this, ret, dest, fill, pad);
5831         pad = 0;
5832     }
5833     num_put_char__Putc(this, &dest, dest, buf, count);
5834     return num_put_char__Rep(this, ret, dest, fill, pad);
5835 }
5836
5837 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
5838 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
5839 #define call_num_put_char_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_char*, \
5840         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, LONG), \
5841         (this, ret, dest, base, fill, v))
5842 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_long, 28)
5843 ostreambuf_iterator_char* __thiscall num_put_char_do_put_long(const num_put *this, ostreambuf_iterator_char *ret,
5844         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
5845 {
5846     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
5847     char fmt[7]; /* strlen("%+#lld")+1 */
5848
5849     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5850
5851     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
5852             sprintf(tmp, num_put_char__Ifmt(this, fmt, "ld", base->fmtfl), v));
5853 }
5854
5855 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
5856 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
5857 DEFINE_THISCALL_WRAPPER(num_put_char_put_long, 28)
5858 ostreambuf_iterator_char* __thiscall num_put_char_put_long(const num_put *this, ostreambuf_iterator_char *ret,
5859         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
5860 {
5861     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5862     return call_num_put_char_do_put_long(this, ret, dest, base, fill, v);
5863 }
5864
5865 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
5866 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
5867 #define call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_char*, \
5868         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, ULONG), \
5869         (this, ret, dest, base, fill, v))
5870 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ulong, 28)
5871 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
5872         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
5873 {
5874     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
5875     char fmt[7]; /* strlen("%+#lld")+1 */
5876
5877     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5878
5879     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
5880             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lu", base->fmtfl), v));
5881 }
5882
5883 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
5884 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
5885 DEFINE_THISCALL_WRAPPER(num_put_char_put_ulong, 28)
5886 ostreambuf_iterator_char* __thiscall num_put_char_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
5887         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
5888 {
5889     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5890     return call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v);
5891 }
5892
5893 static inline streamsize get_precision(const ios_base *base)
5894 {
5895     return base->prec <= 0 && !(base->fmtfl & FMTFLAG_fixed) ? 6 : base->prec;
5896 }
5897
5898 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
5899 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
5900 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
5901 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
5902 #define call_num_put_char_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_char*, \
5903         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
5904         (this, ret, dest, base, fill, v))
5905 #define call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_char*, \
5906         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
5907         (this, ret, dest, base, fill, v))
5908 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_double, 32)
5909 ostreambuf_iterator_char* __thiscall num_put_char_do_put_double(const num_put *this, ostreambuf_iterator_char *ret,
5910         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5911 {
5912     char *tmp;
5913     char fmt[8]; /* strlen("%+#.*lg")+1 */
5914     int size;
5915     streamsize prec;
5916
5917     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5918
5919     num_put_char__Ffmt(this, fmt, '\0', base->fmtfl);
5920     prec = get_precision(base);
5921     size = _scprintf(fmt, prec, v);
5922
5923     /* TODO: don't use dynamic allocation */
5924     tmp = MSVCRT_operator_new(size*2);
5925     if(!tmp) {
5926         ERR("Out of memory\n");
5927         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5928     }
5929     num_put_char_fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v));
5930     MSVCRT_operator_delete(tmp);
5931     return ret;
5932 }
5933
5934 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
5935 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
5936 DEFINE_THISCALL_WRAPPER(num_put_char_put_double, 32)
5937 ostreambuf_iterator_char* __thiscall num_put_char_put_double(const num_put *this, ostreambuf_iterator_char *ret,
5938         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5939 {
5940     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5941     return call_num_put_char_do_put_double(this, ret, dest, base, fill, v);
5942 }
5943
5944 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
5945 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
5946 DEFINE_THISCALL_WRAPPER(num_put_char_put_ldouble, 32)
5947 ostreambuf_iterator_char* __thiscall num_put_char_put_ldouble(const num_put *this, ostreambuf_iterator_char *ret,
5948         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5949 {
5950     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5951     return call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v);
5952 }
5953
5954 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
5955 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
5956 #define call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_char*, \
5957         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, const void*), \
5958         (this, ret, dest, base, fill, v))
5959 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ptr, 28)
5960 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
5961         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
5962 {
5963     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
5964
5965     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
5966
5967     return num_put_char__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
5968 }
5969
5970 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
5971 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
5972 DEFINE_THISCALL_WRAPPER(num_put_char_put_ptr, 28)
5973 ostreambuf_iterator_char* __thiscall num_put_char_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
5974         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
5975 {
5976     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
5977     return call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v);
5978 }
5979
5980 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
5981 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
5982 #define call_num_put_char_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_char*, \
5983         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, __int64), \
5984         (this, ret, dest, base, fill, v))
5985 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_int64, 32)
5986 ostreambuf_iterator_char* __thiscall num_put_char_do_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
5987         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
5988 {
5989     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
5990     char fmt[7]; /* strlen("%+#lld")+1 */
5991
5992     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
5993
5994     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
5995             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lld", base->fmtfl), v));
5996 }
5997
5998 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
5999 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
6000 DEFINE_THISCALL_WRAPPER(num_put_char_put_int64, 32)
6001 ostreambuf_iterator_char* __thiscall num_put_char_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6002         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6003 {
6004     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6005     return call_num_put_char_do_put_int64(this, ret, dest, base, fill, v);
6006 }
6007
6008 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6009 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6010 #define call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_char*, \
6011         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, unsigned __int64), \
6012         (this, ret, dest, base, fill, v))
6013 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_uint64, 32)
6014 ostreambuf_iterator_char* __thiscall num_put_char_do_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6015         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6016 {
6017     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6018     char fmt[7]; /* strlen("%+#lld")+1 */
6019
6020     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6021
6022     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6023             sprintf(tmp, num_put_char__Ifmt(this, fmt, "llu", base->fmtfl), v));
6024 }
6025
6026 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6027 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6028 DEFINE_THISCALL_WRAPPER(num_put_char_put_uint64, 32)
6029 ostreambuf_iterator_char* __thiscall num_put_char_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6030         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6031 {
6032     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6033     return call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v);
6034 }
6035
6036 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6037 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6038 #define call_num_put_char_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_char*, \
6039         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, MSVCP_bool), \
6040         (this, ret, dest, base, fill, v))
6041 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_bool, 28)
6042 ostreambuf_iterator_char* __thiscall num_put_char_do_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6043         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6044 {
6045     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6046
6047     if(base->fmtfl & FMTFLAG_boolalpha) {
6048         numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
6049         basic_string_char str;
6050         MSVCP_size_t pad, len;
6051
6052         if(v)
6053             numpunct_char_truename(numpunct, &str);
6054         else
6055             numpunct_char_falsename(numpunct, &str);
6056
6057         len = basic_string_char_length(&str);
6058         pad = (len>base->wide ? 0 : base->wide-len);
6059         base->wide = 0;
6060
6061         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6062             num_put_char__Rep(this, &dest, dest, fill, pad);
6063             pad = 0;
6064         }
6065         num_put_char__Putc(this, &dest, dest, basic_string_char_c_str(&str), len);
6066         basic_string_char_dtor(&str);
6067         return num_put_char__Rep(this, ret, dest, fill, pad);
6068     }
6069
6070     return num_put_char_put_long(this, ret, dest, base, fill, v);
6071 }
6072
6073 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6074 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6075 DEFINE_THISCALL_WRAPPER(num_put_char_put_bool, 28)
6076 ostreambuf_iterator_char* __thiscall num_put_char_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6077         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6078 {
6079     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6080     return call_num_put_char_do_put_bool(this, ret, dest, base, fill, v);
6081 }
6082
6083 /* ?id@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
6084 static locale_id num_put_wchar_id = {0};
6085 /* ?id@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
6086 locale_id num_put_short_id = {0};
6087
6088 /* num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
6089 extern const vtable_ptr MSVCP_num_put_wchar_vtable;
6090 /* num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
6091 extern const vtable_ptr MSVCP_num_put_short_vtable;
6092
6093 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
6094 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
6095 DEFINE_THISCALL_WRAPPER(num_put_wchar__Init, 8)
6096 void __thiscall num_put_wchar__Init(num_put *this, const _Locinfo *locinfo)
6097 {
6098     TRACE("(%p %p)\n", this, locinfo);
6099     _Locinfo__Getcvt(locinfo, &this->cvt);
6100 }
6101
6102 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6103 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6104 static num_put* num_put_wchar_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6105 {
6106     TRACE("(%p %p %ld)\n", this, locinfo, refs);
6107
6108     locale_facet_ctor_refs(&this->facet, refs);
6109     this->facet.vtable = &MSVCP_num_put_wchar_vtable;
6110
6111     num_put_wchar__Init(this, locinfo);
6112     return this;
6113 }
6114
6115 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6116 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6117 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_locinfo, 12)
6118 num_put* __thiscall num_put_short_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6119 {
6120     num_put_wchar_ctor_locinfo(this, locinfo, refs);
6121     this->facet.vtable = &MSVCP_num_put_short_vtable;
6122     return this;
6123 }
6124
6125 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
6126 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
6127 static num_put* num_put_wchar_ctor_refs(num_put *this, MSVCP_size_t refs)
6128 {
6129     _Locinfo locinfo;
6130
6131     TRACE("(%p %lu)\n", this, refs);
6132
6133     _Locinfo_ctor(&locinfo);
6134     num_put_wchar_ctor_locinfo(this, &locinfo, refs);
6135     _Locinfo_dtor(&locinfo);
6136     return this;
6137 }
6138
6139 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
6140 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
6141 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_refs, 8)
6142 num_put* __thiscall num_put_short_ctor_refs(num_put *this, MSVCP_size_t refs)
6143 {
6144     num_put_wchar_ctor_refs(this, refs);
6145     this->facet.vtable = &MSVCP_num_put_short_vtable;
6146     return this;
6147 }
6148
6149 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAEXXZ */
6150 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAAXXZ */
6151 DEFINE_THISCALL_WRAPPER(num_put_short_ctor, 4)
6152 num_put* __thiscall num_put_short_ctor(num_put *this)
6153 {
6154     return num_put_short_ctor_refs(this, 0);
6155 }
6156
6157 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@UAE@XZ */
6158 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@UEAA@XZ */
6159 DEFINE_THISCALL_WRAPPER(num_put_wchar_dtor, 4)
6160 void __thiscall num_put_wchar_dtor(num_put *this)
6161 {
6162     TRACE("(%p)\n", this);
6163     locale_facet_dtor(&this->facet);
6164 }
6165
6166 DEFINE_THISCALL_WRAPPER(num_put_wchar_vector_dtor, 8)
6167 num_put* __thiscall num_put_wchar_vector_dtor(num_put *this, unsigned int flags)
6168 {
6169     TRACE("(%p %x)\n", this, flags);
6170     if(flags & 2) {
6171         /* we have an array, with the number of elements stored before the first object */
6172         INT_PTR i, *ptr = (INT_PTR *)this-1;
6173
6174         for(i=*ptr-1; i>=0; i--)
6175             num_put_wchar_dtor(this+i);
6176         MSVCRT_operator_delete(ptr);
6177     } else {
6178         num_put_wchar_dtor(this);
6179         if(flags & 1)
6180             MSVCRT_operator_delete(this);
6181     }
6182
6183     return this;
6184 }
6185
6186 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6187 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6188 static MSVCP_size_t num_put_wchar__Getcat(const locale_facet **facet, const locale *loc)
6189 {
6190     TRACE("(%p %p)\n", facet, loc);
6191
6192     if(facet && !*facet) {
6193         _Locinfo locinfo;
6194
6195         *facet = MSVCRT_operator_new(sizeof(num_put));
6196         if(!*facet) {
6197             ERR("Out of memory\n");
6198             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6199             return 0;
6200         }
6201
6202         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
6203         num_put_wchar_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6204         _Locinfo_dtor(&locinfo);
6205     }
6206
6207     return LC_NUMERIC;
6208 }
6209
6210 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6211 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6212 static MSVCP_size_t num_put_short__Getcat(const locale_facet **facet, const locale *loc)
6213 {
6214     TRACE("(%p %p)\n", facet, loc);
6215
6216     if(facet && !*facet) {
6217         _Locinfo locinfo;
6218
6219         *facet = MSVCRT_operator_new(sizeof(num_put));
6220         if(!*facet) {
6221             ERR("Out of memory\n");
6222             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6223             return 0;
6224         }
6225
6226         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
6227         num_put_short_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6228         _Locinfo_dtor(&locinfo);
6229     }
6230
6231     return LC_NUMERIC;
6232 }
6233
6234 static num_put* num_put_wchar_use_facet(const locale *loc)
6235 {
6236     static num_put *obj = NULL;
6237
6238     _Lockit lock;
6239     const locale_facet *fac;
6240
6241     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6242     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_wchar_id));
6243     if(fac) {
6244         _Lockit_dtor(&lock);
6245         return (num_put*)fac;
6246     }
6247
6248     if(obj) {
6249         _Lockit_dtor(&lock);
6250         return obj;
6251     }
6252
6253     num_put_wchar__Getcat(&fac, loc);
6254     obj = (num_put*)fac;
6255     locale_facet__Incref(&obj->facet);
6256     locale_facet_register(&obj->facet);
6257     _Lockit_dtor(&lock);
6258
6259     return obj;
6260 }
6261
6262 num_put* num_put_short_use_facet(const locale *loc)
6263 {
6264     static num_put *obj = NULL;
6265
6266     _Lockit lock;
6267     const locale_facet *fac;
6268
6269     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6270     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_short_id));
6271     if(fac) {
6272         _Lockit_dtor(&lock);
6273         return (num_put*)fac;
6274     }
6275
6276     if(obj) {
6277         _Lockit_dtor(&lock);
6278         return obj;
6279     }
6280
6281     num_put_short__Getcat(&fac, loc);
6282     obj = (num_put*)fac;
6283     locale_facet__Incref(&obj->facet);
6284     locale_facet_register(&obj->facet);
6285     _Lockit_dtor(&lock);
6286
6287     return obj;
6288 }
6289
6290 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PB_WI@Z */
6291 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEB_W_K@Z */
6292 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBGI@Z */
6293 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBG_K@Z */
6294 static ostreambuf_iterator_wchar* num_put_wchar__Put(const num_put *this, ostreambuf_iterator_wchar *ret,
6295         ostreambuf_iterator_wchar dest, const wchar_t *ptr, MSVCP_size_t count)
6296 {
6297     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_wn(ptr, count), count);
6298
6299     for(; count>0; count--)
6300         ostreambuf_iterator_wchar_put(&dest, *ptr++);
6301
6302     *ret = dest;
6303     return ret;
6304 }
6305
6306 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PBDI@Z */
6307 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEBD_K@Z */
6308 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBDI@Z */
6309 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBD_K@Z */
6310 static ostreambuf_iterator_wchar* num_put_wchar__Putc(const num_put *this, ostreambuf_iterator_wchar *ret,
6311         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count)
6312 {
6313     int state = 0;
6314     wchar_t ch;
6315
6316     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_an(ptr, count), count);
6317
6318     for(; count>0; count--) {
6319         if(_Mbrtowc(&ch, ptr++, 1, &state, &this->cvt) == 1)
6320             ostreambuf_iterator_wchar_put(&dest, ch);
6321     }
6322
6323     *ret = dest;
6324     return ret;
6325 }
6326
6327 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_WI@Z */
6328 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_W_K@Z */
6329 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@GI@Z */
6330 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@G_K@Z */
6331 static ostreambuf_iterator_wchar* num_put_wchar__Rep(const num_put *this, ostreambuf_iterator_wchar *ret,
6332         ostreambuf_iterator_wchar dest, wchar_t c, MSVCP_size_t count)
6333 {
6334     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
6335
6336     for(; count>0; count--)
6337         ostreambuf_iterator_wchar_put(&dest, c);
6338
6339     *ret = dest;
6340     return ret;
6341 }
6342
6343 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADDH@Z */
6344 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6345 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADDH@Z */
6346 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6347 static char* num_put_wchar__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
6348 {
6349     int type = fmtfl & FMTFLAG_floatfield;
6350     char *p = fmt;
6351
6352     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
6353
6354     *p++ = '%';
6355     if(fmtfl & FMTFLAG_showpos)
6356         *p++ = '+';
6357     if(fmtfl & FMTFLAG_showbase)
6358         *p++ = '#';
6359     *p++ = '.';
6360     *p++ = '*';
6361     if(spec)
6362         *p++ = spec;
6363
6364     if(type == FMTFLAG_fixed)
6365         *p++ = 'f';
6366     else if(type == FMTFLAG_scientific)
6367         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
6368     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
6369         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
6370     else
6371         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
6372
6373     *p++ = '\0';
6374     return fmt;
6375 }
6376
6377 /* TODO: This function should be removed when num_put_wchar__Fput is implemented */
6378 static ostreambuf_iterator_wchar* num_put__fput(const num_put *this, ostreambuf_iterator_wchar *ret,
6379         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6380         MSVCP_size_t count, numpunct_wchar *numpunct)
6381 {
6382     char *p, dec_point = *localeconv()->decimal_point;
6383     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6384     MSVCP_size_t i, pad;
6385
6386     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6387
6388     for(p=buf; p<buf+count; p++) {
6389         if(*p == dec_point)
6390             break;
6391     }
6392     p--;
6393
6394     /* Display number with padding */
6395     if(count >= base->wide)
6396         pad = 0;
6397     else
6398         pad = base->wide-count;
6399     base->wide = 0;
6400
6401     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6402         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6403         buf++;
6404     }
6405     if(adjustfield != FMTFLAG_left) {
6406         num_put_wchar__Rep(this, ret, dest, fill, pad);
6407         pad = 0;
6408     }
6409
6410     for(i=0; i<count; i++) {
6411         if(buf[i] == dec_point)
6412             num_put_wchar__Rep(this, &dest, dest, numpunct_wchar_decimal_point(numpunct), 1);
6413         else
6414             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6415     }
6416
6417     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6418 }
6419
6420 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADPBDH@Z */
6421 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6422 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADPBDH@Z */
6423 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6424 static char* num_put_wchar__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
6425 {
6426     int base = fmtfl & FMTFLAG_basefield;
6427     char *p = fmt;
6428
6429     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
6430
6431     *p++ = '%';
6432     if(fmtfl & FMTFLAG_showpos)
6433         *p++ = '+';
6434     if(fmtfl & FMTFLAG_showbase)
6435         *p++ = '#';
6436
6437     *p++ = *spec++;
6438     if(*spec == 'l')
6439         *p++ = *spec++;
6440
6441     if(base == FMTFLAG_oct)
6442         *p++ = 'o';
6443     else if(base == FMTFLAG_hex)
6444         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
6445     else
6446         *p++ = *spec;
6447
6448     *p++ = '\0';
6449     return fmt;
6450 }
6451
6452 static ostreambuf_iterator_wchar* num_put__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6453         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6454         MSVCP_size_t count, numpunct_wchar *numpunct)
6455 {
6456     basic_string_char grouping_bstr;
6457     const char *grouping;
6458     char *p;
6459     wchar_t sep;
6460     int cur_group = 0, group_size = 0;
6461     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6462     MSVCP_size_t i, pad;
6463
6464     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6465
6466     /* Add separators to number */
6467     numpunct_wchar_grouping(numpunct, &grouping_bstr);
6468     grouping = basic_string_char_c_str(&grouping_bstr);
6469     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
6470
6471     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6472         group_size++;
6473         if(group_size == grouping[cur_group]) {
6474             group_size = 0;
6475             if(grouping[cur_group+1])
6476                 cur_group++;
6477
6478             memmove(p+1, p, buf+count-p);
6479             *p = '\0'; /* mark thousands separator positions */
6480             count++;
6481         }
6482     }
6483     basic_string_char_dtor(&grouping_bstr);
6484
6485     /* Display number with padding */
6486     if(count >= base->wide)
6487         pad = 0;
6488     else
6489         pad = base->wide-count;
6490     base->wide = 0;
6491
6492     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6493         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6494         buf++;
6495     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
6496         num_put_wchar__Putc(this, &dest, dest, buf, 2);
6497         buf += 2;
6498     }
6499     if(adjustfield != FMTFLAG_left) {
6500         num_put_wchar__Rep(this, ret, dest, fill, pad);
6501         pad = 0;
6502     }
6503
6504     for(i=0; i<count; i++) {
6505         if(!buf[i])
6506             num_put_wchar__Rep(this, &dest, dest, sep, 1);
6507         else
6508             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6509     }
6510
6511     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6512 }
6513
6514 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPADI@Z */
6515 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEAD_K@Z */
6516 static ostreambuf_iterator_wchar* num_put_wchar__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6517         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6518 {
6519     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_wchar_use_facet(&base->loc));
6520 }
6521
6522 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPADI@Z */
6523 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEAD_K@Z */
6524 static ostreambuf_iterator_wchar* num_put_short__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6525         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6526 {
6527     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_short_use_facet(&base->loc));
6528 }
6529
6530 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
6531 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
6532 #define call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_wchar*, \
6533         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, LONG), \
6534         (this, ret, dest, base, fill, v))
6535 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_long, 28)
6536 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6537         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6538 {
6539     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6540     char fmt[7]; /* strlen("%+#lld")+1 */
6541
6542     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6543
6544     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6545             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6546 }
6547
6548 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
6549 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
6550 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_long, 28)
6551 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6552         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6553 {
6554     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6555     char fmt[7]; /* strlen("%+#lld")+1 */
6556
6557     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6558
6559     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6560             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6561 }
6562
6563 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
6564 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
6565 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
6566 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
6567 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_long, 28)
6568 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6569         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6570 {
6571     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6572     return call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v);
6573 }
6574
6575 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
6576 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
6577 #define call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_wchar*, \
6578         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, ULONG), \
6579         (this, ret, dest, base, fill, v))
6580 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ulong, 28)
6581 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6582         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6583 {
6584     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6585     char fmt[7]; /* strlen("%+#lld")+1 */
6586
6587     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6588
6589     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6590             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6591 }
6592
6593 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
6594 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
6595 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ulong, 28)
6596 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6597         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6598 {
6599     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6600     char fmt[7]; /* strlen("%+#lld")+1 */
6601
6602     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6603
6604     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6605             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6606 }
6607
6608 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
6609 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
6610 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
6611 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
6612 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ulong, 28)
6613 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6614         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6615 {
6616     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6617     return call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v);
6618 }
6619
6620 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
6621 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
6622 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
6623 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
6624 #define call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_wchar*, \
6625         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6626         (this, ret, dest, base, fill, v))
6627 #define call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_wchar*, \
6628         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6629         (this, ret, dest, base, fill, v))
6630 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_double, 32)
6631 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6632         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6633 {
6634     char *tmp;
6635     char fmt[8]; /* strlen("%+#.*lg")+1 */
6636     int size;
6637
6638     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6639
6640     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6641     size = _scprintf(fmt, base->prec, v);
6642
6643     /* TODO: don't use dynamic allocation */
6644     tmp = MSVCRT_operator_new(size*2);
6645     if(!tmp) {
6646         ERR("Out of memory\n");
6647         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6648     }
6649     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, base->prec, v),
6650             numpunct_wchar_use_facet(&base->loc));
6651     MSVCRT_operator_delete(tmp);
6652     return ret;
6653 }
6654
6655 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
6656 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
6657 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
6658 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
6659 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_double, 32)
6660 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6661         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6662 {
6663     char *tmp;
6664     char fmt[8]; /* strlen("%+#.*lg")+1 */
6665     int size;
6666     streamsize prec;
6667
6668     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6669
6670     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6671     prec = get_precision(base);
6672     size = _scprintf(fmt, prec, v);
6673
6674     /* TODO: don't use dynamic allocation */
6675     tmp = MSVCRT_operator_new(size*2);
6676     if(!tmp) {
6677         ERR("Out of memory\n");
6678         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6679     }
6680     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v),
6681             numpunct_short_use_facet(&base->loc));
6682     MSVCRT_operator_delete(tmp);
6683     return ret;
6684 }
6685
6686 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
6687 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
6688 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
6689 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
6690 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_double, 32)
6691 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6692         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6693 {
6694     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6695     return call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v);
6696 }
6697
6698 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
6699 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
6700 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
6701 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
6702 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ldouble, 32)
6703 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ldouble(const num_put *this, ostreambuf_iterator_wchar *ret,
6704         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6705 {
6706     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6707     return call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v);
6708 }
6709
6710 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
6711 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
6712 #define call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_wchar*, \
6713         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, const void*), \
6714         (this, ret, dest, base, fill, v))
6715 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ptr, 28)
6716 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6717         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6718 {
6719     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6720
6721     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6722
6723     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6724 }
6725
6726 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
6727 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
6728 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ptr, 28)
6729 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6730         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6731 {
6732     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6733
6734     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6735
6736     return num_put_short__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6737 }
6738
6739 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
6740 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
6741 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
6742 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
6743 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ptr, 28)
6744 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6745         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6746 {
6747     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6748     return call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v);
6749 }
6750
6751 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
6752 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
6753 #define call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_wchar*, \
6754         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, __int64), \
6755         (this, ret, dest, base, fill, v))
6756 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_int64, 32)
6757 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6758         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6759 {
6760     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6761     char fmt[7]; /* strlen("%+#lld")+1 */
6762
6763     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6764
6765     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6766             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
6767 }
6768
6769 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
6770 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
6771 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_int64, 32)
6772 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6773         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6774 {
6775     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6776     char fmt[7]; /* strlen("%+#lld")+1 */
6777
6778     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6779
6780     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6781             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
6782 }
6783
6784 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
6785 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
6786 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
6787 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
6788 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_int64, 32)
6789 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6790         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6791 {
6792     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6793     return call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v);
6794 }
6795
6796 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
6797 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
6798 #define call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_wchar*, \
6799         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, unsigned __int64), \
6800         (this, ret, dest, base, fill, v))
6801 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_uint64, 32)
6802 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6803         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6804 {
6805     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6806     char fmt[7]; /* strlen("%+#lld")+1 */
6807
6808     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6809
6810     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6811             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
6812 }
6813
6814 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
6815 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
6816 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_uint64, 32)
6817 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6818         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6819 {
6820     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6821     char fmt[7]; /* strlen("%+#lld")+1 */
6822
6823     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6824
6825     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6826             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
6827 }
6828
6829 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
6830 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
6831 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
6832 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
6833 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_uint64, 32)
6834 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6835         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6836 {
6837     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6838     return call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v);
6839 }
6840
6841 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
6842 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
6843 #define call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_wchar*, \
6844         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, MSVCP_bool), \
6845         (this, ret, dest, base, fill, v))
6846 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_bool, 28)
6847 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6848         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6849 {
6850     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6851
6852     if(base->fmtfl & FMTFLAG_boolalpha) {
6853         numpunct_wchar *numpunct = numpunct_wchar_use_facet(&base->loc);
6854         basic_string_wchar str;
6855         MSVCP_size_t pad, len;
6856
6857         if(v)
6858             numpunct_wchar_truename(numpunct, &str);
6859         else
6860             numpunct_wchar_falsename(numpunct, &str);
6861
6862         len = basic_string_wchar_length(&str);
6863         pad = (len>base->wide ? 0 : base->wide-len);
6864         base->wide = 0;
6865
6866         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6867             num_put_wchar__Rep(this, &dest, dest, fill, pad);
6868             pad = 0;
6869         }
6870         num_put_wchar__Put(this, &dest, dest, basic_string_wchar_c_str(&str), len);
6871         basic_string_wchar_dtor(&str);
6872         return num_put_wchar__Rep(this, ret, dest, fill, pad);
6873     }
6874
6875     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
6876 }
6877
6878 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
6879 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
6880 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_bool, 28)
6881 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6882         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6883 {
6884     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6885
6886     if(base->fmtfl & FMTFLAG_boolalpha) {
6887         numpunct_wchar *numpunct = numpunct_short_use_facet(&base->loc);
6888         basic_string_wchar str;
6889         MSVCP_size_t pad, len;
6890
6891         if(v)
6892             numpunct_wchar_truename(numpunct, &str);
6893         else
6894             numpunct_wchar_falsename(numpunct, &str);
6895
6896         len = basic_string_wchar_length(&str);
6897         pad = (len>base->wide ? 0 : base->wide-len);
6898         base->wide = 0;
6899
6900         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6901             num_put_wchar__Rep(this, &dest, dest, fill, pad);
6902             pad = 0;
6903         }
6904         num_put_wchar__Put(this, &dest, dest, basic_string_wchar_c_str(&str), len);
6905         basic_string_wchar_dtor(&str);
6906         return num_put_wchar__Rep(this, ret, dest, fill, pad);
6907     }
6908
6909     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
6910 }
6911
6912 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
6913 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
6914 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
6915 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
6916 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_bool, 28)
6917 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6918         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6919 {
6920     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6921     return call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v);
6922 }
6923
6924 /* ??0_Locimp@locale@std@@AAE@_N@Z */
6925 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
6926 static locale__Locimp* locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
6927 {
6928     TRACE("(%p %d)\n", this, transparent);
6929
6930     memset(this, 0, sizeof(locale__Locimp));
6931     locale_facet_ctor_refs(&this->facet, 1);
6932     this->transparent = transparent;
6933     basic_string_char_ctor_cstr(&this->name, "*");
6934     return this;
6935 }
6936
6937 /* ??_F_Locimp@locale@std@@QAEXXZ */
6938 /* ??_F_Locimp@locale@std@@QEAAXXZ */
6939 static locale__Locimp* locale__Locimp_ctor(locale__Locimp *this)
6940 {
6941     return locale__Locimp_ctor_transparent(this, FALSE);
6942 }
6943
6944 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
6945 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
6946 static locale__Locimp* locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
6947 {
6948     _Lockit lock;
6949     MSVCP_size_t i;
6950
6951     TRACE("(%p %p)\n", this, copy);
6952
6953     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6954     memcpy(this, copy, sizeof(locale__Locimp));
6955     locale_facet_ctor_refs(&this->facet, 1);
6956     if(copy->facetvec) {
6957         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
6958         if(!this->facetvec) {
6959             _Lockit_dtor(&lock);
6960             ERR("Out of memory\n");
6961             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6962             return NULL;
6963         }
6964         for(i=0; i<this->facet_cnt; i++)
6965         {
6966             this->facetvec[i] = copy->facetvec[i];
6967             if(this->facetvec[i])
6968                 locale_facet__Incref(this->facetvec[i]);
6969         }
6970     }
6971     basic_string_char_copy_ctor(&this->name, &copy->name);
6972     _Lockit_dtor(&lock);
6973     return this;
6974 }
6975
6976 /* ??1_Locimp@locale@std@@MAE@XZ */
6977 /* ??1_Locimp@locale@std@@MEAA@XZ */
6978 static void locale__Locimp_dtor(locale__Locimp *this)
6979 {
6980     MSVCP_size_t i;
6981
6982     TRACE("(%p)\n", this);
6983
6984     locale_facet_dtor(&this->facet);
6985     for(i=0; i<this->facet_cnt; i++)
6986         if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
6987             call_locale_facet_vector_dtor(this->facetvec[i], 1);
6988
6989     MSVCRT_operator_delete(this->facetvec);
6990     basic_string_char_dtor(&this->name);
6991 }
6992
6993 DEFINE_THISCALL_WRAPPER(locale__Locimp_vector_dtor, 8)
6994 locale__Locimp* __thiscall locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
6995 {
6996     TRACE("(%p %x)\n", this, flags);
6997     if(flags & 2) {
6998         /* we have an array, with the number of elements stored before the first object */
6999         INT_PTR i, *ptr = (INT_PTR *)this-1;
7000
7001         for(i=*ptr-1; i>=0; i--)
7002             locale__Locimp_dtor(this+i);
7003         MSVCRT_operator_delete(ptr);
7004     } else {
7005         locale__Locimp_dtor(this);
7006         if(flags & 1)
7007             MSVCRT_operator_delete(this);
7008     }
7009
7010     return this;
7011 }
7012
7013 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
7014 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
7015 static void locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
7016 {
7017     _Lockit lock;
7018
7019     TRACE("(%p %p %lu)\n", locimp, facet, id);
7020
7021     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7022     if(id >= locimp->facet_cnt) {
7023         MSVCP_size_t new_size = id+1;
7024         locale_facet **new_facetvec;
7025
7026         if(new_size < locale_id__Id_cnt+1)
7027             new_size = locale_id__Id_cnt+1;
7028
7029         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
7030         if(!new_facetvec) {
7031             _Lockit_dtor(&lock);
7032             ERR("Out of memory\n");
7033             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7034             return;
7035         }
7036
7037         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
7038         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
7039         MSVCRT_operator_delete(locimp->facetvec);
7040         locimp->facetvec = new_facetvec;
7041         locimp->facet_cnt = new_size;
7042     }
7043
7044     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
7045         call_locale_facet_vector_dtor(locimp->facetvec[id], 1);
7046
7047     locimp->facetvec[id] = facet;
7048     if(facet)
7049         locale_facet__Incref(facet);
7050     _Lockit_dtor(&lock);
7051 }
7052
7053 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
7054 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
7055 static void locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
7056 {
7057     locale__Locimp__Locimp_Addfac(this, facet, id);
7058 }
7059
7060 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7061 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7062 /* List of missing facets:
7063  * num_put, collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7064  */
7065 static void locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7066 {
7067     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7068
7069     if(cat & (1<<(ctype_short__Getcat(NULL, NULL)-1))) {
7070         ctype_wchar *ctype;
7071
7072         if(loc) {
7073             ctype = ctype_short_use_facet(loc);
7074         }else {
7075             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7076             if(!ctype) {
7077                 ERR("Out of memory\n");
7078                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7079             }
7080             ctype_short_ctor_locinfo(ctype, locinfo, 0);
7081         }
7082         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_short_id));
7083     }
7084
7085     if(cat & (1<<(num_get_short__Getcat(NULL, NULL)-1))) {
7086         num_get *numget;
7087
7088         if(loc) {
7089             numget = num_get_short_use_facet(loc);
7090         }else {
7091             numget = MSVCRT_operator_new(sizeof(num_get));
7092             if(!numget) {
7093                 ERR("Out of memory\n");
7094                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7095             }
7096             num_get_short_ctor_locinfo(numget, locinfo, 0);
7097         }
7098         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_short_id));
7099     }
7100
7101     if(cat & (1<<(num_put_short__Getcat(NULL, NULL)-1))) {
7102         num_put *numput;
7103
7104         if(loc) {
7105             numput = num_put_short_use_facet(loc);
7106         }else {
7107             numput = MSVCRT_operator_new(sizeof(num_put));
7108             if(!numput) {
7109                 ERR("Out of memory\n");
7110                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7111             }
7112             num_put_short_ctor_locinfo(numput, locinfo, 0);
7113         }
7114         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_short_id));
7115     }
7116
7117     if(cat & (1<<(numpunct_short__Getcat(NULL, NULL)-1))) {
7118         numpunct_wchar *numpunct;
7119
7120         if(loc) {
7121             numpunct = numpunct_short_use_facet(loc);
7122         }else {
7123             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7124             if(!numpunct) {
7125                 ERR("Out of memory\n");
7126                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7127             }
7128             numpunct_short_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7129         }
7130         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_short_id));
7131     }
7132
7133     if(cat & (1<<(codecvt_short__Getcat(NULL, NULL)-1))) {
7134         codecvt_wchar *codecvt;
7135
7136         if(loc) {
7137             codecvt = codecvt_short_use_facet(loc);
7138         }else {
7139             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7140             if(!codecvt) {
7141                 ERR("Out of memory\n");
7142                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7143             }
7144             codecvt_short_ctor_locinfo(codecvt, locinfo, 0);
7145         }
7146         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_short_id));
7147     }
7148 }
7149
7150 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7151 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7152 /* List of missing facets:
7153  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7154  */
7155 static void locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7156 {
7157     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7158
7159     if(cat & (1<<(ctype_wchar__Getcat(NULL, NULL)-1))) {
7160         ctype_wchar *ctype;
7161
7162         if(loc) {
7163             ctype = ctype_wchar_use_facet(loc);
7164         }else {
7165             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7166             if(!ctype) {
7167                 ERR("Out of memory\n");
7168                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7169             }
7170             ctype_wchar_ctor_locinfo(ctype, locinfo, 0);
7171         }
7172         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_wchar_id));
7173     }
7174
7175     if(cat & (1<<(num_get_wchar__Getcat(NULL, NULL)-1))) {
7176         num_get *numget;
7177
7178         if(loc) {
7179             numget = num_get_wchar_use_facet(loc);
7180         }else {
7181             numget = MSVCRT_operator_new(sizeof(num_get));
7182             if(!numget) {
7183                 ERR("Out of memory\n");
7184                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7185             }
7186             num_get_wchar_ctor_locinfo(numget, locinfo, 0);
7187         }
7188         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_wchar_id));
7189     }
7190
7191     if(cat & (1<<(num_put_wchar__Getcat(NULL, NULL)-1))) {
7192         num_put *numput;
7193
7194         if(loc) {
7195             numput = num_put_wchar_use_facet(loc);
7196         }else {
7197             numput = MSVCRT_operator_new(sizeof(num_put));
7198             if(!numput) {
7199                 ERR("Out of memory\n");
7200                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7201             }
7202             num_put_wchar_ctor_locinfo(numput, locinfo, 0);
7203         }
7204         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_wchar_id));
7205     }
7206
7207     if(cat & (1<<(numpunct_wchar__Getcat(NULL, NULL)-1))) {
7208         numpunct_wchar *numpunct;
7209
7210         if(loc) {
7211             numpunct = numpunct_wchar_use_facet(loc);
7212         }else {
7213             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7214             if(!numpunct) {
7215                 ERR("Out of memory\n");
7216                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7217             }
7218             numpunct_wchar_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7219         }
7220         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_wchar_id));
7221     }
7222
7223     if(cat & (1<<(codecvt_wchar__Getcat(NULL, NULL)-1))) {
7224         codecvt_wchar *codecvt;
7225
7226         if(loc) {
7227             codecvt = codecvt_wchar_use_facet(loc);
7228         }else {
7229             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7230             if(!codecvt) {
7231                 ERR("Out of memory\n");
7232                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7233             }
7234             codecvt_wchar_ctor_locinfo(codecvt, locinfo, 0);
7235         }
7236         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_wchar_id));
7237     }
7238 }
7239
7240 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7241 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7242 /* List of missing facets:
7243  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7244  */
7245 static void locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7246 {
7247     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7248
7249     if(cat & (1<<(ctype_char__Getcat(NULL, NULL)-1))) {
7250         ctype_char *ctype;
7251
7252         if(loc) {
7253             ctype = ctype_char_use_facet(loc);
7254         }else {
7255             ctype = MSVCRT_operator_new(sizeof(ctype_char));
7256             if(!ctype) {
7257                 ERR("Out of memory\n");
7258                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7259             }
7260             ctype_char_ctor_locinfo(ctype, locinfo, 0);
7261         }
7262         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_char_id));
7263     }
7264
7265     if(cat & (1<<(num_get_char__Getcat(NULL, NULL)-1))) {
7266         num_get *numget;
7267
7268         if(loc) {
7269             numget = num_get_char_use_facet(loc);
7270         }else {
7271             numget = MSVCRT_operator_new(sizeof(num_get));
7272             if(!numget) {
7273                 ERR("Out of memory\n");
7274                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7275             }
7276             num_get_char_ctor_locinfo(numget, locinfo, 0);
7277         }
7278         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_char_id));
7279     }
7280
7281     if(cat & (1<<(num_put_char__Getcat(NULL, NULL)-1))) {
7282         num_put *numput;
7283
7284         if(loc) {
7285             numput = num_put_char_use_facet(loc);
7286         }else {
7287             numput = MSVCRT_operator_new(sizeof(num_put));
7288             if(!numput) {
7289                 ERR("Out of memory\n");
7290                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7291             }
7292             num_put_char_ctor_locinfo(numput, locinfo, 0);
7293         }
7294         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_char_id));
7295     }
7296
7297     if(cat & (1<<(numpunct_char__Getcat(NULL, NULL)-1))) {
7298         numpunct_char *numpunct;
7299
7300         if(loc) {
7301             numpunct = numpunct_char_use_facet(loc);
7302         }else {
7303             numpunct = MSVCRT_operator_new(sizeof(numpunct_char));
7304             if(!numpunct) {
7305                 ERR("Out of memory\n");
7306                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7307             }
7308             numpunct_char_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7309         }
7310         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_char_id));
7311     }
7312
7313     if(cat & (1<<(codecvt_char__Getcat(NULL, NULL)-1))) {
7314         codecvt_char *codecvt;
7315
7316         if(loc) {
7317             codecvt = codecvt_char_use_facet(loc);
7318         }else {
7319             codecvt = MSVCRT_operator_new(sizeof(codecvt_char));
7320             if(!codecvt) {
7321                 ERR("Out of memory\n");
7322                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7323             }
7324             codecvt_char_ctor_locinfo(codecvt, locinfo, 0);
7325         }
7326         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_char_id));
7327     }
7328 }
7329
7330 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
7331 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7332 static locale__Locimp* locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7333 {
7334     TRACE("(%p %d %p %p)\n", locinfo, cat, locimp, loc);
7335
7336     locale__Locimp__Makexloc(locinfo, cat, locimp, loc);
7337     locale__Locimp__Makewloc(locinfo, cat, locimp, loc);
7338     locale__Locimp__Makeushloc(locinfo, cat, locimp, loc);
7339
7340     locimp->catmask |= cat;
7341     basic_string_char_copy_ctor(&locimp->name, &locinfo->newlocname);
7342     return locimp;
7343 }
7344
7345 /* ??_7_Locimp@locale@std@@6B@ */
7346 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
7347     (vtable_ptr)THISCALL_NAME(locale__Locimp_vector_dtor)
7348 };
7349
7350 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
7351 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
7352 DEFINE_THISCALL_WRAPPER(locale_ctor_locimp, 8)
7353 locale* __thiscall locale_ctor_locimp(locale *this, locale__Locimp *locimp)
7354 {
7355     TRACE("(%p %p)\n", this, locimp);
7356     /* Don't change locimp reference counter */
7357     this->ptr = locimp;
7358     return this;
7359 }
7360
7361 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
7362 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
7363 locale__Locimp* __cdecl locale__Init(void)
7364 {
7365     _Lockit lock;
7366
7367     TRACE("\n");
7368
7369     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7370     if(global_locale) {
7371         _Lockit_dtor(&lock);
7372         return global_locale;
7373     }
7374
7375     global_locale = MSVCRT_operator_new(sizeof(locale__Locimp));
7376     if(!global_locale) {
7377         _Lockit_dtor(&lock);
7378         ERR("Out of memory\n");
7379         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7380         return NULL;
7381     }
7382
7383     locale__Locimp_ctor(global_locale);
7384     global_locale->catmask = (1<<(LC_MAX+1))-1;
7385     basic_string_char_dtor(&global_locale->name);
7386     basic_string_char_ctor_cstr(&global_locale->name, "C");
7387
7388     locale__Locimp__Clocptr = global_locale;
7389     global_locale->facet.refs++;
7390     locale_ctor_locimp(&classic_locale, locale__Locimp__Clocptr);
7391     _Lockit_dtor(&lock);
7392
7393     return global_locale;
7394 }
7395
7396 /* ??0locale@std@@QAE@ABV01@0H@Z */
7397 /* ??0locale@std@@QEAA@AEBV01@0H@Z */
7398 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_locale, 16)
7399 locale* __thiscall locale_ctor_locale_locale(locale *this, const locale *loc, const locale *other, category cat)
7400 {
7401     _Locinfo locinfo;
7402
7403     TRACE("(%p %p %p %d)\n", this, loc, other, cat);
7404
7405     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7406     if(!this->ptr) {
7407         ERR("Out of memory\n");
7408         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7409     }
7410     locale__Locimp_copy_ctor(this->ptr, loc->ptr);
7411
7412     _Locinfo_ctor_cat_cstr(&locinfo, loc->ptr->catmask, basic_string_char_c_str(&loc->ptr->name));
7413     _Locinfo__Addcats(&locinfo, cat & other->ptr->catmask, basic_string_char_c_str(&other->ptr->name));
7414     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, other);
7415     _Locinfo_dtor(&locinfo);
7416
7417     return this;
7418 }
7419
7420 /* ??0locale@std@@QAE@ABV01@@Z */
7421 /* ??0locale@std@@QEAA@AEBV01@@Z */
7422 DEFINE_THISCALL_WRAPPER(locale_copy_ctor, 8)
7423 locale* __thiscall locale_copy_ctor(locale *this, const locale *copy)
7424 {
7425     TRACE("(%p %p)\n", this, copy);
7426     this->ptr = copy->ptr;
7427     locale_facet__Incref(&this->ptr->facet);
7428     return this;
7429 }
7430
7431 /* ??0locale@std@@QAE@ABV01@PBDH@Z */
7432 /* ??0locale@std@@QEAA@AEBV01@PEBDH@Z */
7433 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_cstr, 16)
7434 locale* __thiscall locale_ctor_locale_cstr(locale *this, const locale *loc, const char *locname, category cat)
7435 {
7436     FIXME("(%p %p %s %d) stub\n", this, loc, locname, cat);
7437     return NULL;
7438 }
7439
7440 /* ??0locale@std@@QAE@PBDH@Z */
7441 /* ??0locale@std@@QEAA@PEBDH@Z */
7442 DEFINE_THISCALL_WRAPPER(locale_ctor_cstr, 12)
7443 locale* __thiscall locale_ctor_cstr(locale *this, const char *locname, category cat)
7444 {
7445     _Locinfo locinfo;
7446
7447     TRACE("(%p %s %d)\n", this, locname, cat);
7448
7449     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7450     if(!this->ptr) {
7451         ERR("Out of memory\n");
7452         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7453     }
7454     locale__Locimp_ctor(this->ptr);
7455
7456     locale__Init();
7457
7458     _Locinfo_ctor_cat_cstr(&locinfo, cat, locname);
7459     if(!memcmp(basic_string_char_c_str(&locinfo.newlocname), "*", 2)) {
7460         _Locinfo_dtor(&locinfo);
7461         MSVCRT_operator_delete(this->ptr);
7462         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
7463     }
7464
7465     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, NULL);
7466     _Locinfo_dtor(&locinfo);
7467
7468     return this;
7469 }
7470
7471 /* ??0locale@std@@QAE@W4_Uninitialized@1@@Z */
7472 /* ??0locale@std@@QEAA@W4_Uninitialized@1@@Z */
7473 DEFINE_THISCALL_WRAPPER(locale_ctor_uninitialized, 8)
7474 locale* __thiscall locale_ctor_uninitialized(locale *this, int uninitialized)
7475 {
7476     TRACE("(%p)\n", this);
7477     this->ptr = NULL;
7478     return this;
7479 }
7480
7481 /* ??0locale@std@@QAE@XZ */
7482 /* ??0locale@std@@QEAA@XZ */
7483 DEFINE_THISCALL_WRAPPER(locale_ctor, 4)
7484 locale* __thiscall locale_ctor(locale *this)
7485 {
7486     TRACE("(%p)\n", this);
7487     this->ptr = locale__Init();
7488     locale_facet__Incref(&this->ptr->facet);
7489     return this;
7490 }
7491
7492 /* ??1locale@std@@QAE@XZ */
7493 /* ??1locale@std@@QEAA@XZ */
7494 DEFINE_THISCALL_WRAPPER(locale_dtor, 4)
7495 void __thiscall locale_dtor(locale *this)
7496 {
7497     TRACE("(%p)\n", this);
7498     if(this->ptr && locale_facet__Decref(&this->ptr->facet)) {
7499         locale__Locimp_dtor(this->ptr);
7500         MSVCRT_operator_delete(this);
7501     }
7502 }
7503
7504 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
7505 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
7506 DEFINE_THISCALL_WRAPPER(locale_operator_assign, 8)
7507 locale* __thiscall locale_operator_assign(locale *this, const locale *loc)
7508 {
7509     FIXME("(%p %p) stub\n", this, loc);
7510     return NULL;
7511 }
7512
7513 /* ??8locale@std@@QBE_NABV01@@Z */
7514 /* ??8locale@std@@QEBA_NAEBV01@@Z */
7515 DEFINE_THISCALL_WRAPPER(locale_operator_equal, 8)
7516 MSVCP_bool __thiscall locale_operator_equal(const locale *this, const locale *loc)
7517 {
7518     FIXME("(%p %p) stub\n", this, loc);
7519     return 0;
7520 }
7521
7522 /* ??9locale@std@@QBE_NABV01@@Z */
7523 /* ??9locale@std@@QEBA_NAEBV01@@Z */
7524 DEFINE_THISCALL_WRAPPER(locale_operator_not_equal, 8)
7525 MSVCP_bool __thiscall locale_operator_not_equal(const locale *this, locale const *loc)
7526 {
7527     FIXME("(%p %p) stub\n", this, loc);
7528     return 0;
7529 }
7530
7531 /* ?_Addfac@locale@std@@QAEAAV12@PAVfacet@12@II@Z */
7532 /* ?_Addfac@locale@std@@QEAAAEAV12@PEAVfacet@12@_K1@Z */
7533 DEFINE_THISCALL_WRAPPER(locale__Addfac, 16)
7534 locale* __thiscall locale__Addfac(locale *this, locale_facet *facet, MSVCP_size_t id, MSVCP_size_t catmask)
7535 {
7536     TRACE("(%p %p %lu %lu)\n", this, facet, id, catmask);
7537
7538     if(this->ptr->facet.refs > 1) {
7539         locale__Locimp *new_ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7540         if(!new_ptr) {
7541             ERR("Out of memory\n");
7542             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7543             return NULL;
7544         }
7545         locale__Locimp_copy_ctor(new_ptr, this->ptr);
7546         locale_facet__Decref(&this->ptr->facet);
7547         this->ptr = new_ptr;
7548     }
7549
7550     locale__Locimp__Addfac(this->ptr, facet, id);
7551
7552     if(catmask) {
7553         basic_string_char_dtor(&this->ptr->name);
7554         basic_string_char_ctor_cstr(&this->ptr->name, "*");
7555     }
7556     return this;
7557 }
7558
7559 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
7560 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
7561 static const locale_facet* locale__Getfacet(const locale *this, MSVCP_size_t id)
7562 {
7563     locale_facet *fac;
7564
7565     TRACE("(%p %lu)\n", this, id);
7566
7567     fac = id < this->ptr->facet_cnt ? this->ptr->facetvec[id] : NULL;
7568     if(fac || !this->ptr->transparent)
7569         return fac;
7570
7571     return id < global_locale->facet_cnt ? global_locale->facetvec[id] : NULL;
7572 }
7573
7574 /* ?classic@locale@std@@SAABV12@XZ */
7575 /* ?classic@locale@std@@SAAEBV12@XZ */
7576 const locale* __cdecl locale_classic(void)
7577 {
7578     TRACE("\n");
7579     locale__Init();
7580     return &classic_locale;
7581 }
7582
7583 /* ?empty@locale@std@@SA?AV12@XZ */
7584 locale* __cdecl locale_empty(locale *ret)
7585 {
7586     TRACE("\n");
7587
7588     locale__Init();
7589
7590     ret->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7591     if(!ret->ptr) {
7592         ERR("Out of memory\n");
7593         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7594     }
7595     locale__Locimp_ctor_transparent(ret->ptr, TRUE);
7596     return ret;
7597 }
7598
7599 /* ?name@locale@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
7600 /* ?name@locale@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
7601 DEFINE_THISCALL_WRAPPER(locale_name, 8)
7602 basic_string_char* __thiscall locale_name(const locale *this, basic_string_char *ret)
7603 {
7604     TRACE( "(%p)\n", this);
7605     basic_string_char_copy_ctor(ret, &this->ptr->name);
7606     return ret;
7607 }
7608
7609 /* ?global@locale@std@@SA?AV12@ABV12@@Z */
7610 /* ?global@locale@std@@SA?AV12@AEBV12@@Z */
7611 locale* __cdecl locale_global(locale *ret, const locale *loc)
7612 {
7613     _Lockit lock;
7614     int i;
7615
7616     TRACE("(%p %p)\n", loc, ret);
7617
7618     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7619     locale_ctor(ret);
7620
7621     if(loc->ptr != global_locale) {
7622         locale_facet__Decref(&global_locale->facet);
7623         global_locale = loc->ptr;
7624         locale_facet__Incref(&global_locale->facet);
7625
7626         for(i=LC_ALL+1; i<=LC_MAX; i++) {
7627             if((global_locale->catmask & (1<<(i-1))) == 0)
7628                 continue;
7629             setlocale(i, basic_string_char_c_str(&global_locale->name));
7630         }
7631     }
7632     _Lockit_dtor(&lock);
7633     return ret;
7634 }
7635
7636 /* wctrans */
7637 wctrans_t __cdecl wctrans(const char *property)
7638 {
7639     static const char str_tolower[] = "tolower";
7640     static const char str_toupper[] = "toupper";
7641
7642     if(!strcmp(property, str_tolower))
7643         return 2;
7644     if(!strcmp(property, str_toupper))
7645         return 1;
7646     return 0;
7647 }
7648
7649 /* towctrans */
7650 wint_t __cdecl towctrans(wint_t c, wctrans_t category)
7651 {
7652     if(category == 1)
7653         return towupper(c);
7654     return towlower(c);
7655 }
7656
7657 DEFINE_RTTI_DATA0(locale_facet, 0, ".?AVfacet@locale@std@@");
7658 DEFINE_RTTI_DATA1(collate_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@D@std@@");
7659 DEFINE_RTTI_DATA1(collate_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@_W@std@@");
7660 DEFINE_RTTI_DATA1(collate_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@G@std@@");
7661 DEFINE_RTTI_DATA1(ctype_base, 0, &locale_facet_rtti_base_descriptor, ".?AUctype_base@std@@");
7662 DEFINE_RTTI_DATA2(ctype_char, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@D@std@@");
7663 DEFINE_RTTI_DATA2(ctype_wchar, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@_W@std@@");
7664 DEFINE_RTTI_DATA2(ctype_short, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@G@std@@");
7665 DEFINE_RTTI_DATA1(codecvt_base, 0, &locale_facet_rtti_base_descriptor, ".?AVcodecvt_base@std@@");
7666 DEFINE_RTTI_DATA2(codecvt_char, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@DDH@std@@");
7667 DEFINE_RTTI_DATA2(codecvt_wchar, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@_WDH@std@@");
7668 DEFINE_RTTI_DATA2(codecvt_short, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@GDH@std@@");
7669 DEFINE_RTTI_DATA1(numpunct_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@D@std@@");
7670 DEFINE_RTTI_DATA1(numpunct_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@_W@std@@");
7671 DEFINE_RTTI_DATA1(numpunct_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@G@std@@");
7672 DEFINE_RTTI_DATA1(num_get_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@");
7673 DEFINE_RTTI_DATA1(num_get_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@");
7674 DEFINE_RTTI_DATA1(num_get_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@");
7675 DEFINE_RTTI_DATA1(num_put_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@");
7676 DEFINE_RTTI_DATA1(num_put_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@");
7677 DEFINE_RTTI_DATA1(num_put_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@");
7678
7679 #ifndef __GNUC__
7680 void __asm_dummy_vtables(void) {
7681 #endif
7682     __ASM_VTABLE(locale_facet,
7683             VTABLE_ADD_FUNC(locale_facet_vector_dtor));
7684     __ASM_VTABLE(collate_char,
7685             VTABLE_ADD_FUNC(collate_char_vector_dtor)
7686             VTABLE_ADD_FUNC(collate_char_do_compare)
7687             VTABLE_ADD_FUNC(collate_char_do_transform)
7688             VTABLE_ADD_FUNC(collate_char_do_hash));
7689     __ASM_VTABLE(collate_wchar,
7690             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7691             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7692             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7693             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7694     __ASM_VTABLE(collate_short,
7695             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7696             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7697             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7698             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7699     __ASM_VTABLE(ctype_base,
7700             VTABLE_ADD_FUNC(ctype_base_vector_dtor));
7701     __ASM_VTABLE(ctype_char,
7702             VTABLE_ADD_FUNC(ctype_char_vector_dtor)
7703             VTABLE_ADD_FUNC(ctype_char_do_tolower)
7704             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
7705             VTABLE_ADD_FUNC(ctype_char_do_toupper)
7706             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
7707             VTABLE_ADD_FUNC(ctype_char_do_widen)
7708             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
7709             VTABLE_ADD_FUNC(ctype_char_do_narrow)
7710             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch));
7711     __ASM_VTABLE(ctype_wchar,
7712             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7713             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7714             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7715             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7716             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7717             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7718             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7719             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7720             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7721             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7722             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7723             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7724             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7725     __ASM_VTABLE(ctype_short,
7726             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7727             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7728             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7729             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7730             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7731             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7732             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7733             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7734             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7735             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7736             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7737             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7738             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7739     __ASM_VTABLE(codecvt_base,
7740             VTABLE_ADD_FUNC(codecvt_base_vector_dtor)
7741             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7742             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7743             VTABLE_ADD_FUNC(codecvt_base_do_encoding));
7744     __ASM_VTABLE(codecvt_char,
7745             VTABLE_ADD_FUNC(codecvt_char_vector_dtor)
7746             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7747             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7748             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7749             VTABLE_ADD_FUNC(codecvt_char_do_in)
7750             VTABLE_ADD_FUNC(codecvt_char_do_out)
7751             VTABLE_ADD_FUNC(codecvt_char_do_unshift)
7752             VTABLE_ADD_FUNC(codecvt_char_do_length));
7753     __ASM_VTABLE(codecvt_wchar,
7754             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7755             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7756             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7757             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7758             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7759             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7760             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7761             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7762     __ASM_VTABLE(codecvt_short,
7763             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7764             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7765             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7766             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7767             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7768             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7769             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7770             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7771     __ASM_VTABLE(numpunct_char,
7772             VTABLE_ADD_FUNC(numpunct_char_vector_dtor)
7773             VTABLE_ADD_FUNC(numpunct_char_do_decimal_point)
7774             VTABLE_ADD_FUNC(numpunct_char_do_thousands_sep)
7775             VTABLE_ADD_FUNC(numpunct_char_do_grouping)
7776             VTABLE_ADD_FUNC(numpunct_char_do_falsename)
7777             VTABLE_ADD_FUNC(numpunct_char_do_truename));
7778     __ASM_VTABLE(numpunct_wchar,
7779             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7780             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7781             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7782             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7783             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7784             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7785     __ASM_VTABLE(numpunct_short,
7786             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7787             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7788             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7789             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7790             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7791             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7792     __ASM_VTABLE(num_get_char,
7793             VTABLE_ADD_FUNC(num_get_char_vector_dtor)
7794             VTABLE_ADD_FUNC(num_get_char_do_get_void)
7795             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7796             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7797             VTABLE_ADD_FUNC(num_get_char_do_get_float)
7798             VTABLE_ADD_FUNC(num_get_char_do_get_uint64)
7799             VTABLE_ADD_FUNC(num_get_char_do_get_int64)
7800             VTABLE_ADD_FUNC(num_get_char_do_get_ulong)
7801             VTABLE_ADD_FUNC(num_get_char_do_get_long)
7802             VTABLE_ADD_FUNC(num_get_char_do_get_uint)
7803             VTABLE_ADD_FUNC(num_get_char_do_get_ushort)
7804             VTABLE_ADD_FUNC(num_get_char_do_get_bool));
7805     __ASM_VTABLE(num_get_short,
7806             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7807             VTABLE_ADD_FUNC(num_get_short_do_get_void)
7808             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7809             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7810             VTABLE_ADD_FUNC(num_get_short_do_get_float)
7811             VTABLE_ADD_FUNC(num_get_short_do_get_uint64)
7812             VTABLE_ADD_FUNC(num_get_short_do_get_int64)
7813             VTABLE_ADD_FUNC(num_get_short_do_get_ulong)
7814             VTABLE_ADD_FUNC(num_get_short_do_get_long)
7815             VTABLE_ADD_FUNC(num_get_short_do_get_uint)
7816             VTABLE_ADD_FUNC(num_get_short_do_get_ushort)
7817             VTABLE_ADD_FUNC(num_get_short_do_get_bool));
7818     __ASM_VTABLE(num_get_wchar,
7819             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7820             VTABLE_ADD_FUNC(num_get_wchar_do_get_void)
7821             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7822             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7823             VTABLE_ADD_FUNC(num_get_wchar_do_get_float)
7824             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint64)
7825             VTABLE_ADD_FUNC(num_get_wchar_do_get_int64)
7826             VTABLE_ADD_FUNC(num_get_wchar_do_get_ulong)
7827             VTABLE_ADD_FUNC(num_get_wchar_do_get_long)
7828             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint)
7829             VTABLE_ADD_FUNC(num_get_wchar_do_get_ushort)
7830             VTABLE_ADD_FUNC(num_get_wchar_do_get_bool));
7831     __ASM_VTABLE(num_put_char,
7832             VTABLE_ADD_FUNC(num_put_char_vector_dtor)
7833             VTABLE_ADD_FUNC(num_put_char_do_put_ptr)
7834             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7835             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7836             VTABLE_ADD_FUNC(num_put_char_do_put_uint64)
7837             VTABLE_ADD_FUNC(num_put_char_do_put_int64)
7838             VTABLE_ADD_FUNC(num_put_char_do_put_ulong)
7839             VTABLE_ADD_FUNC(num_put_char_do_put_long)
7840             VTABLE_ADD_FUNC(num_put_char_do_put_bool));
7841     __ASM_VTABLE(num_put_wchar,
7842             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7843             VTABLE_ADD_FUNC(num_put_wchar_do_put_ptr)
7844             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7845             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7846             VTABLE_ADD_FUNC(num_put_wchar_do_put_uint64)
7847             VTABLE_ADD_FUNC(num_put_wchar_do_put_int64)
7848             VTABLE_ADD_FUNC(num_put_wchar_do_put_ulong)
7849             VTABLE_ADD_FUNC(num_put_wchar_do_put_long)
7850             VTABLE_ADD_FUNC(num_put_wchar_do_put_bool));
7851     __ASM_VTABLE(num_put_short,
7852             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7853             VTABLE_ADD_FUNC(num_put_short_do_put_ptr)
7854             VTABLE_ADD_FUNC(num_put_short_do_put_double)
7855             VTABLE_ADD_FUNC(num_put_short_do_put_double)
7856             VTABLE_ADD_FUNC(num_put_short_do_put_uint64)
7857             VTABLE_ADD_FUNC(num_put_short_do_put_int64)
7858             VTABLE_ADD_FUNC(num_put_short_do_put_ulong)
7859             VTABLE_ADD_FUNC(num_put_short_do_put_long)
7860             VTABLE_ADD_FUNC(num_put_short_do_put_bool));
7861 #ifndef __GNUC__
7862 }
7863 #endif
7864
7865 void init_locale(void *base)
7866 {
7867 #ifdef __x86_64__
7868     init_locale_facet_rtti(base);
7869     init_collate_char_rtti(base);
7870     init_collate_wchar_rtti(base);
7871     init_collate_short_rtti(base);
7872     init_ctype_base_rtti(base);
7873     init_ctype_char_rtti(base);
7874     init_ctype_wchar_rtti(base);
7875     init_ctype_short_rtti(base);
7876     init_codecvt_base_rtti(base);
7877     init_codecvt_char_rtti(base);
7878     init_codecvt_wchar_rtti(base);
7879     init_codecvt_short_rtti(base);
7880     init_numpunct_char_rtti(base);
7881     init_numpunct_wchar_rtti(base);
7882     init_numpunct_short_rtti(base);
7883     init_num_get_char_rtti(base);
7884     init_num_get_wchar_rtti(base);
7885     init_num_get_short_rtti(base);
7886     init_num_put_char_rtti(base);
7887     init_num_put_wchar_rtti(base);
7888     init_num_put_short_rtti(base);
7889 #endif
7890 }
7891
7892 void free_locale(void)
7893 {
7894     facets_elem *iter, *safe;
7895
7896     if(global_locale) {
7897         locale__Locimp_dtor(global_locale);
7898         locale_dtor(&classic_locale);
7899     }
7900
7901     LIST_FOR_EACH_ENTRY_SAFE(iter, safe, &lazy_facets, facets_elem, entry) {
7902         list_remove(&iter->entry);
7903         if(locale_facet__Decref(iter->fac))
7904             call_locale_facet_vector_dtor(iter->fac, 1);
7905         MSVCRT_operator_delete(iter);
7906     }
7907 }