ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cpp.c
Go to the documentation of this file.
00001 /*
00002  * msvcrt.dll C++ objects
00003  *
00004  * Copyright 2000 Jon Griffiths
00005  * Copyright 2003, 2004 Alexandre Julliard
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <precomp.h>
00023 
00024 #include <wine/exception.h>
00025 #include <internal/wine/msvcrt.h>
00026 #include <internal/wine/cppexcept.h>
00027 
00028 typedef exception bad_cast;
00029 typedef exception bad_typeid;
00030 typedef exception __non_rtti_object;
00031 
00032 typedef struct _rtti_base_descriptor
00033 {
00034   const type_info *type_descriptor;
00035   int num_base_classes;
00036   this_ptr_offsets offsets;    /* offsets for computing the this pointer */
00037   unsigned int attributes;
00038 } rtti_base_descriptor;
00039 
00040 typedef struct _rtti_base_array
00041 {
00042   const rtti_base_descriptor *bases[3]; /* First element is the class itself */
00043 } rtti_base_array;
00044 
00045 typedef struct _rtti_object_hierarchy
00046 {
00047   unsigned int signature;
00048   unsigned int attributes;
00049   int array_len; /* Size of the array pointed to by 'base_classes' */
00050   const rtti_base_array *base_classes;
00051 } rtti_object_hierarchy;
00052 
00053 typedef struct _rtti_object_locator
00054 {
00055   unsigned int signature;
00056   int base_class_offset;
00057   unsigned int flags;
00058   const type_info *type_descriptor;
00059   const rtti_object_hierarchy *type_hierarchy;
00060 } rtti_object_locator;
00061 
00062 #ifdef __i386__  /* thiscall functions are i386-specific */
00063 
00064 #define THISCALL(func) __thiscall_ ## func
00065 #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
00066 
00067 #ifdef _MSC_VER
00068 #include <internal/wine_msc.h>
00069 #else
00070 #define DEFINE_THISCALL_WRAPPER(func,args) \
00071     extern void THISCALL(func)(void); \
00072     __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
00073                       "popl %eax\n\t" \
00074                       "pushl %ecx\n\t" \
00075                       "pushl %eax\n\t" \
00076                       "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
00077 #endif /* _MSC_VER */
00078 
00079 #else /* __i386__ */
00080 
00081 #define THISCALL(func) func
00082 #define THISCALL_NAME(func) __ASM_NAME(#func)
00083 #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
00084 
00085 #endif /* __i386__ */
00086 
00087 extern const vtable_ptr MSVCRT_exception_vtable;
00088 extern const vtable_ptr MSVCRT_bad_typeid_vtable;
00089 extern const vtable_ptr MSVCRT_bad_cast_vtable;
00090 extern const vtable_ptr MSVCRT___non_rtti_object_vtable;
00091 extern const vtable_ptr MSVCRT_type_info_vtable;
00092 
00093 /* get the vtable pointer for a C++ object */
00094 static inline const vtable_ptr *get_vtable( void *obj )
00095 {
00096     return *(const vtable_ptr **)obj;
00097 }
00098 
00099 static inline const rtti_object_locator *get_obj_locator( void *cppobj )
00100 {
00101     const vtable_ptr *vtable = get_vtable( cppobj );
00102     return (const rtti_object_locator *)vtable[-1];
00103 }
00104 
00105 static void dump_obj_locator( const rtti_object_locator *ptr )
00106 {
00107     int i;
00108     const rtti_object_hierarchy *h = ptr->type_hierarchy;
00109 
00110     TRACE( "%p: sig=%08x base_offset=%08x flags=%08x type=%p %s hierarchy=%p\n",
00111            ptr, ptr->signature, ptr->base_class_offset, ptr->flags,
00112            ptr->type_descriptor, dbgstr_type_info(ptr->type_descriptor), ptr->type_hierarchy );
00113     TRACE( "  hierarchy: sig=%08x attr=%08x len=%d base classes=%p\n",
00114            h->signature, h->attributes, h->array_len, h->base_classes );
00115     for (i = 0; i < h->array_len; i++)
00116     {
00117         TRACE( "    base class %p: num %d off %d,%d,%d attr %08x type %p %s\n",
00118                h->base_classes->bases[i],
00119                h->base_classes->bases[i]->num_base_classes,
00120                h->base_classes->bases[i]->offsets.this_offset,
00121                h->base_classes->bases[i]->offsets.vbase_descr,
00122                h->base_classes->bases[i]->offsets.vbase_offset,
00123                h->base_classes->bases[i]->attributes,
00124                h->base_classes->bases[i]->type_descriptor,
00125                dbgstr_type_info(h->base_classes->bases[i]->type_descriptor) );
00126     }
00127 }
00128 
00129 /* Internal common ctor for exception */
00130 static void EXCEPTION_ctor(exception *_this, const char** name)
00131 {
00132   _this->vtable = &MSVCRT_exception_vtable;
00133   if (*name)
00134   {
00135     size_t name_len = strlen(*name) + 1;
00136     _this->name = MSVCRT_malloc(name_len);
00137     memcpy(_this->name, *name, name_len);
00138     _this->do_free = TRUE;
00139   }
00140   else
00141   {
00142     _this->name = NULL;
00143     _this->do_free = FALSE;
00144   }
00145 }
00146 
00147 /******************************************************************
00148  *      ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
00149  */
00150 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor,8)
00151 exception * __stdcall MSVCRT_exception_ctor(exception * _this, const char ** name)
00152 {
00153   TRACE("(%p,%s)\n", _this, *name);
00154   EXCEPTION_ctor(_this, name);
00155   return _this;
00156 }
00157 
00158 /******************************************************************
00159  *      ??0exception@@QAE@ABQBDH@Z (MSVCRT.@)
00160  */
00161 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_ctor_noalloc,12)
00162 exception * __stdcall MSVCRT_exception_ctor_noalloc(exception * _this, char ** name, int noalloc)
00163 {
00164   TRACE("(%p,%s)\n", _this, *name);
00165   _this->vtable = &MSVCRT_exception_vtable;
00166   _this->name = *name;
00167   _this->do_free = FALSE;
00168   return _this;
00169 }
00170 
00171 /******************************************************************
00172  *      ??0exception@@QAE@ABV0@@Z (MSVCRT.@)
00173  */
00174 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_copy_ctor,8)
00175 exception * __stdcall MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
00176 {
00177   TRACE("(%p,%p)\n", _this, rhs);
00178 
00179   if (!rhs->do_free)
00180   {
00181     _this->vtable = &MSVCRT_exception_vtable;
00182     _this->name = rhs->name;
00183     _this->do_free = FALSE;
00184   }
00185   else
00186     EXCEPTION_ctor(_this, (const char**)&rhs->name);
00187   TRACE("name = %s\n", _this->name);
00188   return _this;
00189 }
00190 
00191 /******************************************************************
00192  *      ??0exception@@QAE@XZ (MSVCRT.@)
00193  */
00194 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_default_ctor,4)
00195 exception * __stdcall MSVCRT_exception_default_ctor(exception * _this)
00196 {
00197   static const char* empty = NULL;
00198 
00199   TRACE("(%p)\n", _this);
00200   EXCEPTION_ctor(_this, &empty);
00201   return _this;
00202 }
00203 
00204 /******************************************************************
00205  *      ??1exception@@UAE@XZ (MSVCRT.@)
00206  */
00207 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_dtor,4)
00208 void __stdcall MSVCRT_exception_dtor(exception * _this)
00209 {
00210   TRACE("(%p)\n", _this);
00211   _this->vtable = &MSVCRT_exception_vtable;
00212   if (_this->do_free) MSVCRT_free(_this->name);
00213 }
00214 
00215 /******************************************************************
00216  *      ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
00217  */
00218 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_opequals,8)
00219 exception * __stdcall MSVCRT_exception_opequals(exception * _this, const exception * rhs)
00220 {
00221   TRACE("(%p %p)\n", _this, rhs);
00222   if (_this != rhs)
00223   {
00224       MSVCRT_exception_dtor(_this);
00225       MSVCRT_exception_copy_ctor(_this, rhs);
00226   }
00227   TRACE("name = %s\n", _this->name);
00228   return _this;
00229 }
00230 
00231 /******************************************************************
00232  *      ??_Eexception@@UAEPAXI@Z (MSVCRT.@)
00233  */
00234 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_vector_dtor,8)
00235 void * __stdcall MSVCRT_exception_vector_dtor(exception * _this, unsigned int flags)
00236 {
00237     TRACE("(%p %x)\n", _this, flags);
00238     if (flags & 2)
00239     {
00240         /* we have an array, with the number of elements stored before the first object */
00241         int i, *ptr = (int *)_this - 1;
00242 
00243         for (i = *ptr - 1; i >= 0; i--) MSVCRT_exception_dtor(_this + i);
00244         MSVCRT_operator_delete(ptr);
00245     }
00246     else
00247     {
00248         MSVCRT_exception_dtor(_this);
00249         if (flags & 1) MSVCRT_operator_delete(_this);
00250     }
00251     return _this;
00252 }
00253 
00254 /******************************************************************
00255  *      ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
00256  */
00257 DEFINE_THISCALL_WRAPPER(MSVCRT_exception_scalar_dtor,8)
00258 void * __stdcall MSVCRT_exception_scalar_dtor(exception * _this, unsigned int flags)
00259 {
00260     TRACE("(%p %x)\n", _this, flags);
00261     MSVCRT_exception_dtor(_this);
00262     if (flags & 1) MSVCRT_operator_delete(_this);
00263     return _this;
00264 }
00265 
00266 /******************************************************************
00267  *      ?what@exception@@UBEPBDXZ (MSVCRT.@)
00268  */
00269 DEFINE_THISCALL_WRAPPER(MSVCRT_what_exception,4)
00270 const char * __stdcall MSVCRT_what_exception(exception * _this)
00271 {
00272   TRACE("(%p) returning %s\n", _this, _this->name);
00273   return _this->name ? _this->name : "Unknown exception";
00274 }
00275 
00276 /******************************************************************
00277  *      ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
00278  */
00279 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_copy_ctor,8)
00280 bad_typeid * __stdcall MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
00281 {
00282   TRACE("(%p %p)\n", _this, rhs);
00283   MSVCRT_exception_copy_ctor(_this, rhs);
00284   _this->vtable = &MSVCRT_bad_typeid_vtable;
00285   return _this;
00286 }
00287 
00288 /******************************************************************
00289  *      ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
00290  */
00291 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_ctor,8)
00292 bad_typeid * __stdcall MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
00293 {
00294   TRACE("(%p %s)\n", _this, name);
00295   EXCEPTION_ctor(_this, &name);
00296   _this->vtable = &MSVCRT_bad_typeid_vtable;
00297   return _this;
00298 }
00299 
00300 /******************************************************************
00301  *      ??_Fbad_typeid@@QAEXXZ (MSVCRT.@)
00302  */
00303 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_default_ctor,4)
00304 bad_typeid * __stdcall MSVCRT_bad_typeid_default_ctor(bad_typeid * _this)
00305 {
00306   return MSVCRT_bad_typeid_ctor( _this, "bad typeid" );
00307 }
00308 
00309 /******************************************************************
00310  *      ??1bad_typeid@@UAE@XZ (MSVCRT.@)
00311  */
00312 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_dtor,4)
00313 void __stdcall MSVCRT_bad_typeid_dtor(bad_typeid * _this)
00314 {
00315   TRACE("(%p)\n", _this);
00316   MSVCRT_exception_dtor(_this);
00317 }
00318 
00319 /******************************************************************
00320  *      ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
00321  */
00322 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_opequals,8)
00323 bad_typeid * __stdcall MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
00324 {
00325   TRACE("(%p %p)\n", _this, rhs);
00326   MSVCRT_exception_opequals(_this, rhs);
00327   return _this;
00328 }
00329 
00330 /******************************************************************
00331  *              ??_Ebad_typeid@@UAEPAXI@Z (MSVCRT.@)
00332  */
00333 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_vector_dtor,8)
00334 void * __stdcall MSVCRT_bad_typeid_vector_dtor(bad_typeid * _this, unsigned int flags)
00335 {
00336     TRACE("(%p %x)\n", _this, flags);
00337     if (flags & 2)
00338     {
00339         /* we have an array, with the number of elements stored before the first object */
00340         int i, *ptr = (int *)_this - 1;
00341 
00342         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_typeid_dtor(_this + i);
00343         MSVCRT_operator_delete(ptr);
00344     }
00345     else
00346     {
00347         MSVCRT_bad_typeid_dtor(_this);
00348         if (flags & 1) MSVCRT_operator_delete(_this);
00349     }
00350     return _this;
00351 }
00352 
00353 /******************************************************************
00354  *      ??_Gbad_typeid@@UAEPAXI@Z (MSVCRT.@)
00355  */
00356 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_typeid_scalar_dtor,8)
00357 void * __stdcall MSVCRT_bad_typeid_scalar_dtor(bad_typeid * _this, unsigned int flags)
00358 {
00359     TRACE("(%p %x)\n", _this, flags);
00360     MSVCRT_bad_typeid_dtor(_this);
00361     if (flags & 1) MSVCRT_operator_delete(_this);
00362     return _this;
00363 }
00364 
00365 /******************************************************************
00366  *      ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
00367  */
00368 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_copy_ctor,8)
00369 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
00370                                                                  const __non_rtti_object * rhs)
00371 {
00372   TRACE("(%p %p)\n", _this, rhs);
00373   MSVCRT_bad_typeid_copy_ctor(_this, rhs);
00374   _this->vtable = &MSVCRT___non_rtti_object_vtable;
00375   return _this;
00376 }
00377 
00378 /******************************************************************
00379  *      ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
00380  */
00381 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_ctor,8)
00382 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
00383                                                             const char * name)
00384 {
00385   TRACE("(%p %s)\n", _this, name);
00386   EXCEPTION_ctor(_this, &name);
00387   _this->vtable = &MSVCRT___non_rtti_object_vtable;
00388   return _this;
00389 }
00390 
00391 /******************************************************************
00392  *      ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
00393  */
00394 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_dtor,4)
00395 void __stdcall MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
00396 {
00397   TRACE("(%p)\n", _this);
00398   MSVCRT_bad_typeid_dtor(_this);
00399 }
00400 
00401 /******************************************************************
00402  *      ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
00403  */
00404 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_opequals,8)
00405 __non_rtti_object * __stdcall MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
00406                                                                 const __non_rtti_object *rhs)
00407 {
00408   TRACE("(%p %p)\n", _this, rhs);
00409   MSVCRT_bad_typeid_opequals(_this, rhs);
00410   return _this;
00411 }
00412 
00413 /******************************************************************
00414  *      ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
00415  */
00416 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_vector_dtor,8)
00417 void * __stdcall MSVCRT___non_rtti_object_vector_dtor(__non_rtti_object * _this, unsigned int flags)
00418 {
00419     TRACE("(%p %x)\n", _this, flags);
00420     if (flags & 2)
00421     {
00422         /* we have an array, with the number of elements stored before the first object */
00423         int i, *ptr = (int *)_this - 1;
00424 
00425         for (i = *ptr - 1; i >= 0; i--) MSVCRT___non_rtti_object_dtor(_this + i);
00426         MSVCRT_operator_delete(ptr);
00427     }
00428     else
00429     {
00430         MSVCRT___non_rtti_object_dtor(_this);
00431         if (flags & 1) MSVCRT_operator_delete(_this);
00432     }
00433     return _this;
00434 }
00435 
00436 /******************************************************************
00437  *      ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
00438  */
00439 DEFINE_THISCALL_WRAPPER(MSVCRT___non_rtti_object_scalar_dtor,8)
00440 void * __stdcall MSVCRT___non_rtti_object_scalar_dtor(__non_rtti_object * _this, unsigned int flags)
00441 {
00442   TRACE("(%p %x)\n", _this, flags);
00443   MSVCRT___non_rtti_object_dtor(_this);
00444   if (flags & 1) MSVCRT_operator_delete(_this);
00445   return _this;
00446 }
00447 
00448 /******************************************************************
00449  *      ??0bad_cast@@AAE@PBQBD@Z (MSVCRT.@)
00450  *      ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
00451  */
00452 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor,8)
00453 bad_cast * __stdcall MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
00454 {
00455   TRACE("(%p %s)\n", _this, *name);
00456   EXCEPTION_ctor(_this, name);
00457   _this->vtable = &MSVCRT_bad_cast_vtable;
00458   return _this;
00459 }
00460 
00461 /******************************************************************
00462  *      ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
00463  */
00464 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_copy_ctor,8)
00465 bad_cast * __stdcall MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
00466 {
00467   TRACE("(%p %p)\n", _this, rhs);
00468   MSVCRT_exception_copy_ctor(_this, rhs);
00469   _this->vtable = &MSVCRT_bad_cast_vtable;
00470   return _this;
00471 }
00472 
00473 /******************************************************************
00474  *      ??0bad_cast@@QAE@PBD@Z (MSVCRT.@)
00475  */
00476 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_ctor_charptr,8)
00477 bad_cast * __stdcall MSVCRT_bad_cast_ctor_charptr(bad_cast * _this, const char * name)
00478 {
00479   TRACE("(%p %s)\n", _this, name);
00480   EXCEPTION_ctor(_this, &name);
00481   _this->vtable = &MSVCRT_bad_cast_vtable;
00482   return _this;
00483 }
00484 
00485 /******************************************************************
00486  *      ??_Fbad_cast@@QAEXXZ (MSVCRT.@)
00487  */
00488 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_default_ctor,4)
00489 bad_cast * __stdcall MSVCRT_bad_cast_default_ctor(bad_cast * _this)
00490 {
00491   return MSVCRT_bad_cast_ctor_charptr( _this, "bad cast" );
00492 }
00493 
00494 /******************************************************************
00495  *      ??1bad_cast@@UAE@XZ (MSVCRT.@)
00496  */
00497 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_dtor,4)
00498 void __stdcall MSVCRT_bad_cast_dtor(bad_cast * _this)
00499 {
00500   TRACE("(%p)\n", _this);
00501   MSVCRT_exception_dtor(_this);
00502 }
00503 
00504 /******************************************************************
00505  *      ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
00506  */
00507 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_opequals,8)
00508 bad_cast * __stdcall MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
00509 {
00510   TRACE("(%p %p)\n", _this, rhs);
00511   MSVCRT_exception_opequals(_this, rhs);
00512   return _this;
00513 }
00514 
00515 /******************************************************************
00516  *              ??_Ebad_cast@@UAEPAXI@Z (MSVCRT.@)
00517  */
00518 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_vector_dtor,8)
00519 void * __stdcall MSVCRT_bad_cast_vector_dtor(bad_cast * _this, unsigned int flags)
00520 {
00521     TRACE("(%p %x)\n", _this, flags);
00522     if (flags & 2)
00523     {
00524         /* we have an array, with the number of elements stored before the first object */
00525         int i, *ptr = (int *)_this - 1;
00526 
00527         for (i = *ptr - 1; i >= 0; i--) MSVCRT_bad_cast_dtor(_this + i);
00528         MSVCRT_operator_delete(ptr);
00529     }
00530     else
00531     {
00532         MSVCRT_bad_cast_dtor(_this);
00533         if (flags & 1) MSVCRT_operator_delete(_this);
00534     }
00535     return _this;
00536 }
00537 
00538 /******************************************************************
00539  *      ??_Gbad_cast@@UAEPAXI@Z (MSVCRT.@)
00540  */
00541 DEFINE_THISCALL_WRAPPER(MSVCRT_bad_cast_scalar_dtor,8)
00542 void * __stdcall MSVCRT_bad_cast_scalar_dtor(bad_cast * _this, unsigned int flags)
00543 {
00544   TRACE("(%p %x)\n", _this, flags);
00545   MSVCRT_bad_cast_dtor(_this);
00546   if (flags & 1) MSVCRT_operator_delete(_this);
00547   return _this;
00548 }
00549 
00550 /******************************************************************
00551  *      ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
00552  */
00553 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
00554 int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
00555 {
00556     int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
00557     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
00558     return ret;
00559 }
00560 
00561 /******************************************************************
00562  *      ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
00563  */
00564 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opnot_equals,8)
00565 int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
00566 {
00567     int ret = !!strcmp(_this->mangled + 1, rhs->mangled + 1);
00568     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
00569     return ret;
00570 }
00571 
00572 /******************************************************************
00573  *      ?before@type_info@@QBEHABV1@@Z (MSVCRT.@)
00574  */
00575 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_before,8)
00576 int __stdcall MSVCRT_type_info_before(type_info * _this, const type_info * rhs)
00577 {
00578     int ret = strcmp(_this->mangled + 1, rhs->mangled + 1) < 0;
00579     TRACE("(%p %p) returning %d\n", _this, rhs, ret);
00580     return ret;
00581 }
00582 
00583 /******************************************************************
00584  *      ??1type_info@@UAE@XZ (MSVCRT.@)
00585  */
00586 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_dtor,4)
00587 void __stdcall MSVCRT_type_info_dtor(type_info * _this)
00588 {
00589   TRACE("(%p)\n", _this);
00590   MSVCRT_free(_this->name);
00591 }
00592 
00593 /******************************************************************
00594  *      ?name@type_info@@QBEPBDXZ (MSVCRT.@)
00595  */
00596 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name,4)
00597 const char * __stdcall MSVCRT_type_info_name(type_info * _this)
00598 {
00599   if (!_this->name)
00600   {
00601     /* Create and set the demangled name */
00602     /* Note: mangled name in type_info struct always starts with a '.', while
00603      * it isn't valid for mangled name.
00604      * Is this '.' really part of the mangled name, or has it some other meaning ?
00605      */
00606     char* name = __unDName(0, _this->mangled + 1, 0,
00607                            MSVCRT_malloc, MSVCRT_free, 0x2800);
00608     if (name)
00609     {
00610       size_t len = strlen(name);
00611 
00612       /* It seems _unDName may leave blanks at the end of the demangled name */
00613       while (len && name[--len] == ' ')
00614         name[len] = '\0';
00615 
00616       if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
00617       {
00618         /* Another thread set this member since we checked above - use it */
00619         MSVCRT_free(name);
00620       }
00621     }
00622   }
00623   TRACE("(%p) returning %s\n", _this, _this->name);
00624   return _this->name;
00625 }
00626 
00627 /******************************************************************
00628  *      ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
00629  */
00630 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_raw_name,4)
00631 const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this)
00632 {
00633   TRACE("(%p) returning %s\n", _this, _this->mangled);
00634   return _this->mangled;
00635 }
00636 
00637 /* Unexported */
00638 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_vector_dtor,8)
00639 void * __stdcall MSVCRT_type_info_vector_dtor(type_info * _this, unsigned int flags)
00640 {
00641     TRACE("(%p %x)\n", _this, flags);
00642     if (flags & 2)
00643     {
00644         /* we have an array, with the number of elements stored before the first object */
00645         int i, *ptr = (int *)_this - 1;
00646 
00647         for (i = *ptr - 1; i >= 0; i--) MSVCRT_type_info_dtor(_this + i);
00648         MSVCRT_operator_delete(ptr);
00649     }
00650     else
00651     {
00652         MSVCRT_type_info_dtor(_this);
00653         if (flags & 1) MSVCRT_operator_delete(_this);
00654     }
00655     return _this;
00656 }
00657 
00658 /* vtables */
00659 
00660 #ifdef __GNUC__
00661 #ifdef _WIN64
00662 
00663 #define __ASM_VTABLE(name,funcs) \
00664     __asm__(".data\n" \
00665             "\t.align 8\n" \
00666             "\t.quad " __ASM_NAME(#name "_rtti") "\n" \
00667             "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
00668             __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \
00669             "\t.quad " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \
00670             funcs "\n\t.text");
00671 
00672 #define __ASM_EXCEPTION_VTABLE(name) \
00673     __ASM_VTABLE(name, "\t.quad " THISCALL_NAME(MSVCRT_what_exception) )
00674 
00675 #else
00676 
00677 #define __ASM_VTABLE(name,funcs) \
00678     __asm__(".data\n" \
00679             "\t.align 4\n" \
00680             "\t.long " __ASM_NAME(#name "_rtti") "\n" \
00681             "\t.globl " __ASM_NAME("MSVCRT_" #name "_vtable") "\n" \
00682             __ASM_NAME("MSVCRT_" #name "_vtable") ":\n" \
00683             "\t.long " THISCALL_NAME(MSVCRT_ ## name ## _vector_dtor) "\n" \
00684             funcs "\n\t.text");
00685 
00686 #define __ASM_EXCEPTION_VTABLE(name) \
00687     __ASM_VTABLE(name, "\t.long " THISCALL_NAME(MSVCRT_what_exception) )
00688 
00689 #endif /* _WIN64 */
00690 
00691 #ifndef __GNUC__
00692 void __asm_dummy_vtables(void) {
00693 #endif
00694 
00695 __ASM_VTABLE(type_info,"")
00696 __ASM_EXCEPTION_VTABLE(exception)
00697 __ASM_EXCEPTION_VTABLE(bad_typeid)
00698 __ASM_EXCEPTION_VTABLE(bad_cast)
00699 __ASM_EXCEPTION_VTABLE(__non_rtti_object)
00700 
00701 #ifndef __GNUC__
00702 }
00703 #endif
00704 #endif
00705 
00706 /* Static RTTI for exported objects */
00707 
00708 static const type_info exception_type_info =
00709 {
00710   &MSVCRT_type_info_vtable,
00711   NULL,
00712   ".?AVexception@@"
00713 };
00714 
00715 static const rtti_base_descriptor exception_rtti_base_descriptor =
00716 {
00717   &exception_type_info,
00718   0,
00719   { 0, -1, 0 },
00720   0
00721 };
00722 
00723 static const rtti_base_array exception_rtti_base_array =
00724 {
00725   {
00726     &exception_rtti_base_descriptor,
00727     NULL,
00728     NULL
00729   }
00730 };
00731 
00732 static const rtti_object_hierarchy exception_type_hierarchy =
00733 {
00734   0,
00735   0,
00736   1,
00737   &exception_rtti_base_array
00738 };
00739 
00740 const rtti_object_locator exception_rtti =
00741 {
00742   0,
00743   0,
00744   0,
00745   &exception_type_info,
00746   &exception_type_hierarchy
00747 };
00748 
00749 static const cxx_type_info exception_cxx_type_info =
00750 {
00751   0,
00752   &exception_type_info,
00753   { 0, -1, 0 },
00754   sizeof(exception),
00755   (cxx_copy_ctor)THISCALL(MSVCRT_exception_copy_ctor)
00756 };
00757 
00758 static const type_info bad_typeid_type_info =
00759 {
00760   &MSVCRT_type_info_vtable,
00761   NULL,
00762   ".?AVbad_typeid@@"
00763 };
00764 
00765 static const rtti_base_descriptor bad_typeid_rtti_base_descriptor =
00766 {
00767   &bad_typeid_type_info,
00768   1,
00769   { 0, -1, 0 },
00770   0
00771 };
00772 
00773 static const rtti_base_array bad_typeid_rtti_base_array =
00774 {
00775   {
00776     &bad_typeid_rtti_base_descriptor,
00777     &exception_rtti_base_descriptor,
00778     NULL
00779   }
00780 };
00781 
00782 static const rtti_object_hierarchy bad_typeid_type_hierarchy =
00783 {
00784   0,
00785   0,
00786   2,
00787   &bad_typeid_rtti_base_array
00788 };
00789 
00790 const rtti_object_locator bad_typeid_rtti =
00791 {
00792   0,
00793   0,
00794   0,
00795   &bad_typeid_type_info,
00796   &bad_typeid_type_hierarchy
00797 };
00798 
00799 static const cxx_type_info bad_typeid_cxx_type_info =
00800 {
00801   0,
00802   &bad_typeid_type_info,
00803   { 0, -1, 0 },
00804   sizeof(exception),
00805   (cxx_copy_ctor)THISCALL(MSVCRT_bad_typeid_copy_ctor)
00806 };
00807 
00808 static const type_info bad_cast_type_info =
00809 {
00810   &MSVCRT_type_info_vtable,
00811   NULL,
00812   ".?AVbad_cast@@"
00813 };
00814 
00815 static const rtti_base_descriptor bad_cast_rtti_base_descriptor =
00816 {
00817   &bad_cast_type_info,
00818   1,
00819   { 0, -1, 0 },
00820   0
00821 };
00822 
00823 static const rtti_base_array bad_cast_rtti_base_array =
00824 {
00825   {
00826     &bad_cast_rtti_base_descriptor,
00827     &exception_rtti_base_descriptor,
00828     NULL
00829   }
00830 };
00831 
00832 static const rtti_object_hierarchy bad_cast_type_hierarchy =
00833 {
00834   0,
00835   0,
00836   2,
00837   &bad_cast_rtti_base_array
00838 };
00839 
00840 const rtti_object_locator bad_cast_rtti =
00841 {
00842   0,
00843   0,
00844   0,
00845   &bad_cast_type_info,
00846   &bad_cast_type_hierarchy
00847 };
00848 
00849 static const cxx_type_info bad_cast_cxx_type_info =
00850 {
00851   0,
00852   &bad_cast_type_info,
00853   { 0, -1, 0 },
00854   sizeof(exception),
00855   (cxx_copy_ctor)THISCALL(MSVCRT_bad_cast_copy_ctor)
00856 };
00857 
00858 static const type_info __non_rtti_object_type_info =
00859 {
00860   &MSVCRT_type_info_vtable,
00861   NULL,
00862   ".?AV__non_rtti_object@@"
00863 };
00864 
00865 static const rtti_base_descriptor __non_rtti_object_rtti_base_descriptor =
00866 {
00867   &__non_rtti_object_type_info,
00868   2,
00869   { 0, -1, 0 },
00870   0
00871 };
00872 
00873 static const rtti_base_array __non_rtti_object_rtti_base_array =
00874 {
00875   {
00876     &__non_rtti_object_rtti_base_descriptor,
00877     &bad_typeid_rtti_base_descriptor,
00878     &exception_rtti_base_descriptor
00879   }
00880 };
00881 
00882 static const rtti_object_hierarchy __non_rtti_object_type_hierarchy =
00883 {
00884   0,
00885   0,
00886   3,
00887   &__non_rtti_object_rtti_base_array
00888 };
00889 
00890 const rtti_object_locator __non_rtti_object_rtti =
00891 {
00892   0,
00893   0,
00894   0,
00895   &__non_rtti_object_type_info,
00896   &__non_rtti_object_type_hierarchy
00897 };
00898 
00899 static const cxx_type_info __non_rtti_object_cxx_type_info =
00900 {
00901   0,
00902   &__non_rtti_object_type_info,
00903   { 0, -1, 0 },
00904   sizeof(exception),
00905   (cxx_copy_ctor)THISCALL(MSVCRT___non_rtti_object_copy_ctor)
00906 };
00907 
00908 static const type_info type_info_type_info =
00909 {
00910   &MSVCRT_type_info_vtable,
00911   NULL,
00912   ".?AVtype_info@@"
00913 };
00914 
00915 static const rtti_base_descriptor type_info_rtti_base_descriptor =
00916 {
00917   &type_info_type_info,
00918   0,
00919   { 0, -1, 0 },
00920   0
00921 };
00922 
00923 static const rtti_base_array type_info_rtti_base_array =
00924 {
00925   {
00926     &type_info_rtti_base_descriptor,
00927     NULL,
00928     NULL
00929   }
00930 };
00931 
00932 static const rtti_object_hierarchy type_info_type_hierarchy =
00933 {
00934   0,
00935   0,
00936   1,
00937   &type_info_rtti_base_array
00938 };
00939 
00940 const rtti_object_locator type_info_rtti =
00941 {
00942   0,
00943   0,
00944   0,
00945   &type_info_type_info,
00946   &type_info_type_hierarchy
00947 };
00948 
00949 /*
00950  * Exception RTTI for cpp objects
00951  */
00952 static const cxx_type_info_table bad_cast_type_info_table =
00953 {
00954   3,
00955   {
00956    &__non_rtti_object_cxx_type_info,
00957    &bad_typeid_cxx_type_info,
00958    &exception_cxx_type_info
00959   }
00960 };
00961 
00962 static const cxx_exception_type bad_cast_exception_type =
00963 {
00964   0,
00965   (void*)THISCALL(MSVCRT_bad_cast_dtor),
00966   NULL,
00967   &bad_cast_type_info_table
00968 };
00969 
00970 static const cxx_type_info_table bad_typeid_type_info_table =
00971 {
00972   2,
00973   {
00974    &bad_cast_cxx_type_info,
00975    &exception_cxx_type_info,
00976    NULL
00977   }
00978 };
00979 
00980 static const cxx_exception_type bad_typeid_exception_type =
00981 {
00982   0,
00983   (void*)THISCALL(MSVCRT_bad_typeid_dtor),
00984   NULL,
00985   &bad_cast_type_info_table
00986 };
00987 
00988 static const cxx_exception_type __non_rtti_object_exception_type =
00989 {
00990   0,
00991   (void*)THISCALL(MSVCRT___non_rtti_object_dtor),
00992   NULL,
00993   &bad_typeid_type_info_table
00994 };
00995 
00996 
00997 /******************************************************************
00998  *      ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
00999  *
01000  * Install a handler to be called when terminate() is called.
01001  *
01002  * PARAMS
01003  *  func [I] Handler function to install
01004  *
01005  * RETURNS
01006  *  The previously installed handler function, if any.
01007  */
01008 terminate_function CDECL MSVCRT_set_terminate(terminate_function func)
01009 {
01010     thread_data_t *data = msvcrt_get_thread_data();
01011     terminate_function previous = data->terminate_handler;
01012     TRACE("(%p) returning %p\n",func,previous);
01013     data->terminate_handler = func;
01014     return previous;
01015 }
01016 
01017 /******************************************************************
01018  *              _get_terminate (MSVCRT.@)
01019  */
01020 terminate_function CDECL _get_terminate(void)
01021 {
01022     thread_data_t *data = msvcrt_get_thread_data();
01023     return data->terminate_handler;
01024 }
01025 
01026 /******************************************************************
01027  *      ?set_unexpected@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
01028  *
01029  * Install a handler to be called when unexpected() is called.
01030  *
01031  * PARAMS
01032  *  func [I] Handler function to install
01033  *
01034  * RETURNS
01035  *  The previously installed handler function, if any.
01036  */
01037 unexpected_function CDECL MSVCRT_set_unexpected(unexpected_function func)
01038 {
01039     thread_data_t *data = msvcrt_get_thread_data();
01040     unexpected_function previous = data->unexpected_handler;
01041     TRACE("(%p) returning %p\n",func,previous);
01042     data->unexpected_handler = func;
01043     return previous;
01044 }
01045 
01046 /******************************************************************
01047  *              _get_unexpected (MSVCRT.@)
01048  */
01049 unexpected_function CDECL _get_unexpected(void)
01050 {
01051     thread_data_t *data = msvcrt_get_thread_data();
01052     return data->unexpected_handler;
01053 }
01054 
01055 /******************************************************************
01056  *              ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z  (MSVCRT.@)
01057  */
01058 _se_translator_function CDECL MSVCRT__set_se_translator(_se_translator_function func)
01059 {
01060     thread_data_t *data = msvcrt_get_thread_data();
01061     _se_translator_function previous = data->se_translator;
01062     TRACE("(%p) returning %p\n",func,previous);
01063     data->se_translator = func;
01064     return previous;
01065 }
01066 
01067 /******************************************************************
01068  *      ?terminate@@YAXXZ (MSVCRT.@)
01069  *
01070  * Default handler for an unhandled exception.
01071  *
01072  * PARAMS
01073  *  None.
01074  *
01075  * RETURNS
01076  *  This function does not return. Either control resumes from any
01077  *  handler installed by calling set_terminate(), or (by default) abort()
01078  *  is called.
01079  */
01080 void CDECL MSVCRT_terminate(void)
01081 {
01082     thread_data_t *data = msvcrt_get_thread_data();
01083     if (data->terminate_handler) data->terminate_handler();
01084     abort();
01085 }
01086 
01087 /******************************************************************
01088  *      ?unexpected@@YAXXZ (MSVCRT.@)
01089  */
01090 void CDECL MSVCRT_unexpected(void)
01091 {
01092     thread_data_t *data = msvcrt_get_thread_data();
01093     if (data->unexpected_handler) data->unexpected_handler();
01094     MSVCRT_terminate();
01095 }
01096 
01097 
01098 /******************************************************************
01099  *      __RTtypeid (MSVCRT.@)
01100  *
01101  * Retrieve the Run Time Type Information (RTTI) for a C++ object.
01102  *
01103  * PARAMS
01104  *  cppobj [I] C++ object to get type information for.
01105  *
01106  * RETURNS
01107  *  Success: A type_info object describing cppobj.
01108  *  Failure: If the object to be cast has no RTTI, a __non_rtti_object
01109  *           exception is thrown. If cppobj is NULL, a bad_typeid exception
01110  *           is thrown. In either case, this function does not return.
01111  *
01112  * NOTES
01113  *  This function is usually called by compiler generated code as a result
01114  *  of using one of the C++ dynamic cast statements.
01115  */
01116 const type_info* CDECL MSVCRT___RTtypeid(void *cppobj)
01117 {
01118     const type_info *ret;
01119 
01120     if (!cppobj)
01121     {
01122         bad_typeid e;
01123         MSVCRT_bad_typeid_ctor( &e, "Attempted a typeid of NULL pointer!" );
01124         _CxxThrowException( &e, &bad_typeid_exception_type );
01125         return NULL;
01126     }
01127 
01128     __TRY
01129     {
01130         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
01131         ret = obj_locator->type_descriptor;
01132     }
01133     __EXCEPT_PAGE_FAULT
01134     {
01135         __non_rtti_object e;
01136         MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" );
01137         _CxxThrowException( &e, &bad_typeid_exception_type );
01138         return NULL;
01139     }
01140     __ENDTRY
01141     return ret;
01142 }
01143 
01144 /******************************************************************
01145  *      __RTDynamicCast (MSVCRT.@)
01146  *
01147  * Dynamically cast a C++ object to one of its base classes.
01148  *
01149  * PARAMS
01150  *  cppobj   [I] Any C++ object to cast
01151  *  unknown  [I] Reserved, set to 0
01152  *  src      [I] type_info object describing cppobj
01153  *  dst      [I] type_info object describing the base class to cast to
01154  *  do_throw [I] TRUE = throw an exception if the cast fails, FALSE = don't
01155  *
01156  * RETURNS
01157  *  Success: The address of cppobj, cast to the object described by dst.
01158  *  Failure: NULL, If the object to be cast has no RTTI, or dst is not a
01159  *           valid cast for cppobj. If do_throw is TRUE, a bad_cast exception
01160  *           is thrown and this function does not return.
01161  *
01162  * NOTES
01163  *  This function is usually called by compiler generated code as a result
01164  *  of using one of the C++ dynamic cast statements.
01165  */
01166 void* CDECL MSVCRT___RTDynamicCast(void *cppobj, int unknown,
01167                                    type_info *src, type_info *dst,
01168                                    int do_throw)
01169 {
01170     void *ret;
01171 
01172     if (!cppobj) return NULL;
01173 
01174     TRACE("obj: %p unknown: %d src: %p %s dst: %p %s do_throw: %d)\n",
01175           cppobj, unknown, src, dbgstr_type_info(src), dst, dbgstr_type_info(dst), do_throw);
01176 
01177     /* To cast an object at runtime:
01178      * 1.Find out the true type of the object from the typeinfo at vtable[-1]
01179      * 2.Search for the destination type in the class hierarchy
01180      * 3.If destination type is found, return base object address + dest offset
01181      *   Otherwise, fail the cast
01182      *
01183      * FIXME: the unknown parameter doesn't seem to be used for anything
01184      */
01185     __TRY
01186     {
01187         int i;
01188         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
01189         const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy;
01190         const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases;
01191 
01192         if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator);
01193 
01194         ret = NULL;
01195         for (i = 0; i < obj_bases->array_len; i++)
01196         {
01197             const type_info *typ = base_desc[i]->type_descriptor;
01198 
01199             if (!strcmp(typ->mangled, dst->mangled))
01200             {
01201                 /* compute the correct this pointer for that base class */
01202                 void *this_ptr = (char *)cppobj - obj_locator->base_class_offset;
01203                 ret = get_this_pointer( &base_desc[i]->offsets, this_ptr );
01204                 break;
01205             }
01206         }
01207         /* VC++ sets do_throw to 1 when the result of a dynamic_cast is assigned
01208          * to a reference, since references cannot be NULL.
01209          */
01210         if (!ret && do_throw)
01211         {
01212             const char *msg = "Bad dynamic_cast!";
01213             bad_cast e;
01214             MSVCRT_bad_cast_ctor( &e, &msg );
01215             _CxxThrowException( &e, &bad_cast_exception_type );
01216         }
01217     }
01218     __EXCEPT_PAGE_FAULT
01219     {
01220         __non_rtti_object e;
01221         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
01222         _CxxThrowException( &e, &bad_typeid_exception_type );
01223         return NULL;
01224     }
01225     __ENDTRY
01226     return ret;
01227 }
01228 
01229 
01230 /******************************************************************
01231  *      __RTCastToVoid (MSVCRT.@)
01232  *
01233  * Dynamically cast a C++ object to a void*.
01234  *
01235  * PARAMS
01236  *  cppobj [I] The C++ object to cast
01237  *
01238  * RETURNS
01239  *  Success: The base address of the object as a void*.
01240  *  Failure: NULL, if cppobj is NULL or has no RTTI.
01241  *
01242  * NOTES
01243  *  This function is usually called by compiler generated code as a result
01244  *  of using one of the C++ dynamic cast statements.
01245  */
01246 void* CDECL MSVCRT___RTCastToVoid(void *cppobj)
01247 {
01248     void *ret;
01249 
01250     if (!cppobj) return NULL;
01251 
01252     __TRY
01253     {
01254         const rtti_object_locator *obj_locator = get_obj_locator( cppobj );
01255         ret = (char *)cppobj - obj_locator->base_class_offset;
01256     }
01257     __EXCEPT_PAGE_FAULT
01258     {
01259         __non_rtti_object e;
01260         MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" );
01261         _CxxThrowException( &e, &bad_typeid_exception_type );
01262         return NULL;
01263     }
01264     __ENDTRY
01265     return ret;
01266 }

Generated on Sun May 27 2012 04:36:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.