msvcrt: Support 64-bit RTTI in __RTtypeid function.
[wine] / dlls / msvcrt / cpp.c
1 /*
2  * msvcrt.dll C++ objects
3  *
4  * Copyright 2000 Jon Griffiths
5  * Copyright 2003, 2004 Alexandre Julliard
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winternl.h"
29 #include "wine/exception.h"
30 #include "wine/debug.h"
31 #include "msvcrt.h"
32 #include "cppexcept.h"
33 #include "mtdll.h"
34 #include "cxx.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
37
38 typedef exception bad_cast;
39 typedef exception bad_typeid;
40 typedef exception __non_rtti_object;
41
42 #ifdef __x86_64__
43
44 /* x86_64 RTTI structures */
45 typedef struct
46 {
47     unsigned int type_descriptor;
48     int num_base_classes;
49     this_ptr_offsets offsets;
50     unsigned int attributes;
51 } rtti_base_descriptor_x64;
52
53 typedef struct
54 {
55     unsigned bases[3];
56 } rtti_base_array_x64;
57
58 typedef struct
59 {
60     unsigned int signature;
61     unsigned int attributes;
62     int array_len;
63     unsigned int base_classes;
64 } rtti_object_hierarchy_x64;
65
66 typedef struct
67 {
68     unsigned int signature;
69     int base_class_offset;
70     unsigned int flags;
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;
75
76 #endif
77
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;
83
84 /* get the vtable pointer for a C++ object */
85 static inline const vtable_ptr *get_vtable( void *obj )
86 {
87     return *(const vtable_ptr **)obj;
88 }
89
90 static inline const rtti_object_locator *get_obj_locator( void *cppobj )
91 {
92     const vtable_ptr *vtable = get_vtable( cppobj );
93     return (const rtti_object_locator *)vtable[-1];
94 }
95
96 static void dump_obj_locator( const rtti_object_locator *ptr )
97 {
98     int i;
99     const rtti_object_hierarchy *h = ptr->type_hierarchy;
100
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++)
107     {
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) );
117     }
118 }
119
120 /* Internal common ctor for exception */
121 static void EXCEPTION_ctor(exception *_this, const char** name)
122 {
123   _this->vtable = &MSVCRT_exception_vtable;
124   if (*name)
125   {
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;
130   }
131   else
132   {
133     _this->name = NULL;
134     _this->do_free = FALSE;
135   }
136 }
137
138 /******************************************************************
139  *              ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
140  */
141 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
142 exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name)
143 {
144   TRACE("(%p,%s)\n", _this, *name);
145   EXCEPTION_ctor(_this, name);
146   return _this;
147 }
148
149 /******************************************************************
150  *              ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
151  */
152 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
153 exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
154 {
155   TRACE("(%p,%s)\n", _this, *name);
156   _this->vtable = &MSVCRT_exception_vtable;
157   _this->name = *name;
158   _this->do_free = FALSE;
159   return _this;
160 }
161
162 /******************************************************************
163  *              ??0exception@@QAE@ABV0@@Z (MSVCRT.@)
164  */
165 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
166 exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
167 {
168   TRACE("(%p,%p)\n", _this, rhs);
169
170   if (!rhs->do_free)
171   {
172     _this->vtable = &MSVCRT_exception_vtable;
173     _this->name = rhs->name;
174     _this->do_free = FALSE;
175   }
176   else
177     EXCEPTION_ctor(_this, (const char**)&rhs->name);
178   TRACE("name = %s\n", _this->name);
179   return _this;
180 }
181
182 /******************************************************************
183  *              ??0exception@@QAE@XZ (MSVCRT.@)
184  */
185 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
186 exception * __thiscall MSVCRT_exception_default_ctor(exception * _this)
187 {
188   static const char* empty = NULL;
189
190   TRACE("(%p)\n", _this);
191   EXCEPTION_ctor(_this, &empty);
192   return _this;
193 }
194
195 /******************************************************************
196  *              ??1exception@@UAE@XZ (MSVCRT.@)
197  */
198 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
199 void __thiscall MSVCRT_exception_dtor(exception * _this)
200 {
201   TRACE("(%p)\n", _this);
202   _this->vtable = &MSVCRT_exception_vtable;
203   if (_this->do_free) MSVCRT_free(_this->name);
204 }
205
206 /******************************************************************
207  *              ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
208  */
209 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
210 exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
211 {
212   TRACE("(%p %p)\n", _this, rhs);
213   if (_this != rhs)
214   {
215       MSVCRT_exception_dtor(_this);
216       MSVCRT_exception_copy_ctor(_this, rhs);
217   }
218   TRACE("name = %s\n", _this->name);
219   return _this;
220 }
221
222 /******************************************************************
223  *              ??_Eexception@@UAEPAXI@Z (MSVCRT.@)
224  */
225 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
226 void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
227 {
228     TRACE("(%p %x)\n", _this, flags);
229     if (flags & 2)
230     {
231         /* we have an array, with the number of elements stored before the first object */
232         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
233
234         for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
235         MSVCRT_operator_delete(ptr);
236     }
237     else
238     {
239         MSVCRT_exception_dtor(_this);
240         if (flags & 1) MSVCRT_operator_delete(_this);
241     }
242     return _this;
243 }
244
245 /******************************************************************
246  *              ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
247  */
248 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
249 void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
250 {
251     TRACE("(%p %x)\n", _this, flags);
252     MSVCRT_exception_dtor(_this);
253     if (flags & 1) MSVCRT_operator_delete(_this);
254     return _this;
255 }
256
257 /******************************************************************
258  *              ?what@exception@@UBEPBDXZ (MSVCRT.@)
259  */
260 DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
261 const char * __thiscall MSVCRT_what_exception(exception * _this)
262 {
263   TRACE("(%p) returning %s\n", _this, _this->name);
264   return _this->name ? _this->name : "Unknown exception";
265 }
266
267 /******************************************************************
268  *              ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
269  */
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)
272 {
273   TRACE("(%p %p)\n", _this, rhs);
274   MSVCRT_exception_copy_ctor(_this, rhs);
275   _this->vtable = &MSVCRT_bad_typeid_vtable;
276   return _this;
277 }
278
279 /******************************************************************
280  *              ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
281  */
282 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
283 bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
284 {
285   TRACE("(%p %s)\n", _this, name);
286   EXCEPTION_ctor(_this, &name);
287   _this->vtable = &MSVCRT_bad_typeid_vtable;
288   return _this;
289 }
290
291 /******************************************************************
292  *              ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
293  */
294 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
295 bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
296 {
297   return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
298 }
299
300 /******************************************************************
301  *              ??1bad_typeid@@UAE@XZ (MSVCRT.@)
302  */
303 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
304 void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
305 {
306   TRACE("(%p)\n", _this);
307   MSVCRT_exception_dtor(_this);
308 }
309
310 /******************************************************************
311  *              ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
312  */
313 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
314 bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
315 {
316   TRACE("(%p %p)\n", _this, rhs);
317   MSVCRT_exception_opequals(_this, rhs);
318   return _this;
319 }
320
321 /******************************************************************
322  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
323  */
324 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
325 void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
326 {
327     TRACE("(%p %x)\n", _this, flags);
328     if (flags & 2)
329     {
330         /* we have an array, with the number of elements stored before the first object */
331         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
332
333         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
334         MSVCRT_operator_delete(ptr);
335     }
336     else
337     {
338         MSVCRT_bad_typeid_dtor(_this);
339         if (flags & 1) MSVCRT_operator_delete(_this);
340     }
341     return _this;
342 }
343
344 /******************************************************************
345  *              ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
346  */
347 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
348 void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
349 {
350     TRACE("(%p %x)\n", _this, flags);
351     MSVCRT_bad_typeid_dtor(_this);
352     if (flags & 1) MSVCRT_operator_delete(_this);
353     return _this;
354 }
355
356 /******************************************************************
357  *              ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
358  */
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)
362 {
363   TRACE("(%p %p)\n", _this, rhs);
364   MSVCRT_bad_typeid_copy_ctor(_this, rhs);
365   _this->vtable = &MSVCRT___non_rtti_object_vtable;
366   return _this;
367 }
368
369 /******************************************************************
370  *              ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
371  */
372 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
373 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
374                                                             const char * name)
375 {
376   TRACE("(%p %s)\n", _this, name);
377   EXCEPTION_ctor(_this, &name);
378   _this->vtable = &MSVCRT___non_rtti_object_vtable;
379   return _this;
380 }
381
382 /******************************************************************
383  *              ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
384  */
385 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
386 void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
387 {
388   TRACE("(%p)\n", _this);
389   MSVCRT_bad_typeid_dtor(_this);
390 }
391
392 /******************************************************************
393  *              ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
394  */
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)
398 {
399   TRACE("(%p %p)\n", _this, rhs);
400   MSVCRT_bad_typeid_opequals(_this, rhs);
401   return _this;
402 }
403
404 /******************************************************************
405  *              ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
406  */
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)
409 {
410     TRACE("(%p %x)\n", _this, flags);
411     if (flags & 2)
412     {
413         /* we have an array, with the number of elements stored before the first object */
414         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
415
416         for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
417         MSVCRT_operator_delete(ptr);
418     }
419     else
420     {
421         MSVCRT___non_rtti_object_dtor(_this);
422         if (flags & 1) MSVCRT_operator_delete(_this);
423     }
424     return _this;
425 }
426
427 /******************************************************************
428  *              ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
429  */
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)
432 {
433   TRACE("(%p %x)\n", _this, flags);
434   MSVCRT___non_rtti_object_dtor(_this);
435   if (flags & 1) MSVCRT_operator_delete(_this);
436   return _this;
437 }
438
439 /******************************************************************
440  *              ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
441  *              ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
442  */
443 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
444 bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
445 {
446   TRACE("(%p %s)\n", _this, *name);
447   EXCEPTION_ctor(_this, name);
448   _this->vtable = &MSVCRT_bad_cast_vtable;
449   return _this;
450 }
451
452 /******************************************************************
453  *              ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
454  */
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)
457 {
458   TRACE("(%p %p)\n", _this, rhs);
459   MSVCRT_exception_copy_ctor(_this, rhs);
460   _this->vtable = &MSVCRT_bad_cast_vtable;
461   return _this;
462 }
463
464 /******************************************************************
465  *              ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
466  */
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)
469 {
470   TRACE("(%p %s)\n", _this, name);
471   EXCEPTION_ctor(_this, &name);
472   _this->vtable = &MSVCRT_bad_cast_vtable;
473   return _this;
474 }
475
476 /******************************************************************
477  *              ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
478  */
479 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
480 bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
481 {
482   return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
483 }
484
485 /******************************************************************
486  *              ??1bad_cast@@UAE@XZ (MSVCRT.@)
487  */
488 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
489 void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this)
490 {
491   TRACE("(%p)\n", _this);
492   MSVCRT_exception_dtor(_this);
493 }
494
495 /******************************************************************
496  *              ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
497  */
498 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
499 bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
500 {
501   TRACE("(%p %p)\n", _this, rhs);
502   MSVCRT_exception_opequals(_this, rhs);
503   return _this;
504 }
505
506 /******************************************************************
507  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
508  */
509 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
510 void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
511 {
512     TRACE("(%p %x)\n", _this, flags);
513     if (flags & 2)
514     {
515         /* we have an array, with the number of elements stored before the first object */
516         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
517
518         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
519         MSVCRT_operator_delete(ptr);
520     }
521     else
522     {
523         MSVCRT_bad_cast_dtor(_this);
524         if (flags & 1) MSVCRT_operator_delete(_this);
525     }
526     return _this;
527 }
528
529 /******************************************************************
530  *              ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
531  */
532 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
533 void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
534 {
535   TRACE("(%p %x)\n", _this, flags);
536   MSVCRT_bad_cast_dtor(_this);
537   if (flags & 1) MSVCRT_operator_delete(_this);
538   return _this;
539 }
540
541 /******************************************************************
542  *              ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
543  */
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)
546 {
547     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
548     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
549     return ret;
550 }
551
552 /******************************************************************
553  *              ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
554  */
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)
557 {
558     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
559     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
560     return ret;
561 }
562
563 /******************************************************************
564  *              ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
565  */
566 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
567 int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
568 {
569     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
570     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
571     return ret;
572 }
573
574 /******************************************************************
575  *              ??1type_info@@UAE@XZ (MSVCRT.@)
576  */
577 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
578 void __thiscall MSVCRT_type_info_dtor(type_info * _this)
579 {
580   TRACE("(%p)\n", _this);
581   MSVCRT_free(_this->name);
582 }
583
584 /******************************************************************
585  *              ?name@type_info@@QBEPBDXZ (MSVCRT.@)
586  */
587 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
588 const char * __thiscall MSVCRT_type_info_name(type_info * _this)
589 {
590   if (!_this->name)
591   {
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 ?
596      */
597     char* name = __unDName(0, _this->mangled + 1, 0,
598                            MSVCRT_malloc, MSVCRT_free, 0x2800);
599     if (name)
600     {
601       unsigned int len = strlen(name);
602
603       /* It seems _unDName may leave blanks at the end of the demangled name */
604       while (len && name[--len] == ' ')
605         name[len] = '\0';
606
607       if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
608       {
609         /* Another thread set this member since we checked above - use it */
610         MSVCRT_free(name);
611       }
612     }
613   }
614   TRACE("(%p) returning %s\n", _this, _this->name);
615   return _this->name;
616 }
617
618 /******************************************************************
619  *              ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
620  */
621 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
622 const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this)
623 {
624   TRACE("(%p) returning %s\n", _this, _this->mangled);
625   return _this->mangled;
626 }
627
628 /* Unexported */
629 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
630 void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
631 {
632     TRACE("(%p %x)\n", _this, flags);
633     if (flags & 2)
634     {
635         /* we have an array, with the number of elements stored before the first object */
636         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
637
638         for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
639         MSVCRT_operator_delete(ptr);
640     }
641     else
642     {
643         MSVCRT_type_info_dtor(_this);
644         if (flags & 1) MSVCRT_operator_delete(_this);
645     }
646     return _this;
647 }
648
649 #ifndef __GNUC__
650 void __asm_dummy_vtables(void) {
651 #endif
652
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));
667
668 #ifndef __GNUC__
669 }
670 #endif
671
672 #define DEFINE_EXCEPTION_TYPE_INFO(name, base_classes, cl1, cl2) \
673 static const cxx_type_info name ## _cxx_type_info = \
674 { \
675     0, \
676     &name ## _type_info, \
677     { 0, -1, 0 }, \
678     sizeof(name), \
679     (cxx_copy_ctor)THISCALL(MSVCRT_ ## name ## _copy_ctor) \
680 }; \
681 \
682 static const cxx_type_info_table name ## _type_info_table = \
683 { \
684     base_classes+1, \
685     { \
686         &name ## _cxx_type_info, \
687         cl1, \
688         cl2 \
689     } \
690 }; \
691 \
692 const cxx_exception_type name ## _exception_type = \
693 { \
694     0, \
695     (void *)THISCALL(MSVCRT_ ## name ## _dtor), \
696     NULL, \
697     &name ## _type_info_table \
698 }
699
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@@" );
705
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 );
710
711
712 /******************************************************************
713  *              ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
714  *
715  * Install a handler to be called when terminate() is called.
716  *
717  * PARAMS
718  *  func [I] Handler function to install
719  *
720  * RETURNS
721  *  The previously installed handler function, if any.
722  */
723 MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func)
724 {
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;
729     return previous;
730 }
731
732 /******************************************************************
733  *              _get_terminate (MSVCRT.@)
734  */
735 MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void)
736 {
737     thread_data_t *data = msvcrt_get_thread_data();
738     TRACE("returning %p\n", data->terminate_handler);
739     return data->terminate_handler;
740 }
741
742 /******************************************************************
743  *              ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
744  *
745  * Install a handler to be called when unexpected() is called.
746  *
747  * PARAMS
748  *  func [I] Handler function to install
749  *
750  * RETURNS
751  *  The previously installed handler function, if any.
752  */
753 MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
754 {
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;
759     return previous;
760 }
761
762 /******************************************************************
763  *              _get_unexpected (MSVCRT.@)
764  */
765 MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void)
766 {
767     thread_data_t *data = msvcrt_get_thread_data();
768     TRACE("returning %p\n", data->unexpected_handler);
769     return data->unexpected_handler;
770 }
771
772 /******************************************************************
773  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
774  */
775 MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
776 {
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;
781     return previous;
782 }
783
784 /******************************************************************
785  *              ?terminate@@YAXXZ (MSVCRT.@)
786  *
787  * Default handler for an unhandled exception.
788  *
789  * PARAMS
790  *  None.
791  *
792  * RETURNS
793  *  This function does not return. Either control resumes from any
794  *  handler installed by calling set_terminate(), or (by default) abort()
795  *  is called.
796  */
797 void CDECL MSVCRT_terminate(void)
798 {
799     thread_data_t *data = msvcrt_get_thread_data();
800     if (data->terminate_handler) data->terminate_handler();
801     MSVCRT_abort();
802 }
803
804 /******************************************************************
805  *              ?unexpected@@YAXXZ (MSVCRT.@)
806  */
807 void CDECL MSVCRT_unexpected(void)
808 {
809     thread_data_t *data = msvcrt_get_thread_data();
810     if (data->unexpected_handler) data->unexpected_handler();
811     MSVCRT_terminate();
812 }
813
814
815 /******************************************************************
816  *              __RTtypeid (MSVCRT.@)
817  *
818  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
819  *
820  * PARAMS
821  *  cppobj [I] C++ object to get type information for.
822  *
823  * RETURNS
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.
828  *
829  * NOTES
830  *  This function is usually called by compiler generated code as a result
831  *  of using one of the C++ dynamic cast statements.
832  */
833 #ifndef __x86_64__
834 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
835 {
836     const type_info *ret;
837
838     if (!cppobj)
839     {
840         bad_typeid e;
841         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
842         _CxxThrowException( &e, &bad_typeid_exception_type );
843         return NULL;
844     }
845
846     __TRY
847     {
848         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
849         ret = obj_locator->type_descriptor;
850     }
851     __EXCEPT_PAGE_FAULT
852     {
853         __non_rtti_object e;
854         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
855         _CxxThrowException( &e, &bad_typeid_exception_type );
856         return NULL;
857     }
858     __ENDTRY
859     return ret;
860 }
861
862 #else
863
864 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
865 {
866     const type_info *ret;
867
868     if (!cppobj)
869     {
870         bad_typeid e;
871         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
872         _CxxThrowException( &e, &bad_typeid_exception_type );
873         return NULL;
874     }
875
876     __TRY
877     {
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;
882         else
883         {
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);
886         }
887     }
888     __EXCEPT_PAGE_FAULT
889     {
890         __non_rtti_object e;
891         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
892         _CxxThrowException( &e, &bad_typeid_exception_type );
893         return NULL;
894     }
895     __ENDTRY
896     return ret;
897 }
898 #endif
899
900 /******************************************************************
901  *              __RTDynamicCast (MSVCRT.@)
902  *
903  * Dynamically cast a C++ object to one of its base classes.
904  *
905  * PARAMS
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
911  *
912  * RETURNS
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.
917  *
918  * NOTES
919  *  This function is usually called by compiler generated code as a result
920  *  of using one of the C++ dynamic cast statements.
921  */
922 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
923                                    type_info *src, type_info *dst,
924                                    int do_throw)
925 {
926     void *ret;
927
928     if (!cppobj) return NULL;
929
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);
932
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
938      *
939      * FIXME: the unknown parameter doesn't seem to be used for anything
940      */
941     __TRY
942     {
943         int i;
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;
947
948         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
949
950         ret = NULL;
951         for (i = 0; i < obj_bases->array_len; i++)
952         {
953             const type_info *typ = base_desc[i]->type_descriptor;
954
955             if (!strcmp(typ->mangled, dst->mangled))
956             {
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 );
960                 break;
961             }
962         }
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.
965          */
966         if (!ret && do_throw)
967         {
968             const char *msg = "Bad dynamic_cast!";
969             bad_cast e;
970             MSVCRT_bad_cast_ctor( &e, &msg );
971             _CxxThrowException( &e, &bad_cast_exception_type );
972         }
973     }
974     __EXCEPT_PAGE_FAULT
975     {
976         __non_rtti_object e;
977         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
978         _CxxThrowException( &e, &bad_typeid_exception_type );
979         return NULL;
980     }
981     __ENDTRY
982     return ret;
983 }
984
985
986 /******************************************************************
987  *              __RTCastToVoid (MSVCRT.@)
988  *
989  * Dynamically cast a C++ object to a void*.
990  *
991  * PARAMS
992  *  cppobj [I] The C++ object to cast
993  *
994  * RETURNS
995  *  Success: The base address of the object as a void*.
996  *  Failure: NULL, if cppobj is NULL or has no RTTI.
997  *
998  * NOTES
999  *  This function is usually called by compiler generated code as a result
1000  *  of using one of the C++ dynamic cast statements.
1001  */
1002 void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
1003 {
1004     void *ret;
1005
1006     if (!cppobj) return NULL;
1007
1008     __TRY
1009     {
1010         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1011         ret = (char *)cppobj - obj_locator->base_class_offset;
1012     }
1013     __EXCEPT_PAGE_FAULT
1014     {
1015         __non_rtti_object e;
1016         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1017         _CxxThrowException( &e, &bad_typeid_exception_type );
1018         return NULL;
1019     }
1020     __ENDTRY
1021     return ret;
1022 }
1023
1024
1025 /*********************************************************************
1026  *              _CxxThrowException (MSVCRT.@)
1027  */
1028 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
1029 {
1030     ULONG_PTR args[3];
1031
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 );
1036 }