📄 rtti.cpp
字号:
/*
This is a C++ run-time library for Windows kernel-mode drivers.
Copyright (C) 2004 Bo Brant閚.
*/
/*
The following is a modified subset of wine/dlls/msvcrt/cpp.c
from version wine20040505.
*/
/* * msvcrt.dll C++ objects * * Copyright 2000 Jon Griffiths * Copyright 2003 Alexandre Julliard * * 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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <typeinfo.h>
extern "C" unsigned char __stdcall IsBadReadPtr(const void*, unsigned int);
typedef void (*v_table_ptr)();
typedef struct _cpp_object
{
v_table_ptr* vtable;
} cpp_object;
typedef struct _rtti_base_descriptor{ type_info* type_descriptor; int num_base_classes; int base_class_offset; unsigned int flags; int unknown1; int unknown2;} rtti_base_descriptor;typedef struct _rtti_base_array{ const rtti_base_descriptor* bases[3]; /* First element is the class itself */} rtti_base_array;typedef struct _rtti_object_hierachy{ int unknown1; int unknown2; int array_len; /* Size of the array pointed to by 'base_classes' */ const rtti_base_array* base_classes;} rtti_object_hierachy;typedef struct _rtti_object_locator{ int unknown1; int base_class_offset; unsigned int flags; type_info* type_descriptor; const rtti_object_hierachy* type_hierachy;} rtti_object_locator;
/* Get type info from an object (internal) */static const rtti_object_locator* RTTI_GetObjectLocator(void* inptr){
cpp_object* cppobj = (cpp_object*) inptr; const rtti_object_locator* obj_locator = 0;
if (!IsBadReadPtr(cppobj, sizeof(void*)) &&
!IsBadReadPtr(cppobj->vtable - 1, sizeof(void*)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator))) { obj_locator = (rtti_object_locator*) cppobj->vtable[-1]; } return obj_locator;}/****************************************************************** * __RTtypeid (MSVCRT.@) * * 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. */extern "C" void* __cdecl __RTtypeid(void* inptr)
{
cpp_object* cppobj = (cpp_object*) inptr;
const rtti_object_locator* obj_locator = RTTI_GetObjectLocator(cppobj); if (!obj_locator) { if (!cppobj) {
throw bad_typeid(); } else {
throw __non_rtti_object(); } }
return obj_locator->type_descriptor;}/****************************************************************** * __RTDynamicCast (MSVCRT.@) * * Dynamically cast a C++ object to one of its base classes. * * PARAMS * inptr [I] Any C++ object to cast * unknown [I] Reserved, set to 0 * SrcType [I] type_info object describing cppobj * TargetType [I] type_info object describing the base class to cast to * isReference [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 isReference 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. */extern "C" void* __cdecl __RTDynamicCast(void* inptr, long unknown, void* SrcType, void* TargetType, int isReference)
{
cpp_object* cppobj = (cpp_object*) inptr;
type_info* src = (type_info*) SrcType;
type_info* dst = (type_info*) TargetType;
const rtti_object_locator* obj_locator;
if (unknown)
{
//DbgPrint("Unknown parameter is non-zero: please report\n");
}
if (!cppobj)
{ return 0;
}
obj_locator = RTTI_GetObjectLocator(cppobj); /* 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 */ if (obj_locator) { int count = 0; const rtti_object_hierachy* obj_bases = obj_locator->type_hierachy; const rtti_base_descriptor* const * base_desc = obj_bases->base_classes->bases; int src_offset = obj_locator->base_class_offset, dst_offset = -1; while (count < obj_bases->array_len) { const type_info* typ = (*base_desc)->type_descriptor; if (typ == dst) { dst_offset = (*base_desc)->base_class_offset; break; } base_desc++; count++; } if (dst_offset >= 0)
{ return (void*)((unsigned long)cppobj - src_offset + dst_offset);
} } /* VC++ sets isReference to 1 when the result of a dynamic_cast is assigned * to a reference, since references cannot be NULL. */ if (isReference) {
throw bad_cast();
}
return 0;}/****************************************************************** * __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. */extern "C" void* __cdecl __RTCastToVoid(void* inptr)
{
cpp_object* cppobj = (cpp_object*) inptr;
const rtti_object_locator* obj_locator = RTTI_GetObjectLocator(cppobj);
if (!obj_locator)
{
return 0;
}
/* Casts to void* simply cast to the base object */ return (void*)((unsigned long)cppobj - obj_locator->base_class_offset);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -