user32: Don't crash in DrawTextEx when tab length is zero.
[wine.git] / dlls / msvcirt / msvcirt.c
blob09f488ad102fe7c3ed724aec69f9f87d422da757
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 /* ?seekoff@streambuf@@UAEJJW4seek_dir@ios@@H@Z */
505 /* ?seekoff@streambuf@@UEAAJJW4seek_dir@ios@@H@Z */
506 DEFINE_THISCALL_WRAPPER(streambuf_seekoff, 16)
507 #define call_streambuf_seekoff(this, off, dir, mode) CALL_VTBL_FUNC(this, 12, streampos, (streambuf*, streamoff, ios_seek_dir, int), (this, off, dir, mode))
508 streampos __thiscall streambuf_seekoff(streambuf *this, streamoff offset, ios_seek_dir dir, int mode)
510 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
511 return EOF;
514 /* ?seekpos@streambuf@@UAEJJH@Z */
515 /* ?seekpos@streambuf@@UEAAJJH@Z */
516 DEFINE_THISCALL_WRAPPER(streambuf_seekpos, 12)
517 streampos __thiscall streambuf_seekpos(streambuf *this, streampos pos, int mode)
519 TRACE("(%p %d %d)\n", this, pos, mode);
520 return call_streambuf_seekoff(this, pos, SEEKDIR_beg, mode);
523 /* ?pbackfail@streambuf@@UAEHH@Z */
524 /* ?pbackfail@streambuf@@UEAAHH@Z */
525 DEFINE_THISCALL_WRAPPER(streambuf_pbackfail, 8)
526 #define call_streambuf_pbackfail(this, c) CALL_VTBL_FUNC(this, 36, int, (streambuf*, int), (this, c))
527 int __thiscall streambuf_pbackfail(streambuf *this, int c)
529 TRACE("(%p %d)\n", this, c);
530 if (this->gptr > this->eback)
531 return *--this->gptr = c;
532 if (call_streambuf_seekoff(this, -1, SEEKDIR_cur, OPENMODE_in) == EOF)
533 return EOF;
534 if (!this->unbuffered && this->egptr) {
535 /* 'c' should be the next character read */
536 memmove(this->gptr + 1, this->gptr, this->egptr - this->gptr - 1);
537 *this->gptr = c;
539 return c;
542 /* ?setb@streambuf@@IAEXPAD0H@Z */
543 /* ?setb@streambuf@@IEAAXPEAD0H@Z */
544 DEFINE_THISCALL_WRAPPER(streambuf_setb, 16)
545 void __thiscall streambuf_setb(streambuf *this, char *ba, char *eb, int delete)
547 TRACE("(%p %p %p %d)\n", this, ba, eb, delete);
548 if (this->allocated)
549 MSVCRT_operator_delete(this->base);
550 this->allocated = delete;
551 this->base = ba;
552 this->ebuf = eb;
555 /* ?setbuf@streambuf@@UAEPAV1@PADH@Z */
556 /* ?setbuf@streambuf@@UEAAPEAV1@PEADH@Z */
557 DEFINE_THISCALL_WRAPPER(streambuf_setbuf, 12)
558 streambuf* __thiscall streambuf_setbuf(streambuf *this, char *buffer, int length)
560 TRACE("(%p %p %d)\n", this, buffer, length);
561 if (this->base != NULL)
562 return NULL;
564 if (buffer == NULL || !length) {
565 this->unbuffered = 1;
566 this->base = this->ebuf = NULL;
567 } else {
568 this->unbuffered = 0;
569 this->base = buffer;
570 this->ebuf = buffer + length;
572 return this;
575 /* ?setg@streambuf@@IAEXPAD00@Z */
576 /* ?setg@streambuf@@IEAAXPEAD00@Z */
577 DEFINE_THISCALL_WRAPPER(streambuf_setg, 16)
578 void __thiscall streambuf_setg(streambuf *this, char *ek, char *gp, char *eg)
580 TRACE("(%p %p %p %p)\n", this, ek, gp, eg);
581 this->eback = ek;
582 this->gptr = gp;
583 this->egptr = eg;
586 /* ?setlock@streambuf@@QAEXXZ */
587 /* ?setlock@streambuf@@QEAAXXZ */
588 DEFINE_THISCALL_WRAPPER(streambuf_setlock, 4)
589 void __thiscall streambuf_setlock(streambuf *this)
591 TRACE("(%p)\n", this);
592 this->do_lock--;
595 /* ?setp@streambuf@@IAEXPAD0@Z */
596 /* ?setp@streambuf@@IEAAXPEAD0@Z */
597 DEFINE_THISCALL_WRAPPER(streambuf_setp, 12)
598 void __thiscall streambuf_setp(streambuf *this, char *pb, char *ep)
600 TRACE("(%p %p %p)\n", this, pb, ep);
601 this->pbase = this->pptr = pb;
602 this->epptr = ep;
605 /* ?sync@streambuf@@UAEHXZ */
606 /* ?sync@streambuf@@UEAAHXZ */
607 DEFINE_THISCALL_WRAPPER(streambuf_sync, 4)
608 #define call_streambuf_sync(this) CALL_VTBL_FUNC(this, 4, int, (streambuf*), (this))
609 int __thiscall streambuf_sync(streambuf *this)
611 TRACE("(%p)\n", this);
612 return (this->gptr >= this->egptr && this->pbase >= this->pptr) ? 0 : EOF;
615 /* ?unbuffered@streambuf@@IAEXH@Z */
616 /* ?unbuffered@streambuf@@IEAAXH@Z */
617 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_set, 8)
618 void __thiscall streambuf_unbuffered_set(streambuf *this, int buf)
620 TRACE("(%p %d)\n", this, buf);
621 this->unbuffered = buf;
624 /* ?unbuffered@streambuf@@IBEHXZ */
625 /* ?unbuffered@streambuf@@IEBAHXZ */
626 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_get, 4)
627 int __thiscall streambuf_unbuffered_get(const streambuf *this)
629 TRACE("(%p)\n", this);
630 return this->unbuffered;
633 /* Unexported */
634 DEFINE_THISCALL_WRAPPER(streambuf_underflow, 4)
635 #define call_streambuf_underflow(this) CALL_VTBL_FUNC(this, 32, int, (streambuf*), (this))
636 int __thiscall streambuf_underflow(streambuf *this)
638 ERR("underflow is not implemented in streambuf\n");
639 return EOF;
642 /* ?unlock@streambuf@@QAEXXZ */
643 /* ?unlock@streambuf@@QEAAXXZ */
644 DEFINE_THISCALL_WRAPPER(streambuf_unlock, 4)
645 void __thiscall streambuf_unlock(streambuf *this)
647 TRACE("(%p)\n", this);
648 if (this->do_lock < 0)
649 LeaveCriticalSection(&this->lock);
652 /* ?xsgetn@streambuf@@UAEHPADH@Z */
653 /* ?xsgetn@streambuf@@UEAAHPEADH@Z */
654 DEFINE_THISCALL_WRAPPER(streambuf_xsgetn, 12)
655 #define call_streambuf_xsgetn(this, buffer, count) CALL_VTBL_FUNC(this, 24, int, (streambuf*, char*, int), (this, buffer, count))
656 int __thiscall streambuf_xsgetn(streambuf *this, char *buffer, int count)
658 int copied = 0, chunk;
660 TRACE("(%p %p %d)\n", this, buffer, count);
662 if (this->unbuffered) {
663 if (this->stored_char == EOF)
664 this->stored_char = call_streambuf_underflow(this);
665 while (copied < count && this->stored_char != EOF) {
666 buffer[copied++] = this->stored_char;
667 this->stored_char = call_streambuf_underflow(this);
669 } else {
670 while (copied < count) {
671 if (call_streambuf_underflow(this) == EOF)
672 break;
673 chunk = this->egptr - this->gptr;
674 if (chunk > count - copied)
675 chunk = count - copied;
676 memcpy(buffer+copied, this->gptr, chunk);
677 this->gptr += chunk;
678 copied += chunk;
681 return copied;
684 /* ?xsputn@streambuf@@UAEHPBDH@Z */
685 /* ?xsputn@streambuf@@UEAAHPEBDH@Z */
686 DEFINE_THISCALL_WRAPPER(streambuf_xsputn, 12)
687 #define call_streambuf_xsputn(this, data, length) CALL_VTBL_FUNC(this, 20, int, (streambuf*, const char*, int), (this, data, length))
688 int __thiscall streambuf_xsputn(streambuf *this, const char *data, int length)
690 int copied = 0, chunk;
692 TRACE("(%p %p %d)\n", this, data, length);
694 while (copied < length) {
695 if (this->unbuffered || this->pptr == this->epptr) {
696 if (call_streambuf_overflow(this, data[copied]) == EOF)
697 break;
698 copied++;
699 } else {
700 chunk = this->epptr - this->pptr;
701 if (chunk > length - copied)
702 chunk = length - copied;
703 memcpy(this->pptr, data+copied, chunk);
704 this->pptr += chunk;
705 copied += chunk;
708 return copied;
711 /* ?sgetc@streambuf@@QAEHXZ */
712 /* ?sgetc@streambuf@@QEAAHXZ */
713 DEFINE_THISCALL_WRAPPER(streambuf_sgetc, 4)
714 int __thiscall streambuf_sgetc(streambuf *this)
716 TRACE("(%p)\n", this);
717 if (this->unbuffered) {
718 if (this->stored_char == EOF)
719 this->stored_char = call_streambuf_underflow(this);
720 return this->stored_char;
721 } else
722 return call_streambuf_underflow(this);
725 /* ?sputc@streambuf@@QAEHH@Z */
726 /* ?sputc@streambuf@@QEAAHH@Z */
727 DEFINE_THISCALL_WRAPPER(streambuf_sputc, 8)
728 int __thiscall streambuf_sputc(streambuf *this, int ch)
730 TRACE("(%p %d)\n", this, ch);
731 return (this->pptr < this->epptr) ? *this->pptr++ = ch : call_streambuf_overflow(this, ch);
734 /* ?sgetn@streambuf@@QAEHPADH@Z */
735 /* ?sgetn@streambuf@@QEAAHPEADH@Z */
736 DEFINE_THISCALL_WRAPPER(streambuf_sgetn, 12)
737 int __thiscall streambuf_sgetn(streambuf *this, char *buffer, int count)
739 return call_streambuf_xsgetn(this, buffer, count);
742 /* ?sputn@streambuf@@QAEHPBDH@Z */
743 /* ?sputn@streambuf@@QEAAHPEBDH@Z */
744 DEFINE_THISCALL_WRAPPER(streambuf_sputn, 12)
745 int __thiscall streambuf_sputn(streambuf *this, const char *data, int length)
747 return call_streambuf_xsputn(this, data, length);
750 /* ?snextc@streambuf@@QAEHXZ */
751 /* ?snextc@streambuf@@QEAAHXZ */
752 DEFINE_THISCALL_WRAPPER(streambuf_snextc, 4)
753 int __thiscall streambuf_snextc(streambuf *this)
755 TRACE("(%p)\n", this);
756 if (this->unbuffered) {
757 if (this->stored_char == EOF)
758 call_streambuf_underflow(this);
759 return this->stored_char = call_streambuf_underflow(this);
760 } else {
761 if (this->gptr >= this->egptr)
762 call_streambuf_underflow(this);
763 this->gptr++;
764 return (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
768 /* ?sbumpc@streambuf@@QAEHXZ */
769 /* ?sbumpc@streambuf@@QEAAHXZ */
770 DEFINE_THISCALL_WRAPPER(streambuf_sbumpc, 4)
771 int __thiscall streambuf_sbumpc(streambuf *this)
773 int ret;
775 TRACE("(%p)\n", this);
777 if (this->unbuffered) {
778 ret = this->stored_char;
779 this->stored_char = EOF;
780 if (ret == EOF)
781 ret = call_streambuf_underflow(this);
782 } else {
783 ret = (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
784 this->gptr++;
786 return ret;
789 /* ?stossc@streambuf@@QAEXXZ */
790 /* ?stossc@streambuf@@QEAAXXZ */
791 DEFINE_THISCALL_WRAPPER(streambuf_stossc, 4)
792 void __thiscall streambuf_stossc(streambuf *this)
794 TRACE("(%p)\n", this);
795 if (this->unbuffered) {
796 if (this->stored_char == EOF)
797 call_streambuf_underflow(this);
798 else
799 this->stored_char = EOF;
800 } else {
801 if (this->gptr >= this->egptr)
802 call_streambuf_underflow(this);
803 if (this->gptr < this->egptr)
804 this->gptr++;
808 /* ?sputbackc@streambuf@@QAEHD@Z */
809 /* ?sputbackc@streambuf@@QEAAHD@Z */
810 DEFINE_THISCALL_WRAPPER(streambuf_sputbackc, 8)
811 int __thiscall streambuf_sputbackc(streambuf *this, char ch)
813 TRACE("(%p %d)\n", this, ch);
814 return call_streambuf_pbackfail(this, ch);
817 /* ?dbp@streambuf@@QAEXXZ */
818 /* ?dbp@streambuf@@QEAAXXZ */
819 DEFINE_THISCALL_WRAPPER(streambuf_dbp, 4)
820 void __thiscall streambuf_dbp(streambuf *this)
822 printf("\nSTREAMBUF DEBUG INFO: this=%p, ", this);
823 if (this->unbuffered) {
824 printf("unbuffered\n");
825 } else {
826 printf("_fAlloc=%d\n", this->allocated);
827 printf(" base()=%p, ebuf()=%p, blen()=%d\n", this->base, this->ebuf, streambuf_blen(this));
828 printf("pbase()=%p, pptr()=%p, epptr()=%p\n", this->pbase, this->pptr, this->epptr);
829 printf("eback()=%p, gptr()=%p, egptr()=%p\n", this->eback, this->gptr, this->egptr);
833 /* ??0filebuf@@QAE@ABV0@@Z */
834 /* ??0filebuf@@QEAA@AEBV0@@Z */
835 DEFINE_THISCALL_WRAPPER(filebuf_copy_ctor, 8)
836 filebuf* __thiscall filebuf_copy_ctor(filebuf* this, const filebuf *copy)
838 TRACE("(%p %p)\n", this, copy);
839 *this = *copy;
840 this->base.vtable = &MSVCP_filebuf_vtable;
841 return this;
844 /* ??0filebuf@@QAE@HPADH@Z */
845 /* ??0filebuf@@QEAA@HPEADH@Z */
846 DEFINE_THISCALL_WRAPPER(filebuf_fd_reserve_ctor, 16)
847 filebuf* __thiscall filebuf_fd_reserve_ctor(filebuf* this, filedesc fd, char *buffer, int length)
849 TRACE("(%p %d %p %d)\n", this, fd, buffer, length);
850 streambuf_reserve_ctor(&this->base, buffer, length);
851 this->base.vtable = &MSVCP_filebuf_vtable;
852 this->fd = fd;
853 this->close = 0;
854 return this;
857 /* ??0filebuf@@QAE@H@Z */
858 /* ??0filebuf@@QEAA@H@Z */
859 DEFINE_THISCALL_WRAPPER(filebuf_fd_ctor, 8)
860 filebuf* __thiscall filebuf_fd_ctor(filebuf* this, filedesc fd)
862 filebuf_fd_reserve_ctor(this, fd, NULL, 0);
863 this->base.unbuffered = 0;
864 return this;
867 /* ??0filebuf@@QAE@XZ */
868 /* ??0filebuf@@QEAA@XZ */
869 DEFINE_THISCALL_WRAPPER(filebuf_ctor, 4)
870 filebuf* __thiscall filebuf_ctor(filebuf* this)
872 return filebuf_fd_ctor(this, -1);
875 /* ??1filebuf@@UAE@XZ */
876 /* ??1filebuf@@UEAA@XZ */
877 DEFINE_THISCALL_WRAPPER(filebuf_dtor, 4)
878 void __thiscall filebuf_dtor(filebuf* this)
880 TRACE("(%p)\n", this);
881 if (this->close)
882 filebuf_close(this);
883 streambuf_dtor(&this->base);
886 /* ??4filebuf@@QAEAAV0@ABV0@@Z */
887 /* ??4filebuf@@QEAAAEAV0@AEBV0@@Z */
888 DEFINE_THISCALL_WRAPPER(filebuf_assign, 8)
889 filebuf* __thiscall filebuf_assign(filebuf* this, const filebuf *rhs)
891 filebuf_dtor(this);
892 return filebuf_copy_ctor(this, rhs);
895 /* ??_Efilebuf@@UAEPAXI@Z */
896 DEFINE_THISCALL_WRAPPER(filebuf_vector_dtor, 8)
897 filebuf* __thiscall filebuf_vector_dtor(filebuf *this, unsigned int flags)
899 TRACE("(%p %x)\n", this, flags);
900 if (flags & 2) {
901 /* we have an array, with the number of elements stored before the first object */
902 INT_PTR i, *ptr = (INT_PTR *)this-1;
904 for (i = *ptr-1; i >= 0; i--)
905 filebuf_dtor(this+i);
906 MSVCRT_operator_delete(ptr);
907 } else {
908 filebuf_dtor(this);
909 if (flags & 1)
910 MSVCRT_operator_delete(this);
912 return this;
915 /* ??_Gfilebuf@@UAEPAXI@Z */
916 DEFINE_THISCALL_WRAPPER(filebuf_scalar_dtor, 8)
917 filebuf* __thiscall filebuf_scalar_dtor(filebuf *this, unsigned int flags)
919 TRACE("(%p %x)\n", this, flags);
920 filebuf_dtor(this);
921 if (flags & 1) MSVCRT_operator_delete(this);
922 return this;
925 /* ?attach@filebuf@@QAEPAV1@H@Z */
926 /* ?attach@filebuf@@QEAAPEAV1@H@Z */
927 DEFINE_THISCALL_WRAPPER(filebuf_attach, 8)
928 filebuf* __thiscall filebuf_attach(filebuf *this, filedesc fd)
930 TRACE("(%p %d)\n", this, fd);
931 if (this->fd != -1)
932 return NULL;
934 streambuf_lock(&this->base);
935 this->fd = fd;
936 streambuf_allocate(&this->base);
937 streambuf_unlock(&this->base);
938 return this;
941 /* ?close@filebuf@@QAEPAV1@XZ */
942 /* ?close@filebuf@@QEAAPEAV1@XZ */
943 DEFINE_THISCALL_WRAPPER(filebuf_close, 4)
944 filebuf* __thiscall filebuf_close(filebuf *this)
946 filebuf *ret;
948 TRACE("(%p)\n", this);
949 if (this->fd == -1)
950 return NULL;
952 streambuf_lock(&this->base);
953 if (call_streambuf_sync(&this->base) == EOF || _close(this->fd) < 0) {
954 ret = NULL;
955 } else {
956 this->fd = -1;
957 ret = this;
959 streambuf_unlock(&this->base);
960 return ret;
963 /* ?fd@filebuf@@QBEHXZ */
964 /* ?fd@filebuf@@QEBAHXZ */
965 DEFINE_THISCALL_WRAPPER(filebuf_fd, 4)
966 filedesc __thiscall filebuf_fd(const filebuf *this)
968 TRACE("(%p)\n", this);
969 return this->fd;
972 /* ?is_open@filebuf@@QBEHXZ */
973 /* ?is_open@filebuf@@QEBAHXZ */
974 DEFINE_THISCALL_WRAPPER(filebuf_is_open, 4)
975 int __thiscall filebuf_is_open(const filebuf *this)
977 TRACE("(%p)\n", this);
978 return this->fd != -1;
981 /* ?open@filebuf@@QAEPAV1@PBDHH@Z */
982 /* ?open@filebuf@@QEAAPEAV1@PEBDHH@Z */
983 DEFINE_THISCALL_WRAPPER(filebuf_open, 16)
984 filebuf* __thiscall filebuf_open(filebuf *this, const char *name, ios_open_mode mode, int protection)
986 const int inout_mode[4] = {-1, _O_RDONLY, _O_WRONLY, _O_RDWR};
987 const int share_mode[4] = {_SH_DENYRW, _SH_DENYWR, _SH_DENYRD, _SH_DENYNO};
988 int op_flags, sh_flags, fd;
990 TRACE("(%p %s %x %x)\n", this, name, mode, protection);
991 if (this->fd != -1)
992 return NULL;
994 /* mode */
995 if (mode & (OPENMODE_app|OPENMODE_trunc))
996 mode |= OPENMODE_out;
997 op_flags = inout_mode[mode & (OPENMODE_in|OPENMODE_out)];
998 if (op_flags < 0)
999 return NULL;
1000 if (mode & OPENMODE_app)
1001 op_flags |= _O_APPEND;
1002 if ((mode & OPENMODE_trunc) ||
1003 ((mode & OPENMODE_out) && !(mode & (OPENMODE_in|OPENMODE_app|OPENMODE_ate))))
1004 op_flags |= _O_TRUNC;
1005 if (!(mode & OPENMODE_nocreate))
1006 op_flags |= _O_CREAT;
1007 if (mode & OPENMODE_noreplace)
1008 op_flags |= _O_EXCL;
1009 op_flags |= (mode & OPENMODE_binary) ? _O_BINARY : _O_TEXT;
1011 /* share protection */
1012 sh_flags = (protection & filebuf_sh_none) ? share_mode[(protection >> 9) & 3] : _SH_DENYNO;
1014 TRACE("op_flags %x, sh_flags %x\n", op_flags, sh_flags);
1015 fd = _sopen(name, op_flags, sh_flags, _S_IREAD|_S_IWRITE);
1016 if (fd < 0)
1017 return NULL;
1019 streambuf_lock(&this->base);
1020 this->close = 1;
1021 this->fd = fd;
1022 if ((mode & OPENMODE_ate) &&
1023 call_streambuf_seekoff(&this->base, 0, SEEKDIR_end, mode & (OPENMODE_in|OPENMODE_out)) == EOF) {
1024 _close(fd);
1025 this->fd = -1;
1027 streambuf_allocate(&this->base);
1028 streambuf_unlock(&this->base);
1029 return (this->fd == -1) ? NULL : this;
1032 /* ?overflow@filebuf@@UAEHH@Z */
1033 /* ?overflow@filebuf@@UEAAHH@Z */
1034 DEFINE_THISCALL_WRAPPER(filebuf_overflow, 8)
1035 int __thiscall filebuf_overflow(filebuf *this, int c)
1037 TRACE("(%p %d)\n", this, c);
1038 if (call_streambuf_sync(&this->base) == EOF)
1039 return EOF;
1040 if (this->base.unbuffered)
1041 return (c == EOF) ? 1 : _write(this->fd, &c, 1);
1042 if (streambuf_allocate(&this->base) == EOF)
1043 return EOF;
1045 this->base.pbase = this->base.pptr = this->base.base;
1046 this->base.epptr = this->base.ebuf;
1047 if (c != EOF)
1048 *this->base.pptr++ = c;
1049 return 1;
1052 /* ?seekoff@filebuf@@UAEJJW4seek_dir@ios@@H@Z */
1053 /* ?seekoff@filebuf@@UEAAJJW4seek_dir@ios@@H@Z */
1054 DEFINE_THISCALL_WRAPPER(filebuf_seekoff, 16)
1055 streampos __thiscall filebuf_seekoff(filebuf *this, streamoff offset, ios_seek_dir dir, int mode)
1057 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
1058 if (call_streambuf_sync(&this->base) == EOF)
1059 return EOF;
1060 return _lseek(this->fd, offset, dir);
1063 /* ?setbuf@filebuf@@UAEPAVstreambuf@@PADH@Z */
1064 /* ?setbuf@filebuf@@UEAAPEAVstreambuf@@PEADH@Z */
1065 DEFINE_THISCALL_WRAPPER(filebuf_setbuf, 12)
1066 streambuf* __thiscall filebuf_setbuf(filebuf *this, char *buffer, int length)
1068 streambuf *ret;
1070 TRACE("(%p %p %d)\n", this, buffer, length);
1071 if (this->base.base != NULL)
1072 return NULL;
1074 streambuf_lock(&this->base);
1075 ret = streambuf_setbuf(&this->base, buffer, length);
1076 streambuf_unlock(&this->base);
1077 return ret;
1080 /* ?setmode@filebuf@@QAEHH@Z */
1081 /* ?setmode@filebuf@@QEAAHH@Z */
1082 DEFINE_THISCALL_WRAPPER(filebuf_setmode, 8)
1083 int __thiscall filebuf_setmode(filebuf *this, int mode)
1085 int ret;
1087 TRACE("(%p %d)\n", this, mode);
1088 if (mode != filebuf_text && mode != filebuf_binary)
1089 return -1;
1091 streambuf_lock(&this->base);
1092 ret = (call_streambuf_sync(&this->base) == EOF) ? -1 : _setmode(this->fd, mode);
1093 streambuf_unlock(&this->base);
1094 return ret;
1097 /* ?sync@filebuf@@UAEHXZ */
1098 /* ?sync@filebuf@@UEAAHXZ */
1099 DEFINE_THISCALL_WRAPPER(filebuf_sync, 4)
1100 int __thiscall filebuf_sync(filebuf *this)
1102 int count, mode;
1103 char *ptr;
1104 LONG offset;
1106 TRACE("(%p)\n", this);
1107 if (this->fd == -1)
1108 return EOF;
1109 if (this->base.unbuffered)
1110 return 0;
1112 /* flush output buffer */
1113 if (this->base.pptr != NULL) {
1114 count = this->base.pptr - this->base.pbase;
1115 if (count > 0 && _write(this->fd, this->base.pbase, count) != count)
1116 return EOF;
1117 this->base.pbase = this->base.pptr = this->base.epptr = NULL;
1119 /* flush input buffer */
1120 if (this->base.egptr != NULL) {
1121 offset = this->base.egptr - this->base.gptr;
1122 if (offset > 0) {
1123 mode = _setmode(this->fd, _O_TEXT);
1124 _setmode(this->fd, mode);
1125 if (mode & _O_TEXT) {
1126 /* in text mode, '\n' in the buffer means '\r\n' in the file */
1127 for (ptr = this->base.gptr; ptr < this->base.egptr; ptr++)
1128 if (*ptr == '\n')
1129 offset++;
1131 if (_lseek(this->fd, -offset, SEEK_CUR) < 0)
1132 return EOF;
1134 this->base.eback = this->base.gptr = this->base.egptr = NULL;
1136 return 0;
1139 /* ?underflow@filebuf@@UAEHXZ */
1140 /* ?underflow@filebuf@@UEAAHXZ */
1141 DEFINE_THISCALL_WRAPPER(filebuf_underflow, 4)
1142 int __thiscall filebuf_underflow(filebuf *this)
1144 int buffer_size, read_bytes;
1145 char c;
1147 TRACE("(%p)\n", this);
1149 if (this->base.unbuffered)
1150 return (_read(this->fd, &c, 1) < 1) ? EOF : c;
1152 if (this->base.gptr >= this->base.egptr) {
1153 if (call_streambuf_sync(&this->base) == EOF)
1154 return EOF;
1155 buffer_size = this->base.ebuf - this->base.base;
1156 read_bytes = _read(this->fd, this->base.base, buffer_size);
1157 if (read_bytes <= 0)
1158 return EOF;
1159 this->base.eback = this->base.gptr = this->base.base;
1160 this->base.egptr = this->base.base + read_bytes;
1162 return *this->base.gptr;
1165 /* ??0strstreambuf@@QAE@ABV0@@Z */
1166 /* ??0strstreambuf@@QEAA@AEBV0@@Z */
1167 DEFINE_THISCALL_WRAPPER(strstreambuf_copy_ctor, 8)
1168 strstreambuf* __thiscall strstreambuf_copy_ctor(strstreambuf *this, const strstreambuf *copy)
1170 TRACE("(%p %p)\n", this, copy);
1171 *this = *copy;
1172 this->base.vtable = &MSVCP_strstreambuf_vtable;
1173 return this;
1176 /* ??0strstreambuf@@QAE@H@Z */
1177 /* ??0strstreambuf@@QEAA@H@Z */
1178 DEFINE_THISCALL_WRAPPER(strstreambuf_dynamic_ctor, 8)
1179 strstreambuf* __thiscall strstreambuf_dynamic_ctor(strstreambuf* this, int length)
1181 TRACE("(%p %d)\n", this, length);
1182 streambuf_ctor(&this->base);
1183 this->base.vtable = &MSVCP_strstreambuf_vtable;
1184 this->dynamic = 1;
1185 this->increase = length;
1186 this->constant = 0;
1187 this->f_alloc = NULL;
1188 this->f_free = NULL;
1189 return this;
1192 /* ??0strstreambuf@@QAE@P6APAXJ@ZP6AXPAX@Z@Z */
1193 /* ??0strstreambuf@@QEAA@P6APEAXJ@ZP6AXPEAX@Z@Z */
1194 DEFINE_THISCALL_WRAPPER(strstreambuf_funcs_ctor, 12)
1195 strstreambuf* __thiscall strstreambuf_funcs_ctor(strstreambuf* this, allocFunction falloc, freeFunction ffree)
1197 TRACE("(%p %p %p)\n", this, falloc, ffree);
1198 strstreambuf_dynamic_ctor(this, 1);
1199 this->f_alloc = falloc;
1200 this->f_free = ffree;
1201 return this;
1204 /* ??0strstreambuf@@QAE@PADH0@Z */
1205 /* ??0strstreambuf@@QEAA@PEADH0@Z */
1206 DEFINE_THISCALL_WRAPPER(strstreambuf_buffer_ctor, 16)
1207 strstreambuf* __thiscall strstreambuf_buffer_ctor(strstreambuf *this, char *buffer, int length, char *put)
1209 char *end_buffer;
1211 TRACE("(%p %p %d %p)\n", this, buffer, length, put);
1213 if (length > 0)
1214 end_buffer = buffer + length;
1215 else if (length == 0)
1216 end_buffer = buffer + strlen(buffer);
1217 else
1218 end_buffer = (char*) -1;
1220 streambuf_ctor(&this->base);
1221 streambuf_setb(&this->base, buffer, end_buffer, 0);
1222 if (put == NULL) {
1223 streambuf_setg(&this->base, buffer, buffer, end_buffer);
1224 } else {
1225 streambuf_setg(&this->base, buffer, buffer, put);
1226 streambuf_setp(&this->base, put, end_buffer);
1228 this->base.vtable = &MSVCP_strstreambuf_vtable;
1229 this->dynamic = 0;
1230 this->constant = 1;
1231 return this;
1234 /* ??0strstreambuf@@QAE@PAEH0@Z */
1235 /* ??0strstreambuf@@QEAA@PEAEH0@Z */
1236 DEFINE_THISCALL_WRAPPER(strstreambuf_ubuffer_ctor, 16)
1237 strstreambuf* __thiscall strstreambuf_ubuffer_ctor(strstreambuf *this, unsigned char *buffer, int length, unsigned char *put)
1239 TRACE("(%p %p %d %p)\n", this, buffer, length, put);
1240 return strstreambuf_buffer_ctor(this, (char*)buffer, length, (char*)put);
1243 /* ??0strstreambuf@@QAE@XZ */
1244 /* ??0strstreambuf@@QEAA@XZ */
1245 DEFINE_THISCALL_WRAPPER(strstreambuf_ctor, 4)
1246 strstreambuf* __thiscall strstreambuf_ctor(strstreambuf *this)
1248 TRACE("(%p)\n", this);
1249 return strstreambuf_dynamic_ctor(this, 1);
1252 /* ??1strstreambuf@@UAE@XZ */
1253 /* ??1strstreambuf@@UEAA@XZ */
1254 DEFINE_THISCALL_WRAPPER(strstreambuf_dtor, 4)
1255 void __thiscall strstreambuf_dtor(strstreambuf *this)
1257 TRACE("(%p)\n", this);
1258 if (this->dynamic && this->base.base) {
1259 if (this->f_free)
1260 this->f_free(this->base.base);
1261 else
1262 MSVCRT_operator_delete(this->base.base);
1264 streambuf_dtor(&this->base);
1267 /* ??4strstreambuf@@QAEAAV0@ABV0@@Z */
1268 /* ??4strstreambuf@@QEAAAEAV0@AEBV0@@Z */
1269 DEFINE_THISCALL_WRAPPER(strstreambuf_assign, 8)
1270 strstreambuf* __thiscall strstreambuf_assign(strstreambuf *this, const strstreambuf *rhs)
1272 strstreambuf_dtor(this);
1273 return strstreambuf_copy_ctor(this, rhs);
1276 /* ??_Estrstreambuf@@UAEPAXI@Z */
1277 DEFINE_THISCALL_WRAPPER(strstreambuf_vector_dtor, 8)
1278 strstreambuf* __thiscall strstreambuf_vector_dtor(strstreambuf *this, unsigned int flags)
1280 TRACE("(%p %x)\n", this, flags);
1281 if (flags & 2) {
1282 /* we have an array, with the number of elements stored before the first object */
1283 INT_PTR i, *ptr = (INT_PTR *)this-1;
1285 for (i = *ptr-1; i >= 0; i--)
1286 strstreambuf_dtor(this+i);
1287 MSVCRT_operator_delete(ptr);
1288 } else {
1289 strstreambuf_dtor(this);
1290 if (flags & 1)
1291 MSVCRT_operator_delete(this);
1293 return this;
1296 /* ??_Gstrstreambuf@@UAEPAXI@Z */
1297 DEFINE_THISCALL_WRAPPER(strstreambuf_scalar_dtor, 8)
1298 strstreambuf* __thiscall strstreambuf_scalar_dtor(strstreambuf *this, unsigned int flags)
1300 TRACE("(%p %x)\n", this, flags);
1301 strstreambuf_dtor(this);
1302 if (flags & 1) MSVCRT_operator_delete(this);
1303 return this;
1306 /* ?doallocate@strstreambuf@@MAEHXZ */
1307 /* ?doallocate@strstreambuf@@MEAAHXZ */
1308 DEFINE_THISCALL_WRAPPER(strstreambuf_doallocate, 4)
1309 int __thiscall strstreambuf_doallocate(strstreambuf *this)
1311 char *prev_buffer = this->base.base, *new_buffer;
1312 LONG prev_size = this->base.ebuf - this->base.base, new_size;
1314 TRACE("(%p)\n", this);
1316 /* calculate the size of the new buffer */
1317 new_size = (prev_size > 0 ? prev_size : 0) + (this->increase > 0 ? this->increase : 1);
1318 /* get a new buffer */
1319 if (this->f_alloc)
1320 new_buffer = this->f_alloc(new_size);
1321 else
1322 new_buffer = MSVCRT_operator_new(new_size);
1323 if (!new_buffer)
1324 return EOF;
1325 if (this->base.ebuf) {
1326 /* copy the contents and adjust the pointers */
1327 memcpy(new_buffer, this->base.base, prev_size);
1328 if (this->base.egptr) {
1329 this->base.eback += new_buffer - prev_buffer;
1330 this->base.gptr += new_buffer - prev_buffer;
1331 this->base.egptr += new_buffer - prev_buffer;
1333 if (this->base.epptr) {
1334 this->base.pbase += new_buffer - prev_buffer;
1335 this->base.pptr += new_buffer - prev_buffer;
1336 this->base.epptr += new_buffer - prev_buffer;
1338 /* free the old buffer */
1339 if (this->f_free)
1340 this->f_free(this->base.base);
1341 else
1342 MSVCRT_operator_delete(this->base.base);
1344 streambuf_setb(&this->base, new_buffer, new_buffer + new_size, 0);
1345 return 1;
1348 /* ?freeze@strstreambuf@@QAEXH@Z */
1349 /* ?freeze@strstreambuf@@QEAAXH@Z */
1350 DEFINE_THISCALL_WRAPPER(strstreambuf_freeze, 8)
1351 void __thiscall strstreambuf_freeze(strstreambuf *this, int frozen)
1353 TRACE("(%p %d)\n", this, frozen);
1354 if (!this->constant)
1355 this->dynamic = !frozen;
1358 /* ?overflow@strstreambuf@@UAEHH@Z */
1359 /* ?overflow@strstreambuf@@UEAAHH@Z */
1360 DEFINE_THISCALL_WRAPPER(strstreambuf_overflow, 8)
1361 int __thiscall strstreambuf_overflow(strstreambuf *this, int c)
1363 TRACE("(%p %d)\n", this, c);
1364 if (this->base.pptr >= this->base.epptr) {
1365 /* increase the buffer size if it's dynamic */
1366 if (!this->dynamic || call_streambuf_doallocate(&this->base) == EOF)
1367 return EOF;
1368 if (!this->base.epptr)
1369 this->base.pbase = this->base.pptr = this->base.egptr ? this->base.egptr : this->base.base;
1370 this->base.epptr = this->base.ebuf;
1372 if (c != EOF)
1373 *this->base.pptr++ = c;
1374 return 1;
1377 /* ?seekoff@strstreambuf@@UAEJJW4seek_dir@ios@@H@Z */
1378 /* ?seekoff@strstreambuf@@UEAAJJW4seek_dir@ios@@H@Z */
1379 DEFINE_THISCALL_WRAPPER(strstreambuf_seekoff, 16)
1380 streampos __thiscall strstreambuf_seekoff(strstreambuf *this, streamoff offset, ios_seek_dir dir, int mode)
1382 char *base[3];
1384 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
1386 if (dir < SEEKDIR_beg || dir > SEEKDIR_end || !(mode & (OPENMODE_in|OPENMODE_out)))
1387 return EOF;
1388 /* read buffer */
1389 if (mode & OPENMODE_in) {
1390 call_streambuf_underflow(&this->base);
1391 base[SEEKDIR_beg] = this->base.eback;
1392 base[SEEKDIR_cur] = this->base.gptr;
1393 base[SEEKDIR_end] = this->base.egptr;
1394 if (base[dir] + offset < this->base.eback || base[dir] + offset > this->base.egptr)
1395 return EOF;
1396 this->base.gptr = base[dir] + offset;
1398 /* write buffer */
1399 if (mode & OPENMODE_out) {
1400 if (!this->base.epptr && call_streambuf_overflow(&this->base, EOF) == EOF)
1401 return EOF;
1402 base[SEEKDIR_beg] = this->base.pbase;
1403 base[SEEKDIR_cur] = this->base.pptr;
1404 base[SEEKDIR_end] = this->base.epptr;
1405 if (base[dir] + offset < this->base.pbase)
1406 return EOF;
1407 if (base[dir] + offset > this->base.epptr) {
1408 /* make room if the buffer is dynamic */
1409 if (!this->dynamic)
1410 return EOF;
1411 this->increase = offset;
1412 if (call_streambuf_doallocate(&this->base) == EOF)
1413 return EOF;
1415 this->base.pptr = base[dir] + offset;
1416 return this->base.pptr - base[SEEKDIR_beg];
1418 return this->base.gptr - base[SEEKDIR_beg];
1421 /* ?setbuf@strstreambuf@@UAEPAVstreambuf@@PADH@Z */
1422 /* ?setbuf@strstreambuf@@UEAAPEAVstreambuf@@PEADH@Z */
1423 DEFINE_THISCALL_WRAPPER(strstreambuf_setbuf, 12)
1424 streambuf* __thiscall strstreambuf_setbuf(strstreambuf *this, char *buffer, int length)
1426 TRACE("(%p %p %d)\n", this, buffer, length);
1427 if (length)
1428 this->increase = length;
1429 return &this->base;
1432 /* ?str@strstreambuf@@QAEPADXZ */
1433 /* ?str@strstreambuf@@QEAAPEADXZ */
1434 DEFINE_THISCALL_WRAPPER(strstreambuf_str, 4)
1435 char* __thiscall strstreambuf_str(strstreambuf *this)
1437 TRACE("(%p)\n", this);
1438 strstreambuf_freeze(this, 1);
1439 return this->base.base;
1442 /* ?sync@strstreambuf@@UAEHXZ */
1443 /* ?sync@strstreambuf@@UEAAHXZ */
1444 DEFINE_THISCALL_WRAPPER(strstreambuf_sync, 4)
1445 int __thiscall strstreambuf_sync(strstreambuf *this)
1447 TRACE("(%p)\n", this);
1448 return 0;
1451 /* ?underflow@strstreambuf@@UAEHXZ */
1452 /* ?underflow@strstreambuf@@UEAAHXZ */
1453 DEFINE_THISCALL_WRAPPER(strstreambuf_underflow, 4)
1454 int __thiscall strstreambuf_underflow(strstreambuf *this)
1456 TRACE("(%p)\n", this);
1457 if (this->base.gptr < this->base.egptr)
1458 return *this->base.gptr;
1459 /* extend the get area to include the characters written */
1460 if (this->base.egptr < this->base.pptr)
1461 this->base.egptr = this->base.pptr;
1462 return (this->base.gptr < this->base.egptr) ? *this->base.gptr : EOF;
1465 /* ??0stdiobuf@@QAE@ABV0@@Z */
1466 /* ??0stdiobuf@@QEAA@AEBV0@@Z */
1467 DEFINE_THISCALL_WRAPPER(stdiobuf_copy_ctor, 8)
1468 stdiobuf* __thiscall stdiobuf_copy_ctor(stdiobuf *this, const stdiobuf *copy)
1470 TRACE("(%p %p)\n", this, copy);
1471 *this = *copy;
1472 this->base.vtable = &MSVCP_stdiobuf_vtable;
1473 return this;
1476 /* ??0stdiobuf@@QAE@PAU_iobuf@@@Z */
1477 /* ??0stdiobuf@@QEAA@PEAU_iobuf@@@Z */
1478 DEFINE_THISCALL_WRAPPER(stdiobuf_file_ctor, 8)
1479 stdiobuf* __thiscall stdiobuf_file_ctor(stdiobuf *this, FILE *file)
1481 TRACE("(%p %p)\n", this, file);
1482 streambuf_reserve_ctor(&this->base, NULL, 0);
1483 this->base.vtable = &MSVCP_stdiobuf_vtable;
1484 this->file = file;
1485 return this;
1488 /* ??1stdiobuf@@UAE@XZ */
1489 /* ??1stdiobuf@@UEAA@XZ */
1490 DEFINE_THISCALL_WRAPPER(stdiobuf_dtor, 4)
1491 void __thiscall stdiobuf_dtor(stdiobuf *this)
1493 TRACE("(%p)\n", this);
1494 call_streambuf_sync(&this->base);
1495 streambuf_dtor(&this->base);
1498 /* ??4stdiobuf@@QAEAAV0@ABV0@@Z */
1499 /* ??4stdiobuf@@QEAAAEAV0@AEBV0@@Z */
1500 DEFINE_THISCALL_WRAPPER(stdiobuf_assign, 8)
1501 stdiobuf* __thiscall stdiobuf_assign(stdiobuf *this, const stdiobuf *rhs)
1503 stdiobuf_dtor(this);
1504 return stdiobuf_copy_ctor(this, rhs);
1507 /* ??_Estdiobuf@@UAEPAXI@Z */
1508 DEFINE_THISCALL_WRAPPER(stdiobuf_vector_dtor, 8)
1509 stdiobuf* __thiscall stdiobuf_vector_dtor(stdiobuf *this, unsigned int flags)
1511 TRACE("(%p %x)\n", this, flags);
1512 if (flags & 2) {
1513 /* we have an array, with the number of elements stored before the first object */
1514 INT_PTR i, *ptr = (INT_PTR *)this-1;
1516 for (i = *ptr-1; i >= 0; i--)
1517 stdiobuf_dtor(this+i);
1518 MSVCRT_operator_delete(ptr);
1519 } else {
1520 stdiobuf_dtor(this);
1521 if (flags & 1)
1522 MSVCRT_operator_delete(this);
1524 return this;
1527 /* ??_Gstdiobuf@@UAEPAXI@Z */
1528 DEFINE_THISCALL_WRAPPER(stdiobuf_scalar_dtor, 8)
1529 stdiobuf* __thiscall stdiobuf_scalar_dtor(stdiobuf *this, unsigned int flags)
1531 TRACE("(%p %x)\n", this, flags);
1532 stdiobuf_dtor(this);
1533 if (flags & 1) MSVCRT_operator_delete(this);
1534 return this;
1537 /* ?overflow@stdiobuf@@UAEHH@Z */
1538 /* ?overflow@stdiobuf@@UEAAHH@Z */
1539 DEFINE_THISCALL_WRAPPER(stdiobuf_overflow, 8)
1540 int __thiscall stdiobuf_overflow(stdiobuf *this, int c)
1542 TRACE("(%p %d)\n", this, c);
1543 if (this->base.unbuffered)
1544 return (c == EOF) ? 1 : fputc(c, this->file);
1545 if (streambuf_allocate(&this->base) == EOF)
1546 return EOF;
1548 if (!this->base.epptr) {
1549 /* set the put area to the second half of the buffer */
1550 streambuf_setp(&this->base,
1551 this->base.base + (this->base.ebuf - this->base.base) / 2, this->base.ebuf);
1552 } else if (this->base.pptr > this->base.pbase) {
1553 /* flush the put area */
1554 int count = this->base.pptr - this->base.pbase;
1555 if (fwrite(this->base.pbase, sizeof(char), count, this->file) != count)
1556 return EOF;
1557 this->base.pptr = this->base.pbase;
1559 if (c != EOF) {
1560 if (this->base.pbase >= this->base.epptr)
1561 return fputc(c, this->file);
1562 *this->base.pptr++ = c;
1564 return 1;
1567 /* ?pbackfail@stdiobuf@@UAEHH@Z */
1568 /* ?pbackfail@stdiobuf@@UEAAHH@Z */
1569 DEFINE_THISCALL_WRAPPER(stdiobuf_pbackfail, 8)
1570 int __thiscall stdiobuf_pbackfail(stdiobuf *this, int c)
1572 TRACE("(%p %d)\n", this, c);
1573 return streambuf_pbackfail(&this->base, c);
1576 /* ?seekoff@stdiobuf@@UAEJJW4seek_dir@ios@@H@Z */
1577 /* ?seekoff@stdiobuf@@UEAAJJW4seek_dir@ios@@H@Z */
1578 DEFINE_THISCALL_WRAPPER(stdiobuf_seekoff, 16)
1579 streampos __thiscall stdiobuf_seekoff(stdiobuf *this, streamoff offset, ios_seek_dir dir, int mode)
1581 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
1582 call_streambuf_overflow(&this->base, EOF);
1583 if (fseek(this->file, offset, dir))
1584 return EOF;
1585 return ftell(this->file);
1588 /* ?setrwbuf@stdiobuf@@QAEHHH@Z */
1589 /* ?setrwbuf@stdiobuf@@QEAAHHH@Z */
1590 DEFINE_THISCALL_WRAPPER(stdiobuf_setrwbuf, 12)
1591 int __thiscall stdiobuf_setrwbuf(stdiobuf *this, int read_size, int write_size)
1593 char *reserve;
1594 int buffer_size = read_size + write_size;
1596 TRACE("(%p %d %d)\n", this, read_size, write_size);
1597 if (read_size < 0 || write_size < 0)
1598 return 0;
1599 if (!buffer_size) {
1600 this->base.unbuffered = 1;
1601 return 0;
1603 /* get a new buffer */
1604 reserve = MSVCRT_operator_new(buffer_size);
1605 if (!reserve)
1606 return 0;
1607 streambuf_setb(&this->base, reserve, reserve + buffer_size, 1);
1608 this->base.unbuffered = 0;
1609 /* set the get/put areas */
1610 if (read_size > 0)
1611 streambuf_setg(&this->base, reserve, reserve + read_size, reserve + read_size);
1612 else
1613 streambuf_setg(&this->base, NULL, NULL, NULL);
1614 if (write_size > 0)
1615 streambuf_setp(&this->base, reserve + read_size, reserve + buffer_size);
1616 else
1617 streambuf_setp(&this->base, NULL, NULL);
1618 return 1;
1621 /* ?stdiofile@stdiobuf@@QAEPAU_iobuf@@XZ */
1622 /* ?stdiofile@stdiobuf@@QEAAPEAU_iobuf@@XZ */
1623 DEFINE_THISCALL_WRAPPER(stdiobuf_stdiofile, 4)
1624 FILE* __thiscall stdiobuf_stdiofile(stdiobuf *this)
1626 TRACE("(%p)\n", this);
1627 return this->file;
1630 /* ?sync@stdiobuf@@UAEHXZ */
1631 /* ?sync@stdiobuf@@UEAAHXZ */
1632 DEFINE_THISCALL_WRAPPER(stdiobuf_sync, 4)
1633 int __thiscall stdiobuf_sync(stdiobuf *this)
1635 TRACE("(%p)\n", this);
1636 if (this->base.unbuffered)
1637 return 0;
1638 /* flush the put area */
1639 if (call_streambuf_overflow(&this->base, EOF) == EOF)
1640 return EOF;
1641 /* flush the get area */
1642 if (this->base.gptr < this->base.egptr) {
1643 char *ptr;
1644 int fd, mode, offset = this->base.egptr - this->base.gptr;
1645 if ((fd = fileno(this->file)) < 0)
1646 return EOF;
1647 mode = _setmode(fd, _O_TEXT);
1648 _setmode(fd, mode);
1649 if (mode & _O_TEXT) {
1650 /* in text mode, '\n' in the buffer means '\r\n' in the file */
1651 for (ptr = this->base.gptr; ptr < this->base.egptr; ptr++)
1652 if (*ptr == '\n')
1653 offset++;
1655 if (fseek(this->file, -offset, SEEK_CUR))
1656 return EOF;
1657 this->base.gptr = this->base.egptr;
1659 return 0;
1662 /* ?underflow@stdiobuf@@UAEHXZ */
1663 /* ?underflow@stdiobuf@@UEAAHXZ */
1664 DEFINE_THISCALL_WRAPPER(stdiobuf_underflow, 4)
1665 int __thiscall stdiobuf_underflow(stdiobuf *this)
1667 TRACE("(%p)\n", this);
1668 if (!this->file)
1669 return EOF;
1670 if (this->base.unbuffered)
1671 return fgetc(this->file);
1672 if (streambuf_allocate(&this->base) == EOF)
1673 return EOF;
1675 if (!this->base.egptr) {
1676 /* set the get area to the first half of the buffer */
1677 char *middle = this->base.base + (this->base.ebuf - this->base.base) / 2;
1678 streambuf_setg(&this->base, this->base.base, middle, middle);
1680 if (this->base.gptr >= this->base.egptr) {
1681 /* read characters from the file */
1682 int buffer_size = this->base.egptr - this->base.eback, read_bytes;
1683 if (!this->base.eback ||
1684 (read_bytes = fread(this->base.eback, sizeof(char), buffer_size, this->file)) <= 0)
1685 return EOF;
1686 memmove(this->base.egptr - read_bytes, this->base.eback, read_bytes);
1687 this->base.gptr = this->base.egptr - read_bytes;
1689 return *this->base.gptr++;
1692 /* ??0ios@@IAE@ABV0@@Z */
1693 /* ??0ios@@IEAA@AEBV0@@Z */
1694 DEFINE_THISCALL_WRAPPER(ios_copy_ctor, 8)
1695 ios* __thiscall ios_copy_ctor(ios *this, const ios *copy)
1697 TRACE("(%p %p)\n", this, copy);
1698 ios_fLockcInit++;
1699 this->vtable = &MSVCP_ios_vtable;
1700 this->sb = NULL;
1701 this->delbuf = 0;
1702 InitializeCriticalSection(&this->lock);
1703 return ios_assign(this, copy);
1706 /* ??0ios@@QAE@PAVstreambuf@@@Z */
1707 /* ??0ios@@QEAA@PEAVstreambuf@@@Z */
1708 DEFINE_THISCALL_WRAPPER(ios_sb_ctor, 8)
1709 ios* __thiscall ios_sb_ctor(ios *this, streambuf *sb)
1711 TRACE("(%p %p)\n", this, sb);
1712 ios_fLockcInit++;
1713 this->vtable = &MSVCP_ios_vtable;
1714 this->sb = sb;
1715 this->state = sb ? IOSTATE_goodbit : IOSTATE_badbit;
1716 this->special[0] = this->special[1] = 0;
1717 this->delbuf = 0;
1718 this->tie = NULL;
1719 this->flags = 0;
1720 this->precision = 6;
1721 this->fill = ' ';
1722 this->width = 0;
1723 this->do_lock = -1;
1724 InitializeCriticalSection(&this->lock);
1725 return this;
1728 /* ??0ios@@IAE@XZ */
1729 /* ??0ios@@IEAA@XZ */
1730 DEFINE_THISCALL_WRAPPER(ios_ctor, 4)
1731 ios* __thiscall ios_ctor(ios *this)
1733 return ios_sb_ctor(this, NULL);
1736 /* ??1ios@@UAE@XZ */
1737 /* ??1ios@@UEAA@XZ */
1738 DEFINE_THISCALL_WRAPPER(ios_dtor, 4)
1739 void __thiscall ios_dtor(ios *this)
1741 TRACE("(%p)\n", this);
1742 ios_fLockcInit--;
1743 if (this->delbuf && this->sb)
1744 call_streambuf_vector_dtor(this->sb, 1);
1745 this->sb = NULL;
1746 this->state = IOSTATE_badbit;
1747 DeleteCriticalSection(&this->lock);
1750 /* ??4ios@@IAEAAV0@ABV0@@Z */
1751 /* ??4ios@@IEAAAEAV0@AEBV0@@Z */
1752 DEFINE_THISCALL_WRAPPER(ios_assign, 8)
1753 ios* __thiscall ios_assign(ios *this, const ios *rhs)
1755 TRACE("(%p %p)\n", this, rhs);
1756 this->state = rhs->state;
1757 if (!this->sb)
1758 this->state |= IOSTATE_badbit;
1759 this->tie = rhs->tie;
1760 this->flags = rhs->flags;
1761 this->precision = (char) rhs->precision;
1762 this->fill = rhs->fill;
1763 this->width = (char) rhs->width;
1764 return this;
1767 /* ??7ios@@QBEHXZ */
1768 /* ??7ios@@QEBAHXZ */
1769 DEFINE_THISCALL_WRAPPER(ios_op_not, 4)
1770 int __thiscall ios_op_not(const ios *this)
1772 TRACE("(%p)\n", this);
1773 return ios_fail(this);
1776 /* ??Bios@@QBEPAXXZ */
1777 /* ??Bios@@QEBAPEAXXZ */
1778 DEFINE_THISCALL_WRAPPER(ios_op_void, 4)
1779 void* __thiscall ios_op_void(const ios *this)
1781 TRACE("(%p)\n", this);
1782 return ios_fail(this) ? NULL : (void*)this;
1785 /* ??_Eios@@UAEPAXI@Z */
1786 DEFINE_THISCALL_WRAPPER(ios_vector_dtor, 8)
1787 ios* __thiscall ios_vector_dtor(ios *this, unsigned int flags)
1789 TRACE("(%p %x)\n", this, flags);
1790 if (flags & 2) {
1791 /* we have an array, with the number of elements stored before the first object */
1792 INT_PTR i, *ptr = (INT_PTR *)this-1;
1794 for (i = *ptr-1; i >= 0; i--)
1795 ios_dtor(this+i);
1796 MSVCRT_operator_delete(ptr);
1797 } else {
1798 ios_dtor(this);
1799 if (flags & 1)
1800 MSVCRT_operator_delete(this);
1802 return this;
1805 /* ??_Gios@@UAEPAXI@Z */
1806 DEFINE_THISCALL_WRAPPER(ios_scalar_dtor, 8)
1807 ios* __thiscall ios_scalar_dtor(ios *this, unsigned int flags)
1809 TRACE("(%p %x)\n", this, flags);
1810 ios_dtor(this);
1811 if (flags & 1) MSVCRT_operator_delete(this);
1812 return this;
1815 /* ?bad@ios@@QBEHXZ */
1816 /* ?bad@ios@@QEBAHXZ */
1817 DEFINE_THISCALL_WRAPPER(ios_bad, 4)
1818 int __thiscall ios_bad(const ios *this)
1820 TRACE("(%p)\n", this);
1821 return (this->state & IOSTATE_badbit);
1824 /* ?bitalloc@ios@@SAJXZ */
1825 LONG __cdecl ios_bitalloc(void)
1827 TRACE("()\n");
1828 ios_lockc();
1829 ios_maxbit <<= 1;
1830 ios_unlockc();
1831 return ios_maxbit;
1834 /* ?clear@ios@@QAEXH@Z */
1835 /* ?clear@ios@@QEAAXH@Z */
1836 DEFINE_THISCALL_WRAPPER(ios_clear, 8)
1837 void __thiscall ios_clear(ios *this, int state)
1839 TRACE("(%p %d)\n", this, state);
1840 ios_lock(this);
1841 this->state = state;
1842 ios_unlock(this);
1845 /* ?clrlock@ios@@QAAXXZ */
1846 /* ?clrlock@ios@@QEAAXXZ */
1847 void __cdecl ios_clrlock(ios *this)
1849 TRACE("(%p)\n", this);
1850 if (this->do_lock <= 0)
1851 this->do_lock++;
1852 if (this->sb)
1853 streambuf_clrlock(this->sb);
1856 /* ?delbuf@ios@@QAEXH@Z */
1857 /* ?delbuf@ios@@QEAAXH@Z */
1858 DEFINE_THISCALL_WRAPPER(ios_delbuf_set, 8)
1859 void __thiscall ios_delbuf_set(ios *this, int delete)
1861 TRACE("(%p %d)\n", this, delete);
1862 this->delbuf = delete;
1865 /* ?delbuf@ios@@QBEHXZ */
1866 /* ?delbuf@ios@@QEBAHXZ */
1867 DEFINE_THISCALL_WRAPPER(ios_delbuf_get, 4)
1868 int __thiscall ios_delbuf_get(const ios *this)
1870 TRACE("(%p)\n", this);
1871 return this->delbuf;
1874 /* ?dec@@YAAAVios@@AAV1@@Z */
1875 /* ?dec@@YAAEAVios@@AEAV1@@Z */
1876 ios* __cdecl ios_dec(ios *this)
1878 TRACE("(%p)\n", this);
1879 ios_setf_mask(this, FLAGS_dec, ios_basefield);
1880 return this;
1883 /* ?eof@ios@@QBEHXZ */
1884 /* ?eof@ios@@QEBAHXZ */
1885 DEFINE_THISCALL_WRAPPER(ios_eof, 4)
1886 int __thiscall ios_eof(const ios *this)
1888 TRACE("(%p)\n", this);
1889 return (this->state & IOSTATE_eofbit);
1892 /* ?fail@ios@@QBEHXZ */
1893 /* ?fail@ios@@QEBAHXZ */
1894 DEFINE_THISCALL_WRAPPER(ios_fail, 4)
1895 int __thiscall ios_fail(const ios *this)
1897 TRACE("(%p)\n", this);
1898 return (this->state & (IOSTATE_failbit|IOSTATE_badbit));
1901 /* ?fill@ios@@QAEDD@Z */
1902 /* ?fill@ios@@QEAADD@Z */
1903 DEFINE_THISCALL_WRAPPER(ios_fill_set, 8)
1904 char __thiscall ios_fill_set(ios *this, char fill)
1906 char prev = this->fill;
1908 TRACE("(%p %d)\n", this, fill);
1910 this->fill = fill;
1911 return prev;
1914 /* ?fill@ios@@QBEDXZ */
1915 /* ?fill@ios@@QEBADXZ */
1916 DEFINE_THISCALL_WRAPPER(ios_fill_get, 4)
1917 char __thiscall ios_fill_get(const ios *this)
1919 TRACE("(%p)\n", this);
1920 return this->fill;
1923 /* ?flags@ios@@QAEJJ@Z */
1924 /* ?flags@ios@@QEAAJJ@Z */
1925 DEFINE_THISCALL_WRAPPER(ios_flags_set, 8)
1926 LONG __thiscall ios_flags_set(ios *this, LONG flags)
1928 LONG prev = this->flags;
1930 TRACE("(%p %x)\n", this, flags);
1932 this->flags = flags;
1933 return prev;
1936 /* ?flags@ios@@QBEJXZ */
1937 /* ?flags@ios@@QEBAJXZ */
1938 DEFINE_THISCALL_WRAPPER(ios_flags_get, 4)
1939 LONG __thiscall ios_flags_get(const ios *this)
1941 TRACE("(%p)\n", this);
1942 return this->flags;
1945 /* ?good@ios@@QBEHXZ */
1946 /* ?good@ios@@QEBAHXZ */
1947 DEFINE_THISCALL_WRAPPER(ios_good, 4)
1948 int __thiscall ios_good(const ios *this)
1950 TRACE("(%p)\n", this);
1951 return this->state == IOSTATE_goodbit;
1954 /* ?hex@@YAAAVios@@AAV1@@Z */
1955 /* ?hex@@YAAEAVios@@AEAV1@@Z */
1956 ios* __cdecl ios_hex(ios *this)
1958 TRACE("(%p)\n", this);
1959 ios_setf_mask(this, FLAGS_hex, ios_basefield);
1960 return this;
1963 /* ?init@ios@@IAEXPAVstreambuf@@@Z */
1964 /* ?init@ios@@IEAAXPEAVstreambuf@@@Z */
1965 DEFINE_THISCALL_WRAPPER(ios_init, 8)
1966 void __thiscall ios_init(ios *this, streambuf *sb)
1968 TRACE("(%p %p)\n", this, sb);
1969 if (this->delbuf && this->sb)
1970 call_streambuf_vector_dtor(this->sb, 1);
1971 this->sb = sb;
1972 if (sb == NULL)
1973 this->state |= IOSTATE_badbit;
1974 else
1975 this->state &= ~IOSTATE_badbit;
1978 /* ?iword@ios@@QBEAAJH@Z */
1979 /* ?iword@ios@@QEBAAEAJH@Z */
1980 DEFINE_THISCALL_WRAPPER(ios_iword, 8)
1981 LONG* __thiscall ios_iword(const ios *this, int index)
1983 TRACE("(%p %d)\n", this, index);
1984 return &ios_statebuf[index];
1987 /* ?lock@ios@@QAAXXZ */
1988 /* ?lock@ios@@QEAAXXZ */
1989 void __cdecl ios_lock(ios *this)
1991 TRACE("(%p)\n", this);
1992 if (this->do_lock < 0)
1993 EnterCriticalSection(&this->lock);
1996 /* ?lockbuf@ios@@QAAXXZ */
1997 /* ?lockbuf@ios@@QEAAXXZ */
1998 void __cdecl ios_lockbuf(ios *this)
2000 TRACE("(%p)\n", this);
2001 streambuf_lock(this->sb);
2004 /* ?lockc@ios@@KAXXZ */
2005 void __cdecl ios_lockc(void)
2007 TRACE("()\n");
2008 EnterCriticalSection(&ios_static_lock);
2011 /* ?lockptr@ios@@IAEPAU_CRT_CRITICAL_SECTION@@XZ */
2012 /* ?lockptr@ios@@IEAAPEAU_CRT_CRITICAL_SECTION@@XZ */
2013 DEFINE_THISCALL_WRAPPER(ios_lockptr, 4)
2014 CRITICAL_SECTION* __thiscall ios_lockptr(ios *this)
2016 TRACE("(%p)\n", this);
2017 return &this->lock;
2020 /* ?oct@@YAAAVios@@AAV1@@Z */
2021 /* ?oct@@YAAEAVios@@AEAV1@@Z */
2022 ios* __cdecl ios_oct(ios *this)
2024 TRACE("(%p)\n", this);
2025 ios_setf_mask(this, FLAGS_oct, ios_basefield);
2026 return this;
2029 /* ?precision@ios@@QAEHH@Z */
2030 /* ?precision@ios@@QEAAHH@Z */
2031 DEFINE_THISCALL_WRAPPER(ios_precision_set, 8)
2032 int __thiscall ios_precision_set(ios *this, int prec)
2034 int prev = this->precision;
2036 TRACE("(%p %d)\n", this, prec);
2038 this->precision = prec;
2039 return prev;
2042 /* ?precision@ios@@QBEHXZ */
2043 /* ?precision@ios@@QEBAHXZ */
2044 DEFINE_THISCALL_WRAPPER(ios_precision_get, 4)
2045 int __thiscall ios_precision_get(const ios *this)
2047 TRACE("(%p)\n", this);
2048 return this->precision;
2051 /* ?pword@ios@@QBEAAPAXH@Z */
2052 /* ?pword@ios@@QEBAAEAPEAXH@Z */
2053 DEFINE_THISCALL_WRAPPER(ios_pword, 8)
2054 void** __thiscall ios_pword(const ios *this, int index)
2056 TRACE("(%p %d)\n", this, index);
2057 return (void**)&ios_statebuf[index];
2060 /* ?rdbuf@ios@@QBEPAVstreambuf@@XZ */
2061 /* ?rdbuf@ios@@QEBAPEAVstreambuf@@XZ */
2062 DEFINE_THISCALL_WRAPPER(ios_rdbuf, 4)
2063 streambuf* __thiscall ios_rdbuf(const ios *this)
2065 TRACE("(%p)\n", this);
2066 return this->sb;
2069 /* ?rdstate@ios@@QBEHXZ */
2070 /* ?rdstate@ios@@QEBAHXZ */
2071 DEFINE_THISCALL_WRAPPER(ios_rdstate, 4)
2072 int __thiscall ios_rdstate(const ios *this)
2074 TRACE("(%p)\n", this);
2075 return this->state;
2078 /* ?setf@ios@@QAEJJ@Z */
2079 /* ?setf@ios@@QEAAJJ@Z */
2080 DEFINE_THISCALL_WRAPPER(ios_setf, 8)
2081 LONG __thiscall ios_setf(ios *this, LONG flags)
2083 LONG prev = this->flags;
2085 TRACE("(%p %x)\n", this, flags);
2087 ios_lock(this);
2088 this->flags |= flags;
2089 ios_unlock(this);
2090 return prev;
2093 /* ?setf@ios@@QAEJJJ@Z */
2094 /* ?setf@ios@@QEAAJJJ@Z */
2095 DEFINE_THISCALL_WRAPPER(ios_setf_mask, 12)
2096 LONG __thiscall ios_setf_mask(ios *this, LONG flags, LONG mask)
2098 LONG prev = this->flags;
2100 TRACE("(%p %x %x)\n", this, flags, mask);
2102 ios_lock(this);
2103 this->flags = (this->flags & (~mask)) | (flags & mask);
2104 ios_unlock(this);
2105 return prev;
2108 /* ?setlock@ios@@QAAXXZ */
2109 /* ?setlock@ios@@QEAAXXZ */
2110 void __cdecl ios_setlock(ios *this)
2112 TRACE("(%p)\n", this);
2113 this->do_lock--;
2114 if (this->sb)
2115 streambuf_setlock(this->sb);
2118 /* ?sync_with_stdio@ios@@SAXXZ */
2119 void __cdecl ios_sync_with_stdio(void)
2121 FIXME("() stub\n");
2124 /* ?tie@ios@@QAEPAVostream@@PAV2@@Z */
2125 /* ?tie@ios@@QEAAPEAVostream@@PEAV2@@Z */
2126 DEFINE_THISCALL_WRAPPER(ios_tie_set, 8)
2127 ostream* __thiscall ios_tie_set(ios *this, ostream *ostr)
2129 ostream *prev = this->tie;
2131 TRACE("(%p %p)\n", this, ostr);
2133 this->tie = ostr;
2134 return prev;
2137 /* ?tie@ios@@QBEPAVostream@@XZ */
2138 /* ?tie@ios@@QEBAPEAVostream@@XZ */
2139 DEFINE_THISCALL_WRAPPER(ios_tie_get, 4)
2140 ostream* __thiscall ios_tie_get(const ios *this)
2142 TRACE("(%p)\n", this);
2143 return this->tie;
2146 /* ?unlock@ios@@QAAXXZ */
2147 /* ?unlock@ios@@QEAAXXZ */
2148 void __cdecl ios_unlock(ios *this)
2150 TRACE("(%p)\n", this);
2151 if (this->do_lock < 0)
2152 LeaveCriticalSection(&this->lock);
2155 /* ?unlockbuf@ios@@QAAXXZ */
2156 /* ?unlockbuf@ios@@QEAAXXZ */
2157 void __cdecl ios_unlockbuf(ios *this)
2159 TRACE("(%p)\n", this);
2160 streambuf_unlock(this->sb);
2163 /* ?unlockc@ios@@KAXXZ */
2164 void __cdecl ios_unlockc(void)
2166 TRACE("()\n");
2167 LeaveCriticalSection(&ios_static_lock);
2170 /* ?unsetf@ios@@QAEJJ@Z */
2171 /* ?unsetf@ios@@QEAAJJ@Z */
2172 DEFINE_THISCALL_WRAPPER(ios_unsetf, 8)
2173 LONG __thiscall ios_unsetf(ios *this, LONG flags)
2175 LONG prev = this->flags;
2177 TRACE("(%p %x)\n", this, flags);
2179 ios_lock(this);
2180 this->flags &= ~flags;
2181 ios_unlock(this);
2182 return prev;
2185 /* ?width@ios@@QAEHH@Z */
2186 /* ?width@ios@@QEAAHH@Z */
2187 DEFINE_THISCALL_WRAPPER(ios_width_set, 8)
2188 int __thiscall ios_width_set(ios *this, int width)
2190 int prev = this->width;
2192 TRACE("(%p %d)\n", this, width);
2194 this->width = width;
2195 return prev;
2198 /* ?width@ios@@QBEHXZ */
2199 /* ?width@ios@@QEBAHXZ */
2200 DEFINE_THISCALL_WRAPPER(ios_width_get, 4)
2201 int __thiscall ios_width_get(const ios *this)
2203 TRACE("(%p)\n", this);
2204 return this->width;
2207 /* ?xalloc@ios@@SAHXZ */
2208 int __cdecl ios_xalloc(void)
2210 int ret;
2212 TRACE("()\n");
2214 ios_lockc();
2215 ret = (ios_curindex < STATEBUF_SIZE-1) ? ++ios_curindex : -1;
2216 ios_unlockc();
2217 return ret;
2220 /******************************************************************
2221 * ??0ostrstream@@QAE@XZ (MSVCRTI.@)
2223 DEFINE_THISCALL_WRAPPER(MSVCIRT_ostrstream_ctor,8)
2224 void * __thiscall MSVCIRT_ostrstream_ctor(ostream *this, BOOL virt_init)
2226 FIXME("(%p %x) stub\n", this, virt_init);
2227 return this;
2230 /******************************************************************
2231 * ??1ostrstream@@UAE@XZ (MSVCRTI.@)
2233 DEFINE_THISCALL_WRAPPER(MSVCIRT_ostrstream_dtor,4)
2234 void __thiscall MSVCIRT_ostrstream_dtor(ios *base)
2236 FIXME("(%p) stub\n", base);
2239 /******************************************************************
2240 * ??6ostream@@QAEAAV0@E@Z (MSVCRTI.@)
2241 * class ostream & __thiscall ostream::operator<<(unsigned char)
2243 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_uchar,8)
2244 void * __thiscall MSVCIRT_operator_sl_uchar(ostream * _this, unsigned char ch)
2246 FIXME("(%p)->(%c) stub\n", _this, ch);
2247 return _this;
2250 /******************************************************************
2251 * ??6ostream@@QAEAAV0@H@Z (MSVCRTI.@)
2252 * class ostream & __thiscall ostream::operator<<(int)
2254 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_int,8)
2255 void * __thiscall MSVCIRT_operator_sl_int(ostream * _this, int integer)
2257 FIXME("(%p)->(%d) stub\n", _this, integer);
2258 return _this;
2261 /******************************************************************
2262 * ??6ostream@@QAEAAV0@PBD@Z (MSVCRTI.@)
2263 * class ostream & __thiscall ostream::operator<<(char const *)
2265 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_pchar,8)
2266 void * __thiscall MSVCIRT_operator_sl_pchar(ostream * _this, const char * string)
2268 FIXME("(%p)->(%s) stub\n", _this, debugstr_a(string));
2269 return _this;
2272 /******************************************************************
2273 * ??6ostream@@QAEAAV0@P6AAAV0@AAV0@@Z@Z (MSVCRTI.@)
2274 * class ostream & __thiscall ostream::operator<<(class ostream & (__cdecl*)(class ostream &))
2276 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_callback,8)
2277 void * __thiscall MSVCIRT_operator_sl_callback(ostream * _this, ostream * (__cdecl*func)(ostream*))
2279 TRACE("%p, %p\n", _this, func);
2280 return func(_this);
2283 /******************************************************************
2284 * ?endl@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
2285 * class ostream & __cdecl endl(class ostream &)
2287 void * CDECL MSVCIRT_endl(ostream * _this)
2289 FIXME("(%p)->() stub\n", _this);
2290 return _this;
2293 /******************************************************************
2294 * ?ends@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
2295 * class ostream & __cdecl ends(class ostream &)
2297 void * CDECL MSVCIRT_ends(ostream * _this)
2299 FIXME("(%p)->() stub\n", _this);
2300 return _this;
2303 #ifdef __i386__
2305 #define DEFINE_VTBL_WRAPPER(off) \
2306 __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
2307 "popl %eax\n\t" \
2308 "popl %ecx\n\t" \
2309 "pushl %eax\n\t" \
2310 "movl 0(%ecx), %eax\n\t" \
2311 "jmp *" #off "(%eax)\n\t")
2313 DEFINE_VTBL_WRAPPER(0);
2314 DEFINE_VTBL_WRAPPER(4);
2315 DEFINE_VTBL_WRAPPER(8);
2316 DEFINE_VTBL_WRAPPER(12);
2317 DEFINE_VTBL_WRAPPER(16);
2318 DEFINE_VTBL_WRAPPER(20);
2319 DEFINE_VTBL_WRAPPER(24);
2320 DEFINE_VTBL_WRAPPER(28);
2321 DEFINE_VTBL_WRAPPER(32);
2322 DEFINE_VTBL_WRAPPER(36);
2323 DEFINE_VTBL_WRAPPER(40);
2324 DEFINE_VTBL_WRAPPER(44);
2325 DEFINE_VTBL_WRAPPER(48);
2326 DEFINE_VTBL_WRAPPER(52);
2327 DEFINE_VTBL_WRAPPER(56);
2329 #endif
2331 void* (__cdecl *MSVCRT_operator_new)(SIZE_T);
2332 void (__cdecl *MSVCRT_operator_delete)(void*);
2334 static void init_cxx_funcs(void)
2336 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
2338 if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */
2340 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPEAX_K@Z");
2341 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPEAX@Z");
2343 else
2345 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPAXI@Z");
2346 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPAX@Z");
2350 static void init_io(void *base)
2352 #ifdef __x86_64__
2353 init_streambuf_rtti(base);
2354 init_filebuf_rtti(base);
2355 init_strstreambuf_rtti(base);
2356 init_stdiobuf_rtti(base);
2357 init_ios_rtti(base);
2358 #endif
2361 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2363 switch (reason)
2365 case DLL_WINE_PREATTACH:
2366 return FALSE; /* prefer native version */
2367 case DLL_PROCESS_ATTACH:
2368 init_cxx_funcs();
2369 init_exception(inst);
2370 init_io(inst);
2371 DisableThreadLibraryCalls( inst );
2372 break;
2374 return TRUE;