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