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