msvcp90: Added partial basic_ios<wchar> implementation.
[wine] / dlls / msvcp90 / exception.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #include "msvcp90.h"
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcp90);
29
30 /* dlls/msvcrt/cppexcept.h */
31 typedef void (*cxx_copy_ctor)(void);
32
33 /* complete information about a C++ type */
34 typedef struct __cxx_type_info
35 {
36     UINT             flags;        /* flags (see CLASS_* flags below) */
37     const type_info *type_info;    /* C++ type info */
38     this_ptr_offsets offsets;      /* offsets for computing the this pointer */
39     unsigned int     size;         /* object size */
40     cxx_copy_ctor    copy_ctor;    /* copy constructor */
41 } cxx_type_info;
42 #define CLASS_IS_SIMPLE_TYPE          1
43 #define CLASS_HAS_VIRTUAL_BASE_CLASS  4
44
45 /* table of C++ types that apply for a given object */
46 typedef struct __cxx_type_info_table
47 {
48     UINT                 count;     /* number of types */
49     const cxx_type_info *info[3];   /* variable length, we declare it large enough for static RTTI */
50 } cxx_type_info_table;
51
52 /* type information for an exception object */
53 typedef struct __cxx_exception_type
54 {
55     UINT                       flags;            /* TYPE_FLAG flags */
56     void                     (*destructor)(void);/* exception object destructor */
57     void* /*cxx_exc_custom_handler*/ custom_handler;   /* custom handler for this exception */
58     const cxx_type_info_table *type_info_table;  /* list of types for this exception object */
59 } cxx_exception_type;
60
61 void WINAPI _CxxThrowException(exception*,const cxx_exception_type*);
62
63 /* vtables */
64 extern const vtable_ptr MSVCP_exception_vtable;
65 extern const vtable_ptr MSVCP_bad_alloc_vtable;
66 extern const vtable_ptr MSVCP_logic_error_vtable;
67 extern const vtable_ptr MSVCP_length_error_vtable;
68 extern const vtable_ptr MSVCP_out_of_range_vtable;
69 extern const vtable_ptr MSVCP_invalid_argument_vtable;
70 extern const vtable_ptr MSVCP_runtime_error_vtable;
71 extern const vtable_ptr MSVCP_failure_vtable;
72
73 DEFINE_THISCALL_WRAPPER(MSVCP_exception_ctor, 8)
74 exception* __thiscall MSVCP_exception_ctor(exception *this, const char **name)
75 {
76     TRACE("(%p %s)\n", this, *name);
77
78     this->vtable = &MSVCP_exception_vtable;
79     if(*name) {
80         unsigned int name_len = strlen(*name) + 1;
81         this->name = malloc(name_len);
82         memcpy(this->name, *name, name_len);
83         this->do_free = TRUE;
84     } else {
85         this->name = NULL;
86         this->do_free = FALSE;
87     }
88     return this;
89 }
90
91 DEFINE_THISCALL_WRAPPER(MSVCP_exception_copy_ctor,8)
92 exception* __thiscall MSVCP_exception_copy_ctor(exception *this, const exception *rhs)
93 {
94     TRACE("(%p,%p)\n", this, rhs);
95
96     if(!rhs->do_free) {
97         this->vtable = &MSVCP_exception_vtable;
98         this->name = rhs->name;
99         this->do_free = FALSE;
100     } else
101         MSVCP_exception_ctor(this, (const char**)&rhs->name);
102     TRACE("name = %s\n", this->name);
103     return this;
104 }
105
106 DEFINE_THISCALL_WRAPPER(MSVCP_exception_dtor,4)
107 void __thiscall MSVCP_exception_dtor(exception *this)
108 {
109     TRACE("(%p)\n", this);
110     this->vtable = &MSVCP_exception_vtable;
111     if(this->do_free)
112         free(this->name);
113 }
114
115 DEFINE_THISCALL_WRAPPER(MSVCP_exception_vector_dtor, 8)
116 void * __thiscall MSVCP_exception_vector_dtor(exception *this, unsigned int flags)
117 {
118     TRACE("%p %x\n", this, flags);
119     if(flags & 2) {
120         /* we have an array, with the number of elements stored before the first object */
121         int i, *ptr = (int *)this-1;
122
123         for(i=*ptr-1; i>=0; i--)
124             MSVCP_exception_dtor(this+i);
125         MSVCRT_operator_delete(ptr);
126     } else {
127         MSVCP_exception_dtor(this);
128         if(flags & 1)
129             MSVCRT_operator_delete(this);
130     }
131
132     return this;
133 }
134
135 DEFINE_RTTI_DATA(exception, 0, 0, NULL, NULL, NULL, ".?AVexception@std@@");
136
137 static const cxx_type_info exception_cxx_type_info = {
138     0,
139     &exception_type_info,
140     { 0, -1, 0 },
141     sizeof(exception),
142     (cxx_copy_ctor)THISCALL(MSVCP_exception_dtor)
143 };
144
145 static const cxx_type_info_table exception_cxx_type_table = {
146     1,
147     {
148         &exception_cxx_type_info,
149         NULL,
150         NULL
151     }
152 };
153
154 static const cxx_exception_type exception_cxx_type = {
155     0,
156     (cxx_copy_ctor)THISCALL(MSVCP_exception_copy_ctor),
157     NULL,
158     &exception_cxx_type_table
159 };
160
161 /* bad_alloc class data */
162 typedef exception bad_alloc;
163
164 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_ctor, 8)
165 bad_alloc* __thiscall MSVCP_bad_alloc_ctor(bad_alloc *this, const char **name)
166 {
167     TRACE("%p %s\n", this, *name);
168     MSVCP_exception_ctor(this, name);
169     this->vtable = &MSVCP_bad_alloc_vtable;
170     return this;
171 }
172
173 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_copy_ctor, 8)
174 bad_alloc* __thiscall MSVCP_bad_alloc_copy_ctor(bad_alloc *this, const bad_alloc *rhs)
175 {
176     TRACE("%p %p\n", this, rhs);
177     MSVCP_exception_copy_ctor(this, rhs);
178     this->vtable = &MSVCP_bad_alloc_vtable;
179     return this;
180 }
181
182 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_dtor, 4)
183 void __thiscall MSVCP_bad_alloc_dtor(bad_alloc *this)
184 {
185     TRACE("%p\n", this);
186     MSVCP_exception_dtor(this);
187 }
188
189 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_vector_dtor, 8)
190 void * __thiscall MSVCP_bad_alloc_vector_dtor(bad_alloc *this, unsigned int flags)
191 {
192     TRACE("%p %x\n", this, flags);
193     if(flags & 2) {
194         /* we have an array, with the number of elements stored before the first object */
195         int i, *ptr = (int *)this-1;
196
197         for(i=*ptr-1; i>=0; i--)
198             MSVCP_bad_alloc_dtor(this+i);
199         MSVCRT_operator_delete(ptr);
200     } else {
201         MSVCP_bad_alloc_dtor(this);
202         if(flags & 1)
203             MSVCRT_operator_delete(this);
204     }
205
206     return this;
207 }
208
209 DEFINE_THISCALL_WRAPPER(MSVCP_what_exception,4)
210 const char* __thiscall MSVCP_what_exception(exception * this)
211 {
212     TRACE("(%p) returning %s\n", this, this->name);
213     return this->name ? this->name : "Unknown exception";
214 }
215
216 DEFINE_RTTI_DATA(bad_alloc, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVbad_alloc@std@@");
217
218 static const cxx_type_info bad_alloc_cxx_type_info = {
219     0,
220     &bad_alloc_type_info,
221     { 0, -1, 0 },
222     sizeof(bad_alloc),
223     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_copy_ctor)
224 };
225
226 static const cxx_type_info_table bad_alloc_cxx_type_table = {
227     2,
228     {
229         &bad_alloc_cxx_type_info,
230         &exception_cxx_type_info,
231         NULL
232     }
233 };
234
235 static const cxx_exception_type bad_alloc_cxx_type = {
236     0,
237     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_dtor),
238     NULL,
239     &bad_alloc_cxx_type_table
240 };
241
242 /* logic_error class data */
243 typedef struct _logic_error {
244     exception e;
245     basic_string_char str;
246 } logic_error;
247
248 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_ctor, 8)
249 logic_error* __thiscall MSVCP_logic_error_ctor(
250         logic_error *this, const char **name)
251 {
252     TRACE("%p %s\n", this, *name);
253     this->e.vtable = &MSVCP_logic_error_vtable;
254     this->e.name = NULL;
255     this->e.do_free = FALSE;
256     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
257     return this;
258 }
259
260 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_copy_ctor, 8)
261 logic_error* __thiscall MSVCP_logic_error_copy_ctor(
262         logic_error *this, logic_error *rhs)
263 {
264     TRACE("%p %p\n", this, rhs);
265     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
266     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
267     this->e.vtable = &MSVCP_logic_error_vtable;
268     return this;
269 }
270
271 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_dtor, 4)
272 void __thiscall MSVCP_logic_error_dtor(logic_error *this)
273 {
274     TRACE("%p\n", this);
275     MSVCP_exception_dtor(&this->e);
276     MSVCP_basic_string_char_dtor(&this->str);
277 }
278
279 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_vector_dtor, 8)
280 void* __thiscall MSVCP_logic_error_vector_dtor(
281         logic_error *this, unsigned int flags)
282 {
283     TRACE("%p %x\n", this, flags);
284     if(flags & 2) {
285         /* we have an array, with the number of elements stored before the first object */
286         int i, *ptr = (int *)this-1;
287
288         for(i=*ptr-1; i>=0; i--)
289             MSVCP_logic_error_dtor(this+i);
290         MSVCRT_operator_delete(ptr);
291     } else {
292         MSVCP_logic_error_dtor(this);
293         if(flags & 1)
294             MSVCRT_operator_delete(this);
295     }
296
297     return this;
298 }
299
300 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_what, 4)
301 const char* __thiscall MSVCP_logic_error_what(logic_error *this)
302 {
303     TRACE("%p\n", this);
304     return MSVCP_basic_string_char_c_str(&this->str);
305 }
306
307 DEFINE_RTTI_DATA(logic_error, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVlogic_error@std@@");
308
309 static const cxx_type_info logic_error_cxx_type_info = {
310     0,
311     &logic_error_type_info,
312     { 0, -1, 0 },
313     sizeof(logic_error),
314     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_copy_ctor)
315 };
316
317 static const cxx_type_info_table logic_error_cxx_type_table = {
318     2,
319     {
320         &logic_error_cxx_type_info,
321         &exception_cxx_type_info,
322         NULL
323     }
324 };
325
326 static const cxx_exception_type logic_error_cxx_type = {
327     0,
328     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
329     NULL,
330     &logic_error_cxx_type_table
331 };
332
333 /* length_error class data */
334 typedef logic_error length_error;
335
336 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_ctor, 8)
337 length_error* __thiscall MSVCP_length_error_ctor(
338         length_error *this, const char **name)
339 {
340     TRACE("%p %s\n", this, *name);
341     MSVCP_logic_error_ctor(this, name);
342     this->e.vtable = &MSVCP_length_error_vtable;
343     return this;
344 }
345
346 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_copy_ctor, 8)
347 length_error* __thiscall MSVCP_length_error_copy_ctor(
348         length_error *this, length_error *rhs)
349 {
350     TRACE("%p %p\n", this, rhs);
351     MSVCP_logic_error_copy_ctor(this, rhs);
352     this->e.vtable = &MSVCP_length_error_vtable;
353     return this;
354 }
355
356 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_vector_dtor, 8)
357 void* __thiscall MSVCP_length_error_vector_dtor(
358         length_error *this, unsigned int flags)
359 {
360     TRACE("%p %x\n", this, flags);
361     return MSVCP_logic_error_vector_dtor(this, flags);
362 }
363
364 DEFINE_RTTI_DATA(length_error, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVlength_error@std@@");
365
366 static const cxx_type_info length_error_cxx_type_info = {
367     0,
368     &length_error_type_info,
369     { 0, -1, 0 },
370     sizeof(length_error),
371     (cxx_copy_ctor)THISCALL(MSVCP_length_error_copy_ctor)
372 };
373
374 static const cxx_type_info_table length_error_cxx_type_table = {
375     3,
376     {
377         &length_error_cxx_type_info,
378         &logic_error_cxx_type_info,
379         &exception_cxx_type_info
380     }
381 };
382
383 static const cxx_exception_type length_error_cxx_type = {
384     0,
385     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
386     NULL,
387     &length_error_cxx_type_table
388 };
389
390 /* out_of_range class data */
391 typedef logic_error out_of_range;
392
393 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_ctor, 8)
394 out_of_range* __thiscall MSVCP_out_of_range_ctor(
395         out_of_range *this, const char **name)
396 {
397     TRACE("%p %s\n", this, *name);
398     MSVCP_logic_error_ctor(this, name);
399     this->e.vtable = &MSVCP_out_of_range_vtable;
400     return this;
401 }
402
403 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_copy_ctor, 8)
404 out_of_range* __thiscall MSVCP_out_of_range_copy_ctor(
405         out_of_range *this, out_of_range *rhs)
406 {
407     TRACE("%p %p\n", this, rhs);
408     MSVCP_logic_error_copy_ctor(this, rhs);
409     this->e.vtable = &MSVCP_out_of_range_vtable;
410     return this;
411 }
412
413 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_vector_dtor, 8)
414 void* __thiscall MSVCP_out_of_range_vector_dtor(
415         out_of_range *this, unsigned int flags)
416 {
417     TRACE("%p %x\n", this, flags);
418     return MSVCP_logic_error_vector_dtor(this, flags);
419 }
420
421 DEFINE_RTTI_DATA(out_of_range, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVout_of_range@std@@");
422
423 static const cxx_type_info out_of_range_cxx_type_info = {
424     0,
425     &out_of_range_type_info,
426     { 0, -1, 0 },
427     sizeof(out_of_range),
428     (cxx_copy_ctor)THISCALL(MSVCP_out_of_range_copy_ctor)
429 };
430
431 static const cxx_type_info_table out_of_range_cxx_type_table = {
432     3,
433     {
434         &out_of_range_cxx_type_info,
435         &logic_error_cxx_type_info,
436         &exception_cxx_type_info
437     }
438 };
439
440 static const cxx_exception_type out_of_range_cxx_type = {
441     0,
442     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
443     NULL,
444     &out_of_range_cxx_type_table
445 };
446
447 /* invalid_argument class data */
448 typedef logic_error invalid_argument;
449
450 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_ctor, 8)
451 invalid_argument* __thiscall MSVCP_invalid_argument_ctor(
452         invalid_argument *this, const char **name)
453 {
454     TRACE("%p %s\n", this, *name);
455     MSVCP_logic_error_ctor(this, name);
456     this->e.vtable = &MSVCP_invalid_argument_vtable;
457     return this;
458 }
459
460 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_copy_ctor, 8)
461 invalid_argument* __thiscall MSVCP_invalid_argument_copy_ctor(
462         invalid_argument *this, invalid_argument *rhs)
463 {
464     TRACE("%p %p\n", this, rhs);
465     MSVCP_logic_error_copy_ctor(this, rhs);
466     this->e.vtable = &MSVCP_invalid_argument_vtable;
467     return this;
468 }
469
470 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_vector_dtor, 8)
471 void* __thiscall MSVCP_invalid_argument_vector_dtor(
472         invalid_argument *this, unsigned int flags)
473 {
474     TRACE("%p %x\n", this, flags);
475     return MSVCP_logic_error_vector_dtor(this, flags);
476 }
477
478 DEFINE_RTTI_DATA(invalid_argument, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVinvalid_argument@std@@");
479
480 static const cxx_type_info invalid_argument_cxx_type_info = {
481     0,
482     &invalid_argument_type_info,
483     { 0, -1, 0 },
484     sizeof(invalid_argument),
485     (cxx_copy_ctor)THISCALL(MSVCP_invalid_argument_copy_ctor)
486 };
487
488 static const cxx_type_info_table invalid_argument_cxx_type_table = {
489     3,
490     {
491         &invalid_argument_cxx_type_info,
492         &logic_error_cxx_type_info,
493         &exception_cxx_type_info
494     }
495 };
496
497 static const cxx_exception_type invalid_argument_cxx_type = {
498     0,
499     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
500     NULL,
501     &invalid_argument_cxx_type_table
502 };
503
504 /* runtime_error class data */
505 typedef struct {
506     exception e;
507     basic_string_char str;
508 } runtime_error;
509
510 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_ctor, 8)
511 runtime_error* __thiscall MSVCP_runtime_error_ctor(
512         runtime_error *this, const char **name)
513 {
514     TRACE("%p %s\n", this, *name);
515     this->e.vtable = &MSVCP_runtime_error_vtable;
516     this->e.name = NULL;
517     this->e.do_free = FALSE;
518     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
519     return this;
520 }
521
522 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_copy_ctor, 8)
523 runtime_error* __thiscall MSVCP_runtime_error_copy_ctor(
524         runtime_error *this, runtime_error *rhs)
525 {
526     TRACE("%p %p\n", this, rhs);
527     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
528     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
529     this->e.vtable = &MSVCP_runtime_error_vtable;
530     return this;
531 }
532
533 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_dtor, 4)
534 void __thiscall MSVCP_runtime_error_dtor(runtime_error *this)
535 {
536     TRACE("%p\n", this);
537     MSVCP_exception_dtor(&this->e);
538     MSVCP_basic_string_char_dtor(&this->str);
539 }
540
541 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_vector_dtor, 8)
542 void* __thiscall MSVCP_runtime_error_vector_dtor(
543         runtime_error *this, unsigned int flags)
544 {
545     TRACE("%p %x\n", this, flags);
546     if(flags & 2) {
547         /* we have an array, with the number of elements stored before the first object */
548         int i, *ptr = (int *)this-1;
549
550         for(i=*ptr-1; i>=0; i--)
551             MSVCP_runtime_error_dtor(this+i);
552         MSVCRT_operator_delete(ptr);
553     } else {
554         MSVCP_runtime_error_dtor(this);
555         if(flags & 1)
556             MSVCRT_operator_delete(this);
557     }
558
559     return this;
560 }
561
562 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_what, 4)
563 const char* __thiscall MSVCP_runtime_error_what(runtime_error *this)
564 {
565     TRACE("%p\n", this);
566     return MSVCP_basic_string_char_c_str(&this->str);
567 }
568
569 DEFINE_RTTI_DATA(runtime_error, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVruntime_error@std@@");
570
571 static const cxx_type_info runtime_error_cxx_type_info = {
572     0,
573     &runtime_error_type_info,
574     { 0, -1, 0 },
575     sizeof(runtime_error),
576     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_copy_ctor)
577 };
578
579 static const cxx_type_info_table runtime_error_cxx_type_table = {
580     2,
581     {
582         &runtime_error_cxx_type_info,
583         &exception_cxx_type_info,
584         NULL
585     }
586 };
587
588 static const cxx_exception_type runtime_error_cxx_type = {
589     0,
590     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_dtor),
591     NULL,
592     &runtime_error_cxx_type_table
593 };
594
595 /* failure class data */
596 typedef runtime_error failure;
597
598 DEFINE_THISCALL_WRAPPER(MSVCP_failure_ctor, 8)
599 failure* __thiscall MSVCP_failure_ctor(
600         failure *this, const char **name)
601 {
602     TRACE("%p %s\n", this, *name);
603     MSVCP_runtime_error_ctor(this, name);
604     this->e.vtable = &MSVCP_failure_vtable;
605     return this;
606 }
607
608 DEFINE_THISCALL_WRAPPER(MSVCP_failure_copy_ctor, 8)
609 failure* __thiscall MSVCP_failure_copy_ctor(
610         failure *this, failure *rhs)
611 {
612     TRACE("%p %p\n", this, rhs);
613     MSVCP_runtime_error_copy_ctor(this, rhs);
614     this->e.vtable = &MSVCP_failure_vtable;
615     return this;
616 }
617
618 DEFINE_THISCALL_WRAPPER(MSVCP_failure_dtor, 4)
619 void __thiscall MSVCP_failure_dtor(failure *this)
620 {
621     TRACE("%p\n", this);
622     MSVCP_runtime_error_dtor(this);
623 }
624
625 DEFINE_THISCALL_WRAPPER(MSVCP_failure_vector_dtor, 8)
626 void* __thiscall MSVCP_failure_vector_dtor(
627         failure *this, unsigned int flags)
628 {
629     TRACE("%p %x\n", this, flags);
630     return MSVCP_runtime_error_vector_dtor(this, flags);
631 }
632
633 DEFINE_THISCALL_WRAPPER(MSVCP_failure_what, 4)
634 const char* __thiscall MSVCP_failure_what(failure *this)
635 {
636     TRACE("%p\n", this);
637     return MSVCP_runtime_error_what(this);
638 }
639
640 DEFINE_RTTI_DATA(failure, 0, 1, &runtime_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVfailure@std@@");
641
642 static const cxx_type_info failure_cxx_type_info = {
643     0,
644     &failure_type_info,
645     { 0, -1, 0 },
646     sizeof(failure),
647     (cxx_copy_ctor)THISCALL(MSVCP_failure_copy_ctor)
648 };
649
650 static const cxx_type_info_table failure_cxx_type_table = {
651     3,
652     {
653         &failure_cxx_type_info,
654         &runtime_error_cxx_type_info,
655         &exception_cxx_type_info
656     }
657 };
658
659 static const cxx_exception_type failure_cxx_type = {
660     0,
661     (cxx_copy_ctor)THISCALL(MSVCP_failure_dtor),
662     NULL,
663     &failure_cxx_type_table
664 };
665
666 #ifndef __GNUC__
667 void __asm_dummy_vtables(void) {
668 #endif
669     __ASM_VTABLE(exception, VTABLE_ADD_FUNC(MSVCP_what_exception));
670     __ASM_VTABLE(bad_alloc, VTABLE_ADD_FUNC(MSVCP_what_exception));
671     __ASM_VTABLE(logic_error, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
672     __ASM_VTABLE(length_error, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
673     __ASM_VTABLE(out_of_range, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
674     __ASM_VTABLE(invalid_argument, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
675     __ASM_VTABLE(runtime_error, VTABLE_ADD_FUNC(MSVCP_runtime_error_what));
676     __ASM_VTABLE(failure, VTABLE_ADD_FUNC(MSVCP_failure_what));
677 #ifndef __GNUC__
678 }
679 #endif
680
681 /* Internal: throws selected exception */
682 void throw_exception(exception_type et, const char *str)
683 {
684     const char *addr = str;
685
686     switch(et) {
687     case EXCEPTION_RERAISE:
688         _CxxThrowException(NULL, NULL);
689     case EXCEPTION: {
690         exception e;
691         MSVCP_exception_ctor(&e, &addr);
692         _CxxThrowException(&e, &exception_cxx_type);
693     }
694     case EXCEPTION_BAD_ALLOC: {
695         bad_alloc e;
696         MSVCP_bad_alloc_ctor(&e, &addr);
697         _CxxThrowException(&e, &bad_alloc_cxx_type);
698     }
699     case EXCEPTION_LOGIC_ERROR: {
700         logic_error e;
701         MSVCP_logic_error_ctor(&e, &addr);
702         _CxxThrowException((exception*)&e, &logic_error_cxx_type);
703     }
704     case EXCEPTION_LENGTH_ERROR: {
705         length_error e;
706         MSVCP_length_error_ctor(&e, &addr);
707         _CxxThrowException((exception*)&e, &length_error_cxx_type);
708     }
709     case EXCEPTION_OUT_OF_RANGE: {
710         out_of_range e;
711         MSVCP_out_of_range_ctor(&e, &addr);
712         _CxxThrowException((exception*)&e, &out_of_range_cxx_type);
713     }
714     case EXCEPTION_INVALID_ARGUMENT: {
715         invalid_argument e;
716         MSVCP_invalid_argument_ctor(&e, &addr);
717         _CxxThrowException((exception*)&e, &invalid_argument_cxx_type);
718     }
719     case EXCEPTION_RUNTIME_ERROR: {
720         runtime_error e;
721         MSVCP_runtime_error_ctor(&e, &addr);
722         _CxxThrowException((exception*)&e, &runtime_error_cxx_type);
723     }
724     case EXCEPTION_FAILURE: {
725         failure e;
726         MSVCP_failure_ctor(&e, &addr);
727         _CxxThrowException((exception*)&e, &failure_cxx_type);
728     }
729     }
730 }