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