include: Specify calling convention explicitly in idl files where needed.
[wine/hramrach.git] / dlls / msvcp90 / exception.c
blobcef4980b99b7f360aa8b39791cd1246e06ac410f
1 /*
2 * Copyright 2010 Piotr Caban for CodeWeavers
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.
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.
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
19 #include "config.h"
21 #include <stdarg.h>
23 #include "msvcp90.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcp90);
30 /* dlls/msvcrt/cppexcept.h */
31 typedef void (*cxx_copy_ctor)(void);
33 /* complete information about a C++ type */
34 typedef struct __cxx_type_info
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
45 /* table of C++ types that apply for a given object */
46 typedef struct __cxx_type_info_table
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;
52 /* type information for an exception object */
53 typedef struct __cxx_exception_type
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;
61 void CDECL _CxxThrowException(exception*,const cxx_exception_type*);
63 /* vtables */
65 #ifdef _WIN64
67 #define __ASM_VTABLE(name,funcs) \
68 __asm__(".data\n" \
69 "\t.align 8\n" \
70 "\t.quad " __ASM_NAME(#name "_rtti") "\n" \
71 "\t.globl " __ASM_NAME("MSVCP_" #name "_vtable") "\n" \
72 __ASM_NAME("MSVCP_" #name "_vtable") ":\n" \
73 "\t.quad " THISCALL_NAME(MSVCP_ ## name ## _vector_dtor) "\n" \
74 funcs "\n\t.text");
76 #define __ASM_EXCEPTION_VTABLE(name) \
77 __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCP_what_exception) )
79 #define __ASM_EXCEPTION_STRING_VTABLE(name) \
80 __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCP_logic_error_what) )
82 #else
84 #define __ASM_VTABLE(name,funcs) \
85 __asm__(".data\n" \
86 "\t.align 4\n" \
87 "\t.long " __ASM_NAME(#name "_rtti") "\n" \
88 "\t.globl " __ASM_NAME("MSVCP_" #name "_vtable") "\n" \
89 __ASM_NAME("MSVCP_" #name "_vtable") ":\n" \
90 "\t.long " THISCALL_NAME(MSVCP_ ## name ## _vector_dtor) "\n" \
91 funcs "\n\t.text");
93 #define __ASM_EXCEPTION_VTABLE(name) \
94 __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCP_what_exception) )
96 #define __ASM_EXCEPTION_STRING_VTABLE(name) \
97 __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCP_logic_error_what) )
99 #endif /* _WIN64 */
101 extern const vtable_ptr MSVCP_bad_alloc_vtable;
102 extern const vtable_ptr MSVCP_logic_error_vtable;
103 extern const vtable_ptr MSVCP_length_error_vtable;
104 extern const vtable_ptr MSVCP_out_of_range_vtable;
105 extern const vtable_ptr MSVCP_invalid_argument_vtable;
107 /* exception class data */
108 static type_info exception_type_info = {
109 NULL, /* set by set_exception_vtable */
110 NULL,
111 ".?AVexception@std@@"
114 DEFINE_THISCALL_WRAPPER(MSVCP_exception_ctor, 8)
115 exception* __thiscall MSVCP_exception_ctor(exception *this, const char **name)
117 TRACE("(%p %s)\n", this, *name);
119 this->vtable = exception_type_info.vtable;
120 if(*name) {
121 unsigned int name_len = strlen(*name) + 1;
122 this->name = malloc(name_len);
123 memcpy(this->name, *name, name_len);
124 this->do_free = TRUE;
125 } else {
126 this->name = NULL;
127 this->do_free = FALSE;
129 return this;
132 DEFINE_THISCALL_WRAPPER(MSVCP_exception_copy_ctor,8)
133 exception* __thiscall MSVCP_exception_copy_ctor(exception *this, const exception *rhs)
135 TRACE("(%p,%p)\n", this, rhs);
137 if(!rhs->do_free) {
138 this->vtable = exception_type_info.vtable;
139 this->name = rhs->name;
140 this->do_free = FALSE;
141 } else
142 MSVCP_exception_ctor(this, (const char**)&rhs->name);
143 TRACE("name = %s\n", this->name);
144 return this;
147 DEFINE_THISCALL_WRAPPER(MSVCP_exception_dtor,4)
148 void __thiscall MSVCP_exception_dtor(exception *this)
150 TRACE("(%p)\n", this);
151 this->vtable = exception_type_info.vtable;
152 if(this->do_free)
153 free(this->name);
156 static const rtti_base_descriptor exception_rtti_base_descriptor = {
157 &exception_type_info,
159 { 0, -1, 0 },
163 static const cxx_type_info exception_cxx_type_info = {
165 &exception_type_info,
166 { 0, -1, 0 },
167 sizeof(exception),
168 (cxx_copy_ctor)THISCALL(MSVCP_exception_dtor)
171 static const cxx_type_info_table exception_cxx_type_table = {
174 &exception_cxx_type_info,
175 NULL,
176 NULL
180 static const cxx_exception_type exception_cxx_type = {
182 (cxx_copy_ctor)THISCALL(MSVCP_exception_copy_ctor),
183 NULL,
184 &exception_cxx_type_table
187 void set_exception_vtable(void)
189 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
190 exception_type_info.vtable = (void*)GetProcAddress(hmod, "??_7exception@@6B@");
193 /* bad_alloc class data */
194 typedef exception bad_alloc;
196 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_ctor, 8)
197 bad_alloc* __thiscall MSVCP_bad_alloc_ctor(bad_alloc *this, const char **name)
199 TRACE("%p %s\n", this, *name);
200 MSVCP_exception_ctor(this, name);
201 this->vtable = &MSVCP_bad_alloc_vtable;
202 return this;
205 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_copy_ctor, 8)
206 bad_alloc* __thiscall MSVCP_bad_alloc_copy_ctor(bad_alloc *this, const bad_alloc *rhs)
208 TRACE("%p %p\n", this, rhs);
209 MSVCP_exception_copy_ctor(this, rhs);
210 this->vtable = &MSVCP_bad_alloc_vtable;
211 return this;
214 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_dtor, 4)
215 void __thiscall MSVCP_bad_alloc_dtor(bad_alloc *this)
217 TRACE("%p\n", this);
218 MSVCP_exception_dtor(this);
221 DEFINE_THISCALL_WRAPPER(MSVCP_bad_alloc_vector_dtor, 8)
222 void * __thiscall MSVCP_bad_alloc_vector_dtor(bad_alloc *this, unsigned int flags)
224 TRACE("%p %x\n", this, flags);
225 if(flags & 2) {
226 /* we have an array, with the number of elements stored before the first object */
227 int i, *ptr = (int *)this-1;
229 for(i=*ptr-1; i>=0; i--)
230 MSVCP_bad_alloc_dtor(this+i);
231 MSVCRT_operator_delete(ptr);
232 } else {
233 MSVCP_bad_alloc_dtor(this);
234 if(flags & 1)
235 MSVCRT_operator_delete(this);
238 return this;
241 DEFINE_THISCALL_WRAPPER(MSVCP_what_exception,4)
242 const char* __thiscall MSVCP_what_exception(exception * this)
244 TRACE("(%p) returning %s\n", this, this->name);
245 return this->name ? this->name : "Unknown exception";
248 static const type_info bad_alloc_type_info = {
249 &MSVCP_bad_alloc_vtable,
250 NULL,
251 ".?AVbad_alloc@std@@"
254 static const rtti_base_descriptor bad_alloc_rtti_base_descriptor = {
255 &bad_alloc_type_info,
257 { 0, -1, 0 },
261 static const rtti_base_array bad_alloc_rtti_base_array = {
263 &bad_alloc_rtti_base_descriptor,
264 &exception_rtti_base_descriptor,
265 NULL
269 static const rtti_object_hierarchy bad_alloc_type_hierarchy = {
273 &bad_alloc_rtti_base_array
276 const rtti_object_locator bad_alloc_rtti = {
280 &bad_alloc_type_info,
281 &bad_alloc_type_hierarchy
284 static const cxx_type_info bad_alloc_cxx_type_info = {
286 &bad_alloc_type_info,
287 { 0, -1, 0 },
288 sizeof(bad_alloc),
289 (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_copy_ctor)
292 static const cxx_type_info_table bad_alloc_cxx_type_table = {
295 &bad_alloc_cxx_type_info,
296 &exception_cxx_type_info,
297 NULL
301 static const cxx_exception_type bad_alloc_cxx_type = {
303 (cxx_copy_ctor)THISCALL(MSVCP_bad_alloc_dtor),
304 NULL,
305 &bad_alloc_cxx_type_table
308 /* logic_error class data */
309 typedef struct _logic_error {
310 exception e;
311 basic_string_char str;
312 } logic_error;
314 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_ctor, 8)
315 logic_error* __thiscall MSVCP_logic_error_ctor(
316 logic_error *this, const char **name)
318 TRACE("%p %s\n", this, *name);
319 this->e.vtable = &MSVCP_logic_error_vtable;
320 this->e.name = NULL;
321 this->e.do_free = FALSE;
322 MSVCP_basic_string_char_ctor_cstr(&this->str, *name);
323 return this;
326 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_copy_ctor, 8)
327 logic_error* __thiscall MSVCP_logic_error_copy_ctor(
328 logic_error *this, logic_error *rhs)
330 TRACE("%p %p\n", this, rhs);
331 MSVCP_exception_copy_ctor(&this->e, &rhs->e);
332 MSVCP_basic_string_char_copy_ctor(&this->str, &rhs->str);
333 this->e.vtable = &MSVCP_logic_error_vtable;
334 return this;
337 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_dtor, 4)
338 void __thiscall MSVCP_logic_error_dtor(logic_error *this)
340 TRACE("%p\n", this);
341 MSVCP_exception_dtor(&this->e);
342 MSVCP_basic_string_char_dtor(&this->str);
345 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_vector_dtor, 8)
346 void* __thiscall MSVCP_logic_error_vector_dtor(
347 logic_error *this, unsigned int flags)
349 TRACE("%p %x\n", this, flags);
350 if(flags & 2) {
351 /* we have an array, with the number of elements stored before the first object */
352 int i, *ptr = (int *)this-1;
354 for(i=*ptr-1; i>=0; i--)
355 MSVCP_logic_error_dtor(this+i);
356 MSVCRT_operator_delete(ptr);
357 } else {
358 MSVCP_logic_error_dtor(this);
359 if(flags & 1)
360 MSVCRT_operator_delete(this);
363 return this;
366 DEFINE_THISCALL_WRAPPER(MSVCP_logic_error_what, 4)
367 const char* __thiscall MSVCP_logic_error_what(logic_error *this)
369 TRACE("%p\n", this);
370 return MSVCP_basic_string_char_c_str(&this->str);
373 static const type_info logic_error_type_info = {
374 &MSVCP_logic_error_vtable,
375 NULL,
376 ".?AVlogic_error@std@@"
379 static const rtti_base_descriptor logic_error_rtti_base_descriptor = {
380 &logic_error_type_info,
382 { 0, -1, 0 },
386 static const rtti_base_array logic_error_rtti_base_array = {
388 &logic_error_rtti_base_descriptor,
389 &exception_rtti_base_descriptor,
390 NULL
394 static const rtti_object_hierarchy logic_error_type_hierarchy = {
398 &logic_error_rtti_base_array
401 const rtti_object_locator logic_error_rtti = {
405 &logic_error_type_info,
406 &logic_error_type_hierarchy
409 static const cxx_type_info logic_error_cxx_type_info = {
411 &logic_error_type_info,
412 { 0, -1, 0 },
413 sizeof(logic_error),
414 (cxx_copy_ctor)THISCALL(MSVCP_logic_error_copy_ctor)
417 static const cxx_type_info_table logic_error_cxx_type_table = {
420 &logic_error_cxx_type_info,
421 &exception_cxx_type_info,
422 NULL
426 static const cxx_exception_type logic_error_cxx_type = {
428 (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
429 NULL,
430 &logic_error_cxx_type_table
433 /* length_error class data */
434 typedef logic_error length_error;
436 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_ctor, 8)
437 length_error* __thiscall MSVCP_length_error_ctor(
438 length_error *this, const char **name)
440 TRACE("%p %s\n", this, *name);
441 MSVCP_logic_error_ctor(this, name);
442 this->e.vtable = &MSVCP_length_error_vtable;
443 return this;
446 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_copy_ctor, 8)
447 length_error* __thiscall MSVCP_length_error_copy_ctor(
448 length_error *this, length_error *rhs)
450 TRACE("%p %p\n", this, rhs);
451 MSVCP_logic_error_copy_ctor(this, rhs);
452 this->e.vtable = &MSVCP_length_error_vtable;
453 return this;
456 DEFINE_THISCALL_WRAPPER(MSVCP_length_error_vector_dtor, 8)
457 void* __thiscall MSVCP_length_error_vector_dtor(
458 length_error *this, unsigned int flags)
460 TRACE("%p %x\n", this, flags);
461 return MSVCP_logic_error_vector_dtor(this, flags);
464 static const type_info length_error_type_info = {
465 &MSVCP_length_error_vtable,
466 NULL,
467 ".?AVlength_error@std@@"
470 static const rtti_base_descriptor length_error_rtti_base_descriptor = {
471 &length_error_type_info,
473 { 0, -1, 0 },
477 static const rtti_base_array length_error_rtti_base_array = {
479 &length_error_rtti_base_descriptor,
480 &logic_error_rtti_base_descriptor,
481 &exception_rtti_base_descriptor
485 static const rtti_object_hierarchy length_error_type_hierarchy = {
489 &length_error_rtti_base_array
492 const rtti_object_locator length_error_rtti = {
496 &length_error_type_info,
497 &length_error_type_hierarchy
500 static const cxx_type_info length_error_cxx_type_info = {
502 &length_error_type_info,
503 { 0, -1, 0 },
504 sizeof(length_error),
505 (cxx_copy_ctor)THISCALL(MSVCP_length_error_copy_ctor)
508 static const cxx_type_info_table length_error_cxx_type_table = {
511 &length_error_cxx_type_info,
512 &logic_error_cxx_type_info,
513 &exception_cxx_type_info
517 static const cxx_exception_type length_error_cxx_type = {
519 (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
520 NULL,
521 &length_error_cxx_type_table
524 /* out_of_range class data */
525 typedef logic_error out_of_range;
527 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_ctor, 8)
528 out_of_range* __thiscall MSVCP_out_of_range_ctor(
529 out_of_range *this, const char **name)
531 TRACE("%p %s\n", this, *name);
532 MSVCP_logic_error_ctor(this, name);
533 this->e.vtable = &MSVCP_out_of_range_vtable;
534 return this;
537 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_copy_ctor, 8)
538 out_of_range* __thiscall MSVCP_out_of_range_copy_ctor(
539 out_of_range *this, out_of_range *rhs)
541 TRACE("%p %p\n", this, rhs);
542 MSVCP_logic_error_copy_ctor(this, rhs);
543 this->e.vtable = &MSVCP_out_of_range_vtable;
544 return this;
547 DEFINE_THISCALL_WRAPPER(MSVCP_out_of_range_vector_dtor, 8)
548 void* __thiscall MSVCP_out_of_range_vector_dtor(
549 out_of_range *this, unsigned int flags)
551 TRACE("%p %x\n", this, flags);
552 return MSVCP_logic_error_vector_dtor(this, flags);
555 static const type_info out_of_range_type_info = {
556 &MSVCP_out_of_range_vtable,
557 NULL,
558 ".?AVout_of_range@std@@"
561 static const rtti_base_descriptor out_of_range_rtti_base_descriptor = {
562 &out_of_range_type_info,
564 { 0, -1, 0 },
568 static const rtti_base_array out_of_range_rtti_base_array = {
570 &out_of_range_rtti_base_descriptor,
571 &logic_error_rtti_base_descriptor,
572 &exception_rtti_base_descriptor
576 static const rtti_object_hierarchy out_of_range_type_hierarchy = {
580 &out_of_range_rtti_base_array
583 const rtti_object_locator out_of_range_rtti = {
587 &out_of_range_type_info,
588 &out_of_range_type_hierarchy
591 static const cxx_type_info out_of_range_cxx_type_info = {
593 &out_of_range_type_info,
594 { 0, -1, 0 },
595 sizeof(out_of_range),
596 (cxx_copy_ctor)THISCALL(MSVCP_out_of_range_copy_ctor)
599 static const cxx_type_info_table out_of_range_cxx_type_table = {
602 &out_of_range_cxx_type_info,
603 &logic_error_cxx_type_info,
604 &exception_cxx_type_info
608 static const cxx_exception_type out_of_range_cxx_type = {
610 (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
611 NULL,
612 &out_of_range_cxx_type_table
615 /* invalid_argument class data */
616 typedef logic_error invalid_argument;
618 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_ctor, 8)
619 invalid_argument* __thiscall MSVCP_invalid_argument_ctor(
620 invalid_argument *this, const char **name)
622 TRACE("%p %s\n", this, *name);
623 MSVCP_logic_error_ctor(this, name);
624 this->e.vtable = &MSVCP_invalid_argument_vtable;
625 return this;
628 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_copy_ctor, 8)
629 invalid_argument* __thiscall MSVCP_invalid_argument_copy_ctor(
630 invalid_argument *this, invalid_argument *rhs)
632 TRACE("%p %p\n", this, rhs);
633 MSVCP_logic_error_copy_ctor(this, rhs);
634 this->e.vtable = &MSVCP_invalid_argument_vtable;
635 return this;
638 DEFINE_THISCALL_WRAPPER(MSVCP_invalid_argument_vector_dtor, 8)
639 void* __thiscall MSVCP_invalid_argument_vector_dtor(
640 invalid_argument *this, unsigned int flags)
642 TRACE("%p %x\n", this, flags);
643 return MSVCP_logic_error_vector_dtor(this, flags);
646 static const type_info invalid_argument_type_info = {
647 &MSVCP_invalid_argument_vtable,
648 NULL,
649 ".?AVinvalid_argument@std@@"
652 static const rtti_base_descriptor invalid_argument_rtti_base_descriptor = {
653 &invalid_argument_type_info,
655 { 0, -1, 0 },
659 static const rtti_base_array invalid_argument_rtti_base_array = {
661 &invalid_argument_rtti_base_descriptor,
662 &logic_error_rtti_base_descriptor,
663 &exception_rtti_base_descriptor
667 static const rtti_object_hierarchy invalid_argument_type_hierarchy = {
671 &invalid_argument_rtti_base_array
674 const rtti_object_locator invalid_argument_rtti = {
678 &invalid_argument_type_info,
679 &invalid_argument_type_hierarchy
682 static const cxx_type_info invalid_argument_cxx_type_info = {
684 &invalid_argument_type_info,
685 { 0, -1, 0 },
686 sizeof(invalid_argument),
687 (cxx_copy_ctor)THISCALL(MSVCP_invalid_argument_copy_ctor)
690 static const cxx_type_info_table invalid_argument_cxx_type_table = {
693 &invalid_argument_cxx_type_info,
694 &logic_error_cxx_type_info,
695 &exception_cxx_type_info
699 static const cxx_exception_type invalid_argument_cxx_type = {
701 (cxx_copy_ctor)THISCALL(MSVCP_logic_error_dtor),
702 NULL,
703 &invalid_argument_cxx_type_table
706 #ifndef __GNUC__
707 void __asm_dummy_vtables(void) {
708 #endif
709 __ASM_EXCEPTION_VTABLE(bad_alloc)
710 __ASM_EXCEPTION_STRING_VTABLE(logic_error)
711 __ASM_EXCEPTION_STRING_VTABLE(length_error)
712 __ASM_EXCEPTION_STRING_VTABLE(out_of_range)
713 __ASM_EXCEPTION_STRING_VTABLE(invalid_argument)
714 #ifndef __GNUC__
716 #endif
718 /* Internal: throws selected exception */
719 void throw_exception(exception_type et, const char *str)
721 const char *addr = str;
723 switch(et) {
724 case EXCEPTION: {
725 exception e;
726 MSVCP_exception_ctor(&e, &addr);
727 _CxxThrowException(&e, &exception_cxx_type);
728 return;
730 case EXCEPTION_BAD_ALLOC: {
731 bad_alloc e;
732 MSVCP_bad_alloc_ctor(&e, &addr);
733 _CxxThrowException(&e, &bad_alloc_cxx_type);
734 return;
736 case EXCEPTION_LOGIC_ERROR: {
737 logic_error e;
738 MSVCP_logic_error_ctor(&e, &addr);
739 _CxxThrowException((exception*)&e, &logic_error_cxx_type);
740 return;
742 case EXCEPTION_LENGTH_ERROR: {
743 length_error e;
744 MSVCP_length_error_ctor(&e, &addr);
745 _CxxThrowException((exception*)&e, &length_error_cxx_type);
746 return;
748 case EXCEPTION_OUT_OF_RANGE: {
749 out_of_range e;
750 MSVCP_out_of_range_ctor(&e, &addr);
751 _CxxThrowException((exception*)&e, &out_of_range_cxx_type);
753 case EXCEPTION_INVALID_ARGUMENT: {
754 invalid_argument e;
755 MSVCP_invalid_argument_ctor(&e, &addr);
756 _CxxThrowException((exception*)&e, &invalid_argument_cxx_type);