quartz/tests: Remove misplaced ok() call.
[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 static void MSVCP_type_info_dtor(type_info * _this)
74 {
75     free(_this->name);
76 }
77
78 /* Unexported */
79 DEFINE_THISCALL_WRAPPER(MSVCP_type_info_vector_dtor,8)
80 void * __thiscall MSVCP_type_info_vector_dtor(type_info * _this, unsigned int flags)
81 {
82     TRACE("(%p %x)\n", _this, flags);
83     if (flags & 2)
84     {
85         /* we have an array, with the number of elements stored before the first object */
86         int i, *ptr = (int *)_this - 1;
87
88         for (i = *ptr - 1; i >= 0; i--) MSVCP_type_info_dtor(_this + i);
89         MSVCRT_operator_delete(ptr);
90     }
91     else
92     {
93         MSVCP_type_info_dtor(_this);
94         if (flags & 1) MSVCRT_operator_delete(_this);
95     }
96     return _this;
97 }
98
99 DEFINE_RTTI_DATA( type_info, 0, 0, NULL, NULL, NULL, ".?AVtype_info@@" );
100
101 DEFINE_THISCALL_WRAPPER(MSVCP_exception_ctor, 8)
102 exception* __thiscall MSVCP_exception_ctor(exception *this, const char **name)
103 {
104     TRACE("(%p %s)\n", this, *name);
105
106     this->vtable = &MSVCP_exception_vtable;
107     if(*name) {
108         unsigned int name_len = strlen(*name) + 1;
109         this->name = malloc(name_len);
110         memcpy(this->name, *name, name_len);
111         this->do_free = TRUE;
112     } else {
113         this->name = NULL;
114         this->do_free = FALSE;
115     }
116     return this;
117 }
118
119 DEFINE_THISCALL_WRAPPER(MSVCP_exception_copy_ctor,8)
120 exception* __thiscall MSVCP_exception_copy_ctor(exception *this, const exception *rhs)
121 {
122     TRACE("(%p,%p)\n", this, rhs);
123
124     if(!rhs->do_free) {
125         this->vtable = &MSVCP_exception_vtable;
126         this->name = rhs->name;
127         this->do_free = FALSE;
128     } else
129         MSVCP_exception_ctor(this, (const char**)&rhs->name);
130     TRACE("name = %s\n", this->name);
131     return this;
132 }
133
134 DEFINE_THISCALL_WRAPPER(MSVCP_exception_dtor,4)
135 void __thiscall MSVCP_exception_dtor(exception *this)
136 {
137     TRACE("(%p)\n", this);
138     this->vtable = &MSVCP_exception_vtable;
139     if(this->do_free)
140         free(this->name);
141 }
142
143 DEFINE_THISCALL_WRAPPER(MSVCP_exception_vector_dtor, 8)
144 void * __thiscall MSVCP_exception_vector_dtor(exception *this, unsigned int flags)
145 {
146     TRACE("%p %x\n", this, flags);
147     if(flags & 2) {
148         /* we have an array, with the number of elements stored before the first object */
149         int i, *ptr = (int *)this-1;
150
151         for(i=*ptr-1; i>=0; i--)
152             MSVCP_exception_dtor(this+i);
153         MSVCRT_operator_delete(ptr);
154     } else {
155         MSVCP_exception_dtor(this);
156         if(flags & 1)
157             MSVCRT_operator_delete(this);
158     }
159
160     return this;
161 }
162
163 DEFINE_RTTI_DATA(exception, 0, 0, NULL, NULL, NULL, ".?AVexception@std@@");
164
165 static const cxx_type_info exception_cxx_type_info = {
166     0,
167     &exception_type_info,
168     { 0, -1, 0 },
169     sizeof(exception),
170     (cxx_copy_ctor)THISCALL(MSVCP_exception_dtor)
171 };
172
173 static const cxx_type_info_table exception_cxx_type_table = {
174     1,
175     {
176         &exception_cxx_type_info,
177         NULL,
178         NULL
179     }
180 };
181
182 static const cxx_exception_type exception_cxx_type = {
183     0,
184     (cxx_copy_ctor)THISCALL(MSVCP_exception_copy_ctor),
185     NULL,
186     &exception_cxx_type_table
187 };
188
189 /* bad_alloc class data */
190 typedef exception bad_alloc;
191
192 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_ctor, 8)
193 bad_alloc* __thiscall MSVCP_bad_alloc_ctor(bad_alloc *this, const char **name)
194 {
195     TRACE("%p %s\n", this, *name);
196     MSVCP_exception_ctor(this, name);
197     this->vtable = &MSVCP_bad_alloc_vtable;
198     return this;
199 }
200
201 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_copy_ctor, 8)
202 bad_alloc* __thiscall MSVCP_bad_alloc_copy_ctor(bad_alloc *this, const bad_alloc *rhs)
203 {
204     TRACE("%p %p\n", this, rhs);
205     MSVCP_exception_copy_ctor(this, rhs);
206     this->vtable = &MSVCP_bad_alloc_vtable;
207     return this;
208 }
209
210 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_dtor, 4)
211 void __thiscall MSVCP_bad_alloc_dtor(bad_alloc *this)
212 {
213     TRACE("%p\n", this);
214     MSVCP_exception_dtor(this);
215 }
216
217 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_vector_dtor, 8)
218 void * __thiscall MSVCP_bad_alloc_vector_dtor(bad_alloc *this, unsigned int flags)
219 {
220     TRACE("%p %x\n", this, flags);
221     if(flags & 2) {
222         /* we have an array, with the number of elements stored before the first object */
223         int i, *ptr = (int *)this-1;
224
225         for(i=*ptr-1; i>=0; i--)
226             MSVCP_bad_alloc_dtor(this+i);
227         MSVCRT_operator_delete(ptr);
228     } else {
229         MSVCP_bad_alloc_dtor(this);
230         if(flags & 1)
231             MSVCRT_operator_delete(this);
232     }
233
234     return this;
235 }
236
237 DEFINE_THISCALL_WRAPPER(MSVCP_what_exception,4)
238 const char* __thiscall MSVCP_what_exception(exception * this)
239 {
240     TRACE("(%p) returning %s\n", this, this->name);
241     return this->name ? this->name : "Unknown exception";
242 }
243
244 DEFINE_RTTI_DATA(bad_alloc, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVbad_alloc@std@@");
245
246 static const cxx_type_info bad_alloc_cxx_type_info = {
247     0,
248     &bad_alloc_type_info,
249     { 0, -1, 0 },
250     sizeof(bad_alloc),
251     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_copy_ctor)
252 };
253
254 static const cxx_type_info_table bad_alloc_cxx_type_table = {
255     2,
256     {
257         &bad_alloc_cxx_type_info,
258         &exception_cxx_type_info,
259         NULL
260     }
261 };
262
263 static const cxx_exception_type bad_alloc_cxx_type = {
264     0,
265     (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_dtor),
266     NULL,
267     &bad_alloc_cxx_type_table
268 };
269
270 /* logic_error class data */
271 typedef struct _logic_error {
272     exception e;
273     basic_string_char str;
274 } logic_error;
275
276 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_ctor, 8)
277 logic_error* __thiscall MSVCP_logic_error_ctor(
278         logic_error *this, const char **name)
279 {
280     TRACE("%p %s\n", this, *name);
281     this->e.vtable = &MSVCP_logic_error_vtable;
282     this->e.name = NULL;
283     this->e.do_free = FALSE;
284     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
285     return this;
286 }
287
288 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_copy_ctor, 8)
289 logic_error* __thiscall MSVCP_logic_error_copy_ctor(
290         logic_error *this, logic_error *rhs)
291 {
292     TRACE("%p %p\n", this, rhs);
293     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
294     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
295     this->e.vtable = &MSVCP_logic_error_vtable;
296     return this;
297 }
298
299 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_dtor, 4)
300 void __thiscall MSVCP_logic_error_dtor(logic_error *this)
301 {
302     TRACE("%p\n", this);
303     MSVCP_exception_dtor(&this->e);
304     MSVCP_basic_string_char_dtor(&this->str);
305 }
306
307 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_vector_dtor, 8)
308 void* __thiscall MSVCP_logic_error_vector_dtor(
309         logic_error *this, unsigned int flags)
310 {
311     TRACE("%p %x\n", this, flags);
312     if(flags & 2) {
313         /* we have an array, with the number of elements stored before the first object */
314         int i, *ptr = (int *)this-1;
315
316         for(i=*ptr-1; i>=0; i--)
317             MSVCP_logic_error_dtor(this+i);
318         MSVCRT_operator_delete(ptr);
319     } else {
320         MSVCP_logic_error_dtor(this);
321         if(flags & 1)
322             MSVCRT_operator_delete(this);
323     }
324
325     return this;
326 }
327
328 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_what, 4)
329 const char* __thiscall MSVCP_logic_error_what(logic_error *this)
330 {
331     TRACE("%p\n", this);
332     return MSVCP_basic_string_char_c_str(&this->str);
333 }
334
335 DEFINE_RTTI_DATA(logic_error, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVlogic_error@std@@");
336
337 static const cxx_type_info logic_error_cxx_type_info = {
338     0,
339     &logic_error_type_info,
340     { 0, -1, 0 },
341     sizeof(logic_error),
342     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_copy_ctor)
343 };
344
345 static const cxx_type_info_table logic_error_cxx_type_table = {
346     2,
347     {
348         &logic_error_cxx_type_info,
349         &exception_cxx_type_info,
350         NULL
351     }
352 };
353
354 static const cxx_exception_type logic_error_cxx_type = {
355     0,
356     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
357     NULL,
358     &logic_error_cxx_type_table
359 };
360
361 /* length_error class data */
362 typedef logic_error length_error;
363
364 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_ctor, 8)
365 length_error* __thiscall MSVCP_length_error_ctor(
366         length_error *this, const char **name)
367 {
368     TRACE("%p %s\n", this, *name);
369     MSVCP_logic_error_ctor(this, name);
370     this->e.vtable = &MSVCP_length_error_vtable;
371     return this;
372 }
373
374 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_copy_ctor, 8)
375 length_error* __thiscall MSVCP_length_error_copy_ctor(
376         length_error *this, length_error *rhs)
377 {
378     TRACE("%p %p\n", this, rhs);
379     MSVCP_logic_error_copy_ctor(this, rhs);
380     this->e.vtable = &MSVCP_length_error_vtable;
381     return this;
382 }
383
384 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_vector_dtor, 8)
385 void* __thiscall MSVCP_length_error_vector_dtor(
386         length_error *this, unsigned int flags)
387 {
388     TRACE("%p %x\n", this, flags);
389     return MSVCP_logic_error_vector_dtor(this, flags);
390 }
391
392 DEFINE_RTTI_DATA(length_error, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVlength_error@std@@");
393
394 static const cxx_type_info length_error_cxx_type_info = {
395     0,
396     &length_error_type_info,
397     { 0, -1, 0 },
398     sizeof(length_error),
399     (cxx_copy_ctor)THISCALL(MSVCP_length_error_copy_ctor)
400 };
401
402 static const cxx_type_info_table length_error_cxx_type_table = {
403     3,
404     {
405         &length_error_cxx_type_info,
406         &logic_error_cxx_type_info,
407         &exception_cxx_type_info
408     }
409 };
410
411 static const cxx_exception_type length_error_cxx_type = {
412     0,
413     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
414     NULL,
415     &length_error_cxx_type_table
416 };
417
418 /* out_of_range class data */
419 typedef logic_error out_of_range;
420
421 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_ctor, 8)
422 out_of_range* __thiscall MSVCP_out_of_range_ctor(
423         out_of_range *this, const char **name)
424 {
425     TRACE("%p %s\n", this, *name);
426     MSVCP_logic_error_ctor(this, name);
427     this->e.vtable = &MSVCP_out_of_range_vtable;
428     return this;
429 }
430
431 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_copy_ctor, 8)
432 out_of_range* __thiscall MSVCP_out_of_range_copy_ctor(
433         out_of_range *this, out_of_range *rhs)
434 {
435     TRACE("%p %p\n", this, rhs);
436     MSVCP_logic_error_copy_ctor(this, rhs);
437     this->e.vtable = &MSVCP_out_of_range_vtable;
438     return this;
439 }
440
441 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_vector_dtor, 8)
442 void* __thiscall MSVCP_out_of_range_vector_dtor(
443         out_of_range *this, unsigned int flags)
444 {
445     TRACE("%p %x\n", this, flags);
446     return MSVCP_logic_error_vector_dtor(this, flags);
447 }
448
449 DEFINE_RTTI_DATA(out_of_range, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVout_of_range@std@@");
450
451 static const cxx_type_info out_of_range_cxx_type_info = {
452     0,
453     &out_of_range_type_info,
454     { 0, -1, 0 },
455     sizeof(out_of_range),
456     (cxx_copy_ctor)THISCALL(MSVCP_out_of_range_copy_ctor)
457 };
458
459 static const cxx_type_info_table out_of_range_cxx_type_table = {
460     3,
461     {
462         &out_of_range_cxx_type_info,
463         &logic_error_cxx_type_info,
464         &exception_cxx_type_info
465     }
466 };
467
468 static const cxx_exception_type out_of_range_cxx_type = {
469     0,
470     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
471     NULL,
472     &out_of_range_cxx_type_table
473 };
474
475 /* invalid_argument class data */
476 typedef logic_error invalid_argument;
477
478 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_ctor, 8)
479 invalid_argument* __thiscall MSVCP_invalid_argument_ctor(
480         invalid_argument *this, const char **name)
481 {
482     TRACE("%p %s\n", this, *name);
483     MSVCP_logic_error_ctor(this, name);
484     this->e.vtable = &MSVCP_invalid_argument_vtable;
485     return this;
486 }
487
488 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_copy_ctor, 8)
489 invalid_argument* __thiscall MSVCP_invalid_argument_copy_ctor(
490         invalid_argument *this, invalid_argument *rhs)
491 {
492     TRACE("%p %p\n", this, rhs);
493     MSVCP_logic_error_copy_ctor(this, rhs);
494     this->e.vtable = &MSVCP_invalid_argument_vtable;
495     return this;
496 }
497
498 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_vector_dtor, 8)
499 void* __thiscall MSVCP_invalid_argument_vector_dtor(
500         invalid_argument *this, unsigned int flags)
501 {
502     TRACE("%p %x\n", this, flags);
503     return MSVCP_logic_error_vector_dtor(this, flags);
504 }
505
506 DEFINE_RTTI_DATA(invalid_argument, 0, 2, &logic_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVinvalid_argument@std@@");
507
508 static const cxx_type_info invalid_argument_cxx_type_info = {
509     0,
510     &invalid_argument_type_info,
511     { 0, -1, 0 },
512     sizeof(invalid_argument),
513     (cxx_copy_ctor)THISCALL(MSVCP_invalid_argument_copy_ctor)
514 };
515
516 static const cxx_type_info_table invalid_argument_cxx_type_table = {
517     3,
518     {
519         &invalid_argument_cxx_type_info,
520         &logic_error_cxx_type_info,
521         &exception_cxx_type_info
522     }
523 };
524
525 static const cxx_exception_type invalid_argument_cxx_type = {
526     0,
527     (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
528     NULL,
529     &invalid_argument_cxx_type_table
530 };
531
532 /* runtime_error class data */
533 typedef struct {
534     exception e;
535     basic_string_char str;
536 } runtime_error;
537
538 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_ctor, 8)
539 runtime_error* __thiscall MSVCP_runtime_error_ctor(
540         runtime_error *this, const char **name)
541 {
542     TRACE("%p %s\n", this, *name);
543     this->e.vtable = &MSVCP_runtime_error_vtable;
544     this->e.name = NULL;
545     this->e.do_free = FALSE;
546     MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
547     return this;
548 }
549
550 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_copy_ctor, 8)
551 runtime_error* __thiscall MSVCP_runtime_error_copy_ctor(
552         runtime_error *this, runtime_error *rhs)
553 {
554     TRACE("%p %p\n", this, rhs);
555     MSVCP_exception_copy_ctor(&this->e, &rhs->e);
556     MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
557     this->e.vtable = &MSVCP_runtime_error_vtable;
558     return this;
559 }
560
561 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_dtor, 4)
562 void __thiscall MSVCP_runtime_error_dtor(runtime_error *this)
563 {
564     TRACE("%p\n", this);
565     MSVCP_exception_dtor(&this->e);
566     MSVCP_basic_string_char_dtor(&this->str);
567 }
568
569 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_vector_dtor, 8)
570 void* __thiscall MSVCP_runtime_error_vector_dtor(
571         runtime_error *this, unsigned int flags)
572 {
573     TRACE("%p %x\n", this, flags);
574     if(flags & 2) {
575         /* we have an array, with the number of elements stored before the first object */
576         int i, *ptr = (int *)this-1;
577
578         for(i=*ptr-1; i>=0; i--)
579             MSVCP_runtime_error_dtor(this+i);
580         MSVCRT_operator_delete(ptr);
581     } else {
582         MSVCP_runtime_error_dtor(this);
583         if(flags & 1)
584             MSVCRT_operator_delete(this);
585     }
586
587     return this;
588 }
589
590 DEFINE_THISCALL_WRAPPER(MSVCP_runtime_error_what, 4)
591 const char* __thiscall MSVCP_runtime_error_what(runtime_error *this)
592 {
593     TRACE("%p\n", this);
594     return MSVCP_basic_string_char_c_str(&this->str);
595 }
596
597 DEFINE_RTTI_DATA(runtime_error, 0, 1, &exception_rtti_base_descriptor, NULL, NULL, ".?AVruntime_error@std@@");
598
599 static const cxx_type_info runtime_error_cxx_type_info = {
600     0,
601     &runtime_error_type_info,
602     { 0, -1, 0 },
603     sizeof(runtime_error),
604     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_copy_ctor)
605 };
606
607 static const cxx_type_info_table runtime_error_cxx_type_table = {
608     2,
609     {
610         &runtime_error_cxx_type_info,
611         &exception_cxx_type_info,
612         NULL
613     }
614 };
615
616 static const cxx_exception_type runtime_error_cxx_type = {
617     0,
618     (cxx_copy_ctor)THISCALL(MSVCP_runtime_error_dtor),
619     NULL,
620     &runtime_error_cxx_type_table
621 };
622
623 /* failure class data */
624 typedef runtime_error failure;
625
626 DEFINE_THISCALL_WRAPPER(MSVCP_failure_ctor, 8)
627 failure* __thiscall MSVCP_failure_ctor(
628         failure *this, const char **name)
629 {
630     TRACE("%p %s\n", this, *name);
631     MSVCP_runtime_error_ctor(this, name);
632     this->e.vtable = &MSVCP_failure_vtable;
633     return this;
634 }
635
636 DEFINE_THISCALL_WRAPPER(MSVCP_failure_copy_ctor, 8)
637 failure* __thiscall MSVCP_failure_copy_ctor(
638         failure *this, failure *rhs)
639 {
640     TRACE("%p %p\n", this, rhs);
641     MSVCP_runtime_error_copy_ctor(this, rhs);
642     this->e.vtable = &MSVCP_failure_vtable;
643     return this;
644 }
645
646 DEFINE_THISCALL_WRAPPER(MSVCP_failure_dtor, 4)
647 void __thiscall MSVCP_failure_dtor(failure *this)
648 {
649     TRACE("%p\n", this);
650     MSVCP_runtime_error_dtor(this);
651 }
652
653 DEFINE_THISCALL_WRAPPER(MSVCP_failure_vector_dtor, 8)
654 void* __thiscall MSVCP_failure_vector_dtor(
655         failure *this, unsigned int flags)
656 {
657     TRACE("%p %x\n", this, flags);
658     return MSVCP_runtime_error_vector_dtor(this, flags);
659 }
660
661 DEFINE_THISCALL_WRAPPER(MSVCP_failure_what, 4)
662 const char* __thiscall MSVCP_failure_what(failure *this)
663 {
664     TRACE("%p\n", this);
665     return MSVCP_runtime_error_what(this);
666 }
667
668 DEFINE_RTTI_DATA(failure, 0, 1, &runtime_error_rtti_base_descriptor, &exception_rtti_base_descriptor, NULL, ".?AVfailure@std@@");
669
670 static const cxx_type_info failure_cxx_type_info = {
671     0,
672     &failure_type_info,
673     { 0, -1, 0 },
674     sizeof(failure),
675     (cxx_copy_ctor)THISCALL(MSVCP_failure_copy_ctor)
676 };
677
678 static const cxx_type_info_table failure_cxx_type_table = {
679     3,
680     {
681         &failure_cxx_type_info,
682         &runtime_error_cxx_type_info,
683         &exception_cxx_type_info
684     }
685 };
686
687 static const cxx_exception_type failure_cxx_type = {
688     0,
689     (cxx_copy_ctor)THISCALL(MSVCP_failure_dtor),
690     NULL,
691     &failure_cxx_type_table
692 };
693
694 #ifndef __GNUC__
695 void __asm_dummy_vtables(void) {
696 #endif
697     __ASM_VTABLE(type_info, "");
698     __ASM_VTABLE(exception, VTABLE_ADD_FUNC(MSVCP_what_exception));
699     __ASM_VTABLE(bad_alloc, VTABLE_ADD_FUNC(MSVCP_what_exception));
700     __ASM_VTABLE(logic_error, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
701     __ASM_VTABLE(length_error, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
702     __ASM_VTABLE(out_of_range, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
703     __ASM_VTABLE(invalid_argument, VTABLE_ADD_FUNC(MSVCP_logic_error_what));
704     __ASM_VTABLE(runtime_error, VTABLE_ADD_FUNC(MSVCP_runtime_error_what));
705     __ASM_VTABLE(failure, VTABLE_ADD_FUNC(MSVCP_failure_what));
706 #ifndef __GNUC__
707 }
708 #endif
709
710 /* Internal: throws selected exception */
711 void throw_exception(exception_type et, const char *str)
712 {
713     const char *addr = str;
714
715     switch(et) {
716     case EXCEPTION_RERAISE:
717         _CxxThrowException(NULL, NULL);
718     case EXCEPTION: {
719         exception e;
720         MSVCP_exception_ctor(&e, &addr);
721         _CxxThrowException(&e, &exception_cxx_type);
722     }
723     case EXCEPTION_BAD_ALLOC: {
724         bad_alloc e;
725         MSVCP_bad_alloc_ctor(&e, &addr);
726         _CxxThrowException(&e, &bad_alloc_cxx_type);
727     }
728     case EXCEPTION_LOGIC_ERROR: {
729         logic_error e;
730         MSVCP_logic_error_ctor(&e, &addr);
731         _CxxThrowException((exception*)&e, &logic_error_cxx_type);
732     }
733     case EXCEPTION_LENGTH_ERROR: {
734         length_error e;
735         MSVCP_length_error_ctor(&e, &addr);
736         _CxxThrowException((exception*)&e, &length_error_cxx_type);
737     }
738     case EXCEPTION_OUT_OF_RANGE: {
739         out_of_range e;
740         MSVCP_out_of_range_ctor(&e, &addr);
741         _CxxThrowException((exception*)&e, &out_of_range_cxx_type);
742     }
743     case EXCEPTION_INVALID_ARGUMENT: {
744         invalid_argument e;
745         MSVCP_invalid_argument_ctor(&e, &addr);
746         _CxxThrowException((exception*)&e, &invalid_argument_cxx_type);
747     }
748     case EXCEPTION_RUNTIME_ERROR: {
749         runtime_error e;
750         MSVCP_runtime_error_ctor(&e, &addr);
751         _CxxThrowException((exception*)&e, &runtime_error_cxx_type);
752     }
753     case EXCEPTION_FAILURE: {
754         failure e;
755         MSVCP_failure_ctor(&e, &addr);
756         _CxxThrowException((exception*)&e, &failure_cxx_type);
757     }
758     }
759 }