msvcrt: Support 64-bit RTTI in __RTDynamicCast.
[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 #ifdef __x86_64__
121 static void dump_obj_locator_x64( const rtti_object_locator_x64 *ptr )
122 {
123     int i;
124     char *base = (char*)ptr - ptr->object_locator;
125     const rtti_object_hierarchy_x64 *h = (const rtti_object_hierarchy_x64*)(base + ptr->type_hierarchy);
126     const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor);
127
128     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
129             ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
130             type_descriptor, dbgstr_type_info(type_descriptor), h );
131     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
132             h->signature, h->attributes, h->array_len, base + h->base_classes );
133     for (i = 0; i < h->array_len; i++)
134     {
135         const rtti_base_descriptor_x64 *bases = (rtti_base_descriptor_x64*)(base +
136                 ((const rtti_base_array_x64*)(base + h->base_classes))->bases[i]);
137
138         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
139                 bases,
140                 bases->num_base_classes,
141                 bases->offsets.this_offset,
142                 bases->offsets.vbase_descr,
143                 bases->offsets.vbase_offset,
144                 bases->attributes,
145                 base + bases->type_descriptor,
146                 dbgstr_type_info((const type_info*)(base + bases->type_descriptor)) );
147     }
148 }
149 #endif
150
151 /* Internal common ctor for exception */
152 static void EXCEPTION_ctor(exception *_this, const char** name)
153 {
154   _this->vtable = &MSVCRT_exception_vtable;
155   if (*name)
156   {
157     unsigned int name_len = strlen(*name) + 1;
158     _this->name = MSVCRT_malloc(name_len);
159     memcpy(_this->name, *name, name_len);
160     _this->do_free = TRUE;
161   }
162   else
163   {
164     _this->name = NULL;
165     _this->do_free = FALSE;
166   }
167 }
168
169 /******************************************************************
170  *              ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
171  */
172 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
173 exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name)
174 {
175   TRACE("(%p,%s)\n", _this, *name);
176   EXCEPTION_ctor(_this, name);
177   return _this;
178 }
179
180 /******************************************************************
181  *              ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
182  */
183 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
184 exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
185 {
186   TRACE("(%p,%s)\n", _this, *name);
187   _this->vtable = &MSVCRT_exception_vtable;
188   _this->name = *name;
189   _this->do_free = FALSE;
190   return _this;
191 }
192
193 /******************************************************************
194  *              ??0exception@@QAE@ABV0@@Z (MSVCRT.@)
195  */
196 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
197 exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
198 {
199   TRACE("(%p,%p)\n", _this, rhs);
200
201   if (!rhs->do_free)
202   {
203     _this->vtable = &MSVCRT_exception_vtable;
204     _this->name = rhs->name;
205     _this->do_free = FALSE;
206   }
207   else
208     EXCEPTION_ctor(_this, (const char**)&rhs->name);
209   TRACE("name = %s\n", _this->name);
210   return _this;
211 }
212
213 /******************************************************************
214  *              ??0exception@@QAE@XZ (MSVCRT.@)
215  */
216 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
217 exception * __thiscall MSVCRT_exception_default_ctor(exception * _this)
218 {
219   static const char* empty = NULL;
220
221   TRACE("(%p)\n", _this);
222   EXCEPTION_ctor(_this, &empty);
223   return _this;
224 }
225
226 /******************************************************************
227  *              ??1exception@@UAE@XZ (MSVCRT.@)
228  */
229 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
230 void __thiscall MSVCRT_exception_dtor(exception * _this)
231 {
232   TRACE("(%p)\n", _this);
233   _this->vtable = &MSVCRT_exception_vtable;
234   if (_this->do_free) MSVCRT_free(_this->name);
235 }
236
237 /******************************************************************
238  *              ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
239  */
240 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
241 exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
242 {
243   TRACE("(%p %p)\n", _this, rhs);
244   if (_this != rhs)
245   {
246       MSVCRT_exception_dtor(_this);
247       MSVCRT_exception_copy_ctor(_this, rhs);
248   }
249   TRACE("name = %s\n", _this->name);
250   return _this;
251 }
252
253 /******************************************************************
254  *              ??_Eexception@@UAEPAXI@Z (MSVCRT.@)
255  */
256 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
257 void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
258 {
259     TRACE("(%p %x)\n", _this, flags);
260     if (flags & 2)
261     {
262         /* we have an array, with the number of elements stored before the first object */
263         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
264
265         for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
266         MSVCRT_operator_delete(ptr);
267     }
268     else
269     {
270         MSVCRT_exception_dtor(_this);
271         if (flags & 1) MSVCRT_operator_delete(_this);
272     }
273     return _this;
274 }
275
276 /******************************************************************
277  *              ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
278  */
279 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
280 void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
281 {
282     TRACE("(%p %x)\n", _this, flags);
283     MSVCRT_exception_dtor(_this);
284     if (flags & 1) MSVCRT_operator_delete(_this);
285     return _this;
286 }
287
288 /******************************************************************
289  *              ?what@exception@@UBEPBDXZ (MSVCRT.@)
290  */
291 DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
292 const char * __thiscall MSVCRT_what_exception(exception * _this)
293 {
294   TRACE("(%p) returning %s\n", _this, _this->name);
295   return _this->name ? _this->name : "Unknown exception";
296 }
297
298 /******************************************************************
299  *              ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
300  */
301 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
302 bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
303 {
304   TRACE("(%p %p)\n", _this, rhs);
305   MSVCRT_exception_copy_ctor(_this, rhs);
306   _this->vtable = &MSVCRT_bad_typeid_vtable;
307   return _this;
308 }
309
310 /******************************************************************
311  *              ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
312  */
313 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
314 bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
315 {
316   TRACE("(%p %s)\n", _this, name);
317   EXCEPTION_ctor(_this, &name);
318   _this->vtable = &MSVCRT_bad_typeid_vtable;
319   return _this;
320 }
321
322 /******************************************************************
323  *              ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
324  */
325 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
326 bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
327 {
328   return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
329 }
330
331 /******************************************************************
332  *              ??1bad_typeid@@UAE@XZ (MSVCRT.@)
333  */
334 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
335 void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
336 {
337   TRACE("(%p)\n", _this);
338   MSVCRT_exception_dtor(_this);
339 }
340
341 /******************************************************************
342  *              ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
343  */
344 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
345 bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
346 {
347   TRACE("(%p %p)\n", _this, rhs);
348   MSVCRT_exception_opequals(_this, rhs);
349   return _this;
350 }
351
352 /******************************************************************
353  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
354  */
355 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
356 void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
357 {
358     TRACE("(%p %x)\n", _this, flags);
359     if (flags & 2)
360     {
361         /* we have an array, with the number of elements stored before the first object */
362         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
363
364         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
365         MSVCRT_operator_delete(ptr);
366     }
367     else
368     {
369         MSVCRT_bad_typeid_dtor(_this);
370         if (flags & 1) MSVCRT_operator_delete(_this);
371     }
372     return _this;
373 }
374
375 /******************************************************************
376  *              ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
377  */
378 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
379 void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
380 {
381     TRACE("(%p %x)\n", _this, flags);
382     MSVCRT_bad_typeid_dtor(_this);
383     if (flags & 1) MSVCRT_operator_delete(_this);
384     return _this;
385 }
386
387 /******************************************************************
388  *              ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
389  */
390 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
391 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
392                                                                  const __non_rtti_object * rhs)
393 {
394   TRACE("(%p %p)\n", _this, rhs);
395   MSVCRT_bad_typeid_copy_ctor(_this, rhs);
396   _this->vtable = &MSVCRT___non_rtti_object_vtable;
397   return _this;
398 }
399
400 /******************************************************************
401  *              ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
402  */
403 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
404 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
405                                                             const char * name)
406 {
407   TRACE("(%p %s)\n", _this, name);
408   EXCEPTION_ctor(_this, &name);
409   _this->vtable = &MSVCRT___non_rtti_object_vtable;
410   return _this;
411 }
412
413 /******************************************************************
414  *              ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
415  */
416 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
417 void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
418 {
419   TRACE("(%p)\n", _this);
420   MSVCRT_bad_typeid_dtor(_this);
421 }
422
423 /******************************************************************
424  *              ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
425  */
426 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
427 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
428                                                                 const __non_rtti_object *rhs)
429 {
430   TRACE("(%p %p)\n", _this, rhs);
431   MSVCRT_bad_typeid_opequals(_this, rhs);
432   return _this;
433 }
434
435 /******************************************************************
436  *              ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
437  */
438 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
439 void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
440 {
441     TRACE("(%p %x)\n", _this, flags);
442     if (flags & 2)
443     {
444         /* we have an array, with the number of elements stored before the first object */
445         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
446
447         for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
448         MSVCRT_operator_delete(ptr);
449     }
450     else
451     {
452         MSVCRT___non_rtti_object_dtor(_this);
453         if (flags & 1) MSVCRT_operator_delete(_this);
454     }
455     return _this;
456 }
457
458 /******************************************************************
459  *              ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
460  */
461 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
462 void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
463 {
464   TRACE("(%p %x)\n", _this, flags);
465   MSVCRT___non_rtti_object_dtor(_this);
466   if (flags & 1) MSVCRT_operator_delete(_this);
467   return _this;
468 }
469
470 /******************************************************************
471  *              ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
472  *              ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
473  */
474 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
475 bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
476 {
477   TRACE("(%p %s)\n", _this, *name);
478   EXCEPTION_ctor(_this, name);
479   _this->vtable = &MSVCRT_bad_cast_vtable;
480   return _this;
481 }
482
483 /******************************************************************
484  *              ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
485  */
486 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
487 bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
488 {
489   TRACE("(%p %p)\n", _this, rhs);
490   MSVCRT_exception_copy_ctor(_this, rhs);
491   _this->vtable = &MSVCRT_bad_cast_vtable;
492   return _this;
493 }
494
495 /******************************************************************
496  *              ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
497  */
498 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
499 bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
500 {
501   TRACE("(%p %s)\n", _this, name);
502   EXCEPTION_ctor(_this, &name);
503   _this->vtable = &MSVCRT_bad_cast_vtable;
504   return _this;
505 }
506
507 /******************************************************************
508  *              ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
509  */
510 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
511 bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
512 {
513   return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
514 }
515
516 /******************************************************************
517  *              ??1bad_cast@@UAE@XZ (MSVCRT.@)
518  */
519 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
520 void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this)
521 {
522   TRACE("(%p)\n", _this);
523   MSVCRT_exception_dtor(_this);
524 }
525
526 /******************************************************************
527  *              ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
528  */
529 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
530 bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
531 {
532   TRACE("(%p %p)\n", _this, rhs);
533   MSVCRT_exception_opequals(_this, rhs);
534   return _this;
535 }
536
537 /******************************************************************
538  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
539  */
540 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
541 void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
542 {
543     TRACE("(%p %x)\n", _this, flags);
544     if (flags & 2)
545     {
546         /* we have an array, with the number of elements stored before the first object */
547         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
548
549         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
550         MSVCRT_operator_delete(ptr);
551     }
552     else
553     {
554         MSVCRT_bad_cast_dtor(_this);
555         if (flags & 1) MSVCRT_operator_delete(_this);
556     }
557     return _this;
558 }
559
560 /******************************************************************
561  *              ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
562  */
563 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
564 void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
565 {
566   TRACE("(%p %x)\n", _this, flags);
567   MSVCRT_bad_cast_dtor(_this);
568   if (flags & 1) MSVCRT_operator_delete(_this);
569   return _this;
570 }
571
572 /******************************************************************
573  *              ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
574  */
575 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
576 int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
577 {
578     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
579     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
580     return ret;
581 }
582
583 /******************************************************************
584  *              ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
585  */
586 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
587 int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
588 {
589     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
590     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
591     return ret;
592 }
593
594 /******************************************************************
595  *              ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
596  */
597 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
598 int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
599 {
600     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
601     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
602     return ret;
603 }
604
605 /******************************************************************
606  *              ??1type_info@@UAE@XZ (MSVCRT.@)
607  */
608 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
609 void __thiscall MSVCRT_type_info_dtor(type_info * _this)
610 {
611   TRACE("(%p)\n", _this);
612   MSVCRT_free(_this->name);
613 }
614
615 /******************************************************************
616  *              ?name@type_info@@QBEPBDXZ (MSVCRT.@)
617  */
618 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
619 const char * __thiscall MSVCRT_type_info_name(type_info * _this)
620 {
621   if (!_this->name)
622   {
623     /* Create and set the demangled name */
624     /* Note: mangled name in type_info struct always starts with a '.', while
625      * it isn't valid for mangled name.
626      * Is this '.' really part of the mangled name, or has it some other meaning ?
627      */
628     char* name = __unDName(0, _this->mangled + 1, 0,
629                            MSVCRT_malloc, MSVCRT_free, 0x2800);
630     if (name)
631     {
632       unsigned int len = strlen(name);
633
634       /* It seems _unDName may leave blanks at the end of the demangled name */
635       while (len && name[--len] == ' ')
636         name[len] = '\0';
637
638       if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
639       {
640         /* Another thread set this member since we checked above - use it */
641         MSVCRT_free(name);
642       }
643     }
644   }
645   TRACE("(%p) returning %s\n", _this, _this->name);
646   return _this->name;
647 }
648
649 /******************************************************************
650  *              ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
651  */
652 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
653 const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this)
654 {
655   TRACE("(%p) returning %s\n", _this, _this->mangled);
656   return _this->mangled;
657 }
658
659 /* Unexported */
660 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
661 void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
662 {
663     TRACE("(%p %x)\n", _this, flags);
664     if (flags & 2)
665     {
666         /* we have an array, with the number of elements stored before the first object */
667         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
668
669         for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
670         MSVCRT_operator_delete(ptr);
671     }
672     else
673     {
674         MSVCRT_type_info_dtor(_this);
675         if (flags & 1) MSVCRT_operator_delete(_this);
676     }
677     return _this;
678 }
679
680 #ifndef __GNUC__
681 void __asm_dummy_vtables(void) {
682 #endif
683
684 __ASM_VTABLE(type_info,
685         VTABLE_ADD_FUNC(MSVCRT_type_info_vector_dtor));
686 __ASM_VTABLE(exception,
687         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
688         VTABLE_ADD_FUNC(MSVCRT_what_exception));
689 __ASM_VTABLE(bad_typeid,
690         VTABLE_ADD_FUNC(MSVCRT_bad_typeid_vector_dtor)
691         VTABLE_ADD_FUNC(MSVCRT_what_exception));
692 __ASM_VTABLE(bad_cast,
693         VTABLE_ADD_FUNC(MSVCRT_bad_cast_vector_dtor)
694         VTABLE_ADD_FUNC(MSVCRT_what_exception));
695 __ASM_VTABLE(__non_rtti_object,
696         VTABLE_ADD_FUNC(MSVCRT___non_rtti_object_vector_dtor)
697         VTABLE_ADD_FUNC(MSVCRT_what_exception));
698
699 #ifndef __GNUC__
700 }
701 #endif
702
703 #define DEFINE_EXCEPTION_TYPE_INFO(name, base_classes, cl1, cl2) \
704 static const cxx_type_info name ## _cxx_type_info = \
705 { \
706     0, \
707     &name ## _type_info, \
708     { 0, -1, 0 }, \
709     sizeof(name), \
710     (cxx_copy_ctor)THISCALL(MSVCRT_ ## name ## _copy_ctor) \
711 }; \
712 \
713 static const cxx_type_info_table name ## _type_info_table = \
714 { \
715     base_classes+1, \
716     { \
717         &name ## _cxx_type_info, \
718         cl1, \
719         cl2 \
720     } \
721 }; \
722 \
723 const cxx_exception_type name ## _exception_type = \
724 { \
725     0, \
726     (void *)THISCALL(MSVCRT_ ## name ## _dtor), \
727     NULL, \
728     &name ## _type_info_table \
729 }
730
731 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" );
732 DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@@" );
733 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" );
734 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" );
735 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" );
736
737 DEFINE_EXCEPTION_TYPE_INFO( exception, 0, NULL, NULL );
738 DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL );
739 DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL );
740 DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info );
741
742
743 /******************************************************************
744  *              ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
745  *
746  * Install a handler to be called when terminate() is called.
747  *
748  * PARAMS
749  *  func [I] Handler function to install
750  *
751  * RETURNS
752  *  The previously installed handler function, if any.
753  */
754 MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func)
755 {
756     thread_data_t *data = msvcrt_get_thread_data();
757     MSVCRT_terminate_function previous = data->terminate_handler;
758     TRACE("(%p) returning %p\n",func,previous);
759     data->terminate_handler = func;
760     return previous;
761 }
762
763 /******************************************************************
764  *              _get_terminate (MSVCRT.@)
765  */
766 MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void)
767 {
768     thread_data_t *data = msvcrt_get_thread_data();
769     TRACE("returning %p\n", data->terminate_handler);
770     return data->terminate_handler;
771 }
772
773 /******************************************************************
774  *              ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
775  *
776  * Install a handler to be called when unexpected() is called.
777  *
778  * PARAMS
779  *  func [I] Handler function to install
780  *
781  * RETURNS
782  *  The previously installed handler function, if any.
783  */
784 MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
785 {
786     thread_data_t *data = msvcrt_get_thread_data();
787     MSVCRT_unexpected_function previous = data->unexpected_handler;
788     TRACE("(%p) returning %p\n",func,previous);
789     data->unexpected_handler = func;
790     return previous;
791 }
792
793 /******************************************************************
794  *              _get_unexpected (MSVCRT.@)
795  */
796 MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void)
797 {
798     thread_data_t *data = msvcrt_get_thread_data();
799     TRACE("returning %p\n", data->unexpected_handler);
800     return data->unexpected_handler;
801 }
802
803 /******************************************************************
804  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
805  */
806 MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
807 {
808     thread_data_t *data = msvcrt_get_thread_data();
809     MSVCRT__se_translator_function previous = data->se_translator;
810     TRACE("(%p) returning %p\n",func,previous);
811     data->se_translator = func;
812     return previous;
813 }
814
815 /******************************************************************
816  *              ?terminate@@YAXXZ (MSVCRT.@)
817  *
818  * Default handler for an unhandled exception.
819  *
820  * PARAMS
821  *  None.
822  *
823  * RETURNS
824  *  This function does not return. Either control resumes from any
825  *  handler installed by calling set_terminate(), or (by default) abort()
826  *  is called.
827  */
828 void CDECL MSVCRT_terminate(void)
829 {
830     thread_data_t *data = msvcrt_get_thread_data();
831     if (data->terminate_handler) data->terminate_handler();
832     MSVCRT_abort();
833 }
834
835 /******************************************************************
836  *              ?unexpected@@YAXXZ (MSVCRT.@)
837  */
838 void CDECL MSVCRT_unexpected(void)
839 {
840     thread_data_t *data = msvcrt_get_thread_data();
841     if (data->unexpected_handler) data->unexpected_handler();
842     MSVCRT_terminate();
843 }
844
845
846 /******************************************************************
847  *              __RTtypeid (MSVCRT.@)
848  *
849  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
850  *
851  * PARAMS
852  *  cppobj [I] C++ object to get type information for.
853  *
854  * RETURNS
855  *  Success: A type_info object describing cppobj.
856  *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
857  *           exception is thrown. If cppobj is NULL, a bad_typeid exception
858  *           is thrown. In either case, this function does not return.
859  *
860  * NOTES
861  *  This function is usually called by compiler generated code as a result
862  *  of using one of the C++ dynamic cast statements.
863  */
864 #ifndef __x86_64__
865 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
866 {
867     const type_info *ret;
868
869     if (!cppobj)
870     {
871         bad_typeid e;
872         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
873         _CxxThrowException( &e, &bad_typeid_exception_type );
874         return NULL;
875     }
876
877     __TRY
878     {
879         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
880         ret = obj_locator->type_descriptor;
881     }
882     __EXCEPT_PAGE_FAULT
883     {
884         __non_rtti_object e;
885         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
886         _CxxThrowException( &e, &bad_typeid_exception_type );
887         return NULL;
888     }
889     __ENDTRY
890     return ret;
891 }
892
893 #else
894
895 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
896 {
897     const type_info *ret;
898
899     if (!cppobj)
900     {
901         bad_typeid e;
902         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
903         _CxxThrowException( &e, &bad_typeid_exception_type );
904         return NULL;
905     }
906
907     __TRY
908     {
909         const rtti_object_locator *obj_locator = (rtti_object_locator*)get_obj_locator( cppobj );
910         /* FIXME: Change signature==0 handling when wine generates correct RTTI data on 64-bit systems */
911         if(obj_locator->signature == 0)
912             ret = obj_locator->type_descriptor;
913         else
914         {
915             const rtti_object_locator_x64 *obj_locator_x64 = (const rtti_object_locator_x64*)obj_locator;
916             ret = (type_info*)((char*)obj_locator_x64 - obj_locator_x64->object_locator + obj_locator_x64->type_descriptor);
917         }
918     }
919     __EXCEPT_PAGE_FAULT
920     {
921         __non_rtti_object e;
922         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
923         _CxxThrowException( &e, &bad_typeid_exception_type );
924         return NULL;
925     }
926     __ENDTRY
927     return ret;
928 }
929 #endif
930
931 /******************************************************************
932  *              __RTDynamicCast (MSVCRT.@)
933  *
934  * Dynamically cast a C++ object to one of its base classes.
935  *
936  * PARAMS
937  *  cppobj   [I] Any C++ object to cast
938  *  unknown  [I] Reserved, set to 0
939  *  src      [I] type_info object describing cppobj
940  *  dst      [I] type_info object describing the base class to cast to
941  *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
942  *
943  * RETURNS
944  *  Success: The address of cppobj, cast to the object described by dst.
945  *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
946  *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
947  *           is thrown and this function does not return.
948  *
949  * NOTES
950  *  This function is usually called by compiler generated code as a result
951  *  of using one of the C++ dynamic cast statements.
952  */
953 #ifndef __x86_64__
954 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
955                                    type_info *src, type_info *dst,
956                                    int do_throw)
957 {
958     void *ret;
959
960     if (!cppobj) return NULL;
961
962     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
963           cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
964
965     /* To cast an object at runtime:
966      * 1.Find out the true type of the object from the typeinfo at vtable[-1]
967      * 2.Search for the destination type in the class hierarchy
968      * 3.If destination type is found, return base object address + dest offset
969      *   Otherwise, fail the cast
970      *
971      * FIXME: the unknown parameter doesn't seem to be used for anything
972      */
973     __TRY
974     {
975         int i;
976         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
977         const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
978         const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
979
980         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
981
982         ret = NULL;
983         for (i = 0; i < obj_bases->array_len; i++)
984         {
985             const type_info *typ = base_desc[i]->type_descriptor;
986
987             if (!strcmp(typ->mangled, dst->mangled))
988             {
989                 /* compute the correct this pointer for that base class */
990                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
991                 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
992                 break;
993             }
994         }
995         /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
996          * to a reference, since references cannot be NULL.
997          */
998         if (!ret && do_throw)
999         {
1000             const char *msg = "Bad dynamic_cast!";
1001             bad_cast e;
1002             MSVCRT_bad_cast_ctor( &e, &msg );
1003             _CxxThrowException( &e, &bad_cast_exception_type );
1004         }
1005     }
1006     __EXCEPT_PAGE_FAULT
1007     {
1008         __non_rtti_object e;
1009         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1010         _CxxThrowException( &e, &bad_typeid_exception_type );
1011         return NULL;
1012     }
1013     __ENDTRY
1014     return ret;
1015 }
1016
1017 #else
1018
1019 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
1020         type_info *src, type_info *dst,
1021         int do_throw)
1022 {
1023     void *ret;
1024
1025     if (!cppobj) return NULL;
1026
1027     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
1028             cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
1029
1030     __TRY
1031     {
1032         int i;
1033         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1034
1035         if(obj_locator->signature == 0)
1036         {
1037             const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
1038             const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
1039
1040             if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
1041
1042             ret = NULL;
1043             for (i = 0; i < obj_bases->array_len; i++)
1044             {
1045                 const type_info *typ = base_desc[i]->type_descriptor;
1046
1047                 if (!strcmp(typ->mangled, dst->mangled))
1048                 {
1049                     void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
1050                     ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
1051                     break;
1052                 }
1053             }
1054         }
1055         else
1056         {
1057             const rtti_object_locator_x64 *obj_locator_x64 = (const rtti_object_locator_x64*)obj_locator;
1058             const char *base = (const char*)obj_locator_x64 - obj_locator_x64->object_locator;
1059             const rtti_object_hierarchy_x64 *obj_bases = (const rtti_object_hierarchy_x64*)(base + obj_locator_x64->type_hierarchy);
1060             const rtti_base_array_x64 *base_array = (const rtti_base_array_x64*)(base + obj_bases->base_classes);
1061
1062             if (TRACE_ON(msvcrt)) dump_obj_locator_x64(obj_locator_x64);
1063
1064             ret = NULL;
1065             for (i = 0; i < obj_bases->array_len; i++)
1066             {
1067                 const rtti_base_descriptor_x64 *base_desc = (const rtti_base_descriptor_x64*)(base + base_array->bases[i]);
1068                 const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
1069
1070                 if (!strcmp(typ->mangled, dst->mangled))
1071                 {
1072                     void *this_ptr = (char *)cppobj - obj_locator_x64->base_class_offset;
1073                     ret = get_this_pointer( &base_desc->offsets, this_ptr );
1074                     break;
1075                 }
1076             }
1077         }
1078         if (!ret && do_throw)
1079         {
1080             const char *msg = "Bad dynamic_cast!";
1081             bad_cast e;
1082             MSVCRT_bad_cast_ctor( &e, &msg );
1083             _CxxThrowException( &e, &bad_cast_exception_type );
1084         }
1085     }
1086     __EXCEPT_PAGE_FAULT
1087     {
1088         __non_rtti_object e;
1089         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1090         _CxxThrowException( &e, &bad_typeid_exception_type );
1091         return NULL;
1092     }
1093     __ENDTRY
1094     return ret;
1095 }
1096 #endif
1097
1098
1099 /******************************************************************
1100  *              __RTCastToVoid (MSVCRT.@)
1101  *
1102  * Dynamically cast a C++ object to a void*.
1103  *
1104  * PARAMS
1105  *  cppobj [I] The C++ object to cast
1106  *
1107  * RETURNS
1108  *  Success: The base address of the object as a void*.
1109  *  Failure: NULL, if cppobj is NULL or has no RTTI.
1110  *
1111  * NOTES
1112  *  This function is usually called by compiler generated code as a result
1113  *  of using one of the C++ dynamic cast statements.
1114  */
1115 void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
1116 {
1117     void *ret;
1118
1119     if (!cppobj) return NULL;
1120
1121     __TRY
1122     {
1123         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1124         ret = (char *)cppobj - obj_locator->base_class_offset;
1125     }
1126     __EXCEPT_PAGE_FAULT
1127     {
1128         __non_rtti_object e;
1129         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1130         _CxxThrowException( &e, &bad_typeid_exception_type );
1131         return NULL;
1132     }
1133     __ENDTRY
1134     return ret;
1135 }
1136
1137
1138 /*********************************************************************
1139  *              _CxxThrowException (MSVCRT.@)
1140  */
1141 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
1142 {
1143     ULONG_PTR args[3];
1144
1145     args[0] = CXX_FRAME_MAGIC_VC6;
1146     args[1] = (ULONG_PTR)object;
1147     args[2] = (ULONG_PTR)type;
1148     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
1149 }