xref: /reactos/sdk/lib/crt/wine/cpp.c (revision ae0fa8ba)
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 || defined(__UCRTSUPPORT__)
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     {
1067     }
1068     __ENDTRY
1069 
1070     if(ret == -1)
1071         terminate();
1072     return ret;
1073 }
1074 #else
_is_exception_typeof(const type_info * ti,EXCEPTION_POINTERS * ep)1075 int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
1076 {
1077     int ret = -1;
1078 
1079     TRACE("(%p %p)\n", ti, ep);
1080 
1081     __TRY
1082     {
1083         EXCEPTION_RECORD *rec = ep->ExceptionRecord;
1084 
1085         if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==4 &&
1086                 (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
1087                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
1088                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
1089         {
1090             const cxx_exception_type *et = (cxx_exception_type*)rec->ExceptionInformation[2];
1091             const cxx_type_info_table *tit = (const cxx_type_info_table*)(rec->ExceptionInformation[3]+et->type_info_table);
1092             int i;
1093 
1094             for (i=0; i<tit->count; i++) {
1095                 const cxx_type_info *cti = (const cxx_type_info*)(rec->ExceptionInformation[3]+tit->info[i]);
1096                 const type_info *except_ti = (const type_info*)(rec->ExceptionInformation[3]+cti->type_info);
1097                 if (ti==except_ti || !strcmp(ti->mangled, except_ti->mangled))
1098                 {
1099                     ret = 1;
1100                     break;
1101                 }
1102             }
1103 
1104             if (i == tit->count)
1105                 ret = 0;
1106         }
1107     }
1108     __EXCEPT_PAGE_FAULT
1109     {
1110     }
1111     __ENDTRY
1112 
1113     if(ret == -1)
1114         terminate();
1115     return ret;
1116 }
1117 #endif
1118 
1119 /*********************************************************************
1120  * __clean_type_info_names_internal (MSVCR80.@)
1121  */
__clean_type_info_names_internal(void * p)1122 void CDECL __clean_type_info_names_internal(void *p)
1123 {
1124     FIXME("(%p) stub\n", p);
1125 }
1126 
1127 /*********************************************************************
1128  * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
1129  */
1130 const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node);
1131 DEFINE_THISCALL_WRAPPER(type_info_name_internal_method,8)
type_info_name_internal_method(type_info * _this,struct __type_info_node * node)1132 const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node)
1133 {
1134     static int once;
1135     if (node && !once++) FIXME("type_info_node parameter ignored\n");
1136 
1137     return type_info_name(_this);
1138 }
1139 
1140 #endif /* _MSVCR_VER >= 80 */
1141 
1142 /* std::exception_ptr class helpers */
1143 typedef struct
1144 {
1145     EXCEPTION_RECORD *rec;
1146     int *ref; /* not binary compatible with native msvcr100 */
1147 } exception_ptr;
1148 
1149 #if _MSVCR_VER >= 100
1150 
1151 /*********************************************************************
1152  * ?__ExceptionPtrCreate@@YAXPAX@Z
1153  * ?__ExceptionPtrCreate@@YAXPEAX@Z
1154  */
__ExceptionPtrCreate(exception_ptr * ep)1155 void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
1156 {
1157     TRACE("(%p)\n", ep);
1158 
1159     ep->rec = NULL;
1160     ep->ref = NULL;
1161 }
1162 
1163 #ifdef __ASM_USE_THISCALL_WRAPPER
1164 extern void call_dtor(const cxx_exception_type *type, void *func, void *object);
1165 
1166 __ASM_GLOBAL_FUNC( call_dtor,
1167                    "movl 12(%esp),%ecx\n\t"
1168                    "call *8(%esp)\n\t"
1169                    "ret" );
1170 #elif __x86_64__
call_dtor(const cxx_exception_type * type,unsigned int dtor,void * object)1171 static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object)
1172 {
1173     char *base = RtlPcToFileHeader((void*)type, (void**)&base);
1174     void (__cdecl *func)(void*) = (void*)(base + dtor);
1175     func(object);
1176 }
1177 #else
1178 #define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
1179 #endif
1180 
1181 /*********************************************************************
1182  * ?__ExceptionPtrDestroy@@YAXPAX@Z
1183  * ?__ExceptionPtrDestroy@@YAXPEAX@Z
1184  */
__ExceptionPtrDestroy(exception_ptr * ep)1185 void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
1186 {
1187     TRACE("(%p)\n", ep);
1188 
1189     if (!ep->rec)
1190         return;
1191 
1192     if (!InterlockedDecrement(ep->ref))
1193     {
1194         if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1195         {
1196             const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2];
1197             void *obj = (void*)ep->rec->ExceptionInformation[1];
1198 
1199             if (type && type->destructor) call_dtor(type, type->destructor, obj);
1200             HeapFree(GetProcessHeap(), 0, obj);
1201         }
1202 
1203         HeapFree(GetProcessHeap(), 0, ep->rec);
1204         HeapFree(GetProcessHeap(), 0, ep->ref);
1205     }
1206 }
1207 
1208 /*********************************************************************
1209  * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
1210  * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
1211  */
__ExceptionPtrCopy(exception_ptr * ep,const exception_ptr * copy)1212 void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy)
1213 {
1214     TRACE("(%p %p)\n", ep, copy);
1215 
1216     /* don't destroy object stored in ep */
1217     *ep = *copy;
1218     if (ep->ref)
1219         InterlockedIncrement(copy->ref);
1220 }
1221 
1222 /*********************************************************************
1223  * ?__ExceptionPtrAssign@@YAXPAXPBX@Z
1224  * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
1225  */
__ExceptionPtrAssign(exception_ptr * ep,const exception_ptr * assign)1226 void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign)
1227 {
1228     TRACE("(%p %p)\n", ep, assign);
1229 
1230     /* don't destroy object stored in ep */
1231     if (ep->ref)
1232         InterlockedDecrement(ep->ref);
1233 
1234     *ep = *assign;
1235     if (ep->ref)
1236         InterlockedIncrement(ep->ref);
1237 }
1238 
1239 #endif /* _MSVCR_VER >= 100 */
1240 
1241 /*********************************************************************
1242  * ?__ExceptionPtrRethrow@@YAXPBX@Z
1243  * ?__ExceptionPtrRethrow@@YAXPEBX@Z
1244  */
__ExceptionPtrRethrow(const exception_ptr * ep)1245 void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
1246 {
1247     TRACE("(%p)\n", ep);
1248 
1249     if (!ep->rec)
1250     {
1251         static const char *exception_msg = "bad exception";
1252         exception e;
1253 
1254         exception_ctor(&e, &exception_msg);
1255         _CxxThrowException(&e, &exception_exception_type);
1256         return;
1257     }
1258 
1259     RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
1260             ep->rec->NumberParameters, ep->rec->ExceptionInformation);
1261 }
1262 
1263 #if _MSVCR_VER >= 100
1264 
1265 #ifdef __i386__
1266 extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
1267 #else
call_copy_ctor(void * func,void * this,void * src,int has_vbase)1268 static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
1269 {
1270     TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
1271     if (has_vbase)
1272         ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
1273     else
1274         ((void (__cdecl*)(void*, void*))func)(this, src);
1275 }
1276 #endif
1277 
1278 /*********************************************************************
1279  * ?__ExceptionPtrCurrentException@@YAXPAX@Z
1280  * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
1281  */
1282 #ifndef __x86_64__
__ExceptionPtrCurrentException(exception_ptr * ep)1283 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1284 {
1285     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1286 
1287     TRACE("(%p)\n", ep);
1288 
1289     if (!rec)
1290     {
1291         ep->rec = NULL;
1292         ep->ref = NULL;
1293         return;
1294     }
1295 
1296     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1297     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1298 
1299     *ep->rec = *rec;
1300     *ep->ref = 1;
1301 
1302     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1303     {
1304         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1305         const cxx_type_info *ti;
1306         void **data, *obj;
1307 
1308         ti = et->type_info_table->info[0];
1309         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1310 
1311         obj = (void*)ep->rec->ExceptionInformation[1];
1312         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1313         {
1314             memcpy(data, obj, ti->size);
1315             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1316         }
1317         else if (ti->copy_ctor)
1318         {
1319             call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1320                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1321         }
1322         else
1323             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1324         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1325     }
1326     return;
1327 }
1328 #else
__ExceptionPtrCurrentException(exception_ptr * ep)1329 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1330 {
1331     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1332 
1333     TRACE("(%p)\n", ep);
1334 
1335     if (!rec)
1336     {
1337         ep->rec = NULL;
1338         ep->ref = NULL;
1339         return;
1340     }
1341 
1342     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1343     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1344 
1345     *ep->rec = *rec;
1346     *ep->ref = 1;
1347 
1348     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1349     {
1350         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1351         const cxx_type_info *ti;
1352         void **data, *obj;
1353         char *base = RtlPcToFileHeader((void*)et, (void**)&base);
1354 
1355         ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]);
1356         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1357 
1358         obj = (void*)ep->rec->ExceptionInformation[1];
1359         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1360         {
1361             memcpy(data, obj, ti->size);
1362             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1363         }
1364         else if (ti->copy_ctor)
1365         {
1366             call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1367                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1368         }
1369         else
1370             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1371         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1372     }
1373     return;
1374 }
1375 #endif
1376 
1377 #endif /* _MSVCR_VER >= 100 */
1378 
1379 #if _MSVCR_VER >= 110
1380 /*********************************************************************
1381  * ?__ExceptionPtrToBool@@YA_NPBX@Z
1382  * ?__ExceptionPtrToBool@@YA_NPEBX@Z
1383  */
__ExceptionPtrToBool(exception_ptr * ep)1384 bool __cdecl __ExceptionPtrToBool(exception_ptr *ep)
1385 {
1386     return !!ep->rec;
1387 }
1388 #endif
1389 
1390 #if _MSVCR_VER >= 100
1391 
1392 /*********************************************************************
1393  * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
1394  * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
1395  */
1396 #ifndef __x86_64__
__ExceptionPtrCopyException(exception_ptr * ep,exception * object,const cxx_exception_type * type)1397 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1398         exception *object, const cxx_exception_type *type)
1399 {
1400     const cxx_type_info *ti;
1401     void **data;
1402 
1403     __ExceptionPtrDestroy(ep);
1404 
1405     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1406     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1407     *ep->ref = 1;
1408 
1409     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
1410     ep->rec->ExceptionCode = CXX_EXCEPTION;
1411     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
1412     ep->rec->NumberParameters = 3;
1413     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
1414     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
1415 
1416     ti = type->type_info_table->info[0];
1417     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1418     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1419     {
1420         memcpy(data, object, ti->size);
1421         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1422     }
1423     else if (ti->copy_ctor)
1424     {
1425         call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
1426                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1427     }
1428     else
1429         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
1430     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1431 }
1432 #else
__ExceptionPtrCopyException(exception_ptr * ep,exception * object,const cxx_exception_type * type)1433 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1434         exception *object, const cxx_exception_type *type)
1435 {
1436     const cxx_type_info *ti;
1437     void **data;
1438     char *base;
1439 
1440     RtlPcToFileHeader((void*)type, (void**)&base);
1441     __ExceptionPtrDestroy(ep);
1442 
1443     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1444     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1445     *ep->ref = 1;
1446 
1447     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
1448     ep->rec->ExceptionCode = CXX_EXCEPTION;
1449     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
1450     ep->rec->NumberParameters = 4;
1451     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
1452     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
1453     ep->rec->ExceptionInformation[3] = (ULONG_PTR)base;
1454 
1455     ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]);
1456     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1457     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1458     {
1459         memcpy(data, object, ti->size);
1460         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1461     }
1462     else if (ti->copy_ctor)
1463     {
1464         call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
1465                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1466     }
1467     else
1468         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
1469     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1470 }
1471 #endif
1472 
__ExceptionPtrCompare(const exception_ptr * ep1,const exception_ptr * ep2)1473 bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2)
1474 {
1475     return ep1->rec == ep2->rec;
1476 }
1477 
1478 #endif /* _MSVCR_VER >= 100 */
1479 
1480 #if _MSVCR_VER >= 80 || defined(__UCRTSUPPORT__)
__AdjustPointer(void * obj,const this_ptr_offsets * off)1481 void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off)
1482 {
1483     return get_this_pointer(off, obj);
1484 }
1485 #endif
1486 
1487 #if _MSVCR_VER >= 140 || defined(__UCRTSUPPORT__)
1488 
1489 typedef struct
1490 {
1491     char *name;
1492     char mangled[1];
1493 } type_info140;
1494 
1495 typedef struct
1496 {
1497     SLIST_ENTRY entry;
1498     char name[1];
1499 } type_info_entry;
1500 
type_info_entry_malloc(size_t size)1501 static void* CDECL type_info_entry_malloc(size_t size)
1502 {
1503     type_info_entry *ret = malloc(FIELD_OFFSET(type_info_entry, name) + size);
1504     return ret->name;
1505 }
1506 
type_info_entry_free(void * ptr)1507 static void CDECL type_info_entry_free(void *ptr)
1508 {
1509     ptr = (char*)ptr - FIELD_OFFSET(type_info_entry, name);
1510     free(ptr);
1511 }
1512 
1513 /******************************************************************
1514  *		__std_type_info_compare (UCRTBASE.@)
1515  */
__std_type_info_compare(const type_info140 * l,const type_info140 * r)1516 int CDECL __std_type_info_compare(const type_info140 *l, const type_info140 *r)
1517 {
1518     int ret;
1519 
1520     if (l == r) ret = 0;
1521     else ret = strcmp(l->mangled + 1, r->mangled + 1);
1522     TRACE("(%p %p) returning %d\n", l, r, ret);
1523     return ret;
1524 }
1525 
1526 /******************************************************************
1527  *		__std_type_info_name (UCRTBASE.@)
1528  */
__std_type_info_name(type_info140 * ti,SLIST_HEADER * header)1529 const char* CDECL __std_type_info_name(type_info140 *ti, SLIST_HEADER *header)
1530 {
1531       if (!ti->name)
1532       {
1533           char* name = __unDName(0, ti->mangled + 1, 0,
1534                   type_info_entry_malloc, type_info_entry_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
1535           if (name)
1536           {
1537               unsigned int len = strlen(name);
1538 
1539               while (len && name[--len] == ' ')
1540                   name[len] = '\0';
1541 
1542               if (InterlockedCompareExchangePointer((void**)&ti->name, name, NULL))
1543               {
1544                   type_info_entry_free(name);
1545               }
1546               else
1547               {
1548                   type_info_entry *entry = (type_info_entry*)(name-FIELD_OFFSET(type_info_entry, name));
1549                   InterlockedPushEntrySList(header, &entry->entry);
1550               }
1551           }
1552       }
1553       TRACE("(%p) returning %s\n", ti, ti->name);
1554       return ti->name;
1555 }
1556 
1557 /******************************************************************
1558  *		__std_type_info_destroy_list  (UCRTBASE.@)
1559  */
__std_type_info_destroy_list(SLIST_HEADER * header)1560 void CDECL __std_type_info_destroy_list(SLIST_HEADER *header)
1561 {
1562     SLIST_ENTRY *cur, *next;
1563 
1564     TRACE("(%p)\n", header);
1565 
1566     for(cur = InterlockedFlushSList(header); cur; cur = next)
1567     {
1568         next = cur->Next;
1569         free(cur);
1570     }
1571 }
1572 
1573 /******************************************************************
1574  *              __std_type_info_hash (UCRTBASE.@)
1575  */
__std_type_info_hash(const type_info140 * ti)1576 size_t CDECL __std_type_info_hash(const type_info140 *ti)
1577 {
1578     size_t hash, fnv_prime;
1579     const char *p;
1580 
1581 #ifdef _WIN64
1582     hash = 0xcbf29ce484222325;
1583     fnv_prime = 0x100000001b3;
1584 #else
1585     hash = 0x811c9dc5;
1586     fnv_prime = 0x1000193;
1587 #endif
1588 
1589     TRACE("(%p)->%s\n", ti, ti->mangled);
1590 
1591     for(p = ti->mangled+1; *p; p++) {
1592         hash ^= *p;
1593         hash *= fnv_prime;
1594     }
1595 
1596 #ifdef _WIN64
1597     hash ^= hash >> 32;
1598 #endif
1599 
1600     return hash;
1601 }
1602 
1603 #endif /* _MSVCR_VER >= 140 */
1604