While implementing ifstream::setbuf() it turned out that filebuf::setbuf(), behaves a bit different on Windows than our implementation.
It seems to reimplement streambuf::setbuf() with a very minor difference - it doesn't ever set unbuffered to 0 and allows to change the underlying buffer as long as the file is not opened.
Test for how streambuf::setb() and both setbuf()s affect value of unbuffered are also included.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/msvcirt/msvcirt.c | 24 ++++++++++++--- dlls/msvcirt/tests/msvcirt.c | 60 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index 7e1d9977b78..ab40ad36a28 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -1175,16 +1175,30 @@ streampos __thiscall filebuf_seekoff(filebuf *this, streamoff offset, ios_seek_d DEFINE_THISCALL_WRAPPER(filebuf_setbuf, 12) streambuf* __thiscall filebuf_setbuf(filebuf *this, char *buffer, int length) { - streambuf *ret; - TRACE("(%p %p %d)\n", this, buffer, length); - if (this->base.base != NULL) + + if (filebuf_is_open(this) && this->base.base != NULL) return NULL;
streambuf_lock(&this->base); - ret = streambuf_setbuf(&this->base, buffer, length); + + if (buffer == NULL || !length) { + this->base.unbuffered = 1; + } else { + + if (this->base.allocated) + { + MSVCRT_operator_delete(this->base.base); + this->base.allocated = 0; + } + + this->base.base = buffer; + this->base.ebuf = buffer + length; + } + streambuf_unlock(&this->base); - return ret; + + return &this->base; }
/* ?setmode@filebuf@@QAEHH@Z */ diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index 4f9f859a861..a21ac20267c 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -1168,16 +1168,22 @@ static void test_streambuf(void) sb.do_lock = -1;
/* setb */ + sb.unbuffered = 1; call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 0); + ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered); 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); call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 4); + ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered); ok(sb.allocated == 4, "wrong allocate value, expected 4 got %d\n", sb.allocated); sb.allocated = 0; + sb.unbuffered = 0; call_func4(p_streambuf_setb, &sb, NULL, NULL, 3); + ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered); ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
/* setbuf */ + sb.unbuffered = 0; psb = call_func3(p_streambuf_setbuf, &sb, NULL, 5); ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb); ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated); @@ -1659,21 +1665,75 @@ static void test_filebuf(void)
/* setbuf */ fb1.base.do_lock = 0; + fb1.fd = -1; /* closed */ + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", fb1.base.unbuffered); + ok(fb1.fd == -1, "wrong fd, expected 1 got %d\n", fb1.fd); + fb1.base.unbuffered = 1; pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer, 16); ok(pret == &fb1, "wrong return, expected %p got %p\n", &fb1, pret); ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer + 8, 8); + ok(pret == &fb1, "wrong return, expected %p got %p\n", NULL, pret); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer + 8, "wrong buffer, expected %p got %p\n", read_buffer + 8, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + fb1.base.unbuffered = 0; + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, NULL, 0); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer + 8, "wrong buffer, expected %p got %p\n", read_buffer + 8, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + ok((int) call_func1(p_streambuf_doallocate, &fb1.base) == 1, "failed to allocate buffer\n"); + ok(fb1.base.allocated == 1, "wrong allocate value, expected 1 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base != NULL, "wrong buffer, expected not NULL got %p\n", fb1.base.base); + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer + 2, 14); + ok(pret == &fb1, "wrong return, expected %p got %p\n", &fb1, pret); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer + 2, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + fb1.fd = 1; /* opened */ + fb1.base.unbuffered = 1; + fb1.base.base = fb1.base.ebuf = NULL; + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer, 16); + ok(pret == &fb1, "wrong return, expected %p got %p\n", &fb1, pret); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer + 8, 8); + ok(pret == NULL, "wrong return, expected %p got %p\n", NULL, pret); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); + ok(fb1.base.base == read_buffer, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); + ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + fb1.base.unbuffered = 0; + pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, NULL, 0); + ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", fb1.base.unbuffered); ok(fb1.base.base == read_buffer, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); ok(fb1.base.pbase == NULL, "wrong put area, expected %p got %p\n", NULL, fb1.base.pbase); + fb1.base.unbuffered = 1; fb1.base.pbase = fb1.base.pptr = fb1.base.base; fb1.base.epptr = fb1.base.ebuf; fb1.base.do_lock = -1; pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer, 16); ok(pret == NULL, "wrong return, expected %p got %p\n", NULL, pret); ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated); + ok(fb1.base.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", fb1.base.unbuffered); ok(fb1.base.base == read_buffer, "wrong buffer, expected %p got %p\n", read_buffer, fb1.base.base); ok(fb1.base.pbase == read_buffer, "wrong put area, expected %p got %p\n", read_buffer, fb1.base.pbase); fb1.base.base = fb1.base.ebuf = NULL; fb1.base.do_lock = 0; + fb1.base.unbuffered = 0; pret = (filebuf*) call_func3(p_filebuf_setbuf, &fb1, read_buffer, 0); ok(pret == &fb1, "wrong return, expected %p got %p\n", &fb1, pret); ok(fb1.base.allocated == 0, "wrong allocate value, expected 0 got %d\n", fb1.base.allocated);
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/msvcirt/msvcirt.c | 19 +++++ dlls/msvcirt/msvcirt.spec | 4 +- dlls/msvcirt/tests/msvcirt.c | 130 +++++++++++++++++++++++++++++++++++ dlls/msvcrt20/msvcrt20.spec | 4 +- dlls/msvcrt40/msvcrt40.spec | 4 +- 5 files changed, 155 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c index ab40ad36a28..3bd43d24709 100644 --- a/dlls/msvcirt/msvcirt.c +++ b/dlls/msvcirt/msvcirt.c @@ -4278,6 +4278,25 @@ void __thiscall ifstream_open(istream *this, const char *name, ios_open_mode mod ios_clear(base, base->state | IOSTATE_failbit); }
+/* ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z */ +/* ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z */ +DEFINE_THISCALL_WRAPPER(ifstream_setbuf, 12) +streambuf* __thiscall ifstream_setbuf(istream *this, char *buffer, int length) +{ + ios *base = istream_get_ios(this); + filebuf* fb = ifstream_rdbuf(this); + + TRACE("(%p %p %d)\n", this, buffer, length); + + if (filebuf_is_open(fb)) + { + ios_clear(base, base->state | IOSTATE_failbit); + return NULL; + } + + return filebuf_setbuf(fb, buffer, length); +} + /* ?setmode@ifstream@@QAEHH@Z */ /* ?setmode@ifstream@@QEAAHH@Z */ DEFINE_THISCALL_WRAPPER(ifstream_setmode, 8) diff --git a/dlls/msvcirt/msvcirt.spec b/dlls/msvcirt/msvcirt.spec index 75ae312b486..c2b4b9d30eb 100644 --- a/dlls/msvcirt/msvcirt.spec +++ b/dlls/msvcirt/msvcirt.spec @@ -663,8 +663,8 @@ @ cdecl -arch=win64 ?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) filebuf_setbuf @ stub -arch=win32 ?setbuf@fstream@@QAEPAVstreambuf@@PADH@Z # class streambuf * __thiscall fstream::setbuf(char *,int) @ stub -arch=win64 ?setbuf@fstream@@QEAAPEAVstreambuf@@PEADH@Z -@ stub -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z # class streambuf * __thiscall ifstream::setbuf(char *,int) -@ stub -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z +@ thiscall -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z(ptr ptr long) ifstream_setbuf +@ cdecl -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) ifstream_setbuf @ stub -arch=win32 ?setbuf@ofstream@@QAEPAVstreambuf@@PADH@Z # class streambuf * __thiscall ofstream::setbuf(char *,int) @ stub -arch=win64 ?setbuf@ofstream@@QEAAPEAVstreambuf@@PEADH@Z @ thiscall -arch=win32 ?setbuf@streambuf@@UAEPAV1@PADH@Z(ptr ptr long) streambuf_setbuf diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c index a21ac20267c..d411e606f2e 100644 --- a/dlls/msvcirt/tests/msvcirt.c +++ b/dlls/msvcirt/tests/msvcirt.c @@ -418,6 +418,7 @@ static filedesc (*__thiscall p_ifstream_fd)(istream*); static int (*__thiscall p_ifstream_is_open)(const istream*); static void (*__thiscall p_ifstream_open)(istream*, const char*, ios_open_mode, int); static filebuf* (*__thiscall p_ifstream_rdbuf)(const istream*); +static streambuf* (*__thiscall p_ifstream_setbuf)(istream*, char*, int); static int (*__thiscall p_ifstream_setmode)(istream*, int);
/* strstream */ @@ -733,6 +734,7 @@ static BOOL init(void) SET(p_ifstream_is_open, "?is_open@ifstream@@QEBAHXZ"); SET(p_ifstream_open, "?open@ifstream@@QEAAXPEBDHH@Z"); SET(p_ifstream_rdbuf, "?rdbuf@ifstream@@QEBAPEAVfilebuf@@XZ"); + SET(p_ifstream_setbuf, "?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z"); SET(p_ifstream_setmode, "?setmode@ifstream@@QEAAHH@Z");
SET(p_strstream_copy_ctor, "??0strstream@@QEAA@AEBV0@@Z"); @@ -962,6 +964,7 @@ static BOOL init(void) SET(p_ifstream_is_open, "?is_open@ifstream@@QBEHXZ"); SET(p_ifstream_open, "?open@ifstream@@QAEXPBDHH@Z"); SET(p_ifstream_rdbuf, "?rdbuf@ifstream@@QBEPAVfilebuf@@XZ"); + SET(p_ifstream_setbuf, "?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z"); SET(p_ifstream_setmode, "?setmode@ifstream@@QAEHH@Z");
SET(p_strstream_copy_ctor, "??0strstream@@QAE@ABV0@@Z"); @@ -6831,6 +6834,7 @@ static void test_ifstream(void) { const char *filename = "ifstream_test"; istream ifs, ifs_copy, *pifs; + streambuf *psb; filebuf *pfb; char buffer[64]; char st[8]; @@ -6926,6 +6930,132 @@ static void test_ifstream(void) call_func1(p_ifstream_vbase_dtor, &ifs); ok(_close(fd) == -1, "expected ifstream to close opened file\n");
+ /* setbuf */ + call_func5(p_ifstream_buffer_ctor, &ifs, -1, NULL, 0, TRUE); + ok(ifs.base_ios.sb->base == NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", pfb->base.unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + + psb = call_func3(p_ifstream_setbuf, &ifs, buffer, ARRAY_SIZE(buffer)); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer, "wrong buffer, expected %p got %p\n", buffer, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, NULL, 0); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer, "wrong buffer, expected %p got %p\n", buffer, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + call_func1(p_ifstream_vbase_dtor, &ifs); + + call_func2(p_ifstream_ctor, &ifs, TRUE); + ok(ifs.base_ios.sb->base == NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 0, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, buffer, ARRAY_SIZE(buffer)); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer, "wrong buffer, expected %p got %p\n", buffer, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, NULL, 0); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer, "wrong buffer, expected %p got %p\n", buffer, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, buffer + 8, ARRAY_SIZE(buffer) - 8); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer + 8, "wrong buffer, expected %p got %p\n", buffer + 8, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, buffer + 8, 0); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer + 8, "wrong buffer, expected %p got %p\n", buffer + 8, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, buffer + 4, ARRAY_SIZE(buffer) - 4); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer + 4, "wrong buffer, expected %p got %p\n", buffer + 4, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + + psb = call_func3(p_ifstream_setbuf, &ifs, NULL, 5); + ok(psb == ifs.base_ios.sb, "wrong return, expected %p got %p\n", ifs.base_ios.sb, psb); + ok(ifs.base_ios.sb->base == buffer + 4, "wrong buffer, expected %p got %p\n", buffer + 4, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == buffer + ARRAY_SIZE(buffer), "wrong ebuf, expected %p got %p\n", buffer + ARRAY_SIZE(buffer), ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == IOSTATE_goodbit, "expected %d got %d\n", IOSTATE_goodbit, ifs.base_ios.state); + call_func1(p_ifstream_vbase_dtor, &ifs); + + /* setbuf - seems to be a nop and always return NULL in those other cases */ + pifs = call_func5(p_ifstream_buffer_ctor, &ifs, 42, NULL, 0, TRUE); + ok(ifs.base_ios.sb->base == NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + + ifs.base_ios.state = IOSTATE_eofbit; + psb = call_func3(p_ifstream_setbuf, &ifs, buffer, ARRAY_SIZE(buffer)); + ok(psb == NULL, "wrong return, expected NULL got %p\n", psb); + ok(ifs.base_ios.sb->base == NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == (IOSTATE_eofbit | IOSTATE_failbit), "attaching on already setup stream did not set failbit\n"); + + ifs.base_ios.state = IOSTATE_eofbit; + psb = call_func3(p_ifstream_setbuf, &ifs, NULL, 0); + ok(psb == NULL, "wrong return, expected NULL got %p\n", psb); + ok(ifs.base_ios.sb->base == NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf == NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 0, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == (IOSTATE_eofbit | IOSTATE_failbit), "attaching on already setup stream did not set failbit\n"); + call_func1(p_ifstream_vbase_dtor, &ifs); + + pifs = call_func5(p_ifstream_open_ctor, &ifs, filename, OPENMODE_in, filebuf_openprot, TRUE); + ifs.base_ios.state = IOSTATE_eofbit; + psb = call_func3(p_ifstream_setbuf, &ifs, NULL, 0); + ok(psb == NULL, "wrong return, expected NULL got %p\n", psb); + ok(ifs.base_ios.sb->base != NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->ebuf != NULL, "wrong ebuf value, expected NULL got %p\n", ifs.base_ios.sb->ebuf); + ok(ifs.base_ios.sb->unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 1, "wrong allocated value, expected 1 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == (IOSTATE_eofbit | IOSTATE_failbit), "attaching on already setup stream did not set failbit\n"); + + ifs.base_ios.state = IOSTATE_eofbit; + psb = call_func3(p_ifstream_setbuf, &ifs, buffer, ARRAY_SIZE(buffer)); + ok(psb == NULL, "wrong return, expected NULL got %p\n", psb); + ok(ifs.base_ios.sb->base != NULL, "wrong base value, expected NULL got %p\n", ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->base != buffer, "wrong base value, expected not %p got %p\n", buffer, ifs.base_ios.sb->base); + ok(ifs.base_ios.sb->unbuffered == 0, "wrong unbuffered value, expected 1 got %d\n", ifs.base_ios.sb->unbuffered); + ok(ifs.base_ios.sb->allocated == 1, "wrong allocated value, expected 0 got %d\n", ifs.base_ios.sb->allocated); + ok(ifs.base_ios.state == (IOSTATE_eofbit | IOSTATE_failbit), "attaching on already setup stream did not set failbit\n"); + call_func1(p_ifstream_vbase_dtor, &ifs); + /* attach */ pifs = call_func2(p_ifstream_ctor, &ifs, TRUE); pfb = (filebuf*) ifs.base_ios.sb; diff --git a/dlls/msvcrt20/msvcrt20.spec b/dlls/msvcrt20/msvcrt20.spec index 96c6c681478..2ce72c6b13c 100644 --- a/dlls/msvcrt20/msvcrt20.spec +++ b/dlls/msvcrt20/msvcrt20.spec @@ -651,8 +651,8 @@ @ cdecl -arch=win64 ?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) msvcirt.?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z @ stub -arch=win32 ?setbuf@fstream@@QAEPAVstreambuf@@PADH@Z @ stub -arch=win64 ?setbuf@fstream@@QEAAPEAVstreambuf@@PEADH@Z -@ stub -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z -@ stub -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z +@ thiscall -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z(ptr ptr long) msvcirt.?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z +@ cdecl -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) msvcirt.?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z @ stub -arch=win32 ?setbuf@ofstream@@QAEPAVstreambuf@@PADH@Z @ stub -arch=win64 ?setbuf@ofstream@@QEAAPEAVstreambuf@@PEADH@Z @ thiscall -arch=win32 ?setbuf@streambuf@@UAEPAV1@PADH@Z(ptr ptr long) msvcirt.?setbuf@streambuf@@UAEPAV1@PADH@Z diff --git a/dlls/msvcrt40/msvcrt40.spec b/dlls/msvcrt40/msvcrt40.spec index 6a2c9a7e52e..efa3e3251d6 100644 --- a/dlls/msvcrt40/msvcrt40.spec +++ b/dlls/msvcrt40/msvcrt40.spec @@ -723,8 +723,8 @@ @ cdecl -arch=win64 ?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) msvcirt.?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z @ stub -arch=win32 ?setbuf@fstream@@QAEPAVstreambuf@@PADH@Z @ stub -arch=win64 ?setbuf@fstream@@QEAAPEAVstreambuf@@PEADH@Z -@ stub -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z -@ stub -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z +@ thiscall -arch=win32 ?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z(ptr ptr long) msvcirt.?setbuf@ifstream@@QAEPAVstreambuf@@PADH@Z +@ cdecl -arch=win64 ?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z(ptr ptr long) msvcirt.?setbuf@ifstream@@QEAAPEAVstreambuf@@PEADH@Z @ stub -arch=win32 ?setbuf@ofstream@@QAEPAVstreambuf@@PADH@Z @ stub -arch=win64 ?setbuf@ofstream@@QEAAPEAVstreambuf@@PEADH@Z @ thiscall -arch=win32 ?setbuf@streambuf@@UAEPAV1@PADH@Z(ptr ptr long) msvcirt.?setbuf@streambuf@@UAEPAV1@PADH@Z