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