2 * msvcrt.dll C++ objects
4 * Copyright 2000 Jon Griffiths
5 * Copyright 2003, 2004 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
29 #include "wine/exception.h"
30 #include "wine/debug.h"
32 #include "cppexcept.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
38 typedef exception bad_cast;
39 typedef exception bad_typeid;
40 typedef exception __non_rtti_object;
44 /* x86_64 RTTI structures */
47 unsigned int type_descriptor;
49 this_ptr_offsets offsets;
50 unsigned int attributes;
51 } rtti_base_descriptor_x64;
56 } rtti_base_array_x64;
60 unsigned int signature;
61 unsigned int attributes;
63 unsigned int base_classes;
64 } rtti_object_hierarchy_x64;
68 unsigned int signature;
69 int base_class_offset;
71 unsigned int type_descriptor;
72 unsigned int type_hierarchy;
73 unsigned int object_locator; /* not present if signature == 0 */
74 } rtti_object_locator_x64;
78 extern const vtable_ptr MSVCRT_exception_vtable;
79 extern const vtable_ptr MSVCRT_bad_typeid_vtable;
80 extern const vtable_ptr MSVCRT_bad_cast_vtable;
81 extern const vtable_ptr MSVCRT___non_rtti_object_vtable;
82 extern const vtable_ptr MSVCRT_type_info_vtable;
84 /* get the vtable pointer for a C++ object */
85 static inline const vtable_ptr *get_vtable( void *obj )
87 return *(const vtable_ptr **)obj;
90 static inline const rtti_object_locator *get_obj_locator( void *cppobj )
92 const vtable_ptr *vtable = get_vtable( cppobj );
93 return (const rtti_object_locator *)vtable[-1];
96 static void dump_obj_locator( const rtti_object_locator *ptr )
99 const rtti_object_hierarchy *h = ptr->type_hierarchy;
101 TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
102 ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
103 ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy );
104 TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
105 h->signature, h->attributes, h->array_len, h->base_classes );
106 for (i = 0; i < h->array_len; i++)
108 TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
109 h->base_classes->bases[i],
110 h->base_classes->bases[i]->num_base_classes,
111 h->base_classes->bases[i]->offsets.this_offset,
112 h->base_classes->bases[i]->offsets.vbase_descr,
113 h->base_classes->bases[i]->offsets.vbase_offset,
114 h->base_classes->bases[i]->attributes,
115 h->base_classes->bases[i]->type_descriptor,
116 dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) );
120 /* Internal common ctor for exception */
121 static void EXCEPTION_ctor(exception *_this, const char** name)
123 _this->vtable = &MSVCRT_exception_vtable;
126 unsigned int name_len = strlen(*name) + 1;
127 _this->name = MSVCRT_malloc(name_len);
128 memcpy(_this->name, *name, name_len);
129 _this->do_free = TRUE;
134 _this->do_free = FALSE;
138 /******************************************************************
139 * ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
141 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
142 exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name)
144 TRACE("(%p,%s)\n", _this, *name);
145 EXCEPTION_ctor(_this, name);
149 /******************************************************************
150 * ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
152 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
153 exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
155 TRACE("(%p,%s)\n", _this, *name);
156 _this->vtable = &MSVCRT_exception_vtable;
158 _this->do_free = FALSE;
162 /******************************************************************
163 * ??0exception@@QAE@ABV0@@Z (MSVCRT.@)
165 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
166 exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
168 TRACE("(%p,%p)\n", _this, rhs);
172 _this->vtable = &MSVCRT_exception_vtable;
173 _this->name = rhs->name;
174 _this->do_free = FALSE;
177 EXCEPTION_ctor(_this, (const char**)&rhs->name);
178 TRACE("name = %s\n", _this->name);
182 /******************************************************************
183 * ??0exception@@QAE@XZ (MSVCRT.@)
185 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
186 exception * __thiscall MSVCRT_exception_default_ctor(exception * _this)
188 static const char* empty = NULL;
190 TRACE("(%p)\n", _this);
191 EXCEPTION_ctor(_this, &empty);
195 /******************************************************************
196 * ??1exception@@UAE@XZ (MSVCRT.@)
198 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
199 void __thiscall MSVCRT_exception_dtor(exception * _this)
201 TRACE("(%p)\n", _this);
202 _this->vtable = &MSVCRT_exception_vtable;
203 if (_this->do_free) MSVCRT_free(_this->name);
206 /******************************************************************
207 * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
209 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
210 exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
212 TRACE("(%p %p)\n", _this, rhs);
215 MSVCRT_exception_dtor(_this);
216 MSVCRT_exception_copy_ctor(_this, rhs);
218 TRACE("name = %s\n", _this->name);
222 /******************************************************************
223 * ??_Eexception@@UAEPAXI@Z (MSVCRT.@)
225 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
226 void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
228 TRACE("(%p %x)\n", _this, flags);
231 /* we have an array, with the number of elements stored before the first object */
232 INT_PTR i, *ptr = (INT_PTR *)_this - 1;
234 for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
235 MSVCRT_operator_delete(ptr);
239 MSVCRT_exception_dtor(_this);
240 if (flags & 1) MSVCRT_operator_delete(_this);
245 /******************************************************************
246 * ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
248 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
249 void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
251 TRACE("(%p %x)\n", _this, flags);
252 MSVCRT_exception_dtor(_this);
253 if (flags & 1) MSVCRT_operator_delete(_this);
257 /******************************************************************
258 * ?what@exception@@UBEPBDXZ (MSVCRT.@)
260 DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
261 const char * __thiscall MSVCRT_what_exception(exception * _this)
263 TRACE("(%p) returning %s\n", _this, _this->name);
264 return _this->name ? _this->name : "Unknown exception";
267 /******************************************************************
268 * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
270 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
271 bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
273 TRACE("(%p %p)\n", _this, rhs);
274 MSVCRT_exception_copy_ctor(_this, rhs);
275 _this->vtable = &MSVCRT_bad_typeid_vtable;
279 /******************************************************************
280 * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
282 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
283 bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
285 TRACE("(%p %s)\n", _this, name);
286 EXCEPTION_ctor(_this, &name);
287 _this->vtable = &MSVCRT_bad_typeid_vtable;
291 /******************************************************************
292 * ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
294 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
295 bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
297 return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
300 /******************************************************************
301 * ??1bad_typeid@@UAE@XZ (MSVCRT.@)
303 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
304 void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
306 TRACE("(%p)\n", _this);
307 MSVCRT_exception_dtor(_this);
310 /******************************************************************
311 * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
313 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
314 bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
316 TRACE("(%p %p)\n", _this, rhs);
317 MSVCRT_exception_opequals(_this, rhs);
321 /******************************************************************
322 * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
324 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
325 void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
327 TRACE("(%p %x)\n", _this, flags);
330 /* we have an array, with the number of elements stored before the first object */
331 INT_PTR i, *ptr = (INT_PTR *)_this - 1;
333 for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
334 MSVCRT_operator_delete(ptr);
338 MSVCRT_bad_typeid_dtor(_this);
339 if (flags & 1) MSVCRT_operator_delete(_this);
344 /******************************************************************
345 * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
347 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
348 void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
350 TRACE("(%p %x)\n", _this, flags);
351 MSVCRT_bad_typeid_dtor(_this);
352 if (flags & 1) MSVCRT_operator_delete(_this);
356 /******************************************************************
357 * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
359 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
360 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
361 const __non_rtti_object * rhs)
363 TRACE("(%p %p)\n", _this, rhs);
364 MSVCRT_bad_typeid_copy_ctor(_this, rhs);
365 _this->vtable = &MSVCRT___non_rtti_object_vtable;
369 /******************************************************************
370 * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
372 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
373 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
376 TRACE("(%p %s)\n", _this, name);
377 EXCEPTION_ctor(_this, &name);
378 _this->vtable = &MSVCRT___non_rtti_object_vtable;
382 /******************************************************************
383 * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
385 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
386 void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
388 TRACE("(%p)\n", _this);
389 MSVCRT_bad_typeid_dtor(_this);
392 /******************************************************************
393 * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
395 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
396 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
397 const __non_rtti_object *rhs)
399 TRACE("(%p %p)\n", _this, rhs);
400 MSVCRT_bad_typeid_opequals(_this, rhs);
404 /******************************************************************
405 * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
407 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
408 void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
410 TRACE("(%p %x)\n", _this, flags);
413 /* we have an array, with the number of elements stored before the first object */
414 INT_PTR i, *ptr = (INT_PTR *)_this - 1;
416 for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
417 MSVCRT_operator_delete(ptr);
421 MSVCRT___non_rtti_object_dtor(_this);
422 if (flags & 1) MSVCRT_operator_delete(_this);
427 /******************************************************************
428 * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
430 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
431 void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
433 TRACE("(%p %x)\n", _this, flags);
434 MSVCRT___non_rtti_object_dtor(_this);
435 if (flags & 1) MSVCRT_operator_delete(_this);
439 /******************************************************************
440 * ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
441 * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
443 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
444 bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
446 TRACE("(%p %s)\n", _this, *name);
447 EXCEPTION_ctor(_this, name);
448 _this->vtable = &MSVCRT_bad_cast_vtable;
452 /******************************************************************
453 * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
455 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
456 bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
458 TRACE("(%p %p)\n", _this, rhs);
459 MSVCRT_exception_copy_ctor(_this, rhs);
460 _this->vtable = &MSVCRT_bad_cast_vtable;
464 /******************************************************************
465 * ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
467 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
468 bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
470 TRACE("(%p %s)\n", _this, name);
471 EXCEPTION_ctor(_this, &name);
472 _this->vtable = &MSVCRT_bad_cast_vtable;
476 /******************************************************************
477 * ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
479 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
480 bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
482 return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
485 /******************************************************************
486 * ??1bad_cast@@UAE@XZ (MSVCRT.@)
488 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
489 void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this)
491 TRACE("(%p)\n", _this);
492 MSVCRT_exception_dtor(_this);
495 /******************************************************************
496 * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
498 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
499 bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
501 TRACE("(%p %p)\n", _this, rhs);
502 MSVCRT_exception_opequals(_this, rhs);
506 /******************************************************************
507 * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
509 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
510 void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
512 TRACE("(%p %x)\n", _this, flags);
515 /* we have an array, with the number of elements stored before the first object */
516 INT_PTR i, *ptr = (INT_PTR *)_this - 1;
518 for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
519 MSVCRT_operator_delete(ptr);
523 MSVCRT_bad_cast_dtor(_this);
524 if (flags & 1) MSVCRT_operator_delete(_this);
529 /******************************************************************
530 * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
532 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
533 void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
535 TRACE("(%p %x)\n", _this, flags);
536 MSVCRT_bad_cast_dtor(_this);
537 if (flags & 1) MSVCRT_operator_delete(_this);
541 /******************************************************************
542 * ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
544 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
545 int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
547 int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
548 TRACE("(%p %p) returning %d\n", _this, rhs, ret);
552 /******************************************************************
553 * ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
555 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
556 int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
558 int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
559 TRACE("(%p %p) returning %d\n", _this, rhs, ret);
563 /******************************************************************
564 * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
566 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
567 int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
569 int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
570 TRACE("(%p %p) returning %d\n", _this, rhs, ret);
574 /******************************************************************
575 * ??1type_info@@UAE@XZ (MSVCRT.@)
577 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
578 void __thiscall MSVCRT_type_info_dtor(type_info * _this)
580 TRACE("(%p)\n", _this);
581 MSVCRT_free(_this->name);
584 /******************************************************************
585 * ?name@type_info@@QBEPBDXZ (MSVCRT.@)
587 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
588 const char * __thiscall MSVCRT_type_info_name(type_info * _this)
592 /* Create and set the demangled name */
593 /* Note: mangled name in type_info struct always starts with a '.', while
594 * it isn't valid for mangled name.
595 * Is this '.' really part of the mangled name, or has it some other meaning ?
597 char* name = __unDName(0, _this->mangled + 1, 0,
598 MSVCRT_malloc, MSVCRT_free, 0x2800);
601 unsigned int len = strlen(name);
603 /* It seems _unDName may leave blanks at the end of the demangled name */
604 while (len && name[--len] == ' ')
607 if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
609 /* Another thread set this member since we checked above - use it */
614 TRACE("(%p) returning %s\n", _this, _this->name);
618 /******************************************************************
619 * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
621 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
622 const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this)
624 TRACE("(%p) returning %s\n", _this, _this->mangled);
625 return _this->mangled;
629 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
630 void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
632 TRACE("(%p %x)\n", _this, flags);
635 /* we have an array, with the number of elements stored before the first object */
636 INT_PTR i, *ptr = (INT_PTR *)_this - 1;
638 for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
639 MSVCRT_operator_delete(ptr);
643 MSVCRT_type_info_dtor(_this);
644 if (flags & 1) MSVCRT_operator_delete(_this);
650 void __asm_dummy_vtables(void) {
653 __ASM_VTABLE(type_info,
654 VTABLE_ADD_FUNC(MSVCRT_type_info_vector_dtor));
655 __ASM_VTABLE(exception,
656 VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
657 VTABLE_ADD_FUNC(MSVCRT_what_exception));
658 __ASM_VTABLE(bad_typeid,
659 VTABLE_ADD_FUNC(MSVCRT_bad_typeid_vector_dtor)
660 VTABLE_ADD_FUNC(MSVCRT_what_exception));
661 __ASM_VTABLE(bad_cast,
662 VTABLE_ADD_FUNC(MSVCRT_bad_cast_vector_dtor)
663 VTABLE_ADD_FUNC(MSVCRT_what_exception));
664 __ASM_VTABLE(__non_rtti_object,
665 VTABLE_ADD_FUNC(MSVCRT___non_rtti_object_vector_dtor)
666 VTABLE_ADD_FUNC(MSVCRT_what_exception));
672 #define DEFINE_EXCEPTION_TYPE_INFO(name, base_classes, cl1, cl2) \
673 static const cxx_type_info name ## _cxx_type_info = \
676 &name ## _type_info, \
679 (cxx_copy_ctor)THISCALL(MSVCRT_ ## name ## _copy_ctor) \
682 static const cxx_type_info_table name ## _type_info_table = \
686 &name ## _cxx_type_info, \
692 const cxx_exception_type name ## _exception_type = \
695 (void *)THISCALL(MSVCRT_ ## name ## _dtor), \
697 &name ## _type_info_table \
700 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" );
701 DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@@" );
702 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" );
703 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" );
704 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" );
706 DEFINE_EXCEPTION_TYPE_INFO( exception, 0, NULL, NULL );
707 DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL );
708 DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL );
709 DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info );
712 /******************************************************************
713 * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
715 * Install a handler to be called when terminate() is called.
718 * func [I] Handler function to install
721 * The previously installed handler function, if any.
723 MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func)
725 thread_data_t *data = msvcrt_get_thread_data();
726 MSVCRT_terminate_function previous = data->terminate_handler;
727 TRACE("(%p) returning %p\n",func,previous);
728 data->terminate_handler = func;
732 /******************************************************************
733 * _get_terminate (MSVCRT.@)
735 MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void)
737 thread_data_t *data = msvcrt_get_thread_data();
738 TRACE("returning %p\n", data->terminate_handler);
739 return data->terminate_handler;
742 /******************************************************************
743 * ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
745 * Install a handler to be called when unexpected() is called.
748 * func [I] Handler function to install
751 * The previously installed handler function, if any.
753 MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
755 thread_data_t *data = msvcrt_get_thread_data();
756 MSVCRT_unexpected_function previous = data->unexpected_handler;
757 TRACE("(%p) returning %p\n",func,previous);
758 data->unexpected_handler = func;
762 /******************************************************************
763 * _get_unexpected (MSVCRT.@)
765 MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void)
767 thread_data_t *data = msvcrt_get_thread_data();
768 TRACE("returning %p\n", data->unexpected_handler);
769 return data->unexpected_handler;
772 /******************************************************************
773 * ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@)
775 MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
777 thread_data_t *data = msvcrt_get_thread_data();
778 MSVCRT__se_translator_function previous = data->se_translator;
779 TRACE("(%p) returning %p\n",func,previous);
780 data->se_translator = func;
784 /******************************************************************
785 * ?terminate@@YAXXZ (MSVCRT.@)
787 * Default handler for an unhandled exception.
793 * This function does not return. Either control resumes from any
794 * handler installed by calling set_terminate(), or (by default) abort()
797 void CDECL MSVCRT_terminate(void)
799 thread_data_t *data = msvcrt_get_thread_data();
800 if (data->terminate_handler) data->terminate_handler();
804 /******************************************************************
805 * ?unexpected@@YAXXZ (MSVCRT.@)
807 void CDECL MSVCRT_unexpected(void)
809 thread_data_t *data = msvcrt_get_thread_data();
810 if (data->unexpected_handler) data->unexpected_handler();
815 /******************************************************************
816 * __RTtypeid (MSVCRT.@)
818 * Retrieve the Run Time Type Information (RTTI) for a C++ object.
821 * cppobj [I] C++ object to get type information for.
824 * Success: A type_info object describing cppobj.
825 * Failure: If the object to be cast has no RTTI, a __non_rtti_object
826 * exception is thrown. If cppobj is NULL, a bad_typeid exception
827 * is thrown. In either case, this function does not return.
830 * This function is usually called by compiler generated code as a result
831 * of using one of the C++ dynamic cast statements.
834 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
836 const type_info *ret;
841 MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
842 _CxxThrowException( &e, &bad_typeid_exception_type );
848 const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
849 ret = obj_locator->type_descriptor;
854 MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
855 _CxxThrowException( &e, &bad_typeid_exception_type );
864 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
866 const type_info *ret;
871 MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
872 _CxxThrowException( &e, &bad_typeid_exception_type );
878 const rtti_object_locator *obj_locator = (rtti_object_locator*)get_obj_locator( cppobj );
879 /* FIXME: Change signature==0 handling when wine generates correct RTTI data on 64-bit systems */
880 if(obj_locator->signature == 0)
881 ret = obj_locator->type_descriptor;
884 const rtti_object_locator_x64 *obj_locator_x64 = (const rtti_object_locator_x64*)obj_locator;
885 ret = (type_info*)((char*)obj_locator_x64 - obj_locator_x64->object_locator + obj_locator_x64->type_descriptor);
891 MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
892 _CxxThrowException( &e, &bad_typeid_exception_type );
900 /******************************************************************
901 * __RTDynamicCast (MSVCRT.@)
903 * Dynamically cast a C++ object to one of its base classes.
906 * cppobj [I] Any C++ object to cast
907 * unknown [I] Reserved, set to 0
908 * src [I] type_info object describing cppobj
909 * dst [I] type_info object describing the base class to cast to
910 * do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
913 * Success: The address of cppobj, cast to the object described by dst.
914 * Failure: NULL, If the object to be cast has no RTTI, or dst is not a
915 * valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
916 * is thrown and this function does not return.
919 * This function is usually called by compiler generated code as a result
920 * of using one of the C++ dynamic cast statements.
922 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
923 type_info *src, type_info *dst,
928 if (!cppobj) return NULL;
930 TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
931 cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
933 /* To cast an object at runtime:
934 * 1.Find out the true type of the object from the typeinfo at vtable[-1]
935 * 2.Search for the destination type in the class hierarchy
936 * 3.If destination type is found, return base object address + dest offset
937 * Otherwise, fail the cast
939 * FIXME: the unknown parameter doesn't seem to be used for anything
944 const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
945 const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
946 const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
948 if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
951 for (i = 0; i < obj_bases->array_len; i++)
953 const type_info *typ = base_desc[i]->type_descriptor;
955 if (!strcmp(typ->mangled, dst->mangled))
957 /* compute the correct this pointer for that base class */
958 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
959 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
963 /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
964 * to a reference, since references cannot be NULL.
966 if (!ret && do_throw)
968 const char *msg = "Bad dynamic_cast!";
970 MSVCRT_bad_cast_ctor( &e, &msg );
971 _CxxThrowException( &e, &bad_cast_exception_type );
977 MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
978 _CxxThrowException( &e, &bad_typeid_exception_type );
986 /******************************************************************
987 * __RTCastToVoid (MSVCRT.@)
989 * Dynamically cast a C++ object to a void*.
992 * cppobj [I] The C++ object to cast
995 * Success: The base address of the object as a void*.
996 * Failure: NULL, if cppobj is NULL or has no RTTI.
999 * This function is usually called by compiler generated code as a result
1000 * of using one of the C++ dynamic cast statements.
1002 void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
1006 if (!cppobj) return NULL;
1010 const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1011 ret = (char *)cppobj - obj_locator->base_class_offset;
1015 __non_rtti_object e;
1016 MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1017 _CxxThrowException( &e, &bad_typeid_exception_type );
1025 /*********************************************************************
1026 * _CxxThrowException (MSVCRT.@)
1028 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
1032 args[0] = CXX_FRAME_MAGIC_VC6;
1033 args[1] = (ULONG_PTR)object;
1034 args[2] = (ULONG_PTR)type;
1035 RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );