msvcirt: Implement stdiobuf::underflow.
[wine.git] / dlls / msvcirt / msvcirt.c
blob2b54f5bd48f27121589b1e5a2593ec8d9db81000
1 /*
2 * Copyright (C) 2007 Alexandre Julliard
3 * Copyright (C) 2015 Iván Matellanes
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
22 #include <fcntl.h>
23 #include <io.h>
24 #include <share.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <sys/stat.h>
29 #include "msvcirt.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcirt);
36 #define RESERVE_SIZE 512
37 #define STATEBUF_SIZE 8
39 /* ?sh_none@filebuf@@2HB */
40 const int filebuf_sh_none = 0x800;
41 /* ?sh_read@filebuf@@2HB */
42 const int filebuf_sh_read = 0xa00;
43 /* ?sh_write@filebuf@@2HB */
44 const int filebuf_sh_write = 0xc00;
45 /* ?openprot@filebuf@@2HB */
46 const int filebuf_openprot = 420;
47 /* ?binary@filebuf@@2HB */
48 const int filebuf_binary = _O_BINARY;
49 /* ?text@filebuf@@2HB */
50 const int filebuf_text = _O_TEXT;
52 /* ?adjustfield@ios@@2JB */
53 const LONG ios_adjustfield = FLAGS_left | FLAGS_right | FLAGS_internal;
54 /* ?basefield@ios@@2JB */
55 const LONG ios_basefield = FLAGS_dec | FLAGS_oct | FLAGS_hex;
56 /* ?floatfield@ios@@2JB */
57 const LONG ios_floatfield = FLAGS_scientific | FLAGS_fixed;
58 /* ?fLockcInit@ios@@0HA */
59 /* FIXME: should be initialized to 0 and increased on construction of cin, cout, cerr and clog */
60 int ios_fLockcInit = 4;
61 /* ?x_lockc@ios@@0U_CRT_CRITICAL_SECTION@@A */
62 extern CRITICAL_SECTION ios_static_lock;
63 CRITICAL_SECTION_DEBUG ios_static_lock_debug =
65 0, 0, &ios_static_lock,
66 { &ios_static_lock_debug.ProcessLocksList, &ios_static_lock_debug.ProcessLocksList },
67 0, 0, { (DWORD_PTR)(__FILE__ ": ios_static_lock") }
69 CRITICAL_SECTION ios_static_lock = { &ios_static_lock_debug, -1, 0, 0, 0, 0 };
70 /* ?x_maxbit@ios@@0JA */
71 LONG ios_maxbit = 0x8000;
72 /* ?x_curindex@ios@@0HA */
73 int ios_curindex = -1;
74 /* ?x_statebuf@ios@@0PAJA */
75 LONG ios_statebuf[STATEBUF_SIZE] = {0};
77 /* class streambuf */
78 typedef struct {
79 const vtable_ptr *vtable;
80 int allocated;
81 int unbuffered;
82 int stored_char;
83 char *base;
84 char *ebuf;
85 char *pbase;
86 char *pptr;
87 char *epptr;
88 char *eback;
89 char *gptr;
90 char *egptr;
91 int do_lock;
92 CRITICAL_SECTION lock;
93 } streambuf;
95 void __thiscall streambuf_setb(streambuf*, char*, char*, int);
96 streambuf* __thiscall streambuf_setbuf(streambuf*, char*, int);
97 void __thiscall streambuf_setg(streambuf*, char*, char*, char*);
98 void __thiscall streambuf_setp(streambuf*, char*, char*);
100 /* class filebuf */
101 typedef struct {
102 streambuf base;
103 filedesc fd;
104 int close;
105 } filebuf;
107 filebuf* __thiscall filebuf_close(filebuf*);
109 /* class strstreambuf */
110 typedef struct {
111 streambuf base;
112 int dynamic;
113 int increase;
114 int unknown;
115 int constant;
116 allocFunction f_alloc;
117 freeFunction f_free;
118 } strstreambuf;
120 /* class stdiobuf */
121 typedef struct {
122 streambuf base;
123 FILE *file;
124 } stdiobuf;
126 /* class ios */
127 struct _ostream;
128 typedef struct {
129 const vtable_ptr *vtable;
130 streambuf *sb;
131 ios_io_state state;
132 int special[4];
133 int delbuf;
134 struct _ostream *tie;
135 ios_flags flags;
136 int precision;
137 char fill;
138 int width;
139 int do_lock;
140 CRITICAL_SECTION lock;
141 } ios;
143 ios* __thiscall ios_assign(ios*, const ios*);
144 int __thiscall ios_fail(const ios*);
145 void __cdecl ios_lock(ios*);
146 void __cdecl ios_lockc(void);
147 LONG __thiscall ios_setf_mask(ios*, LONG, LONG);
148 void __cdecl ios_unlock(ios*);
149 void __cdecl ios_unlockc(void);
151 /* class ostream */
152 typedef struct _ostream {
153 const vtable_ptr *vtable;
154 } ostream;
156 /* ??_7streambuf@@6B@ */
157 extern const vtable_ptr MSVCP_streambuf_vtable;
158 /* ??_7filebuf@@6B@ */
159 extern const vtable_ptr MSVCP_filebuf_vtable;
160 /* ??_7strstreambuf@@6B@ */
161 extern const vtable_ptr MSVCP_strstreambuf_vtable;
162 /* ??_7stdiobuf@@6B@ */
163 extern const vtable_ptr MSVCP_stdiobuf_vtable;
164 /* ??_7ios@@6B@ */
165 extern const vtable_ptr MSVCP_ios_vtable;
167 #ifndef __GNUC__
168 void __asm_dummy_vtables(void) {
169 #endif
170 __ASM_VTABLE(streambuf,
171 VTABLE_ADD_FUNC(streambuf_vector_dtor)
172 VTABLE_ADD_FUNC(streambuf_sync)
173 VTABLE_ADD_FUNC(streambuf_setbuf)
174 VTABLE_ADD_FUNC(streambuf_seekoff)
175 VTABLE_ADD_FUNC(streambuf_seekpos)
176 VTABLE_ADD_FUNC(streambuf_xsputn)
177 VTABLE_ADD_FUNC(streambuf_xsgetn)
178 VTABLE_ADD_FUNC(streambuf_overflow)
179 VTABLE_ADD_FUNC(streambuf_underflow)
180 VTABLE_ADD_FUNC(streambuf_pbackfail)
181 VTABLE_ADD_FUNC(streambuf_doallocate));
182 __ASM_VTABLE(filebuf,
183 VTABLE_ADD_FUNC(filebuf_vector_dtor)
184 VTABLE_ADD_FUNC(filebuf_sync)
185 VTABLE_ADD_FUNC(filebuf_setbuf)
186 VTABLE_ADD_FUNC(filebuf_seekoff)
187 VTABLE_ADD_FUNC(streambuf_seekpos)
188 VTABLE_ADD_FUNC(streambuf_xsputn)
189 VTABLE_ADD_FUNC(streambuf_xsgetn)
190 VTABLE_ADD_FUNC(filebuf_overflow)
191 VTABLE_ADD_FUNC(filebuf_underflow)
192 VTABLE_ADD_FUNC(streambuf_pbackfail)
193 VTABLE_ADD_FUNC(streambuf_doallocate));
194 __ASM_VTABLE(strstreambuf,
195 VTABLE_ADD_FUNC(strstreambuf_vector_dtor)
196 VTABLE_ADD_FUNC(strstreambuf_sync)
197 VTABLE_ADD_FUNC(strstreambuf_setbuf)
198 VTABLE_ADD_FUNC(strstreambuf_seekoff)
199 VTABLE_ADD_FUNC(streambuf_seekpos)
200 VTABLE_ADD_FUNC(streambuf_xsputn)
201 VTABLE_ADD_FUNC(streambuf_xsgetn)
202 VTABLE_ADD_FUNC(strstreambuf_overflow)
203 VTABLE_ADD_FUNC(strstreambuf_underflow)
204 VTABLE_ADD_FUNC(streambuf_pbackfail)
205 VTABLE_ADD_FUNC(strstreambuf_doallocate));
206 __ASM_VTABLE(stdiobuf,
207 VTABLE_ADD_FUNC(stdiobuf_vector_dtor)
208 VTABLE_ADD_FUNC(stdiobuf_sync)
209 VTABLE_ADD_FUNC(streambuf_setbuf)
210 VTABLE_ADD_FUNC(stdiobuf_seekoff)
211 VTABLE_ADD_FUNC(streambuf_seekpos)
212 VTABLE_ADD_FUNC(streambuf_xsputn)
213 VTABLE_ADD_FUNC(streambuf_xsgetn)
214 VTABLE_ADD_FUNC(stdiobuf_overflow)
215 VTABLE_ADD_FUNC(stdiobuf_underflow)
216 VTABLE_ADD_FUNC(stdiobuf_pbackfail)
217 VTABLE_ADD_FUNC(streambuf_doallocate));
218 __ASM_VTABLE(ios,
219 VTABLE_ADD_FUNC(ios_vector_dtor));
220 #ifndef __GNUC__
222 #endif
224 DEFINE_RTTI_DATA0(streambuf, 0, ".?AVstreambuf@@")
225 DEFINE_RTTI_DATA1(filebuf, 0, &streambuf_rtti_base_descriptor, ".?AVfilebuf@@")
226 DEFINE_RTTI_DATA1(strstreambuf, 0, &streambuf_rtti_base_descriptor, ".?AVstrstreambuf@@")
227 DEFINE_RTTI_DATA1(stdiobuf, 0, &streambuf_rtti_base_descriptor, ".?AVstdiobuf@@")
228 DEFINE_RTTI_DATA0(ios, 0, ".?AVios@@")
230 /* ??0streambuf@@IAE@PADH@Z */
231 /* ??0streambuf@@IEAA@PEADH@Z */
232 DEFINE_THISCALL_WRAPPER(streambuf_reserve_ctor, 12)
233 streambuf* __thiscall streambuf_reserve_ctor(streambuf *this, char *buffer, int length)
235 TRACE("(%p %p %d)\n", this, buffer, length);
236 this->vtable = &MSVCP_streambuf_vtable;
237 this->allocated = 0;
238 this->stored_char = EOF;
239 this->do_lock = -1;
240 this->base = NULL;
241 streambuf_setbuf(this, buffer, length);
242 streambuf_setg(this, NULL, NULL, NULL);
243 streambuf_setp(this, NULL, NULL);
244 InitializeCriticalSection(&this->lock);
245 return this;
248 /* ??0streambuf@@IAE@XZ */
249 /* ??0streambuf@@IEAA@XZ */
250 DEFINE_THISCALL_WRAPPER(streambuf_ctor, 4)
251 streambuf* __thiscall streambuf_ctor(streambuf *this)
253 streambuf_reserve_ctor(this, NULL, 0);
254 this->unbuffered = 0;
255 return this;
258 /* ??0streambuf@@QAE@ABV0@@Z */
259 /* ??0streambuf@@QEAA@AEBV0@@Z */
260 DEFINE_THISCALL_WRAPPER(streambuf_copy_ctor, 8)
261 streambuf* __thiscall streambuf_copy_ctor(streambuf *this, const streambuf *copy)
263 TRACE("(%p %p)\n", this, copy);
264 *this = *copy;
265 this->vtable = &MSVCP_streambuf_vtable;
266 return this;
269 /* ??1streambuf@@UAE@XZ */
270 /* ??1streambuf@@UEAA@XZ */
271 DEFINE_THISCALL_WRAPPER(streambuf_dtor, 4)
272 void __thiscall streambuf_dtor(streambuf *this)
274 TRACE("(%p)\n", this);
275 if (this->allocated)
276 MSVCRT_operator_delete(this->base);
277 DeleteCriticalSection(&this->lock);
280 /* ??4streambuf@@QAEAAV0@ABV0@@Z */
281 /* ??4streambuf@@QEAAAEAV0@AEBV0@@Z */
282 DEFINE_THISCALL_WRAPPER(streambuf_assign, 8)
283 streambuf* __thiscall streambuf_assign(streambuf *this, const streambuf *rhs)
285 streambuf_dtor(this);
286 return streambuf_copy_ctor(this, rhs);
289 /* ??_Estreambuf@@UAEPAXI@Z */
290 DEFINE_THISCALL_WRAPPER(streambuf_vector_dtor, 8)
291 #define call_streambuf_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0,\
292 streambuf*, (streambuf*, unsigned int), (this, flags))
293 streambuf* __thiscall streambuf_vector_dtor(streambuf *this, unsigned int flags)
295 TRACE("(%p %x)\n", this, flags);
296 if (flags & 2) {
297 /* we have an array, with the number of elements stored before the first object */
298 INT_PTR i, *ptr = (INT_PTR *)this-1;
300 for (i = *ptr-1; i >= 0; i--)
301 streambuf_dtor(this+i);
302 MSVCRT_operator_delete(ptr);
303 } else {
304 streambuf_dtor(this);
305 if (flags & 1)
306 MSVCRT_operator_delete(this);
308 return this;
311 /* ??_Gstreambuf@@UAEPAXI@Z */
312 DEFINE_THISCALL_WRAPPER(streambuf_scalar_dtor, 8)
313 streambuf* __thiscall streambuf_scalar_dtor(streambuf *this, unsigned int flags)
315 TRACE("(%p %x)\n", this, flags);
316 streambuf_dtor(this);
317 if (flags & 1) MSVCRT_operator_delete(this);
318 return this;
321 /* ?doallocate@streambuf@@MAEHXZ */
322 /* ?doallocate@streambuf@@MEAAHXZ */
323 DEFINE_THISCALL_WRAPPER(streambuf_doallocate, 4)
324 #define call_streambuf_doallocate(this) CALL_VTBL_FUNC(this, 40, int, (streambuf*), (this))
325 int __thiscall streambuf_doallocate(streambuf *this)
327 char *reserve;
329 TRACE("(%p)\n", this);
330 reserve = MSVCRT_operator_new(RESERVE_SIZE);
331 if (!reserve)
332 return EOF;
334 streambuf_setb(this, reserve, reserve + RESERVE_SIZE, 1);
335 return 1;
338 /* ?allocate@streambuf@@IAEHXZ */
339 /* ?allocate@streambuf@@IEAAHXZ */
340 DEFINE_THISCALL_WRAPPER(streambuf_allocate, 4)
341 int __thiscall streambuf_allocate(streambuf *this)
343 TRACE("(%p)\n", this);
344 if (this->base != NULL || this->unbuffered)
345 return 0;
346 return call_streambuf_doallocate(this);
349 /* ?base@streambuf@@IBEPADXZ */
350 /* ?base@streambuf@@IEBAPEADXZ */
351 DEFINE_THISCALL_WRAPPER(streambuf_base, 4)
352 char* __thiscall streambuf_base(const streambuf *this)
354 TRACE("(%p)\n", this);
355 return this->base;
358 /* ?blen@streambuf@@IBEHXZ */
359 /* ?blen@streambuf@@IEBAHXZ */
360 DEFINE_THISCALL_WRAPPER(streambuf_blen, 4)
361 int __thiscall streambuf_blen(const streambuf *this)
363 TRACE("(%p)\n", this);
364 return this->ebuf - this->base;
367 /* ?eback@streambuf@@IBEPADXZ */
368 /* ?eback@streambuf@@IEBAPEADXZ */
369 DEFINE_THISCALL_WRAPPER(streambuf_eback, 4)
370 char* __thiscall streambuf_eback(const streambuf *this)
372 TRACE("(%p)\n", this);
373 return this->eback;
376 /* ?ebuf@streambuf@@IBEPADXZ */
377 /* ?ebuf@streambuf@@IEBAPEADXZ */
378 DEFINE_THISCALL_WRAPPER(streambuf_ebuf, 4)
379 char* __thiscall streambuf_ebuf(const streambuf *this)
381 TRACE("(%p)\n", this);
382 return this->ebuf;
385 /* ?egptr@streambuf@@IBEPADXZ */
386 /* ?egptr@streambuf@@IEBAPEADXZ */
387 DEFINE_THISCALL_WRAPPER(streambuf_egptr, 4)
388 char* __thiscall streambuf_egptr(const streambuf *this)
390 TRACE("(%p)\n", this);
391 return this->egptr;
394 /* ?epptr@streambuf@@IBEPADXZ */
395 /* ?epptr@streambuf@@IEBAPEADXZ */
396 DEFINE_THISCALL_WRAPPER(streambuf_epptr, 4)
397 char* __thiscall streambuf_epptr(const streambuf *this)
399 TRACE("(%p)\n", this);
400 return this->epptr;
403 /* ?gptr@streambuf@@IBEPADXZ */
404 /* ?gptr@streambuf@@IEBAPEADXZ */
405 DEFINE_THISCALL_WRAPPER(streambuf_gptr, 4)
406 char* __thiscall streambuf_gptr(const streambuf *this)
408 TRACE("(%p)\n", this);
409 return this->gptr;
412 /* ?pbase@streambuf@@IBEPADXZ */
413 /* ?pbase@streambuf@@IEBAPEADXZ */
414 DEFINE_THISCALL_WRAPPER(streambuf_pbase, 4)
415 char* __thiscall streambuf_pbase(const streambuf *this)
417 TRACE("(%p)\n", this);
418 return this->pbase;
421 /* ?pptr@streambuf@@IBEPADXZ */
422 /* ?pptr@streambuf@@IEBAPEADXZ */
423 DEFINE_THISCALL_WRAPPER(streambuf_pptr, 4)
424 char* __thiscall streambuf_pptr(const streambuf *this)
426 TRACE("(%p)\n", this);
427 return this->pptr;
430 /* ?clrlock@streambuf@@QAEXXZ */
431 /* ?clrlock@streambuf@@QEAAXXZ */
432 DEFINE_THISCALL_WRAPPER(streambuf_clrlock, 4)
433 void __thiscall streambuf_clrlock(streambuf *this)
435 TRACE("(%p)\n", this);
436 if (this->do_lock <= 0)
437 this->do_lock++;
440 /* ?lock@streambuf@@QAEXXZ */
441 /* ?lock@streambuf@@QEAAXXZ */
442 DEFINE_THISCALL_WRAPPER(streambuf_lock, 4)
443 void __thiscall streambuf_lock(streambuf *this)
445 TRACE("(%p)\n", this);
446 if (this->do_lock < 0)
447 EnterCriticalSection(&this->lock);
450 /* ?lockptr@streambuf@@IAEPAU_CRT_CRITICAL_SECTION@@XZ */
451 /* ?lockptr@streambuf@@IEAAPEAU_CRT_CRITICAL_SECTION@@XZ */
452 DEFINE_THISCALL_WRAPPER(streambuf_lockptr, 4)
453 CRITICAL_SECTION* __thiscall streambuf_lockptr(streambuf *this)
455 TRACE("(%p)\n", this);
456 return &this->lock;
459 /* ?gbump@streambuf@@IAEXH@Z */
460 /* ?gbump@streambuf@@IEAAXH@Z */
461 DEFINE_THISCALL_WRAPPER(streambuf_gbump, 8)
462 void __thiscall streambuf_gbump(streambuf *this, int count)
464 TRACE("(%p %d)\n", this, count);
465 this->gptr += count;
468 /* ?pbump@streambuf@@IAEXH@Z */
469 /* ?pbump@streambuf@@IEAAXH@Z */
470 DEFINE_THISCALL_WRAPPER(streambuf_pbump, 8)
471 void __thiscall streambuf_pbump(streambuf *this, int count)
473 TRACE("(%p %d)\n", this, count);
474 this->pptr += count;
477 /* ?in_avail@streambuf@@QBEHXZ */
478 /* ?in_avail@streambuf@@QEBAHXZ */
479 DEFINE_THISCALL_WRAPPER(streambuf_in_avail, 4)
480 int __thiscall streambuf_in_avail(const streambuf *this)
482 TRACE("(%p)\n", this);
483 return this->egptr - this->gptr;
486 /* ?out_waiting@streambuf@@QBEHXZ */
487 /* ?out_waiting@streambuf@@QEBAHXZ */
488 DEFINE_THISCALL_WRAPPER(streambuf_out_waiting, 4)
489 int __thiscall streambuf_out_waiting(const streambuf *this)
491 TRACE("(%p)\n", this);
492 return this->pptr - this->pbase;
495 /* Unexported */
496 DEFINE_THISCALL_WRAPPER(streambuf_overflow, 8)
497 #define call_streambuf_overflow(this, c) CALL_VTBL_FUNC(this, 28, int, (streambuf*, int), (this, c))
498 int __thiscall streambuf_overflow(streambuf *this, int c)
500 ERR("overflow is not implemented in streambuf\n");
501 return EOF;
504 /* ?pbackfail@streambuf@@UAEHH@Z */
505 /* ?pbackfail@streambuf@@UEAAHH@Z */
506 DEFINE_THISCALL_WRAPPER(streambuf_pbackfail, 8)
507 #define call_streambuf_pbackfail(this, c) CALL_VTBL_FUNC(this, 36, int, (streambuf*, int), (this, c))
508 int __thiscall streambuf_pbackfail(streambuf *this, int c)
510 TRACE("(%p %d)\n", this, c);
511 if (this->gptr <= this->eback)
512 return EOF;
513 return *--this->gptr = c;
516 /* ?seekoff@streambuf@@UAEJJW4seek_dir@ios@@H@Z */
517 /* ?seekoff@streambuf@@UEAAJJW4seek_dir@ios@@H@Z */
518 DEFINE_THISCALL_WRAPPER(streambuf_seekoff, 16)
519 #define call_streambuf_seekoff(this, off, dir, mode) CALL_VTBL_FUNC(this, 12, streampos, (streambuf*, streamoff, ios_seek_dir, int), (this, off, dir, mode))
520 streampos __thiscall streambuf_seekoff(streambuf *this, streamoff offset, ios_seek_dir dir, int mode)
522 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
523 return EOF;
526 /* ?seekpos@streambuf@@UAEJJH@Z */
527 /* ?seekpos@streambuf@@UEAAJJH@Z */
528 DEFINE_THISCALL_WRAPPER(streambuf_seekpos, 12)
529 streampos __thiscall streambuf_seekpos(streambuf *this, streampos pos, int mode)
531 TRACE("(%p %d %d)\n", this, pos, mode);
532 return call_streambuf_seekoff(this, pos, SEEKDIR_beg, mode);
535 /* ?setb@streambuf@@IAEXPAD0H@Z */
536 /* ?setb@streambuf@@IEAAXPEAD0H@Z */
537 DEFINE_THISCALL_WRAPPER(streambuf_setb, 16)
538 void __thiscall streambuf_setb(streambuf *this, char *ba, char *eb, int delete)
540 TRACE("(%p %p %p %d)\n", this, ba, eb, delete);
541 if (this->allocated)
542 MSVCRT_operator_delete(this->base);
543 this->allocated = delete;
544 this->base = ba;
545 this->ebuf = eb;
548 /* ?setbuf@streambuf@@UAEPAV1@PADH@Z */
549 /* ?setbuf@streambuf@@UEAAPEAV1@PEADH@Z */
550 DEFINE_THISCALL_WRAPPER(streambuf_setbuf, 12)
551 streambuf* __thiscall streambuf_setbuf(streambuf *this, char *buffer, int length)
553 TRACE("(%p %p %d)\n", this, buffer, length);
554 if (this->base != NULL)
555 return NULL;
557 if (buffer == NULL || !length) {
558 this->unbuffered = 1;
559 this->base = this->ebuf = NULL;
560 } else {
561 this->unbuffered = 0;
562 this->base = buffer;
563 this->ebuf = buffer + length;
565 return this;
568 /* ?setg@streambuf@@IAEXPAD00@Z */
569 /* ?setg@streambuf@@IEAAXPEAD00@Z */
570 DEFINE_THISCALL_WRAPPER(streambuf_setg, 16)
571 void __thiscall streambuf_setg(streambuf *this, char *ek, char *gp, char *eg)
573 TRACE("(%p %p %p %p)\n", this, ek, gp, eg);
574 this->eback = ek;
575 this->gptr = gp;
576 this->egptr = eg;
579 /* ?setlock@streambuf@@QAEXXZ */
580 /* ?setlock@streambuf@@QEAAXXZ */
581 DEFINE_THISCALL_WRAPPER(streambuf_setlock, 4)
582 void __thiscall streambuf_setlock(streambuf *this)
584 TRACE("(%p)\n", this);
585 this->do_lock--;
588 /* ?setp@streambuf@@IAEXPAD0@Z */
589 /* ?setp@streambuf@@IEAAXPEAD0@Z */
590 DEFINE_THISCALL_WRAPPER(streambuf_setp, 12)
591 void __thiscall streambuf_setp(streambuf *this, char *pb, char *ep)
593 TRACE("(%p %p %p)\n", this, pb, ep);
594 this->pbase = this->pptr = pb;
595 this->epptr = ep;
598 /* ?sync@streambuf@@UAEHXZ */
599 /* ?sync@streambuf@@UEAAHXZ */
600 DEFINE_THISCALL_WRAPPER(streambuf_sync, 4)
601 #define call_streambuf_sync(this) CALL_VTBL_FUNC(this, 4, int, (streambuf*), (this))
602 int __thiscall streambuf_sync(streambuf *this)
604 TRACE("(%p)\n", this);
605 return (this->gptr >= this->egptr && this->pbase >= this->pptr) ? 0 : EOF;
608 /* ?unbuffered@streambuf@@IAEXH@Z */
609 /* ?unbuffered@streambuf@@IEAAXH@Z */
610 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_set, 8)
611 void __thiscall streambuf_unbuffered_set(streambuf *this, int buf)
613 TRACE("(%p %d)\n", this, buf);
614 this->unbuffered = buf;
617 /* ?unbuffered@streambuf@@IBEHXZ */
618 /* ?unbuffered@streambuf@@IEBAHXZ */
619 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_get, 4)
620 int __thiscall streambuf_unbuffered_get(const streambuf *this)
622 TRACE("(%p)\n", this);
623 return this->unbuffered;
626 /* Unexported */
627 DEFINE_THISCALL_WRAPPER(streambuf_underflow, 4)
628 #define call_streambuf_underflow(this) CALL_VTBL_FUNC(this, 32, int, (streambuf*), (this))
629 int __thiscall streambuf_underflow(streambuf *this)
631 ERR("underflow is not implemented in streambuf\n");
632 return EOF;
635 /* ?unlock@streambuf@@QAEXXZ */
636 /* ?unlock@streambuf@@QEAAXXZ */
637 DEFINE_THISCALL_WRAPPER(streambuf_unlock, 4)
638 void __thiscall streambuf_unlock(streambuf *this)
640 TRACE("(%p)\n", this);
641 if (this->do_lock < 0)
642 LeaveCriticalSection(&this->lock);
645 /* ?xsgetn@streambuf@@UAEHPADH@Z */
646 /* ?xsgetn@streambuf@@UEAAHPEADH@Z */
647 DEFINE_THISCALL_WRAPPER(streambuf_xsgetn, 12)
648 #define call_streambuf_xsgetn(this, buffer, count) CALL_VTBL_FUNC(this, 24, int, (streambuf*, char*, int), (this, buffer, count))
649 int __thiscall streambuf_xsgetn(streambuf *this, char *buffer, int count)
651 int copied = 0, chunk;
653 TRACE("(%p %p %d)\n", this, buffer, count);
655 if (this->unbuffered) {
656 if (this->stored_char == EOF)
657 this->stored_char = call_streambuf_underflow(this);
658 while (copied < count && this->stored_char != EOF) {
659 buffer[copied++] = this->stored_char;
660 this->stored_char = call_streambuf_underflow(this);
662 } else {
663 while (copied < count) {
664 if (call_streambuf_underflow(this) == EOF)
665 break;
666 chunk = this->egptr - this->gptr;
667 if (chunk > count - copied)
668 chunk = count - copied;
669 memcpy(buffer+copied, this->gptr, chunk);
670 this->gptr += chunk;
671 copied += chunk;
674 return copied;
677 /* ?xsputn@streambuf@@UAEHPBDH@Z */
678 /* ?xsputn@streambuf@@UEAAHPEBDH@Z */
679 DEFINE_THISCALL_WRAPPER(streambuf_xsputn, 12)
680 #define call_streambuf_xsputn(this, data, length) CALL_VTBL_FUNC(this, 20, int, (streambuf*, const char*, int), (this, data, length))
681 int __thiscall streambuf_xsputn(streambuf *this, const char *data, int length)
683 int copied = 0, chunk;
685 TRACE("(%p %p %d)\n", this, data, length);
687 while (copied < length) {
688 if (this->unbuffered || this->pptr == this->epptr) {
689 if (call_streambuf_overflow(this, data[copied]) == EOF)
690 break;
691 copied++;
692 } else {
693 chunk = this->epptr - this->pptr;
694 if (chunk > length - copied)
695 chunk = length - copied;
696 memcpy(this->pptr, data+copied, chunk);
697 this->pptr += chunk;
698 copied += chunk;
701 return copied;
704 /* ?sgetc@streambuf@@QAEHXZ */
705 /* ?sgetc@streambuf@@QEAAHXZ */
706 DEFINE_THISCALL_WRAPPER(streambuf_sgetc, 4)
707 int __thiscall streambuf_sgetc(streambuf *this)
709 TRACE("(%p)\n", this);
710 if (this->unbuffered) {
711 if (this->stored_char == EOF)
712 this->stored_char = call_streambuf_underflow(this);
713 return this->stored_char;
714 } else
715 return call_streambuf_underflow(this);
718 /* ?sputc@streambuf@@QAEHH@Z */
719 /* ?sputc@streambuf@@QEAAHH@Z */
720 DEFINE_THISCALL_WRAPPER(streambuf_sputc, 8)
721 int __thiscall streambuf_sputc(streambuf *this, int ch)
723 TRACE("(%p %d)\n", this, ch);
724 return (this->pptr < this->epptr) ? *this->pptr++ = ch : call_streambuf_overflow(this, ch);
727 /* ?sgetn@streambuf@@QAEHPADH@Z */
728 /* ?sgetn@streambuf@@QEAAHPEADH@Z */
729 DEFINE_THISCALL_WRAPPER(streambuf_sgetn, 12)
730 int __thiscall streambuf_sgetn(streambuf *this, char *buffer, int count)
732 return call_streambuf_xsgetn(this, buffer, count);
735 /* ?sputn@streambuf@@QAEHPBDH@Z */
736 /* ?sputn@streambuf@@QEAAHPEBDH@Z */
737 DEFINE_THISCALL_WRAPPER(streambuf_sputn, 12)
738 int __thiscall streambuf_sputn(streambuf *this, const char *data, int length)
740 return call_streambuf_xsputn(this, data, length);
743 /* ?snextc@streambuf@@QAEHXZ */
744 /* ?snextc@streambuf@@QEAAHXZ */
745 DEFINE_THISCALL_WRAPPER(streambuf_snextc, 4)
746 int __thiscall streambuf_snextc(streambuf *this)
748 TRACE("(%p)\n", this);
749 if (this->unbuffered) {
750 if (this->stored_char == EOF)
751 call_streambuf_underflow(this);
752 return this->stored_char = call_streambuf_underflow(this);
753 } else {
754 if (this->gptr >= this->egptr)
755 call_streambuf_underflow(this);
756 this->gptr++;
757 return (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
761 /* ?sbumpc@streambuf@@QAEHXZ */
762 /* ?sbumpc@streambuf@@QEAAHXZ */
763 DEFINE_THISCALL_WRAPPER(streambuf_sbumpc, 4)
764 int __thiscall streambuf_sbumpc(streambuf *this)
766 int ret;
768 TRACE("(%p)\n", this);
770 if (this->unbuffered) {
771 ret = this->stored_char;
772 this->stored_char = EOF;
773 if (ret == EOF)
774 ret = call_streambuf_underflow(this);
775 } else {
776 ret = (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
777 this->gptr++;
779 return ret;
782 /* ?stossc@streambuf@@QAEXXZ */
783 /* ?stossc@streambuf@@QEAAXXZ */
784 DEFINE_THISCALL_WRAPPER(streambuf_stossc, 4)
785 void __thiscall streambuf_stossc(streambuf *this)
787 TRACE("(%p)\n", this);
788 if (this->unbuffered) {
789 if (this->stored_char == EOF)
790 call_streambuf_underflow(this);
791 else
792 this->stored_char = EOF;
793 } else {
794 if (this->gptr >= this->egptr)
795 call_streambuf_underflow(this);
796 if (this->gptr < this->egptr)
797 this->gptr++;
801 /* ?sputbackc@streambuf@@QAEHD@Z */
802 /* ?sputbackc@streambuf@@QEAAHD@Z */
803 DEFINE_THISCALL_WRAPPER(streambuf_sputbackc, 8)
804 int __thiscall streambuf_sputbackc(streambuf *this, char ch)
806 TRACE("(%p %d)\n", this, ch);
807 return call_streambuf_pbackfail(this, ch);
810 /* ?dbp@streambuf@@QAEXXZ */
811 /* ?dbp@streambuf@@QEAAXXZ */
812 DEFINE_THISCALL_WRAPPER(streambuf_dbp, 4)
813 void __thiscall streambuf_dbp(streambuf *this)
815 printf("\nSTREAMBUF DEBUG INFO: this=%p, ", this);
816 if (this->unbuffered) {
817 printf("unbuffered\n");
818 } else {
819 printf("_fAlloc=%d\n", this->allocated);
820 printf(" base()=%p, ebuf()=%p, blen()=%d\n", this->base, this->ebuf, streambuf_blen(this));
821 printf("pbase()=%p, pptr()=%p, epptr()=%d\n", this->pbase, this->pptr, this->epptr);
822 printf("eback()=%p, gptr()=%p, egptr()=%d\n", this->eback, this->gptr, this->egptr);
826 /* ??0filebuf@@QAE@ABV0@@Z */
827 /* ??0filebuf@@QEAA@AEBV0@@Z */
828 DEFINE_THISCALL_WRAPPER(filebuf_copy_ctor, 8)
829 filebuf* __thiscall filebuf_copy_ctor(filebuf* this, const filebuf *copy)
831 TRACE("(%p %p)\n", this, copy);
832 *this = *copy;
833 this->base.vtable = &MSVCP_filebuf_vtable;
834 return this;
837 /* ??0filebuf@@QAE@HPADH@Z */
838 /* ??0filebuf@@QEAA@HPEADH@Z */
839 DEFINE_THISCALL_WRAPPER(filebuf_fd_reserve_ctor, 16)
840 filebuf* __thiscall filebuf_fd_reserve_ctor(filebuf* this, filedesc fd, char *buffer, int length)
842 TRACE("(%p %d %p %d)\n", this, fd, buffer, length);
843 streambuf_reserve_ctor(&this->base, buffer, length);
844 this->base.vtable = &MSVCP_filebuf_vtable;
845 this->fd = fd;
846 this->close = 0;
847 return this;
850 /* ??0filebuf@@QAE@H@Z */
851 /* ??0filebuf@@QEAA@H@Z */
852 DEFINE_THISCALL_WRAPPER(filebuf_fd_ctor, 8)
853 filebuf* __thiscall filebuf_fd_ctor(filebuf* this, filedesc fd)
855 filebuf_fd_reserve_ctor(this, fd, NULL, 0);
856 this->base.unbuffered = 0;
857 return this;
860 /* ??0filebuf@@QAE@XZ */
861 /* ??0filebuf@@QEAA@XZ */
862 DEFINE_THISCALL_WRAPPER(filebuf_ctor, 4)
863 filebuf* __thiscall filebuf_ctor(filebuf* this)
865 return filebuf_fd_ctor(this, -1);
868 /* ??1filebuf@@UAE@XZ */
869 /* ??1filebuf@@UEAA@XZ */
870 DEFINE_THISCALL_WRAPPER(filebuf_dtor, 4)
871 void __thiscall filebuf_dtor(filebuf* this)
873 TRACE("(%p)\n", this);
874 if (this->close)
875 filebuf_close(this);
876 streambuf_dtor(&this->base);
879 /* ??4filebuf@@QAEAAV0@ABV0@@Z */
880 /* ??4filebuf@@QEAAAEAV0@AEBV0@@Z */
881 DEFINE_THISCALL_WRAPPER(filebuf_assign, 8)
882 filebuf* __thiscall filebuf_assign(filebuf* this, const filebuf *rhs)
884 filebuf_dtor(this);
885 return filebuf_copy_ctor(this, rhs);
888 /* ??_Efilebuf@@UAEPAXI@Z */
889 DEFINE_THISCALL_WRAPPER(filebuf_vector_dtor, 8)
890 filebuf* __thiscall filebuf_vector_dtor(filebuf *this, unsigned int flags)
892 TRACE("(%p %x)\n", this, flags);
893 if (flags & 2) {
894 /* we have an array, with the number of elements stored before the first object */
895 INT_PTR i, *ptr = (INT_PTR *)this-1;
897 for (i = *ptr-1; i >= 0; i--)
898 filebuf_dtor(this+i);
899 MSVCRT_operator_delete(ptr);
900 } else {
901 filebuf_dtor(this);
902 if (flags & 1)
903 MSVCRT_operator_delete(this);
905 return this;
908 /* ??_Gfilebuf@@UAEPAXI@Z */
909 DEFINE_THISCALL_WRAPPER(filebuf_scalar_dtor, 8)
910 filebuf* __thiscall filebuf_scalar_dtor(filebuf *this, unsigned int flags)
912 TRACE("(%p %x)\n", this, flags);
913 filebuf_dtor(this);
914 if (flags & 1) MSVCRT_operator_delete(this);
915 return this;
918 /* ?attach@filebuf@@QAEPAV1@H@Z */
919 /* ?attach@filebuf@@QEAAPEAV1@H@Z */
920 DEFINE_THISCALL_WRAPPER(filebuf_attach, 8)
921 filebuf* __thiscall filebuf_attach(filebuf *this, filedesc fd)
923 TRACE("(%p %d)\n", this, fd);
924 if (this->fd != -1)
925 return NULL;
927 streambuf_lock(&this->base);
928 this->fd = fd;
929 streambuf_allocate(&this->base);
930 streambuf_unlock(&this->base);
931 return this;
934 /* ?close@filebuf@@QAEPAV1@XZ */
935 /* ?close@filebuf@@QEAAPEAV1@XZ */
936 DEFINE_THISCALL_WRAPPER(filebuf_close, 4)
937 filebuf* __thiscall filebuf_close(filebuf *this)
939 filebuf *ret;
941 TRACE("(%p)\n", this);
942 if (this->fd == -1)
943 return NULL;
945 streambuf_lock(&this->base);
946 if (call_streambuf_sync(&this->base) == EOF || _close(this->fd) < 0) {
947 ret = NULL;
948 } else {
949 this->fd = -1;
950 ret = this;
952 streambuf_unlock(&this->base);
953 return ret;
956 /* ?fd@filebuf@@QBEHXZ */
957 /* ?fd@filebuf@@QEBAHXZ */
958 DEFINE_THISCALL_WRAPPER(filebuf_fd, 4)
959 filedesc __thiscall filebuf_fd(const filebuf *this)
961 TRACE("(%p)\n", this);
962 return this->fd;
965 /* ?is_open@filebuf@@QBEHXZ */
966 /* ?is_open@filebuf@@QEBAHXZ */
967 DEFINE_THISCALL_WRAPPER(filebuf_is_open, 4)
968 int __thiscall filebuf_is_open(const filebuf *this)
970 TRACE("(%p)\n", this);
971 return this->fd != -1;
974 /* ?open@filebuf@@QAEPAV1@PBDHH@Z */
975 /* ?open@filebuf@@QEAAPEAV1@PEBDHH@Z */
976 DEFINE_THISCALL_WRAPPER(filebuf_open, 16)
977 filebuf* __thiscall filebuf_open(filebuf *this, const char *name, ios_open_mode mode, int protection)
979 const int inout_mode[4] = {-1, _O_RDONLY, _O_WRONLY, _O_RDWR};
980 const int share_mode[4] = {_SH_DENYRW, _SH_DENYWR, _SH_DENYRD, _SH_DENYNO};
981 int op_flags, sh_flags, fd;
983 TRACE("(%p %s %x %x)\n", this, name, mode, protection);
984 if (this->fd != -1)
985 return NULL;
987 /* mode */
988 if (mode & (OPENMODE_app|OPENMODE_trunc))
989 mode |= OPENMODE_out;
990 op_flags = inout_mode[mode & (OPENMODE_in|OPENMODE_out)];
991 if (op_flags < 0)
992 return NULL;
993 if (mode & OPENMODE_app)
994 op_flags |= _O_APPEND;
995 if ((mode & OPENMODE_trunc) ||
996 ((mode & OPENMODE_out) && !(mode & (OPENMODE_in|OPENMODE_app|OPENMODE_ate))))
997 op_flags |= _O_TRUNC;
998 if (!(mode & OPENMODE_nocreate))
999 op_flags |= _O_CREAT;
1000 if (mode & OPENMODE_noreplace)
1001 op_flags |= _O_EXCL;
1002 op_flags |= (mode & OPENMODE_binary) ? _O_BINARY : _O_TEXT;
1004 /* share protection */
1005 sh_flags = (protection & filebuf_sh_none) ? share_mode[(protection >> 9) & 3] : _SH_DENYNO;
1007 TRACE("op_flags %x, sh_flags %x\n", op_flags, sh_flags);
1008 fd = _sopen(name, op_flags, sh_flags, _S_IREAD|_S_IWRITE);
1009 if (fd < 0)
1010 return NULL;
1012 streambuf_lock(&this->base);
1013 this->close = 1;
1014 this->fd = fd;
1015 if ((mode & OPENMODE_ate) &&
1016 call_streambuf_seekoff(&this->base, 0, SEEKDIR_end, mode & (OPENMODE_in|OPENMODE_out)) == EOF) {
1017 _close(fd);
1018 this->fd = -1;
1020 streambuf_allocate(&this->base);
1021 streambuf_unlock(&this->base);
1022 return (this->fd == -1) ? NULL : this;
1025 /* ?overflow@filebuf@@UAEHH@Z */
1026 /* ?overflow@filebuf@@UEAAHH@Z */
1027 DEFINE_THISCALL_WRAPPER(filebuf_overflow, 8)
1028 int __thiscall filebuf_overflow(filebuf *this, int c)
1030 TRACE("(%p %d)\n", this, c);
1031 if (call_streambuf_sync(&this->base) == EOF)
1032 return EOF;
1033 if (this->base.unbuffered)
1034 return (c == EOF) ? 1 : _write(this->fd, &c, 1);
1035 if (streambuf_allocate(&this->base) == EOF)
1036 return EOF;
1038 this->base.pbase = this->base.pptr = this->base.base;
1039 this->base.epptr = this->base.ebuf;
1040 if (c != EOF)
1041 *this->base.pptr++ = c;
1042 return 1;
1045 /* ?seekoff@filebuf@@UAEJJW4seek_dir@ios@@H@Z */
1046 /* ?seekoff@filebuf@@UEAAJJW4seek_dir@ios@@H@Z */
1047 DEFINE_THISCALL_WRAPPER(filebuf_seekoff, 16)
1048 streampos __thiscall filebuf_seekoff(filebuf *this, streamoff offset, ios_seek_dir dir, int mode)
1050 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
1051 if (call_streambuf_sync(&this->base) == EOF)
1052 return EOF;
1053 return _lseek(this->fd, offset, dir);
1056 /* ?setbuf@filebuf@@UAEPAVstreambuf@@PADH@Z */
1057 /* ?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z */
1058 DEFINE_THISCALL_WRAPPER(filebuf_setbuf, 12)
1059 streambuf* __thiscall filebuf_setbuf(filebuf *this, char *buffer, int length)
1061 streambuf *ret;
1063 TRACE("(%p %p %d)\n", this, buffer, length);
1064 if (this->base.base != NULL)
1065 return NULL;
1067 streambuf_lock(&this->base);
1068 ret = streambuf_setbuf(&this->base, buffer, length);
1069 streambuf_unlock(&this->base);
1070 return ret;
1073 /* ?setmode@filebuf@@QAEHH@Z */
1074 /* ?setmode@filebuf@@QEAAHH@Z */
1075 DEFINE_THISCALL_WRAPPER(filebuf_setmode, 8)
1076 int __thiscall filebuf_setmode(filebuf *this, int mode)
1078 int ret;
1080 TRACE("(%p %d)\n", this, mode);
1081 if (mode != filebuf_text && mode != filebuf_binary)
1082 return -1;
1084 streambuf_lock(&this->base);
1085 ret = (call_streambuf_sync(&this->base) == EOF) ? -1 : _setmode(this->fd, mode);
1086 streambuf_unlock(&this->base);
1087 return ret;
1090 /* ?sync@filebuf@@UAEHXZ */
1091 /* ?sync@filebuf@@UEAAHXZ */
1092 DEFINE_THISCALL_WRAPPER(filebuf_sync, 4)
1093 int __thiscall filebuf_sync(filebuf *this)
1095 int count, mode;
1096 char *ptr;
1097 LONG offset;
1099 TRACE("(%p)\n", this);
1100 if (this->fd == -1)
1101 return EOF;
1102 if (this->base.unbuffered)
1103 return 0;
1105 /* flush output buffer */
1106 if (this->base.pptr != NULL) {
1107 count = this->base.pptr - this->base.pbase;
1108 if (count > 0 && _write(this->fd, this->base.pbase, count) != count)
1109 return EOF;
1110 this->base.pbase = this->base.pptr = this->base.epptr = NULL;
1112 /* flush input buffer */
1113 if (this->base.egptr != NULL) {
1114 offset = this->base.egptr - this->base.gptr;
1115 if (offset > 0) {
1116 mode = _setmode(this->fd, _O_TEXT);
1117 _setmode(this->fd, mode);
1118 if (mode & _O_TEXT) {
1119 /* in text mode, '\n' in the buffer means '\r\n' in the file */
1120 for (ptr = this->base.gptr; ptr < this->base.egptr; ptr++)
1121 if (*ptr == '\n')
1122 offset++;
1124 if (_lseek(this->fd, -offset, SEEK_CUR) < 0)
1125 return EOF;
1127 this->base.eback = this->base.gptr = this->base.egptr = NULL;
1129 return 0;
1132 /* ?underflow@filebuf@@UAEHXZ */
1133 /* ?underflow@filebuf@@UEAAHXZ */
1134 DEFINE_THISCALL_WRAPPER(filebuf_underflow, 4)
1135 int __thiscall filebuf_underflow(filebuf *this)
1137 int buffer_size, read_bytes;
1138 char c;
1140 TRACE("(%p)\n", this);
1142 if (this->base.unbuffered)
1143 return (_read(this->fd, &c, 1) < 1) ? EOF : c;
1145 if (this->base.gptr >= this->base.egptr) {
1146 if (call_streambuf_sync(&this->base) == EOF)
1147 return EOF;
1148 buffer_size = this->base.ebuf - this->base.base;
1149 read_bytes = _read(this->fd, this->base.base, buffer_size);
1150 if (read_bytes <= 0)
1151 return EOF;
1152 this->base.eback = this->base.gptr = this->base.base;
1153 this->base.egptr = this->base.base + read_bytes;
1155 return *this->base.gptr;
1158 /* ??0strstreambuf@@QAE@ABV0@@Z */
1159 /* ??0strstreambuf@@QEAA@AEBV0@@Z */
1160 DEFINE_THISCALL_WRAPPER(strstreambuf_copy_ctor, 8)
1161 strstreambuf* __thiscall strstreambuf_copy_ctor(strstreambuf *this, const strstreambuf *copy)
1163 TRACE("(%p %p)\n", this, copy);
1164 *this = *copy;
1165 this->base.vtable = &MSVCP_strstreambuf_vtable;
1166 return this;
1169 /* ??0strstreambuf@@QAE@H@Z */
1170 /* ??0strstreambuf@@QEAA@H@Z */
1171 DEFINE_THISCALL_WRAPPER(strstreambuf_dynamic_ctor, 8)
1172 strstreambuf* __thiscall strstreambuf_dynamic_ctor(strstreambuf* this, int length)
1174 TRACE("(%p %d)\n", this, length);
1175 streambuf_ctor(&this->base);
1176 this->base.vtable = &MSVCP_strstreambuf_vtable;
1177 this->dynamic = 1;
1178 this->increase = length;
1179 this->constant = 0;
1180 this->f_alloc = NULL;
1181 this->f_free = NULL;
1182 return this;
1185 /* ??0strstreambuf@@QAE@P6APAXJ@ZP6AXPAX@Z@Z */
1186 /* ??0strstreambuf@@QEAA@P6APEAXJ@ZP6AXPEAX@Z@Z */
1187 DEFINE_THISCALL_WRAPPER(strstreambuf_funcs_ctor, 12)
1188 strstreambuf* __thiscall strstreambuf_funcs_ctor(strstreambuf* this, allocFunction falloc, freeFunction ffree)
1190 TRACE("(%p %p %p)\n", this, falloc, ffree);
1191 strstreambuf_dynamic_ctor(this, 1);
1192 this->f_alloc = falloc;
1193 this->f_free = ffree;
1194 return this;
1197 /* ??0strstreambuf@@QAE@PADH0@Z */
1198 /* ??0strstreambuf@@QEAA@PEADH0@Z */
1199 DEFINE_THISCALL_WRAPPER(strstreambuf_buffer_ctor, 16)
1200 strstreambuf* __thiscall strstreambuf_buffer_ctor(strstreambuf *this, char *buffer, int length, char *put)
1202 char *end_buffer;
1204 TRACE("(%p %p %d %p)\n", this, buffer, length, put);
1206 if (length > 0)
1207 end_buffer = buffer + length;
1208 else if (length == 0)
1209 end_buffer = buffer + strlen(buffer);
1210 else
1211 end_buffer = (char*) -1;
1213 streambuf_ctor(&this->base);
1214 streambuf_setb(&this->base, buffer, end_buffer, 0);
1215 if (put == NULL) {
1216 streambuf_setg(&this->base, buffer, buffer, end_buffer);
1217 } else {
1218 streambuf_setg(&this->base, buffer, buffer, put);
1219 streambuf_setp(&this->base, put, end_buffer);
1221 this->base.vtable = &MSVCP_strstreambuf_vtable;
1222 this->dynamic = 0;
1223 this->constant = 1;
1224 return this;
1227 /* ??0strstreambuf@@QAE@PAEH0@Z */
1228 /* ??0strstreambuf@@QEAA@PEAEH0@Z */
1229 DEFINE_THISCALL_WRAPPER(strstreambuf_ubuffer_ctor, 16)
1230 strstreambuf* __thiscall strstreambuf_ubuffer_ctor(strstreambuf *this, unsigned char *buffer, int length, unsigned char *put)
1232 TRACE("(%p %p %d %p)\n", this, buffer, length, put);
1233 return strstreambuf_buffer_ctor(this, (char*)buffer, length, (char*)put);
1236 /* ??0strstreambuf@@QAE@XZ */
1237 /* ??0strstreambuf@@QEAA@XZ */
1238 DEFINE_THISCALL_WRAPPER(strstreambuf_ctor, 4)
1239 strstreambuf* __thiscall strstreambuf_ctor(strstreambuf *this)
1241 TRACE("(%p)\n", this);
1242 return strstreambuf_dynamic_ctor(this, 1);
1245 /* ??1strstreambuf@@UAE@XZ */
1246 /* ??1strstreambuf@@UEAA@XZ */
1247 DEFINE_THISCALL_WRAPPER(strstreambuf_dtor, 4)
1248 void __thiscall strstreambuf_dtor(strstreambuf *this)
1250 TRACE("(%p)\n", this);
1251 if (this->dynamic && this->base.base) {
1252 if (this->f_free)
1253 this->f_free(this->base.base);
1254 else
1255 MSVCRT_operator_delete(this->base.base);
1257 streambuf_dtor(&this->base);
1260 /* ??4strstreambuf@@QAEAAV0@ABV0@@Z */
1261 /* ??4strstreambuf@@QEAAAEAV0@AEBV0@@Z */
1262 DEFINE_THISCALL_WRAPPER(strstreambuf_assign, 8)
1263 strstreambuf* __thiscall strstreambuf_assign(strstreambuf *this, const strstreambuf *rhs)
1265 strstreambuf_dtor(this);
1266 return strstreambuf_copy_ctor(this, rhs);
1269 /* ??_Estrstreambuf@@UAEPAXI@Z */
1270 DEFINE_THISCALL_WRAPPER(strstreambuf_vector_dtor, 8)
1271 strstreambuf* __thiscall strstreambuf_vector_dtor(strstreambuf *this, unsigned int flags)
1273 TRACE("(%p %x)\n", this, flags);
1274 if (flags & 2) {
1275 /* we have an array, with the number of elements stored before the first object */
1276 INT_PTR i, *ptr = (INT_PTR *)this-1;
1278 for (i = *ptr-1; i >= 0; i--)
1279 strstreambuf_dtor(this+i);
1280 MSVCRT_operator_delete(ptr);
1281 } else {
1282 strstreambuf_dtor(this);
1283 if (flags & 1)
1284 MSVCRT_operator_delete(this);
1286 return this;
1289 /* ??_Gstrstreambuf@@UAEPAXI@Z */
1290 DEFINE_THISCALL_WRAPPER(strstreambuf_scalar_dtor, 8)
1291 strstreambuf* __thiscall strstreambuf_scalar_dtor(strstreambuf *this, unsigned int flags)
1293 TRACE("(%p %x)\n", this, flags);
1294 strstreambuf_dtor(this);
1295 if (flags & 1) MSVCRT_operator_delete(this);
1296 return this;
1299 /* ?doallocate@strstreambuf@@MAEHXZ */
1300 /* ?doallocate@strstreambuf@@MEAAHXZ */
1301 DEFINE_THISCALL_WRAPPER(strstreambuf_doallocate, 4)
1302 int __thiscall strstreambuf_doallocate(strstreambuf *this)
1304 char *prev_buffer = this->base.base, *new_buffer;
1305 LONG prev_size = this->base.ebuf - this->base.base, new_size;
1307 TRACE("(%p)\n", this);
1309 /* calculate the size of the new buffer */
1310 new_size = (prev_size > 0 ? prev_size : 0) + (this->increase > 0 ? this->increase : 1);
1311 /* get a new buffer */
1312 if (this->f_alloc)
1313 new_buffer = this->f_alloc(new_size);
1314 else
1315 new_buffer = MSVCRT_operator_new(new_size);
1316 if (!new_buffer)
1317 return EOF;
1318 if (this->base.ebuf) {
1319 /* copy the contents and adjust the pointers */
1320 memcpy(new_buffer, this->base.base, prev_size);
1321 if (this->base.egptr) {
1322 this->base.eback += new_buffer - prev_buffer;
1323 this->base.gptr += new_buffer - prev_buffer;
1324 this->base.egptr += new_buffer - prev_buffer;
1326 if (this->base.epptr) {
1327 this->base.pbase += new_buffer - prev_buffer;
1328 this->base.pptr += new_buffer - prev_buffer;
1329 this->base.epptr += new_buffer - prev_buffer;
1331 /* free the old buffer */
1332 if (this->f_free)
1333 this->f_free(this->base.base);
1334 else
1335 MSVCRT_operator_delete(this->base.base);
1337 streambuf_setb(&this->base, new_buffer, new_buffer + new_size, 0);
1338 return 1;
1341 /* ?freeze@strstreambuf@@QAEXH@Z */
1342 /* ?freeze@strstreambuf@@QEAAXH@Z */
1343 DEFINE_THISCALL_WRAPPER(strstreambuf_freeze, 8)
1344 void __thiscall strstreambuf_freeze(strstreambuf *this, int frozen)
1346 TRACE("(%p %d)\n", this, frozen);
1347 if (!this->constant)
1348 this->dynamic = !frozen;
1351 /* ?overflow@strstreambuf@@UAEHH@Z */
1352 /* ?overflow@strstreambuf@@UEAAHH@Z */
1353 DEFINE_THISCALL_WRAPPER(strstreambuf_overflow, 8)
1354 int __thiscall strstreambuf_overflow(strstreambuf *this, int c)
1356 TRACE("(%p %d)\n", this, c);
1357 if (this->base.pptr >= this->base.epptr) {
1358 /* increase the buffer size if it's dynamic */
1359 if (!this->dynamic || call_streambuf_doallocate(&this->base) == EOF)
1360 return EOF;
1361 if (!this->base.epptr)
1362 this->base.pbase = this->base.pptr = this->base.egptr ? this->base.egptr : this->base.base;
1363 this->base.epptr = this->base.ebuf;
1365 if (c != EOF)
1366 *this->base.pptr++ = c;
1367 return 1;
1370 /* ?seekoff@strstreambuf@@UAEJJW4seek_dir@ios@@H@Z */
1371 /* ?seekoff@strstreambuf@@UEAAJJW4seek_dir@ios@@H@Z */
1372 DEFINE_THISCALL_WRAPPER(strstreambuf_seekoff, 16)
1373 streampos __thiscall strstreambuf_seekoff(strstreambuf *this, streamoff offset, ios_seek_dir dir, int mode)
1375 char *base[3];
1377 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
1379 if (dir < SEEKDIR_beg || dir > SEEKDIR_end || !(mode & (OPENMODE_in|OPENMODE_out)))
1380 return EOF;
1381 /* read buffer */
1382 if (mode & OPENMODE_in) {
1383 call_streambuf_underflow(&this->base);
1384 base[SEEKDIR_beg] = this->base.eback;
1385 base[SEEKDIR_cur] = this->base.gptr;
1386 base[SEEKDIR_end] = this->base.egptr;
1387 if (base[dir] + offset < this->base.eback || base[dir] + offset > this->base.egptr)
1388 return EOF;
1389 this->base.gptr = base[dir] + offset;
1391 /* write buffer */
1392 if (mode & OPENMODE_out) {
1393 if (!this->base.epptr && call_streambuf_overflow(&this->base, EOF) == EOF)
1394 return EOF;
1395 base[SEEKDIR_beg] = this->base.pbase;
1396 base[SEEKDIR_cur] = this->base.pptr;
1397 base[SEEKDIR_end] = this->base.epptr;
1398 if (base[dir] + offset < this->base.pbase)
1399 return EOF;
1400 if (base[dir] + offset > this->base.epptr) {
1401 /* make room if the buffer is dynamic */
1402 if (!this->dynamic)
1403 return EOF;
1404 this->increase = offset;
1405 if (call_streambuf_doallocate(&this->base) == EOF)
1406 return EOF;
1408 this->base.pptr = base[dir] + offset;
1409 return this->base.pptr - base[SEEKDIR_beg];
1411 return this->base.gptr - base[SEEKDIR_beg];
1414 /* ?setbuf@strstreambuf@@UAEPAVstreambuf@@PADH@Z */
1415 /* ?setbuf@strstreambuf@@UEAAPEAVstreambuf@@PEADH@Z */
1416 DEFINE_THISCALL_WRAPPER(strstreambuf_setbuf, 12)
1417 streambuf* __thiscall strstreambuf_setbuf(strstreambuf *this, char *buffer, int length)
1419 TRACE("(%p %p %d)\n", this, buffer, length);
1420 if (length)
1421 this->increase = length;
1422 return &this->base;
1425 /* ?str@strstreambuf@@QAEPADXZ */
1426 /* ?str@strstreambuf@@QEAAPEADXZ */
1427 DEFINE_THISCALL_WRAPPER(strstreambuf_str, 4)
1428 char* __thiscall strstreambuf_str(strstreambuf *this)
1430 TRACE("(%p)\n", this);
1431 strstreambuf_freeze(this, 1);
1432 return this->base.base;
1435 /* ?sync@strstreambuf@@UAEHXZ */
1436 /* ?sync@strstreambuf@@UEAAHXZ */
1437 DEFINE_THISCALL_WRAPPER(strstreambuf_sync, 4)
1438 int __thiscall strstreambuf_sync(strstreambuf *this)
1440 TRACE("(%p)\n", this);
1441 return 0;
1444 /* ?underflow@strstreambuf@@UAEHXZ */
1445 /* ?underflow@strstreambuf@@UEAAHXZ */
1446 DEFINE_THISCALL_WRAPPER(strstreambuf_underflow, 4)
1447 int __thiscall strstreambuf_underflow(strstreambuf *this)
1449 TRACE("(%p)\n", this);
1450 if (this->base.gptr < this->base.egptr)
1451 return *this->base.gptr;
1452 /* extend the get area to include the characters written */
1453 if (this->base.egptr < this->base.pptr)
1454 this->base.egptr = this->base.pptr;
1455 return (this->base.gptr < this->base.egptr) ? *this->base.gptr : EOF;
1458 /* ??0stdiobuf@@QAE@ABV0@@Z */
1459 /* ??0stdiobuf@@QEAA@AEBV0@@Z */
1460 DEFINE_THISCALL_WRAPPER(stdiobuf_copy_ctor, 8)
1461 stdiobuf* __thiscall stdiobuf_copy_ctor(stdiobuf *this, const stdiobuf *copy)
1463 TRACE("(%p %p)\n", this, copy);
1464 *this = *copy;
1465 this->base.vtable = &MSVCP_stdiobuf_vtable;
1466 return this;
1469 /* ??0stdiobuf@@QAE@PAU_iobuf@@@Z */
1470 /* ??0stdiobuf@@QEAA@PEAU_iobuf@@@Z */
1471 DEFINE_THISCALL_WRAPPER(stdiobuf_file_ctor, 8)
1472 stdiobuf* __thiscall stdiobuf_file_ctor(stdiobuf *this, FILE *file)
1474 TRACE("(%p %p)\n", this, file);
1475 streambuf_reserve_ctor(&this->base, NULL, 0);
1476 this->base.vtable = &MSVCP_stdiobuf_vtable;
1477 this->file = file;
1478 return this;
1481 /* ??1stdiobuf@@UAE@XZ */
1482 /* ??1stdiobuf@@UEAA@XZ */
1483 DEFINE_THISCALL_WRAPPER(stdiobuf_dtor, 4)
1484 void __thiscall stdiobuf_dtor(stdiobuf *this)
1486 TRACE("(%p)\n", this);
1487 call_streambuf_sync(&this->base);
1488 streambuf_dtor(&this->base);
1491 /* ??4stdiobuf@@QAEAAV0@ABV0@@Z */
1492 /* ??4stdiobuf@@QEAAAEAV0@AEBV0@@Z */
1493 DEFINE_THISCALL_WRAPPER(stdiobuf_assign, 8)
1494 stdiobuf* __thiscall stdiobuf_assign(stdiobuf *this, const stdiobuf *rhs)
1496 stdiobuf_dtor(this);
1497 return stdiobuf_copy_ctor(this, rhs);
1500 /* ??_Estdiobuf@@UAEPAXI@Z */
1501 DEFINE_THISCALL_WRAPPER(stdiobuf_vector_dtor, 8)
1502 stdiobuf* __thiscall stdiobuf_vector_dtor(stdiobuf *this, unsigned int flags)
1504 TRACE("(%p %x)\n", this, flags);
1505 if (flags & 2) {
1506 /* we have an array, with the number of elements stored before the first object */
1507 INT_PTR i, *ptr = (INT_PTR *)this-1;
1509 for (i = *ptr-1; i >= 0; i--)
1510 stdiobuf_dtor(this+i);
1511 MSVCRT_operator_delete(ptr);
1512 } else {
1513 stdiobuf_dtor(this);
1514 if (flags & 1)
1515 MSVCRT_operator_delete(this);
1517 return this;
1520 /* ??_Gstdiobuf@@UAEPAXI@Z */
1521 DEFINE_THISCALL_WRAPPER(stdiobuf_scalar_dtor, 8)
1522 stdiobuf* __thiscall stdiobuf_scalar_dtor(stdiobuf *this, unsigned int flags)
1524 TRACE("(%p %x)\n", this, flags);
1525 stdiobuf_dtor(this);
1526 if (flags & 1) MSVCRT_operator_delete(this);
1527 return this;
1530 /* ?overflow@stdiobuf@@UAEHH@Z */
1531 /* ?overflow@stdiobuf@@UEAAHH@Z */
1532 DEFINE_THISCALL_WRAPPER(stdiobuf_overflow, 8)
1533 int __thiscall stdiobuf_overflow(stdiobuf *this, int c)
1535 TRACE("(%p %d)\n", this, c);
1536 if (this->base.unbuffered)
1537 return (c == EOF) ? 1 : fputc(c, this->file);
1538 if (streambuf_allocate(&this->base) == EOF)
1539 return EOF;
1541 if (!this->base.epptr) {
1542 /* set the put area to the second half of the buffer */
1543 streambuf_setp(&this->base,
1544 this->base.base + (this->base.ebuf - this->base.base) / 2, this->base.ebuf);
1545 } else if (this->base.pptr > this->base.pbase) {
1546 /* flush the put area */
1547 int count = this->base.pptr - this->base.pbase;
1548 if (fwrite(this->base.pbase, sizeof(char), count, this->file) != count)
1549 return EOF;
1550 this->base.pptr = this->base.pbase;
1552 if (c != EOF) {
1553 if (this->base.pbase >= this->base.epptr)
1554 return fputc(c, this->file);
1555 *this->base.pptr++ = c;
1557 return 1;
1560 /* ?pbackfail@stdiobuf@@UAEHH@Z */
1561 /* ?pbackfail@stdiobuf@@UEAAHH@Z */
1562 DEFINE_THISCALL_WRAPPER(stdiobuf_pbackfail, 8)
1563 int __thiscall stdiobuf_pbackfail(stdiobuf *this, int c)
1565 FIXME("(%p %d) stub\n", this, c);
1566 return EOF;
1569 /* ?seekoff@stdiobuf@@UAEJJW4seek_dir@ios@@H@Z */
1570 /* ?seekoff@stdiobuf@@UEAAJJW4seek_dir@ios@@H@Z */
1571 DEFINE_THISCALL_WRAPPER(stdiobuf_seekoff, 16)
1572 streampos __thiscall stdiobuf_seekoff(stdiobuf *this, streamoff offset, ios_seek_dir dir, int mode)
1574 FIXME("(%p %d %d %d) stub\n", this, offset, dir, mode);
1575 return EOF;
1578 /* ?setrwbuf@stdiobuf@@QAEHHH@Z */
1579 /* ?setrwbuf@stdiobuf@@QEAAHHH@Z */
1580 DEFINE_THISCALL_WRAPPER(stdiobuf_setrwbuf, 12)
1581 int __thiscall stdiobuf_setrwbuf(stdiobuf *this, int read_size, int write_size)
1583 FIXME("(%p %d %d) stub\n", this, read_size, write_size);
1584 return EOF;
1587 /* ?stdiofile@stdiobuf@@QAEPAU_iobuf@@XZ */
1588 /* ?stdiofile@stdiobuf@@QEAAPEAU_iobuf@@XZ */
1589 DEFINE_THISCALL_WRAPPER(stdiobuf_stdiofile, 4)
1590 FILE* __thiscall stdiobuf_stdiofile(stdiobuf *this)
1592 FIXME("(%p) stub\n", this);
1593 return NULL;
1596 /* ?sync@stdiobuf@@UAEHXZ */
1597 /* ?sync@stdiobuf@@UEAAHXZ */
1598 DEFINE_THISCALL_WRAPPER(stdiobuf_sync, 4)
1599 int __thiscall stdiobuf_sync(stdiobuf *this)
1601 FIXME("(%p) stub\n", this);
1602 return EOF;
1605 /* ?underflow@stdiobuf@@UAEHXZ */
1606 /* ?underflow@stdiobuf@@UEAAHXZ */
1607 DEFINE_THISCALL_WRAPPER(stdiobuf_underflow, 4)
1608 int __thiscall stdiobuf_underflow(stdiobuf *this)
1610 TRACE("(%p)\n", this);
1611 if (!this->file)
1612 return EOF;
1613 if (this->base.unbuffered)
1614 return fgetc(this->file);
1615 if (streambuf_allocate(&this->base) == EOF)
1616 return EOF;
1618 if (!this->base.egptr) {
1619 /* set the get area to the first half of the buffer */
1620 char *middle = this->base.base + (this->base.ebuf - this->base.base) / 2;
1621 streambuf_setg(&this->base, this->base.base, middle, middle);
1623 if (this->base.gptr >= this->base.egptr) {
1624 /* read characters from the file */
1625 int buffer_size = this->base.egptr - this->base.eback, read_bytes;
1626 if (!this->base.eback ||
1627 (read_bytes = fread(this->base.eback, sizeof(char), buffer_size, this->file)) <= 0)
1628 return EOF;
1629 memmove(this->base.egptr - read_bytes, this->base.eback, read_bytes);
1630 this->base.gptr = this->base.egptr - read_bytes;
1632 return *this->base.gptr++;
1635 /* ??0ios@@IAE@ABV0@@Z */
1636 /* ??0ios@@IEAA@AEBV0@@Z */
1637 DEFINE_THISCALL_WRAPPER(ios_copy_ctor, 8)
1638 ios* __thiscall ios_copy_ctor(ios *this, const ios *copy)
1640 TRACE("(%p %p)\n", this, copy);
1641 ios_fLockcInit++;
1642 this->vtable = &MSVCP_ios_vtable;
1643 this->sb = NULL;
1644 this->delbuf = 0;
1645 InitializeCriticalSection(&this->lock);
1646 return ios_assign(this, copy);
1649 /* ??0ios@@QAE@PAVstreambuf@@@Z */
1650 /* ??0ios@@QEAA@PEAVstreambuf@@@Z */
1651 DEFINE_THISCALL_WRAPPER(ios_sb_ctor, 8)
1652 ios* __thiscall ios_sb_ctor(ios *this, streambuf *sb)
1654 TRACE("(%p %p)\n", this, sb);
1655 ios_fLockcInit++;
1656 this->vtable = &MSVCP_ios_vtable;
1657 this->sb = sb;
1658 this->state = sb ? IOSTATE_goodbit : IOSTATE_badbit;
1659 this->special[0] = this->special[1] = 0;
1660 this->delbuf = 0;
1661 this->tie = NULL;
1662 this->flags = 0;
1663 this->precision = 6;
1664 this->fill = ' ';
1665 this->width = 0;
1666 this->do_lock = -1;
1667 InitializeCriticalSection(&this->lock);
1668 return this;
1671 /* ??0ios@@IAE@XZ */
1672 /* ??0ios@@IEAA@XZ */
1673 DEFINE_THISCALL_WRAPPER(ios_ctor, 4)
1674 ios* __thiscall ios_ctor(ios *this)
1676 return ios_sb_ctor(this, NULL);
1679 /* ??1ios@@UAE@XZ */
1680 /* ??1ios@@UEAA@XZ */
1681 DEFINE_THISCALL_WRAPPER(ios_dtor, 4)
1682 void __thiscall ios_dtor(ios *this)
1684 TRACE("(%p)\n", this);
1685 ios_fLockcInit--;
1686 if (this->delbuf && this->sb)
1687 call_streambuf_vector_dtor(this->sb, 1);
1688 this->sb = NULL;
1689 this->state = IOSTATE_badbit;
1690 DeleteCriticalSection(&this->lock);
1693 /* ??4ios@@IAEAAV0@ABV0@@Z */
1694 /* ??4ios@@IEAAAEAV0@AEBV0@@Z */
1695 DEFINE_THISCALL_WRAPPER(ios_assign, 8)
1696 ios* __thiscall ios_assign(ios *this, const ios *rhs)
1698 TRACE("(%p %p)\n", this, rhs);
1699 this->state = rhs->state;
1700 if (!this->sb)
1701 this->state |= IOSTATE_badbit;
1702 this->tie = rhs->tie;
1703 this->flags = rhs->flags;
1704 this->precision = (char) rhs->precision;
1705 this->fill = rhs->fill;
1706 this->width = (char) rhs->width;
1707 return this;
1710 /* ??7ios@@QBEHXZ */
1711 /* ??7ios@@QEBAHXZ */
1712 DEFINE_THISCALL_WRAPPER(ios_op_not, 4)
1713 int __thiscall ios_op_not(const ios *this)
1715 TRACE("(%p)\n", this);
1716 return ios_fail(this);
1719 /* ??Bios@@QBEPAXXZ */
1720 /* ??Bios@@QEBAPEAXXZ */
1721 DEFINE_THISCALL_WRAPPER(ios_op_void, 4)
1722 void* __thiscall ios_op_void(const ios *this)
1724 TRACE("(%p)\n", this);
1725 return ios_fail(this) ? NULL : (void*)this;
1728 /* ??_Eios@@UAEPAXI@Z */
1729 DEFINE_THISCALL_WRAPPER(ios_vector_dtor, 8)
1730 ios* __thiscall ios_vector_dtor(ios *this, unsigned int flags)
1732 TRACE("(%p %x)\n", this, flags);
1733 if (flags & 2) {
1734 /* we have an array, with the number of elements stored before the first object */
1735 INT_PTR i, *ptr = (INT_PTR *)this-1;
1737 for (i = *ptr-1; i >= 0; i--)
1738 ios_dtor(this+i);
1739 MSVCRT_operator_delete(ptr);
1740 } else {
1741 ios_dtor(this);
1742 if (flags & 1)
1743 MSVCRT_operator_delete(this);
1745 return this;
1748 /* ??_Gios@@UAEPAXI@Z */
1749 DEFINE_THISCALL_WRAPPER(ios_scalar_dtor, 8)
1750 ios* __thiscall ios_scalar_dtor(ios *this, unsigned int flags)
1752 TRACE("(%p %x)\n", this, flags);
1753 ios_dtor(this);
1754 if (flags & 1) MSVCRT_operator_delete(this);
1755 return this;
1758 /* ?bad@ios@@QBEHXZ */
1759 /* ?bad@ios@@QEBAHXZ */
1760 DEFINE_THISCALL_WRAPPER(ios_bad, 4)
1761 int __thiscall ios_bad(const ios *this)
1763 TRACE("(%p)\n", this);
1764 return (this->state & IOSTATE_badbit);
1767 /* ?bitalloc@ios@@SAJXZ */
1768 LONG __cdecl ios_bitalloc(void)
1770 TRACE("()\n");
1771 ios_lockc();
1772 ios_maxbit <<= 1;
1773 ios_unlockc();
1774 return ios_maxbit;
1777 /* ?clear@ios@@QAEXH@Z */
1778 /* ?clear@ios@@QEAAXH@Z */
1779 DEFINE_THISCALL_WRAPPER(ios_clear, 8)
1780 void __thiscall ios_clear(ios *this, int state)
1782 TRACE("(%p %d)\n", this, state);
1783 ios_lock(this);
1784 this->state = state;
1785 ios_unlock(this);
1788 /* ?clrlock@ios@@QAAXXZ */
1789 /* ?clrlock@ios@@QEAAXXZ */
1790 void __cdecl ios_clrlock(ios *this)
1792 TRACE("(%p)\n", this);
1793 if (this->do_lock <= 0)
1794 this->do_lock++;
1795 if (this->sb)
1796 streambuf_clrlock(this->sb);
1799 /* ?delbuf@ios@@QAEXH@Z */
1800 /* ?delbuf@ios@@QEAAXH@Z */
1801 DEFINE_THISCALL_WRAPPER(ios_delbuf_set, 8)
1802 void __thiscall ios_delbuf_set(ios *this, int delete)
1804 TRACE("(%p %d)\n", this, delete);
1805 this->delbuf = delete;
1808 /* ?delbuf@ios@@QBEHXZ */
1809 /* ?delbuf@ios@@QEBAHXZ */
1810 DEFINE_THISCALL_WRAPPER(ios_delbuf_get, 4)
1811 int __thiscall ios_delbuf_get(const ios *this)
1813 TRACE("(%p)\n", this);
1814 return this->delbuf;
1817 /* ?dec@@YAAAVios@@AAV1@@Z */
1818 /* ?dec@@YAAEAVios@@AEAV1@@Z */
1819 ios* __cdecl ios_dec(ios *this)
1821 TRACE("(%p)\n", this);
1822 ios_setf_mask(this, FLAGS_dec, ios_basefield);
1823 return this;
1826 /* ?eof@ios@@QBEHXZ */
1827 /* ?eof@ios@@QEBAHXZ */
1828 DEFINE_THISCALL_WRAPPER(ios_eof, 4)
1829 int __thiscall ios_eof(const ios *this)
1831 TRACE("(%p)\n", this);
1832 return (this->state & IOSTATE_eofbit);
1835 /* ?fail@ios@@QBEHXZ */
1836 /* ?fail@ios@@QEBAHXZ */
1837 DEFINE_THISCALL_WRAPPER(ios_fail, 4)
1838 int __thiscall ios_fail(const ios *this)
1840 TRACE("(%p)\n", this);
1841 return (this->state & (IOSTATE_failbit|IOSTATE_badbit));
1844 /* ?fill@ios@@QAEDD@Z */
1845 /* ?fill@ios@@QEAADD@Z */
1846 DEFINE_THISCALL_WRAPPER(ios_fill_set, 8)
1847 char __thiscall ios_fill_set(ios *this, char fill)
1849 char prev = this->fill;
1851 TRACE("(%p %d)\n", this, fill);
1853 this->fill = fill;
1854 return prev;
1857 /* ?fill@ios@@QBEDXZ */
1858 /* ?fill@ios@@QEBADXZ */
1859 DEFINE_THISCALL_WRAPPER(ios_fill_get, 4)
1860 char __thiscall ios_fill_get(const ios *this)
1862 TRACE("(%p)\n", this);
1863 return this->fill;
1866 /* ?flags@ios@@QAEJJ@Z */
1867 /* ?flags@ios@@QEAAJJ@Z */
1868 DEFINE_THISCALL_WRAPPER(ios_flags_set, 8)
1869 LONG __thiscall ios_flags_set(ios *this, LONG flags)
1871 LONG prev = this->flags;
1873 TRACE("(%p %x)\n", this, flags);
1875 this->flags = flags;
1876 return prev;
1879 /* ?flags@ios@@QBEJXZ */
1880 /* ?flags@ios@@QEBAJXZ */
1881 DEFINE_THISCALL_WRAPPER(ios_flags_get, 4)
1882 LONG __thiscall ios_flags_get(const ios *this)
1884 TRACE("(%p)\n", this);
1885 return this->flags;
1888 /* ?good@ios@@QBEHXZ */
1889 /* ?good@ios@@QEBAHXZ */
1890 DEFINE_THISCALL_WRAPPER(ios_good, 4)
1891 int __thiscall ios_good(const ios *this)
1893 TRACE("(%p)\n", this);
1894 return this->state == IOSTATE_goodbit;
1897 /* ?hex@@YAAAVios@@AAV1@@Z */
1898 /* ?hex@@YAAEAVios@@AEAV1@@Z */
1899 ios* __cdecl ios_hex(ios *this)
1901 TRACE("(%p)\n", this);
1902 ios_setf_mask(this, FLAGS_hex, ios_basefield);
1903 return this;
1906 /* ?init@ios@@IAEXPAVstreambuf@@@Z */
1907 /* ?init@ios@@IEAAXPEAVstreambuf@@@Z */
1908 DEFINE_THISCALL_WRAPPER(ios_init, 8)
1909 void __thiscall ios_init(ios *this, streambuf *sb)
1911 TRACE("(%p %p)\n", this, sb);
1912 if (this->delbuf && this->sb)
1913 call_streambuf_vector_dtor(this->sb, 1);
1914 this->sb = sb;
1915 if (sb == NULL)
1916 this->state |= IOSTATE_badbit;
1917 else
1918 this->state &= ~IOSTATE_badbit;
1921 /* ?iword@ios@@QBEAAJH@Z */
1922 /* ?iword@ios@@QEBAAEAJH@Z */
1923 DEFINE_THISCALL_WRAPPER(ios_iword, 8)
1924 LONG* __thiscall ios_iword(const ios *this, int index)
1926 TRACE("(%p %d)\n", this, index);
1927 return &ios_statebuf[index];
1930 /* ?lock@ios@@QAAXXZ */
1931 /* ?lock@ios@@QEAAXXZ */
1932 void __cdecl ios_lock(ios *this)
1934 TRACE("(%p)\n", this);
1935 if (this->do_lock < 0)
1936 EnterCriticalSection(&this->lock);
1939 /* ?lockbuf@ios@@QAAXXZ */
1940 /* ?lockbuf@ios@@QEAAXXZ */
1941 void __cdecl ios_lockbuf(ios *this)
1943 TRACE("(%p)\n", this);
1944 streambuf_lock(this->sb);
1947 /* ?lockc@ios@@KAXXZ */
1948 void __cdecl ios_lockc(void)
1950 TRACE("()\n");
1951 EnterCriticalSection(&ios_static_lock);
1954 /* ?lockptr@ios@@IAEPAU_CRT_CRITICAL_SECTION@@XZ */
1955 /* ?lockptr@ios@@IEAAPEAU_CRT_CRITICAL_SECTION@@XZ */
1956 DEFINE_THISCALL_WRAPPER(ios_lockptr, 4)
1957 CRITICAL_SECTION* __thiscall ios_lockptr(ios *this)
1959 TRACE("(%p)\n", this);
1960 return &this->lock;
1963 /* ?oct@@YAAAVios@@AAV1@@Z */
1964 /* ?oct@@YAAEAVios@@AEAV1@@Z */
1965 ios* __cdecl ios_oct(ios *this)
1967 TRACE("(%p)\n", this);
1968 ios_setf_mask(this, FLAGS_oct, ios_basefield);
1969 return this;
1972 /* ?precision@ios@@QAEHH@Z */
1973 /* ?precision@ios@@QEAAHH@Z */
1974 DEFINE_THISCALL_WRAPPER(ios_precision_set, 8)
1975 int __thiscall ios_precision_set(ios *this, int prec)
1977 int prev = this->precision;
1979 TRACE("(%p %d)\n", this, prec);
1981 this->precision = prec;
1982 return prev;
1985 /* ?precision@ios@@QBEHXZ */
1986 /* ?precision@ios@@QEBAHXZ */
1987 DEFINE_THISCALL_WRAPPER(ios_precision_get, 4)
1988 int __thiscall ios_precision_get(const ios *this)
1990 TRACE("(%p)\n", this);
1991 return this->precision;
1994 /* ?pword@ios@@QBEAAPAXH@Z */
1995 /* ?pword@ios@@QEBAAEAPEAXH@Z */
1996 DEFINE_THISCALL_WRAPPER(ios_pword, 8)
1997 void** __thiscall ios_pword(const ios *this, int index)
1999 TRACE("(%p %d)\n", this, index);
2000 return (void**)&ios_statebuf[index];
2003 /* ?rdbuf@ios@@QBEPAVstreambuf@@XZ */
2004 /* ?rdbuf@ios@@QEBAPEAVstreambuf@@XZ */
2005 DEFINE_THISCALL_WRAPPER(ios_rdbuf, 4)
2006 streambuf* __thiscall ios_rdbuf(const ios *this)
2008 TRACE("(%p)\n", this);
2009 return this->sb;
2012 /* ?rdstate@ios@@QBEHXZ */
2013 /* ?rdstate@ios@@QEBAHXZ */
2014 DEFINE_THISCALL_WRAPPER(ios_rdstate, 4)
2015 int __thiscall ios_rdstate(const ios *this)
2017 TRACE("(%p)\n", this);
2018 return this->state;
2021 /* ?setf@ios@@QAEJJ@Z */
2022 /* ?setf@ios@@QEAAJJ@Z */
2023 DEFINE_THISCALL_WRAPPER(ios_setf, 8)
2024 LONG __thiscall ios_setf(ios *this, LONG flags)
2026 LONG prev = this->flags;
2028 TRACE("(%p %x)\n", this, flags);
2030 ios_lock(this);
2031 this->flags |= flags;
2032 ios_unlock(this);
2033 return prev;
2036 /* ?setf@ios@@QAEJJJ@Z */
2037 /* ?setf@ios@@QEAAJJJ@Z */
2038 DEFINE_THISCALL_WRAPPER(ios_setf_mask, 12)
2039 LONG __thiscall ios_setf_mask(ios *this, LONG flags, LONG mask)
2041 LONG prev = this->flags;
2043 TRACE("(%p %x %x)\n", this, flags, mask);
2045 ios_lock(this);
2046 this->flags = (this->flags & (~mask)) | (flags & mask);
2047 ios_unlock(this);
2048 return prev;
2051 /* ?setlock@ios@@QAAXXZ */
2052 /* ?setlock@ios@@QEAAXXZ */
2053 void __cdecl ios_setlock(ios *this)
2055 TRACE("(%p)\n", this);
2056 this->do_lock--;
2057 if (this->sb)
2058 streambuf_setlock(this->sb);
2061 /* ?sync_with_stdio@ios@@SAXXZ */
2062 void __cdecl ios_sync_with_stdio(void)
2064 FIXME("() stub\n");
2067 /* ?tie@ios@@QAEPAVostream@@PAV2@@Z */
2068 /* ?tie@ios@@QEAAPEAVostream@@PEAV2@@Z */
2069 DEFINE_THISCALL_WRAPPER(ios_tie_set, 8)
2070 ostream* __thiscall ios_tie_set(ios *this, ostream *ostr)
2072 ostream *prev = this->tie;
2074 TRACE("(%p %p)\n", this, ostr);
2076 this->tie = ostr;
2077 return prev;
2080 /* ?tie@ios@@QBEPAVostream@@XZ */
2081 /* ?tie@ios@@QEBAPEAVostream@@XZ */
2082 DEFINE_THISCALL_WRAPPER(ios_tie_get, 4)
2083 ostream* __thiscall ios_tie_get(const ios *this)
2085 TRACE("(%p)\n", this);
2086 return this->tie;
2089 /* ?unlock@ios@@QAAXXZ */
2090 /* ?unlock@ios@@QEAAXXZ */
2091 void __cdecl ios_unlock(ios *this)
2093 TRACE("(%p)\n", this);
2094 if (this->do_lock < 0)
2095 LeaveCriticalSection(&this->lock);
2098 /* ?unlockbuf@ios@@QAAXXZ */
2099 /* ?unlockbuf@ios@@QEAAXXZ */
2100 void __cdecl ios_unlockbuf(ios *this)
2102 TRACE("(%p)\n", this);
2103 streambuf_unlock(this->sb);
2106 /* ?unlockc@ios@@KAXXZ */
2107 void __cdecl ios_unlockc(void)
2109 TRACE("()\n");
2110 LeaveCriticalSection(&ios_static_lock);
2113 /* ?unsetf@ios@@QAEJJ@Z */
2114 /* ?unsetf@ios@@QEAAJJ@Z */
2115 DEFINE_THISCALL_WRAPPER(ios_unsetf, 8)
2116 LONG __thiscall ios_unsetf(ios *this, LONG flags)
2118 LONG prev = this->flags;
2120 TRACE("(%p %x)\n", this, flags);
2122 ios_lock(this);
2123 this->flags &= ~flags;
2124 ios_unlock(this);
2125 return prev;
2128 /* ?width@ios@@QAEHH@Z */
2129 /* ?width@ios@@QEAAHH@Z */
2130 DEFINE_THISCALL_WRAPPER(ios_width_set, 8)
2131 int __thiscall ios_width_set(ios *this, int width)
2133 int prev = this->width;
2135 TRACE("(%p %d)\n", this, width);
2137 this->width = width;
2138 return prev;
2141 /* ?width@ios@@QBEHXZ */
2142 /* ?width@ios@@QEBAHXZ */
2143 DEFINE_THISCALL_WRAPPER(ios_width_get, 4)
2144 int __thiscall ios_width_get(const ios *this)
2146 TRACE("(%p)\n", this);
2147 return this->width;
2150 /* ?xalloc@ios@@SAHXZ */
2151 int __cdecl ios_xalloc(void)
2153 int ret;
2155 TRACE("()\n");
2157 ios_lockc();
2158 ret = (ios_curindex < STATEBUF_SIZE-1) ? ++ios_curindex : -1;
2159 ios_unlockc();
2160 return ret;
2163 /******************************************************************
2164 * ??0ostrstream@@QAE@XZ (MSVCRTI.@)
2166 DEFINE_THISCALL_WRAPPER(MSVCIRT_ostrstream_ctor,8)
2167 void * __thiscall MSVCIRT_ostrstream_ctor(ostream *this, BOOL virt_init)
2169 FIXME("(%p %x) stub\n", this, virt_init);
2170 return this;
2173 /******************************************************************
2174 * ??1ostrstream@@UAE@XZ (MSVCRTI.@)
2176 DEFINE_THISCALL_WRAPPER(MSVCIRT_ostrstream_dtor,4)
2177 void __thiscall MSVCIRT_ostrstream_dtor(ios *base)
2179 FIXME("(%p) stub\n", base);
2182 /******************************************************************
2183 * ??6ostream@@QAEAAV0@E@Z (MSVCRTI.@)
2184 * class ostream & __thiscall ostream::operator<<(unsigned char)
2186 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_uchar,8)
2187 void * __thiscall MSVCIRT_operator_sl_uchar(ostream * _this, unsigned char ch)
2189 FIXME("(%p)->(%c) stub\n", _this, ch);
2190 return _this;
2193 /******************************************************************
2194 * ??6ostream@@QAEAAV0@H@Z (MSVCRTI.@)
2195 * class ostream & __thiscall ostream::operator<<(int)
2197 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_int,8)
2198 void * __thiscall MSVCIRT_operator_sl_int(ostream * _this, int integer)
2200 FIXME("(%p)->(%d) stub\n", _this, integer);
2201 return _this;
2204 /******************************************************************
2205 * ??6ostream@@QAEAAV0@PBD@Z (MSVCRTI.@)
2206 * class ostream & __thiscall ostream::operator<<(char const *)
2208 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_pchar,8)
2209 void * __thiscall MSVCIRT_operator_sl_pchar(ostream * _this, const char * string)
2211 FIXME("(%p)->(%s) stub\n", _this, debugstr_a(string));
2212 return _this;
2215 /******************************************************************
2216 * ??6ostream@@QAEAAV0@P6AAAV0@AAV0@@Z@Z (MSVCRTI.@)
2217 * class ostream & __thiscall ostream::operator<<(class ostream & (__cdecl*)(class ostream &))
2219 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_callback,8)
2220 void * __thiscall MSVCIRT_operator_sl_callback(ostream * _this, ostream * (__cdecl*func)(ostream*))
2222 TRACE("%p, %p\n", _this, func);
2223 return func(_this);
2226 /******************************************************************
2227 * ?endl@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
2228 * class ostream & __cdecl endl(class ostream &)
2230 void * CDECL MSVCIRT_endl(ostream * _this)
2232 FIXME("(%p)->() stub\n", _this);
2233 return _this;
2236 /******************************************************************
2237 * ?ends@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
2238 * class ostream & __cdecl ends(class ostream &)
2240 void * CDECL MSVCIRT_ends(ostream * _this)
2242 FIXME("(%p)->() stub\n", _this);
2243 return _this;
2246 #ifdef __i386__
2248 #define DEFINE_VTBL_WRAPPER(off) \
2249 __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
2250 "popl %eax\n\t" \
2251 "popl %ecx\n\t" \
2252 "pushl %eax\n\t" \
2253 "movl 0(%ecx), %eax\n\t" \
2254 "jmp *" #off "(%eax)\n\t")
2256 DEFINE_VTBL_WRAPPER(0);
2257 DEFINE_VTBL_WRAPPER(4);
2258 DEFINE_VTBL_WRAPPER(8);
2259 DEFINE_VTBL_WRAPPER(12);
2260 DEFINE_VTBL_WRAPPER(16);
2261 DEFINE_VTBL_WRAPPER(20);
2262 DEFINE_VTBL_WRAPPER(24);
2263 DEFINE_VTBL_WRAPPER(28);
2264 DEFINE_VTBL_WRAPPER(32);
2265 DEFINE_VTBL_WRAPPER(36);
2266 DEFINE_VTBL_WRAPPER(40);
2267 DEFINE_VTBL_WRAPPER(44);
2268 DEFINE_VTBL_WRAPPER(48);
2269 DEFINE_VTBL_WRAPPER(52);
2270 DEFINE_VTBL_WRAPPER(56);
2272 #endif
2274 void* (__cdecl *MSVCRT_operator_new)(SIZE_T);
2275 void (__cdecl *MSVCRT_operator_delete)(void*);
2277 static void init_cxx_funcs(void)
2279 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
2281 if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */
2283 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPEAX_K@Z");
2284 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPEAX@Z");
2286 else
2288 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPAXI@Z");
2289 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPAX@Z");
2293 static void init_io(void *base)
2295 #ifdef __x86_64__
2296 init_streambuf_rtti(base);
2297 init_filebuf_rtti(base);
2298 init_strstreambuf_rtti(base);
2299 init_stdiobuf_rtti(base);
2300 init_ios_rtti(base);
2301 #endif
2304 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2306 switch (reason)
2308 case DLL_WINE_PREATTACH:
2309 return FALSE; /* prefer native version */
2310 case DLL_PROCESS_ATTACH:
2311 init_cxx_funcs();
2312 init_exception(inst);
2313 init_io(inst);
2314 DisableThreadLibraryCalls( inst );
2315 break;
2317 return TRUE;