xref: /reactos/sdk/lib/crt/wine/cpp.c (revision 53221834)
1 /*
2  * msvcrt.dll C++ objects
3  *
4  * Copyright 2000 Jon Griffiths
5  * Copyright 2003, 2004 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "config.h"
23 #include "wine/port.h"
24 
25 #include <stdarg.h>
26 
27 #include "windef.h"
28 #include "winternl.h"
29 #include "wine/exception.h"
30 #include "wine/debug.h"
31 #include "msvcrt.h"
32 #include "cppexcept.h"
33 #include "mtdll.h"
34 #include "cxx.h"
35 
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
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 MSVCRT_exception_vtable;
49 extern const vtable_ptr MSVCRT_bad_typeid_vtable;
50 extern const vtable_ptr MSVCRT_bad_cast_vtable;
51 extern const vtable_ptr MSVCRT___non_rtti_object_vtable;
52 extern const vtable_ptr MSVCRT_type_info_vtable;
53 
54 /* get the vtable pointer for a C++ object */
55 static inline const vtable_ptr *get_vtable( void *obj )
56 {
57     return *(const vtable_ptr **)obj;
58 }
59 
60 static inline const rtti_object_locator *get_obj_locator( void *cppobj )
61 {
62     const vtable_ptr *vtable = get_vtable( cppobj );
63     return (const rtti_object_locator *)vtable[-1];
64 }
65 
66 #ifndef __x86_64__
67 static void dump_obj_locator( const rtti_object_locator *ptr )
68 {
69     int i;
70     const rtti_object_hierarchy *h = ptr->type_hierarchy;
71 
72     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
73            ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
74            ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy );
75     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
76            h->signature, h->attributes, h->array_len, h->base_classes );
77     for (i = 0; i < h->array_len; i++)
78     {
79         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
80                h->base_classes->bases[i],
81                h->base_classes->bases[i]->num_base_classes,
82                h->base_classes->bases[i]->offsets.this_offset,
83                h->base_classes->bases[i]->offsets.vbase_descr,
84                h->base_classes->bases[i]->offsets.vbase_offset,
85                h->base_classes->bases[i]->attributes,
86                h->base_classes->bases[i]->type_descriptor,
87                dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) );
88     }
89 }
90 
91 #else
92 
93 static void dump_obj_locator( const rtti_object_locator *ptr )
94 {
95     int i;
96     char *base = ptr->signature == 0 ? RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
97     const rtti_object_hierarchy *h = (const rtti_object_hierarchy*)(base + ptr->type_hierarchy);
98     const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor);
99 
100     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
101             ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
102             type_descriptor, dbgstr_type_info(type_descriptor), h );
103     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
104             h->signature, h->attributes, h->array_len, base + h->base_classes );
105     for (i = 0; i < h->array_len; i++)
106     {
107         const rtti_base_descriptor *bases = (rtti_base_descriptor*)(base +
108                 ((const rtti_base_array*)(base + h->base_classes))->bases[i]);
109 
110         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
111                 bases,
112                 bases->num_base_classes,
113                 bases->offsets.this_offset,
114                 bases->offsets.vbase_descr,
115                 bases->offsets.vbase_offset,
116                 bases->attributes,
117                 base + bases->type_descriptor,
118                 dbgstr_type_info((const type_info*)(base + bases->type_descriptor)) );
119     }
120 }
121 #endif
122 
123 /* Internal common ctor for exception */
124 static void EXCEPTION_ctor(exception *_this, const char** name)
125 {
126   _this->vtable = &MSVCRT_exception_vtable;
127   if (*name)
128   {
129     unsigned int name_len = strlen(*name) + 1;
130     _this->name = MSVCRT_malloc(name_len);
131     memcpy(_this->name, *name, name_len);
132     _this->do_free = TRUE;
133   }
134   else
135   {
136     _this->name = NULL;
137     _this->do_free = FALSE;
138   }
139 }
140 
141 #ifdef __REACTOS__
142 #include <internal/wine_msc.h>
143 #endif /* __REACTOS__ */
144 
145 /******************************************************************
146  *		??0exception@@QAE@ABQBD@Z (MSVCRT.@)
147  */
148 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
149 exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name)
150 {
151   TRACE("(%p,%s)\n", _this, *name);
152   EXCEPTION_ctor(_this, name);
153   return _this;
154 }
155 
156 /******************************************************************
157  *		??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
158  */
159 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
160 exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
161 {
162   TRACE("(%p,%s)\n", _this, *name);
163   _this->vtable = &MSVCRT_exception_vtable;
164   _this->name = *name;
165   _this->do_free = FALSE;
166   return _this;
167 }
168 
169 /******************************************************************
170  *		??0exception@@QAE@ABV0@@Z (MSVCRT.@)
171  */
172 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
173 exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
174 {
175   TRACE("(%p,%p)\n", _this, rhs);
176 
177   if (!rhs->do_free)
178   {
179     _this->vtable = &MSVCRT_exception_vtable;
180     _this->name = rhs->name;
181     _this->do_free = FALSE;
182   }
183   else
184     EXCEPTION_ctor(_this, (const char**)&rhs->name);
185   TRACE("name = %s\n", _this->name);
186   return _this;
187 }
188 
189 /******************************************************************
190  *		??0exception@@QAE@XZ (MSVCRT.@)
191  */
192 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
193 exception * __thiscall MSVCRT_exception_default_ctor(exception * _this)
194 {
195   static const char* empty = NULL;
196 
197   TRACE("(%p)\n", _this);
198   EXCEPTION_ctor(_this, &empty);
199   return _this;
200 }
201 
202 /******************************************************************
203  *		??1exception@@UAE@XZ (MSVCRT.@)
204  */
205 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
206 void __thiscall MSVCRT_exception_dtor(exception * _this)
207 {
208   TRACE("(%p)\n", _this);
209   _this->vtable = &MSVCRT_exception_vtable;
210   if (_this->do_free) MSVCRT_free(_this->name);
211 }
212 
213 /******************************************************************
214  *		??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
215  */
216 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
217 exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
218 {
219   TRACE("(%p %p)\n", _this, rhs);
220   if (_this != rhs)
221   {
222       MSVCRT_exception_dtor(_this);
223       MSVCRT_exception_copy_ctor(_this, rhs);
224   }
225   TRACE("name = %s\n", _this->name);
226   return _this;
227 }
228 
229 /******************************************************************
230  *		??_Eexception@@UAEPAXI@Z (MSVCRT.@)
231  */
232 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
233 void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
234 {
235     TRACE("(%p %x)\n", _this, flags);
236     if (flags & 2)
237     {
238         /* we have an array, with the number of elements stored before the first object */
239         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
240 
241         for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
242         MSVCRT_operator_delete(ptr);
243     }
244     else
245     {
246         MSVCRT_exception_dtor(_this);
247         if (flags & 1) MSVCRT_operator_delete(_this);
248     }
249     return _this;
250 }
251 
252 /******************************************************************
253  *		??_Gexception@@UAEPAXI@Z (MSVCRT.@)
254  */
255 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
256 void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
257 {
258     TRACE("(%p %x)\n", _this, flags);
259     MSVCRT_exception_dtor(_this);
260     if (flags & 1) MSVCRT_operator_delete(_this);
261     return _this;
262 }
263 
264 /******************************************************************
265  *		?what@exception@@UBEPBDXZ (MSVCRT.@)
266  */
267 DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
268 const char * __thiscall MSVCRT_what_exception(exception * _this)
269 {
270   TRACE("(%p) returning %s\n", _this, _this->name);
271   return _this->name ? _this->name : "Unknown exception";
272 }
273 
274 /******************************************************************
275  *		??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
276  */
277 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
278 bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
279 {
280   TRACE("(%p %p)\n", _this, rhs);
281   MSVCRT_exception_copy_ctor(_this, rhs);
282   _this->vtable = &MSVCRT_bad_typeid_vtable;
283   return _this;
284 }
285 
286 /******************************************************************
287  *		??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
288  */
289 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
290 bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
291 {
292   TRACE("(%p %s)\n", _this, name);
293   EXCEPTION_ctor(_this, &name);
294   _this->vtable = &MSVCRT_bad_typeid_vtable;
295   return _this;
296 }
297 
298 /******************************************************************
299  *		??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
300  */
301 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
302 bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
303 {
304   return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
305 }
306 
307 /******************************************************************
308  *		??1bad_typeid@@UAE@XZ (MSVCRT.@)
309  */
310 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
311 void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
312 {
313   TRACE("(%p)\n", _this);
314   MSVCRT_exception_dtor(_this);
315 }
316 
317 /******************************************************************
318  *		??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
319  */
320 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
321 bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
322 {
323   TRACE("(%p %p)\n", _this, rhs);
324   MSVCRT_exception_opequals(_this, rhs);
325   return _this;
326 }
327 
328 /******************************************************************
329  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
330  */
331 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
332 void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
333 {
334     TRACE("(%p %x)\n", _this, flags);
335     if (flags & 2)
336     {
337         /* we have an array, with the number of elements stored before the first object */
338         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
339 
340         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
341         MSVCRT_operator_delete(ptr);
342     }
343     else
344     {
345         MSVCRT_bad_typeid_dtor(_this);
346         if (flags & 1) MSVCRT_operator_delete(_this);
347     }
348     return _this;
349 }
350 
351 /******************************************************************
352  *		??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
353  */
354 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
355 void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
356 {
357     TRACE("(%p %x)\n", _this, flags);
358     MSVCRT_bad_typeid_dtor(_this);
359     if (flags & 1) MSVCRT_operator_delete(_this);
360     return _this;
361 }
362 
363 /******************************************************************
364  *		??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
365  */
366 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
367 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
368                                                                  const __non_rtti_object * rhs)
369 {
370   TRACE("(%p %p)\n", _this, rhs);
371   MSVCRT_bad_typeid_copy_ctor(_this, rhs);
372   _this->vtable = &MSVCRT___non_rtti_object_vtable;
373   return _this;
374 }
375 
376 /******************************************************************
377  *		??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
378  */
379 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
380 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
381                                                             const char * name)
382 {
383   TRACE("(%p %s)\n", _this, name);
384   EXCEPTION_ctor(_this, &name);
385   _this->vtable = &MSVCRT___non_rtti_object_vtable;
386   return _this;
387 }
388 
389 /******************************************************************
390  *		??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
391  */
392 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
393 void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
394 {
395   TRACE("(%p)\n", _this);
396   MSVCRT_bad_typeid_dtor(_this);
397 }
398 
399 /******************************************************************
400  *		??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
401  */
402 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
403 __non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
404                                                                 const __non_rtti_object *rhs)
405 {
406   TRACE("(%p %p)\n", _this, rhs);
407   MSVCRT_bad_typeid_opequals(_this, rhs);
408   return _this;
409 }
410 
411 /******************************************************************
412  *		??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
413  */
414 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
415 void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
416 {
417     TRACE("(%p %x)\n", _this, flags);
418     if (flags & 2)
419     {
420         /* we have an array, with the number of elements stored before the first object */
421         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
422 
423         for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
424         MSVCRT_operator_delete(ptr);
425     }
426     else
427     {
428         MSVCRT___non_rtti_object_dtor(_this);
429         if (flags & 1) MSVCRT_operator_delete(_this);
430     }
431     return _this;
432 }
433 
434 /******************************************************************
435  *		??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
436  */
437 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
438 void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
439 {
440   TRACE("(%p %x)\n", _this, flags);
441   MSVCRT___non_rtti_object_dtor(_this);
442   if (flags & 1) MSVCRT_operator_delete(_this);
443   return _this;
444 }
445 
446 /******************************************************************
447  *		??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
448  *		??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
449  */
450 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
451 bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
452 {
453   TRACE("(%p %s)\n", _this, *name);
454   EXCEPTION_ctor(_this, name);
455   _this->vtable = &MSVCRT_bad_cast_vtable;
456   return _this;
457 }
458 
459 /******************************************************************
460  *		??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
461  */
462 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
463 bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
464 {
465   TRACE("(%p %p)\n", _this, rhs);
466   MSVCRT_exception_copy_ctor(_this, rhs);
467   _this->vtable = &MSVCRT_bad_cast_vtable;
468   return _this;
469 }
470 
471 /******************************************************************
472  *		??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
473  */
474 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
475 bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
476 {
477   TRACE("(%p %s)\n", _this, name);
478   EXCEPTION_ctor(_this, &name);
479   _this->vtable = &MSVCRT_bad_cast_vtable;
480   return _this;
481 }
482 
483 /******************************************************************
484  *		??_Fbad_cast@@QAEXXZ (MSVCRT.@)
485  */
486 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
487 bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
488 {
489   return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
490 }
491 
492 /******************************************************************
493  *		??1bad_cast@@UAE@XZ (MSVCRT.@)
494  */
495 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
496 void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this)
497 {
498   TRACE("(%p)\n", _this);
499   MSVCRT_exception_dtor(_this);
500 }
501 
502 /******************************************************************
503  *		??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
504  */
505 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
506 bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
507 {
508   TRACE("(%p %p)\n", _this, rhs);
509   MSVCRT_exception_opequals(_this, rhs);
510   return _this;
511 }
512 
513 /******************************************************************
514  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
515  */
516 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
517 void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
518 {
519     TRACE("(%p %x)\n", _this, flags);
520     if (flags & 2)
521     {
522         /* we have an array, with the number of elements stored before the first object */
523         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
524 
525         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
526         MSVCRT_operator_delete(ptr);
527     }
528     else
529     {
530         MSVCRT_bad_cast_dtor(_this);
531         if (flags & 1) MSVCRT_operator_delete(_this);
532     }
533     return _this;
534 }
535 
536 /******************************************************************
537  *		??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
538  */
539 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
540 void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
541 {
542   TRACE("(%p %x)\n", _this, flags);
543   MSVCRT_bad_cast_dtor(_this);
544   if (flags & 1) MSVCRT_operator_delete(_this);
545   return _this;
546 }
547 
548 /******************************************************************
549  *		??8type_info@@QBEHABV0@@Z (MSVCRT.@)
550  */
551 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
552 int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
553 {
554     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
555     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
556     return ret;
557 }
558 
559 /******************************************************************
560  *		??9type_info@@QBEHABV0@@Z (MSVCRT.@)
561  */
562 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
563 int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
564 {
565     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
566     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
567     return ret;
568 }
569 
570 /******************************************************************
571  *		?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
572  */
573 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
574 int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
575 {
576     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
577     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
578     return ret;
579 }
580 
581 /******************************************************************
582  *		??1type_info@@UAE@XZ (MSVCRT.@)
583  */
584 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
585 void __thiscall MSVCRT_type_info_dtor(type_info * _this)
586 {
587   TRACE("(%p)\n", _this);
588   MSVCRT_free(_this->name);
589 }
590 
591 /******************************************************************
592  *		?name@type_info@@QBEPBDXZ (MSVCRT.@)
593  */
594 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
595 const char * __thiscall MSVCRT_type_info_name(type_info * _this)
596 {
597   if (!_this->name)
598   {
599     /* Create and set the demangled name */
600     /* Note: mangled name in type_info struct always starts with a '.', while
601      * it isn't valid for mangled name.
602      * Is this '.' really part of the mangled name, or has it some other meaning ?
603      */
604     char* name = __unDName(0, _this->mangled + 1, 0,
605                            MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
606     if (name)
607     {
608       unsigned int len = strlen(name);
609 
610       /* It seems _unDName may leave blanks at the end of the demangled name */
611       while (len && name[--len] == ' ')
612         name[len] = '\0';
613 
614       if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
615       {
616         /* Another thread set this member since we checked above - use it */
617         MSVCRT_free(name);
618       }
619     }
620   }
621   TRACE("(%p) returning %s\n", _this, _this->name);
622   return _this->name;
623 }
624 
625 /******************************************************************
626  *		?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
627  */
628 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
629 const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this)
630 {
631   TRACE("(%p) returning %s\n", _this, _this->mangled);
632   return _this->mangled;
633 }
634 
635 /* Unexported */
636 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
637 void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
638 {
639     TRACE("(%p %x)\n", _this, flags);
640     if (flags & 2)
641     {
642         /* we have an array, with the number of elements stored before the first object */
643         INT_PTR i, *ptr = (INT_PTR *)_this - 1;
644 
645         for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
646         MSVCRT_operator_delete(ptr);
647     }
648     else
649     {
650         MSVCRT_type_info_dtor(_this);
651         if (flags & 1) MSVCRT_operator_delete(_this);
652     }
653     return _this;
654 }
655 
656 #if _MSVCR_VER >= 80
657 
658 typedef exception bad_alloc;
659 extern const vtable_ptr MSVCRT_bad_alloc_vtable;
660 
661 static void bad_alloc_ctor(bad_alloc *this, const char **name)
662 {
663     MSVCRT_exception_ctor(this, name);
664     this->vtable = &MSVCRT_bad_alloc_vtable;
665 }
666 
667 /* bad_alloc class implementation */
668 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_copy_ctor,8)
669 bad_alloc * __thiscall MSVCRT_bad_alloc_copy_ctor(bad_alloc * _this, const bad_alloc * rhs)
670 {
671     TRACE("(%p %p)\n", _this, rhs);
672     MSVCRT_exception_copy_ctor(_this, rhs);
673     _this->vtable = &MSVCRT_bad_alloc_vtable;
674     return _this;
675 }
676 
677 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_dtor,4)
678 void __thiscall MSVCRT_bad_alloc_dtor(bad_alloc * _this)
679 {
680     TRACE("(%p)\n", _this);
681     MSVCRT_exception_dtor(_this);
682 }
683 
684 #endif /* _MSVCR_VER >= 80 */
685 
686 #if _MSVCR_VER >= 100
687 
688 typedef struct {
689     exception e;
690     HRESULT hr;
691 } scheduler_resource_allocation_error;
692 extern const vtable_ptr MSVCRT_scheduler_resource_allocation_error_vtable;
693 
694 /* ??0scheduler_resource_allocation_error@Concurrency@@QAE@PBDJ@Z */
695 /* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@PEBDJ@Z */
696 DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor_name, 12)
697 scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor_name(
698         scheduler_resource_allocation_error *this, const char *name, HRESULT hr)
699 {
700     TRACE("(%p %s %x)\n", this, wine_dbgstr_a(name), hr);
701     MSVCRT_exception_ctor(&this->e, &name);
702     this->e.vtable = &MSVCRT_scheduler_resource_allocation_error_vtable;
703     this->hr = hr;
704     return this;
705 }
706 
707 /* ??0scheduler_resource_allocation_error@Concurrency@@QAE@J@Z */
708 /* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@J@Z */
709 DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor, 8)
710 scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor(
711         scheduler_resource_allocation_error *this, HRESULT hr)
712 {
713     return scheduler_resource_allocation_error_ctor_name(this, NULL, hr);
714 }
715 
716 DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_copy_ctor,8)
717 scheduler_resource_allocation_error* __thiscall MSVCRT_scheduler_resource_allocation_error_copy_ctor(
718         scheduler_resource_allocation_error *this,
719         const scheduler_resource_allocation_error *rhs)
720 {
721     TRACE("(%p,%p)\n", this, rhs);
722 
723     if (!rhs->e.do_free)
724         memcpy(this, rhs, sizeof(*this));
725     else
726         scheduler_resource_allocation_error_ctor_name(this, rhs->e.name, rhs->hr);
727     return this;
728 }
729 
730 /* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QBEJXZ */
731 /* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QEBAJXZ */
732 DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_get_error_code, 4)
733 HRESULT __thiscall scheduler_resource_allocation_error_get_error_code(
734         const scheduler_resource_allocation_error *this)
735 {
736     TRACE("(%p)\n", this);
737     return this->hr;
738 }
739 
740 DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_dtor,4)
741 void __thiscall MSVCRT_scheduler_resource_allocation_error_dtor(
742         scheduler_resource_allocation_error * this)
743 {
744     TRACE("(%p)\n", this);
745     MSVCRT_exception_dtor(&this->e);
746 }
747 
748 typedef exception improper_lock;
749 extern const vtable_ptr MSVCRT_improper_lock_vtable;
750 
751 /* ??0improper_lock@Concurrency@@QAE@PBD@Z */
752 /* ??0improper_lock@Concurrency@@QEAA@PEBD@Z */
753 DEFINE_THISCALL_WRAPPER(improper_lock_ctor_str, 8)
754 improper_lock* __thiscall improper_lock_ctor_str(improper_lock *this, const char *str)
755 {
756     TRACE("(%p %p)\n", this, str);
757     MSVCRT_exception_ctor(this, &str);
758     this->vtable = &MSVCRT_improper_lock_vtable;
759     return this;
760 }
761 
762 /* ??0improper_lock@Concurrency@@QAE@XZ */
763 /* ??0improper_lock@Concurrency@@QEAA@XZ */
764 DEFINE_THISCALL_WRAPPER(improper_lock_ctor, 4)
765 improper_lock* __thiscall improper_lock_ctor(improper_lock *this)
766 {
767     return improper_lock_ctor_str(this, NULL);
768 }
769 
770 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_copy_ctor,8)
771 improper_lock * __thiscall MSVCRT_improper_lock_copy_ctor(improper_lock * _this, const improper_lock * rhs)
772 {
773     TRACE("(%p %p)\n", _this, rhs);
774     MSVCRT_exception_copy_ctor(_this, rhs);
775     _this->vtable = &MSVCRT_improper_lock_vtable;
776     return _this;
777 }
778 
779 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_dtor,4)
780 void __thiscall MSVCRT_improper_lock_dtor(improper_lock * _this)
781 {
782     TRACE("(%p)\n", _this);
783     MSVCRT_exception_dtor(_this);
784 }
785 
786 typedef exception invalid_scheduler_policy_key;
787 extern const vtable_ptr MSVCRT_invalid_scheduler_policy_key_vtable;
788 
789 /* ??0invalid_scheduler_policy_key@Concurrency@@QAE@PBD@Z */
790 /* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@PEBD@Z */
791 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor_str, 8)
792 invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor_str(
793         invalid_scheduler_policy_key *this, const char *str)
794 {
795     TRACE("(%p %p)\n", this, str);
796     MSVCRT_exception_ctor(this, &str);
797     this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable;
798     return this;
799 }
800 
801 /* ??0invalid_scheduler_policy_key@Concurrency@@QAE@XZ */
802 /* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@XZ */
803 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor, 4)
804 invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor(
805         invalid_scheduler_policy_key *this)
806 {
807     return invalid_scheduler_policy_key_ctor_str(this, NULL);
808 }
809 
810 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_copy_ctor,8)
811 invalid_scheduler_policy_key * __thiscall MSVCRT_invalid_scheduler_policy_key_copy_ctor(
812         invalid_scheduler_policy_key * _this, const invalid_scheduler_policy_key * rhs)
813 {
814     TRACE("(%p %p)\n", _this, rhs);
815     MSVCRT_exception_copy_ctor(_this, rhs);
816     _this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable;
817     return _this;
818 }
819 
820 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_dtor,4)
821 void __thiscall MSVCRT_invalid_scheduler_policy_key_dtor(
822         invalid_scheduler_policy_key * _this)
823 {
824     TRACE("(%p)\n", _this);
825     MSVCRT_exception_dtor(_this);
826 }
827 
828 typedef exception invalid_scheduler_policy_value;
829 extern const vtable_ptr MSVCRT_invalid_scheduler_policy_value_vtable;
830 
831 /* ??0invalid_scheduler_policy_value@Concurrency@@QAE@PBD@Z */
832 /* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@PEBD@Z */
833 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor_str, 8)
834 invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor_str(
835         invalid_scheduler_policy_value *this, const char *str)
836 {
837     TRACE("(%p %p)\n", this, str);
838     MSVCRT_exception_ctor(this, &str);
839     this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable;
840     return this;
841 }
842 
843 /* ??0invalid_scheduler_policy_value@Concurrency@@QAE@XZ */
844 /* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@XZ */
845 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor, 4)
846 invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor(
847         invalid_scheduler_policy_value *this)
848 {
849     return invalid_scheduler_policy_value_ctor_str(this, NULL);
850 }
851 
852 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_copy_ctor,8)
853 invalid_scheduler_policy_value * __thiscall MSVCRT_invalid_scheduler_policy_value_copy_ctor(
854         invalid_scheduler_policy_value * _this, const invalid_scheduler_policy_value * rhs)
855 {
856     TRACE("(%p %p)\n", _this, rhs);
857     MSVCRT_exception_copy_ctor(_this, rhs);
858     _this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable;
859     return _this;
860 }
861 
862 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_dtor,4)
863 void __thiscall MSVCRT_invalid_scheduler_policy_value_dtor(
864         invalid_scheduler_policy_value * _this)
865 {
866     TRACE("(%p)\n", _this);
867     MSVCRT_exception_dtor(_this);
868 }
869 
870 typedef exception invalid_scheduler_policy_thread_specification;
871 extern const vtable_ptr MSVCRT_invalid_scheduler_policy_thread_specification_vtable;
872 
873 /* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@PBD@Z */
874 /* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@PEBD@Z */
875 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor_str, 8)
876 invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor_str(
877         invalid_scheduler_policy_thread_specification *this, const char *str)
878 {
879     TRACE("(%p %p)\n", this, str);
880     MSVCRT_exception_ctor(this, &str);
881     this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable;
882     return this;
883 }
884 
885 /* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@XZ */
886 /* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@XZ */
887 DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor, 4)
888 invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor(
889         invalid_scheduler_policy_thread_specification *this)
890 {
891     return invalid_scheduler_policy_thread_specification_ctor_str(this, NULL);
892 }
893 
894 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor,8)
895 invalid_scheduler_policy_thread_specification * __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor(
896         invalid_scheduler_policy_thread_specification * _this, const invalid_scheduler_policy_thread_specification * rhs)
897 {
898     TRACE("(%p %p)\n", _this, rhs);
899     MSVCRT_exception_copy_ctor(_this, rhs);
900     _this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable;
901     return _this;
902 }
903 
904 DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_dtor,4)
905 void __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_dtor(
906         invalid_scheduler_policy_thread_specification * _this)
907 {
908     TRACE("(%p)\n", _this);
909     MSVCRT_exception_dtor(_this);
910 }
911 
912 typedef exception improper_scheduler_attach;
913 extern const vtable_ptr MSVCRT_improper_scheduler_attach_vtable;
914 
915 /* ??0improper_scheduler_attach@Concurrency@@QAE@PBD@Z */
916 /* ??0improper_scheduler_attach@Concurrency@@QEAA@PEBD@Z */
917 DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor_str, 8)
918 improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor_str(
919         improper_scheduler_attach *this, const char *str)
920 {
921     TRACE("(%p %p)\n", this, str);
922     MSVCRT_exception_ctor(this, &str);
923     this->vtable = &MSVCRT_improper_scheduler_attach_vtable;
924     return this;
925 }
926 
927 /* ??0improper_scheduler_attach@Concurrency@@QAE@XZ */
928 /* ??0improper_scheduler_attach@Concurrency@@QEAA@XZ */
929 DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor, 4)
930 improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor(
931         improper_scheduler_attach *this)
932 {
933     return improper_scheduler_attach_ctor_str(this, NULL);
934 }
935 
936 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_copy_ctor,8)
937 improper_scheduler_attach * __thiscall MSVCRT_improper_scheduler_attach_copy_ctor(
938         improper_scheduler_attach * _this, const improper_scheduler_attach * rhs)
939 {
940     TRACE("(%p %p)\n", _this, rhs);
941     MSVCRT_exception_copy_ctor(_this, rhs);
942     _this->vtable = &MSVCRT_improper_scheduler_attach_vtable;
943     return _this;
944 }
945 
946 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_dtor,4)
947 void __thiscall MSVCRT_improper_scheduler_attach_dtor(
948         improper_scheduler_attach * _this)
949 {
950     TRACE("(%p)\n", _this);
951     MSVCRT_exception_dtor(_this);
952 }
953 
954 typedef exception improper_scheduler_detach;
955 extern const vtable_ptr MSVCRT_improper_scheduler_detach_vtable;
956 
957 /* ??0improper_scheduler_detach@Concurrency@@QAE@PBD@Z */
958 /* ??0improper_scheduler_detach@Concurrency@@QEAA@PEBD@Z */
959 DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor_str, 8)
960 improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor_str(
961         improper_scheduler_detach *this, const char *str)
962 {
963     TRACE("(%p %p)\n", this, str);
964     MSVCRT_exception_ctor(this, &str);
965     this->vtable = &MSVCRT_improper_scheduler_detach_vtable;
966     return this;
967 }
968 
969 /* ??0improper_scheduler_detach@Concurrency@@QAE@XZ */
970 /* ??0improper_scheduler_detach@Concurrency@@QEAA@XZ */
971 DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor, 4)
972 improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor(
973         improper_scheduler_detach *this)
974 {
975     return improper_scheduler_detach_ctor_str(this, NULL);
976 }
977 
978 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_copy_ctor,8)
979 improper_scheduler_detach * __thiscall MSVCRT_improper_scheduler_detach_copy_ctor(
980         improper_scheduler_detach * _this, const improper_scheduler_detach * rhs)
981 {
982     TRACE("(%p %p)\n", _this, rhs);
983     MSVCRT_exception_copy_ctor(_this, rhs);
984     _this->vtable = &MSVCRT_improper_scheduler_detach_vtable;
985     return _this;
986 }
987 
988 DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_dtor,4)
989 void __thiscall MSVCRT_improper_scheduler_detach_dtor(
990         improper_scheduler_detach * _this)
991 {
992     TRACE("(%p)\n", _this);
993     MSVCRT_exception_dtor(_this);
994 }
995 
996 #endif /* _MSVCR_VER >= 100 */
997 
998 #ifndef _MSC_VER
999 #ifndef __GNUC__
1000 void __asm_dummy_vtables(void) {
1001 #endif
1002 
1003 __ASM_VTABLE(type_info,
1004         VTABLE_ADD_FUNC(MSVCRT_type_info_vector_dtor));
1005 __ASM_VTABLE(exception,
1006         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1007         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1008 #if _MSVCR_VER >= 80
1009 __ASM_VTABLE(exception_old,
1010         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1011         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1012 __ASM_VTABLE(bad_alloc,
1013         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1014         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1015 #endif
1016 __ASM_VTABLE(bad_typeid,
1017         VTABLE_ADD_FUNC(MSVCRT_bad_typeid_vector_dtor)
1018         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1019 __ASM_VTABLE(bad_cast,
1020         VTABLE_ADD_FUNC(MSVCRT_bad_cast_vector_dtor)
1021         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1022 __ASM_VTABLE(__non_rtti_object,
1023         VTABLE_ADD_FUNC(MSVCRT___non_rtti_object_vector_dtor)
1024         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1025 #if _MSVCR_VER >= 100
1026 __ASM_VTABLE(scheduler_resource_allocation_error,
1027         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1028         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1029 __ASM_VTABLE(improper_lock,
1030         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1031         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1032 __ASM_VTABLE(invalid_scheduler_policy_key,
1033         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1034         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1035 __ASM_VTABLE(invalid_scheduler_policy_value,
1036         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1037         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1038 __ASM_VTABLE(invalid_scheduler_policy_thread_specification,
1039         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1040         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1041 __ASM_VTABLE(improper_scheduler_attach,
1042         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1043         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1044 __ASM_VTABLE(improper_scheduler_detach,
1045         VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
1046         VTABLE_ADD_FUNC(MSVCRT_what_exception));
1047 #endif
1048 
1049 #ifndef __GNUC__
1050 }
1051 #endif
1052 #endif /* !_MSC_VER */
1053 
1054 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" )
1055 #if _MSVCR_VER >= 80
1056 DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@std@@" )
1057 DEFINE_RTTI_DATA0( exception_old, 0, ".?AVexception@@" )
1058 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@std@@" )
1059 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@std@@" )
1060 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@std@@" )
1061 DEFINE_RTTI_DATA1( bad_alloc, 0, &exception_rtti_base_descriptor, ".?AVbad_alloc@std@@" )
1062 #else
1063 DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@@" )
1064 DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" )
1065 DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" )
1066 DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" )
1067 #endif
1068 #if _MSVCR_VER >= 100
1069 DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &exception_rtti_base_descriptor,
1070         ".?AVscheduler_resource_allocation_error@Concurrency@@")
1071 DEFINE_RTTI_DATA1(improper_lock, 0, &exception_rtti_base_descriptor, ".?AVimproper_lock@Concurrency@@" )
1072 DEFINE_RTTI_DATA1(invalid_scheduler_policy_key, 0, &exception_rtti_base_descriptor,
1073         ".?AVinvalid_scheduler_policy_key@Concurrency@@" )
1074 DEFINE_RTTI_DATA1(invalid_scheduler_policy_value, 0, &exception_rtti_base_descriptor,
1075         ".?AVinvalid_scheduler_policy_value@Concurrency@@" )
1076 DEFINE_RTTI_DATA1(invalid_scheduler_policy_thread_specification, 0, &exception_rtti_base_descriptor,
1077         ".?AVinvalid_scheduler_policy_thread_specification@Concurrency@@" )
1078 DEFINE_RTTI_DATA1(improper_scheduler_attach, 0, &exception_rtti_base_descriptor,
1079         ".?AVimproper_scheduler_attach@Concurrency@@" )
1080 DEFINE_RTTI_DATA1(improper_scheduler_detach, 0, &exception_rtti_base_descriptor,
1081         ".?AVimproper_scheduler_detach@Concurrency@@" )
1082 #endif
1083 
1084 DEFINE_EXCEPTION_TYPE_INFO( exception, 0, NULL, NULL )
1085 DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL )
1086 DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL )
1087 DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info )
1088 #if _MSVCR_VER >= 80
1089 DEFINE_EXCEPTION_TYPE_INFO( bad_alloc, 1, &exception_cxx_type_info, NULL )
1090 #endif
1091 #if _MSVCR_VER >= 100
1092 DEFINE_EXCEPTION_TYPE_INFO(scheduler_resource_allocation_error, 1, &exception_cxx_type_info, NULL)
1093 DEFINE_EXCEPTION_TYPE_INFO(improper_lock, 1, &exception_cxx_type_info, NULL)
1094 DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_key, 1, &exception_cxx_type_info, NULL)
1095 DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_value, 1, &exception_cxx_type_info, NULL)
1096 DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_thread_specification, 1, &exception_cxx_type_info, NULL)
1097 DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_attach, 1, &exception_cxx_type_info, NULL)
1098 DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_detach, 1, &exception_cxx_type_info, NULL)
1099 #endif
1100 
1101 void msvcrt_init_exception(void *base)
1102 {
1103 #ifdef __x86_64__
1104     init_type_info_rtti(base);
1105     init_exception_rtti(base);
1106 #if _MSVCR_VER >= 80
1107     init_exception_old_rtti(base);
1108     init_bad_alloc_rtti(base);
1109 #endif
1110     init_bad_typeid_rtti(base);
1111     init_bad_cast_rtti(base);
1112     init___non_rtti_object_rtti(base);
1113 #if _MSVCR_VER >= 100
1114     init_scheduler_resource_allocation_error_rtti(base);
1115     init_improper_lock_rtti(base);
1116     init_invalid_scheduler_policy_key_rtti(base);
1117     init_invalid_scheduler_policy_value_rtti(base);
1118     init_invalid_scheduler_policy_thread_specification_rtti(base);
1119     init_improper_scheduler_attach_rtti(base);
1120     init_improper_scheduler_detach_rtti(base);
1121 #endif
1122 
1123     init_exception_cxx(base);
1124     init_bad_typeid_cxx(base);
1125     init_bad_cast_cxx(base);
1126     init___non_rtti_object_cxx(base);
1127 #if _MSVCR_VER >= 80
1128     init_bad_alloc_cxx(base);
1129 #endif
1130 #if _MSVCR_VER >= 100
1131     init_scheduler_resource_allocation_error_cxx(base);
1132     init_improper_lock_cxx(base);
1133     init_invalid_scheduler_policy_key_cxx(base);
1134     init_invalid_scheduler_policy_value_cxx(base);
1135     init_invalid_scheduler_policy_thread_specification_cxx(base);
1136     init_improper_scheduler_attach_cxx(base);
1137     init_improper_scheduler_detach_cxx(base);
1138 #endif
1139 #endif
1140 }
1141 
1142 #if _MSVCR_VER >= 80
1143 void throw_exception(exception_type et, HRESULT hr, const char *str)
1144 {
1145     switch(et) {
1146     case EXCEPTION_BAD_ALLOC: {
1147         bad_alloc e;
1148         bad_alloc_ctor(&e, &str);
1149         _CxxThrowException(&e, &bad_alloc_exception_type);
1150     }
1151 #if _MSVCR_VER >= 100
1152     case EXCEPTION_SCHEDULER_RESOURCE_ALLOCATION_ERROR: {
1153         scheduler_resource_allocation_error e;
1154         scheduler_resource_allocation_error_ctor_name(&e, str, hr);
1155         _CxxThrowException(&e.e, &scheduler_resource_allocation_error_exception_type);
1156     }
1157     case EXCEPTION_IMPROPER_LOCK: {
1158         improper_lock e;
1159         improper_lock_ctor_str(&e, str);
1160         _CxxThrowException(&e, &improper_lock_exception_type);
1161     }
1162     case EXCEPTION_INVALID_SCHEDULER_POLICY_KEY: {
1163         invalid_scheduler_policy_key e;
1164         invalid_scheduler_policy_key_ctor_str(&e, str);
1165         _CxxThrowException(&e, &invalid_scheduler_policy_key_exception_type);
1166     }
1167     case EXCEPTION_INVALID_SCHEDULER_POLICY_VALUE: {
1168         invalid_scheduler_policy_value e;
1169         invalid_scheduler_policy_value_ctor_str(&e, str);
1170         _CxxThrowException(&e, &invalid_scheduler_policy_value_exception_type);
1171     }
1172     case EXCEPTION_INVALID_SCHEDULER_POLICY_THREAD_SPECIFICATION: {
1173         invalid_scheduler_policy_thread_specification e;
1174         invalid_scheduler_policy_thread_specification_ctor_str(&e, str);
1175         _CxxThrowException(&e, &invalid_scheduler_policy_thread_specification_exception_type);
1176     }
1177     case EXCEPTION_IMPROPER_SCHEDULER_ATTACH: {
1178         improper_scheduler_attach e;
1179         improper_scheduler_attach_ctor_str(&e, str);
1180         _CxxThrowException(&e, &improper_scheduler_attach_exception_type);
1181     }
1182     case EXCEPTION_IMPROPER_SCHEDULER_DETACH: {
1183         improper_scheduler_detach e;
1184         improper_scheduler_detach_ctor_str(&e, str);
1185         _CxxThrowException(&e, &improper_scheduler_detach_exception_type);
1186     }
1187 #endif
1188     }
1189 }
1190 #endif
1191 
1192 /******************************************************************
1193  *		?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
1194  *
1195  * Install a handler to be called when terminate() is called.
1196  *
1197  * PARAMS
1198  *  func [I] Handler function to install
1199  *
1200  * RETURNS
1201  *  The previously installed handler function, if any.
1202  */
1203 MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func)
1204 {
1205     thread_data_t *data = msvcrt_get_thread_data();
1206     MSVCRT_terminate_function previous = data->terminate_handler;
1207     TRACE("(%p) returning %p\n",func,previous);
1208     data->terminate_handler = func;
1209     return previous;
1210 }
1211 
1212 /******************************************************************
1213  *              _get_terminate (MSVCRT.@)
1214  */
1215 MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void)
1216 {
1217     thread_data_t *data = msvcrt_get_thread_data();
1218     TRACE("returning %p\n", data->terminate_handler);
1219     return data->terminate_handler;
1220 }
1221 
1222 /******************************************************************
1223  *		?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
1224  *
1225  * Install a handler to be called when unexpected() is called.
1226  *
1227  * PARAMS
1228  *  func [I] Handler function to install
1229  *
1230  * RETURNS
1231  *  The previously installed handler function, if any.
1232  */
1233 MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
1234 {
1235     thread_data_t *data = msvcrt_get_thread_data();
1236     MSVCRT_unexpected_function previous = data->unexpected_handler;
1237     TRACE("(%p) returning %p\n",func,previous);
1238     data->unexpected_handler = func;
1239     return previous;
1240 }
1241 
1242 /******************************************************************
1243  *              _get_unexpected (MSVCRT.@)
1244  */
1245 MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void)
1246 {
1247     thread_data_t *data = msvcrt_get_thread_data();
1248     TRACE("returning %p\n", data->unexpected_handler);
1249     return data->unexpected_handler;
1250 }
1251 
1252 /******************************************************************
1253  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
1254  */
1255 MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
1256 {
1257     thread_data_t *data = msvcrt_get_thread_data();
1258     MSVCRT__se_translator_function previous = data->se_translator;
1259     TRACE("(%p) returning %p\n",func,previous);
1260     data->se_translator = func;
1261     return previous;
1262 }
1263 
1264 /******************************************************************
1265  *		?terminate@@YAXXZ (MSVCRT.@)
1266  *
1267  * Default handler for an unhandled exception.
1268  *
1269  * PARAMS
1270  *  None.
1271  *
1272  * RETURNS
1273  *  This function does not return. Either control resumes from any
1274  *  handler installed by calling set_terminate(), or (by default) abort()
1275  *  is called.
1276  */
1277 void CDECL MSVCRT_terminate(void)
1278 {
1279     thread_data_t *data = msvcrt_get_thread_data();
1280     if (data->terminate_handler) data->terminate_handler();
1281     MSVCRT_abort();
1282 }
1283 
1284 /******************************************************************
1285  *		?unexpected@@YAXXZ (MSVCRT.@)
1286  */
1287 void CDECL MSVCRT_unexpected(void)
1288 {
1289     thread_data_t *data = msvcrt_get_thread_data();
1290     if (data->unexpected_handler) data->unexpected_handler();
1291     MSVCRT_terminate();
1292 }
1293 
1294 
1295 /******************************************************************
1296  *		__RTtypeid (MSVCRT.@)
1297  *
1298  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
1299  *
1300  * PARAMS
1301  *  cppobj [I] C++ object to get type information for.
1302  *
1303  * RETURNS
1304  *  Success: A type_info object describing cppobj.
1305  *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
1306  *           exception is thrown. If cppobj is NULL, a bad_typeid exception
1307  *           is thrown. In either case, this function does not return.
1308  *
1309  * NOTES
1310  *  This function is usually called by compiler generated code as a result
1311  *  of using one of the C++ dynamic cast statements.
1312  */
1313 #ifndef __x86_64__
1314 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
1315 {
1316     const type_info *ret;
1317 
1318     if (!cppobj)
1319     {
1320         bad_typeid e;
1321         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
1322         _CxxThrowException( &e, &bad_typeid_exception_type );
1323         return NULL;
1324     }
1325 
1326     __TRY
1327     {
1328         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1329         ret = obj_locator->type_descriptor;
1330     }
1331     __EXCEPT_PAGE_FAULT
1332     {
1333         __non_rtti_object e;
1334         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
1335         _CxxThrowException( &e, &__non_rtti_object_exception_type );
1336         return NULL;
1337     }
1338     __ENDTRY
1339     return ret;
1340 }
1341 
1342 #else
1343 
1344 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
1345 {
1346     const type_info *ret;
1347 
1348     if (!cppobj)
1349     {
1350         bad_typeid e;
1351         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
1352         _CxxThrowException( &e, &bad_typeid_exception_type );
1353         return NULL;
1354     }
1355 
1356     __TRY
1357     {
1358         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1359         char *base;
1360 
1361         if(obj_locator->signature == 0)
1362             base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
1363         else
1364             base = (char*)obj_locator - obj_locator->object_locator;
1365 
1366         ret = (type_info*)(base + obj_locator->type_descriptor);
1367     }
1368     __EXCEPT_PAGE_FAULT
1369     {
1370         __non_rtti_object e;
1371         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
1372         _CxxThrowException( &e, &__non_rtti_object_exception_type );
1373         return NULL;
1374     }
1375     __ENDTRY
1376     return ret;
1377 }
1378 #endif
1379 
1380 /******************************************************************
1381  *		__RTDynamicCast (MSVCRT.@)
1382  *
1383  * Dynamically cast a C++ object to one of its base classes.
1384  *
1385  * PARAMS
1386  *  cppobj   [I] Any C++ object to cast
1387  *  unknown  [I] Reserved, set to 0
1388  *  src      [I] type_info object describing cppobj
1389  *  dst      [I] type_info object describing the base class to cast to
1390  *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
1391  *
1392  * RETURNS
1393  *  Success: The address of cppobj, cast to the object described by dst.
1394  *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
1395  *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
1396  *           is thrown and this function does not return.
1397  *
1398  * NOTES
1399  *  This function is usually called by compiler generated code as a result
1400  *  of using one of the C++ dynamic cast statements.
1401  */
1402 #ifndef __x86_64__
1403 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
1404                                    type_info *src, type_info *dst,
1405                                    int do_throw)
1406 {
1407     void *ret;
1408 
1409     if (!cppobj) return NULL;
1410 
1411     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
1412           cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
1413 
1414     /* To cast an object at runtime:
1415      * 1.Find out the true type of the object from the typeinfo at vtable[-1]
1416      * 2.Search for the destination type in the class hierarchy
1417      * 3.If destination type is found, return base object address + dest offset
1418      *   Otherwise, fail the cast
1419      *
1420      * FIXME: the unknown parameter doesn't seem to be used for anything
1421      */
1422     __TRY
1423     {
1424         int i;
1425         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1426         const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
1427         const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
1428 
1429         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
1430 
1431         ret = NULL;
1432         for (i = 0; i < obj_bases->array_len; i++)
1433         {
1434             const type_info *typ = base_desc[i]->type_descriptor;
1435 
1436             if (!strcmp(typ->mangled, dst->mangled))
1437             {
1438                 /* compute the correct this pointer for that base class */
1439                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
1440                 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
1441                 break;
1442             }
1443         }
1444         /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
1445          * to a reference, since references cannot be NULL.
1446          */
1447         if (!ret && do_throw)
1448         {
1449             const char *msg = "Bad dynamic_cast!";
1450             bad_cast e;
1451             MSVCRT_bad_cast_ctor( &e, &msg );
1452             _CxxThrowException( &e, &bad_cast_exception_type );
1453         }
1454     }
1455     __EXCEPT_PAGE_FAULT
1456     {
1457         __non_rtti_object e;
1458         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1459         _CxxThrowException( &e, &__non_rtti_object_exception_type );
1460         return NULL;
1461     }
1462     __ENDTRY
1463     return ret;
1464 }
1465 
1466 #else
1467 
1468 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
1469         type_info *src, type_info *dst,
1470         int do_throw)
1471 {
1472     void *ret;
1473 
1474     if (!cppobj) return NULL;
1475 
1476     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
1477             cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
1478 
1479     __TRY
1480     {
1481         int i;
1482         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1483         const rtti_object_hierarchy *obj_bases;
1484         const rtti_base_array *base_array;
1485         char *base;
1486 
1487         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
1488 
1489         if(obj_locator->signature == 0)
1490             base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
1491         else
1492             base = (char*)obj_locator - obj_locator->object_locator;
1493 
1494         obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy);
1495         base_array = (const rtti_base_array*)(base + obj_bases->base_classes);
1496 
1497         ret = NULL;
1498         for (i = 0; i < obj_bases->array_len; i++)
1499         {
1500             const rtti_base_descriptor *base_desc = (const rtti_base_descriptor*)(base + base_array->bases[i]);
1501             const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
1502 
1503             if (!strcmp(typ->mangled, dst->mangled))
1504             {
1505                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
1506                 ret = get_this_pointer( &base_desc->offsets, this_ptr );
1507                 break;
1508             }
1509         }
1510         if (!ret && do_throw)
1511         {
1512             const char *msg = "Bad dynamic_cast!";
1513             bad_cast e;
1514             MSVCRT_bad_cast_ctor( &e, &msg );
1515             _CxxThrowException( &e, &bad_cast_exception_type );
1516         }
1517     }
1518     __EXCEPT_PAGE_FAULT
1519     {
1520         __non_rtti_object e;
1521         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1522         _CxxThrowException( &e, &__non_rtti_object_exception_type );
1523         return NULL;
1524     }
1525     __ENDTRY
1526     return ret;
1527 }
1528 #endif
1529 
1530 
1531 /******************************************************************
1532  *		__RTCastToVoid (MSVCRT.@)
1533  *
1534  * Dynamically cast a C++ object to a void*.
1535  *
1536  * PARAMS
1537  *  cppobj [I] The C++ object to cast
1538  *
1539  * RETURNS
1540  *  Success: The base address of the object as a void*.
1541  *  Failure: NULL, if cppobj is NULL or has no RTTI.
1542  *
1543  * NOTES
1544  *  This function is usually called by compiler generated code as a result
1545  *  of using one of the C++ dynamic cast statements.
1546  */
1547 void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
1548 {
1549     void *ret;
1550 
1551     if (!cppobj) return NULL;
1552 
1553     __TRY
1554     {
1555         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1556         ret = (char *)cppobj - obj_locator->base_class_offset;
1557     }
1558     __EXCEPT_PAGE_FAULT
1559     {
1560         __non_rtti_object e;
1561         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1562         _CxxThrowException( &e, &__non_rtti_object_exception_type );
1563         return NULL;
1564     }
1565     __ENDTRY
1566     return ret;
1567 }
1568 
1569 
1570 /*********************************************************************
1571  *		_CxxThrowException (MSVCRT.@)
1572  */
1573 #ifndef __x86_64__
1574 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
1575 {
1576     ULONG_PTR args[3];
1577 
1578     args[0] = CXX_FRAME_MAGIC_VC6;
1579     args[1] = (ULONG_PTR)object;
1580     args[2] = (ULONG_PTR)type;
1581     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
1582 }
1583 #else
1584 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
1585 {
1586     ULONG_PTR args[4];
1587 
1588     args[0] = CXX_FRAME_MAGIC_VC6;
1589     args[1] = (ULONG_PTR)object;
1590     args[2] = (ULONG_PTR)type;
1591     RtlPcToFileHeader( (void*)type, (void**)&args[3]);
1592     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 4, args );
1593 }
1594 #endif
1595 
1596 #if _MSVCR_VER >= 80
1597 
1598 /*********************************************************************
1599  * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z
1600  * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z
1601  */
1602 #ifndef __x86_64__
1603 int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
1604 {
1605     int ret = -1;
1606 
1607     TRACE("(%p %p)\n", ti, ep);
1608 
1609     __TRY
1610     {
1611         EXCEPTION_RECORD *rec = ep->ExceptionRecord;
1612 
1613         if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==3 &&
1614                 (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
1615                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
1616                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
1617         {
1618             const cxx_type_info_table *tit = ((cxx_exception_type*)rec->ExceptionInformation[2])->type_info_table;
1619             int i;
1620 
1621             for (i=0; i<tit->count; i++) {
1622                 if (ti==tit->info[i]->type_info || !strcmp(ti->mangled, tit->info[i]->type_info->mangled))
1623                 {
1624                     ret = 1;
1625                     break;
1626                 }
1627             }
1628 
1629             if (i == tit->count)
1630                 ret = 0;
1631         }
1632     }
1633     __EXCEPT_PAGE_FAULT
1634     __ENDTRY
1635 
1636     if(ret == -1)
1637         MSVCRT_terminate();
1638     return ret;
1639 }
1640 #else
1641 int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
1642 {
1643     int ret = -1;
1644 
1645     TRACE("(%p %p)\n", ti, ep);
1646 
1647     __TRY
1648     {
1649         EXCEPTION_RECORD *rec = ep->ExceptionRecord;
1650 
1651         if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==4 &&
1652                 (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
1653                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
1654                  rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
1655         {
1656             const cxx_exception_type *et = (cxx_exception_type*)rec->ExceptionInformation[2];
1657             const cxx_type_info_table *tit = (const cxx_type_info_table*)(rec->ExceptionInformation[3]+et->type_info_table);
1658             int i;
1659 
1660             for (i=0; i<tit->count; i++) {
1661                 const cxx_type_info *cti = (const cxx_type_info*)(rec->ExceptionInformation[3]+tit->info[i]);
1662                 const type_info *except_ti = (const type_info*)(rec->ExceptionInformation[3]+cti->type_info);
1663                 if (ti==except_ti || !strcmp(ti->mangled, except_ti->mangled))
1664                 {
1665                     ret = 1;
1666                     break;
1667                 }
1668             }
1669 
1670             if (i == tit->count)
1671                 ret = 0;
1672         }
1673     }
1674     __EXCEPT_PAGE_FAULT
1675     __ENDTRY
1676 
1677     if(ret == -1)
1678         MSVCRT_terminate();
1679     return ret;
1680 }
1681 #endif
1682 
1683 /*********************************************************************
1684  * __clean_type_info_names_internal (MSVCR80.@)
1685  */
1686 void CDECL __clean_type_info_names_internal(void *p)
1687 {
1688     FIXME("(%p) stub\n", p);
1689 }
1690 
1691 /*********************************************************************
1692  * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
1693  */
1694 DEFINE_THISCALL_WRAPPER(type_info_name_internal_method,8)
1695 const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node)
1696 {
1697     static int once;
1698     if (node && !once++) FIXME("type_info_node parameter ignored\n");
1699 
1700     return MSVCRT_type_info_name(_this);
1701 }
1702 
1703 #endif /* _MSVCR_VER >= 80 */
1704 
1705 /* std::exception_ptr class helpers */
1706 typedef struct
1707 {
1708     EXCEPTION_RECORD *rec;
1709     int *ref; /* not binary compatible with native msvcr100 */
1710 } exception_ptr;
1711 
1712 #if _MSVCR_VER >= 100
1713 
1714 /*********************************************************************
1715  * ?__ExceptionPtrCreate@@YAXPAX@Z
1716  * ?__ExceptionPtrCreate@@YAXPEAX@Z
1717  */
1718 void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
1719 {
1720     TRACE("(%p)\n", ep);
1721 
1722     ep->rec = NULL;
1723     ep->ref = NULL;
1724 }
1725 
1726 #if defined(__i386__) && !defined(__MINGW32__)
1727 extern void call_dtor(const cxx_exception_type *type, void *func, void *object);
1728 
1729 __ASM_GLOBAL_FUNC( call_dtor,
1730                    "movl 12(%esp),%ecx\n\t"
1731                    "call *8(%esp)\n\t"
1732                    "ret" );
1733 #elif __x86_64__
1734 static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object)
1735 {
1736     char *base = RtlPcToFileHeader((void*)type, (void**)&base);
1737     void (__cdecl *func)(void*) = (void*)(base + dtor);
1738     func(object);
1739 }
1740 #else
1741 #define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
1742 #endif
1743 
1744 /*********************************************************************
1745  * ?__ExceptionPtrDestroy@@YAXPAX@Z
1746  * ?__ExceptionPtrDestroy@@YAXPEAX@Z
1747  */
1748 void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
1749 {
1750     TRACE("(%p)\n", ep);
1751 
1752     if (!ep->rec)
1753         return;
1754 
1755     if (!InterlockedDecrement(ep->ref))
1756     {
1757         if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1758         {
1759             const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2];
1760             void *obj = (void*)ep->rec->ExceptionInformation[1];
1761 
1762             if (type && type->destructor) call_dtor(type, type->destructor, obj);
1763             HeapFree(GetProcessHeap(), 0, obj);
1764         }
1765 
1766         HeapFree(GetProcessHeap(), 0, ep->rec);
1767         HeapFree(GetProcessHeap(), 0, ep->ref);
1768     }
1769 }
1770 
1771 /*********************************************************************
1772  * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
1773  * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
1774  */
1775 void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy)
1776 {
1777     TRACE("(%p %p)\n", ep, copy);
1778 
1779     /* don't destroy object stored in ep */
1780     *ep = *copy;
1781     if (ep->ref)
1782         InterlockedIncrement(copy->ref);
1783 }
1784 
1785 /*********************************************************************
1786  * ?__ExceptionPtrAssign@@YAXPAXPBX@Z
1787  * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
1788  */
1789 void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign)
1790 {
1791     TRACE("(%p %p)\n", ep, assign);
1792 
1793     /* don't destroy object stored in ep */
1794     if (ep->ref)
1795         InterlockedDecrement(ep->ref);
1796 
1797     *ep = *assign;
1798     if (ep->ref)
1799         InterlockedIncrement(ep->ref);
1800 }
1801 
1802 #endif /* _MSVCR_VER >= 100 */
1803 
1804 /*********************************************************************
1805  * ?__ExceptionPtrRethrow@@YAXPBX@Z
1806  * ?__ExceptionPtrRethrow@@YAXPEBX@Z
1807  */
1808 void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
1809 {
1810     TRACE("(%p)\n", ep);
1811 
1812     if (!ep->rec)
1813     {
1814         static const char *exception_msg = "bad exception";
1815         exception e;
1816 
1817         MSVCRT_exception_ctor(&e, &exception_msg);
1818         _CxxThrowException(&e, &exception_exception_type);
1819         return;
1820     }
1821 
1822     RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
1823             ep->rec->NumberParameters, ep->rec->ExceptionInformation);
1824 }
1825 
1826 #if _MSVCR_VER >= 100
1827 
1828 #ifdef __i386__
1829 extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
1830 #else
1831 static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
1832 {
1833     TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
1834     if (has_vbase)
1835         ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
1836     else
1837         ((void (__cdecl*)(void*, void*))func)(this, src);
1838 }
1839 #endif
1840 
1841 /*********************************************************************
1842  * ?__ExceptionPtrCurrentException@@YAXPAX@Z
1843  * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
1844  */
1845 #ifndef __x86_64__
1846 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1847 {
1848     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1849 
1850     TRACE("(%p)\n", ep);
1851 
1852     if (!rec)
1853     {
1854         ep->rec = NULL;
1855         ep->ref = NULL;
1856         return;
1857     }
1858 
1859     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1860     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1861 
1862     *ep->rec = *rec;
1863     *ep->ref = 1;
1864 
1865     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1866     {
1867         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1868         const cxx_type_info *ti;
1869         void **data, *obj;
1870 
1871         ti = et->type_info_table->info[0];
1872         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1873 
1874         obj = (void*)ep->rec->ExceptionInformation[1];
1875         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1876         {
1877             memcpy(data, obj, ti->size);
1878             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1879         }
1880         else if (ti->copy_ctor)
1881         {
1882             call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1883                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1884         }
1885         else
1886             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1887         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1888     }
1889     return;
1890 }
1891 #else
1892 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
1893 {
1894     EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;
1895 
1896     TRACE("(%p)\n", ep);
1897 
1898     if (!rec)
1899     {
1900         ep->rec = NULL;
1901         ep->ref = NULL;
1902         return;
1903     }
1904 
1905     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1906     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1907 
1908     *ep->rec = *rec;
1909     *ep->ref = 1;
1910 
1911     if (ep->rec->ExceptionCode == CXX_EXCEPTION)
1912     {
1913         const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
1914         const cxx_type_info *ti;
1915         void **data, *obj;
1916         char *base = RtlPcToFileHeader((void*)et, (void**)&base);
1917 
1918         ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]);
1919         data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1920 
1921         obj = (void*)ep->rec->ExceptionInformation[1];
1922         if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1923         {
1924             memcpy(data, obj, ti->size);
1925             if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1926         }
1927         else if (ti->copy_ctor)
1928         {
1929             call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
1930                     ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1931         }
1932         else
1933             memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
1934         ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1935     }
1936     return;
1937 }
1938 #endif
1939 
1940 #endif /* _MSVCR_VER >= 100 */
1941 
1942 #if _MSVCR_VER >= 110
1943 /*********************************************************************
1944  * ?__ExceptionPtrToBool@@YA_NPBX@Z
1945  * ?__ExceptionPtrToBool@@YA_NPEBX@Z
1946  */
1947 MSVCRT_bool __cdecl __ExceptionPtrToBool(exception_ptr *ep)
1948 {
1949     return !!ep->rec;
1950 }
1951 #endif
1952 
1953 #if _MSVCR_VER >= 100
1954 
1955 /*********************************************************************
1956  * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
1957  * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
1958  */
1959 #ifndef __x86_64__
1960 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1961         exception *object, const cxx_exception_type *type)
1962 {
1963     const cxx_type_info *ti;
1964     void **data;
1965 
1966     __ExceptionPtrDestroy(ep);
1967 
1968     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
1969     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
1970     *ep->ref = 1;
1971 
1972     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
1973     ep->rec->ExceptionCode = CXX_EXCEPTION;
1974     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
1975     ep->rec->NumberParameters = 3;
1976     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
1977     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
1978 
1979     ti = type->type_info_table->info[0];
1980     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
1981     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
1982     {
1983         memcpy(data, object, ti->size);
1984         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
1985     }
1986     else if (ti->copy_ctor)
1987     {
1988         call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
1989                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
1990     }
1991     else
1992         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
1993     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
1994 }
1995 #else
1996 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
1997         exception *object, const cxx_exception_type *type)
1998 {
1999     const cxx_type_info *ti;
2000     void **data;
2001     char *base;
2002 
2003     RtlPcToFileHeader((void*)type, (void**)&base);
2004     __ExceptionPtrDestroy(ep);
2005 
2006     ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
2007     ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
2008     *ep->ref = 1;
2009 
2010     memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
2011     ep->rec->ExceptionCode = CXX_EXCEPTION;
2012     ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
2013     ep->rec->NumberParameters = 4;
2014     ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
2015     ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
2016     ep->rec->ExceptionInformation[3] = (ULONG_PTR)base;
2017 
2018     ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]);
2019     data = HeapAlloc(GetProcessHeap(), 0, ti->size);
2020     if (ti->flags & CLASS_IS_SIMPLE_TYPE)
2021     {
2022         memcpy(data, object, ti->size);
2023         if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
2024     }
2025     else if (ti->copy_ctor)
2026     {
2027         call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
2028                 ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
2029     }
2030     else
2031         memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
2032     ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
2033 }
2034 #endif
2035 
2036 MSVCRT_bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2)
2037 {
2038     return ep1->rec == ep2->rec;
2039 }
2040 
2041 #endif /* _MSVCR_VER >= 100 */
2042 
2043 #if _MSVCR_VER >= 80
2044 void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off)
2045 {
2046     return get_this_pointer(off, obj);
2047 }
2048 #endif
2049 
2050 #if _MSVCR_VER >= 140
2051 
2052 typedef struct
2053 {
2054     char *name;
2055     char mangled[1];
2056 } type_info140;
2057 
2058 typedef struct
2059 {
2060     SLIST_ENTRY entry;
2061     char name[1];
2062 } type_info_entry;
2063 
2064 static void* CDECL type_info_entry_malloc(MSVCRT_size_t size)
2065 {
2066     type_info_entry *ret = MSVCRT_malloc(FIELD_OFFSET(type_info_entry, name) + size);
2067     return ret->name;
2068 }
2069 
2070 static void CDECL type_info_entry_free(void *ptr)
2071 {
2072     ptr = (char*)ptr - FIELD_OFFSET(type_info_entry, name);
2073     MSVCRT_free(ptr);
2074 }
2075 
2076 /******************************************************************
2077  *		__std_type_info_compare (UCRTBASE.@)
2078  */
2079 int CDECL MSVCRT_type_info_compare(const type_info140 *l, const type_info140 *r)
2080 {
2081     int ret;
2082 
2083     if (l == r) ret = 0;
2084     else ret = MSVCRT_strcmp(l->mangled + 1, r->mangled + 1);
2085     TRACE("(%p %p) returning %d\n", l, r, ret);
2086     return ret;
2087 }
2088 
2089 /******************************************************************
2090  *		__std_type_info_name (UCRTBASE.@)
2091  */
2092 const char* CDECL MSVCRT_type_info_name_list(type_info140 *ti, SLIST_HEADER *header)
2093 {
2094       if (!ti->name)
2095       {
2096           char* name = __unDName(0, ti->mangled + 1, 0,
2097                   type_info_entry_malloc, type_info_entry_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
2098           if (name)
2099           {
2100               unsigned int len = strlen(name);
2101 
2102               while (len && name[--len] == ' ')
2103                   name[len] = '\0';
2104 
2105               if (InterlockedCompareExchangePointer((void**)&ti->name, name, NULL))
2106               {
2107                   type_info_entry_free(name);
2108               }
2109               else
2110               {
2111                   type_info_entry *entry = (type_info_entry*)(name-FIELD_OFFSET(type_info_entry, name));
2112                   InterlockedPushEntrySList(header, &entry->entry);
2113               }
2114           }
2115       }
2116       TRACE("(%p) returning %s\n", ti, ti->name);
2117       return ti->name;
2118 }
2119 
2120 /******************************************************************
2121  *		__std_type_info_destroy_list  (UCRTBASE.@)
2122  */
2123 void CDECL MSVCRT_type_info_destroy_list(SLIST_HEADER *header)
2124 {
2125     SLIST_ENTRY *cur, *next;
2126 
2127     TRACE("(%p)\n", header);
2128 
2129     for(cur = InterlockedFlushSList(header); cur; cur = next)
2130     {
2131         next = cur->Next;
2132         MSVCRT_free(cur);
2133     }
2134 }
2135 
2136 /******************************************************************
2137  *              __std_type_info_hash (UCRTBASE.@)
2138  */
2139 MSVCRT_size_t CDECL MSVCRT_type_info_hash(const type_info140 *ti)
2140 {
2141     MSVCRT_size_t hash, fnv_prime;
2142     const char *p;
2143 
2144 #ifdef _WIN64
2145     hash = 0xcbf29ce484222325;
2146     fnv_prime = 0x100000001b3;
2147 #else
2148     hash = 0x811c9dc5;
2149     fnv_prime = 0x1000193;
2150 #endif
2151 
2152     TRACE("(%p)->%s\n", ti, ti->mangled);
2153 
2154     for(p = ti->mangled+1; *p; p++) {
2155         hash ^= *p;
2156         hash *= fnv_prime;
2157     }
2158 
2159 #ifdef _WIN64
2160     hash ^= hash >> 32;
2161 #endif
2162 
2163     return hash;
2164 }
2165 
2166 #endif /* _MSVCR_VER >= 140 */
2167 
2168 #if _MSVCR_VER >= 100
2169 
2170 enum ConcRT_EventType
2171 {
2172     CONCRT_EVENT_GENERIC,
2173     CONCRT_EVENT_START,
2174     CONCRT_EVENT_END,
2175     CONCRT_EVENT_BLOCK,
2176     CONCRT_EVENT_UNBLOCK,
2177     CONCRT_EVENT_YIELD,
2178     CONCRT_EVENT_ATTACH,
2179     CONCRT_EVENT_DETACH
2180 };
2181 
2182 /* ?_Trace_ppl_function@Concurrency@@YAXABU_GUID@@EW4ConcRT_EventType@1@@Z */
2183 /* ?_Trace_ppl_function@Concurrency@@YAXAEBU_GUID@@EW4ConcRT_EventType@1@@Z */
2184 void __cdecl Concurrency__Trace_ppl_function(const GUID *guid, unsigned char level, enum ConcRT_EventType type)
2185 {
2186     FIXME("(%s %u %i) stub\n", debugstr_guid(guid), level, type);
2187 }
2188 
2189 #endif /* _MSVCR_VER >= 100 */
2190