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