[1/4] msvcirt: Add implementation of streambuf::allocate

Iván Matellanes matellanesivan at gmail.com
Sun Jun 7 13:54:39 CDT 2015


---
 dlls/msvcirt/msvcirt.c       | 56 ++++++++++++++++++++++++++++++++++++++++++--
 dlls/msvcirt/msvcirt.h       |  1 +
 dlls/msvcirt/msvcirt.spec    |  4 ++--
 dlls/msvcirt/tests/msvcirt.c | 23 +++++++++++++++++-
 dlls/msvcrt20/msvcrt20.spec  |  4 ++--
 dlls/msvcrt40/msvcrt40.spec  |  4 ++--
 6 files changed, 83 insertions(+), 9 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index e0781b9..b320a82 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -29,6 +29,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcirt);
 
+#define RESERVE_SIZE 512
+
 /* class streambuf */
 typedef struct {
     const vtable_ptr *vtable;
@@ -47,6 +49,7 @@ typedef struct {
     CRITICAL_SECTION lock;
 } streambuf;
 
+void __thiscall streambuf_setb(streambuf*, char*, char*, int);
 streambuf* __thiscall streambuf_setbuf(streambuf*, char*, int);
 void __thiscall streambuf_setg(streambuf*, char*, char*, char*);
 void __thiscall streambuf_setp(streambuf*, char*, char*);
@@ -176,13 +179,31 @@ streambuf* __thiscall streambuf_scalar_dtor(streambuf *this, unsigned int flags)
     return this;
 }
 
+/* ?allocate at streambuf@@IAEHXZ */
+/* ?allocate at streambuf@@IEAAHXZ */
+DEFINE_THISCALL_WRAPPER(streambuf_allocate, 4)
+int __thiscall streambuf_allocate(streambuf *this)
+{
+    TRACE("(%p)\n", this);
+    if (this->base != NULL || this->unbuffered)
+        return 0;
+    return CALL_VTBL_FUNC(this, 40, int, (streambuf*), (this));
+}
+
 /* ?doallocate at streambuf@@MAEHXZ */
 /* ?doallocate at streambuf@@MEAAHXZ */
 DEFINE_THISCALL_WRAPPER(streambuf_doallocate, 4)
 int __thiscall streambuf_doallocate(streambuf *this)
 {
-    FIXME("(%p): stub\n", this);
-    return EOF;
+    char *reserve;
+
+    TRACE("(%p)\n", this);
+    reserve = MSVCRT_operator_new(RESERVE_SIZE);
+    if (!reserve)
+        return EOF;
+
+    streambuf_setb(this, reserve, reserve + RESERVE_SIZE, 1);
+    return 1;
 }
 
 /* Unexported */
@@ -404,6 +425,35 @@ char * __thiscall MSVCIRT_str_sl_void(class_strstreambuf * _this)
    return 0;
 }
 
+#ifdef __i386__
+
+#define DEFINE_VTBL_WRAPPER(off)            \
+    __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
+        "popl %eax\n\t"                     \
+        "popl %ecx\n\t"                     \
+        "pushl %eax\n\t"                    \
+        "movl 0(%ecx), %eax\n\t"            \
+        "jmp *" #off "(%eax)\n\t")
+
+DEFINE_VTBL_WRAPPER(0);
+DEFINE_VTBL_WRAPPER(4);
+DEFINE_VTBL_WRAPPER(8);
+DEFINE_VTBL_WRAPPER(12);
+DEFINE_VTBL_WRAPPER(16);
+DEFINE_VTBL_WRAPPER(20);
+DEFINE_VTBL_WRAPPER(24);
+DEFINE_VTBL_WRAPPER(28);
+DEFINE_VTBL_WRAPPER(32);
+DEFINE_VTBL_WRAPPER(36);
+DEFINE_VTBL_WRAPPER(40);
+DEFINE_VTBL_WRAPPER(44);
+DEFINE_VTBL_WRAPPER(48);
+DEFINE_VTBL_WRAPPER(52);
+DEFINE_VTBL_WRAPPER(56);
+
+#endif
+
+void* (__cdecl *MSVCRT_operator_new)(SIZE_T);
 void (__cdecl *MSVCRT_operator_delete)(void*);
 
 static void init_cxx_funcs(void)
@@ -412,10 +462,12 @@ static void init_cxx_funcs(void)
 
     if (sizeof(void *) > sizeof(int))  /* 64-bit has different names */
     {
+        MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2 at YAPEAX_K@Z");
         MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3 at YAXPEAX@Z");
     }
     else
     {
+        MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2 at YAPAXI@Z");
         MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3 at YAXPAX@Z");
     }
 }
diff --git a/dlls/msvcirt/msvcirt.h b/dlls/msvcirt/msvcirt.h
index bdcd7d8..5cf15de 100644
--- a/dlls/msvcirt/msvcirt.h
+++ b/dlls/msvcirt/msvcirt.h
@@ -23,6 +23,7 @@
 typedef LONG streamoff;
 typedef LONG streampos;
 
+extern void* (__cdecl *MSVCRT_operator_new)(SIZE_T);
 extern void (__cdecl *MSVCRT_operator_delete)(void*);
 
 void init_exception(void*);
diff --git a/dlls/msvcirt/msvcirt.spec b/dlls/msvcirt/msvcirt.spec
index dfb2734..f987dfd 100644
--- a/dlls/msvcirt/msvcirt.spec
+++ b/dlls/msvcirt/msvcirt.spec
@@ -400,8 +400,8 @@
 @ stub -arch=win32 ??_Gstrstream@@UAEPAXI at Z  # virtual void * __thiscall strstream::`scalar deleting destructor'(unsigned int)
 @ stub -arch=win32 ??_Gstrstreambuf@@UAEPAXI at Z  # virtual void * __thiscall strstreambuf::`scalar deleting destructor'(unsigned int)
 # @ extern ?adjustfield at ios@@2JB  # static long const ios::adjustfield
-@ stub -arch=win32 ?allocate at streambuf@@IAEHXZ  # int __thiscall streambuf::allocate(void)
-@ stub -arch=win64 ?allocate at streambuf@@IEAAHXZ
+@ thiscall -arch=win32 ?allocate at streambuf@@IAEHXZ(ptr) streambuf_allocate
+@ cdecl -arch=win64 ?allocate at streambuf@@IEAAHXZ(ptr) streambuf_allocate
 @ stub -arch=win32 ?attach at filebuf@@QAEPAV1 at H@Z  # class filebuf * __thiscall filebuf::attach(int)
 @ stub -arch=win64 ?attach at filebuf@@QEAAPEAV1 at H@Z
 @ stub -arch=win32 ?attach at fstream@@QAEXH at Z  # void __thiscall fstream::attach(int)
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index 311fd97..8bf194f 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -52,6 +52,8 @@ typedef struct {
 static streambuf* (*__thiscall p_streambuf_reserve_ctor)(streambuf*, char*, int);
 static streambuf* (*__thiscall p_streambuf_ctor)(streambuf*);
 static void (*__thiscall p_streambuf_dtor)(streambuf*);
+static int (*__thiscall p_streambuf_allocate)(streambuf*);
+static int (*__thiscall p_streambuf_doallocate)(streambuf*);
 static void (*__thiscall p_streambuf_setb)(streambuf*, char*, char*, int);
 static streambuf* (*__thiscall p_streambuf_setbuf)(streambuf*, char*, int);
 
@@ -127,12 +129,16 @@ static BOOL init(void)
         SET(p_streambuf_reserve_ctor, "??0streambuf@@IEAA at PEADH@Z");
         SET(p_streambuf_ctor, "??0streambuf@@IEAA at XZ");
         SET(p_streambuf_dtor, "??1streambuf@@UEAA at XZ");
+        SET(p_streambuf_allocate, "?allocate at streambuf@@IEAAHXZ");
+        SET(p_streambuf_doallocate, "?doallocate at streambuf@@MEAAHXZ");
         SET(p_streambuf_setb, "?setb at streambuf@@IEAAXPEAD0H at Z");
         SET(p_streambuf_setbuf, "?setbuf at streambuf@@UEAAPEAV1 at PEADH@Z");
     } else {
         SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE at PADH@Z");
         SET(p_streambuf_ctor, "??0streambuf@@IAE at XZ");
         SET(p_streambuf_dtor, "??1streambuf@@UAE at XZ");
+        SET(p_streambuf_allocate, "?allocate at streambuf@@IAEHXZ");
+        SET(p_streambuf_doallocate, "?doallocate at streambuf@@MAEHXZ");
         SET(p_streambuf_setb, "?setb at streambuf@@IAEXPAD0H at Z");
         SET(p_streambuf_setbuf, "?setbuf at streambuf@@UAEPAV1 at PADH@Z");
     }
@@ -145,6 +151,7 @@ static void test_streambuf(void)
 {
     streambuf sb, sb2, *psb;
     char reserve[16];
+    int ret;
 
     memset(&sb, 0xab, sizeof(streambuf));
     memset(&sb2, 0xab, sizeof(streambuf));
@@ -197,7 +204,21 @@ static void test_streambuf(void)
     ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
     ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
 
-    sb.allocated = 0;
+    /* allocate */
+    ret = (int) call_func1(p_streambuf_allocate, &sb);
+    ok(ret == 0, "wrong return value, expected 0 got %d\n", ret);
+    sb.base = NULL;
+    ret = (int) call_func1(p_streambuf_allocate, &sb);
+    ok(ret == 1, "wrong return value, expected 1 got %d\n", ret);
+    ok(sb.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb.allocated);
+    ok(sb.ebuf - sb.base == 512 , "wrong reserve area size, expected 512 got %d\n", sb.ebuf - sb.base);
+
+    /* doallocate */
+    ret = (int) call_func1(p_streambuf_doallocate, &sb2);
+    ok(ret == 1, "doallocate failed, got %d\n", ret);
+    ok(sb2.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb2.allocated);
+    ok(sb2.ebuf - sb2.base == 512 , "wrong reserve area size, expected 512 got %d\n", sb2.ebuf - sb2.base);
+
     call_func1(p_streambuf_dtor, &sb);
     call_func1(p_streambuf_dtor, &sb2);
 }
diff --git a/dlls/msvcrt20/msvcrt20.spec b/dlls/msvcrt20/msvcrt20.spec
index 3cefd74..195cdf1 100644
--- a/dlls/msvcrt20/msvcrt20.spec
+++ b/dlls/msvcrt20/msvcrt20.spec
@@ -388,8 +388,8 @@
 @ cdecl -arch=win32 ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z
 @ cdecl -arch=win64 ?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z
 # @ extern ?adjustfield at ios@@2JB
-@ stub -arch=win32 ?allocate at streambuf@@IAEHXZ
-@ stub -arch=win64 ?allocate at streambuf@@IEAAHXZ
+@ thiscall -arch=win32 ?allocate at streambuf@@IAEHXZ(ptr) msvcirt.?allocate at streambuf@@IAEHXZ
+@ cdecl -arch=win64 ?allocate at streambuf@@IEAAHXZ(ptr) msvcirt.?allocate at streambuf@@IEAAHXZ
 @ stub -arch=win32 ?attach at filebuf@@QAEPAV1 at H@Z
 @ stub -arch=win64 ?attach at filebuf@@QEAAPEAV1 at H@Z
 @ stub -arch=win32 ?attach at fstream@@QAEXH at Z
diff --git a/dlls/msvcrt40/msvcrt40.spec b/dlls/msvcrt40/msvcrt40.spec
index 705521a..0042f17 100644
--- a/dlls/msvcrt40/msvcrt40.spec
+++ b/dlls/msvcrt40/msvcrt40.spec
@@ -451,8 +451,8 @@
 @ cdecl -arch=win32 ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z
 @ cdecl -arch=win64 ?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0 at Z@Z
 # @ extern ?adjustfield at ios@@2JB
-@ stub -arch=win32 ?allocate at streambuf@@IAEHXZ
-@ stub -arch=win64 ?allocate at streambuf@@IEAAHXZ
+@ thiscall -arch=win32 ?allocate at streambuf@@IAEHXZ(ptr) msvcirt.?allocate at streambuf@@IAEHXZ
+@ cdecl -arch=win64 ?allocate at streambuf@@IEAAHXZ(ptr) msvcirt.?allocate at streambuf@@IEAAHXZ
 @ stub -arch=win32 ?attach at filebuf@@QAEPAV1 at H@Z
 @ stub -arch=win64 ?attach at filebuf@@QEAAPEAV1 at H@Z
 @ stub -arch=win32 ?attach at fstream@@QAEXH at Z
-- 
2.1.4




More information about the wine-patches mailing list