📄 rtti.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/***
*rtti.cpp - C++ runtime type information
*
*
*Purpose:
* Implementation of C++ standard runtime type information
*
****/
extern "C" {
#include <windows.h>
};
#include <stdio.h>
#include <typeinfo>
#include <rtti.h>
static PVOID __cdecl FindCompleteObject(PVOID *);
static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,_RTTITypeDescriptor *,int,_RTTITypeDescriptor *);
static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,_RTTITypeDescriptor *,int,_RTTITypeDescriptor *);
static _RTTIBaseClassDescriptor * __cdecl FindVITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,_RTTITypeDescriptor *,int,_RTTITypeDescriptor *);
static ptrdiff_t __cdecl PMDtoOffset(PVOID, const PMD&);
/////////////////////////////////////////////////////////////////////////////
//
// __RTCastToVoid - Implements dynamic_cast<void*>
//
// Output: Pointer to complete object containing *inptr
//
// Side-effects: NONE.
//
extern "C" PVOID __cdecl __RTCastToVoid (PVOID inptr) // Pointer to polymorphic object
{
if (inptr == NULL)
return NULL;
__try {
return FindCompleteObject((PVOID *)inptr);
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
}
/////////////////////////////////////////////////////////////////////////////
//
// __RTtypeid - Implements typeid() operator
//
// Output: Pointer to type descriptor of complete object containing *inptr
//
// Side-effects: NONE.
//
extern "C" PVOID __cdecl __RTtypeid (PVOID inptr) // Pointer to polymorphic object
{
if (!inptr) {
throw std::bad_typeid ("Attempted a typeid of NULL pointer!"); // WP 5.2.7
return NULL;
}
__try {
// Ptr to CompleteObjectLocator should be stored at vfptr[-1]
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
#if 0
if (!IsBadReadPtr((const void *)pCompleteLocator->pTypeDescriptor, sizeof(TypeDescriptor))) {
return (PVOID) pCompleteLocator->pTypeDescriptor;
}
else {
throw std::__non_rtti_object ("Bad read pointer - no RTTI data!");
return NULL;
}
#else
return (PVOID) pCompleteLocator->pTypeDescriptor;
#endif
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
}
/////////////////////////////////////////////////////////////////////////////
//
// __RTDynamicCast - Runtime implementation of dynamic_cast<> operator
//
// Output: Pointer to the appropriate sub-object, if possible; NULL otherwise
//
// Side-effects: Throws bad_cast() if cast fails & input of dynamic_cast<> is a reference
//
extern "C" PVOID __cdecl __RTDynamicCast (
PVOID inptr, // Pointer to polymorphic object
LONG VfDelta, // Offset of vfptr in object
PVOID SrcType, // Static type of object pointed to by inptr
PVOID TargetType, // Desired result of cast
BOOL isReference) // TRUE if input is reference, FALSE if input is ptr
{
PVOID pResult;
_RTTIBaseClassDescriptor *pBaseClass;
if (inptr == NULL)
return NULL;
__try {
PVOID pCompleteObject = FindCompleteObject((PVOID *)inptr);
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
// Adjust by vfptr displacement, if any
inptr = (PVOID *) ((char *)inptr - VfDelta);
// Calculate offset of source object in complete object
int inptr_delta = (char *)inptr - (char *)pCompleteObject;
if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_MULTINH)) { // if not multiple inheritance
pBaseClass = FindSITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(_RTTITypeDescriptor *) SrcType,
inptr_delta,
(_RTTITypeDescriptor *) TargetType);
} else if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_VIRTINH)) { // if multiple, but not virtual, inheritance
pBaseClass = FindMITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(_RTTITypeDescriptor *) SrcType,
inptr_delta,
(_RTTITypeDescriptor *) TargetType);
} else { // if virtual inheritance
pBaseClass = FindVITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(_RTTITypeDescriptor *) SrcType,
inptr_delta,
(_RTTITypeDescriptor *) TargetType);
}
if (pBaseClass != NULL) {
// Calculate ptr to result base class from pBaseClass->where
pResult = ((char *) pCompleteObject) + PMDtoOffset(pCompleteObject, pBaseClass->where);
}else {
pResult = NULL;
if (isReference) {
throw std::bad_cast("Bad dynamic_cast!");
}
}
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
pResult = NULL;
throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
return pResult;
}
/////////////////////////////////////////////////////////////////////////////
//
// FindCompleteObject - Calculate member offset from PMD & this
//
// Output: pointer to the complete object containing class *inptr
//
// Side-effects: NONE.
//
static PVOID __cdecl FindCompleteObject (PVOID *inptr) // Pointer to polymorphic object
{
// Ptr to CompleteObjectLocator should be stored at vfptr[-1]
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
char *pCompleteObject = (char *)inptr - pCompleteLocator->offset;
// Adjust by construction displacement, if any
if (pCompleteLocator->cdOffset)
pCompleteObject += *(ptrdiff_t *)((char *)inptr - pCompleteLocator->cdOffset);
return (PVOID) pCompleteObject;
}
/////////////////////////////////////////////////////////////////////////////
//
// FindSITargetTypeInstance - workhorse routine of __RTDynamicCast() in a Single-Inheritance hierarchy
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -