[PATCH 2/2] Partially implement type_info::name_internal_method()

Nikolay Sivov nsivov at codeweavers.com
Thu Feb 3 06:56:33 CST 2011


---
 dlls/msvcr100/msvcr100.spec  |    4 +-
 dlls/msvcr80/msvcr80.spec    |    4 +-
 dlls/msvcr90/msvcr90.c       |   78 ++++++++++++++++++++++++++++++
 dlls/msvcr90/msvcr90.spec    |    4 +-
 dlls/msvcr90/tests/msvcr90.c |  108 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 192 insertions(+), 6 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 1b7588c..13f4d19 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -260,8 +260,8 @@
 @ cdecl -arch=win64 ?_invalid_parameter@@YAXPEBG00I_K at Z(wstr wstr wstr long long) msvcrt._invalid_parameter
 @ stub -arch=win32 ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const &,struct _EXCEPTION_POINTERS *)
 @ stub -arch=win64 ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const & __ptr64,struct _EXCEPTION_POINTERS * __ptr64)
-@ stub -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z  # public: char const * __thiscall type_info::_name_internal_method(struct __type_info_node *)const 
-@ stub -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z  # public: char const * __ptr64 __cdecl type_info::_name_internal_method(struct __type_info_node * __ptr64)const __ptr64
+@ thiscall -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z(ptr ptr) msvcr90.?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z
+@ cdecl -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z(ptr ptr) msvcr90.?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z
 @ varargs -arch=win32 ?_open@@YAHPBDHH at Z(str long) msvcrt._open
 @ varargs -arch=win64 ?_open@@YAHPEBDHH at Z(str long) msvcrt._open
 @ cdecl -arch=win32 ?_query_new_handler@@YAP6AHI at ZXZ() msvcrt.?_query_new_handler@@YAP6AHI at ZXZ
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 90ec520..aca11e7 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -83,8 +83,8 @@
 @ cdecl -arch=win64 ?_invalid_parameter@@YAXPEBG00I_K at Z(wstr wstr wstr long long) msvcrt._invalid_parameter
 @ stub -arch=win32 ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const &,struct _EXCEPTION_POINTERS *)
 @ stub -arch=win64 ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const & __ptr64,struct _EXCEPTION_POINTERS * __ptr64)
-@ stub -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z  # public: char const * __thiscall type_info::_name_internal_method(struct __type_info_node *)const 
-@ stub -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z  # public: char const * __ptr64 __cdecl type_info::_name_internal_method(struct __type_info_node * __ptr64)const __ptr64
+@ thiscall -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z(ptr ptr) msvcr90.?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z
+@ cdecl -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z(ptr ptr)  msvcr90.?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z
 @ varargs -arch=win32 ?_open@@YAHPBDHH at Z(str long) msvcrt._open
 @ varargs -arch=win64 ?_open@@YAHPEBDHH at Z(str long) msvcrt._open
 @ cdecl -arch=win32 ?_query_new_handler@@YAP6AHI at ZXZ() msvcrt.?_query_new_handler@@YAP6AHI at ZXZ
diff --git a/dlls/msvcr90/msvcr90.c b/dlls/msvcr90/msvcr90.c
index 34ee20f..2c811cb 100644
--- a/dlls/msvcr90/msvcr90.c
+++ b/dlls/msvcr90/msvcr90.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
 #include <stdarg.h>
 
 #include "stdlib.h"
@@ -30,6 +31,46 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcr90);
 
+#ifdef __i386__  /* thiscall functions are i386-specific */
+
+#define THISCALL(func) __thiscall_ ## func
+#define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
+#define __thiscall __stdcall
+#define DEFINE_THISCALL_WRAPPER(func,args) \
+    extern void THISCALL(func)(void); \
+    __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
+                      "popl %eax\n\t" \
+                      "pushl %ecx\n\t" \
+                      "pushl %eax\n\t" \
+                      "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
+
+#else /* __i386__ */
+
+#define THISCALL(func) func
+#define THISCALL_NAME(func) __ASM_NAME(#func)
+#define __thiscall __cdecl
+#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
+
+#endif /* __i386__ */
+
+struct __type_info_node
+{
+    void *memPtr;
+    struct __type_info_node* next;
+};
+
+typedef struct __type_info
+{
+  const void *vtable;
+  char       *name;        /* Unmangled name, allocated lazily */
+  char        mangled[32]; /* Variable length, but we declare it large enough for static RTTI */
+} type_info;
+
+typedef void* (*__cdecl malloc_func_t)(size_t);
+typedef void  (*__cdecl free_func_t)(void*);
+
+extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,unsigned short int);
+
 /*********************************************************************
  *  msvcr90_stat64_to_stat32 [internal]
  */
@@ -260,3 +301,40 @@ int CDECL _atoflt( _CRT_FLOAT *value, char *str )
 {
     return _atoflt_l( value, str, NULL );
 }
+
+/*********************************************************************
+ * ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z (MSVCR90.@)
+ */
+DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_name_internal_method,8)
+const char * __thiscall MSVCRT_type_info_name_internal_method(type_info * _this, struct __type_info_node *node)
+{
+    static int once;
+
+    if (node && !once++) FIXME("type_info_node parameter ignored\n");
+
+    if (!_this->name)
+    {
+      /* Create and set the demangled name */
+      /* Nota: mangled name in type_info struct always start with a '.', while
+       * it isn't valid for mangled name.
+       * Is this '.' really part of the mangled name, or has it some other meaning ?
+       */
+      char* name = __unDName(0, _this->mangled + 1, 0, malloc, free, 0x2800);
+      if (name)
+      {
+        unsigned int len = strlen(name);
+
+        /* It seems _unDName may leave blanks at the end of the demangled name */
+        while (len && name[--len] == ' ')
+          name[len] = '\0';
+
+        if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL))
+        {
+          /* Another thread set this member since we checked above - use it */
+          free(name);
+        }
+      }
+    }
+    TRACE("(%p) returning %s\n", _this, _this->name);
+    return _this->name;
+}
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index c89bfda..b269b87 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -83,8 +83,8 @@
 @ cdecl -arch=win64 ?_invalid_parameter@@YAXPEBG00I_K at Z(wstr wstr wstr long long) msvcrt._invalid_parameter
 @ stub -arch=win32 ?_is_exception_typeof@@YAHABVtype_info@@PAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const &,struct _EXCEPTION_POINTERS *)
 @ stub -arch=win64 ?_is_exception_typeof@@YAHAEBVtype_info@@PEAU_EXCEPTION_POINTERS@@@Z  # int __cdecl _is_exception_typeof(class type_info const & __ptr64,struct _EXCEPTION_POINTERS * __ptr64)
-@ stub -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z  # public: char const * __thiscall type_info::_name_internal_method(struct __type_info_node *)const 
-@ stub -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z  # public: char const * __ptr64 __cdecl type_info::_name_internal_method(struct __type_info_node * __ptr64)const __ptr64
+@ thiscall -arch=win32 ?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z(ptr ptr) MSVCRT_type_info_name_internal_method
+@ cdecl -arch=win64 ?_name_internal_method at type_info@@QEBAPEBDPEAU__type_info_node@@@Z(ptr ptr) MSVCRT_type_info_name_internal_method
 @ varargs -arch=win32 ?_open@@YAHPBDHH at Z(str long) msvcrt._open
 @ varargs -arch=win64 ?_open@@YAHPEBDHH at Z(str long) msvcrt._open
 @ cdecl -arch=win32 ?_query_new_handler@@YAP6AHI at ZXZ() msvcrt.?_query_new_handler@@YAP6AHI at ZXZ
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index 67b00fc..dc90103 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -79,6 +79,17 @@ static void* (__cdecl *p_realloc_crt)(void*, size_t);
 static void* (__cdecl *p_malloc)(size_t);
 static void (__cdecl *p_free)(void*);
 
+/* type info */
+typedef struct __type_info
+{
+  void *vtable;
+  char *name;
+  char  mangled[16];
+} type_info;
+
+static char* (WINAPI *p_type_info_name_internal_method)(type_info*);
+static void  (WINAPI *ptype_info_dtor)(type_info*);
+
 static void* (WINAPI *pEncodePointer)(void *);
 
 static int cb_called[4];
@@ -91,6 +102,62 @@ static inline int almost_equal_f(float f1, float f2)
 
 /* ########## */
 
+/* thiscall emulation */
+/* Emulate a __thiscall */
+#ifdef _MSC_VER
+static inline void* do_call_func1(void *func, void *_this)
+{
+  volatile void* retval = 0;
+  __asm
+  {
+    push ecx
+    mov ecx, _this
+    call func
+    mov retval, eax
+    pop ecx
+  }
+  return (void*)retval;
+}
+
+static inline void* do_call_func2(void *func, void *_this, const void* arg)
+{
+  volatile void* retval = 0;
+  __asm
+  {
+    push ecx
+    push arg
+    mov ecx, _this
+    call func
+    mov retval, eax
+    pop ecx
+  }
+  return (void*)retval;
+}
+#else
+static void* do_call_func1(void *func, void *_this)
+{
+  void *ret, *dummy;
+  __asm__ __volatile__ ("call *%2"
+                        : "=a" (ret), "=c" (dummy)
+                        : "g" (func), "1" (_this)
+                        : "edx", "memory" );
+  return ret;
+}
+
+static void* do_call_func2(void *func, void *_this, const void* arg)
+{
+  void *ret, *dummy;
+  __asm__ __volatile__ ("pushl %3\n\tcall *%2"
+                        : "=a" (ret), "=c" (dummy)
+                        : "r" (func), "r" (arg), "1" (_this)
+                        : "edx", "memory" );
+  return ret;
+}
+#endif
+
+#define call_func1(x,y)   do_call_func1((void*)x,(void*)y)
+#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(void*)z)
+
 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
         const wchar_t *function, const wchar_t *file,
         unsigned line, uintptr_t arg)
@@ -796,6 +863,43 @@ if (0)
     p_free(mem);
 }
 
+#ifdef __i386__
+
+struct __type_info_node {
+    void *memPtr;
+    struct __type_info_node* next;
+};
+
+static void test_typeinfo(void)
+{
+    static type_info t1 = { NULL, NULL,{'.','?','A','V','t','e','s','t','1','@','@',0,0,0,0,0 } };
+    struct __type_info_node node;
+    char *name;
+
+    if (!p_type_info_name_internal_method)
+    {
+        win_skip("public: char const * __thiscall type_info::_name_internal_method(struct \
+                  __type_info_node *)const not supported\n");
+        return;
+    }
+
+    /* name */
+    t1.name = NULL;
+    node.memPtr = NULL;
+    node.next = NULL;
+    name = call_func2(p_type_info_name_internal_method, &t1, &node);
+    ok(name != NULL, "got %p\n", name);
+    ok(name && t1.name && !strcmp(name, t1.name), "bad name '%s' for t1\n", name);
+
+    ok(t1.name && !strcmp(t1.name, "class test1"), "demangled to '%s' for t1\n", t1.name);
+    call_func1(ptype_info_dtor, &t1);
+}
+#else
+static void test_typeinfo(void)
+{
+}
+#endif
+
 START_TEST(msvcr90)
 {
     HMODULE hcrt;
@@ -834,6 +938,9 @@ START_TEST(msvcr90)
     p_realloc_crt = (void*) GetProcAddress(hcrt, "_realloc_crt");
     p_malloc = (void*) GetProcAddress(hcrt, "malloc");
     p_free = (void*)GetProcAddress(hcrt, "free");
+    p_type_info_name_internal_method = (void*)GetProcAddress(hcrt,
+      "?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z");
+    ptype_info_dtor = (void*)GetProcAddress(hcrt, "??1type_info@@UAE at XZ");
 
     hkernel32 = GetModuleHandleA("kernel32.dll");
     pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
@@ -851,4 +958,5 @@ START_TEST(msvcr90)
     test__sopen_s();
     test__wsopen_s();
     test__realloc_crt();
+    test_typeinfo();
 }
-- 
1.5.6.5


--------------060407040706020207090606--



More information about the wine-patches mailing list