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 ); const rtti_object_hierarchy *obj_bases; const rtti_base_array *base_array; char *base; if (TRACE_ON(msvcrt)) dump_obj_locator(obj_locator); if(obj_locator->signature == 0) base = RtlPcToFileHeader((void*)obj_locator, (void**)&base); else base = (char*)obj_locator - obj_locator->object_locator; obj_bases = (const rtti_object_hierarchy*)(base + obj_locator->type_hierarchy); base_array = (const rtti_base_array*)(base + obj_bases->base_classes); ret = NULL; for (i = 0; i < obj_bases->array_len; i++) { 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); if (!strcmp(typ->mangled, dst->mangled)) { void *this_ptr = (char *)cppobj - obj_locator->base_class_offset; ret = get_this_pointer( &base_desc->offsets, this_ptr ); break; } } 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!" ); _CxxThrowException( &e, &bad_typeid_exception_type ); return NULL; } __ENDTRY return ret; }
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 { const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); char *base; if(obj_locator->signature == 0) base = RtlPcToFileHeader((void*)obj_locator, (void**)&base); else base = (char*)obj_locator - obj_locator->object_locator; ret = (type_info*)(base + obj_locator->type_descriptor); } __EXCEPT_PAGE_FAULT { __non_rtti_object e; MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" ); _CxxThrowException( &e, &bad_typeid_exception_type ); return NULL; } __ENDTRY return ret; }
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 { const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); ret = obj_locator->type_descriptor; } __EXCEPT_PAGE_FAULT { __non_rtti_object e; MSVCRT___non_rtti_object_ctor( &e, "Bad read pointer - no RTTI data!" ); _CxxThrowException( &e, &bad_typeid_exception_type ); return NULL; } __ENDTRY return ret; }
extern "C" __declspec(dllexport) void objc_exception_throw(void *exception) { int typeCount = 0; // Get count of all types in exception Class curType = object_getClass((id) exception); while (curType != nil) { typeCount++; curType = class_getSuperclass(curType); } typeCount++; // For id __ObjC_CatchableTypeArray *exceptTypes = (__ObjC_CatchableTypeArray *)_alloca(sizeof(__ObjC_CatchableTypeArray) + sizeof(__ObjC_CatchableType *) * typeCount); // Add exception type and all base types to throw information typeCount = 0; curType = object_getClass((id)exception); while (curType != nil) { exceptTypes->types[typeCount] = (__ObjC_CatchableType *)_alloca(sizeof(__ObjC_CatchableType)); memset(exceptTypes->types[typeCount], 0, sizeof(__ObjC_CatchableType)); exceptTypes->types[typeCount]->flags = 1; exceptTypes->types[typeCount]->mdisp = 0; exceptTypes->types[typeCount]->pdisp = -1; exceptTypes->types[typeCount]->vdisp = 0; exceptTypes->types[typeCount]->type = (const char *) alloca(32); memset((void *) exceptTypes->types[typeCount]->type, 0, 32); memcpy((char *)exceptTypes->types[typeCount]->type, class_getName(curType), strlen(class_getName(curType))); exceptTypes->types[typeCount]->size = 4; typeCount++; curType = class_getSuperclass(curType); } // Add id exceptTypes->types[typeCount] = (__ObjC_CatchableType *)_alloca(sizeof(__ObjC_CatchableType)); memset(exceptTypes->types[typeCount], 0, sizeof(__ObjC_CatchableType)); exceptTypes->types[typeCount]->flags = 1; exceptTypes->types[typeCount]->mdisp = 0; exceptTypes->types[typeCount]->pdisp = -1; exceptTypes->types[typeCount]->vdisp = 0; exceptTypes->types[typeCount]->type = (const char *)alloca(32); memset((void *)exceptTypes->types[typeCount]->type, 0, 32); exceptTypes->types[typeCount]->size = 4; typeCount++; exceptTypes->count = typeCount; _ThrowInfo ti = { 0, NULL, NULL, (_CatchableTypeArray *) exceptTypes }; _CxxThrowException(&exception, &ti); }
/****************************************************************** * __RTCastToVoid (MSVCRT.@) * * 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. */ void* CDECL MSVCRT___RTCastToVoid(void *cppobj) { void *ret; if (!cppobj) return NULL; __TRY { const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); ret = (char *)cppobj - obj_locator->base_class_offset; } __EXCEPT_PAGE_FAULT { __non_rtti_object e; MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); _CxxThrowException( &e, &bad_typeid_exception_type ); return NULL; } __ENDTRY return ret; }
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); /* 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 * * FIXME: the unknown parameter doesn't seem to be used for anything */ __TRY { int i; const rtti_object_locator *obj_locator = get_obj_locator( cppobj ); const rtti_object_hierarchy *obj_bases = obj_locator->type_hierarchy; const rtti_base_descriptor * const* base_desc = obj_bases->base_classes->bases; 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 ); } } __EXCEPT_PAGE_FAULT { __non_rtti_object e; MSVCRT___non_rtti_object_ctor( &e, "Access violation - no RTTI data!" ); _CxxThrowException( &e, &bad_typeid_exception_type ); return NULL; } __ENDTRY return ret; }