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
27 #include "wine/exception.h"
28 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
35 CREATE_TYPE_INFO_VTABLE
36 CREATE_EXCEPTION_OBJECT(exception
)
38 struct __type_info_node
41 struct __type_info_node
* next
;
44 typedef exception bad_cast
;
45 typedef exception bad_typeid
;
46 typedef exception __non_rtti_object
;
48 extern const vtable_ptr bad_typeid_vtable
;
49 extern const vtable_ptr bad_cast_vtable
;
50 extern const vtable_ptr __non_rtti_object_vtable
;
51 extern const vtable_ptr type_info_vtable
;
53 /* get the vtable pointer for a C++ object */
54 static inline const vtable_ptr
*get_vtable( void *obj
)
56 return *(const vtable_ptr
**)obj
;
59 static inline const rtti_object_locator
*get_obj_locator( void *cppobj
)
61 const vtable_ptr
*vtable
= get_vtable( cppobj
);
62 return (const rtti_object_locator
*)vtable
[-1];
66 static void dump_obj_locator( const rtti_object_locator
*ptr
)
69 const rtti_object_hierarchy
*h
= ptr
->type_hierarchy
;
71 TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
72 ptr
, ptr
->signature
, ptr
->base_class_offset
, ptr
->flags
,
73 ptr
->type_descriptor
, dbgstr_type_info(ptr
->type_descriptor
), ptr
->type_hierarchy
);
74 TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
75 h
->signature
, h
->attributes
, h
->array_len
, h
->base_classes
);
76 for (i
= 0; i
< h
->array_len
; i
++)
78 TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
79 h
->base_classes
->bases
[i
],
80 h
->base_classes
->bases
[i
]->num_base_classes
,
81 h
->base_classes
->bases
[i
]->offsets
.this_offset
,
82 h
->base_classes
->bases
[i
]->offsets
.vbase_descr
,
83 h
->base_classes
->bases
[i
]->offsets
.vbase_offset
,
84 h
->base_classes
->bases
[i
]->attributes
,
85 h
->base_classes
->bases
[i
]->type_descriptor
,
86 dbgstr_type_info(h
->base_classes
->bases
[i
]->type_descriptor
) );
92 static void dump_obj_locator( const rtti_object_locator
*ptr
)
95 char *base
= ptr
->signature
== 0 ? RtlPcToFileHeader((void*)ptr
, (void**)&base
) : (char*)ptr
- ptr
->object_locator
;
96 const rtti_object_hierarchy
*h
= (const rtti_object_hierarchy
*)(base
+ ptr
->type_hierarchy
);
97 const type_info
*type_descriptor
= (const type_info
*)(base
+ ptr
->type_descriptor
);
99 TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
100 ptr
, ptr
->signature
, ptr
->base_class_offset
, ptr
->flags
,
101 type_descriptor
, dbgstr_type_info(type_descriptor
), h
);
102 TRACE( " hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
103 h
->signature
, h
->attributes
, h
->array_len
, base
+ h
->base_classes
);
104 for (i
= 0; i
< h
->array_len
; i
++)
106 const rtti_base_descriptor
*bases
= (rtti_base_descriptor
*)(base
+
107 ((const rtti_base_array
*)(base
+ h
->base_classes
))->bases
[i
]);
109 TRACE( " base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
111 bases
->num_base_classes
,
112 bases
->offsets
.this_offset
,
113 bases
->offsets
.vbase_descr
,
114 bases
->offsets
.vbase_offset
,
116 base
+ bases
->type_descriptor
,
117 dbgstr_type_info((const type_info
*)(base
+ bases
->type_descriptor
)) );
122 /******************************************************************
123 * ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
125 DEFINE_THISCALL_WRAPPER(exception_ctor
,8)
126 exception
* __thiscall
exception_ctor(exception
* _this
, const char ** name
)
128 TRACE("(%p,%s)\n", _this
, *name
);
129 return __exception_ctor(_this
, *name
, &exception_vtable
);
132 /******************************************************************
133 * ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
135 DEFINE_THISCALL_WRAPPER(exception_ctor_noalloc
,12)
136 exception
* __thiscall
exception_ctor_noalloc(exception
* _this
, char ** name
, int noalloc
)
138 TRACE("(%p,%s)\n", _this
, *name
);
139 _this
->vtable
= &exception_vtable
;
141 _this
->do_free
= FALSE
;
145 /******************************************************************
146 * ??0exception@@QAE@XZ (MSVCRT.@)
148 DEFINE_THISCALL_WRAPPER(exception_default_ctor
,4)
149 exception
* __thiscall
exception_default_ctor(exception
* _this
)
151 TRACE("(%p)\n", _this
);
152 return __exception_ctor(_this
, NULL
, &exception_vtable
);
155 /******************************************************************
156 * ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
158 DEFINE_THISCALL_WRAPPER(exception_opequals
,8)
159 exception
* __thiscall
exception_opequals(exception
* _this
, const exception
* rhs
)
161 TRACE("(%p %p)\n", _this
, rhs
);
164 exception_dtor(_this
);
165 exception_copy_ctor(_this
, rhs
);
167 TRACE("name = %s\n", _this
->name
);
171 /******************************************************************
172 * ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
174 DEFINE_THISCALL_WRAPPER(exception_scalar_dtor
,8)
175 void * __thiscall
exception_scalar_dtor(exception
* _this
, unsigned int flags
)
177 TRACE("(%p %x)\n", _this
, flags
);
178 exception_dtor(_this
);
179 if (flags
& 1) operator_delete(_this
);
183 /******************************************************************
184 * ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
186 DEFINE_THISCALL_WRAPPER(bad_typeid_copy_ctor
,8)
187 bad_typeid
* __thiscall
bad_typeid_copy_ctor(bad_typeid
* _this
, const bad_typeid
* rhs
)
189 TRACE("(%p %p)\n", _this
, rhs
);
190 return __exception_copy_ctor(_this
, rhs
, &bad_typeid_vtable
);
193 /******************************************************************
194 * ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
196 DEFINE_THISCALL_WRAPPER(bad_typeid_ctor
,8)
197 bad_typeid
* __thiscall
bad_typeid_ctor(bad_typeid
* _this
, const char * name
)
199 TRACE("(%p %s)\n", _this
, name
);
200 return __exception_ctor(_this
, name
, &bad_typeid_vtable
);
203 /******************************************************************
204 * ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
206 DEFINE_THISCALL_WRAPPER(bad_typeid_default_ctor
,4)
207 bad_typeid
* __thiscall
bad_typeid_default_ctor(bad_typeid
* _this
)
209 return bad_typeid_ctor( _this
, "bad typeid" );
212 /******************************************************************
213 * ??1bad_typeid@@UAE@XZ (MSVCRT.@)
215 DEFINE_THISCALL_WRAPPER(bad_typeid_dtor
,4)
216 void __thiscall
bad_typeid_dtor(bad_typeid
* _this
)
218 TRACE("(%p)\n", _this
);
219 exception_dtor(_this
);
222 /******************************************************************
223 * ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
225 DEFINE_THISCALL_WRAPPER(bad_typeid_opequals
,8)
226 bad_typeid
* __thiscall
bad_typeid_opequals(bad_typeid
* _this
, const bad_typeid
* rhs
)
228 TRACE("(%p %p)\n", _this
, rhs
);
229 exception_opequals(_this
, rhs
);
233 /******************************************************************
234 * ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
236 DEFINE_THISCALL_WRAPPER(bad_typeid_vector_dtor
,8)
237 void * __thiscall
bad_typeid_vector_dtor(bad_typeid
* _this
, unsigned int flags
)
239 TRACE("(%p %x)\n", _this
, flags
);
242 /* we have an array, with the number of elements stored before the first object */
243 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
245 for (i
= *ptr
- 1; i
>= 0; i
--) bad_typeid_dtor(_this
+ i
);
246 operator_delete(ptr
);
250 bad_typeid_dtor(_this
);
251 if (flags
& 1) operator_delete(_this
);
256 /******************************************************************
257 * ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
259 DEFINE_THISCALL_WRAPPER(bad_typeid_scalar_dtor
,8)
260 void * __thiscall
bad_typeid_scalar_dtor(bad_typeid
* _this
, unsigned int flags
)
262 TRACE("(%p %x)\n", _this
, flags
);
263 bad_typeid_dtor(_this
);
264 if (flags
& 1) operator_delete(_this
);
268 /******************************************************************
269 * ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
271 DEFINE_THISCALL_WRAPPER(__non_rtti_object_copy_ctor
,8)
272 __non_rtti_object
* __thiscall
__non_rtti_object_copy_ctor(__non_rtti_object
* _this
,
273 const __non_rtti_object
* rhs
)
275 TRACE("(%p %p)\n", _this
, rhs
);
276 return __exception_copy_ctor(_this
, rhs
, &__non_rtti_object_vtable
);
279 /******************************************************************
280 * ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
282 DEFINE_THISCALL_WRAPPER(__non_rtti_object_ctor
,8)
283 __non_rtti_object
* __thiscall
__non_rtti_object_ctor(__non_rtti_object
* _this
,
286 TRACE("(%p %s)\n", _this
, name
);
287 return __exception_ctor(_this
, name
, &__non_rtti_object_vtable
);
290 /******************************************************************
291 * ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
293 DEFINE_THISCALL_WRAPPER(__non_rtti_object_dtor
,4)
294 void __thiscall
__non_rtti_object_dtor(__non_rtti_object
* _this
)
296 TRACE("(%p)\n", _this
);
297 bad_typeid_dtor(_this
);
300 /******************************************************************
301 * ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
303 DEFINE_THISCALL_WRAPPER(__non_rtti_object_opequals
,8)
304 __non_rtti_object
* __thiscall
__non_rtti_object_opequals(__non_rtti_object
* _this
,
305 const __non_rtti_object
*rhs
)
307 TRACE("(%p %p)\n", _this
, rhs
);
308 bad_typeid_opequals(_this
, rhs
);
312 /******************************************************************
313 * ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
315 DEFINE_THISCALL_WRAPPER(__non_rtti_object_vector_dtor
,8)
316 void * __thiscall
__non_rtti_object_vector_dtor(__non_rtti_object
* _this
, unsigned int flags
)
318 TRACE("(%p %x)\n", _this
, flags
);
321 /* we have an array, with the number of elements stored before the first object */
322 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
324 for (i
= *ptr
- 1; i
>= 0; i
--) __non_rtti_object_dtor(_this
+ i
);
325 operator_delete(ptr
);
329 __non_rtti_object_dtor(_this
);
330 if (flags
& 1) operator_delete(_this
);
335 /******************************************************************
336 * ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
338 DEFINE_THISCALL_WRAPPER(__non_rtti_object_scalar_dtor
,8)
339 void * __thiscall
__non_rtti_object_scalar_dtor(__non_rtti_object
* _this
, unsigned int flags
)
341 TRACE("(%p %x)\n", _this
, flags
);
342 __non_rtti_object_dtor(_this
);
343 if (flags
& 1) operator_delete(_this
);
347 /******************************************************************
348 * ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
349 * ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
351 DEFINE_THISCALL_WRAPPER(bad_cast_ctor
,8)
352 bad_cast
* __thiscall
bad_cast_ctor(bad_cast
* _this
, const char ** name
)
354 TRACE("(%p %s)\n", _this
, *name
);
355 return __exception_ctor(_this
, *name
, &bad_cast_vtable
);
358 /******************************************************************
359 * ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
361 DEFINE_THISCALL_WRAPPER(bad_cast_copy_ctor
,8)
362 bad_cast
* __thiscall
bad_cast_copy_ctor(bad_cast
* _this
, const bad_cast
* rhs
)
364 TRACE("(%p %p)\n", _this
, rhs
);
365 return __exception_copy_ctor(_this
, rhs
, &bad_cast_vtable
);
368 /******************************************************************
369 * ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
371 DEFINE_THISCALL_WRAPPER(bad_cast_ctor_charptr
,8)
372 bad_cast
* __thiscall
bad_cast_ctor_charptr(bad_cast
* _this
, const char * name
)
374 TRACE("(%p %s)\n", _this
, name
);
375 return __exception_ctor(_this
, name
, &bad_cast_vtable
);
378 /******************************************************************
379 * ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
381 DEFINE_THISCALL_WRAPPER(bad_cast_default_ctor
,4)
382 bad_cast
* __thiscall
bad_cast_default_ctor(bad_cast
* _this
)
384 return bad_cast_ctor_charptr( _this
, "bad cast" );
387 /******************************************************************
388 * ??1bad_cast@@UAE@XZ (MSVCRT.@)
390 DEFINE_THISCALL_WRAPPER(bad_cast_dtor
,4)
391 void __thiscall
bad_cast_dtor(bad_cast
* _this
)
393 TRACE("(%p)\n", _this
);
394 exception_dtor(_this
);
397 /******************************************************************
398 * ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
400 DEFINE_THISCALL_WRAPPER(bad_cast_opequals
,8)
401 bad_cast
* __thiscall
bad_cast_opequals(bad_cast
* _this
, const bad_cast
* rhs
)
403 TRACE("(%p %p)\n", _this
, rhs
);
404 exception_opequals(_this
, rhs
);
408 /******************************************************************
409 * ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
411 DEFINE_THISCALL_WRAPPER(bad_cast_vector_dtor
,8)
412 void * __thiscall
bad_cast_vector_dtor(bad_cast
* _this
, unsigned int flags
)
414 TRACE("(%p %x)\n", _this
, flags
);
417 /* we have an array, with the number of elements stored before the first object */
418 INT_PTR i
, *ptr
= (INT_PTR
*)_this
- 1;
420 for (i
= *ptr
- 1; i
>= 0; i
--) bad_cast_dtor(_this
+ i
);
421 operator_delete(ptr
);
425 bad_cast_dtor(_this
);
426 if (flags
& 1) operator_delete(_this
);
431 /******************************************************************
432 * ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
434 DEFINE_THISCALL_WRAPPER(bad_cast_scalar_dtor
,8)
435 void * __thiscall
bad_cast_scalar_dtor(bad_cast
* _this
, unsigned int flags
)
437 TRACE("(%p %x)\n", _this
, flags
);
438 bad_cast_dtor(_this
);
439 if (flags
& 1) operator_delete(_this
);
443 /******************************************************************
444 * ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
446 DEFINE_THISCALL_WRAPPER(type_info_opequals_equals
,8)
447 int __thiscall
type_info_opequals_equals(type_info
* _this
, const type_info
* rhs
)
449 int ret
= !strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1);
450 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
454 /******************************************************************
455 * ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
457 DEFINE_THISCALL_WRAPPER(type_info_opnot_equals
,8)
458 int __thiscall
type_info_opnot_equals(type_info
* _this
, const type_info
* rhs
)
460 int ret
= !!strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1);
461 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
465 /******************************************************************
466 * ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
468 DEFINE_THISCALL_WRAPPER(type_info_before
,8)
469 int __thiscall
type_info_before(type_info
* _this
, const type_info
* rhs
)
471 int ret
= strcmp(_this
->mangled
+ 1, rhs
->mangled
+ 1) < 0;
472 TRACE("(%p %p) returning %d\n", _this
, rhs
, ret
);
476 /******************************************************************
477 * ??1type_info@@UAE@XZ (MSVCRT.@)
479 DEFINE_THISCALL_WRAPPER(type_info_dtor
,4)
480 void __thiscall
type_info_dtor(type_info
* _this
)
482 TRACE("(%p)\n", _this
);
486 /******************************************************************
487 * ?name@type_info@@QBEPBDXZ (MSVCRT.@)
489 DEFINE_THISCALL_WRAPPER(type_info_name
,4)
490 const char * __thiscall
type_info_name(type_info
* _this
)
494 /* Create and set the demangled name */
495 /* Note: mangled name in type_info struct always starts with a '.', while
496 * it isn't valid for mangled name.
497 * Is this '.' really part of the mangled name, or has it some other meaning ?
499 char* name
= __unDName(0, _this
->mangled
+ 1, 0,
500 malloc
, free
, UNDNAME_NO_ARGUMENTS
| UNDNAME_32_BIT_DECODE
);
503 unsigned int len
= strlen(name
);
505 /* It seems _unDName may leave blanks at the end of the demangled name */
506 while (len
&& name
[--len
] == ' ')
509 if (InterlockedCompareExchangePointer((void**)&_this
->name
, name
, NULL
))
511 /* Another thread set this member since we checked above - use it */
516 TRACE("(%p) returning %s\n", _this
, _this
->name
);
520 /******************************************************************
521 * ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
523 DEFINE_THISCALL_WRAPPER(type_info_raw_name
,4)
524 const char * __thiscall
type_info_raw_name(type_info
* _this
)
526 TRACE("(%p) returning %s\n", _this
, _this
->mangled
);
527 return _this
->mangled
;
532 typedef exception bad_alloc
;
533 extern const vtable_ptr bad_alloc_vtable
;
535 /* bad_alloc class implementation */
536 DEFINE_THISCALL_WRAPPER(bad_alloc_copy_ctor
,8)
537 bad_alloc
* __thiscall
bad_alloc_copy_ctor(bad_alloc
* _this
, const bad_alloc
* rhs
)
539 TRACE("(%p %p)\n", _this
, rhs
);
540 return __exception_copy_ctor(_this
, rhs
, &bad_alloc_vtable
);
543 DEFINE_THISCALL_WRAPPER(bad_alloc_dtor
,4)
544 void __thiscall
bad_alloc_dtor(bad_alloc
* _this
)
546 TRACE("(%p)\n", _this
);
547 exception_dtor(_this
);
550 #endif /* _MSVCR_VER >= 80 */
552 __ASM_BLOCK_BEGIN(vtables
)
555 __ASM_VTABLE(exception_old
,
556 VTABLE_ADD_FUNC(exception_vector_dtor
)
557 VTABLE_ADD_FUNC(exception_what
));
558 __ASM_VTABLE(bad_alloc
,
559 VTABLE_ADD_FUNC(exception_vector_dtor
)
560 VTABLE_ADD_FUNC(exception_what
));
562 __ASM_VTABLE(bad_typeid
,
563 VTABLE_ADD_FUNC(bad_typeid_vector_dtor
)
564 VTABLE_ADD_FUNC(exception_what
));
565 __ASM_VTABLE(bad_cast
,
566 VTABLE_ADD_FUNC(bad_cast_vector_dtor
)
567 VTABLE_ADD_FUNC(exception_what
));
568 __ASM_VTABLE(__non_rtti_object
,
569 VTABLE_ADD_FUNC(__non_rtti_object_vector_dtor
)
570 VTABLE_ADD_FUNC(exception_what
));
575 DEFINE_RTTI_DATA0( exception_old
, 0, ".?AVexception@@" )
576 DEFINE_RTTI_DATA1( bad_typeid
, 0, &exception_rtti_base_descriptor
, ".?AVbad_typeid@std@@" )
577 DEFINE_RTTI_DATA1( bad_cast
, 0, &exception_rtti_base_descriptor
, ".?AVbad_cast@std@@" )
578 DEFINE_RTTI_DATA2( __non_rtti_object
, 0, &bad_typeid_rtti_base_descriptor
, &exception_rtti_base_descriptor
, ".?AV__non_rtti_object@std@@" )
579 DEFINE_RTTI_DATA1( bad_alloc
, 0, &exception_rtti_base_descriptor
, ".?AVbad_alloc@std@@" )
581 DEFINE_RTTI_DATA1( bad_typeid
, 0, &exception_rtti_base_descriptor
, ".?AVbad_typeid@@" )
582 DEFINE_RTTI_DATA1( bad_cast
, 0, &exception_rtti_base_descriptor
, ".?AVbad_cast@@" )
583 DEFINE_RTTI_DATA2( __non_rtti_object
, 0, &bad_typeid_rtti_base_descriptor
, &exception_rtti_base_descriptor
, ".?AV__non_rtti_object@@" )
586 #if _MSVCR_VER >= 100
587 DEFINE_CXX_EXCEPTION0( exception
, exception_dtor
)
589 DEFINE_CXX_DATA1( bad_typeid
, &exception_cxx_type_info
, bad_typeid_dtor
)
590 DEFINE_CXX_DATA1( bad_cast
, &exception_cxx_type_info
, bad_cast_dtor
)
591 DEFINE_CXX_DATA2( __non_rtti_object
, &bad_typeid_cxx_type_info
,
592 &exception_cxx_type_info
, __non_rtti_object_dtor
)
594 DEFINE_CXX_DATA1( bad_alloc
, &exception_cxx_type_info
, bad_alloc_dtor
)
597 void msvcrt_init_exception(void *base
)
600 init_type_info_rtti(base
);
601 init_exception_rtti(base
);
603 init_exception_old_rtti(base
);
604 init_bad_alloc_rtti(base
);
606 init_bad_typeid_rtti(base
);
607 init_bad_cast_rtti(base
);
608 init___non_rtti_object_rtti(base
);
610 #if _MSVCR_VER >= 100
611 init_exception_cxx(base
);
613 init_exception_cxx_type_info(base
);
615 init_bad_typeid_cxx(base
);
616 init_bad_cast_cxx(base
);
617 init___non_rtti_object_cxx(base
);
619 init_bad_alloc_cxx(base
);
625 void throw_bad_alloc(void)
628 __exception_ctor(&e
, "bad allocation", &bad_alloc_vtable
);
629 _CxxThrowException(&e
, &bad_alloc_exception_type
);
633 #if _MSVCR_VER >= 100
634 void throw_exception(const char* msg
)
637 __exception_ctor(&e
, msg
, &exception_vtable
);
638 _CxxThrowException(&e
, &exception_exception_type
);
642 /******************************************************************
643 * ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
645 * Install a handler to be called when terminate() is called.
648 * func [I] Handler function to install
651 * The previously installed handler function, if any.
653 terminate_function CDECL
set_terminate(terminate_function func
)
655 thread_data_t
*data
= msvcrt_get_thread_data();
656 terminate_function previous
= data
->terminate_handler
;
657 TRACE("(%p) returning %p\n",func
,previous
);
658 data
->terminate_handler
= func
;
662 /******************************************************************
663 * _get_terminate (MSVCRT.@)
665 terminate_function CDECL
_get_terminate(void)
667 thread_data_t
*data
= msvcrt_get_thread_data();
668 TRACE("returning %p\n", data
->terminate_handler
);
669 return data
->terminate_handler
;
672 /******************************************************************
673 * ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
675 * Install a handler to be called when unexpected() is called.
678 * func [I] Handler function to install
681 * The previously installed handler function, if any.
683 unexpected_function CDECL
set_unexpected(unexpected_function func
)
685 thread_data_t
*data
= msvcrt_get_thread_data();
686 unexpected_function previous
= data
->unexpected_handler
;
687 TRACE("(%p) returning %p\n",func
,previous
);
688 data
->unexpected_handler
= func
;
692 /******************************************************************
693 * _get_unexpected (MSVCRT.@)
695 unexpected_function CDECL
_get_unexpected(void)
697 thread_data_t
*data
= msvcrt_get_thread_data();
698 TRACE("returning %p\n", data
->unexpected_handler
);
699 return data
->unexpected_handler
;
702 /******************************************************************
703 * ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@)
705 _se_translator_function CDECL
_set_se_translator(_se_translator_function func
)
707 thread_data_t
*data
= msvcrt_get_thread_data();
708 _se_translator_function previous
= data
->se_translator
;
709 TRACE("(%p) returning %p\n",func
,previous
);
710 data
->se_translator
= func
;
714 /******************************************************************
715 * ?terminate@@YAXXZ (MSVCRT.@)
717 * Default handler for an unhandled exception.
723 * This function does not return. Either control resumes from any
724 * handler installed by calling set_terminate(), or (by default) abort()
727 void CDECL
terminate(void)
729 thread_data_t
*data
= msvcrt_get_thread_data();
730 if (data
->terminate_handler
) data
->terminate_handler();
734 /******************************************************************
735 * ?unexpected@@YAXXZ (MSVCRT.@)
737 void CDECL
unexpected(void)
739 thread_data_t
*data
= msvcrt_get_thread_data();
740 if (data
->unexpected_handler
) data
->unexpected_handler();
745 /******************************************************************
746 * __RTtypeid (MSVCRT.@)
748 * Retrieve the Run Time Type Information (RTTI) for a C++ object.
751 * cppobj [I] C++ object to get type information for.
754 * Success: A type_info object describing cppobj.
755 * Failure: If the object to be cast has no RTTI, a __non_rtti_object
756 * exception is thrown. If cppobj is NULL, a bad_typeid exception
757 * is thrown. In either case, this function does not return.
760 * This function is usually called by compiler generated code as a result
761 * of using one of the C++ dynamic cast statements.
764 const type_info
* CDECL
__RTtypeid(void *cppobj
)
766 const type_info
*ret
;
771 bad_typeid_ctor( &e
, "Attempted a typeid of NULL pointer!" );
772 _CxxThrowException( &e
, &bad_typeid_exception_type
);
777 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
778 ret
= obj_locator
->type_descriptor
;
783 __non_rtti_object_ctor( &e
, "Bad read pointer - no RTTI data!" );
784 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
792 const type_info
* CDECL
__RTtypeid(void *cppobj
)
794 const type_info
*ret
;
799 bad_typeid_ctor( &e
, "Attempted a typeid of NULL pointer!" );
800 _CxxThrowException( &e
, &bad_typeid_exception_type
);
805 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
808 if(obj_locator
->signature
== 0)
809 base
= RtlPcToFileHeader((void*)obj_locator
, (void**)&base
);
811 base
= (char*)obj_locator
- obj_locator
->object_locator
;
813 ret
= (type_info
*)(base
+ obj_locator
->type_descriptor
);
818 __non_rtti_object_ctor( &e
, "Bad read pointer - no RTTI data!" );
819 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
826 /******************************************************************
827 * __RTDynamicCast (MSVCRT.@)
829 * Dynamically cast a C++ object to one of its base classes.
832 * cppobj [I] Any C++ object to cast
833 * unknown [I] Reserved, set to 0
834 * src [I] type_info object describing cppobj
835 * dst [I] type_info object describing the base class to cast to
836 * do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
839 * Success: The address of cppobj, cast to the object described by dst.
840 * Failure: NULL, If the object to be cast has no RTTI, or dst is not a
841 * valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
842 * is thrown and this function does not return.
845 * This function is usually called by compiler generated code as a result
846 * of using one of the C++ dynamic cast statements.
849 void* CDECL
__RTDynamicCast(void *cppobj
, int unknown
,
850 type_info
*src
, type_info
*dst
,
855 if (!cppobj
) return NULL
;
857 TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
858 cppobj
, unknown
, src
, dbgstr_type_info(src
), dst
, dbgstr_type_info(dst
), do_throw
);
860 /* To cast an object at runtime:
861 * 1.Find out the true type of the object from the typeinfo at vtable[-1]
862 * 2.Search for the destination type in the class hierarchy
863 * 3.If destination type is found, return base object address + dest offset
864 * Otherwise, fail the cast
866 * FIXME: the unknown parameter doesn't seem to be used for anything
871 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
872 const rtti_object_hierarchy
*obj_bases
= obj_locator
->type_hierarchy
;
873 const rtti_base_descriptor
* const* base_desc
= obj_bases
->base_classes
->bases
;
875 if (TRACE_ON(msvcrt
)) dump_obj_locator(obj_locator
);
878 for (i
= 0; i
< obj_bases
->array_len
; i
++)
880 const type_info
*typ
= base_desc
[i
]->type_descriptor
;
882 if (!strcmp(typ
->mangled
, dst
->mangled
))
884 /* compute the correct this pointer for that base class */
885 void *this_ptr
= (char *)cppobj
- obj_locator
->base_class_offset
;
886 ret
= get_this_pointer( &base_desc
[i
]->offsets
, this_ptr
);
890 /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
891 * to a reference, since references cannot be NULL.
893 if (!ret
&& do_throw
)
895 const char *msg
= "Bad dynamic_cast!";
897 bad_cast_ctor( &e
, &msg
);
898 _CxxThrowException( &e
, &bad_cast_exception_type
);
904 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
905 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
913 void* CDECL
__RTDynamicCast(void *cppobj
, int unknown
,
914 type_info
*src
, type_info
*dst
,
919 if (!cppobj
) return NULL
;
921 TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
922 cppobj
, unknown
, src
, dbgstr_type_info(src
), dst
, dbgstr_type_info(dst
), do_throw
);
927 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
928 const rtti_object_hierarchy
*obj_bases
;
929 const rtti_base_array
*base_array
;
932 if (TRACE_ON(msvcrt
)) dump_obj_locator(obj_locator
);
934 if(obj_locator
->signature
== 0)
935 base
= RtlPcToFileHeader((void*)obj_locator
, (void**)&base
);
937 base
= (char*)obj_locator
- obj_locator
->object_locator
;
939 obj_bases
= (const rtti_object_hierarchy
*)(base
+ obj_locator
->type_hierarchy
);
940 base_array
= (const rtti_base_array
*)(base
+ obj_bases
->base_classes
);
943 for (i
= 0; i
< obj_bases
->array_len
; i
++)
945 const rtti_base_descriptor
*base_desc
= (const rtti_base_descriptor
*)(base
+ base_array
->bases
[i
]);
946 const type_info
*typ
= (const type_info
*)(base
+ base_desc
->type_descriptor
);
948 if (!strcmp(typ
->mangled
, dst
->mangled
))
950 void *this_ptr
= (char *)cppobj
- obj_locator
->base_class_offset
;
951 ret
= get_this_pointer( &base_desc
->offsets
, this_ptr
);
955 if (!ret
&& do_throw
)
957 const char *msg
= "Bad dynamic_cast!";
959 bad_cast_ctor( &e
, &msg
);
960 _CxxThrowException( &e
, &bad_cast_exception_type
);
966 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
967 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
975 /******************************************************************
976 * __RTCastToVoid (MSVCRT.@)
978 * Dynamically cast a C++ object to a void*.
981 * cppobj [I] The C++ object to cast
984 * Success: The base address of the object as a void*.
985 * Failure: NULL, if cppobj is NULL or has no RTTI.
988 * This function is usually called by compiler generated code as a result
989 * of using one of the C++ dynamic cast statements.
991 void* CDECL
__RTCastToVoid(void *cppobj
)
995 if (!cppobj
) return NULL
;
999 const rtti_object_locator
*obj_locator
= get_obj_locator( cppobj
);
1000 ret
= (char *)cppobj
- obj_locator
->base_class_offset
;
1004 __non_rtti_object e
;
1005 __non_rtti_object_ctor( &e
, "Access violation - no RTTI data!" );
1006 _CxxThrowException( &e
, &__non_rtti_object_exception_type
);
1013 /*********************************************************************
1014 * _CxxThrowException (MSVCRT.@)
1017 void WINAPI
_CxxThrowException( void *object
, const cxx_exception_type
*type
)
1021 args
[0] = CXX_FRAME_MAGIC_VC6
;
1022 args
[1] = (ULONG_PTR
)object
;
1023 args
[2] = (ULONG_PTR
)type
;
1024 RaiseException( CXX_EXCEPTION
, EH_NONCONTINUABLE
, 3, args
);
1027 void WINAPI
_CxxThrowException( void *object
, const cxx_exception_type
*type
)
1031 args
[0] = CXX_FRAME_MAGIC_VC6
;
1032 args
[1] = (ULONG_PTR
)object
;
1033 args
[2] = (ULONG_PTR
)type
;
1034 RtlPcToFileHeader( (void*)type
, (void**)&args
[3]);
1035 RaiseException( CXX_EXCEPTION
, EH_NONCONTINUABLE
, 4, args
);
1039 #if _MSVCR_VER >= 80
1041 /*********************************************************************
1042 * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z
1043 * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z
1046 int __cdecl
_is_exception_typeof(const type_info
*ti
, EXCEPTION_POINTERS
*ep
)
1050 TRACE("(%p %p)\n", ti
, ep
);
1054 EXCEPTION_RECORD
*rec
= ep
->ExceptionRecord
;
1056 if (rec
->ExceptionCode
==CXX_EXCEPTION
&& rec
->NumberParameters
==3 &&
1057 (rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC6
||
1058 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC7
||
1059 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC8
))
1061 const cxx_type_info_table
*tit
= ((cxx_exception_type
*)rec
->ExceptionInformation
[2])->type_info_table
;
1064 for (i
=0; i
<tit
->count
; i
++) {
1065 if (ti
==tit
->info
[i
]->type_info
|| !strcmp(ti
->mangled
, tit
->info
[i
]->type_info
->mangled
))
1072 if (i
== tit
->count
)
1084 int __cdecl
_is_exception_typeof(const type_info
*ti
, EXCEPTION_POINTERS
*ep
)
1088 TRACE("(%p %p)\n", ti
, ep
);
1092 EXCEPTION_RECORD
*rec
= ep
->ExceptionRecord
;
1094 if (rec
->ExceptionCode
==CXX_EXCEPTION
&& rec
->NumberParameters
==4 &&
1095 (rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC6
||
1096 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC7
||
1097 rec
->ExceptionInformation
[0]==CXX_FRAME_MAGIC_VC8
))
1099 const cxx_exception_type
*et
= (cxx_exception_type
*)rec
->ExceptionInformation
[2];
1100 const cxx_type_info_table
*tit
= (const cxx_type_info_table
*)(rec
->ExceptionInformation
[3]+et
->type_info_table
);
1103 for (i
=0; i
<tit
->count
; i
++) {
1104 const cxx_type_info
*cti
= (const cxx_type_info
*)(rec
->ExceptionInformation
[3]+tit
->info
[i
]);
1105 const type_info
*except_ti
= (const type_info
*)(rec
->ExceptionInformation
[3]+cti
->type_info
);
1106 if (ti
==except_ti
|| !strcmp(ti
->mangled
, except_ti
->mangled
))
1113 if (i
== tit
->count
)
1126 /*********************************************************************
1127 * __clean_type_info_names_internal (MSVCR80.@)
1129 void CDECL
__clean_type_info_names_internal(void *p
)
1131 FIXME("(%p) stub\n", p
);
1134 /*********************************************************************
1135 * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
1137 DEFINE_THISCALL_WRAPPER(type_info_name_internal_method
,8)
1138 const char * __thiscall
type_info_name_internal_method(type_info
* _this
, struct __type_info_node
*node
)
1141 if (node
&& !once
++) FIXME("type_info_node parameter ignored\n");
1143 return type_info_name(_this
);
1146 void* __cdecl
__AdjustPointer(void *obj
, const this_ptr_offsets
*off
)
1148 return get_this_pointer(off
, obj
);
1153 #if _MSVCR_VER >= 140
1167 static void* CDECL
type_info_entry_malloc(size_t size
)
1169 type_info_entry
*ret
= malloc(FIELD_OFFSET(type_info_entry
, name
) + size
);
1173 static void CDECL
type_info_entry_free(void *ptr
)
1175 ptr
= (char*)ptr
- FIELD_OFFSET(type_info_entry
, name
);
1179 /******************************************************************
1180 * __std_type_info_compare (UCRTBASE.@)
1182 int CDECL
__std_type_info_compare(const type_info140
*l
, const type_info140
*r
)
1186 if (l
== r
) ret
= 0;
1187 else ret
= strcmp(l
->mangled
+ 1, r
->mangled
+ 1);
1188 TRACE("(%p %p) returning %d\n", l
, r
, ret
);
1192 /******************************************************************
1193 * __std_type_info_name (UCRTBASE.@)
1195 const char* CDECL
__std_type_info_name(type_info140
*ti
, SLIST_HEADER
*header
)
1199 char* name
= __unDName(0, ti
->mangled
+ 1, 0,
1200 type_info_entry_malloc
, type_info_entry_free
, UNDNAME_NO_ARGUMENTS
| UNDNAME_32_BIT_DECODE
);
1203 unsigned int len
= strlen(name
);
1205 while (len
&& name
[--len
] == ' ')
1208 if (InterlockedCompareExchangePointer((void**)&ti
->name
, name
, NULL
))
1210 type_info_entry_free(name
);
1214 type_info_entry
*entry
= (type_info_entry
*)(name
-FIELD_OFFSET(type_info_entry
, name
));
1215 InterlockedPushEntrySList(header
, &entry
->entry
);
1219 TRACE("(%p) returning %s\n", ti
, ti
->name
);
1223 /******************************************************************
1224 * __std_type_info_destroy_list (UCRTBASE.@)
1226 void CDECL
__std_type_info_destroy_list(SLIST_HEADER
*header
)
1228 SLIST_ENTRY
*cur
, *next
;
1230 TRACE("(%p)\n", header
);
1232 for(cur
= InterlockedFlushSList(header
); cur
; cur
= next
)
1239 /******************************************************************
1240 * __std_type_info_hash (UCRTBASE.@)
1242 size_t CDECL
__std_type_info_hash(const type_info140
*ti
)
1244 size_t hash
, fnv_prime
;
1248 hash
= 0xcbf29ce484222325;
1249 fnv_prime
= 0x100000001b3;
1252 fnv_prime
= 0x1000193;
1255 TRACE("(%p)->%s\n", ti
, ti
->mangled
);
1257 for(p
= ti
->mangled
+1; *p
; p
++) {
1269 #endif /* _MSVCR_VER >= 140 */