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