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 */ 54 static inline const vtable_ptr *get_vtable( void *obj ) 55 { 56 return *(const vtable_ptr **)obj; 57 } 58 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__ 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 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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__ 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 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__ 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 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 */ 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__ 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 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__ 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 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 */ 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) 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 */ 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__ 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 */ 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 */ 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 */ 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 */ 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 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__ 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 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 */ 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__ 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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