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