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