Authors: Jon Griffiths <jon_p_griffiths@yahoo.com>, François Gouget <fgouget@codeweavers.com>

Add RTTI support.
Fix what_exception prototype.
Fix new_handler_func prototype.
Add set_new_handler, _callnewh, _heapadd.
Add stubs for __unDName and __unDNameEx.
Added a semi-stub for __CxxFrameHandler.
This commit is contained in:
Alexandre Julliard 2001-12-21 20:27:39 +00:00
parent 1849f1eb15
commit 4f07f05716
5 changed files with 213 additions and 17 deletions

View File

@ -48,6 +48,36 @@ typedef struct __type_info
char name[1];
} type_info;
typedef struct _rtti_base_descriptor
{
type_info *type_descriptor;
int num_base_classes;
int base_class_offset;
unsigned int flags;
} rtti_base_descriptor;
typedef struct _rtti_base_array
{
rtti_base_descriptor *bases[1]; /* 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' */
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;
rtti_object_hierachy *type_hierachy;
} rtti_object_locator;
/******************************************************************
* ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
*/
@ -124,7 +154,7 @@ void * MSVCRT_exception__unknown_G(exception * _this, unsigned int arg1)
/******************************************************************
* ?what@exception@@UBEPBDXZ (MSVCRT.@)
*/
const char * __stdcall MSVCRT_exception_what(exception * _this)
const char * MSVCRT_what_exception(exception * _this)
{
TRACE("(%p) returning %s\n",_this,_this->name);
return _this->name;
@ -358,13 +388,109 @@ const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this)
}
/******************************************************************
* __RTtypeid (MSVCRT.@)
*/
type_info* MSVCRT___RTtypeid(type_info *cppobj)
{
/* Note: cppobj _isn't_ a type_info, we use that struct for its vtable ptr */
TRACE("(%p)\n",cppobj);
if (!IsBadReadPtr(cppobj, sizeof(void *)) &&
!IsBadReadPtr(cppobj->vtable - 1,sizeof(void *)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
rtti_object_locator *obj_locator = (rtti_object_locator *)cppobj->vtable[-1];
return obj_locator->type_descriptor;
}
/* FIXME: throw a C++ exception */
FIXME("Should throw(bad_typeid). Creating NULL reference, expect crash!\n");
return NULL;
}
/******************************************************************
* __RTDynamicCast (MSVCRT.@)
*/
void* MSVCRT___RTDynamicCast(type_info *cppobj, int unknown,
type_info *src, type_info *dst,
int do_throw)
{
/* Note: cppobj _isn't_ a type_info, we use that struct for its vtable ptr */
TRACE("(%p,%d,%p,%p,%d)\n",cppobj, unknown, src, dst, do_throw);
if (unknown)
FIXME("Unknown prameter is non-zero: please report\n");
/* 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 heirachy
* 3.If destination type is found, return base object address + dest offset
* Otherwise, fail the cast
*/
if (!IsBadReadPtr(cppobj, sizeof(void *)) &&
!IsBadReadPtr(cppobj->vtable - 1,sizeof(void *)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
int count = 0;
rtti_object_locator *obj_locator = (rtti_object_locator *)cppobj->vtable[-1];
rtti_object_hierachy *obj_bases = obj_locator->type_hierachy;
rtti_base_descriptor **base_desc = obj_bases->base_classes->bases;
int src_offset = obj_locator->base_class_offset, dst_offset = -1;
while (count < obj_bases->array_len)
{
type_info *typ = (*base_desc)->type_descriptor;
if (!strcmp(typ->name, dst->name))
{
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 do_throw to 1 when the result of a dynamic_cast is assigned
* to a reference, since references cannot be NULL.
*/
if (do_throw)
FIXME("Should throw(bad_cast). Creating NULL reference, expect crash!\n");
return NULL;
}
/******************************************************************
* __RTCastToVoid (MSVCRT.@)
*/
void* MSVCRT___RTCastToVoid(type_info *cppobj)
{
/* Note: cppobj _isn't_ a type_info, we use that struct for its vtable ptr */
TRACE("(%p)\n",cppobj);
/* Casts to void* simply cast to the base object */
if (!IsBadReadPtr(cppobj, sizeof(void *)) &&
!IsBadReadPtr(cppobj->vtable - 1,sizeof(void *)) &&
!IsBadReadPtr((void*)cppobj->vtable[-1], sizeof(rtti_object_locator)))
{
rtti_object_locator *obj_locator = (rtti_object_locator *)cppobj->vtable[-1];
int src_offset = obj_locator->base_class_offset;
return (void*)((unsigned long)cppobj - src_offset);
}
return NULL;
}
/* INTERNAL: Set up vtables
* FIXME:should be static, cope with versions?
*/
void msvcrt_init_vtables(void)
{
exception_vtable[0] = MSVCRT_exception_dtor;
exception_vtable[1] = (void*)MSVCRT_exception_what;
exception_vtable[1] = (void*)MSVCRT_what_exception;
bad_typeid_vtable[0] = MSVCRT_bad_typeid_dtor;
bad_typeid_vtable[1] = exception_vtable[1];

View File

@ -353,3 +353,20 @@ void* MSVCRT_signal(int sig, MSVCRT_sig_handler_func func)
FIXME("(%d %p):stub\n", sig, func);
return (void*)-1;
}
/*********************************************************************
* __CxxFrameHandler (MSVCRT.@)
*/
DWORD __CxxFrameHandler(PEXCEPTION_RECORD rec, struct __EXCEPTION_FRAME* frame,
PCONTEXT context, struct __EXCEPTION_FRAME** dispatch)
{
FIXME("(%p,%p,%p,%p):stub?\n",rec,frame,context,dispatch);
/* Copied from MSVCRT_nested_handler, I hope this is more
* or less the right thing to do
*/
if (rec->ExceptionFlags & 0x6)
return ExceptionContinueSearch;
*dispatch = frame;
return ExceptionCollidedUnwind;
}

View File

@ -8,6 +8,7 @@
*/
#include "msvcrt.h"
#include "ms_errno.h"
#include "msvcrt/malloc.h"
@ -19,7 +20,7 @@ extern CRITICAL_SECTION MSVCRT_heap_cs;
#define LOCK_HEAP EnterCriticalSection(&MSVCRT_heap_cs)
#define UNLOCK_HEAP LeaveCriticalSection(&MSVCRT_heap_cs)
typedef void (*MSVCRT_new_handler_func)(void);
typedef void (*MSVCRT_new_handler_func)(unsigned long size);
static MSVCRT_new_handler_func MSVCRT_new_handler;
static int MSVCRT_new_mode;
@ -34,7 +35,7 @@ void* MSVCRT_operator_new(unsigned long size)
TRACE("(%ld) returning %p\n", size, retval);
LOCK_HEAP;
if(retval && MSVCRT_new_handler)
(*MSVCRT_new_handler)();
(*MSVCRT_new_handler)(size);
UNLOCK_HEAP;
return retval;
}
@ -79,6 +80,16 @@ MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
return old_handler;
}
/*********************************************************************
* ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
*/
MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func)
{
TRACE("(%p)\n",func);
MSVCRT__set_new_handler(NULL);
return NULL;
}
/*********************************************************************
* ?_set_new_mode@@YAHH@Z (MSVCRT.@)
*/
@ -92,6 +103,16 @@ int MSVCRT__set_new_mode(int mode)
return old_mode;
}
/*********************************************************************
* _callnewh (MSVCRT.@)
*/
int _callnewh(unsigned long size)
{
if(MSVCRT_new_handler)
(*MSVCRT_new_handler)(size);
return 0;
}
/*********************************************************************
* _expand (MSVCRT.@)
*/
@ -187,6 +208,16 @@ int _heapset(unsigned int value)
return retval == _HEAPEND? _HEAPOK : retval;
}
/*********************************************************************
* _heapadd (MSVCRT.@)
*/
int _heapadd(void* mem, MSVCRT_size_t size)
{
TRACE("(%p,%d) unsupported in Win32\n", mem,size);
SET_THREAD_VAR(errno,MSVCRT_ENOSYS);
return -1;
}
/*********************************************************************
* _msize (MSVCRT.@)
*/

View File

@ -34,6 +34,8 @@ void msvcrt_init_args(void);
void msvcrt_free_args(void);
void msvcrt_init_vtables(void);
typedef void* (*MSVCRT_malloc_func)(unsigned int);
typedef void (*MSVCRT_free_func)(void*);
/*********************************************************************
* Init
@ -159,21 +161,41 @@ void MSVCRT_I10_OUTPUT(void)
/* FIXME: This is probably data, not a function */
}
/*********************************************************************
* __unDName (MSVCRT.@)
* Function not really understood but needed to make the DLL work
*/
void MSVCRT___unDName(void)
char* MSVCRT___unDName(int unknown, const char* mangled,
MSVCRT_malloc_func memget,
MSVCRT_free_func memfree,
unsigned int flags)
{
/* Called by all VC compiled progs on startup. No idea what it does */
char* ret;
FIXME("(%d,%s,%p,%p,%x) stub!\n", unknown, mangled, memget, memfree, flags);
/* Experimentation reveals the following flag meanings when set:
* 0x0001 - Dont show __ in calling convention
* 0x0002 - Dont show calling convention at all
* 0x0004 - Dont show function/method return value
* 0x0010 - Same as 0x1
* 0x0080 - Dont show access specifier (public/protected/private)
* 0x0200 - Dont show static specifier
* 0x1000 - Only report the variable/class name
*/
/* Duplicate the mangled name; for comparisons it doesn't matter anyway */
ret = memget(strlen(mangled) + 1);
strcpy(ret, mangled);
return ret;
}
/*********************************************************************
* __unDNameEx (MSVCRT.@)
* Function not really understood but needed to make the DLL work
*/
void MSVCRT___unDNameEx(void)
char* MSVCRT___unDNameEx(void)
{
/* As above */
return NULL;
}

View File

@ -51,12 +51,12 @@ debug_channels (msvcrt)
@ stub ?before@type_info@@QBEHABV1@@Z #(ptr ptr) stdcall
@ stdcall ?name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_name
@ stdcall ?raw_name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name
@ stub ?set_new_handler@@YAP6AXXZP6AXXZ@Z
@ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT__set_new_handler
@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_terminate
@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_unexpected
@ cdecl ?terminate@@YAXXZ() MSVCRT_terminate
@ cdecl ?unexpected@@YAXXZ() MSVCRT_unexpected
@ stdcall ?what@exception@@UBEPBDXZ(ptr) MSVCRT_exception_what
@ cdecl ?what@exception@@UBEPBDXZ(ptr) MSVCRT_what_exception
@ cdecl -noimport _CIacos() _CIacos
@ cdecl -noimport _CIasin() _CIasin
@ cdecl -noimport _CIatan() _CIatan
@ -81,11 +81,11 @@ debug_channels (msvcrt)
@ extern _HUGE MSVCRT__HUGE
@ cdecl _Strftime(str long str ptr ptr) _Strftime
@ cdecl _XcptFilter(long ptr) _XcptFilter
@ stub __CxxFrameHandler
@ cdecl __CxxFrameHandler(ptr ptr ptr ptr) __CxxFrameHandler
@ stub __CxxLongjmpUnwind
@ stub __RTCastToVoid
@ stub __RTDynamicCast
@ stub __RTtypeid
@ cdecl -noimport __RTCastToVoid(ptr) MSVCRT___RTCastToVoid
@ cdecl -noimport __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast
@ cdecl -noimport __RTtypeid(ptr) MSVCRT___RTtypeid
@ stub __STRINGTOLD
@ extern __argc MSVCRT___argc
@ extern __argv MSVCRT___argv
@ -143,7 +143,7 @@ debug_channels (msvcrt)
@ forward __threadhandle kernel32.GetCurrentThread
@ forward __threadid kernel32.GetCurrentThreadId
@ cdecl __toascii(long) MSVCRT___toascii
@ cdecl __unDName() MSVCRT___unDName #FIXME
@ cdecl __unDName(long str ptr ptr long) MSVCRT___unDName
@ cdecl __unDNameEx() MSVCRT___unDNameEx #FIXME
@ extern __unguarded_readlc_active MSVCRT___unguarded_readlc_active
@ extern __wargv MSVCRT___wargv
@ -177,7 +177,7 @@ debug_channels (msvcrt)
@ cdecl _beginthreadex (ptr long ptr ptr long ptr) _beginthreadex
@ cdecl _c_exit() MSVCRT__c_exit
@ cdecl _cabs(long) _cabs
@ stub _callnewh
@ cdecl _callnewh(long) _callnewh
@ cdecl _cexit() MSVCRT__cexit
@ cdecl _cgets(str) _cgets
@ cdecl _chdir(str) _chdir