From 77dbfc8979ef5ed940e89557820f6dd2792158c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Matellanes?= Date: Mon, 8 Jun 2015 21:26:21 +0200 Subject: [PATCH] msvcirt: Add implementation of streambuf::allocate. --- dlls/msvcirt/msvcirt.c | 57 ++++++++++++++++++++++++++++++++++-- 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, 84 insertions(+), 9 deletions(-) diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index e0781b915b6..507ed1132ce 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*); @@ -179,10 +182,29 @@ streambuf* __thiscall streambuf_scalar_dtor(streambuf *this, unsigned int flags) /* ?doallocate@streambuf@@MAEHXZ */ /* ?doallocate@streambuf@@MEAAHXZ */ DEFINE_THISCALL_WRAPPER(streambuf_doallocate, 4) +#define call_streambuf_doallocate(this) CALL_VTBL_FUNC(this, 40, int, (streambuf*), (this)) 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; +} + +/* ?allocate@streambuf@@IAEHXZ */ +/* ?allocate@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_streambuf_doallocate(this); } /* Unexported */ @@ -404,6 +426,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 +463,12 @@ static void init_cxx_funcs(void) if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */ { + MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPEAX_K@Z"); MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPEAX@Z"); } else { + MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPAXI@Z"); MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPAX@Z"); } } diff --git a/dlls/msvcirt/msvcirt.h b/dlls/msvcirt/msvcirt.h index bdcd7d89600..5cf15deb81b 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 dfb273433cd..f987dfd7194 100644 --- a/dlls/msvcirt/msvcirt.spec +++ b/dlls/msvcirt/msvcirt.spec @@ -400,8 +400,8 @@ @ stub -arch=win32 ??_Gstrstream@@UAEPAXI@Z # virtual void * __thiscall strstream::`scalar deleting destructor'(unsigned int) @ stub -arch=win32 ??_Gstrstreambuf@@UAEPAXI@Z # virtual void * __thiscall strstreambuf::`scalar deleting destructor'(unsigned int) # @ extern ?adjustfield@ios@@2JB # static long const ios::adjustfield -@ stub -arch=win32 ?allocate@streambuf@@IAEHXZ # int __thiscall streambuf::allocate(void) -@ stub -arch=win64 ?allocate@streambuf@@IEAAHXZ +@ thiscall -arch=win32 ?allocate@streambuf@@IAEHXZ(ptr) streambuf_allocate +@ cdecl -arch=win64 ?allocate@streambuf@@IEAAHXZ(ptr) streambuf_allocate @ stub -arch=win32 ?attach@filebuf@@QAEPAV1@H@Z # class filebuf * __thiscall filebuf::attach(int) @ stub -arch=win64 ?attach@filebuf@@QEAAPEAV1@H@Z @ stub -arch=win32 ?attach@fstream@@QAEXH@Z # void __thiscall fstream::attach(int) diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index 311fd9776eb..51b75eed2b6 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@PEADH@Z"); SET(p_streambuf_ctor, "??0streambuf@@IEAA@XZ"); SET(p_streambuf_dtor, "??1streambuf@@UEAA@XZ"); + SET(p_streambuf_allocate, "?allocate@streambuf@@IEAAHXZ"); + SET(p_streambuf_doallocate, "?doallocate@streambuf@@MEAAHXZ"); SET(p_streambuf_setb, "?setb@streambuf@@IEAAXPEAD0H@Z"); SET(p_streambuf_setbuf, "?setbuf@streambuf@@UEAAPEAV1@PEADH@Z"); } else { SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE@PADH@Z"); SET(p_streambuf_ctor, "??0streambuf@@IAE@XZ"); SET(p_streambuf_dtor, "??1streambuf@@UAE@XZ"); + SET(p_streambuf_allocate, "?allocate@streambuf@@IAEHXZ"); + SET(p_streambuf_doallocate, "?doallocate@streambuf@@MAEHXZ"); SET(p_streambuf_setb, "?setb@streambuf@@IAEXPAD0H@Z"); SET(p_streambuf_setbuf, "?setbuf@streambuf@@UAEPAV1@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 %p-%p\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 %p-%p\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 3cefd74fe04..195cdf1acb0 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@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z @ cdecl -arch=win64 ?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z # @ extern ?adjustfield@ios@@2JB -@ stub -arch=win32 ?allocate@streambuf@@IAEHXZ -@ stub -arch=win64 ?allocate@streambuf@@IEAAHXZ +@ thiscall -arch=win32 ?allocate@streambuf@@IAEHXZ(ptr) msvcirt.?allocate@streambuf@@IAEHXZ +@ cdecl -arch=win64 ?allocate@streambuf@@IEAAHXZ(ptr) msvcirt.?allocate@streambuf@@IEAAHXZ @ stub -arch=win32 ?attach@filebuf@@QAEPAV1@H@Z @ stub -arch=win64 ?attach@filebuf@@QEAAPEAV1@H@Z @ stub -arch=win32 ?attach@fstream@@QAEXH@Z diff --git a/dlls/msvcrt40/msvcrt40.spec b/dlls/msvcrt40/msvcrt40.spec index 705521afaa8..0042f174abb 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@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z @ cdecl -arch=win64 ?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPEAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z # @ extern ?adjustfield@ios@@2JB -@ stub -arch=win32 ?allocate@streambuf@@IAEHXZ -@ stub -arch=win64 ?allocate@streambuf@@IEAAHXZ +@ thiscall -arch=win32 ?allocate@streambuf@@IAEHXZ(ptr) msvcirt.?allocate@streambuf@@IAEHXZ +@ cdecl -arch=win64 ?allocate@streambuf@@IEAAHXZ(ptr) msvcirt.?allocate@streambuf@@IEAAHXZ @ stub -arch=win32 ?attach@filebuf@@QAEPAV1@H@Z @ stub -arch=win64 ?attach@filebuf@@QEAAPEAV1@H@Z @ stub -arch=win32 ?attach@fstream@@QAEXH@Z