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