Msvcrt patch 1/2
François Gouget
fgouget at codeweavers.com
Thu Dec 20 01:48:39 CST 2001
I have dug up an old patch by Jon Griffiths. I updated it, cleaned it
up and integrated it with current the MSVCRT code. So here it is (it
should make it to CVS this time :-).
Changelog:
Jon Griffiths <jon_p_griffiths at yahoo.com>
François Gouget <fgouget at codeweavers.com>
* dlls/msvcrt/cpp.c,
dlls/msvcrt/except.c,
dlls/msvcrt/heap.c,
dlls/msvcrt/main.c,
dlls/msvcrt/msvcrt.spec
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
--
François Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: dlls/msvcrt/cpp.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/cpp.c,v
retrieving revision 1.8
diff -u -r1.8 cpp.c
--- dlls/msvcrt/cpp.c 2001/07/23 23:50:18 1.8
+++ dlls/msvcrt/cpp.c 2001/12/20 05:48:23
@@ -48,6 +48,36 @@
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 at ABQBD@Z (MSVCRT.@)
*/
@@ -124,7 +154,7 @@
/******************************************************************
* ?what at 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 @@
}
+/******************************************************************
+ * __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];
Index: dlls/msvcrt/except.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/except.c,v
retrieving revision 1.7
diff -u -r1.7 except.c
--- dlls/msvcrt/except.c 2001/09/20 19:33:37 1.7
+++ dlls/msvcrt/except.c 2001/12/20 05:48:23
@@ -261,4 +352,21 @@
{
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;
}
Index: dlls/msvcrt/heap.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/heap.c,v
retrieving revision 1.6
diff -u -r1.6 heap.c
--- dlls/msvcrt/heap.c 2001/07/02 19:59:41 1.6
+++ dlls/msvcrt/heap.c 2001/12/20 05:48:23
@@ -8,6 +8,7 @@
*/
#include "msvcrt.h"
+#include "ms_errno.h"
#include "msvcrt/malloc.h"
@@ -19,7 +20,7 @@
#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 @@
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;
}
@@ -80,6 +81,16 @@
}
/*********************************************************************
+ * ?set_new_handler@@YAP6AXXZP6AXXZ at 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 at Z (MSVCRT.@)
*/
int MSVCRT__set_new_mode(int mode)
@@ -93,6 +104,16 @@
}
/*********************************************************************
+ * _callnewh (MSVCRT.@)
+ */
+int _callnewh(unsigned long size)
+{
+ if(MSVCRT_new_handler)
+ (*MSVCRT_new_handler)(size);
+ return 0;
+}
+
+/*********************************************************************
* _expand (MSVCRT.@)
*/
void* _expand(void* mem, MSVCRT_size_t size)
@@ -185,6 +206,16 @@
}
UNLOCK_HEAP;
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;
}
/*********************************************************************
Index: dlls/msvcrt/main.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/main.c,v
retrieving revision 1.5
diff -u -r1.5 main.c
--- dlls/msvcrt/main.c 2001/09/19 20:29:33 1.5
+++ dlls/msvcrt/main.c 2001/12/20 05:48:24
@@ -34,6 +34,8 @@
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 @@
/* 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)
-{
- /* Called by all VC compiled progs on startup. No idea what it does */
+char* MSVCRT___unDName(int unknown, const char* mangled,
+ MSVCRT_malloc_func memget,
+ MSVCRT_free_func memfree,
+ unsigned int flags)
+{
+ 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;
}
-
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.26
diff -u -r1.26 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec 2001/12/05 22:11:35 1.26
+++ dlls/msvcrt/msvcrt.spec 2001/12/20 05:48:24
@@ -51,12 +51,12 @@
@ stub ?before at type_info@@QBEHABV1@@Z #(ptr ptr) stdcall
@ stdcall ?name at type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_name
@ stdcall ?raw_name at type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name
-@ stub ?set_new_handler@@YAP6AXXZP6AXXZ at Z
+@ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ at Z(ptr) MSVCRT__set_new_handler
@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ at Z(ptr) MSVCRT_set_terminate
@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ at Z(ptr) MSVCRT_set_unexpected
@ cdecl ?terminate@@YAXXZ() MSVCRT_terminate
@ cdecl ?unexpected@@YAXXZ() MSVCRT_unexpected
-@ stdcall ?what at exception@@UBEPBDXZ(ptr) MSVCRT_exception_what
+@ cdecl ?what at exception@@UBEPBDXZ(ptr) MSVCRT_what_exception
@ cdecl -noimport _CIacos() _CIacos
@ cdecl -noimport _CIasin() _CIasin
@ cdecl -noimport _CIatan() _CIatan
@@ -81,11 +81,11 @@
@ 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 @@
@ 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 @@
@ 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
More information about the wine-patches
mailing list