msvcirt: Add implementation of streambuf::sputbackc.
[wine.git] / dlls / msvcirt / msvcirt.c
bloba56fd61284e6140b6efe77070f68ea42dc2d56ac
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 <stdarg.h>
23 #include <stdio.h>
25 #include "msvcirt.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcirt);
32 #define RESERVE_SIZE 512
34 /* class streambuf */
35 typedef struct {
36 const vtable_ptr *vtable;
37 int allocated;
38 int unbuffered;
39 int stored_char;
40 char *base;
41 char *ebuf;
42 char *pbase;
43 char *pptr;
44 char *epptr;
45 char *eback;
46 char *gptr;
47 char *egptr;
48 int do_lock;
49 CRITICAL_SECTION lock;
50 } streambuf;
52 void __thiscall streambuf_setb(streambuf*, char*, char*, int);
53 streambuf* __thiscall streambuf_setbuf(streambuf*, char*, int);
54 void __thiscall streambuf_setg(streambuf*, char*, char*, char*);
55 void __thiscall streambuf_setp(streambuf*, char*, char*);
57 typedef struct {
58 LPVOID VTable;
59 } class_ios;
61 typedef struct {
62 LPVOID VTable;
63 } class_ostream;
65 typedef struct {
66 LPVOID VTable;
67 } class_strstreambuf;
69 /* ??_7streambuf@@6B@ */
70 extern const vtable_ptr MSVCP_streambuf_vtable;
72 #ifndef __GNUC__
73 void __asm_dummy_vtables(void) {
74 #endif
75 __ASM_VTABLE(streambuf,
76 VTABLE_ADD_FUNC(streambuf_vector_dtor)
77 VTABLE_ADD_FUNC(streambuf_sync)
78 VTABLE_ADD_FUNC(streambuf_setbuf)
79 VTABLE_ADD_FUNC(streambuf_seekoff)
80 VTABLE_ADD_FUNC(streambuf_seekpos)
81 VTABLE_ADD_FUNC(streambuf_xsputn)
82 VTABLE_ADD_FUNC(streambuf_xsgetn)
83 VTABLE_ADD_FUNC(streambuf_overflow)
84 VTABLE_ADD_FUNC(streambuf_underflow)
85 VTABLE_ADD_FUNC(streambuf_pbackfail)
86 VTABLE_ADD_FUNC(streambuf_doallocate));
87 #ifndef __GNUC__
89 #endif
91 DEFINE_RTTI_DATA0(streambuf, 0, ".?AVstreambuf@@")
93 /* ??0streambuf@@IAE@PADH@Z */
94 /* ??0streambuf@@IEAA@PEADH@Z */
95 DEFINE_THISCALL_WRAPPER(streambuf_reserve_ctor, 12)
96 streambuf* __thiscall streambuf_reserve_ctor(streambuf *this, char *buffer, int length)
98 TRACE("(%p %p %d)\n", this, buffer, length);
99 this->vtable = &MSVCP_streambuf_vtable;
100 this->allocated = 0;
101 this->stored_char = EOF;
102 this->do_lock = -1;
103 this->base = NULL;
104 streambuf_setbuf(this, buffer, length);
105 streambuf_setg(this, NULL, NULL, NULL);
106 streambuf_setp(this, NULL, NULL);
107 InitializeCriticalSection(&this->lock);
108 return this;
111 /* ??0streambuf@@IAE@XZ */
112 /* ??0streambuf@@IEAA@XZ */
113 DEFINE_THISCALL_WRAPPER(streambuf_ctor, 4)
114 streambuf* __thiscall streambuf_ctor(streambuf *this)
116 streambuf_reserve_ctor(this, NULL, 0);
117 this->unbuffered = 0;
118 return this;
121 /* ??0streambuf@@QAE@ABV0@@Z */
122 /* ??0streambuf@@QEAA@AEBV0@@Z */
123 DEFINE_THISCALL_WRAPPER(streambuf_copy_ctor, 8)
124 streambuf* __thiscall streambuf_copy_ctor(streambuf *this, const streambuf *copy)
126 TRACE("(%p %p)\n", this, copy);
127 *this = *copy;
128 this->vtable = &MSVCP_streambuf_vtable;
129 return this;
132 /* ??1streambuf@@UAE@XZ */
133 /* ??1streambuf@@UEAA@XZ */
134 DEFINE_THISCALL_WRAPPER(streambuf_dtor, 4)
135 void __thiscall streambuf_dtor(streambuf *this)
137 TRACE("(%p)\n", this);
138 if (this->allocated)
139 MSVCRT_operator_delete(this->base);
140 DeleteCriticalSection(&this->lock);
143 /* ??4streambuf@@QAEAAV0@ABV0@@Z */
144 /* ??4streambuf@@QEAAAEAV0@AEBV0@@Z */
145 DEFINE_THISCALL_WRAPPER(streambuf_assign, 8)
146 streambuf* __thiscall streambuf_assign(streambuf *this, const streambuf *rhs)
148 streambuf_dtor(this);
149 return streambuf_copy_ctor(this, rhs);
152 /* ??_Estreambuf@@UAEPAXI@Z */
153 DEFINE_THISCALL_WRAPPER(streambuf_vector_dtor, 8)
154 streambuf* __thiscall streambuf_vector_dtor(streambuf *this, unsigned int flags)
156 TRACE("(%p %x)\n", this, flags);
157 if (flags & 2) {
158 /* we have an array, with the number of elements stored before the first object */
159 INT_PTR i, *ptr = (INT_PTR *)this-1;
161 for (i = *ptr-1; i >= 0; i--)
162 streambuf_dtor(this+i);
163 MSVCRT_operator_delete(ptr);
164 } else {
165 streambuf_dtor(this);
166 if (flags & 1)
167 MSVCRT_operator_delete(this);
169 return this;
172 /* ??_Gstreambuf@@UAEPAXI@Z */
173 DEFINE_THISCALL_WRAPPER(streambuf_scalar_dtor, 8)
174 streambuf* __thiscall streambuf_scalar_dtor(streambuf *this, unsigned int flags)
176 TRACE("(%p %x)\n", this, flags);
177 streambuf_dtor(this);
178 if (flags & 1) MSVCRT_operator_delete(this);
179 return this;
182 /* ?doallocate@streambuf@@MAEHXZ */
183 /* ?doallocate@streambuf@@MEAAHXZ */
184 DEFINE_THISCALL_WRAPPER(streambuf_doallocate, 4)
185 #define call_streambuf_doallocate(this) CALL_VTBL_FUNC(this, 40, int, (streambuf*), (this))
186 int __thiscall streambuf_doallocate(streambuf *this)
188 char *reserve;
190 TRACE("(%p)\n", this);
191 reserve = MSVCRT_operator_new(RESERVE_SIZE);
192 if (!reserve)
193 return EOF;
195 streambuf_setb(this, reserve, reserve + RESERVE_SIZE, 1);
196 return 1;
199 /* ?allocate@streambuf@@IAEHXZ */
200 /* ?allocate@streambuf@@IEAAHXZ */
201 DEFINE_THISCALL_WRAPPER(streambuf_allocate, 4)
202 int __thiscall streambuf_allocate(streambuf *this)
204 TRACE("(%p)\n", this);
205 if (this->base != NULL || this->unbuffered)
206 return 0;
207 return call_streambuf_doallocate(this);
210 /* ?base@streambuf@@IBEPADXZ */
211 /* ?base@streambuf@@IEBAPEADXZ */
212 DEFINE_THISCALL_WRAPPER(streambuf_base, 4)
213 char* __thiscall streambuf_base(const streambuf *this)
215 TRACE("(%p)\n", this);
216 return this->base;
219 /* ?blen@streambuf@@IBEHXZ */
220 /* ?blen@streambuf@@IEBAHXZ */
221 DEFINE_THISCALL_WRAPPER(streambuf_blen, 4)
222 int __thiscall streambuf_blen(const streambuf *this)
224 TRACE("(%p)\n", this);
225 return this->ebuf - this->base;
228 /* ?eback@streambuf@@IBEPADXZ */
229 /* ?eback@streambuf@@IEBAPEADXZ */
230 DEFINE_THISCALL_WRAPPER(streambuf_eback, 4)
231 char* __thiscall streambuf_eback(const streambuf *this)
233 TRACE("(%p)\n", this);
234 return this->eback;
237 /* ?ebuf@streambuf@@IBEPADXZ */
238 /* ?ebuf@streambuf@@IEBAPEADXZ */
239 DEFINE_THISCALL_WRAPPER(streambuf_ebuf, 4)
240 char* __thiscall streambuf_ebuf(const streambuf *this)
242 TRACE("(%p)\n", this);
243 return this->ebuf;
246 /* ?egptr@streambuf@@IBEPADXZ */
247 /* ?egptr@streambuf@@IEBAPEADXZ */
248 DEFINE_THISCALL_WRAPPER(streambuf_egptr, 4)
249 char* __thiscall streambuf_egptr(const streambuf *this)
251 TRACE("(%p)\n", this);
252 return this->egptr;
255 /* ?epptr@streambuf@@IBEPADXZ */
256 /* ?epptr@streambuf@@IEBAPEADXZ */
257 DEFINE_THISCALL_WRAPPER(streambuf_epptr, 4)
258 char* __thiscall streambuf_epptr(const streambuf *this)
260 TRACE("(%p)\n", this);
261 return this->epptr;
264 /* ?gptr@streambuf@@IBEPADXZ */
265 /* ?gptr@streambuf@@IEBAPEADXZ */
266 DEFINE_THISCALL_WRAPPER(streambuf_gptr, 4)
267 char* __thiscall streambuf_gptr(const streambuf *this)
269 TRACE("(%p)\n", this);
270 return this->gptr;
273 /* ?pbase@streambuf@@IBEPADXZ */
274 /* ?pbase@streambuf@@IEBAPEADXZ */
275 DEFINE_THISCALL_WRAPPER(streambuf_pbase, 4)
276 char* __thiscall streambuf_pbase(const streambuf *this)
278 TRACE("(%p)\n", this);
279 return this->pbase;
282 /* ?pptr@streambuf@@IBEPADXZ */
283 /* ?pptr@streambuf@@IEBAPEADXZ */
284 DEFINE_THISCALL_WRAPPER(streambuf_pptr, 4)
285 char* __thiscall streambuf_pptr(const streambuf *this)
287 TRACE("(%p)\n", this);
288 return this->pptr;
291 /* ?clrlock@streambuf@@QAEXXZ */
292 /* ?clrlock@streambuf@@QEAAXXZ */
293 DEFINE_THISCALL_WRAPPER(streambuf_clrlock, 4)
294 void __thiscall streambuf_clrlock(streambuf *this)
296 TRACE("(%p)\n", this);
297 if (this->do_lock <= 0)
298 this->do_lock++;
301 /* ?lock@streambuf@@QAEXXZ */
302 /* ?lock@streambuf@@QEAAXXZ */
303 DEFINE_THISCALL_WRAPPER(streambuf_lock, 4)
304 void __thiscall streambuf_lock(streambuf *this)
306 TRACE("(%p)\n", this);
307 if (this->do_lock < 0)
308 EnterCriticalSection(&this->lock);
311 /* ?lockptr@streambuf@@IAEPAU_CRT_CRITICAL_SECTION@@XZ */
312 /* ?lockptr@streambuf@@IEAAPEAU_CRT_CRITICAL_SECTION@@XZ */
313 DEFINE_THISCALL_WRAPPER(streambuf_lockptr, 4)
314 CRITICAL_SECTION* __thiscall streambuf_lockptr(streambuf *this)
316 TRACE("(%p)\n", this);
317 return &this->lock;
320 /* ?gbump@streambuf@@IAEXH@Z */
321 /* ?gbump@streambuf@@IEAAXH@Z */
322 DEFINE_THISCALL_WRAPPER(streambuf_gbump, 8)
323 void __thiscall streambuf_gbump(streambuf *this, int count)
325 TRACE("(%p %d)\n", this, count);
326 this->gptr += count;
329 /* ?pbump@streambuf@@IAEXH@Z */
330 /* ?pbump@streambuf@@IEAAXH@Z */
331 DEFINE_THISCALL_WRAPPER(streambuf_pbump, 8)
332 void __thiscall streambuf_pbump(streambuf *this, int count)
334 TRACE("(%p %d)\n", this, count);
335 this->pptr += count;
338 /* ?in_avail@streambuf@@QBEHXZ */
339 /* ?in_avail@streambuf@@QEBAHXZ */
340 DEFINE_THISCALL_WRAPPER(streambuf_in_avail, 4)
341 int __thiscall streambuf_in_avail(const streambuf *this)
343 TRACE("(%p)\n", this);
344 return this->egptr - this->gptr;
347 /* ?out_waiting@streambuf@@QBEHXZ */
348 /* ?out_waiting@streambuf@@QEBAHXZ */
349 DEFINE_THISCALL_WRAPPER(streambuf_out_waiting, 4)
350 int __thiscall streambuf_out_waiting(const streambuf *this)
352 TRACE("(%p)\n", this);
353 return this->pptr - this->pbase;
356 /* Unexported */
357 DEFINE_THISCALL_WRAPPER(streambuf_overflow, 8)
358 #define call_streambuf_overflow(this, c) CALL_VTBL_FUNC(this, 28, int, (streambuf*, int), (this, c))
359 int __thiscall streambuf_overflow(streambuf *this, int c)
361 ERR("overflow is not implemented in streambuf\n");
362 return EOF;
365 /* ?pbackfail@streambuf@@UAEHH@Z */
366 /* ?pbackfail@streambuf@@UEAAHH@Z */
367 DEFINE_THISCALL_WRAPPER(streambuf_pbackfail, 8)
368 #define call_streambuf_pbackfail(this, c) CALL_VTBL_FUNC(this, 36, int, (streambuf*, int), (this, c))
369 int __thiscall streambuf_pbackfail(streambuf *this, int c)
371 TRACE("(%p %d)\n", this, c);
372 if (this->gptr <= this->eback)
373 return EOF;
374 return *--this->gptr = c;
377 /* ?seekoff@streambuf@@UAEJJW4seek_dir@ios@@H@Z */
378 /* ?seekoff@streambuf@@UEAAJJW4seek_dir@ios@@H@Z */
379 DEFINE_THISCALL_WRAPPER(streambuf_seekoff, 16)
380 #define call_streambuf_seekoff(this, off, dir, mode) CALL_VTBL_FUNC(this, 12, streampos, (streambuf*, streamoff, ios_seek_dir, int), (this, off, dir, mode))
381 streampos __thiscall streambuf_seekoff(streambuf *this, streamoff offset, ios_seek_dir dir, int mode)
383 TRACE("(%p %d %d %d)\n", this, offset, dir, mode);
384 return EOF;
387 /* ?seekpos@streambuf@@UAEJJH@Z */
388 /* ?seekpos@streambuf@@UEAAJJH@Z */
389 DEFINE_THISCALL_WRAPPER(streambuf_seekpos, 12)
390 streampos __thiscall streambuf_seekpos(streambuf *this, streampos pos, int mode)
392 TRACE("(%p %d %d)\n", this, pos, mode);
393 return call_streambuf_seekoff(this, pos, SEEKDIR_beg, mode);
396 /* ?setb@streambuf@@IAEXPAD0H@Z */
397 /* ?setb@streambuf@@IEAAXPEAD0H@Z */
398 DEFINE_THISCALL_WRAPPER(streambuf_setb, 16)
399 void __thiscall streambuf_setb(streambuf *this, char *ba, char *eb, int delete)
401 TRACE("(%p %p %p %d)\n", this, ba, eb, delete);
402 if (this->allocated)
403 MSVCRT_operator_delete(this->base);
404 this->allocated = delete;
405 this->base = ba;
406 this->ebuf = eb;
409 /* ?setbuf@streambuf@@UAEPAV1@PADH@Z */
410 /* ?setbuf@streambuf@@UEAAPEAV1@PEADH@Z */
411 DEFINE_THISCALL_WRAPPER(streambuf_setbuf, 12)
412 streambuf* __thiscall streambuf_setbuf(streambuf *this, char *buffer, int length)
414 TRACE("(%p %p %d)\n", this, buffer, length);
415 if (this->base != NULL)
416 return NULL;
418 if (buffer == NULL || !length) {
419 this->unbuffered = 1;
420 this->base = this->ebuf = NULL;
421 } else {
422 this->unbuffered = 0;
423 this->base = buffer;
424 this->ebuf = buffer + length;
426 return this;
429 /* ?setg@streambuf@@IAEXPAD00@Z */
430 /* ?setg@streambuf@@IEAAXPEAD00@Z */
431 DEFINE_THISCALL_WRAPPER(streambuf_setg, 16)
432 void __thiscall streambuf_setg(streambuf *this, char *ek, char *gp, char *eg)
434 TRACE("(%p %p %p %p)\n", this, ek, gp, eg);
435 this->eback = ek;
436 this->gptr = gp;
437 this->egptr = eg;
440 /* ?setlock@streambuf@@QAEXXZ */
441 /* ?setlock@streambuf@@QEAAXXZ */
442 DEFINE_THISCALL_WRAPPER(streambuf_setlock, 4)
443 void __thiscall streambuf_setlock(streambuf *this)
445 TRACE("(%p)\n", this);
446 this->do_lock--;
449 /* ?setp@streambuf@@IAEXPAD0@Z */
450 /* ?setp@streambuf@@IEAAXPEAD0@Z */
451 DEFINE_THISCALL_WRAPPER(streambuf_setp, 12)
452 void __thiscall streambuf_setp(streambuf *this, char *pb, char *ep)
454 TRACE("(%p %p %p)\n", this, pb, ep);
455 this->pbase = this->pptr = pb;
456 this->epptr = ep;
459 /* ?sync@streambuf@@UAEHXZ */
460 /* ?sync@streambuf@@UEAAHXZ */
461 DEFINE_THISCALL_WRAPPER(streambuf_sync, 4)
462 int __thiscall streambuf_sync(streambuf *this)
464 TRACE("(%p)\n", this);
465 return (this->gptr >= this->egptr && this->pbase >= this->pptr) ? 0 : EOF;
468 /* ?unbuffered@streambuf@@IAEXH@Z */
469 /* ?unbuffered@streambuf@@IEAAXH@Z */
470 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_set, 8)
471 void __thiscall streambuf_unbuffered_set(streambuf *this, int buf)
473 TRACE("(%p %d)\n", this, buf);
474 this->unbuffered = buf;
477 /* ?unbuffered@streambuf@@IBEHXZ */
478 /* ?unbuffered@streambuf@@IEBAHXZ */
479 DEFINE_THISCALL_WRAPPER(streambuf_unbuffered_get, 4)
480 int __thiscall streambuf_unbuffered_get(const streambuf *this)
482 TRACE("(%p)\n", this);
483 return this->unbuffered;
486 /* Unexported */
487 DEFINE_THISCALL_WRAPPER(streambuf_underflow, 4)
488 #define call_streambuf_underflow(this) CALL_VTBL_FUNC(this, 32, int, (streambuf*), (this))
489 int __thiscall streambuf_underflow(streambuf *this)
491 ERR("underflow is not implemented in streambuf\n");
492 return EOF;
495 /* ?unlock@streambuf@@QAEXXZ */
496 /* ?unlock@streambuf@@QEAAXXZ */
497 DEFINE_THISCALL_WRAPPER(streambuf_unlock, 4)
498 void __thiscall streambuf_unlock(streambuf *this)
500 TRACE("(%p)\n", this);
501 if (this->do_lock < 0)
502 LeaveCriticalSection(&this->lock);
505 /* ?xsgetn@streambuf@@UAEHPADH@Z */
506 /* ?xsgetn@streambuf@@UEAAHPEADH@Z */
507 DEFINE_THISCALL_WRAPPER(streambuf_xsgetn, 12)
508 #define call_streambuf_xsgetn(this, buffer, count) CALL_VTBL_FUNC(this, 24, int, (streambuf*, char*, int), (this, buffer, count))
509 int __thiscall streambuf_xsgetn(streambuf *this, char *buffer, int count)
511 int copied = 0, chunk;
513 TRACE("(%p %p %d)\n", this, buffer, count);
515 if (this->unbuffered) {
516 if (this->stored_char == EOF)
517 this->stored_char = call_streambuf_underflow(this);
518 while (copied < count && this->stored_char != EOF) {
519 buffer[copied++] = this->stored_char;
520 this->stored_char = call_streambuf_underflow(this);
522 } else {
523 while (copied < count) {
524 if (call_streambuf_underflow(this) == EOF)
525 break;
526 chunk = this->egptr - this->gptr;
527 if (chunk > count - copied)
528 chunk = count - copied;
529 memcpy(buffer+copied, this->gptr, chunk);
530 this->gptr += chunk;
531 copied += chunk;
534 return copied;
537 /* ?xsputn@streambuf@@UAEHPBDH@Z */
538 /* ?xsputn@streambuf@@UEAAHPEBDH@Z */
539 DEFINE_THISCALL_WRAPPER(streambuf_xsputn, 12)
540 #define call_streambuf_xsputn(this, data, length) CALL_VTBL_FUNC(this, 20, int, (streambuf*, const char*, int), (this, data, length))
541 int __thiscall streambuf_xsputn(streambuf *this, const char *data, int length)
543 int copied = 0, chunk;
545 TRACE("(%p %p %d)\n", this, data, length);
547 while (copied < length) {
548 if (this->unbuffered || this->pptr == this->epptr) {
549 if (call_streambuf_overflow(this, data[copied]) == EOF)
550 break;
551 copied++;
552 } else {
553 chunk = this->epptr - this->pptr;
554 if (chunk > length - copied)
555 chunk = length - copied;
556 memcpy(this->pptr, data+copied, chunk);
557 this->pptr += chunk;
558 copied += chunk;
561 return copied;
564 /* ?sgetc@streambuf@@QAEHXZ */
565 /* ?sgetc@streambuf@@QEAAHXZ */
566 DEFINE_THISCALL_WRAPPER(streambuf_sgetc, 4)
567 int __thiscall streambuf_sgetc(streambuf *this)
569 TRACE("(%p)\n", this);
570 if (this->unbuffered) {
571 if (this->stored_char == EOF)
572 this->stored_char = call_streambuf_underflow(this);
573 return this->stored_char;
574 } else
575 return call_streambuf_underflow(this);
578 /* ?sputc@streambuf@@QAEHH@Z */
579 /* ?sputc@streambuf@@QEAAHH@Z */
580 DEFINE_THISCALL_WRAPPER(streambuf_sputc, 8)
581 int __thiscall streambuf_sputc(streambuf *this, int ch)
583 TRACE("(%p %d)\n", this, ch);
584 return (this->pptr < this->epptr) ? *this->pptr++ = ch : call_streambuf_overflow(this, ch);
587 /* ?sgetn@streambuf@@QAEHPADH@Z */
588 /* ?sgetn@streambuf@@QEAAHPEADH@Z */
589 DEFINE_THISCALL_WRAPPER(streambuf_sgetn, 12)
590 int __thiscall streambuf_sgetn(streambuf *this, char *buffer, int count)
592 return call_streambuf_xsgetn(this, buffer, count);
595 /* ?sputn@streambuf@@QAEHPBDH@Z */
596 /* ?sputn@streambuf@@QEAAHPEBDH@Z */
597 DEFINE_THISCALL_WRAPPER(streambuf_sputn, 12)
598 int __thiscall streambuf_sputn(streambuf *this, const char *data, int length)
600 return call_streambuf_xsputn(this, data, length);
603 /* ?snextc@streambuf@@QAEHXZ */
604 /* ?snextc@streambuf@@QEAAHXZ */
605 DEFINE_THISCALL_WRAPPER(streambuf_snextc, 4)
606 int __thiscall streambuf_snextc(streambuf *this)
608 TRACE("(%p)\n", this);
609 if (this->unbuffered) {
610 if (this->stored_char == EOF)
611 call_streambuf_underflow(this);
612 return this->stored_char = call_streambuf_underflow(this);
613 } else {
614 if (this->gptr >= this->egptr)
615 call_streambuf_underflow(this);
616 this->gptr++;
617 return (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
621 /* ?sbumpc@streambuf@@QAEHXZ */
622 /* ?sbumpc@streambuf@@QEAAHXZ */
623 DEFINE_THISCALL_WRAPPER(streambuf_sbumpc, 4)
624 int __thiscall streambuf_sbumpc(streambuf *this)
626 int ret;
628 TRACE("(%p)\n", this);
630 if (this->unbuffered) {
631 ret = this->stored_char;
632 this->stored_char = EOF;
633 if (ret == EOF)
634 ret = call_streambuf_underflow(this);
635 } else {
636 ret = (this->gptr < this->egptr) ? *this->gptr : call_streambuf_underflow(this);
637 this->gptr++;
639 return ret;
642 /* ?stossc@streambuf@@QAEXXZ */
643 /* ?stossc@streambuf@@QEAAXXZ */
644 DEFINE_THISCALL_WRAPPER(streambuf_stossc, 4)
645 void __thiscall streambuf_stossc(streambuf *this)
647 TRACE("(%p)\n", this);
648 if (this->unbuffered) {
649 if (this->stored_char == EOF)
650 call_streambuf_underflow(this);
651 else
652 this->stored_char = EOF;
653 } else {
654 if (this->gptr >= this->egptr)
655 call_streambuf_underflow(this);
656 if (this->gptr < this->egptr)
657 this->gptr++;
661 /* ?sputbackc@streambuf@@QAEHD@Z */
662 /* ?sputbackc@streambuf@@QEAAHD@Z */
663 DEFINE_THISCALL_WRAPPER(streambuf_sputbackc, 8)
664 int __thiscall streambuf_sputbackc(streambuf *this, char ch)
666 TRACE("(%p %d)\n", this, ch);
667 return call_streambuf_pbackfail(this, ch);
670 /******************************************************************
671 * ??1ios@@UAE@XZ (MSVCRTI.@)
672 * class ios & __thiscall ios::-ios<<(void)
674 DEFINE_THISCALL_WRAPPER(MSVCIRT_ios_sl_void,4)
675 void * __thiscall MSVCIRT_ios_sl_void(class_ios * _this)
677 FIXME("(%p) stub\n", _this);
678 return _this;
681 /******************************************************************
682 * ??0ostrstream@@QAE@XZ (MSVCRTI.@)
683 * class ostream & __thiscall ostrstream::ostrstream<<(void)
685 DEFINE_THISCALL_WRAPPER(MSVCIRT_ostrstream_sl_void,4)
686 void * __thiscall MSVCIRT_ostrstream_sl_void(class_ostream * _this)
688 FIXME("(%p) stub\n", _this);
689 return _this;
692 /******************************************************************
693 * ??6ostream@@QAEAAV0@E@Z (MSVCRTI.@)
694 * class ostream & __thiscall ostream::operator<<(unsigned char)
696 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_uchar,8)
697 void * __thiscall MSVCIRT_operator_sl_uchar(class_ostream * _this, unsigned char ch)
699 FIXME("(%p)->(%c) stub\n", _this, ch);
700 return _this;
703 /******************************************************************
704 * ??6ostream@@QAEAAV0@H@Z (MSVCRTI.@)
705 * class ostream & __thiscall ostream::operator<<(int)
707 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_int,8)
708 void * __thiscall MSVCIRT_operator_sl_int(class_ostream * _this, int integer)
710 FIXME("(%p)->(%d) stub\n", _this, integer);
711 return _this;
714 /******************************************************************
715 * ??6ostream@@QAEAAV0@PBD@Z (MSVCRTI.@)
716 * class ostream & __thiscall ostream::operator<<(char const *)
718 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_pchar,8)
719 void * __thiscall MSVCIRT_operator_sl_pchar(class_ostream * _this, const char * string)
721 FIXME("(%p)->(%s) stub\n", _this, debugstr_a(string));
722 return _this;
725 /******************************************************************
726 * ??6ostream@@QAEAAV0@P6AAAV0@AAV0@@Z@Z (MSVCRTI.@)
727 * class ostream & __thiscall ostream::operator<<(class ostream & (__cdecl*)(class ostream &))
729 DEFINE_THISCALL_WRAPPER(MSVCIRT_operator_sl_callback,8)
730 void * __thiscall MSVCIRT_operator_sl_callback(class_ostream * _this, class_ostream * (__cdecl*func)(class_ostream*))
732 TRACE("%p, %p\n", _this, func);
733 return func(_this);
736 /******************************************************************
737 * ?endl@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
738 * class ostream & __cdecl endl(class ostream &)
740 void * CDECL MSVCIRT_endl(class_ostream * _this)
742 FIXME("(%p)->() stub\n", _this);
743 return _this;
746 /******************************************************************
747 * ?ends@@YAAAVostream@@AAV1@@Z (MSVCRTI.@)
748 * class ostream & __cdecl ends(class ostream &)
750 void * CDECL MSVCIRT_ends(class_ostream * _this)
752 FIXME("(%p)->() stub\n", _this);
753 return _this;
756 /******************************************************************
757 * ?str@strstreambuf@@QAEPADXZ (MSVCRTI.@)
758 * class strstreambuf & __thiscall strstreambuf::str(class strstreambuf &)
760 DEFINE_THISCALL_WRAPPER(MSVCIRT_str_sl_void,4)
761 char * __thiscall MSVCIRT_str_sl_void(class_strstreambuf * _this)
763 FIXME("(%p)->() stub\n", _this);
764 return 0;
767 #ifdef __i386__
769 #define DEFINE_VTBL_WRAPPER(off) \
770 __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
771 "popl %eax\n\t" \
772 "popl %ecx\n\t" \
773 "pushl %eax\n\t" \
774 "movl 0(%ecx), %eax\n\t" \
775 "jmp *" #off "(%eax)\n\t")
777 DEFINE_VTBL_WRAPPER(0);
778 DEFINE_VTBL_WRAPPER(4);
779 DEFINE_VTBL_WRAPPER(8);
780 DEFINE_VTBL_WRAPPER(12);
781 DEFINE_VTBL_WRAPPER(16);
782 DEFINE_VTBL_WRAPPER(20);
783 DEFINE_VTBL_WRAPPER(24);
784 DEFINE_VTBL_WRAPPER(28);
785 DEFINE_VTBL_WRAPPER(32);
786 DEFINE_VTBL_WRAPPER(36);
787 DEFINE_VTBL_WRAPPER(40);
788 DEFINE_VTBL_WRAPPER(44);
789 DEFINE_VTBL_WRAPPER(48);
790 DEFINE_VTBL_WRAPPER(52);
791 DEFINE_VTBL_WRAPPER(56);
793 #endif
795 void* (__cdecl *MSVCRT_operator_new)(SIZE_T);
796 void (__cdecl *MSVCRT_operator_delete)(void*);
798 static void init_cxx_funcs(void)
800 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
802 if (sizeof(void *) > sizeof(int)) /* 64-bit has different names */
804 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPEAX_K@Z");
805 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPEAX@Z");
807 else
809 MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPAXI@Z");
810 MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPAX@Z");
814 static void init_io(void *base)
816 #ifdef __x86_64__
817 init_streambuf_rtti(base);
818 #endif
821 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
823 switch (reason)
825 case DLL_WINE_PREATTACH:
826 return FALSE; /* prefer native version */
827 case DLL_PROCESS_ATTACH:
828 init_cxx_funcs();
829 init_exception(inst);
830 init_io(inst);
831 DisableThreadLibraryCalls( inst );
832 break;
834 return TRUE;