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