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