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
30 #include "wine/exception.h"
31 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
38 CREATE_TYPE_INFO_VTABLE
39 CREATE_EXCEPTION_OBJECT(exception
)
41 struct __type_info_node
44 struct __type_info_node
* next
;
47 typedef exception bad_cast
;
48 typedef exception bad_typeid
;
49 typedef exception __non_rtti_object
;
51 extern const vtable_ptr bad_typeid_vtable
;
52 extern const vtable_ptr bad_cast_vtable
;
53 extern const vtable_ptr __non_rtti_object_vtable
;
54 extern const vtable_ptr type_info_vtable
;
56 /* get the vtable pointer for a C++ object */
57 static inline const vtable_ptr
*get_vtable( void *obj
)
59 return *(const vtable_ptr
**)obj
;
62 static inline const rtti_object_locator
*get_obj_locator( void *cppobj
)
64 const vtable_ptr
*vtable
= get_vtable( cppobj
);
65 return (const rtti_object_locator
*)vtable
[-1];
69 static void dump_obj_locator( const rtti_object_locator
*ptr
)
72 const rtti_object_hierarchy
*h
= ptr
->type_hierarchy
;
74 TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
75 ptr
, ptr
->signature
, ptr
->base_class_offset
, ptr
->flags
,
76 ptr
->type_descriptor
, dbgstr_type_info(ptr
->type_descriptor
), ptr
->type_hierarchy
);
77 TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
78 h
->signature
, h
->attributes
, h
->array_len
, h
->base_classes
);
79 for (i
= 0; i
< h
->array_len
; i
++)
81 TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
82 h
->base_classes
->bases
[i
],
83 h
->base_classes
->bases
[i
]->num_base_classes
,
84 h
->base_classes
->bases
[i
]->offsets
.this_offset
,
85 h
->base_classes
->bases
[i
]->offsets
.vbase_descr
,
86 h
->base_classes
->bases
[i
]->offsets
.vbase_offset
,
87 h
->base_classes
->bases
[i
]->attributes
,
88 h
->base_classes
->bases
[i
]->type_descriptor
,
89 dbgstr_type_info(h
->base_classes
->bases
[i
]->type_descriptor
) );
95 static void dump_obj_locator( const rtti_object_locator
*ptr
)
98 char *base
= ptr
->signature
== 0 ? RtlPcToFileHeader((void*)ptr
, (void**)&base
) : (char*)ptr
- ptr
->object_locator
;
99 const rtti_object_hierarchy
*h
= (const rtti_object_hierarchy
*)(base
+ ptr
->type_hierarchy
);
100 const type_info
*type_descriptor
= (const type_info
*)(base
+ ptr
->type_descriptor
);
102 TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
103 ptr
, ptr
->signature
, ptr
->base_class_offset
, ptr
->flags
,
104 type_descriptor
, dbgstr_type_info(type_descriptor
), h
);
105 TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
106 h
->signature
, h
->attributes
, h
->array_len
, base
+ h
->base_classes
);
107 for (i
= 0; i
< h
->array_len
; i
++)
109 const rtti_base_descriptor
*bases
= (rtti_base_descriptor
*)(base
+
110 ((const rtti_base_array
*)(base
+ h
->base_classes
))->bases
[i
]);
112 TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
114 bases
->num_base_classes
,
115 bases
->offsets
.this_offset
,
116 bases
->offsets
.vbase_descr
,
117 bases
->offsets
.vbase_offset
,
119 base
+ bases
->type_descriptor
,
120 dbgstr_type_info((const type_info
*)(base
+ bases
->type_descriptor
)) );
125 /******************************************************************
126 * ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
128 DEFINE_THISCALL_WRAPPER(exception_ctor
,8)
129 exception
* __thiscall
exception_ctor(exception
* _this
, const char ** name
)
131 TRACE("(%p,%s)\n", _this
, *name
);
132 return __exception_ctor(_this
, *name
, &exception_vtable
);
135 /******************************************************************
136 * ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
138 DEFINE_THISCALL_WRAPPER(exception_ctor_noalloc
,12)
139 exception
* __thiscall
exception_ctor_noalloc(exception
* _this
, char ** name
, int noalloc
)
141 TRACE("(%p,%s)\n", _this
, *name
);
142 _this
->vtable
= &exception_vtable
;
144 _this
->do_free
= FALSE
;
148 /******************************************************************
149 * ??0exception@@QAE@XZ (MSVCRT.@)
151 DEFINE_THISCALL_WRAPPER(exception_default_ctor
,4)
152 exception
* __thiscall
exception_default_ctor(exception
* _this
)
154 TRACE("(%p)\n", _this
);
155 return __exception_ctor(_this
, NULL
, &exception_vtable
);
158 /******************************************************************
159 * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
161 DEFINE_THISCALL_WRAPPER(exception_opequals
,8)
162 exception
* __thiscall
exception_opequals(exception
* _this
, const exception
* rhs
)
164 TRACE("(%p %p)\n", _this
, rhs
);
167 exception_dtor(_this
);
168 exception_copy_ctor(_this
, rhs
);
170 TRACE("name = %s\n", _this
->name
);
174 /******************************************************************
175 * ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
177 DEFINE_THISCALL_WRAPPER(exception_scalar_dtor
,8)
178 void * __thiscall
exception_scalar_dtor(exception
* _this
, unsigned int flags
)
180 TRACE("(%p %x)\n", _this
, flags
);
181 exception_dtor(_this
);
182 if (flags
& 1) operator_delete(_this
);
186 /******************************************************************
187 * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
189 DEFINE_THISCALL_WRAPPER(bad_typeid_copy_ctor
,8)
190 bad_typeid
* __thiscall
bad_typeid_copy_ctor(bad_typeid
* _this
, const bad_typeid
* rhs
)
192 TRACE("(%p %p)\n", _this
, rhs
);
193 return __exception_copy_ctor(_this
, rhs
, &bad_typeid_vtable
);
196 /******************************************************************
197 * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
199 DEFINE_THISCALL_WRAPPER(bad_typeid_ctor
,8)
200 bad_typeid
* __thiscall
bad_typeid_ctor(bad_typeid
* _this
, const char * name
)
202 TRACE("(%p %s)\n", _this
, name
);
203 return __exception_ctor(_this
, name
, &bad_typeid_vtable
);
206 /******************************************************************
207 * ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
209 DEFINE_THISCALL_WRAPPER(bad_typeid_default_ctor
,4)
210 bad_typeid
* __thiscall
bad_typeid_default_ctor(bad_typeid
* _this
)
212 return bad_typeid_ctor( _this
, "bad typeid" );
215 /******************************************************************
216 * ??1bad_typeid@@UAE@XZ (MSVCRT.@)
218 DEFINE_THISCALL_WRAPPER(bad_typeid_dtor
,4)
219 void __thiscall
bad_typeid_dtor(bad_typeid
* _this
)
221 TRACE("(%p)\n", _this
);
222 exception_dtor(_this
);
225 /******************************************************************
226 * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
228 DEFINE_THISCALL_WRAPPER(bad_typeid_opequals
,8)
229 bad_typeid
* __thiscall
bad_typeid_opequals(bad_typeid
* _this
, const bad_typeid
* rhs
)
231 TRACE("(%p %p)\n", _this
, rhs
);
232 exception_opequals(_this
, rhs
);
236 /******************************************************************
237 * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
239 DEFINE_THISCALL_WRAPPER(bad_typeid_vector_dtor
,8)
240 void * __thiscall
bad_typeid_vector_dtor(bad_typeid
* _this
, unsigned int flags
)
242 TRACE("(%p %x)\n", _this
, flags
);
245 /* we have an array, with the number of elements stored before the first object */
246 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
248 for (i
= *ptr
- 1; i
>= 0; i
--) bad_typeid_dtor(_this
+ i
);
249 operator_delete(ptr
);
253 bad_typeid_dtor(_this
);
254 if (flags
& 1) operator_delete(_this
);
259 /******************************************************************
260 * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
262 DEFINE_THISCALL_WRAPPER(bad_typeid_scalar_dtor
,8)
263 void * __thiscall
bad_typeid_scalar_dtor(bad_typeid
* _this
, unsigned int flags
)
265 TRACE("(%p %x)\n", _this
, flags
);
266 bad_typeid_dtor(_this
);
267 if (flags
& 1) operator_delete(_this
);
271 /******************************************************************
272 * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
274 DEFINE_THISCALL_WRAPPER(__non_rtti_object_copy_ctor
,8)
275 __non_rtti_object
* __thiscall
__non_rtti_object_copy_ctor(__non_rtti_object
* _this
,
276 const __non_rtti_object
* rhs
)
278 TRACE("(%p %p)\n", _this
, rhs
);
279 return __exception_copy_ctor(_this
, rhs
, &__non_rtti_object_vtable
);
282 /******************************************************************
283 * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
285 DEFINE_THISCALL_WRAPPER(__non_rtti_object_ctor
,8)
286 __non_rtti_object
* __thiscall
__non_rtti_object_ctor(__non_rtti_object
* _this
,
289 TRACE("(%p %s)\n", _this
, name
);
290 return __exception_ctor(_this
, name
, &__non_rtti_object_vtable
);
293 /******************************************************************
294 * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
296 DEFINE_THISCALL_WRAPPER(__non_rtti_object_dtor
,4)
297 void __thiscall
__non_rtti_object_dtor(__non_rtti_object
* _this
)
299 TRACE("(%p)\n", _this
);
300 bad_typeid_dtor(_this
);
303 /******************************************************************
304 * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
306 DEFINE_THISCALL_WRAPPER(__non_rtti_object_opequals
,8)
307 __non_rtti_object
* __thiscall
__non_rtti_object_opequals(__non_rtti_object
* _this
,
308 const __non_rtti_object
*rhs
)
310 TRACE("(%p %p)\n", _this
, rhs
);
311 bad_typeid_opequals(_this
, rhs
);
315 /******************************************************************
316 * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
318 DEFINE_THISCALL_WRAPPER(__non_rtti_object_vector_dtor
,8)
319 void * __thiscall
__non_rtti_object_vector_dtor(__non_rtti_object
* _this
, unsigned int flags
)
321 TRACE("(%p %x)\n", _this
, flags
);
324 /* we have an array, with the number of elements stored before the first object */
325 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
327 for (i
= *ptr
- 1; i
>= 0; i
--) __non_rtti_object_dtor(_this
+ i
);
328 operator_delete(ptr
);
332 __non_rtti_object_dtor(_this
);
333 if (flags
& 1) operator_delete(_this
);
338 /******************************************************************
339 * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
341 DEFINE_THISCALL_WRAPPER(__non_rtti_object_scalar_dtor
,8)
342 void * __thiscall
__non_rtti_object_scalar_dtor(__non_rtti_object
* _this
, unsigned int flags
)
344 TRACE("(%p %x)\n", _this
, flags
);
345 __non_rtti_object_dtor(_this
);
346 if (flags
& 1) operator_delete(_this
);
350 /******************************************************************
351 * ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
352 * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
354 DEFINE_THISCALL_WRAPPER(bad_cast_ctor
,8)
355 bad_cast
* __thiscall
bad_cast_ctor(bad_cast
* _this
, const char ** name
)
357 TRACE("(%p %s)\n", _this
, *name
);
358 return __exception_ctor(_this
, *name
, &bad_cast_vtable
);
361 /******************************************************************
362 * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
364 DEFINE_THISCALL_WRAPPER(bad_cast_copy_ctor
,8)
365 bad_cast
* __thiscall
bad_cast_copy_ctor(bad_cast
* _this
, const bad_cast
* rhs
)
367 TRACE("(%p %p)\n", _this
, rhs
);
368 return __exception_copy_ctor(_this
, rhs
, &bad_cast_vtable
);
371 /******************************************************************
372 * ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
374 DEFINE_THISCALL_WRAPPER(bad_cast_ctor_charptr
,8)
375 bad_cast
* __thiscall
bad_cast_ctor_charptr(bad_cast
* _this
, const char * name
)
377 TRACE("(%p %s)\n", _this
, name
);
378 return __exception_ctor(_this
, name
, &bad_cast_vtable
);
381 /******************************************************************
382 * ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
384 DEFINE_THISCALL_WRAPPER(bad_cast_default_ctor
,4)
385 bad_cast
* __thiscall
bad_cast_default_ctor(bad_cast
* _this
)
387 return bad_cast_ctor_charptr( _this
, "bad cast" );
390 /******************************************************************
391 * ??1bad_cast@@UAE@XZ (MSVCRT.@)
393 DEFINE_THISCALL_WRAPPER(bad_cast_dtor
,4)
394 void __thiscall
bad_cast_dtor(bad_cast
* _this
)
396 TRACE("(%p)\n", _this
);
397 exception_dtor(_this
);
400 /******************************************************************
401 * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
403 DEFINE_THISCALL_WRAPPER(bad_cast_opequals
,8)
404 bad_cast
* __thiscall
bad_cast_opequals(bad_cast
* _this
, const bad_cast
* rhs
)
406 TRACE("(%p %p)\n", _this
, rhs
);
407 exception_opequals(_this
, rhs
);
411 /******************************************************************
412 * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
414 DEFINE_THISCALL_WRAPPER(bad_cast_vector_dtor
,8)
415 void * __thiscall
bad_cast_vector_dtor(bad_cast
* _this
, unsigned int flags
)
417 TRACE("(%p %x)\n", _this
, flags
);
420 /* we have an array, with the number of elements stored before the first object */
421 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
423 for (i
= *ptr
- 1; i
>= 0; i
--) bad_cast_dtor(_this
+ i
);
424 operator_delete(ptr
);
428 bad_cast_dtor(_this
);
429 if (flags
& 1) operator_delete(_this
);
434 /******************************************************************
435 * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
437 DEFINE_THISCALL_WRAPPER(bad_cast_scalar_dtor
,8)
438 void * __thiscall
bad_cast_scalar_dtor(bad_cast
* _this
, unsigned int flags
)
440 TRACE("(%p %x)\n", _this
, flags
);
441 bad_cast_dtor(_this
);
442 if (flags
& 1) operator_delete(_this
);
446 /******************************************************************
447 * ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
449 DEFINE_THISCALL_WRAPPER(type_info_opequals_equals
,8)
450 int __thiscall
type_info_opequals_equals(type_info
* _this
, const type_info
* rhs
)
452 int ret
= !strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1);
453 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
457 /******************************************************************
458 * ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
460 DEFINE_THISCALL_WRAPPER(type_info_opnot_equals
,8)
461 int __thiscall
type_info_opnot_equals(type_info
* _this
, const type_info
* rhs
)
463 int ret
= !!strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1);
464 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
468 /******************************************************************
469 * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
471 DEFINE_THISCALL_WRAPPER(type_info_before
,8)
472 int __thiscall
type_info_before(type_info
* _this
, const type_info
* rhs
)
474 int ret
= strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1) < 0;
475 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
479 /******************************************************************
480 * ??1type_info@@UAE@XZ (MSVCRT.@)
482 DEFINE_THISCALL_WRAPPER(type_info_dtor
,4)
483 void __thiscall
type_info_dtor(type_info
* _this
)
485 TRACE("(%p)\n", _this
);
489 /******************************************************************
490 * ?name@type_info@@QBEPBDXZ (MSVCRT.@)
492 DEFINE_THISCALL_WRAPPER(type_info_name
,4)
493 const char * __thiscall
type_info_name(type_info
* _this
)
497 /* Create and set the demangled name */
498 /* Note: mangled name in type_info struct always starts with a '.', while
499 * it isn't valid for mangled name.
500 * Is this '.' really part of the mangled name, or has it some other meaning ?
502 char* name
= __unDName(0, _this
->mangled
+ 1, 0,
503 malloc
, free
, UNDNAME_NO_ARGUMENTS
| UNDNAME_32_BIT_DECODE
);
506 unsigned int len
= strlen(name
);
508 /* It seems _unDName may leave blanks at the end of the demangled name */
509 while (len
&& name
[--len
] == ' ')
512 if (InterlockedCompareExchangePointer((void**)&_this
->name
, name
, NULL
))
514 /* Another thread set this member since we checked above - use it */
519 TRACE("(%p) returning %s\n", _this
, _this
->name
);
523 /******************************************************************
524 * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
526 DEFINE_THISCALL_WRAPPER(type_info_raw_name
,4)
527 const char * __thiscall
type_info_raw_name(type_info
* _this
)
529 TRACE("(%p) returning %s\n", _this
, _this
->mangled
);
530 return _this
->mangled
;
535 typedef exception bad_alloc
;
536 extern const vtable_ptr bad_alloc_vtable
;
538 /* bad_alloc class implementation */
539 DEFINE_THISCALL_WRAPPER(bad_alloc_copy_ctor
,8)
540 bad_alloc
* __thiscall
bad_alloc_copy_ctor(bad_alloc
* _this
, const bad_alloc
* rhs
)
542 TRACE("(%p %p)\n", _this
, rhs
);
543 return __exception_copy_ctor(_this
, rhs
, &bad_alloc_vtable
);
546 DEFINE_THISCALL_WRAPPER(bad_alloc_dtor
,4)
547 void __thiscall
bad_alloc_dtor(bad_alloc
* _this
)
549 TRACE("(%p)\n", _this
);
550 exception_dtor(_this
);
553 #endif /* _MSVCR_VER >= 80 */
555 __ASM_BLOCK_BEGIN(vtables
)
558 __ASM_VTABLE(exception_old
,
559 VTABLE_ADD_FUNC(exception_vector_dtor
)
560 VTABLE_ADD_FUNC(exception_what
));
561 __ASM_VTABLE(bad_alloc
,
562 VTABLE_ADD_FUNC(exception_vector_dtor
)
563 VTABLE_ADD_FUNC(exception_what
));
565 __ASM_VTABLE(bad_typeid
,
566 VTABLE_ADD_FUNC(bad_typeid_vector_dtor
)
567 VTABLE_ADD_FUNC(exception_what
));
568 __ASM_VTABLE(bad_cast
,
569 VTABLE_ADD_FUNC(bad_cast_vector_dtor
)
570 VTABLE_ADD_FUNC(exception_what
));
571 __ASM_VTABLE(__non_rtti_object
,
572 VTABLE_ADD_FUNC(__non_rtti_object_vector_dtor
)
573 VTABLE_ADD_FUNC(exception_what
));
578 DEFINE_RTTI_DATA0( exception_old
, 0, ".?AVexception@@" )
579 DEFINE_RTTI_DATA1( bad_typeid
, 0, &exception_rtti_base_descriptor
, ".?AVbad_typeid@std@@" )
580 DEFINE_RTTI_DATA1( bad_cast
, 0, &exception_rtti_base_descriptor
, ".?AVbad_cast@std@@" )
581 DEFINE_RTTI_DATA2( __non_rtti_object
, 0, &bad_typeid_rtti_base_descriptor
, &exception_rtti_base_descriptor
, ".?AV__non_rtti_object@std@@" )
582 DEFINE_RTTI_DATA1( bad_alloc
, 0, &exception_rtti_base_descriptor
, ".?AVbad_alloc@std@@" )
584 DEFINE_RTTI_DATA1( bad_typeid
, 0, &exception_rtti_base_descriptor
, ".?AVbad_typeid@@" )
585 DEFINE_RTTI_DATA1( bad_cast
, 0, &exception_rtti_base_descriptor
, ".?AVbad_cast@@" )
586 DEFINE_RTTI_DATA2( __non_rtti_object
, 0, &bad_typeid_rtti_base_descriptor
, &exception_rtti_base_descriptor
, ".?AV__non_rtti_object@@" )
589 #if _MSVCR_VER >= 100
590 DEFINE_CXX_EXCEPTION0( exception
, exception_dtor
)
592 DEFINE_CXX_DATA1( bad_typeid
, &exception_cxx_type_info
, bad_typeid_dtor
)
593 DEFINE_CXX_DATA1( bad_cast
, &exception_cxx_type_info
, bad_cast_dtor
)
594 DEFINE_CXX_DATA2( __non_rtti_object
, &bad_typeid_cxx_type_info
,
595 &exception_cxx_type_info
, __non_rtti_object_dtor
)
597 DEFINE_CXX_DATA1( bad_alloc
, &exception_cxx_type_info
, bad_alloc_dtor
)
600 void msvcrt_init_exception(void *base
)
603 init_type_info_rtti(base
);
604 init_exception_rtti(base
);
606 init_exception_old_rtti(base
);
607 init_bad_alloc_rtti(base
);
609 init_bad_typeid_rtti(base
);
610 init_bad_cast_rtti(base
);
611 init___non_rtti_object_rtti(base
);
613 #if _MSVCR_VER >= 100
614 init_exception_cxx(base
);
616 init_exception_cxx_type_info(base
);
618 init_bad_typeid_cxx(base
);
619 init_bad_cast_cxx(base
);
620 init___non_rtti_object_cxx(base
);
622 init_bad_alloc_cxx(base
);
628 void throw_bad_alloc(void)
631 __exception_ctor(&e
, "bad allocation", &bad_alloc_vtable
);
632 _CxxThrowException(&e
, &bad_alloc_exception_type
);
636 #if _MSVCR_VER >= 100
637 void throw_exception(const char* msg
)
640 __exception_ctor(&e
, msg
, &exception_vtable
);
641 _CxxThrowException(&e
, &exception_exception_type
);
645 /******************************************************************
646 * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
648 * Install a handler to be called when terminate() is called.
651 * func [I] Handler function to install
654 * The previously installed handler function, if any.
656 terminate_function CDECL
set_terminate(terminate_function func
)
658 thread_data_t
*data
= msvcrt_get_thread_data();
659 terminate_function previous
= data
->terminate_handler
;
660 TRACE("(%p) returning %p\n",func
,previous
);
661 data
->terminate_handler
= func
;
665 /******************************************************************
666 * _get_terminate (MSVCRT.@)
668 terminate_function CDECL
_get_terminate(void)
670 thread_data_t
*data
= msvcrt_get_thread_data();
671 TRACE("returning %p\n", data
->terminate_handler
);
672 return data
->terminate_handler
;
675 /******************************************************************
676 * ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
678 * Install a handler to be called when unexpected() is called.
681 * func [I] Handler function to install
684 * The previously installed handler function, if any.
686 unexpected_function CDECL
set_unexpected(unexpected_function func
)
688 thread_data_t
*data
= msvcrt_get_thread_data();
689 unexpected_function previous
= data
->unexpected_handler
;
690 TRACE("(%p) returning %p\n",func
,previous
);
691 data
->unexpected_handler
= func
;
695 /******************************************************************
696 * _get_unexpected (MSVCRT.@)
698 unexpected_function CDECL
_get_unexpected(void)
700 thread_data_t
*data
= msvcrt_get_thread_data();
701 TRACE("returning %p\n", data
->unexpected_handler
);
702 return data
->unexpected_handler
;
705 /******************************************************************
706 * ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@)
708 _se_translator_function CDECL
_set_se_translator(_se_translator_function func
)
710 thread_data_t
*data
= msvcrt_get_thread_data();
711 _se_translator_function previous
= data
->se_translator
;
712 TRACE("(%p) returning %p\n",func
,previous
);
713 data
->se_translator
= func
;
717 /******************************************************************
718 * ?terminate@@YAXXZ (MSVCRT.@)
720 * Default handler for an unhandled exception.
726 * This function does not return. Either control resumes from any
727 * handler installed by calling set_terminate(), or (by default) abort()
730 void CDECL
terminate(void)
732 thread_data_t
*data
= msvcrt_get_thread_data();
733 if (data
->terminate_handler
) data
->terminate_handler();
737 /******************************************************************
738 * ?unexpected@@YAXXZ (MSVCRT.@)
740 void CDECL
unexpected(void)
742 thread_data_t
*data
= msvcrt_get_thread_data();
743 if (data
->unexpected_handler
) data
->unexpected_handler();
748 /******************************************************************
749 * __RTtypeid (MSVCRT.@)
751 * Retrieve the Run Time Type Information (RTTI) for a C++ object.
754 * cppobj [I] C++ object to get type information for.
757 * Success: A type_info object describing cppobj.
758 * Failure: If the object to be cast has no RTTI, a __non_rtti_object
759 * exception is thrown. If cppobj is NULL, a bad_typeid exception
760 * is thrown. In either case, this function does not return.
763 * This function is usually called by compiler generated code as a result
764 * of using one of the C++ dynamic cast statements.
767 const type_info
* CDECL
__RTtypeid(void *cppobj
)
769 const type_info
*ret
;
774 bad_typeid_ctor( &e
, "Attempted a typeid of NULL pointer!" );
775 _CxxThrowException( &e
, &bad_typeid_exception_type
);
780 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
781 ret
= obj_locator
->type_descriptor
;
786 __non_rtti_object_ctor( &e
, "Bad read pointer - no RTTI data!" );
787 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
795 const type_info
* CDECL
__RTtypeid(void *cppobj
)
797 const type_info
*ret
;
802 bad_typeid_ctor( &e
, "Attempted a typeid of NULL pointer!" );
803 _CxxThrowException( &e
, &bad_typeid_exception_type
);
808 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
811 if(obj_locator
->signature
== 0)
812 base
= RtlPcToFileHeader((void*)obj_locator
, (void**)&base
);
814 base
= (char*)obj_locator
- obj_locator
->object_locator
;
816 ret
= (type_info
*)(base
+ obj_locator
->type_descriptor
);
821 __non_rtti_object_ctor( &e
, "Bad read pointer - no RTTI data!" );
822 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
829 /******************************************************************
830 * __RTDynamicCast (MSVCRT.@)
832 * Dynamically cast a C++ object to one of its base classes.
835 * cppobj [I] Any C++ object to cast
836 * unknown [I] Reserved, set to 0
837 * src [I] type_info object describing cppobj
838 * dst [I] type_info object describing the base class to cast to
839 * do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
842 * Success: The address of cppobj, cast to the object described by dst.
843 * Failure: NULL, If the object to be cast has no RTTI, or dst is not a
844 * valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
845 * is thrown and this function does not return.
848 * This function is usually called by compiler generated code as a result
849 * of using one of the C++ dynamic cast statements.
852 void* CDECL
__RTDynamicCast(void *cppobj
, int unknown
,
853 type_info
*src
, type_info
*dst
,
858 if (!cppobj
) return NULL
;
860 TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
861 cppobj
, unknown
, src
, dbgstr_type_info(src
), dst
, dbgstr_type_info(dst
), do_throw
);
863 /* To cast an object at runtime:
864 * 1.Find out the true type of the object from the typeinfo at vtable[-1]
865 * 2.Search for the destination type in the class hierarchy
866 * 3.If destination type is found, return base object address + dest offset
867 * Otherwise, fail the cast
869 * FIXME: the unknown parameter doesn't seem to be used for anything
874 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
875 const rtti_object_hierarchy
*obj_bases
= obj_locator
->type_hierarchy
;
876 const rtti_base_descriptor
* const* base_desc
= obj_bases
->base_classes
->bases
;
878 if (TRACE_ON(msvcrt
)) dump_obj_locator(obj_locator
);
881 for (i
= 0; i
< obj_bases
->array_len
; i
++)
883 const type_info
*typ
= base_desc
[i
]->type_descriptor
;
885 if (!strcmp(typ
->mangled
, dst
->mangled
))
887 /* compute the correct this pointer for that base class */
888 void *this_ptr
= (char *)cppobj
- obj_locator
->base_class_offset
;
889 ret
= get_this_pointer( &base_desc
[i
]->offsets
, this_ptr
);
893 /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
894 * to a reference, since references cannot be NULL.
896 if (!ret
&& do_throw
)
898 const char *msg
= "Bad dynamic_cast!";
900 bad_cast_ctor( &e
, &msg
);
901 _CxxThrowException( &e
, &bad_cast_exception_type
);
907 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
908 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
916 void* CDECL
__RTDynamicCast(void *cppobj
, int unknown
,
917 type_info
*src
, type_info
*dst
,
922 if (!cppobj
) return NULL
;
924 TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
925 cppobj
, unknown
, src
, dbgstr_type_info(src
), dst
, dbgstr_type_info(dst
), do_throw
);
930 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
931 const rtti_object_hierarchy
*obj_bases
;
932 const rtti_base_array
*base_array
;
935 if (TRACE_ON(msvcrt
)) dump_obj_locator(obj_locator
);
937 if(obj_locator
->signature
== 0)
938 base
= RtlPcToFileHeader((void*)obj_locator
, (void**)&base
);
940 base
= (char*)obj_locator
- obj_locator
->object_locator
;
942 obj_bases
= (const rtti_object_hierarchy
*)(base
+ obj_locator
->type_hierarchy
);
943 base_array
= (const rtti_base_array
*)(base
+ obj_bases
->base_classes
);
946 for (i
= 0; i
< obj_bases
->array_len
; i
++)
948 const rtti_base_descriptor
*base_desc
= (const rtti_base_descriptor
*)(base
+ base_array
->bases
[i
]);
949 const type_info
*typ
= (const type_info
*)(base
+ base_desc
->type_descriptor
);
951 if (!strcmp(typ
->mangled
, dst
->mangled
))
953 void *this_ptr
= (char *)cppobj
- obj_locator
->base_class_offset
;
954 ret
= get_this_pointer( &base_desc
->offsets
, this_ptr
);
958 if (!ret
&& do_throw
)
960 const char *msg
= "Bad dynamic_cast!";
962 bad_cast_ctor( &e
, &msg
);
963 _CxxThrowException( &e
, &bad_cast_exception_type
);
969 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
970 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
978 /******************************************************************
979 * __RTCastToVoid (MSVCRT.@)
981 * Dynamically cast a C++ object to a void*.
984 * cppobj [I] The C++ object to cast
987 * Success: The base address of the object as a void*.
988 * Failure: NULL, if cppobj is NULL or has no RTTI.
991 * This function is usually called by compiler generated code as a result
992 * of using one of the C++ dynamic cast statements.
994 void* CDECL
__RTCastToVoid(void *cppobj
)
998 if (!cppobj
) return NULL
;
1002 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
1003 ret
= (char *)cppobj
- obj_locator
->base_class_offset
;
1007 __non_rtti_object e
;
1008 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
1009 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
1016 /*********************************************************************
1017 * _CxxThrowException (MSVCRT.@)
1020 void WINAPI
_CxxThrowException( void *object
, const cxx_exception_type
*type
)
1024 args
[0] = CXX_FRAME_MAGIC_VC6
;
1025 args
[1] = (ULONG_PTR
)object
;
1026 args
[2] = (ULONG_PTR
)type
;
1027 RaiseException( CXX_EXCEPTION
, EH_NONCONTINUABLE
, 3, args
);
1030 void WINAPI
_CxxThrowException( void *object
, const cxx_exception_type
*type
)
1034 args
[0] = CXX_FRAME_MAGIC_VC6
;
1035 args
[1] = (ULONG_PTR
)object
;
1036 args
[2] = (ULONG_PTR
)type
;
1037 RtlPcToFileHeader( (void*)type
, (void**)&args
[3]);
1038 RaiseException( CXX_EXCEPTION
, EH_NONCONTINUABLE
, 4, args
);
1042 #if _MSVCR_VER >= 80
1044 /*********************************************************************
1045 * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z
1046 * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z
1049 int __cdecl
_is_exception_typeof(const type_info
*ti
, EXCEPTION_POINTERS
*ep
)
1053 TRACE("(%p %p)\n", ti
, ep
);
1057 EXCEPTION_RECORD
*rec
= ep
->ExceptionRecord
;
1059 if (rec
->ExceptionCode
==CXX_EXCEPTION
&& rec
->NumberParameters
==3 &&
1060 (rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC6
||
1061 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC7
||
1062 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC8
))
1064 const cxx_type_info_table
*tit
= ((cxx_exception_type
*)rec
->ExceptionInformation
[2])->type_info_table
;
1067 for (i
=0; i
<tit
->count
; i
++) {
1068 if (ti
==tit
->info
[i
]->type_info
|| !strcmp(ti
->mangled
, tit
->info
[i
]->type_info
->mangled
))
1075 if (i
== tit
->count
)
1087 int __cdecl
_is_exception_typeof(const type_info
*ti
, EXCEPTION_POINTERS
*ep
)
1091 TRACE("(%p %p)\n", ti
, ep
);
1095 EXCEPTION_RECORD
*rec
= ep
->ExceptionRecord
;
1097 if (rec
->ExceptionCode
==CXX_EXCEPTION
&& rec
->NumberParameters
==4 &&
1098 (rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC6
||
1099 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC7
||
1100 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC8
))
1102 const cxx_exception_type
*et
= (cxx_exception_type
*)rec
->ExceptionInformation
[2];
1103 const cxx_type_info_table
*tit
= (const cxx_type_info_table
*)(rec
->ExceptionInformation
[3]+et
->type_info_table
);
1106 for (i
=0; i
<tit
->count
; i
++) {
1107 const cxx_type_info
*cti
= (const cxx_type_info
*)(rec
->ExceptionInformation
[3]+tit
->info
[i
]);
1108 const type_info
*except_ti
= (const type_info
*)(rec
->ExceptionInformation
[3]+cti
->type_info
);
1109 if (ti
==except_ti
|| !strcmp(ti
->mangled
, except_ti
->mangled
))
1116 if (i
== tit
->count
)
1129 /*********************************************************************
1130 * __clean_type_info_names_internal (MSVCR80.@)
1132 void CDECL
__clean_type_info_names_internal(void *p
)
1134 FIXME("(%p) stub\n", p
);
1137 /*********************************************************************
1138 * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
1140 DEFINE_THISCALL_WRAPPER(type_info_name_internal_method
,8)
1141 const char * __thiscall
type_info_name_internal_method(type_info
* _this
, struct __type_info_node
*node
)
1144 if (node
&& !once
++) FIXME("type_info_node parameter ignored\n");
1146 return type_info_name(_this
);
1149 void* __cdecl
__AdjustPointer(void *obj
, const this_ptr_offsets
*off
)
1151 return get_this_pointer(off
, obj
);
1156 #if _MSVCR_VER >= 140
1170 static void* CDECL
type_info_entry_malloc(size_t size
)
1172 type_info_entry
*ret
= malloc(FIELD_OFFSET(type_info_entry
, name
) + size
);
1176 static void CDECL
type_info_entry_free(void *ptr
)
1178 ptr
= (char*)ptr
- FIELD_OFFSET(type_info_entry
, name
);
1182 /******************************************************************
1183 * __std_type_info_compare (UCRTBASE.@)
1185 int CDECL
__std_type_info_compare(const type_info140
*l
, const type_info140
*r
)
1189 if (l
== r
) ret
= 0;
1190 else ret
= strcmp(l
->mangled
+ 1, r
->mangled
+ 1);
1191 TRACE("(%p %p) returning %d\n", l
, r
, ret
);
1195 /******************************************************************
1196 * __std_type_info_name (UCRTBASE.@)
1198 const char* CDECL
__std_type_info_name(type_info140
*ti
, SLIST_HEADER
*header
)
1202 char* name
= __unDName(0, ti
->mangled
+ 1, 0,
1203 type_info_entry_malloc
, type_info_entry_free
, UNDNAME_NO_ARGUMENTS
| UNDNAME_32_BIT_DECODE
);
1206 unsigned int len
= strlen(name
);
1208 while (len
&& name
[--len
] == ' ')
1211 if (InterlockedCompareExchangePointer((void**)&ti
->name
, name
, NULL
))
1213 type_info_entry_free(name
);
1217 type_info_entry
*entry
= (type_info_entry
*)(name
-FIELD_OFFSET(type_info_entry
, name
));
1218 InterlockedPushEntrySList(header
, &entry
->entry
);
1222 TRACE("(%p) returning %s\n", ti
, ti
->name
);
1226 /******************************************************************
1227 * __std_type_info_destroy_list (UCRTBASE.@)
1229 void CDECL
__std_type_info_destroy_list(SLIST_HEADER
*header
)
1231 SLIST_ENTRY
*cur
, *next
;
1233 TRACE("(%p)\n", header
);
1235 for(cur
= InterlockedFlushSList(header
); cur
; cur
= next
)
1242 /******************************************************************
1243 * __std_type_info_hash (UCRTBASE.@)
1245 size_t CDECL
__std_type_info_hash(const type_info140
*ti
)
1247 size_t hash
, fnv_prime
;
1251 hash
= 0xcbf29ce484222325;
1252 fnv_prime
= 0x100000001b3;
1255 fnv_prime
= 0x1000193;
1258 TRACE("(%p)->%s\n", ti
, ti
->mangled
);
1260 for(p
= ti
->mangled
+1; *p
; p
++) {
1272 #endif /* _MSVCR_VER >= 140 */