cpp.c 70.7 KB
Newer Older
1 2 3 4
/*
 * msvcrt.dll C++ objects
 *
 * Copyright 2000 Jon Griffiths
5
 * Copyright 2003, 2004 Alexandre Julliard
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23 24
#include "config.h"
#include "wine/port.h"

25 26 27
#include <stdarg.h>

#include "windef.h"
28 29 30 31 32 33
#include "winternl.h"
#include "wine/exception.h"
#include "wine/debug.h"
#include "msvcrt.h"
#include "cppexcept.h"
#include "mtdll.h"
34
#include "cxx.h"
35 36

WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
37

38 39 40 41 42 43
struct __type_info_node
{
    void *memPtr;
    struct __type_info_node* next;
};

44 45 46
typedef exception bad_cast;
typedef exception bad_typeid;
typedef exception __non_rtti_object;
47

48 49 50 51 52 53
extern const vtable_ptr MSVCRT_exception_vtable;
extern const vtable_ptr MSVCRT_bad_typeid_vtable;
extern const vtable_ptr MSVCRT_bad_cast_vtable;
extern const vtable_ptr MSVCRT___non_rtti_object_vtable;
extern const vtable_ptr MSVCRT_type_info_vtable;

54 55 56 57 58 59
/* get the vtable pointer for a C++ object */
static inline const vtable_ptr *get_vtable( void *obj )
{
    return *(const vtable_ptr **)obj;
}

60 61 62 63 64
static inline const rtti_object_locator *get_obj_locator( void *cppobj )
{
    const vtable_ptr *vtable = get_vtable( cppobj );
    return (const rtti_object_locator *)vtable[-1];
}
65

66
#ifndef __x86_64__
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
static void dump_obj_locator( const rtti_object_locator *ptr )
{
    int i;
    const rtti_object_hierarchy *h = ptr->type_hierarchy;

    TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
           ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
           ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy );
    TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
           h->signature, h->attributes, h->array_len, h->base_classes );
    for (i = 0; i < h->array_len; i++)
    {
        TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
               h->base_classes->bases[i],
               h->base_classes->bases[i]->num_base_classes,
               h->base_classes->bases[i]->offsets.this_offset,
               h->base_classes->bases[i]->offsets.vbase_descr,
               h->base_classes->bases[i]->offsets.vbase_offset,
               h->base_classes->bases[i]->attributes,
               h->base_classes->bases[i]->type_descriptor,
               dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) );
    }
}

91 92 93
#else

static void dump_obj_locator( const rtti_object_locator *ptr )
94 95
{
    int i;
96
    char *base = ptr->signature == 0 ? RtlPcToFileHeader((void*)ptr, (void**)&base) : (char*)ptr - ptr->object_locator;
97
    const rtti_object_hierarchy *h = (const rtti_object_hierarchy*)(base + ptr->type_hierarchy);
98 99 100 101 102 103 104 105 106
    const type_info *type_descriptor = (const type_info*)(base + ptr->type_descriptor);

    TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
            ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
            type_descriptor, dbgstr_type_info(type_descriptor), h );
    TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
            h->signature, h->attributes, h->array_len, base + h->base_classes );
    for (i = 0; i < h->array_len; i++)
    {
107 108
        const rtti_base_descriptor *bases = (rtti_base_descriptor*)(base +
                ((const rtti_base_array*)(base + h->base_classes))->bases[i]);
109 110 111 112 113 114 115 116 117 118 119 120 121 122

        TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
                bases,
                bases->num_base_classes,
                bases->offsets.this_offset,
                bases->offsets.vbase_descr,
                bases->offsets.vbase_offset,
                bases->attributes,
                base + bases->type_descriptor,
                dbgstr_type_info((const type_info*)(base + bases->type_descriptor)) );
    }
}
#endif

123
/* Internal common ctor for exception */
124
static void EXCEPTION_ctor(exception *_this, const char** name)
125 126 127 128
{
  _this->vtable = &MSVCRT_exception_vtable;
  if (*name)
  {
129
    unsigned int name_len = strlen(*name) + 1;
130 131 132 133 134 135 136 137 138 139
    _this->name = MSVCRT_malloc(name_len);
    memcpy(_this->name, *name, name_len);
    _this->do_free = TRUE;
  }
  else
  {
    _this->name = NULL;
    _this->do_free = FALSE;
  }
}
140

141
/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
142
 *		??0exception@@QAE@ABQBD@Z (MSVCRT.@)
143
 */
144
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
145
exception * __thiscall MSVCRT_exception_ctor(exception * _this, const char ** name)
146
{
147 148
  TRACE("(%p,%s)\n", _this, *name);
  EXCEPTION_ctor(_this, name);
149
  return _this;
150 151
}

152 153 154 155
/******************************************************************
 *		??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
 */
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
156
exception * __thiscall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
157 158 159 160 161 162 163 164
{
  TRACE("(%p,%s)\n", _this, *name);
  _this->vtable = &MSVCRT_exception_vtable;
  _this->name = *name;
  _this->do_free = FALSE;
  return _this;
}

165
/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
166
 *		??0exception@@QAE@ABV0@@Z (MSVCRT.@)
167
 */
168
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
169
exception * __thiscall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
170
{
171 172 173
  TRACE("(%p,%p)\n", _this, rhs);

  if (!rhs->do_free)
174
  {
175 176 177
    _this->vtable = &MSVCRT_exception_vtable;
    _this->name = rhs->name;
    _this->do_free = FALSE;
178
  }
179 180 181
  else
    EXCEPTION_ctor(_this, (const char**)&rhs->name);
  TRACE("name = %s\n", _this->name);
182
  return _this;
183 184 185
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
186
 *		??0exception@@QAE@XZ (MSVCRT.@)
187
 */
188
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
189
exception * __thiscall MSVCRT_exception_default_ctor(exception * _this)
190
{
191 192 193 194
  static const char* empty = NULL;

  TRACE("(%p)\n", _this);
  EXCEPTION_ctor(_this, &empty);
195
  return _this;
196 197 198
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
199
 *		??1exception@@UAE@XZ (MSVCRT.@)
200
 */
201
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
202
void __thiscall MSVCRT_exception_dtor(exception * _this)
203
{
204 205 206
  TRACE("(%p)\n", _this);
  _this->vtable = &MSVCRT_exception_vtable;
  if (_this->do_free) MSVCRT_free(_this->name);
207 208 209
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
210
 *		??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
211
 */
212
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
213
exception * __thiscall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
214
{
215
  TRACE("(%p %p)\n", _this, rhs);
216 217 218 219 220
  if (_this != rhs)
  {
      MSVCRT_exception_dtor(_this);
      MSVCRT_exception_copy_ctor(_this, rhs);
  }
221
  TRACE("name = %s\n", _this->name);
222 223 224 225
  return _this;
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
226
 *		??_Eexception@@UAEPAXI@Z (MSVCRT.@)
227
 */
228
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
229
void * __thiscall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
230
{
231
    TRACE("(%p %x)\n", _this, flags);
232 233 234
    if (flags & 2)
    {
        /* we have an array, with the number of elements stored before the first object */
235
        INT_PTR i, *ptr = (INT_PTR *)_this - 1;
236 237 238 239 240 241 242 243 244 245

        for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
        MSVCRT_operator_delete(ptr);
    }
    else
    {
        MSVCRT_exception_dtor(_this);
        if (flags & 1) MSVCRT_operator_delete(_this);
    }
    return _this;
246 247 248
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
249
 *		??_Gexception@@UAEPAXI@Z (MSVCRT.@)
250
 */
251
DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
252
void * __thiscall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
253
{
254
    TRACE("(%p %x)\n", _this, flags);
255 256 257
    MSVCRT_exception_dtor(_this);
    if (flags & 1) MSVCRT_operator_delete(_this);
    return _this;
258 259 260
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
261
 *		?what@exception@@UBEPBDXZ (MSVCRT.@)
262
 */
263
DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
264
const char * __thiscall MSVCRT_what_exception(exception * _this)
265
{
266
  TRACE("(%p) returning %s\n", _this, _this->name);
267
  return _this->name ? _this->name : "Unknown exception";
268 269 270
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
271
 *		??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
272
 */
273
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
274
bad_typeid * __thiscall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
275
{
276 277 278
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_exception_copy_ctor(_this, rhs);
  _this->vtable = &MSVCRT_bad_typeid_vtable;
279
  return _this;
280 281 282
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
283
 *		??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
284
 */
285
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
286
bad_typeid * __thiscall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
287
{
288 289 290
  TRACE("(%p %s)\n", _this, name);
  EXCEPTION_ctor(_this, &name);
  _this->vtable = &MSVCRT_bad_typeid_vtable;
291
  return _this;
292 293
}

294 295 296 297
/******************************************************************
 *		??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
 */
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
298
bad_typeid * __thiscall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
299 300 301 302
{
  return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
}

303
/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
304
 *		??1bad_typeid@@UAE@XZ (MSVCRT.@)
305
 */
306
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
307
void __thiscall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
308
{
309 310
  TRACE("(%p)\n", _this);
  MSVCRT_exception_dtor(_this);
311 312 313
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
314
 *		??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
315
 */
316
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
317
bad_typeid * __thiscall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
318
{
319 320
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_exception_opequals(_this, rhs);
321 322 323
  return _this;
}

324 325 326
/******************************************************************
 *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
 */
327
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
328
void * __thiscall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
329
{
330
    TRACE("(%p %x)\n", _this, flags);
331 332 333
    if (flags & 2)
    {
        /* we have an array, with the number of elements stored before the first object */
334
        INT_PTR i, *ptr = (INT_PTR *)_this - 1;
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

        for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
        MSVCRT_operator_delete(ptr);
    }
    else
    {
        MSVCRT_bad_typeid_dtor(_this);
        if (flags & 1) MSVCRT_operator_delete(_this);
    }
    return _this;
}

/******************************************************************
 *		??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
 */
350
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
351
void * __thiscall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
352
{
353
    TRACE("(%p %x)\n", _this, flags);
354 355 356 357 358
    MSVCRT_bad_typeid_dtor(_this);
    if (flags & 1) MSVCRT_operator_delete(_this);
    return _this;
}

359
/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
360
 *		??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
361
 */
362
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
363
__non_rtti_object * __thiscall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
364
                                                                 const __non_rtti_object * rhs)
365
{
366 367 368
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_bad_typeid_copy_ctor(_this, rhs);
  _this->vtable = &MSVCRT___non_rtti_object_vtable;
369
  return _this;
370 371 372
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
373
 *		??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
374
 */
375
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
376
__non_rtti_object * __thiscall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
377
                                                            const char * name)
378
{
379 380 381
  TRACE("(%p %s)\n", _this, name);
  EXCEPTION_ctor(_this, &name);
  _this->vtable = &MSVCRT___non_rtti_object_vtable;
382
  return _this;
383 384 385
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
386
 *		??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
387
 */
388
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
389
void __thiscall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
390
{
391 392
  TRACE("(%p)\n", _this);
  MSVCRT_bad_typeid_dtor(_this);
393 394 395
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
396
 *		??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
397
 */
398
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
399
__non_rtti_object * __thiscall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
400
                                                                const __non_rtti_object *rhs)
401
{
402 403
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_bad_typeid_opequals(_this, rhs);
404 405 406 407
  return _this;
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
408
 *		??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
409
 */
410
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
411
void * __thiscall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
412
{
413
    TRACE("(%p %x)\n", _this, flags);
414 415 416
    if (flags & 2)
    {
        /* we have an array, with the number of elements stored before the first object */
417
        INT_PTR i, *ptr = (INT_PTR *)_this - 1;
418 419 420 421 422 423 424 425 426 427

        for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
        MSVCRT_operator_delete(ptr);
    }
    else
    {
        MSVCRT___non_rtti_object_dtor(_this);
        if (flags & 1) MSVCRT_operator_delete(_this);
    }
    return _this;
428 429 430
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
431
 *		??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
432
 */
433
DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
434
void * __thiscall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
435
{
436
  TRACE("(%p %x)\n", _this, flags);
437 438 439
  MSVCRT___non_rtti_object_dtor(_this);
  if (flags & 1) MSVCRT_operator_delete(_this);
  return _this;
440 441 442
}

/******************************************************************
443
 *		??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
Patrik Stridvall's avatar
Patrik Stridvall committed
444
 *		??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
445
 */
446
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
447
bad_cast * __thiscall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
448
{
449 450 451
  TRACE("(%p %s)\n", _this, *name);
  EXCEPTION_ctor(_this, name);
  _this->vtable = &MSVCRT_bad_cast_vtable;
452
  return _this;
453 454 455
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
456
 *		??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
457
 */
458
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
459
bad_cast * __thiscall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
460
{
461 462 463
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_exception_copy_ctor(_this, rhs);
  _this->vtable = &MSVCRT_bad_cast_vtable;
464
  return _this;
465 466
}

467 468 469 470
/******************************************************************
 *		??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
 */
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
471
bad_cast * __thiscall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
472 473 474 475 476 477 478 479 480 481 482
{
  TRACE("(%p %s)\n", _this, name);
  EXCEPTION_ctor(_this, &name);
  _this->vtable = &MSVCRT_bad_cast_vtable;
  return _this;
}

/******************************************************************
 *		??_Fbad_cast@@QAEXXZ (MSVCRT.@)
 */
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
483
bad_cast * __thiscall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
484 485 486 487
{
  return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
}

488
/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
489
 *		??1bad_cast@@UAE@XZ (MSVCRT.@)
490
 */
491
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
492
void __thiscall MSVCRT_bad_cast_dtor(bad_cast * _this)
493
{
494 495
  TRACE("(%p)\n", _this);
  MSVCRT_exception_dtor(_this);
496 497 498
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
499
 *		??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
500
 */
501
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
502
bad_cast * __thiscall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
503
{
504 505
  TRACE("(%p %p)\n", _this, rhs);
  MSVCRT_exception_opequals(_this, rhs);
506 507 508 509 510 511
  return _this;
}

/******************************************************************
 *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
 */
512
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
513
void * __thiscall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
514
{
515
    TRACE("(%p %x)\n", _this, flags);
516 517 518
    if (flags & 2)
    {
        /* we have an array, with the number of elements stored before the first object */
519
        INT_PTR i, *ptr = (INT_PTR *)_this - 1;
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534

        for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
        MSVCRT_operator_delete(ptr);
    }
    else
    {
        MSVCRT_bad_cast_dtor(_this);
        if (flags & 1) MSVCRT_operator_delete(_this);
    }
    return _this;
}

/******************************************************************
 *		??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
 */
535
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
536
void * __thiscall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
537
{
538
  TRACE("(%p %x)\n", _this, flags);
539 540
  MSVCRT_bad_cast_dtor(_this);
  if (flags & 1) MSVCRT_operator_delete(_this);
541 542 543 544
  return _this;
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
545
 *		??8type_info@@QBEHABV0@@Z (MSVCRT.@)
546
 */
547
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
548
int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
549
{
550 551
    int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
    TRACE("(%p %p) returning %d\n", _this, rhs, ret);
552
    return ret;
553 554 555
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
556
 *		??9type_info@@QBEHABV0@@Z (MSVCRT.@)
557
 */
558
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
559
int __thiscall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
560
{
561 562
    int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
    TRACE("(%p %p) returning %d\n", _this, rhs, ret);
563 564 565 566 567 568
    return ret;
}

/******************************************************************
 *		?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
 */
569
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
570
int __thiscall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
571
{
572 573
    int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
    TRACE("(%p %p) returning %d\n", _this, rhs, ret);
574
    return ret;
575 576 577
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
578
 *		??1type_info@@UAE@XZ (MSVCRT.@)
579
 */
580
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
581
void __thiscall MSVCRT_type_info_dtor(type_info * _this)
582
{
583
  TRACE("(%p)\n", _this);
584
  MSVCRT_free(_this->name);
585 586 587
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
588
 *		?name@type_info@@QBEPBDXZ (MSVCRT.@)
589
 */
590
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
591
const char * __thiscall MSVCRT_type_info_name(type_info * _this)
592
{
593 594 595
  if (!_this->name)
  {
    /* Create and set the demangled name */
André Hentschel's avatar
André Hentschel committed
596
    /* Note: mangled name in type_info struct always starts with a '.', while
597 598 599 600
     * it isn't valid for mangled name.
     * Is this '.' really part of the mangled name, or has it some other meaning ?
     */
    char* name = __unDName(0, _this->mangled + 1, 0,
601
                           MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
602 603 604 605 606
    if (name)
    {
      unsigned int len = strlen(name);

      /* It seems _unDName may leave blanks at the end of the demangled name */
607
      while (len && name[--len] == ' ')
608 609
        name[len] = '\0';

610
      if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
611 612 613 614 615 616 617
      {
        /* Another thread set this member since we checked above - use it */
        MSVCRT_free(name);
      }
    }
  }
  TRACE("(%p) returning %s\n", _this, _this->name);
618 619 620 621
  return _this->name;
}

/******************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
622
 *		?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
623
 */
624
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
625
const char * __thiscall MSVCRT_type_info_raw_name(type_info * _this)
626
{
627 628 629 630 631
  TRACE("(%p) returning %s\n", _this, _this->mangled);
  return _this->mangled;
}

/* Unexported */
632
DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
633
void * __thiscall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
634 635 636 637 638
{
    TRACE("(%p %x)\n", _this, flags);
    if (flags & 2)
    {
        /* we have an array, with the number of elements stored before the first object */
639
        INT_PTR i, *ptr = (INT_PTR *)_this - 1;
640 641 642 643 644 645 646 647 648 649

        for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
        MSVCRT_operator_delete(ptr);
    }
    else
    {
        MSVCRT_type_info_dtor(_this);
        if (flags & 1) MSVCRT_operator_delete(_this);
    }
    return _this;
650 651
}

652
#if _MSVCR_VER >= 80
653

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
typedef exception bad_alloc;
extern const vtable_ptr MSVCRT_bad_alloc_vtable;

static void bad_alloc_ctor(bad_alloc *this, const char **name)
{
    MSVCRT_exception_ctor(this, name);
    this->vtable = &MSVCRT_bad_alloc_vtable;
}

/* bad_alloc class implementation */
DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_copy_ctor,8)
bad_alloc * __thiscall MSVCRT_bad_alloc_copy_ctor(bad_alloc * _this, const bad_alloc * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_bad_alloc_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_bad_alloc_dtor,4)
void __thiscall MSVCRT_bad_alloc_dtor(bad_alloc * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
679 680

#endif /* _MSVCR_VER >= 80 */
681

682
#if _MSVCR_VER >= 100
683

684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
typedef struct {
    exception e;
    HRESULT hr;
} scheduler_resource_allocation_error;
extern const vtable_ptr MSVCRT_scheduler_resource_allocation_error_vtable;

/* ??0scheduler_resource_allocation_error@Concurrency@@QAE@PBDJ@Z */
/* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@PEBDJ@Z */
DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor_name, 12)
scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor_name(
        scheduler_resource_allocation_error *this, const char *name, HRESULT hr)
{
    TRACE("(%p %s %x)\n", this, wine_dbgstr_a(name), hr);
    MSVCRT_exception_ctor(&this->e, &name);
    this->e.vtable = &MSVCRT_scheduler_resource_allocation_error_vtable;
    this->hr = hr;
    return this;
}

/* ??0scheduler_resource_allocation_error@Concurrency@@QAE@J@Z */
/* ??0scheduler_resource_allocation_error@Concurrency@@QEAA@J@Z */
DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_ctor, 8)
scheduler_resource_allocation_error* __thiscall scheduler_resource_allocation_error_ctor(
        scheduler_resource_allocation_error *this, HRESULT hr)
{
    return scheduler_resource_allocation_error_ctor_name(this, NULL, hr);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_copy_ctor,8)
scheduler_resource_allocation_error* __thiscall MSVCRT_scheduler_resource_allocation_error_copy_ctor(
        scheduler_resource_allocation_error *this,
        const scheduler_resource_allocation_error *rhs)
{
    TRACE("(%p,%p)\n", this, rhs);

    if (!rhs->e.do_free)
        memcpy(this, rhs, sizeof(*this));
    else
        scheduler_resource_allocation_error_ctor_name(this, rhs->e.name, rhs->hr);
    return this;
}

/* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QBEJXZ */
/* ?get_error_code@scheduler_resource_allocation_error@Concurrency@@QEBAJXZ */
DEFINE_THISCALL_WRAPPER(scheduler_resource_allocation_error_get_error_code, 4)
HRESULT __thiscall scheduler_resource_allocation_error_get_error_code(
        const scheduler_resource_allocation_error *this)
{
    TRACE("(%p)\n", this);
    return this->hr;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_scheduler_resource_allocation_error_dtor,4)
void __thiscall MSVCRT_scheduler_resource_allocation_error_dtor(
        scheduler_resource_allocation_error * this)
{
    TRACE("(%p)\n", this);
    MSVCRT_exception_dtor(&this->e);
}
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780

typedef exception improper_lock;
extern const vtable_ptr MSVCRT_improper_lock_vtable;

/* ??0improper_lock@Concurrency@@QAE@PBD@Z */
/* ??0improper_lock@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(improper_lock_ctor_str, 8)
improper_lock* __thiscall improper_lock_ctor_str(improper_lock *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_improper_lock_vtable;
    return this;
}

/* ??0improper_lock@Concurrency@@QAE@XZ */
/* ??0improper_lock@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(improper_lock_ctor, 4)
improper_lock* __thiscall improper_lock_ctor(improper_lock *this)
{
    return improper_lock_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_copy_ctor,8)
improper_lock * __thiscall MSVCRT_improper_lock_copy_ctor(improper_lock * _this, const improper_lock * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_improper_lock_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_lock_dtor,4)
void __thiscall MSVCRT_improper_lock_dtor(improper_lock * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822

typedef exception invalid_scheduler_policy_key;
extern const vtable_ptr MSVCRT_invalid_scheduler_policy_key_vtable;

/* ??0invalid_scheduler_policy_key@Concurrency@@QAE@PBD@Z */
/* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor_str, 8)
invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor_str(
        invalid_scheduler_policy_key *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable;
    return this;
}

/* ??0invalid_scheduler_policy_key@Concurrency@@QAE@XZ */
/* ??0invalid_scheduler_policy_key@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_key_ctor, 4)
invalid_scheduler_policy_key* __thiscall invalid_scheduler_policy_key_ctor(
        invalid_scheduler_policy_key *this)
{
    return invalid_scheduler_policy_key_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_copy_ctor,8)
invalid_scheduler_policy_key * __thiscall MSVCRT_invalid_scheduler_policy_key_copy_ctor(
        invalid_scheduler_policy_key * _this, const invalid_scheduler_policy_key * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_invalid_scheduler_policy_key_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_key_dtor,4)
void __thiscall MSVCRT_invalid_scheduler_policy_key_dtor(
        invalid_scheduler_policy_key * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864

typedef exception invalid_scheduler_policy_value;
extern const vtable_ptr MSVCRT_invalid_scheduler_policy_value_vtable;

/* ??0invalid_scheduler_policy_value@Concurrency@@QAE@PBD@Z */
/* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor_str, 8)
invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor_str(
        invalid_scheduler_policy_value *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable;
    return this;
}

/* ??0invalid_scheduler_policy_value@Concurrency@@QAE@XZ */
/* ??0invalid_scheduler_policy_value@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_value_ctor, 4)
invalid_scheduler_policy_value* __thiscall invalid_scheduler_policy_value_ctor(
        invalid_scheduler_policy_value *this)
{
    return invalid_scheduler_policy_value_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_copy_ctor,8)
invalid_scheduler_policy_value * __thiscall MSVCRT_invalid_scheduler_policy_value_copy_ctor(
        invalid_scheduler_policy_value * _this, const invalid_scheduler_policy_value * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_invalid_scheduler_policy_value_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_value_dtor,4)
void __thiscall MSVCRT_invalid_scheduler_policy_value_dtor(
        invalid_scheduler_policy_value * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906

typedef exception invalid_scheduler_policy_thread_specification;
extern const vtable_ptr MSVCRT_invalid_scheduler_policy_thread_specification_vtable;

/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@PBD@Z */
/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor_str, 8)
invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor_str(
        invalid_scheduler_policy_thread_specification *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable;
    return this;
}

/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QAE@XZ */
/* ??0invalid_scheduler_policy_thread_specification@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(invalid_scheduler_policy_thread_specification_ctor, 4)
invalid_scheduler_policy_thread_specification* __thiscall invalid_scheduler_policy_thread_specification_ctor(
        invalid_scheduler_policy_thread_specification *this)
{
    return invalid_scheduler_policy_thread_specification_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor,8)
invalid_scheduler_policy_thread_specification * __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_copy_ctor(
        invalid_scheduler_policy_thread_specification * _this, const invalid_scheduler_policy_thread_specification * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_invalid_scheduler_policy_thread_specification_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_invalid_scheduler_policy_thread_specification_dtor,4)
void __thiscall MSVCRT_invalid_scheduler_policy_thread_specification_dtor(
        invalid_scheduler_policy_thread_specification * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948

typedef exception improper_scheduler_attach;
extern const vtable_ptr MSVCRT_improper_scheduler_attach_vtable;

/* ??0improper_scheduler_attach@Concurrency@@QAE@PBD@Z */
/* ??0improper_scheduler_attach@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor_str, 8)
improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor_str(
        improper_scheduler_attach *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_improper_scheduler_attach_vtable;
    return this;
}

/* ??0improper_scheduler_attach@Concurrency@@QAE@XZ */
/* ??0improper_scheduler_attach@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(improper_scheduler_attach_ctor, 4)
improper_scheduler_attach* __thiscall improper_scheduler_attach_ctor(
        improper_scheduler_attach *this)
{
    return improper_scheduler_attach_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_copy_ctor,8)
improper_scheduler_attach * __thiscall MSVCRT_improper_scheduler_attach_copy_ctor(
        improper_scheduler_attach * _this, const improper_scheduler_attach * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_improper_scheduler_attach_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_attach_dtor,4)
void __thiscall MSVCRT_improper_scheduler_attach_dtor(
        improper_scheduler_attach * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990

typedef exception improper_scheduler_detach;
extern const vtable_ptr MSVCRT_improper_scheduler_detach_vtable;

/* ??0improper_scheduler_detach@Concurrency@@QAE@PBD@Z */
/* ??0improper_scheduler_detach@Concurrency@@QEAA@PEBD@Z */
DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor_str, 8)
improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor_str(
        improper_scheduler_detach *this, const char *str)
{
    TRACE("(%p %p)\n", this, str);
    MSVCRT_exception_ctor(this, &str);
    this->vtable = &MSVCRT_improper_scheduler_detach_vtable;
    return this;
}

/* ??0improper_scheduler_detach@Concurrency@@QAE@XZ */
/* ??0improper_scheduler_detach@Concurrency@@QEAA@XZ */
DEFINE_THISCALL_WRAPPER(improper_scheduler_detach_ctor, 4)
improper_scheduler_detach* __thiscall improper_scheduler_detach_ctor(
        improper_scheduler_detach *this)
{
    return improper_scheduler_detach_ctor_str(this, NULL);
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_copy_ctor,8)
improper_scheduler_detach * __thiscall MSVCRT_improper_scheduler_detach_copy_ctor(
        improper_scheduler_detach * _this, const improper_scheduler_detach * rhs)
{
    TRACE("(%p %p)\n", _this, rhs);
    MSVCRT_exception_copy_ctor(_this, rhs);
    _this->vtable = &MSVCRT_improper_scheduler_detach_vtable;
    return _this;
}

DEFINE_THISCALL_WRAPPER(MSVCRT_improper_scheduler_detach_dtor,4)
void __thiscall MSVCRT_improper_scheduler_detach_dtor(
        improper_scheduler_detach * _this)
{
    TRACE("(%p)\n", _this);
    MSVCRT_exception_dtor(_this);
}
991 992

#endif /* _MSVCR_VER >= 100 */
993

994 995 996
#ifndef __GNUC__
void __asm_dummy_vtables(void) {
#endif
997

998 999 1000 1001 1002
__ASM_VTABLE(type_info,
        VTABLE_ADD_FUNC(MSVCRT_type_info_vector_dtor));
__ASM_VTABLE(exception,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1003 1004 1005 1006
#if _MSVCR_VER >= 80
__ASM_VTABLE(exception_old,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1007 1008 1009
__ASM_VTABLE(bad_alloc,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1010
#endif
1011 1012 1013 1014 1015 1016 1017 1018 1019
__ASM_VTABLE(bad_typeid,
        VTABLE_ADD_FUNC(MSVCRT_bad_typeid_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
__ASM_VTABLE(bad_cast,
        VTABLE_ADD_FUNC(MSVCRT_bad_cast_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
__ASM_VTABLE(__non_rtti_object,
        VTABLE_ADD_FUNC(MSVCRT___non_rtti_object_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1020 1021 1022 1023
#if _MSVCR_VER >= 100
__ASM_VTABLE(scheduler_resource_allocation_error,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1024 1025 1026
__ASM_VTABLE(improper_lock,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1027 1028 1029
__ASM_VTABLE(invalid_scheduler_policy_key,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1030 1031 1032
__ASM_VTABLE(invalid_scheduler_policy_value,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1033 1034 1035
__ASM_VTABLE(invalid_scheduler_policy_thread_specification,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1036 1037 1038
__ASM_VTABLE(improper_scheduler_attach,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1039 1040 1041
__ASM_VTABLE(improper_scheduler_detach,
        VTABLE_ADD_FUNC(MSVCRT_exception_vector_dtor)
        VTABLE_ADD_FUNC(MSVCRT_what_exception));
1042
#endif
1043

1044 1045 1046
#ifndef __GNUC__
}
#endif
1047

1048
DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" )
1049 1050 1051 1052 1053 1054
#if _MSVCR_VER >= 80
DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@std@@" )
DEFINE_RTTI_DATA0( exception_old, 0, ".?AVexception@@" )
DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@std@@" )
DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@std@@" )
DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@std@@" )
1055
DEFINE_RTTI_DATA1( bad_alloc, 0, &exception_rtti_base_descriptor, ".?AVbad_alloc@std@@" )
1056
#else
1057 1058 1059 1060
DEFINE_RTTI_DATA0( exception, 0, ".?AVexception@@" )
DEFINE_RTTI_DATA1( bad_typeid, 0, &exception_rtti_base_descriptor, ".?AVbad_typeid@@" )
DEFINE_RTTI_DATA1( bad_cast, 0, &exception_rtti_base_descriptor, ".?AVbad_cast@@" )
DEFINE_RTTI_DATA2( __non_rtti_object, 0, &bad_typeid_rtti_base_descriptor, &exception_rtti_base_descriptor, ".?AV__non_rtti_object@@" )
1061
#endif
1062 1063 1064
#if _MSVCR_VER >= 100
DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &exception_rtti_base_descriptor,
        ".?AVscheduler_resource_allocation_error@Concurrency@@")
1065
DEFINE_RTTI_DATA1(improper_lock, 0, &exception_rtti_base_descriptor, ".?AVimproper_lock@Concurrency@@" )
1066 1067
DEFINE_RTTI_DATA1(invalid_scheduler_policy_key, 0, &exception_rtti_base_descriptor,
        ".?AVinvalid_scheduler_policy_key@Concurrency@@" )
1068 1069
DEFINE_RTTI_DATA1(invalid_scheduler_policy_value, 0, &exception_rtti_base_descriptor,
        ".?AVinvalid_scheduler_policy_value@Concurrency@@" )
1070 1071
DEFINE_RTTI_DATA1(invalid_scheduler_policy_thread_specification, 0, &exception_rtti_base_descriptor,
        ".?AVinvalid_scheduler_policy_thread_specification@Concurrency@@" )
1072 1073
DEFINE_RTTI_DATA1(improper_scheduler_attach, 0, &exception_rtti_base_descriptor,
        ".?AVimproper_scheduler_attach@Concurrency@@" )
1074 1075
DEFINE_RTTI_DATA1(improper_scheduler_detach, 0, &exception_rtti_base_descriptor,
        ".?AVimproper_scheduler_detach@Concurrency@@" )
1076
#endif
1077 1078 1079 1080 1081

DEFINE_EXCEPTION_TYPE_INFO( exception, 0, NULL, NULL )
DEFINE_EXCEPTION_TYPE_INFO( bad_typeid, 1, &exception_cxx_type_info, NULL )
DEFINE_EXCEPTION_TYPE_INFO( bad_cast, 1, &exception_cxx_type_info, NULL )
DEFINE_EXCEPTION_TYPE_INFO( __non_rtti_object, 2, &bad_typeid_cxx_type_info, &exception_cxx_type_info )
1082 1083
#if _MSVCR_VER >= 80
DEFINE_EXCEPTION_TYPE_INFO( bad_alloc, 1, &exception_cxx_type_info, NULL )
1084 1085 1086
#endif
#if _MSVCR_VER >= 100
DEFINE_EXCEPTION_TYPE_INFO(scheduler_resource_allocation_error, 1, &exception_cxx_type_info, NULL)
1087
DEFINE_EXCEPTION_TYPE_INFO(improper_lock, 1, &exception_cxx_type_info, NULL)
1088
DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_key, 1, &exception_cxx_type_info, NULL)
1089
DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_value, 1, &exception_cxx_type_info, NULL)
1090
DEFINE_EXCEPTION_TYPE_INFO(invalid_scheduler_policy_thread_specification, 1, &exception_cxx_type_info, NULL)
1091
DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_attach, 1, &exception_cxx_type_info, NULL)
1092
DEFINE_EXCEPTION_TYPE_INFO(improper_scheduler_detach, 1, &exception_cxx_type_info, NULL)
1093 1094
#endif

1095 1096 1097 1098 1099
void msvcrt_init_exception(void *base)
{
#ifdef __x86_64__
    init_type_info_rtti(base);
    init_exception_rtti(base);
1100 1101
#if _MSVCR_VER >= 80
    init_exception_old_rtti(base);
1102
    init_bad_alloc_rtti(base);
1103
#endif
1104 1105 1106
    init_bad_typeid_rtti(base);
    init_bad_cast_rtti(base);
    init___non_rtti_object_rtti(base);
1107 1108
#if _MSVCR_VER >= 100
    init_scheduler_resource_allocation_error_rtti(base);
1109
    init_improper_lock_rtti(base);
1110
    init_invalid_scheduler_policy_key_rtti(base);
1111
    init_invalid_scheduler_policy_value_rtti(base);
1112
    init_invalid_scheduler_policy_thread_specification_rtti(base);
1113
    init_improper_scheduler_attach_rtti(base);
1114
    init_improper_scheduler_detach_rtti(base);
1115
#endif
1116 1117 1118 1119 1120

    init_exception_cxx(base);
    init_bad_typeid_cxx(base);
    init_bad_cast_cxx(base);
    init___non_rtti_object_cxx(base);
1121 1122 1123
#if _MSVCR_VER >= 80
    init_bad_alloc_cxx(base);
#endif
1124 1125
#if _MSVCR_VER >= 100
    init_scheduler_resource_allocation_error_cxx(base);
1126
    init_improper_lock_cxx(base);
1127
    init_invalid_scheduler_policy_key_cxx(base);
1128
    init_invalid_scheduler_policy_value_cxx(base);
1129
    init_invalid_scheduler_policy_thread_specification_cxx(base);
1130
    init_improper_scheduler_attach_cxx(base);
1131
    init_improper_scheduler_detach_cxx(base);
1132
#endif
1133 1134 1135
#endif
}

1136
#if _MSVCR_VER >= 80
1137
void throw_exception(exception_type et, HRESULT hr, const char *str)
1138
{
1139 1140 1141 1142 1143 1144
    switch(et) {
    case EXCEPTION_BAD_ALLOC: {
        bad_alloc e;
        bad_alloc_ctor(&e, &str);
        _CxxThrowException(&e, &bad_alloc_exception_type);
    }
1145
#if _MSVCR_VER >= 100
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    case EXCEPTION_SCHEDULER_RESOURCE_ALLOCATION_ERROR: {
        scheduler_resource_allocation_error e;
        scheduler_resource_allocation_error_ctor_name(&e, str, hr);
        _CxxThrowException(&e.e, &scheduler_resource_allocation_error_exception_type);
    }
    case EXCEPTION_IMPROPER_LOCK: {
        improper_lock e;
        improper_lock_ctor_str(&e, str);
        _CxxThrowException(&e, &improper_lock_exception_type);
    }
1156 1157 1158 1159 1160
    case EXCEPTION_INVALID_SCHEDULER_POLICY_KEY: {
        invalid_scheduler_policy_key e;
        invalid_scheduler_policy_key_ctor_str(&e, str);
        _CxxThrowException(&e, &invalid_scheduler_policy_key_exception_type);
    }
1161 1162 1163 1164 1165
    case EXCEPTION_INVALID_SCHEDULER_POLICY_VALUE: {
        invalid_scheduler_policy_value e;
        invalid_scheduler_policy_value_ctor_str(&e, str);
        _CxxThrowException(&e, &invalid_scheduler_policy_value_exception_type);
    }
1166 1167 1168 1169 1170
    case EXCEPTION_INVALID_SCHEDULER_POLICY_THREAD_SPECIFICATION: {
        invalid_scheduler_policy_thread_specification e;
        invalid_scheduler_policy_thread_specification_ctor_str(&e, str);
        _CxxThrowException(&e, &invalid_scheduler_policy_thread_specification_exception_type);
    }
1171 1172 1173 1174 1175
    case EXCEPTION_IMPROPER_SCHEDULER_ATTACH: {
        improper_scheduler_attach e;
        improper_scheduler_attach_ctor_str(&e, str);
        _CxxThrowException(&e, &improper_scheduler_attach_exception_type);
    }
1176 1177 1178 1179 1180
    case EXCEPTION_IMPROPER_SCHEDULER_DETACH: {
        improper_scheduler_detach e;
        improper_scheduler_detach_ctor_str(&e, str);
        _CxxThrowException(&e, &improper_scheduler_detach_exception_type);
    }
1181 1182
#endif
    }
1183
}
1184 1185
#endif

1186 1187
/******************************************************************
 *		?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
1188 1189 1190 1191 1192 1193 1194 1195
 *
 * Install a handler to be called when terminate() is called.
 *
 * PARAMS
 *  func [I] Handler function to install
 *
 * RETURNS
 *  The previously installed handler function, if any.
1196
 */
1197
MSVCRT_terminate_function CDECL MSVCRT_set_terminate(MSVCRT_terminate_function func)
1198
{
1199 1200
    thread_data_t *data = msvcrt_get_thread_data();
    MSVCRT_terminate_function previous = data->terminate_handler;
1201 1202 1203 1204 1205
    TRACE("(%p) returning %p\n",func,previous);
    data->terminate_handler = func;
    return previous;
}

1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
/******************************************************************
 *              _get_terminate (MSVCRT.@)
 */
MSVCRT_terminate_function CDECL MSVCRT__get_terminate(void)
{
    thread_data_t *data = msvcrt_get_thread_data();
    TRACE("returning %p\n", data->terminate_handler);
    return data->terminate_handler;
}

1216 1217
/******************************************************************
 *		?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
1218 1219 1220 1221 1222 1223 1224 1225
 *
 * Install a handler to be called when unexpected() is called.
 *
 * PARAMS
 *  func [I] Handler function to install
 *
 * RETURNS
 *  The previously installed handler function, if any.
1226
 */
1227
MSVCRT_unexpected_function CDECL MSVCRT_set_unexpected(MSVCRT_unexpected_function func)
1228
{
1229 1230
    thread_data_t *data = msvcrt_get_thread_data();
    MSVCRT_unexpected_function previous = data->unexpected_handler;
1231 1232 1233 1234 1235
    TRACE("(%p) returning %p\n",func,previous);
    data->unexpected_handler = func;
    return previous;
}

1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
/******************************************************************
 *              _get_unexpected (MSVCRT.@)
 */
MSVCRT_unexpected_function CDECL MSVCRT__get_unexpected(void)
{
    thread_data_t *data = msvcrt_get_thread_data();
    TRACE("returning %p\n", data->unexpected_handler);
    return data->unexpected_handler;
}

1246 1247 1248
/******************************************************************
 *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
 */
1249
MSVCRT__se_translator_function CDECL MSVCRT__set_se_translator(MSVCRT__se_translator_function func)
1250
{
1251 1252
    thread_data_t *data = msvcrt_get_thread_data();
    MSVCRT__se_translator_function previous = data->se_translator;
1253 1254 1255 1256 1257 1258 1259
    TRACE("(%p) returning %p\n",func,previous);
    data->se_translator = func;
    return previous;
}

/******************************************************************
 *		?terminate@@YAXXZ (MSVCRT.@)
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
 *
 * Default handler for an unhandled exception.
 *
 * PARAMS
 *  None.
 *
 * RETURNS
 *  This function does not return. Either control resumes from any
 *  handler installed by calling set_terminate(), or (by default) abort()
 *  is called.
1270
 */
1271
void CDECL MSVCRT_terminate(void)
1272
{
1273
    thread_data_t *data = msvcrt_get_thread_data();
1274 1275 1276 1277 1278 1279 1280
    if (data->terminate_handler) data->terminate_handler();
    MSVCRT_abort();
}

/******************************************************************
 *		?unexpected@@YAXXZ (MSVCRT.@)
 */
1281
void CDECL MSVCRT_unexpected(void)
1282
{
1283
    thread_data_t *data = msvcrt_get_thread_data();
1284 1285 1286
    if (data->unexpected_handler) data->unexpected_handler();
    MSVCRT_terminate();
}
1287

1288

1289 1290
/******************************************************************
 *		__RTtypeid (MSVCRT.@)
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
 *
 * Retrieve the Run Time Type Information (RTTI) for a C++ object.
 *
 * PARAMS
 *  cppobj [I] C++ object to get type information for.
 *
 * RETURNS
 *  Success: A type_info object describing cppobj.
 *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
 *           exception is thrown. If cppobj is NULL, a bad_typeid exception
 *           is thrown. In either case, this function does not return.
 *
 * NOTES
 *  This function is usually called by compiler generated code as a result
 *  of using one of the C++ dynamic cast statements.
1306
 */
1307
#ifndef __x86_64__
1308
const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
1309
{
1310
    const type_info *ret;
1311 1312 1313

    if (!cppobj)
    {
1314 1315 1316 1317
        bad_typeid e;
        MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
        _CxxThrowException( &e, &bad_typeid_exception_type );
        return NULL;
1318
    }
1319 1320

    __TRY
1321
    {
1322 1323
        const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
        ret = obj_locator->type_descriptor;
1324
    }
1325
    __EXCEPT_PAGE_FAULT
1326 1327 1328
    {
        __non_rtti_object e;
        MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
1329
        _CxxThrowException( &e, &__non_rtti_object_exception_type );
1330 1331 1332 1333
        return NULL;
    }
    __ENDTRY
    return ret;
1334 1335
}

1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
#else

const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
{
    const type_info *ret;

    if (!cppobj)
    {
        bad_typeid e;
        MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
        _CxxThrowException( &e, &bad_typeid_exception_type );
        return NULL;
    }

    __TRY
    {
1352 1353 1354
        const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
        char *base;

1355
        if(obj_locator->signature == 0)
1356
            base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
1357
        else
1358 1359 1360
            base = (char*)obj_locator - obj_locator->object_locator;

        ret = (type_info*)(base + obj_locator->type_descriptor);
1361 1362 1363 1364 1365
    }
    __EXCEPT_PAGE_FAULT
    {
        __non_rtti_object e;
        MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
1366
        _CxxThrowException( &e, &__non_rtti_object_exception_type );
1367 1368 1369 1370 1371 1372 1373
        return NULL;
    }
    __ENDTRY
    return ret;
}
#endif

1374 1375
/******************************************************************
 *		__RTDynamicCast (MSVCRT.@)
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
 *
 * Dynamically cast a C++ object to one of its base classes.
 *
 * PARAMS
 *  cppobj   [I] Any C++ object to cast
 *  unknown  [I] Reserved, set to 0
 *  src      [I] type_info object describing cppobj
 *  dst      [I] type_info object describing the base class to cast to
 *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
 *
 * RETURNS
 *  Success: The address of cppobj, cast to the object described by dst.
 *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
 *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
 *           is thrown and this function does not return.
 *
 * NOTES
 *  This function is usually called by compiler generated code as a result
 *  of using one of the C++ dynamic cast statements.
1395
 */
1396
#ifndef __x86_64__
1397 1398 1399
void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
                                   type_info *src, type_info *dst,
                                   int do_throw)
1400
{
1401
    void *ret;
1402

1403
    if (!cppobj) return NULL;
1404

1405 1406
    TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
          cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
1407

1408 1409 1410 1411 1412
    /* To cast an object at runtime:
     * 1.Find out the true type of the object from the typeinfo at vtable[-1]
     * 2.Search for the destination type in the class hierarchy
     * 3.If destination type is found, return base object address + dest offset
     *   Otherwise, fail the cast
1413 1414
     *
     * FIXME: the unknown parameter doesn't seem to be used for anything
1415 1416 1417 1418 1419 1420
     */
    __TRY
    {
        int i;
        const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
        const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
1421
        const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448

        if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);

        ret = NULL;
        for (i = 0; i < obj_bases->array_len; i++)
        {
            const type_info *typ = base_desc[i]->type_descriptor;

            if (!strcmp(typ->mangled, dst->mangled))
            {
                /* compute the correct this pointer for that base class */
                void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
                ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
                break;
            }
        }
        /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
         * to a reference, since references cannot be NULL.
         */
        if (!ret && do_throw)
        {
            const char *msg = "Bad dynamic_cast!";
            bad_cast e;
            MSVCRT_bad_cast_ctor( &e, &msg );
            _CxxThrowException( &e, &bad_cast_exception_type );
        }
    }
1449
    __EXCEPT_PAGE_FAULT
1450 1451 1452
    {
        __non_rtti_object e;
        MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1453
        _CxxThrowException( &e, &__non_rtti_object_exception_type );
1454 1455 1456 1457
        return NULL;
    }
    __ENDTRY
    return ret;
1458 1459
}

1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
#else

void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
        type_info *src, type_info *dst,
        int do_throw)
{
    void *ret;

    if (!cppobj) return NULL;

    TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
            cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);

    __TRY
    {
        int i;
        const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
1477 1478 1479 1480 1481
        const rtti_object_hierarchy *obj_bases;
        const rtti_base_array *base_array;
        char *base;

        if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
1482 1483

        if(obj_locator->signature == 0)
1484
            base = RtlPcToFileHeader((void*)obj_locator, (void**)&base);
1485 1486
        else
            base = (char*)obj_locator - obj_locator->object_locator;
1487

1488 1489
        obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy);
        base_array = (const rtti_base_array*)(base + obj_bases->base_classes);
1490

1491 1492
        ret = NULL;
        for (i = 0; i < obj_bases->array_len; i++)
1493
        {
1494 1495
            const rtti_base_descriptor *base_desc = (const rtti_base_descriptor*)(base + base_array->bases[i]);
            const type_info *typ = (const type_info*)(base + base_desc->type_descriptor);
1496

1497
            if (!strcmp(typ->mangled, dst->mangled))
1498
            {
1499 1500 1501
                void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
                ret = get_this_pointer( &base_desc->offsets, this_ptr );
                break;
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
            }
        }
        if (!ret && do_throw)
        {
            const char *msg = "Bad dynamic_cast!";
            bad_cast e;
            MSVCRT_bad_cast_ctor( &e, &msg );
            _CxxThrowException( &e, &bad_cast_exception_type );
        }
    }
    __EXCEPT_PAGE_FAULT
    {
        __non_rtti_object e;
        MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1516
        _CxxThrowException( &e, &__non_rtti_object_exception_type );
1517 1518 1519 1520 1521 1522 1523
        return NULL;
    }
    __ENDTRY
    return ret;
}
#endif

1524 1525 1526

/******************************************************************
 *		__RTCastToVoid (MSVCRT.@)
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
 *
 * Dynamically cast a C++ object to a void*.
 *
 * PARAMS
 *  cppobj [I] The C++ object to cast
 *
 * RETURNS
 *  Success: The base address of the object as a void*.
 *  Failure: NULL, if cppobj is NULL or has no RTTI.
 *
 * NOTES
 *  This function is usually called by compiler generated code as a result
 *  of using one of the C++ dynamic cast statements.
1540
 */
1541
void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
1542
{
1543
    void *ret;
1544

1545
    if (!cppobj) return NULL;
1546

1547 1548 1549 1550 1551
    __TRY
    {
        const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
        ret = (char *)cppobj - obj_locator->base_class_offset;
    }
1552
    __EXCEPT_PAGE_FAULT
1553 1554 1555
    {
        __non_rtti_object e;
        MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
1556
        _CxxThrowException( &e, &__non_rtti_object_exception_type );
1557 1558 1559 1560
        return NULL;
    }
    __ENDTRY
    return ret;
1561
}
1562 1563 1564 1565 1566


/*********************************************************************
 *		_CxxThrowException (MSVCRT.@)
 */
1567
#ifndef __x86_64__
1568 1569 1570 1571 1572 1573 1574 1575 1576
void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
{
    ULONG_PTR args[3];

    args[0] = CXX_FRAME_MAGIC_VC6;
    args[1] = (ULONG_PTR)object;
    args[2] = (ULONG_PTR)type;
    RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
}
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
#else
void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
{
    ULONG_PTR args[4];

    args[0] = CXX_FRAME_MAGIC_VC6;
    args[1] = (ULONG_PTR)object;
    args[2] = (ULONG_PTR)type;
    RtlPcToFileHeader( (void*)type, (void**)&args[3]);
    RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 4, args );
}
#endif
1589

1590 1591
#if _MSVCR_VER >= 80

1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
/*********************************************************************
 * ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z
 * ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z
 */
#ifndef __x86_64__
int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
{
    int ret = -1;

    TRACE("(%p %p)\n", ti, ep);

    __TRY
    {
        EXCEPTION_RECORD *rec = ep->ExceptionRecord;

        if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==3 &&
                (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
                 rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
                 rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
        {
            const cxx_type_info_table *tit = ((cxx_exception_type*)rec->ExceptionInformation[2])->type_info_table;
            int i;

            for (i=0; i<tit->count; i++) {
                if (ti==tit->info[i]->type_info || !strcmp(ti->mangled, tit->info[i]->type_info->mangled))
                {
                    ret = 1;
                    break;
                }
            }

            if (i == tit->count)
                ret = 0;
        }
    }
    __EXCEPT_PAGE_FAULT
    __ENDTRY

    if(ret == -1)
        MSVCRT_terminate();
    return ret;
}
#else
int __cdecl _is_exception_typeof(const type_info *ti, EXCEPTION_POINTERS *ep)
{
    int ret = -1;

    TRACE("(%p %p)\n", ti, ep);

    __TRY
    {
        EXCEPTION_RECORD *rec = ep->ExceptionRecord;

        if (rec->ExceptionCode==CXX_EXCEPTION && rec->NumberParameters==4 &&
                (rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC6 ||
                 rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC7 ||
                 rec->ExceptionInformation[0]==CXX_FRAME_MAGIC_VC8))
        {
            const cxx_exception_type *et = (cxx_exception_type*)rec->ExceptionInformation[2];
            const cxx_type_info_table *tit = (const cxx_type_info_table*)(rec->ExceptionInformation[3]+et->type_info_table);
            int i;

            for (i=0; i<tit->count; i++) {
                const cxx_type_info *cti = (const cxx_type_info*)(rec->ExceptionInformation[3]+tit->info[i]);
                const type_info *except_ti = (const type_info*)(rec->ExceptionInformation[3]+cti->type_info);
                if (ti==except_ti || !strcmp(ti->mangled, except_ti->mangled))
                {
                    ret = 1;
                    break;
                }
            }

            if (i == tit->count)
                ret = 0;
        }
    }
    __EXCEPT_PAGE_FAULT
    __ENDTRY

    if(ret == -1)
        MSVCRT_terminate();
    return ret;
}
#endif
1676 1677

/*********************************************************************
1678
 * __clean_type_info_names_internal (MSVCR80.@)
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
 */
void CDECL __clean_type_info_names_internal(void *p)
{
    FIXME("(%p) stub\n", p);
}

/*********************************************************************
 * ?_name_internal_method@type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR100.@)
 */
DEFINE_THISCALL_WRAPPER(type_info_name_internal_method,8)
const char * __thiscall type_info_name_internal_method(type_info * _this, struct __type_info_node *node)
{
    static int once;
    if (node && !once++) FIXME("type_info_node parameter ignored\n");

1694
    return MSVCRT_type_info_name(_this);
1695
}
1696

1697 1698
#endif /* _MSVCR_VER >= 80 */

1699 1700 1701 1702 1703 1704 1705
/* std::exception_ptr class helpers */
typedef struct
{
    EXCEPTION_RECORD *rec;
    int *ref; /* not binary compatible with native msvcr100 */
} exception_ptr;

1706 1707
#if _MSVCR_VER >= 100

1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
/*********************************************************************
 * ?__ExceptionPtrCreate@@YAXPAX@Z
 * ?__ExceptionPtrCreate@@YAXPEAX@Z
 */
void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
{
    TRACE("(%p)\n", ep);

    ep->rec = NULL;
    ep->ref = NULL;
}

1720
#if defined(__i386__) && !defined(__MINGW32__)
1721 1722 1723 1724 1725 1726
extern void call_dtor(const cxx_exception_type *type, void *func, void *object);

__ASM_GLOBAL_FUNC( call_dtor,
                   "movl 12(%esp),%ecx\n\t"
                   "call *8(%esp)\n\t"
                   "ret" );
1727 1728 1729 1730 1731 1732 1733 1734
#elif __x86_64__
static inline void call_dtor(const cxx_exception_type *type, unsigned int dtor, void *object)
{
    char *base = RtlPcToFileHeader((void*)type, (void**)&base);
    void (__cdecl *func)(void*) = (void*)(base + dtor);
    func(object);
}
#else
1735
#define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
#endif

/*********************************************************************
 * ?__ExceptionPtrDestroy@@YAXPAX@Z
 * ?__ExceptionPtrDestroy@@YAXPEAX@Z
 */
void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
{
    TRACE("(%p)\n", ep);

    if (!ep->rec)
        return;

    if (!InterlockedDecrement(ep->ref))
    {
        if (ep->rec->ExceptionCode == CXX_EXCEPTION)
        {
            const cxx_exception_type *type = (void*)ep->rec->ExceptionInformation[2];
            void *obj = (void*)ep->rec->ExceptionInformation[1];

            if (type && type->destructor) call_dtor(type, type->destructor, obj);
            HeapFree(GetProcessHeap(), 0, obj);
        }

        HeapFree(GetProcessHeap(), 0, ep->rec);
        HeapFree(GetProcessHeap(), 0, ep->ref);
    }
}

/*********************************************************************
 * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
 * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
 */
void __cdecl __ExceptionPtrCopy(exception_ptr *ep, const exception_ptr *copy)
{
    TRACE("(%p %p)\n", ep, copy);

    /* don't destroy object stored in ep */
    *ep = *copy;
    if (ep->ref)
        InterlockedIncrement(copy->ref);
}

1779 1780 1781 1782 1783 1784 1785 1786 1787
/*********************************************************************
 * ?__ExceptionPtrAssign@@YAXPAXPBX@Z
 * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
 */
void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign)
{
    TRACE("(%p %p)\n", ep, assign);

    /* don't destroy object stored in ep */
1788 1789 1790
    if (ep->ref)
        InterlockedDecrement(ep->ref);

1791
    *ep = *assign;
1792 1793
    if (ep->ref)
        InterlockedIncrement(ep->ref);
1794 1795
}

1796 1797
#endif /* _MSVCR_VER >= 100 */

1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
/*********************************************************************
 * ?__ExceptionPtrRethrow@@YAXPBX@Z
 * ?__ExceptionPtrRethrow@@YAXPEBX@Z
 */
void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
{
    TRACE("(%p)\n", ep);

    if (!ep->rec)
    {
        static const char *exception_msg = "bad exception";
        exception e;

        MSVCRT_exception_ctor(&e, &exception_msg);
        _CxxThrowException(&e, &exception_exception_type);
        return;
    }

    RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
            ep->rec->NumberParameters, ep->rec->ExceptionInformation);
}

1820 1821
#if _MSVCR_VER >= 100

1822
#ifdef __i386__
1823
extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
#else
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
{
    TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
    if (has_vbase)
        ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
    else
        ((void (__cdecl*)(void*, void*))func)(this, src);
}
#endif

/*********************************************************************
 * ?__ExceptionPtrCurrentException@@YAXPAX@Z
 * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
 */
#ifndef __x86_64__
void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
{
    EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;

    TRACE("(%p)\n", ep);

    if (!rec)
    {
        ep->rec = NULL;
        ep->ref = NULL;
        return;
    }

    ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
    ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));

    *ep->rec = *rec;
    *ep->ref = 1;

    if (ep->rec->ExceptionCode == CXX_EXCEPTION)
    {
        const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
        const cxx_type_info *ti;
        void **data, *obj;

        ti = et->type_info_table->info[0];
        data = HeapAlloc(GetProcessHeap(), 0, ti->size);

        obj = (void*)ep->rec->ExceptionInformation[1];
        if (ti->flags & CLASS_IS_SIMPLE_TYPE)
        {
            memcpy(data, obj, ti->size);
            if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
        }
        else if (ti->copy_ctor)
        {
            call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
                    ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
        }
        else
            memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
        ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
    }
    return;
}
#else
void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
{
    EXCEPTION_RECORD *rec = msvcrt_get_thread_data()->exc_record;

    TRACE("(%p)\n", ep);

    if (!rec)
    {
        ep->rec = NULL;
        ep->ref = NULL;
        return;
    }

    ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
    ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));

    *ep->rec = *rec;
    *ep->ref = 1;

    if (ep->rec->ExceptionCode == CXX_EXCEPTION)
    {
        const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
        const cxx_type_info *ti;
        void **data, *obj;
        char *base = RtlPcToFileHeader((void*)et, (void**)&base);

        ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + et->type_info_table))->info[0]);
        data = HeapAlloc(GetProcessHeap(), 0, ti->size);

        obj = (void*)ep->rec->ExceptionInformation[1];
        if (ti->flags & CLASS_IS_SIMPLE_TYPE)
        {
            memcpy(data, obj, ti->size);
            if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
        }
        else if (ti->copy_ctor)
        {
            call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, obj),
                    ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
        }
        else
            memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
        ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
    }
    return;
}
#endif
1933

1934 1935 1936
#endif /* _MSVCR_VER >= 100 */

#if _MSVCR_VER >= 110
1937 1938 1939 1940 1941 1942 1943 1944
/*********************************************************************
 * ?__ExceptionPtrToBool@@YA_NPBX@Z
 * ?__ExceptionPtrToBool@@YA_NPEBX@Z
 */
MSVCRT_bool __cdecl __ExceptionPtrToBool(exception_ptr *ep)
{
    return !!ep->rec;
}
1945 1946 1947
#endif

#if _MSVCR_VER >= 100
1948

1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029
/*********************************************************************
 * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
 * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
 */
#ifndef __x86_64__
void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
        exception *object, const cxx_exception_type *type)
{
    const cxx_type_info *ti;
    void **data;

    __ExceptionPtrDestroy(ep);

    ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
    ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
    *ep->ref = 1;

    memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
    ep->rec->ExceptionCode = CXX_EXCEPTION;
    ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
    ep->rec->NumberParameters = 3;
    ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
    ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;

    ti = type->type_info_table->info[0];
    data = HeapAlloc(GetProcessHeap(), 0, ti->size);
    if (ti->flags & CLASS_IS_SIMPLE_TYPE)
    {
        memcpy(data, object, ti->size);
        if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
    }
    else if (ti->copy_ctor)
    {
        call_copy_ctor(ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
                ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
    }
    else
        memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
    ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
}
#else
void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
        exception *object, const cxx_exception_type *type)
{
    const cxx_type_info *ti;
    void **data;
    char *base;

    RtlPcToFileHeader((void*)type, (void**)&base);
    __ExceptionPtrDestroy(ep);

    ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
    ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
    *ep->ref = 1;

    memset(ep->rec, 0, sizeof(EXCEPTION_RECORD));
    ep->rec->ExceptionCode = CXX_EXCEPTION;
    ep->rec->ExceptionFlags = EH_NONCONTINUABLE;
    ep->rec->NumberParameters = 4;
    ep->rec->ExceptionInformation[0] = CXX_FRAME_MAGIC_VC6;
    ep->rec->ExceptionInformation[2] = (ULONG_PTR)type;
    ep->rec->ExceptionInformation[3] = (ULONG_PTR)base;

    ti = (const cxx_type_info*)(base + ((const cxx_type_info_table*)(base + type->type_info_table))->info[0]);
    data = HeapAlloc(GetProcessHeap(), 0, ti->size);
    if (ti->flags & CLASS_IS_SIMPLE_TYPE)
    {
        memcpy(data, object, ti->size);
        if (ti->size == sizeof(void *)) *data = get_this_pointer(&ti->offsets, *data);
    }
    else if (ti->copy_ctor)
    {
        call_copy_ctor(base + ti->copy_ctor, data, get_this_pointer(&ti->offsets, object),
                ti->flags & CLASS_HAS_VIRTUAL_BASE_CLASS);
    }
    else
        memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
    ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
}
#endif

2030 2031 2032 2033 2034
MSVCRT_bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2)
{
    return ep1->rec == ep2->rec;
}

2035 2036 2037
#endif /* _MSVCR_VER >= 100 */

#if _MSVCR_VER >= 80
2038 2039 2040 2041
void* __cdecl __AdjustPointer(void *obj, const this_ptr_offsets *off)
{
    return get_this_pointer(off, obj);
}
2042
#endif
2043 2044

#if _MSVCR_VER >= 140
2045

2046 2047 2048 2049 2050 2051
typedef struct
{
    char *name;
    char mangled[1];
} type_info140;

2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069
typedef struct
{
    SLIST_ENTRY entry;
    char name[1];
} type_info_entry;

static void* CDECL type_info_entry_malloc(MSVCRT_size_t size)
{
    type_info_entry *ret = MSVCRT_malloc(FIELD_OFFSET(type_info_entry, name) + size);
    return ret->name;
}

static void CDECL type_info_entry_free(void *ptr)
{
    ptr = (char*)ptr - FIELD_OFFSET(type_info_entry, name);
    MSVCRT_free(ptr);
}

2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
/******************************************************************
 *		__std_type_info_compare (UCRTBASE.@)
 */
int CDECL MSVCRT_type_info_compare(const type_info140 *l, const type_info140 *r)
{
    int ret;

    if (l == r) ret = 0;
    else ret = strcmp(l->mangled + 1, r->mangled + 1);
    TRACE("(%p %p) returning %d\n", l, r, ret);
    return ret;
}
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112

/******************************************************************
 *		__std_type_info_name (UCRTBASE.@)
 */
const char* CDECL MSVCRT_type_info_name_list(type_info140 *ti, SLIST_HEADER *header)
{
      if (!ti->name)
      {
          char* name = __unDName(0, ti->mangled + 1, 0,
                  type_info_entry_malloc, type_info_entry_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE);
          if (name)
          {
              unsigned int len = strlen(name);

              while (len && name[--len] == ' ')
                  name[len] = '\0';

              if (InterlockedCompareExchangePointer((void**)&ti->name, name, NULL))
              {
                  type_info_entry_free(name);
              }
              else
              {
                  type_info_entry *entry = (type_info_entry*)(name-FIELD_OFFSET(type_info_entry, name));
                  InterlockedPushEntrySList(header, &entry->entry);
              }
          }
      }
      TRACE("(%p) returning %s\n", ti, ti->name);
      return ti->name;
}
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128

/******************************************************************
 *		__std_type_info_destroy_list  (UCRTBASE.@)
 */
void CDECL MSVCRT_type_info_destroy_list(SLIST_HEADER *header)
{
    SLIST_ENTRY *cur, *next;

    TRACE("(%p)\n", header);

    for(cur = InterlockedFlushSList(header); cur; cur = next)
    {
        next = cur->Next;
        MSVCRT_free(cur);
    }
}
2129 2130 2131 2132 2133 2134

/******************************************************************
 *              __std_type_info_hash (UCRTBASE.@)
 */
MSVCRT_size_t CDECL MSVCRT_type_info_hash(const type_info140 *ti)
{
2135
    MSVCRT_size_t hash, fnv_prime;
2136 2137
    const char *p;

2138 2139 2140 2141 2142 2143 2144 2145
#ifdef _WIN64
    hash = 0xcbf29ce484222325;
    fnv_prime = 0x100000001b3;
#else
    hash = 0x811c9dc5;
    fnv_prime = 0x1000193;
#endif

2146 2147 2148 2149
    TRACE("(%p)->%s\n", ti, ti->mangled);

    for(p = ti->mangled+1; *p; p++) {
        hash ^= *p;
2150
        hash *= fnv_prime;
2151
    }
2152 2153 2154 2155 2156

#ifdef _WIN64
    hash ^= hash >> 32;
#endif

2157 2158
    return hash;
}
2159 2160

#endif /* _MSVCR_VER >= 140 */
2161 2162

#if _MSVCR_VER >= 100
2163

2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181
enum ConcRT_EventType
{
    CONCRT_EVENT_GENERIC,
    CONCRT_EVENT_START,
    CONCRT_EVENT_END,
    CONCRT_EVENT_BLOCK,
    CONCRT_EVENT_UNBLOCK,
    CONCRT_EVENT_YIELD,
    CONCRT_EVENT_ATTACH,
    CONCRT_EVENT_DETACH
};

/* ?_Trace_ppl_function@Concurrency@@YAXABU_GUID@@EW4ConcRT_EventType@1@@Z */
/* ?_Trace_ppl_function@Concurrency@@YAXAEBU_GUID@@EW4ConcRT_EventType@1@@Z */
void __cdecl Concurrency__Trace_ppl_function(const GUID *guid, unsigned char level, enum ConcRT_EventType type)
{
    FIXME("(%s %u %i) stub\n", debugstr_guid(guid), level, type);
}
2182 2183

#endif /* _MSVCR_VER >= 100 */