xref: /reactos/sdk/lib/crt/wine/cpp.c (revision 3a61dd7f)
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 <stdarg.h>
23 #include <stdbool.h>
24 
25 #include "windef.h"
26 #include "winternl.h"
27 #include "wine/exception.h"
28 #include "wine/debug.h"
29 #include "msvcrt.h"
30 #include "mtdll.h"
31 #include "cxx.h"
32 
33 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
34 
35 CREATE_TYPE_INFO_VTABLE
36 CREATE_EXCEPTION_OBJECT(exception)
37 
38 struct __type_info_node
39 {
40     void *memPtr;
41     struct __type_info_node* next;
42 };
43 
44 typedef exception bad_cast;
45 typedef exception bad_typeid;
46 typedef exception __non_rtti_object;
47 
48 extern const vtable_ptr bad_typeid_vtable;
49 extern const vtable_ptr bad_cast_vtable;
50 extern const vtable_ptr __non_rtti_object_vtable;
51 extern const vtable_ptr type_info_vtable;
52 
53 /* get the vtable pointer for a C++ object */
get_vtable(void * obj)54 static inline const vtable_ptr *get_vtable( void *obj )
55 {
56     return *(const vtable_ptr **)obj;
57 }
58 
get_obj_locator(void * cppobj)59 static inline const rtti_object_locator *get_obj_locator( void *cppobj )
60 {
61     const vtable_ptr *vtable = get_vtable( cppobj );
62     return (const rtti_object_locator *)vtable[-1];
63 }
64 
65 #ifndef __x86_64__
dump_obj_locator(const rtti_object_locator * ptr)66 static void dump_obj_locator( const rtti_object_locator *ptr )
67 {
68     int i;
69     const rtti_object_hierarchy *h = ptr->type_hierarchy;
70 
71     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
72            ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
73            ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy );
74     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
75            h->signature, h->attributes, h->array_len, h->base_classes );
76     for (i = 0; i < h->array_len; i++)
77     {
78         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
79                h->base_classes->bases[i],
80                h->base_classes->bases[i]->num_base_classes,
81                h->base_classes->bases[i]->offsets.this_offset,
82                h->base_classes->bases[i]->offsets.vbase_descr,
83                h->base_classes->bases[i]->offsets.vbase_offset,
84                h->base_classes->bases[i]->attributes,
85                h->base_classes->bases[i]->type_descriptor,
86                dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) );
87     }
88 }
89 
90 #else
91 
dump_obj_locator(const rtti_object_locator * ptr)92 static void dump_obj_locator( const rtti_object_locator *ptr )
93 {
94     int i;
95     char *base = ptr->signature == 0 ? RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
96     const rtti_object_hierarchy *h = (const rtti_object_hierarchy*)(base + ptr->type_hierarchy);
97     const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor);
98 
99     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
100             ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
101             type_descriptor, dbgstr_type_info(type_descriptor), h );
102     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
103             h->signature, h->attributes, h->array_len, base + h->base_classes );
104     for (i = 0; i < h->array_len; i++)
105     {
106         const rtti_base_descriptor *bases = (rtti_base_descriptor*)(base +
107                 ((const rtti_base_array*)(base + h->base_classes))->bases[i]);
108 
109         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
110                 bases,
111                 bases->num_base_classes,
112                 bases->offsets.this_offset,
113                 bases->offsets.vbase_descr,
114                 bases->offsets.vbase_offset,
115                 bases->attributes,
116                 base + bases->type_descriptor,
117                 dbgstr_type_info((const type_info*)(base + bases->type_descriptor)) );
118     }
119 }
120 #endif
121 
122 #ifdef __REACTOS__
123 #include <internal/wine_msc.h>
124 #endif /* __REACTOS__ */
125 
126 /******************************************************************
127  *		??0exception@@QAE@ABQBD@Z (MSVCRT.@)
128  */
129 DEFINE_THISCALL_WRAPPER(exception_ctor,8)
exception_ctor(exception * _this,const char ** name)130 exception * __thiscall exception_ctor(exception * _this, const char ** name)
131 {
132   TRACE("(%p,%s)\n", _this, *name);
133   return __exception_ctor(_this, *name, &exception_vtable);
134 }
135 
136 /******************************************************************
137  *		??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
138  */
139 DEFINE_THISCALL_WRAPPER(exception_ctor_noalloc,12)
exception_ctor_noalloc(exception * _this,char ** name,int noalloc)140 exception * __thiscall exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
141 {
142   TRACE("(%p,%s)\n", _this, *name);
143   _this->vtable = &exception_vtable;
144   _this->name = *name;
145   _this->do_free = FALSE;
146   return _this;
147 }
148 
149 /******************************************************************
150  *		??0exception@@QAE@XZ (MSVCRT.@)
151  */
152 DEFINE_THISCALL_WRAPPER(exception_default_ctor,4)
exception_default_ctor(exception * _this)153 exception * __thiscall exception_default_ctor(exception * _this)
154 {
155   TRACE("(%p)\n", _this);
156   return __exception_ctor(_this, NULL, &exception_vtable);
157 }
158 
159 /******************************************************************
160  *		??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
161  */
162 DEFINE_THISCALL_WRAPPER(exception_opequals,8)
exception_opequals(exception * _this,const exception * rhs)163 exception * __thiscall exception_opequals(exception * _this, const exception * rhs)
164 {
165   TRACE("(%p %p)\n", _this, rhs);
166   if (_this != rhs)
167   {
168       exception_dtor(_this);
169       exception_copy_ctor(_this, rhs);
170   }
171   TRACE("name = %s\n", _this->name);
172   return _this;
173 }
174 
175 /******************************************************************
176  *		??_Gexception@@UAEPAXI@Z (MSVCRT.@)
177  */
178 DEFINE_THISCALL_WRAPPER(exception_scalar_dtor,8)
exception_scalar_dtor(exception * _this,unsigned int flags)179 void * __thiscall exception_scalar_dtor(exception * _this, unsigned int flags)
180 {
181     TRACE("(%p %x)\n", _this, flags);
182     exception_dtor(_this);
183     if (flags & 1) operator_delete(_this);
184     return _this;
185 }
186 
187 /******************************************************************
188  *		??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
189  */
190 DEFINE_THISCALL_WRAPPER(bad_typeid_copy_ctor,8)
bad_typeid_copy_ctor(bad_typeid * _this,const bad_typeid * rhs)191 bad_typeid * __thiscall bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
192 {
193   TRACE("(%p %p)\n", _this, rhs);
194   return __exception_copy_ctor(_this, rhs, &bad_typeid_vtable);
195 }
196 
197 /******************************************************************
198  *		??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
199  */
200 DEFINE_THISCALL_WRAPPER(bad_typeid_ctor,8)
bad_typeid_ctor(bad_typeid * _this,const char * name)201 bad_typeid * __thiscall bad_typeid_ctor(bad_typeid * _this, const char * name)
202 {
203   TRACE("(%p %s)\n", _this, name);
204   return __exception_ctor(_this, name, &bad_typeid_vtable);
205 }
206 
207 /******************************************************************
208  *		??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
209  */
210 DEFINE_THISCALL_WRAPPER(bad_typeid_default_ctor,4)
bad_typeid_default_ctor(bad_typeid * _this)211 bad_typeid * __thiscall bad_typeid_default_ctor(bad_typeid * _this)
212 {
213   return bad_typeid_ctor( _this, "bad typeid" );
214 }
215 
216 /******************************************************************
217  *		??1bad_typeid@@UAE@XZ (MSVCRT.@)
218  */
219 DEFINE_THISCALL_WRAPPER(bad_typeid_dtor,4)
bad_typeid_dtor(bad_typeid * _this)220 void __thiscall bad_typeid_dtor(bad_typeid * _this)
221 {
222   TRACE("(%p)\n", _this);
223   exception_dtor(_this);
224 }
225 
226 /******************************************************************
227  *		??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
228  */
229 DEFINE_THISCALL_WRAPPER(bad_typeid_opequals,8)
bad_typeid_opequals(bad_typeid * _this,const bad_typeid * rhs)230 bad_typeid * __thiscall bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
231 {
232   TRACE("(%p %p)\n", _this, rhs);
233   exception_opequals(_this, rhs);
234   return _this;
235 }
236 
237 /******************************************************************
238  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
239  */
240 DEFINE_THISCALL_WRAPPER(bad_typeid_vector_dtor,8)
bad_typeid_vector_dtor(bad_typeid * _this,unsigned int flags)241 void * __thiscall bad_typeid_vector_dtor(bad_typeid * _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_PTR i, *ptr = (INT_PTR *)_this - 1;
248 
249         for (i = *ptr - 1; i >= 0; i--) bad_typeid_dtor(_this + i);
250         operator_delete(ptr);
251     }
252     else
253     {
254         bad_typeid_dtor(_this);
255         if (flags & 1) operator_delete(_this);
256     }
257     return _this;
258 }
259 
260 /******************************************************************
261  *		??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
262  */
263 DEFINE_THISCALL_WRAPPER(bad_typeid_scalar_dtor,8)
bad_typeid_scalar_dtor(bad_typeid * _this,unsigned int flags)264 void * __thiscall bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
265 {
266     TRACE("(%p %x)\n", _this, flags);
267     bad_typeid_dtor(_this);
268     if (flags & 1) operator_delete(_this);
269     return _this;
270 }
271 
272 /******************************************************************
273  *		??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
274  */
275 DEFINE_THISCALL_WRAPPER(__non_rtti_object_copy_ctor,8)
__non_rtti_object_copy_ctor(__non_rtti_object * _this,const __non_rtti_object * rhs)276 __non_rtti_object * __thiscall __non_rtti_object_copy_ctor(__non_rtti_object * _this,
277                                                                  const __non_rtti_object * rhs)
278 {
279     TRACE("(%p %p)\n", _this, rhs);
280     return __exception_copy_ctor(_this, rhs, &__non_rtti_object_vtable);
281 }
282 
283 /******************************************************************
284  *		??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
285  */
286 DEFINE_THISCALL_WRAPPER(__non_rtti_object_ctor,8)
__non_rtti_object_ctor(__non_rtti_object * _this,const char * name)287 __non_rtti_object * __thiscall __non_rtti_object_ctor(__non_rtti_object * _this,
288                                                             const char * name)
289 {
290   TRACE("(%p %s)\n", _this, name);
291   return __exception_ctor(_this, name, &__non_rtti_object_vtable);
292 }
293 
294 /******************************************************************
295  *		??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
296  */
297 DEFINE_THISCALL_WRAPPER(__non_rtti_object_dtor,4)
__non_rtti_object_dtor(__non_rtti_object * _this)298 void __thiscall __non_rtti_object_dtor(__non_rtti_object * _this)
299 {
300   TRACE("(%p)\n", _this);
301   bad_typeid_dtor(_this);
302 }
303 
304 /******************************************************************
305  *		??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
306  */
307 DEFINE_THISCALL_WRAPPER(__non_rtti_object_opequals,8)
__non_rtti_object_opequals(__non_rtti_object * _this,const __non_rtti_object * rhs)308 __non_rtti_object * __thiscall __non_rtti_object_opequals(__non_rtti_object * _this,
309                                                                 const __non_rtti_object *rhs)
310 {
311   TRACE("(%p %p)\n", _this, rhs);
312   bad_typeid_opequals(_this, rhs);
313   return _this;
314 }
315 
316 /******************************************************************
317  *		??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
318  */
319 DEFINE_THISCALL_WRAPPER(__non_rtti_object_vector_dtor,8)
__non_rtti_object_vector_dtor(__non_rtti_object * _this,unsigned int flags)320 void * __thiscall __non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
321 {
322     TRACE("(%p %x)\n", _this, flags);
323     if (flags & 2)
324     {
325         /* we have an array, with the number of elements stored before the first object */
326         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
327 
328         for (i = *ptr - 1; i >= 0; i--) __non_rtti_object_dtor(_this + i);
329         operator_delete(ptr);
330     }
331     else
332     {
333         __non_rtti_object_dtor(_this);
334         if (flags & 1) operator_delete(_this);
335     }
336     return _this;
337 }
338 
339 /******************************************************************
340  *		??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
341  */
342 DEFINE_THISCALL_WRAPPER(__non_rtti_object_scalar_dtor,8)
__non_rtti_object_scalar_dtor(__non_rtti_object * _this,unsigned int flags)343 void * __thiscall __non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
344 {
345   TRACE("(%p %x)\n", _this, flags);
346   __non_rtti_object_dtor(_this);
347   if (flags & 1) operator_delete(_this);
348   return _this;
349 }
350 
351 /******************************************************************
352  *		??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
353  *		??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
354  */
355 DEFINE_THISCALL_WRAPPER(bad_cast_ctor,8)
bad_cast_ctor(bad_cast * _this,const char ** name)356 bad_cast * __thiscall bad_cast_ctor(bad_cast * _this, const char ** name)
357 {
358   TRACE("(%p %s)\n", _this, *name);
359   return __exception_ctor(_this, *name, &bad_cast_vtable);
360 }
361 
362 /******************************************************************
363  *		??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
364  */
365 DEFINE_THISCALL_WRAPPER(bad_cast_copy_ctor,8)
bad_cast_copy_ctor(bad_cast * _this,const bad_cast * rhs)366 bad_cast * __thiscall bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
367 {
368   TRACE("(%p %p)\n", _this, rhs);
369   return __exception_copy_ctor(_this, rhs, &bad_cast_vtable);
370 }
371 
372 /******************************************************************
373  *		??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
374  */
375 DEFINE_THISCALL_WRAPPER(bad_cast_ctor_charptr,8)
bad_cast_ctor_charptr(bad_cast * _this,const char * name)376 bad_cast * __thiscall bad_cast_ctor_charptr(bad_cast * _this, const char * name)
377 {
378   TRACE("(%p %s)\n", _this, name);
379   return __exception_ctor(_this, name, &bad_cast_vtable);
380 }
381 
382 /******************************************************************
383  *		??_Fbad_cast@@QAEXXZ (MSVCRT.@)
384  */
385 DEFINE_THISCALL_WRAPPER(bad_cast_default_ctor,4)
bad_cast_default_ctor(bad_cast * _this)386 bad_cast * __thiscall bad_cast_default_ctor(bad_cast * _this)
387 {
388   return bad_cast_ctor_charptr( _this, "bad cast" );
389 }
390 
391 /******************************************************************
392  *		??1bad_cast@@UAE@XZ (MSVCRT.@)
393  */
394 DEFINE_THISCALL_WRAPPER(bad_cast_dtor,4)
bad_cast_dtor(bad_cast * _this)395 void __thiscall bad_cast_dtor(bad_cast * _this)
396 {
397   TRACE("(%p)\n", _this);
398   exception_dtor(_this);
399 }
400 
401 /******************************************************************
402  *		??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
403  */
404 DEFINE_THISCALL_WRAPPER(bad_cast_opequals,8)
bad_cast_opequals(bad_cast * _this,const bad_cast * rhs)405 bad_cast * __thiscall bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
406 {
407   TRACE("(%p %p)\n", _this, rhs);
408   exception_opequals(_this, rhs);
409   return _this;
410 }
411 
412 /******************************************************************
413  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
414  */
415 DEFINE_THISCALL_WRAPPER(bad_cast_vector_dtor,8)
bad_cast_vector_dtor(bad_cast * _this,unsigned int flags)416 void * __thiscall bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
417 {
418     TRACE("(%p %x)\n", _this, flags);
419     if (flags & 2)
420     {
421         /* we have an array, with the number of elements stored before the first object */
422         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
423 
424         for (i = *ptr - 1; i >= 0; i--) bad_cast_dtor(_this + i);
425         operator_delete(ptr);
426     }
427     else
428     {
429         bad_cast_dtor(_this);
430         if (flags & 1) operator_delete(_this);
431     }
432     return _this;
433 }
434 
435 /******************************************************************
436  *		??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
437  */
438 DEFINE_THISCALL_WRAPPER(bad_cast_scalar_dtor,8)
bad_cast_scalar_dtor(bad_cast * _this,unsigned int flags)439 void * __thiscall bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
440 {
441   TRACE("(%p %x)\n", _this, flags);
442   bad_cast_dtor(_this);
443   if (flags & 1) operator_delete(_this);
444   return _this;
445 }
446 
447 /******************************************************************
448  *		??8type_info@@QBEHABV0@@Z (MSVCRT.@)
449  */
450 DEFINE_THISCALL_WRAPPER(type_info_opequals_equals,8)
type_info_opequals_equals(type_info * _this,const type_info * rhs)451 int __thiscall type_info_opequals_equals(type_info * _this, const type_info * rhs)
452 {
453     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
454     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
455     return ret;
456 }
457 
458 /******************************************************************
459  *		??9type_info@@QBEHABV0@@Z (MSVCRT.@)
460  */
461 DEFINE_THISCALL_WRAPPER(type_info_opnot_equals,8)
type_info_opnot_equals(type_info * _this,const type_info * rhs)462 int __thiscall type_info_opnot_equals(type_info * _this, const type_info * rhs)
463 {
464     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
465     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
466     return ret;
467 }
468 
469 /******************************************************************
470  *		?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
471  */
472 DEFINE_THISCALL_WRAPPER(type_info_before,8)
type_info_before(type_info * _this,const type_info * rhs)473 int __thiscall type_info_before(type_info * _this, const type_info * rhs)
474 {
475     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
476     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
477     return ret;
478 }
479 
480 /******************************************************************
481  *		??1type_info@@UAE@XZ (MSVCRT.@)
482  */
483 DEFINE_THISCALL_WRAPPER(type_info_dtor,4)
type_info_dtor(type_info * _this)484 void __thiscall type_info_dtor(type_info * _this)
485 {
486   TRACE("(%p)\n", _this);
487   free(_this->name);
488 }
489 
490 /******************************************************************
491  *		?name@type_info@@QBEPBDXZ (MSVCRT.@)
492  */
493 DEFINE_THISCALL_WRAPPER(type_info_name,4)
type_info_name(type_info * _this)494 const char * __thiscall type_info_name(type_info * _this)
495 {
496   if (!_this->name)
497   {
498     /* Create and set the demangled name */
499     /* Note: mangled name in type_info struct always starts with a '.', while
500      * it isn't valid for mangled name.
501      * Is this '.' really part of the mangled name, or has it some other meaning ?
502      */
503     char* name = __unDName(0, _this->mangled + 1, 0,
504                            malloc, free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
505     if (name)
506     {
507       unsigned int len = strlen(name);
508 
509       /* It seems _unDName may leave blanks at the end of the demangled name */
510       while (len && name[--len] == ' ')
511         name[len] = '\0';
512 
513       if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
514       {
515         /* Another thread set this member since we checked above - use it */
516         free(name);
517       }
518     }
519   }
520   TRACE("(%p) returning %s\n", _this, _this->name);
521   return _this->name;
522 }
523 
524 /******************************************************************
525  *		?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
526  */
527 DEFINE_THISCALL_WRAPPER(type_info_raw_name,4)
type_info_raw_name(type_info * _this)528 const char * __thiscall type_info_raw_name(type_info * _this)
529 {
530   TRACE("(%p) returning %s\n", _this, _this->mangled);
531   return _this->mangled;
532 }
533 
534 #if _MSVCR_VER >= 80
535 
536 typedef exception bad_alloc;
537 extern const vtable_ptr bad_alloc_vtable;
538 
539 /* bad_alloc class implementation */
540 DEFINE_THISCALL_WRAPPER(bad_alloc_copy_ctor,8)
bad_alloc_copy_ctor(bad_alloc * _this,const bad_alloc * rhs)541 bad_alloc * __thiscall bad_alloc_copy_ctor(bad_alloc * _this, const bad_alloc * rhs)
542 {
543     TRACE("(%p %p)\n", _this, rhs);
544     return __exception_copy_ctor(_this, rhs, &bad_alloc_vtable);
545 }
546 
547 DEFINE_THISCALL_WRAPPER(bad_alloc_dtor,4)
bad_alloc_dtor(bad_alloc * _this)548 void __thiscall bad_alloc_dtor(bad_alloc * _this)
549 {
550     TRACE("(%p)\n", _this);
551     exception_dtor(_this);
552 }
553 
554 #endif /* _MSVCR_VER >= 80 */
555 
556 __ASM_BLOCK_BEGIN(vtables)
557 
558 #if _MSVCR_VER >= 80
559 __ASM_VTABLE(exception_old,
560         VTABLE_ADD_FUNC(exception_vector_dtor)
561         VTABLE_ADD_FUNC(exception_what));
562 __ASM_VTABLE(bad_alloc,
563         VTABLE_ADD_FUNC(exception_vector_dtor)
564         VTABLE_ADD_FUNC(exception_what));
565 #endif
566 __ASM_VTABLE(bad_typeid,
567         VTABLE_ADD_FUNC(bad_typeid_vector_dtor)
568         VTABLE_ADD_FUNC(exception_what));
569 __ASM_VTABLE(bad_cast,
570         VTABLE_ADD_FUNC(bad_cast_vector_dtor)
571         VTABLE_ADD_FUNC(exception_what));
572 __ASM_VTABLE(__non_rtti_object,
573         VTABLE_ADD_FUNC(__non_rtti_object_vector_dtor)
574         VTABLE_ADD_FUNC(exception_what));
575 
576 __ASM_BLOCK_END
577 
578 #if _MSVCR_VER >= 80
579 DEFINE_RTTI_DATA0( exception_old, 0, ".?AVexception@@" )
580 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@std@@" )
581 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@std@@" )
582 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@std@@" )
583 DEFINE_RTTI_DATA1( bad_alloc, 0, &exception_rtti_base_descriptor, ".?AVbad_alloc@std@@" )
584 #else
585 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" )
586 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" )
587 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" )
588 #endif
589 
DEFINE_CXX_EXCEPTION0(exception,exception_dtor)590 DEFINE_CXX_EXCEPTION0( exception, exception_dtor )
591 DEFINE_CXX_DATA1( bad_typeid, &exception_cxx_type_info, bad_typeid_dtor )
592 DEFINE_CXX_DATA1( bad_cast, &exception_cxx_type_info, bad_cast_dtor )
593 DEFINE_CXX_DATA2( __non_rtti_object, &bad_typeid_cxx_type_info,
594         &exception_cxx_type_info, __non_rtti_object_dtor )
595 #if _MSVCR_VER >= 80
596 DEFINE_CXX_DATA1( bad_alloc, &exception_cxx_type_info, bad_alloc_dtor )
597 #endif
598 
599 void msvcrt_init_exception(void *base)
600 {
601 #ifdef __x86_64__
602     init_type_info_rtti(base);
603     init_exception_rtti(base);
604 #if _MSVCR_VER >= 80
605     init_exception_old_rtti(base);
606     init_bad_alloc_rtti(base);
607 #endif
608     init_bad_typeid_rtti(base);
609     init_bad_cast_rtti(base);
610     init___non_rtti_object_rtti(base);
611 
612     init_exception_cxx(base);
613     init_bad_typeid_cxx(base);
614     init_bad_cast_cxx(base);
615     init___non_rtti_object_cxx(base);
616 #if _MSVCR_VER >= 80
617     init_bad_alloc_cxx(base);
618 #endif
619 #endif
620 }
621 
622 #if _MSVCR_VER >= 80
throw_bad_alloc(void)623 void throw_bad_alloc(void)
624 {
625     bad_alloc e;
626     __exception_ctor(&e, "bad allocation", &bad_alloc_vtable);
627     _CxxThrowException(&e, &bad_alloc_exception_type);
628 }
629 #endif
630 
631 /******************************************************************
632  *		?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
633  *
634  * Install a handler to be called when terminate() is called.
635  *
636  * PARAMS
637  *  func [I] Handler function to install
638  *
639  * RETURNS
640  *  The previously installed handler function, if any.
641  */
set_terminate(terminate_function func)642 terminate_function CDECL set_terminate(terminate_function func)
643 {
644     thread_data_t *data = msvcrt_get_thread_data();
645     terminate_function previous = data->terminate_handler;
646     TRACE("(%p) returning %p\n",func,previous);
647     data->terminate_handler = func;
648     return previous;
649 }
650 
651 /******************************************************************
652  *              _get_terminate (MSVCRT.@)
653  */
_get_terminate(void)654 terminate_function CDECL _get_terminate(void)
655 {
656     thread_data_t *data = msvcrt_get_thread_data();
657     TRACE("returning %p\n", data->terminate_handler);
658     return data->terminate_handler;
659 }
660 
661 /******************************************************************
662  *		?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
663  *
664  * Install a handler to be called when unexpected() is called.
665  *
666  * PARAMS
667  *  func [I] Handler function to install
668  *
669  * RETURNS
670  *  The previously installed handler function, if any.
671  */
set_unexpected(unexpected_function func)672 unexpected_function CDECL set_unexpected(unexpected_function func)
673 {
674     thread_data_t *data = msvcrt_get_thread_data();
675     unexpected_function previous = data->unexpected_handler;
676     TRACE("(%p) returning %p\n",func,previous);
677     data->unexpected_handler = func;
678     return previous;
679 }
680 
681 /******************************************************************
682  *              _get_unexpected (MSVCRT.@)
683  */
_get_unexpected(void)684 unexpected_function CDECL _get_unexpected(void)
685 {
686     thread_data_t *data = msvcrt_get_thread_data();
687     TRACE("returning %p\n", data->unexpected_handler);
688     return data->unexpected_handler;
689 }
690 
691 /******************************************************************
692  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
693  */
_set_se_translator(_se_translator_function func)694 _se_translator_function CDECL _set_se_translator(_se_translator_function func)
695 {
696     thread_data_t *data = msvcrt_get_thread_data();
697     _se_translator_function previous = data->se_translator;
698     TRACE("(%p) returning %p\n",func,previous);
699     data->se_translator = func;
700     return previous;
701 }
702 
703 /******************************************************************
704  *		?terminate@@YAXXZ (MSVCRT.@)
705  *
706  * Default handler for an unhandled exception.
707  *
708  * PARAMS
709  *  None.
710  *
711  * RETURNS
712  *  This function does not return. Either control resumes from any
713  *  handler installed by calling set_terminate(), or (by default) abort()
714  *  is called.
715  */
terminate(void)716 void CDECL terminate(void)
717 {
718     thread_data_t *data = msvcrt_get_thread_data();
719     if (data->terminate_handler) data->terminate_handler();
720     abort();
721 }
722 
723 /******************************************************************
724  *		?unexpected@@YAXXZ (MSVCRT.@)
725  */
unexpected(void)726 void CDECL unexpected(void)
727 {
728     thread_data_t *data = msvcrt_get_thread_data();
729     if (data->unexpected_handler) data->unexpected_handler();
730     terminate();
731 }
732 
733 
734 /******************************************************************
735  *		__RTtypeid (MSVCRT.@)
736  *
737  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
738  *
739  * PARAMS
740  *  cppobj [I] C++ object to get type information for.
741  *
742  * RETURNS
743  *  Success: A type_info object describing cppobj.
744  *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
745  *           exception is thrown. If cppobj is NULL, a bad_typeid exception
746  *           is thrown. In either case, this function does not return.
747  *
748  * NOTES
749  *  This function is usually called by compiler generated code as a result
750  *  of using one of the C++ dynamic cast statements.
751  */
752 #ifndef __x86_64__
__RTtypeid(void * cppobj)753 const type_info* CDECL __RTtypeid(void *cppobj)
754 {
755     const type_info *ret;
756 
757     if (!cppobj)
758     {
759         bad_typeid e;
760         bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
761         _CxxThrowException( &e, &bad_typeid_exception_type );
762     }
763 
764     __TRY
765     {
766         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
767         ret = obj_locator->type_descriptor;
768     }
769     __EXCEPT_PAGE_FAULT
770     {
771         __non_rtti_object e;
772         __non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
773         _CxxThrowException( &e, &__non_rtti_object_exception_type );
774     }
775     __ENDTRY
776     return ret;
777 }
778 
779 #else
780 
__RTtypeid(void * cppobj)781 const type_info* CDECL __RTtypeid(void *cppobj)
782 {
783     const type_info *ret;
784 
785     if (!cppobj)
786     {
787         bad_typeid e;
788         bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
789         _CxxThrowException( &e, &bad_typeid_exception_type );
790     }
791 
792     __TRY
793     {
794         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
795         char *base;
796 
797         if(obj_locator->signature == 0)
798             base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
799         else
800             base = (char*)obj_locator - obj_locator->object_locator;
801 
802         ret = (type_info*)(base + obj_locator->type_descriptor);
803     }
804     __EXCEPT_PAGE_FAULT
805     {
806         __non_rtti_object e;
807         __non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
808         _CxxThrowException( &e, &__non_rtti_object_exception_type );
809     }
810     __ENDTRY
811     return ret;
812 }
813 #endif
814 
815 /******************************************************************
816  *		__RTDynamicCast (MSVCRT.@)
817  *
818  * Dynamically cast a C++ object to one of its base classes.
819  *
820  * PARAMS
821  *  cppobj   [I] Any C++ object to cast
822  *  unknown  [I] Reserved, set to 0
823  *  src      [I] type_info object describing cppobj
824  *  dst      [I] type_info object describing the base class to cast to
825  *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
826  *
827  * RETURNS
828  *  Success: The address of cppobj, cast to the object described by dst.
829  *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
830  *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
831  *           is thrown and this function does not return.
832  *
833  * NOTES
834  *  This function is usually called by compiler generated code as a result
835  *  of using one of the C++ dynamic cast statements.
836  */
837 #ifndef __x86_64__
__RTDynamicCast(void * cppobj,int unknown,type_info * src,type_info * dst,int do_throw)838 void* CDECL __RTDynamicCast(void *cppobj, int unknown,
839                                    type_info *src, type_info *dst,
840                                    int do_throw)
841 {
842     void *ret;
843 
844     if (!cppobj) return NULL;
845 
846     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
847           cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
848 
849     /* To cast an object at runtime:
850      * 1.Find out the true type of the object from the typeinfo at vtable[-1]
851      * 2.Search for the destination type in the class hierarchy
852      * 3.If destination type is found, return base object address + dest offset
853      *   Otherwise, fail the cast
854      *
855      * FIXME: the unknown parameter doesn't seem to be used for anything
856      */
857     __TRY
858     {
859         int i;
860         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
861         const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
862         const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
863 
864         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
865 
866         ret = NULL;
867         for (i = 0; i < obj_bases->array_len; i++)
868         {
869             const type_info *typ = base_desc[i]->type_descriptor;
870 
871             if (!strcmp(typ->mangled, dst->mangled))
872             {
873                 /* compute the correct this pointer for that base class */
874                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
875                 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
876                 break;
877             }
878         }
879         /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
880          * to a reference, since references cannot be NULL.
881          */
882         if (!ret && do_throw)
883         {
884             const char *msg = "Bad dynamic_cast!";
885             bad_cast e;
886             bad_cast_ctor( &e, &msg );
887             _CxxThrowException( &e, &bad_cast_exception_type );
888         }
889     }
890     __EXCEPT_PAGE_FAULT
891     {
892         __non_rtti_object e;
893         __non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
894         _CxxThrowException( &e, &__non_rtti_object_exception_type );
895     }
896     __ENDTRY
897     return ret;
898 }
899 
900 #else
901 
__RTDynamicCast(void * cppobj,int unknown,type_info * src,type_info * dst,int do_throw)902 void* CDECL __RTDynamicCast(void *cppobj, int unknown,
903         type_info *src, type_info *dst,
904         int do_throw)
905 {
906     void *ret;
907 
908     if (!cppobj) return NULL;
909 
910     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
911             cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
912 
913     __TRY
914     {
915         int i;
916         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
917         const rtti_object_hierarchy *obj_bases;
918         const rtti_base_array *base_array;
919         char *base;
920 
921         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
922 
923         if(obj_locator->signature == 0)
924             base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
925         else
926             base = (char*)obj_locator - obj_locator->object_locator;
927 
928         obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy);
929         base_array = (const rtti_base_array*)(base + obj_bases->base_classes);
930 
931         ret = NULL;
932         for (i = 0; i < obj_bases->array_len; i++)
933         {
934             const rtti_base_descriptor *base_desc = (const rtti_base_descriptor*)(base + base_array->bases[i]);
935             const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
936 
937             if (!strcmp(typ->mangled, dst->mangled))
938             {
939                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
940                 ret = get_this_pointer( &base_desc->offsets, this_ptr );
941                 break;
942             }
943         }
944         if (!ret && do_throw)
945         {
946             const char *msg = "Bad dynamic_cast!";
947             bad_cast e;
948             bad_cast_ctor( &e, &msg );
949             _CxxThrowException( &e, &bad_cast_exception_type );
950         }
951     }
952     __EXCEPT_PAGE_FAULT
953     {
954         __non_rtti_object e;
955         __non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
956         _CxxThrowException( &e, &__non_rtti_object_exception_type );
957     }
958     __ENDTRY
959     return ret;
960 }
961 #endif
962 
963 
964 /******************************************************************
965  *		__RTCastToVoid (MSVCRT.@)
966  *
967  * Dynamically cast a C++ object to a void*.
968  *
969  * PARAMS
970  *  cppobj [I] The C++ object to cast
971  *
972  * RETURNS
973  *  Success: The base address of the object as a void*.
974  *  Failure: NULL, if cppobj is NULL or has no RTTI.
975  *
976  * NOTES
977  *  This function is usually called by compiler generated code as a result
978  *  of using one of the C++ dynamic cast statements.
979  */
__RTCastToVoid(void * cppobj)980 void* CDECL __RTCastToVoid(void *cppobj)
981 {
982     void *ret;
983 
984     if (!cppobj) return NULL;
985 
986     __TRY
987     {
988         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
989         ret = (char *)cppobj - obj_locator->base_class_offset;
990     }
991     __EXCEPT_PAGE_FAULT
992     {
993         __non_rtti_object e;
994         __non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
995         _CxxThrowException( &e, &__non_rtti_object_exception_type );
996     }
997     __ENDTRY
998     return ret;
999 }
1000 
1001 
1002 /*********************************************************************
1003  *		_CxxThrowException (MSVCRT.@)
1004  */
1005 #ifndef __x86_64__
_CxxThrowException(void * object,const cxx_exception_type * type)1006 void WINAPI _CxxThrowException( void *object, const cxx_exception_type *type )
1007 {
1008     ULONG_PTR args[3];
1009 
1010     args[0] = CXX_FRAME_MAGIC_VC6;
1011     args[1] = (ULONG_PTR)object;
1012     args[2] = (ULONG_PTR)type;
1013     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
1014 }
1015 #else
_CxxThrowException(void * object,const cxx_exception_type * type)1016 void WINAPI _CxxThrowException( void *object, const cxx_exception_type *type )
1017 {
1018     ULONG_PTR args[4];
1019 
1020     args[0] = CXX_FRAME_MAGIC_VC6;
1021     args[1] = (ULONG_PTR)object;
1022     args[2] = (ULONG_PTR)type;
1023     RtlPcToFileHeader( (void*)type, (void**)&args[3]);
1024     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 4, args );
1025 }
1026 #endif
1027 
1028 #if _MSVCR_VER >= 80
1029 
1030 /*********************************************************************
1031  * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z
1032  * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z
1033  */
1034 #ifndef __x86_64__
_is_exception_typeof(const type_info * ti,EXCEPTION_POINTERS * ep)1035 int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
1036 {
1037     int ret = -1;
1038 
1039     TRACE("(%p %p)\n", ti, ep);
1040 
1041     __TRY
1042     {
1043         EXCEPTION_RECORD *rec = ep->ExceptionRecord;
1044 
1045         if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==3 &&
1046                 (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
1047                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
1048                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
1049         {
1050             const cxx_type_info_table *tit = ((cxx_exception_type*)rec->ExceptionInformation[2])->type_info_table;
1051             int i;
1052 
1053             for (i=0; i<tit->count; i++) {
1054                 if (ti==tit->info[i]->type_info || !strcmp(ti->mangled, tit->info[i]->type_info->mangled))
1055                 {
1056                     ret = 1;
1057                     break;
1058                 }
1059             }
1060 
1061             if (i == tit->count)
1062                 ret = 0;
1063         }
1064     }
1065     __EXCEPT_PAGE_FAULT
1066     __ENDTRY
1067 
1068     if(ret == -1)
1069         terminate();
1070     return ret;
1071 }
1072 #else
_is_exception_typeof(const type_info * ti,EXCEPTION_POINTERS * ep)1073 int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
1074 {
1075     int ret = -1;
1076 
1077     TRACE("(%p %p)\n", ti, ep);
1078 
1079     __TRY
1080     {
1081         EXCEPTION_RECORD *rec = ep->ExceptionRecord;
1082 
1083         if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==4 &&
1084                 (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
1085                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
1086                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
1087         {
1088             const cxx_exception_type *et = (cxx_exception_type*)rec->ExceptionInformation[2];
1089             const cxx_type_info_table *tit = (const cxx_type_info_table*)(rec->ExceptionInformation[3]+et->type_info_table);
1090             int i;
1091 
1092             for (i=0; i<tit->count; i++) {
1093                 const cxx_type_info *cti = (const cxx_type_info*)(rec->ExceptionInformation[3]+tit->info[i]);
1094                 const type_info *except_ti = (const type_info*)(rec->ExceptionInformation[3]+cti->type_info);
1095                 if (ti==except_ti || !strcmp(ti->mangled, except_ti->mangled))
1096                 {
1097                     ret = 1;
1098                     break;
1099                 }
1100             }
1101 
1102             if (i == tit->count)
1103                 ret = 0;
1104         }
1105     }
1106     __EXCEPT_PAGE_FAULT
1107     __ENDTRY
1108 
1109     if(ret == -1)
1110         terminate();
1111     return ret;
1112 }
1113 #endif
1114 
1115 /*********************************************************************
1116  * __clean_type_info_names_internal (MSVCR80.@)
1117  */
__clean_type_info_names_internal(void * p)1118 void CDECL __clean_type_info_names_internal(void *p)
1119 {
1120     FIXME("(%p) stub\n", p);
1121 }
1122 
1123 /*********************************************************************
1124  * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
1125  */
1126 DEFINE_THISCALL_WRAPPER(type_info_name_internal_method,8)
type_info_name_internal_method(type_info * _this,struct __type_info_node * node)1127 const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node)
1128 {
1129     static int once;
1130     if (node && !once++) FIXME("type_info_node parameter ignored\n");
1131 
1132     return type_info_name(_this);
1133 }
1134 
1135 #endif /* _MSVCR_VER >= 80 */
1136 
1137 /* std::exception_ptr class helpers */
1138 typedef struct
1139 {
1140     EXCEPTION_RECORD *rec;
1141     int *ref; /* not binary compatible with native msvcr100 */
1142 } exception_ptr;
1143 
1144 #if _MSVCR_VER >= 100
1145 
1146 /*********************************************************************
1147  * ?__ExceptionPtrCreate@@YAXPAX@Z
1148  * ?__ExceptionPtrCreate@@YAXPEAX@Z
1149  */
__ExceptionPtrCreate(exception_ptr * ep)1150 void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
1151 {
1152     TRACE("(%p)\n", ep);
1153 
1154     ep->rec = NULL;
1155     ep->ref = NULL;
1156 }
1157 
1158 #ifdef __ASM_USE_THISCALL_WRAPPER
1159 extern void call_dtor(const cxx_exception_type *type, void *func, void *object);
1160 
1161 __ASM_GLOBAL_FUNC( call_dtor,
1162                    "movl 12(%esp),%ecx\n\t"
1163                    "call *8(%esp)\n\t"
1164                    "ret" );
1165 #elif __x86_64__
call_dtor(const cxx_exception_type * type,unsigned int dtor,void * object)1166 static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object)
1167 {
1168     char *base = RtlPcToFileHeader((void*)type, (void**)&base);
1169     void (__cdecl *func)(void*) = (void*)(base + dtor);
1170     func(object);
1171 }
1172 #else
1173 #define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
1174 #endif
1175 
1176 /*********************************************************************
1177  * ?__ExceptionPtrDestroy@@YAXPAX@Z
1178  * ?__ExceptionPtrDestroy@@YAXPEAX@Z
1179  */
__ExceptionPtrDestroy(exception_ptr * ep)1180 void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
1181 {
1182     TRACE("(%p)\n", ep);
1183 
1184     if (!ep->rec)
1185         return;
1186 
1187     if (!InterlockedDecrement(ep->ref))
1188     {
1189         if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1190         {
1191             const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2];
1192             void *obj = (void*)ep->rec->ExceptionInformation[1];
1193 
1194             if (type && type->destructor) call_dtor(type, type->destructor, obj);
1195             HeapFree(GetProcessHeap(), 0, obj);
1196         }
1197 
1198         HeapFree(GetProcessHeap(), 0, ep->rec);
1199         HeapFree(GetProcessHeap(), 0, ep->ref);
1200     }
1201 }
1202 
1203 /*********************************************************************
1204  * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
1205  * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
1206  */
__ExceptionPtrCopy(exception_ptr * ep,const exception_ptr * copy)1207 void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy)
1208 {
1209     TRACE("(%p %p)\n", ep, copy);
1210 
1211     /* don't destroy object stored in ep */
1212     *ep = *copy;
1213     if (ep->ref)
1214         InterlockedIncrement(copy->ref);
1215 }
1216 
1217 /*********************************************************************
1218  * ?__ExceptionPtrAssign@@YAXPAXPBX@Z
1219  * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
1220  */
__ExceptionPtrAssign(exception_ptr * ep,const exception_ptr * assign)1221 void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign)
1222 {
1223     TRACE("(%p %p)\n", ep, assign);
1224 
1225     /* don't destroy object stored in ep */
1226     if (ep->ref)
1227         InterlockedDecrement(ep->ref);
1228 
1229     *ep = *assign;
1230     if (ep->ref)
1231         InterlockedIncrement(ep->ref);
1232 }
1233 
1234 #endif /* _MSVCR_VER >= 100 */
1235 
1236 /*********************************************************************
1237  * ?__ExceptionPtrRethrow@@YAXPBX@Z
1238  * ?__ExceptionPtrRethrow@@YAXPEBX@Z
1239  */
__ExceptionPtrRethrow(const exception_ptr * ep)1240 void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
1241 {
1242     TRACE("(%p)\n", ep);
1243 
1244     if (!ep->rec)
1245     {
1246         static const char *exception_msg = "bad exception";
1247         exception e;
1248 
1249         exception_ctor(&e, &exception_msg);
1250         _CxxThrowException(&e, &exception_exception_type);
1251         return;
1252     }
1253 
1254     RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
1255             ep->rec->NumberParameters, ep->rec->ExceptionInformation);
1256 }
1257 
1258 #if _MSVCR_VER >= 100
1259 
1260 #ifdef __i386__
1261 extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
1262 #else
call_copy_ctor(void * func,void * this,void * src,int has_vbase)1263 static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
1264 {
1265     TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
1266     if (has_vbase)
1267         ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
1268     else
1269         ((void (__cdecl*)(void*, void*))func)(this, src);
1270 }
1271 #endif
1272 
1273 /*********************************************************************
1274  * ?__ExceptionPtrCurrentException@@YAXPAX@Z
1275  * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
1276  */
1277 #ifndef __x86_64__
__ExceptionPtrCurrentException(exception_ptr * ep)1278 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1279 {
1280     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1281 
1282     TRACE("(%p)\n", ep);
1283 
1284     if (!rec)
1285     {
1286         ep->rec = NULL;
1287         ep->ref = NULL;
1288         return;
1289     }
1290 
1291     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1292     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1293 
1294     *ep->rec = *rec;
1295     *ep->ref = 1;
1296 
1297     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1298     {
1299         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1300         const cxx_type_info *ti;
1301         void **data, *obj;
1302 
1303         ti = et->type_info_table->info[0];
1304         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1305 
1306         obj = (void*)ep->rec->ExceptionInformation[1];
1307         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1308         {
1309             memcpy(data, obj, ti->size);
1310             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1311         }
1312         else if (ti->copy_ctor)
1313         {
1314             call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1315                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1316         }
1317         else
1318             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1319         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1320     }
1321     return;
1322 }
1323 #else
__ExceptionPtrCurrentException(exception_ptr * ep)1324 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1325 {
1326     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1327 
1328     TRACE("(%p)\n", ep);
1329 
1330     if (!rec)
1331     {
1332         ep->rec = NULL;
1333         ep->ref = NULL;
1334         return;
1335     }
1336 
1337     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1338     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1339 
1340     *ep->rec = *rec;
1341     *ep->ref = 1;
1342 
1343     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1344     {
1345         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1346         const cxx_type_info *ti;
1347         void **data, *obj;
1348         char *base = RtlPcToFileHeader((void*)et, (void**)&base);
1349 
1350         ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]);
1351         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1352 
1353         obj = (void*)ep->rec->ExceptionInformation[1];
1354         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1355         {
1356             memcpy(data, obj, ti->size);
1357             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1358         }
1359         else if (ti->copy_ctor)
1360         {
1361             call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1362                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1363         }
1364         else
1365             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1366         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1367     }
1368     return;
1369 }
1370 #endif
1371 
1372 #endif /* _MSVCR_VER >= 100 */
1373 
1374 #if _MSVCR_VER >= 110
1375 /*********************************************************************
1376  * ?__ExceptionPtrToBool@@YA_NPBX@Z
1377  * ?__ExceptionPtrToBool@@YA_NPEBX@Z
1378  */
__ExceptionPtrToBool(exception_ptr * ep)1379 bool __cdecl __ExceptionPtrToBool(exception_ptr *ep)
1380 {
1381     return !!ep->rec;
1382 }
1383 #endif
1384 
1385 #if _MSVCR_VER >= 100
1386 
1387 /*********************************************************************
1388  * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
1389  * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
1390  */
1391 #ifndef __x86_64__
__ExceptionPtrCopyException(exception_ptr * ep,exception * object,const cxx_exception_type * type)1392 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1393         exception *object, const cxx_exception_type *type)
1394 {
1395     const cxx_type_info *ti;
1396     void **data;
1397 
1398     __ExceptionPtrDestroy(ep);
1399 
1400     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1401     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1402     *ep->ref = 1;
1403 
1404     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
1405     ep->rec->ExceptionCode = CXX_EXCEPTION;
1406     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
1407     ep->rec->NumberParameters = 3;
1408     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
1409     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
1410 
1411     ti = type->type_info_table->info[0];
1412     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1413     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1414     {
1415         memcpy(data, object, ti->size);
1416         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1417     }
1418     else if (ti->copy_ctor)
1419     {
1420         call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
1421                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1422     }
1423     else
1424         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
1425     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1426 }
1427 #else
__ExceptionPtrCopyException(exception_ptr * ep,exception * object,const cxx_exception_type * type)1428 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1429         exception *object, const cxx_exception_type *type)
1430 {
1431     const cxx_type_info *ti;
1432     void **data;
1433     char *base;
1434 
1435     RtlPcToFileHeader((void*)type, (void**)&base);
1436     __ExceptionPtrDestroy(ep);
1437 
1438     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1439     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1440     *ep->ref = 1;
1441 
1442     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
1443     ep->rec->ExceptionCode = CXX_EXCEPTION;
1444     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
1445     ep->rec->NumberParameters = 4;
1446     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
1447     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
1448     ep->rec->ExceptionInformation[3] = (ULONG_PTR)base;
1449 
1450     ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]);
1451     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1452     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1453     {
1454         memcpy(data, object, ti->size);
1455         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1456     }
1457     else if (ti->copy_ctor)
1458     {
1459         call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
1460                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1461     }
1462     else
1463         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
1464     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1465 }
1466 #endif
1467 
__ExceptionPtrCompare(const exception_ptr * ep1,const exception_ptr * ep2)1468 bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2)
1469 {
1470     return ep1->rec == ep2->rec;
1471 }
1472 
1473 #endif /* _MSVCR_VER >= 100 */
1474 
1475 #if _MSVCR_VER >= 80
__AdjustPointer(void * obj,const this_ptr_offsets * off)1476 void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off)
1477 {
1478     return get_this_pointer(off, obj);
1479 }
1480 #endif
1481 
1482 #if _MSVCR_VER >= 140
1483 
1484 typedef struct
1485 {
1486     char *name;
1487     char mangled[1];
1488 } type_info140;
1489 
1490 typedef struct
1491 {
1492     SLIST_ENTRY entry;
1493     char name[1];
1494 } type_info_entry;
1495 
type_info_entry_malloc(size_t size)1496 static void* CDECL type_info_entry_malloc(size_t size)
1497 {
1498     type_info_entry *ret = malloc(FIELD_OFFSET(type_info_entry, name) + size);
1499     return ret->name;
1500 }
1501 
type_info_entry_free(void * ptr)1502 static void CDECL type_info_entry_free(void *ptr)
1503 {
1504     ptr = (char*)ptr - FIELD_OFFSET(type_info_entry, name);
1505     free(ptr);
1506 }
1507 
1508 /******************************************************************
1509  *		__std_type_info_compare (UCRTBASE.@)
1510  */
__std_type_info_compare(const type_info140 * l,const type_info140 * r)1511 int CDECL __std_type_info_compare(const type_info140 *l, const type_info140 *r)
1512 {
1513     int ret;
1514 
1515     if (l == r) ret = 0;
1516     else ret = strcmp(l->mangled + 1, r->mangled + 1);
1517     TRACE("(%p %p) returning %d\n", l, r, ret);
1518     return ret;
1519 }
1520 
1521 /******************************************************************
1522  *		__std_type_info_name (UCRTBASE.@)
1523  */
__std_type_info_name(type_info140 * ti,SLIST_HEADER * header)1524 const char* CDECL __std_type_info_name(type_info140 *ti, SLIST_HEADER *header)
1525 {
1526       if (!ti->name)
1527       {
1528           char* name = __unDName(0, ti->mangled + 1, 0,
1529                   type_info_entry_malloc, type_info_entry_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
1530           if (name)
1531           {
1532               unsigned int len = strlen(name);
1533 
1534               while (len && name[--len] == ' ')
1535                   name[len] = '\0';
1536 
1537               if (InterlockedCompareExchangePointer((void**)&ti->name, name, NULL))
1538               {
1539                   type_info_entry_free(name);
1540               }
1541               else
1542               {
1543                   type_info_entry *entry = (type_info_entry*)(name-FIELD_OFFSET(type_info_entry, name));
1544                   InterlockedPushEntrySList(header, &entry->entry);
1545               }
1546           }
1547       }
1548       TRACE("(%p) returning %s\n", ti, ti->name);
1549       return ti->name;
1550 }
1551 
1552 /******************************************************************
1553  *		__std_type_info_destroy_list  (UCRTBASE.@)
1554  */
__std_type_info_destroy_list(SLIST_HEADER * header)1555 void CDECL __std_type_info_destroy_list(SLIST_HEADER *header)
1556 {
1557     SLIST_ENTRY *cur, *next;
1558 
1559     TRACE("(%p)\n", header);
1560 
1561     for(cur = InterlockedFlushSList(header); cur; cur = next)
1562     {
1563         next = cur->Next;
1564         free(cur);
1565     }
1566 }
1567 
1568 /******************************************************************
1569  *              __std_type_info_hash (UCRTBASE.@)
1570  */
__std_type_info_hash(const type_info140 * ti)1571 size_t CDECL __std_type_info_hash(const type_info140 *ti)
1572 {
1573     size_t hash, fnv_prime;
1574     const char *p;
1575 
1576 #ifdef _WIN64
1577     hash = 0xcbf29ce484222325;
1578     fnv_prime = 0x100000001b3;
1579 #else
1580     hash = 0x811c9dc5;
1581     fnv_prime = 0x1000193;
1582 #endif
1583 
1584     TRACE("(%p)->%s\n", ti, ti->mangled);
1585 
1586     for(p = ti->mangled+1; *p; p++) {
1587         hash ^= *p;
1588         hash *= fnv_prime;
1589     }
1590 
1591 #ifdef _WIN64
1592     hash ^= hash >> 32;
1593 #endif
1594 
1595     return hash;
1596 }
1597 
1598 #endif /* _MSVCR_VER >= 140 */
1599