Test that SafeArrayDestroyData keeps the pointer if FADF_STATIC is
[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     char* name = __unDName(0, _this->mangled, 0,
569                            (malloc_func_t)MSVCRT_malloc,
570                            (free_func_t)MSVCRT_free, 0x2800);
571
572     if (name)
573     {
574       unsigned int len = strlen(name);
575
576       /* It seems _unDName may leave blanks at the end of the demangled name */
577       if (name[len] == ' ')
578         name[len] = '\0';
579
580       _mlock(_EXIT_LOCK2);
581
582       if (_this->name)
583       {
584         /* Another thread set this member since we checked above - use it */
585         MSVCRT_free(name);
586       }
587       else
588         _this->name = name;
589
590       _munlock(_EXIT_LOCK2);
591     }
592   }
593   TRACE("(%p) returning %s\n", _this, _this->name);
594   return _this->name;
595 }
596
597 /******************************************************************
598  *              ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
599  */
600 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name);
601 const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this)
602 {
603   TRACE("(%p) returning %s\n", _this, _this->mangled);
604   return _this->mangled;
605 }
606
607 /* Unexported */
608 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor);
609 void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
610 {
611     TRACE("(%p %x)\n", _this, flags);
612     if (flags & 2)
613     {
614         /* we have an array, with the number of elements stored before the first object */
615         int i, *ptr = (int *)_this - 1;
616
617         for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
618         MSVCRT_operator_delete(ptr);
619     }
620     else
621     {
622         MSVCRT_type_info_dtor(_this);
623         if (flags & 1) MSVCRT_operator_delete(_this);
624     }
625     return _this;
626 }
627
628 /* vtables */
629
630 #define __ASM_VTABLE(name,funcs) \
631     __asm__(".align 4\n" \
632             "\t.long " __ASM_NAME(#name "_rtti") "\n" \
633             "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
634             __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \
635             "\t.long " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \
636             funcs);
637
638 #define __ASM_EXCEPTION_VTABLE(name) \
639     __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCRT_what_exception) );
640
641 #ifndef __GNUC__
642 void __asm_dummy_vtables(void) {
643 #endif
644
645 __ASM_VTABLE(type_info,"");
646 __ASM_EXCEPTION_VTABLE(exception);
647 __ASM_EXCEPTION_VTABLE(bad_typeid);
648 __ASM_EXCEPTION_VTABLE(bad_cast);
649 __ASM_EXCEPTION_VTABLE(__non_rtti_object);
650
651 #ifndef __GNUC__
652 }
653 #endif
654
655 /* Static RTTI for exported objects */
656
657 static const type_info exception_type_info =
658 {
659   &MSVCRT_type_info_vtable,
660   NULL,
661   ".?AVexception@@"
662 };
663
664 static const rtti_base_descriptor exception_rtti_base_descriptor =
665 {
666   &exception_type_info,
667   0,
668   { 0, -1, 0 },
669   0
670 };
671
672 static const rtti_base_array exception_rtti_base_array =
673 {
674   {
675     &exception_rtti_base_descriptor,
676     NULL,
677     NULL
678   }
679 };
680
681 static const rtti_object_hierarchy exception_type_hierarchy =
682 {
683   0,
684   0,
685   1,
686   &exception_rtti_base_array
687 };
688
689 const rtti_object_locator exception_rtti =
690 {
691   0,
692   0,
693   0,
694   &exception_type_info,
695   &exception_type_hierarchy
696 };
697
698 static const cxx_type_info exception_cxx_type_info =
699 {
700   0,
701   &exception_type_info,
702   { 0, -1, 0 },
703   sizeof(exception),
704   (cxx_copy_ctor)THISCALL(MSVCRT_exception_copy_ctor)
705 };
706
707 static const type_info bad_typeid_type_info =
708 {
709   &MSVCRT_type_info_vtable,
710   NULL,
711   ".?AVbad_typeid@@"
712 };
713
714 static const rtti_base_descriptor bad_typeid_rtti_base_descriptor =
715 {
716   &bad_typeid_type_info,
717   1,
718   { 0, -1, 0 },
719   0
720 };
721
722 static const rtti_base_array bad_typeid_rtti_base_array =
723 {
724   {
725     &bad_typeid_rtti_base_descriptor,
726     &exception_rtti_base_descriptor,
727     NULL
728   }
729 };
730
731 static const rtti_object_hierarchy bad_typeid_type_hierarchy =
732 {
733   0,
734   0,
735   2,
736   &bad_typeid_rtti_base_array
737 };
738
739 const rtti_object_locator bad_typeid_rtti =
740 {
741   0,
742   0,
743   0,
744   &bad_typeid_type_info,
745   &bad_typeid_type_hierarchy
746 };
747
748 static const cxx_type_info bad_typeid_cxx_type_info =
749 {
750   0,
751   &bad_typeid_type_info,
752   { 0, -1, 0 },
753   sizeof(exception),
754   (cxx_copy_ctor)THISCALL(MSVCRT_bad_typeid_copy_ctor)
755 };
756
757 static const type_info bad_cast_type_info =
758 {
759   &MSVCRT_type_info_vtable,
760   NULL,
761   ".?AVbad_cast@@"
762 };
763
764 static const rtti_base_descriptor bad_cast_rtti_base_descriptor =
765 {
766   &bad_cast_type_info,
767   1,
768   { 0, -1, 0 },
769   0
770 };
771
772 static const rtti_base_array bad_cast_rtti_base_array =
773 {
774   {
775     &bad_cast_rtti_base_descriptor,
776     &exception_rtti_base_descriptor,
777     NULL
778   }
779 };
780
781 static const rtti_object_hierarchy bad_cast_type_hierarchy =
782 {
783   0,
784   0,
785   2,
786   &bad_cast_rtti_base_array
787 };
788
789 const rtti_object_locator bad_cast_rtti =
790 {
791   0,
792   0,
793   0,
794   &bad_cast_type_info,
795   &bad_cast_type_hierarchy
796 };
797
798 static const cxx_type_info bad_cast_cxx_type_info =
799 {
800   0,
801   &bad_cast_type_info,
802   { 0, -1, 0 },
803   sizeof(exception),
804   (cxx_copy_ctor)THISCALL(MSVCRT_bad_cast_copy_ctor)
805 };
806
807 static const type_info __non_rtti_object_type_info =
808 {
809   &MSVCRT_type_info_vtable,
810   NULL,
811   ".?AV__non_rtti_object@@"
812 };
813
814 static const rtti_base_descriptor __non_rtti_object_rtti_base_descriptor =
815 {
816   &__non_rtti_object_type_info,
817   2,
818   { 0, -1, 0 },
819   0
820 };
821
822 static const rtti_base_array __non_rtti_object_rtti_base_array =
823 {
824   {
825     &__non_rtti_object_rtti_base_descriptor,
826     &bad_typeid_rtti_base_descriptor,
827     &exception_rtti_base_descriptor
828   }
829 };
830
831 static const rtti_object_hierarchy __non_rtti_object_type_hierarchy =
832 {
833   0,
834   0,
835   3,
836   &__non_rtti_object_rtti_base_array
837 };
838
839 const rtti_object_locator __non_rtti_object_rtti =
840 {
841   0,
842   0,
843   0,
844   &__non_rtti_object_type_info,
845   &__non_rtti_object_type_hierarchy
846 };
847
848 static const cxx_type_info __non_rtti_object_cxx_type_info =
849 {
850   0,
851   &__non_rtti_object_type_info,
852   { 0, -1, 0 },
853   sizeof(exception),
854   (cxx_copy_ctor)THISCALL(MSVCRT___non_rtti_object_copy_ctor)
855 };
856
857 static const type_info type_info_type_info =
858 {
859   &MSVCRT_type_info_vtable,
860   NULL,
861   ".?AVtype_info@@"
862 };
863
864 static const rtti_base_descriptor type_info_rtti_base_descriptor =
865 {
866   &type_info_type_info,
867   0,
868   { 0, -1, 0 },
869   0
870 };
871
872 static const rtti_base_array type_info_rtti_base_array =
873 {
874   {
875     &type_info_rtti_base_descriptor,
876     NULL,
877     NULL
878   }
879 };
880
881 static const rtti_object_hierarchy type_info_type_hierarchy =
882 {
883   0,
884   0,
885   1,
886   &type_info_rtti_base_array
887 };
888
889 const rtti_object_locator type_info_rtti =
890 {
891   0,
892   0,
893   0,
894   &type_info_type_info,
895   &type_info_type_hierarchy
896 };
897
898 /*
899  * Exception RTTI for cpp objects
900  */
901 static const cxx_type_info_table bad_cast_type_info_table =
902 {
903   3,
904   {
905    &__non_rtti_object_cxx_type_info,
906    &bad_typeid_cxx_type_info,
907    &exception_cxx_type_info
908   }
909 };
910
911 static const cxx_exception_type bad_cast_exception_type =
912 {
913   0,
914   (void*)THISCALL(MSVCRT_bad_cast_dtor),
915   NULL,
916   &bad_cast_type_info_table
917 };
918
919 static const cxx_type_info_table bad_typeid_type_info_table =
920 {
921   2,
922   {
923    &bad_cast_cxx_type_info,
924    &exception_cxx_type_info,
925    NULL
926   }
927 };
928
929 static const cxx_exception_type bad_typeid_exception_type =
930 {
931   0,
932   (void*)THISCALL(MSVCRT_bad_typeid_dtor),
933   NULL,
934   &bad_cast_type_info_table
935 };
936
937 static const cxx_exception_type __non_rtti_object_exception_type =
938 {
939   0,
940   (void*)THISCALL(MSVCRT___non_rtti_object_dtor),
941   NULL,
942   &bad_typeid_type_info_table
943 };
944
945
946 /******************************************************************
947  *              ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
948  *
949  * Install a handler to be called when terminate() is called.
950  *
951  * PARAMS
952  *  func [I] Handler function to install
953  *
954  * RETURNS
955  *  The previously installed handler function, if any.
956  */
957 MSVCRT_terminate_function MSVCRT_set_terminate(MSVCRT_terminate_function func)
958 {
959     thread_data_t *data = msvcrt_get_thread_data();
960     MSVCRT_terminate_function previous = data->terminate_handler;
961     TRACE("(%p) returning %p\n",func,previous);
962     data->terminate_handler = func;
963     return previous;
964 }
965
966 /******************************************************************
967  *              ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
968  *
969  * Install a handler to be called when unexpected() is called.
970  *
971  * PARAMS
972  *  func [I] Handler function to install
973  *
974  * RETURNS
975  *  The previously installed handler function, if any.
976  */
977 MSVCRT_unexpected_function MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
978 {
979     thread_data_t *data = msvcrt_get_thread_data();
980     MSVCRT_unexpected_function previous = data->unexpected_handler;
981     TRACE("(%p) returning %p\n",func,previous);
982     data->unexpected_handler = func;
983     return previous;
984 }
985
986 /******************************************************************
987  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
988  */
989 MSVCRT__se_translator_function MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
990 {
991     thread_data_t *data = msvcrt_get_thread_data();
992     MSVCRT__se_translator_function previous = data->se_translator;
993     TRACE("(%p) returning %p\n",func,previous);
994     data->se_translator = func;
995     return previous;
996 }
997
998 /******************************************************************
999  *              ?terminate@@YAXXZ (MSVCRT.@)
1000  *
1001  * Default handler for an unhandled exception.
1002  *
1003  * PARAMS
1004  *  None.
1005  *
1006  * RETURNS
1007  *  This function does not return. Either control resumes from any
1008  *  handler installed by calling set_terminate(), or (by default) abort()
1009  *  is called.
1010  */
1011 void MSVCRT_terminate(void)
1012 {
1013     thread_data_t *data = msvcrt_get_thread_data();
1014     if (data->terminate_handler) data->terminate_handler();
1015     MSVCRT_abort();
1016 }
1017
1018 /******************************************************************
1019  *              ?unexpected@@YAXXZ (MSVCRT.@)
1020  */
1021 void MSVCRT_unexpected(void)
1022 {
1023     thread_data_t *data = msvcrt_get_thread_data();
1024     if (data->unexpected_handler) data->unexpected_handler();
1025     MSVCRT_terminate();
1026 }
1027
1028
1029 /******************************************************************
1030  *              __RTtypeid (MSVCRT.@)
1031  *
1032  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
1033  *
1034  * PARAMS
1035  *  cppobj [I] C++ object to get type information for.
1036  *
1037  * RETURNS
1038  *  Success: A type_info object describing cppobj.
1039  *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
1040  *           exception is thrown. If cppobj is NULL, a bad_typeid exception
1041  *           is thrown. In either case, this function does not return.
1042  *
1043  * NOTES
1044  *  This function is usually called by compiler generated code as a result
1045  *  of using one of the C++ dynamic cast statements.
1046  */
1047 const type_info* MSVCRT___RTtypeid(void *cppobj)
1048 {
1049     const type_info *ret;
1050
1051     if (!cppobj)
1052     {
1053         bad_typeid e;
1054         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
1055         _CxxThrowException( &e, &bad_typeid_exception_type );
1056         return NULL;
1057     }
1058
1059     __TRY
1060     {
1061         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1062         ret = obj_locator->type_descriptor;
1063     }
1064     __EXCEPT(page_fault)
1065     {
1066         __non_rtti_object e;
1067         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
1068         _CxxThrowException( &e, &bad_typeid_exception_type );
1069         return NULL;
1070     }
1071     __ENDTRY
1072     return ret;
1073 }
1074
1075 /******************************************************************
1076  *              __RTDynamicCast (MSVCRT.@)
1077  *
1078  * Dynamically cast a C++ object to one of its base classes.
1079  *
1080  * PARAMS
1081  *  cppobj   [I] Any C++ object to cast
1082  *  unknown  [I] Reserved, set to 0
1083  *  src      [I] type_info object describing cppobj
1084  *  dst      [I] type_info object describing the base class to cast to
1085  *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
1086  *
1087  * RETURNS
1088  *  Success: The address of cppobj, cast to the object described by dst.
1089  *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
1090  *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
1091  *           is thrown and this function does not return.
1092  *
1093  * NOTES
1094  *  This function is usually called by compiler generated code as a result
1095  *  of using one of the C++ dynamic cast statements.
1096  */
1097 void* MSVCRT___RTDynamicCast(void *cppobj, int unknown,
1098                              type_info *src, type_info *dst,
1099                              int do_throw)
1100 {
1101     void *ret;
1102
1103     if (!cppobj) return NULL;
1104
1105     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
1106           cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
1107
1108     if (unknown) FIXME("Unknown parameter is non-zero: please report\n");
1109
1110     /* To cast an object at runtime:
1111      * 1.Find out the true type of the object from the typeinfo at vtable[-1]
1112      * 2.Search for the destination type in the class hierarchy
1113      * 3.If destination type is found, return base object address + dest offset
1114      *   Otherwise, fail the cast
1115      */
1116     __TRY
1117     {
1118         int i;
1119         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1120         const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
1121         const rtti_base_descriptor **base_desc = obj_bases->base_classes->bases;
1122
1123         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
1124
1125         ret = NULL;
1126         for (i = 0; i < obj_bases->array_len; i++)
1127         {
1128             const type_info *typ = base_desc[i]->type_descriptor;
1129
1130             if (!strcmp(typ->mangled, dst->mangled))
1131             {
1132                 /* compute the correct this pointer for that base class */
1133                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
1134                 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
1135                 break;
1136             }
1137         }
1138         /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
1139          * to a reference, since references cannot be NULL.
1140          */
1141         if (!ret && do_throw)
1142         {
1143             const char *msg = "Bad dynamic_cast!";
1144             bad_cast e;
1145             MSVCRT_bad_cast_ctor( &e, &msg );
1146             _CxxThrowException( &e, &bad_cast_exception_type );
1147         }
1148     }
1149     __EXCEPT(page_fault)
1150     {
1151         __non_rtti_object e;
1152         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1153         _CxxThrowException( &e, &bad_typeid_exception_type );
1154         return NULL;
1155     }
1156     __ENDTRY
1157     return ret;
1158 }
1159
1160
1161 /******************************************************************
1162  *              __RTCastToVoid (MSVCRT.@)
1163  *
1164  * Dynamically cast a C++ object to a void*.
1165  *
1166  * PARAMS
1167  *  cppobj [I] The C++ object to cast
1168  *
1169  * RETURNS
1170  *  Success: The base address of the object as a void*.
1171  *  Failure: NULL, if cppobj is NULL or has no RTTI.
1172  *
1173  * NOTES
1174  *  This function is usually called by compiler generated code as a result
1175  *  of using one of the C++ dynamic cast statements.
1176  */
1177 void* MSVCRT___RTCastToVoid(void *cppobj)
1178 {
1179     void *ret;
1180
1181     if (!cppobj) return NULL;
1182
1183     __TRY
1184     {
1185         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1186         ret = (char *)cppobj - obj_locator->base_class_offset;
1187     }
1188     __EXCEPT(page_fault)
1189     {
1190         __non_rtti_object e;
1191         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1192         _CxxThrowException( &e, &bad_typeid_exception_type );
1193         return NULL;
1194     }
1195     __ENDTRY
1196     return ret;
1197 }