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:
parent
1849f1eb15
commit
4f07f05716
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue