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