2 * Copyright 2015 Iván Matellanes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
24 typedef void (*vtable_ptr
)(void);
28 const vtable_ptr
*vtable
;
41 CRITICAL_SECTION lock
;
46 #define __thiscall __stdcall
48 #define __thiscall __cdecl
52 static streambuf
* (*__thiscall p_streambuf_reserve_ctor
)(streambuf
*, char*, int);
53 static streambuf
* (*__thiscall p_streambuf_ctor
)(streambuf
*);
54 static void (*__thiscall p_streambuf_dtor
)(streambuf
*);
55 static int (*__thiscall p_streambuf_allocate
)(streambuf
*);
56 static void (*__thiscall p_streambuf_clrclock
)(streambuf
*);
57 static int (*__thiscall p_streambuf_doallocate
)(streambuf
*);
58 static void (*__thiscall p_streambuf_gbump
)(streambuf
*, int);
59 static void (*__thiscall p_streambuf_lock
)(streambuf
*);
60 static void (*__thiscall p_streambuf_pbump
)(streambuf
*, int);
61 static int (*__thiscall p_streambuf_sbumpc
)(streambuf
*);
62 static void (*__thiscall p_streambuf_setb
)(streambuf
*, char*, char*, int);
63 static void (*__thiscall p_streambuf_setlock
)(streambuf
*);
64 static streambuf
* (*__thiscall p_streambuf_setbuf
)(streambuf
*, char*, int);
65 static int (*__thiscall p_streambuf_sgetc
)(streambuf
*);
66 static int (*__thiscall p_streambuf_snextc
)(streambuf
*);
67 static int (*__thiscall p_streambuf_sputc
)(streambuf
*, int);
68 static void (*__thiscall p_streambuf_stossc
)(streambuf
*);
69 static int (*__thiscall p_streambuf_sync
)(streambuf
*);
70 static void (*__thiscall p_streambuf_unlock
)(streambuf
*);
71 static int (*__thiscall p_streambuf_xsgetn
)(streambuf
*, char*, int);
72 static int (*__thiscall p_streambuf_xsputn
)(streambuf
*, const char*, int);
74 /* Emulate a __thiscall */
80 BYTE pop_eax
; /* popl %eax (ret addr) */
81 BYTE pop_edx
; /* popl %edx (func) */
82 BYTE pop_ecx
; /* popl %ecx (this) */
83 BYTE push_eax
; /* pushl %eax */
84 WORD jmp_edx
; /* jmp *%edx */
88 static void * (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
89 static void * (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
90 static void * (WINAPI
*call_thiscall_func3
)( void *func
, void *this, const void *a
, const void *b
);
91 static void * (WINAPI
*call_thiscall_func4
)( void *func
, void *this, const void *a
, const void *b
,
93 static void * (WINAPI
*call_thiscall_func5
)( void *func
, void *this, const void *a
, const void *b
,
94 const void *c
, const void *d
);
96 static void init_thiscall_thunk(void)
98 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
99 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
100 thunk
->pop_eax
= 0x58; /* popl %eax */
101 thunk
->pop_edx
= 0x5a; /* popl %edx */
102 thunk
->pop_ecx
= 0x59; /* popl %ecx */
103 thunk
->push_eax
= 0x50; /* pushl %eax */
104 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
105 call_thiscall_func1
= (void *)thunk
;
106 call_thiscall_func2
= (void *)thunk
;
107 call_thiscall_func3
= (void *)thunk
;
108 call_thiscall_func4
= (void *)thunk
;
109 call_thiscall_func5
= (void *)thunk
;
112 #define call_func1(func,_this) call_thiscall_func1(func,_this)
113 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
114 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
115 #define call_func4(func,_this,a,b,c) call_thiscall_func4(func,_this,(const void*)(a),(const void*)(b), \
117 #define call_func5(func,_this,a,b,c,d) call_thiscall_func5(func,_this,(const void*)(a),(const void*)(b), \
118 (const void*)(c), (const void *)(d))
122 #define init_thiscall_thunk()
123 #define call_func1(func,_this) func(_this)
124 #define call_func2(func,_this,a) func(_this,a)
125 #define call_func3(func,_this,a,b) func(_this,a,b)
126 #define call_func4(func,_this,a,b,c) func(_this,a,b,c)
127 #define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d)
129 #endif /* __i386__ */
131 static HMODULE msvcirt
;
132 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcirt,y)
133 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
134 static BOOL
init(void)
136 msvcirt
= LoadLibraryA("msvcirt.dll");
138 win_skip("msvcirt.dll not installed\n");
142 if(sizeof(void*) == 8) { /* 64-bit initialization */
143 SET(p_streambuf_reserve_ctor
, "??0streambuf@@IEAA@PEADH@Z");
144 SET(p_streambuf_ctor
, "??0streambuf@@IEAA@XZ");
145 SET(p_streambuf_dtor
, "??1streambuf@@UEAA@XZ");
146 SET(p_streambuf_allocate
, "?allocate@streambuf@@IEAAHXZ");
147 SET(p_streambuf_clrclock
, "?clrlock@streambuf@@QEAAXXZ");
148 SET(p_streambuf_doallocate
, "?doallocate@streambuf@@MEAAHXZ");
149 SET(p_streambuf_gbump
, "?gbump@streambuf@@IEAAXH@Z");
150 SET(p_streambuf_lock
, "?lock@streambuf@@QEAAXXZ");
151 SET(p_streambuf_pbump
, "?pbump@streambuf@@IEAAXH@Z");
152 SET(p_streambuf_sbumpc
, "?sbumpc@streambuf@@QEAAHXZ");
153 SET(p_streambuf_setb
, "?setb@streambuf@@IEAAXPEAD0H@Z");
154 SET(p_streambuf_setbuf
, "?setbuf@streambuf@@UEAAPEAV1@PEADH@Z");
155 SET(p_streambuf_setlock
, "?setlock@streambuf@@QEAAXXZ");
156 SET(p_streambuf_sgetc
, "?sgetc@streambuf@@QEAAHXZ");
157 SET(p_streambuf_snextc
, "?snextc@streambuf@@QEAAHXZ");
158 SET(p_streambuf_sputc
, "?sputc@streambuf@@QEAAHH@Z");
159 SET(p_streambuf_stossc
, "?stossc@streambuf@@QEAAXXZ");
160 SET(p_streambuf_sync
, "?sync@streambuf@@UEAAHXZ");
161 SET(p_streambuf_unlock
, "?unlock@streambuf@@QEAAXXZ");
162 SET(p_streambuf_xsgetn
, "?xsgetn@streambuf@@UEAAHPEADH@Z");
163 SET(p_streambuf_xsputn
, "?xsputn@streambuf@@UEAAHPEBDH@Z");
165 SET(p_streambuf_reserve_ctor
, "??0streambuf@@IAE@PADH@Z");
166 SET(p_streambuf_ctor
, "??0streambuf@@IAE@XZ");
167 SET(p_streambuf_dtor
, "??1streambuf@@UAE@XZ");
168 SET(p_streambuf_allocate
, "?allocate@streambuf@@IAEHXZ");
169 SET(p_streambuf_clrclock
, "?clrlock@streambuf@@QAEXXZ");
170 SET(p_streambuf_doallocate
, "?doallocate@streambuf@@MAEHXZ");
171 SET(p_streambuf_gbump
, "?gbump@streambuf@@IAEXH@Z");
172 SET(p_streambuf_lock
, "?lock@streambuf@@QAEXXZ");
173 SET(p_streambuf_pbump
, "?pbump@streambuf@@IAEXH@Z");
174 SET(p_streambuf_sbumpc
, "?sbumpc@streambuf@@QAEHXZ");
175 SET(p_streambuf_setb
, "?setb@streambuf@@IAEXPAD0H@Z");
176 SET(p_streambuf_setbuf
, "?setbuf@streambuf@@UAEPAV1@PADH@Z");
177 SET(p_streambuf_setlock
, "?setlock@streambuf@@QAEXXZ");
178 SET(p_streambuf_sgetc
, "?sgetc@streambuf@@QAEHXZ");
179 SET(p_streambuf_snextc
, "?snextc@streambuf@@QAEHXZ");
180 SET(p_streambuf_sputc
, "?sputc@streambuf@@QAEHH@Z");
181 SET(p_streambuf_stossc
, "?stossc@streambuf@@QAEXXZ");
182 SET(p_streambuf_sync
, "?sync@streambuf@@UAEHXZ");
183 SET(p_streambuf_unlock
, "?unlock@streambuf@@QAEXXZ");
184 SET(p_streambuf_xsgetn
, "?xsgetn@streambuf@@UAEHPADH@Z");
185 SET(p_streambuf_xsputn
, "?xsputn@streambuf@@UAEHPBDH@Z");
188 init_thiscall_thunk();
192 static int overflow_count
, underflow_count
;
193 static streambuf
*test_this
;
194 static char test_get_buffer
[24];
195 static int buffer_pos
, get_end
;
198 static int __thiscall
test_streambuf_overflow(int ch
)
200 static int __thiscall
test_streambuf_overflow(streambuf
*this, int ch
)
204 if (ch
== 'L') /* simulate a failure */
206 if (!test_this
->unbuffered
)
207 test_this
->pptr
= test_this
->pbase
+ 5;
212 static int __thiscall
test_streambuf_underflow(void)
214 static int __thiscall
test_streambuf_underflow(streambuf
*this)
218 if (test_this
->unbuffered
) {
219 return (buffer_pos
< 23) ? test_get_buffer
[buffer_pos
++] : EOF
;
220 } else if (test_this
->gptr
< test_this
->egptr
) {
221 return *test_this
->gptr
;
223 return get_end
? EOF
: *(test_this
->gptr
= test_this
->eback
);
227 struct streambuf_lock_arg
234 static DWORD WINAPI
lock_streambuf(void *arg
)
236 struct streambuf_lock_arg
*lock_arg
= arg
;
237 call_func1(p_streambuf_lock
, lock_arg
->sb
);
238 SetEvent(lock_arg
->lock
[0]);
239 WaitForSingleObject(lock_arg
->test
[0], INFINITE
);
240 call_func1(p_streambuf_lock
, lock_arg
->sb
);
241 SetEvent(lock_arg
->lock
[1]);
242 WaitForSingleObject(lock_arg
->test
[1], INFINITE
);
243 call_func1(p_streambuf_lock
, lock_arg
->sb
);
244 SetEvent(lock_arg
->lock
[2]);
245 WaitForSingleObject(lock_arg
->test
[2], INFINITE
);
246 call_func1(p_streambuf_unlock
, lock_arg
->sb
);
247 SetEvent(lock_arg
->lock
[3]);
248 WaitForSingleObject(lock_arg
->test
[3], INFINITE
);
249 call_func1(p_streambuf_unlock
, lock_arg
->sb
);
253 static void test_streambuf(void)
255 streambuf sb
, sb2
, sb3
, *psb
;
256 vtable_ptr test_streambuf_vtbl
[11];
257 struct streambuf_lock_arg lock_arg
;
263 memset(&sb
, 0xab, sizeof(streambuf
));
264 memset(&sb2
, 0xab, sizeof(streambuf
));
265 memset(&sb3
, 0xab, sizeof(streambuf
));
268 call_func1(p_streambuf_ctor
, &sb
);
269 ok(sb
.allocated
== 0, "wrong allocate value, expected 0 got %d\n", sb
.allocated
);
270 ok(sb
.unbuffered
== 0, "wrong unbuffered value, expected 0 got %d\n", sb
.unbuffered
);
271 ok(sb
.base
== NULL
, "wrong base pointer, expected %p got %p\n", NULL
, sb
.base
);
272 ok(sb
.ebuf
== NULL
, "wrong ebuf pointer, expected %p got %p\n", NULL
, sb
.ebuf
);
273 ok(sb
.lock
.LockCount
== -1, "wrong critical section state, expected -1 got %d\n", sb
.lock
.LockCount
);
274 call_func3(p_streambuf_reserve_ctor
, &sb2
, reserve
, 16);
275 ok(sb2
.allocated
== 0, "wrong allocate value, expected 0 got %d\n", sb2
.allocated
);
276 ok(sb2
.unbuffered
== 0, "wrong unbuffered value, expected 0 got %d\n", sb2
.unbuffered
);
277 ok(sb2
.base
== reserve
, "wrong base pointer, expected %p got %p\n", reserve
, sb2
.base
);
278 ok(sb2
.ebuf
== reserve
+16, "wrong ebuf pointer, expected %p got %p\n", reserve
+16, sb2
.ebuf
);
279 ok(sb
.lock
.LockCount
== -1, "wrong critical section state, expected -1 got %d\n", sb
.lock
.LockCount
);
280 call_func1(p_streambuf_ctor
, &sb3
);
281 ok(sb3
.allocated
== 0, "wrong allocate value, expected 0 got %d\n", sb3
.allocated
);
282 ok(sb3
.unbuffered
== 0, "wrong unbuffered value, expected 0 got %d\n", sb3
.unbuffered
);
283 ok(sb3
.base
== NULL
, "wrong base pointer, expected %p got %p\n", NULL
, sb3
.base
);
284 ok(sb3
.ebuf
== NULL
, "wrong ebuf pointer, expected %p got %p\n", NULL
, sb3
.ebuf
);
286 memcpy(test_streambuf_vtbl
, sb
.vtable
, sizeof(test_streambuf_vtbl
));
287 test_streambuf_vtbl
[7] = (vtable_ptr
)&test_streambuf_overflow
;
288 test_streambuf_vtbl
[8] = (vtable_ptr
)&test_streambuf_underflow
;
289 sb2
.vtable
= test_streambuf_vtbl
;
290 sb3
.vtable
= test_streambuf_vtbl
;
291 overflow_count
= underflow_count
= 0;
292 strcpy(test_get_buffer
, "CompuGlobalHyperMegaNet");
293 buffer_pos
= get_end
= 0;
296 ok(sb
.do_lock
== -1, "expected do_lock value -1, got %d\n", sb
.do_lock
);
297 call_func1(p_streambuf_setlock
, &sb
);
298 ok(sb
.do_lock
== -2, "expected do_lock value -2, got %d\n", sb
.do_lock
);
299 call_func1(p_streambuf_setlock
, &sb
);
300 ok(sb
.do_lock
== -3, "expected do_lock value -3, got %d\n", sb
.do_lock
);
302 call_func1(p_streambuf_setlock
, &sb
);
303 ok(sb
.do_lock
== 2, "expected do_lock value 2, got %d\n", sb
.do_lock
);
307 call_func1(p_streambuf_clrclock
, &sb
);
308 ok(sb
.do_lock
== -1, "expected do_lock value -1, got %d\n", sb
.do_lock
);
309 call_func1(p_streambuf_clrclock
, &sb
);
310 ok(sb
.do_lock
== 0, "expected do_lock value 0, got %d\n", sb
.do_lock
);
311 call_func1(p_streambuf_clrclock
, &sb
);
312 ok(sb
.do_lock
== 1, "expected do_lock value 1, got %d\n", sb
.do_lock
);
313 call_func1(p_streambuf_clrclock
, &sb
);
314 ok(sb
.do_lock
== 1, "expected do_lock value 1, got %d\n", sb
.do_lock
);
318 for (i
= 0; i
< 4; i
++) {
319 lock_arg
.lock
[i
] = CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
320 ok(lock_arg
.lock
[i
] != NULL
, "CreateEventW failed\n");
321 lock_arg
.test
[i
] = CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
322 ok(lock_arg
.test
[i
] != NULL
, "CreateEventW failed\n");
326 thread
= CreateThread(NULL
, 0, lock_streambuf
, (void*)&lock_arg
, 0, NULL
);
327 ok(thread
!= NULL
, "CreateThread failed\n");
328 WaitForSingleObject(lock_arg
.lock
[0], INFINITE
);
329 locked
= TryEnterCriticalSection(&sb
.lock
);
330 ok(locked
!= 0, "could not lock the streambuf\n");
331 LeaveCriticalSection(&sb
.lock
);
334 SetEvent(lock_arg
.test
[0]);
335 WaitForSingleObject(lock_arg
.lock
[1], INFINITE
);
336 locked
= TryEnterCriticalSection(&sb
.lock
);
337 ok(locked
!= 0, "could not lock the streambuf\n");
338 LeaveCriticalSection(&sb
.lock
);
341 SetEvent(lock_arg
.test
[1]);
342 WaitForSingleObject(lock_arg
.lock
[2], INFINITE
);
343 locked
= TryEnterCriticalSection(&sb
.lock
);
344 ok(locked
== 0, "the streambuf was not locked before\n");
347 SetEvent(lock_arg
.test
[2]);
348 WaitForSingleObject(lock_arg
.lock
[3], INFINITE
);
349 locked
= TryEnterCriticalSection(&sb
.lock
);
350 ok(locked
== 0, "the streambuf was not locked before\n");
354 call_func4(p_streambuf_setb
, &sb
, reserve
, reserve
+16, 0);
355 ok(sb
.base
== reserve
, "wrong base pointer, expected %p got %p\n", reserve
, sb
.base
);
356 ok(sb
.ebuf
== reserve
+16, "wrong ebuf pointer, expected %p got %p\n", reserve
+16, sb
.ebuf
);
357 call_func4(p_streambuf_setb
, &sb
, reserve
, reserve
+16, 4);
358 ok(sb
.allocated
== 4, "wrong allocate value, expected 4 got %d\n", sb
.allocated
);
360 call_func4(p_streambuf_setb
, &sb
, NULL
, NULL
, 3);
361 ok(sb
.allocated
== 3, "wrong allocate value, expected 3 got %d\n", sb
.allocated
);
364 psb
= call_func3(p_streambuf_setbuf
, &sb
, NULL
, 5);
365 ok(psb
== &sb
, "wrong return value, expected %p got %p\n", &sb
, psb
);
366 ok(sb
.allocated
== 3, "wrong allocate value, expected 3 got %d\n", sb
.allocated
);
367 ok(sb
.unbuffered
== 1, "wrong unbuffered value, expected 1 got %d\n", sb
.unbuffered
);
368 ok(sb
.base
== NULL
, "wrong base pointer, expected %p got %p\n", NULL
, sb
.base
);
369 ok(sb
.ebuf
== NULL
, "wrong ebuf pointer, expected %p got %p\n", NULL
, sb
.ebuf
);
370 psb
= call_func3(p_streambuf_setbuf
, &sb
, reserve
, 0);
371 ok(psb
== &sb
, "wrong return value, expected %p got %p\n", &sb
, psb
);
372 ok(sb
.unbuffered
== 1, "wrong unbuffered value, expected 1 got %d\n", sb
.unbuffered
);
373 ok(sb
.base
== NULL
, "wrong base pointer, expected %p got %p\n", NULL
, sb
.base
);
374 ok(sb
.ebuf
== NULL
, "wrong ebuf pointer, expected %p got %p\n", NULL
, sb
.ebuf
);
375 psb
= call_func3(p_streambuf_setbuf
, &sb
, reserve
, 16);
376 ok(psb
== &sb
, "wrong return value, expected %p got %p\n", &sb
, psb
);
377 ok(sb
.allocated
== 3, "wrong allocate value, expected 3 got %d\n", sb
.allocated
);
378 ok(sb
.unbuffered
== 0, "wrong unbuffered value, expected 0 got %d\n", sb
.unbuffered
);
379 ok(sb
.base
== reserve
, "wrong base pointer, expected %p got %p\n", reserve
, sb
.base
);
380 ok(sb
.ebuf
== reserve
+16, "wrong ebuf pointer, expected %p got %p\n", reserve
+16, sb
.ebuf
);
381 psb
= call_func3(p_streambuf_setbuf
, &sb
, NULL
, 8);
382 ok(psb
== NULL
, "wrong return value, expected %p got %p\n", NULL
, psb
);
383 ok(sb
.unbuffered
== 0, "wrong unbuffered value, expected 0 got %d\n", sb
.unbuffered
);
384 ok(sb
.base
== reserve
, "wrong base pointer, expected %p got %p\n", reserve
, sb
.base
);
385 ok(sb
.ebuf
== reserve
+16, "wrong ebuf pointer, expected %p got %p\n", reserve
+16, sb
.ebuf
);
388 ret
= (int) call_func1(p_streambuf_allocate
, &sb
);
389 ok(ret
== 0, "wrong return value, expected 0 got %d\n", ret
);
391 ret
= (int) call_func1(p_streambuf_allocate
, &sb
);
392 ok(ret
== 1, "wrong return value, expected 1 got %d\n", ret
);
393 ok(sb
.allocated
== 1, "wrong allocate value, expected 1 got %d\n", sb
.allocated
);
394 ok(sb
.ebuf
- sb
.base
== 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb
.ebuf
, sb
.base
);
397 ret
= (int) call_func1(p_streambuf_doallocate
, &sb2
);
398 ok(ret
== 1, "doallocate failed, got %d\n", ret
);
399 ok(sb2
.allocated
== 1, "wrong allocate value, expected 1 got %d\n", sb2
.allocated
);
400 ok(sb2
.ebuf
- sb2
.base
== 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb2
.ebuf
, sb2
.base
);
401 ret
= (int) call_func1(p_streambuf_doallocate
, &sb3
);
402 ok(ret
== 1, "doallocate failed, got %d\n", ret
);
403 ok(sb3
.allocated
== 1, "wrong allocate value, expected 1 got %d\n", sb3
.allocated
);
404 ok(sb3
.ebuf
- sb3
.base
== 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb3
.ebuf
, sb3
.base
);
406 /* sb: buffered, space available */
407 sb
.eback
= sb
.gptr
= sb
.base
;
408 sb
.egptr
= sb
.base
+ 256;
409 sb
.pbase
= sb
.pptr
= sb
.base
+ 256;
410 sb
.epptr
= sb
.base
+ 512;
411 /* sb2: buffered, no space available */
412 sb2
.eback
= sb2
.base
;
413 sb2
.gptr
= sb2
.egptr
= sb2
.base
+ 256;
414 sb2
.pbase
= sb2
.base
+ 256;
415 sb2
.pptr
= sb2
.epptr
= sb2
.base
+ 512;
416 /* sb3: unbuffered */
420 call_func2(p_streambuf_gbump
, &sb
, 10);
421 ok(sb
.gptr
== sb
.eback
+ 10, "advance get pointer failed, expected %p got %p\n", sb
.eback
+ 10, sb
.gptr
);
422 call_func2(p_streambuf_gbump
, &sb
, -15);
423 ok(sb
.gptr
== sb
.eback
- 5, "advance get pointer failed, expected %p got %p\n", sb
.eback
- 5, sb
.gptr
);
427 call_func2(p_streambuf_pbump
, &sb
, -2);
428 ok(sb
.pptr
== sb
.pbase
- 2, "advance put pointer failed, expected %p got %p\n", sb
.pbase
- 2, sb
.pptr
);
429 call_func2(p_streambuf_pbump
, &sb
, 20);
430 ok(sb
.pptr
== sb
.pbase
+ 18, "advance put pointer failed, expected %p got %p\n", sb
.pbase
+ 18, sb
.pptr
);
434 ret
= (int) call_func1(p_streambuf_sync
, &sb
);
435 ok(ret
== EOF
, "sync failed, expected EOF got %d\n", ret
);
437 ret
= (int) call_func1(p_streambuf_sync
, &sb
);
438 ok(ret
== 0, "sync failed, expected 0 got %d\n", ret
);
439 sb
.gptr
= sb
.egptr
+ 1;
440 ret
= (int) call_func1(p_streambuf_sync
, &sb
);
441 ok(ret
== 0, "sync failed, expected 0 got %d\n", ret
);
443 ret
= (int) call_func1(p_streambuf_sync
, &sb2
);
444 ok(ret
== EOF
, "sync failed, expected EOF got %d\n", ret
);
445 sb2
.pptr
= sb2
.pbase
;
446 ret
= (int) call_func1(p_streambuf_sync
, &sb2
);
447 ok(ret
== 0, "sync failed, expected 0 got %d\n", ret
);
448 sb2
.pptr
= sb2
.pbase
- 1;
449 ret
= (int) call_func1(p_streambuf_sync
, &sb2
);
450 ok(ret
== 0, "sync failed, expected 0 got %d\n", ret
);
451 sb2
.pptr
= sb2
.epptr
;
452 ret
= (int) call_func1(p_streambuf_sync
, &sb3
);
453 ok(ret
== 0, "sync failed, expected 0 got %d\n", ret
);
456 strcpy(sb2
.eback
, "WorstTestEver");
458 ret
= (int) call_func1(p_streambuf_sgetc
, &sb2
);
459 ok(ret
== 'W', "expected 'W' got '%c'\n", ret
);
460 ok(underflow_count
== 1, "expected call to underflow\n");
461 ok(sb2
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb2
.stored_char
);
463 ret
= (int) call_func1(p_streambuf_sgetc
, &sb2
);
464 ok(ret
== 'o', "expected 'o' got '%c'\n", ret
);
465 ok(underflow_count
== 2, "expected call to underflow\n");
466 ok(sb2
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb2
.stored_char
);
467 sb2
.gptr
= sb2
.egptr
;
469 ret
= (int) call_func1(p_streambuf_sgetc
, &sb3
);
470 ok(ret
== 'C', "expected 'C' got '%c'\n", ret
);
471 ok(underflow_count
== 3, "expected call to underflow\n");
472 ok(sb3
.stored_char
== 'C', "wrong stored character, expected 'C' got %c\n", sb3
.stored_char
);
473 sb3
.stored_char
= 'b';
474 ret
= (int) call_func1(p_streambuf_sgetc
, &sb3
);
475 ok(ret
== 'b', "expected 'b' got '%c'\n", ret
);
476 ok(underflow_count
== 3, "no call to underflow expected\n");
477 ok(sb3
.stored_char
== 'b', "wrong stored character, expected 'b' got %c\n", sb3
.stored_char
);
481 ret
= (int) call_func2(p_streambuf_sputc
, &sb
, 'c');
482 ok(ret
== 'c', "wrong return value, expected 'c' got %d\n", ret
);
483 ok(overflow_count
== 0, "no call to overflow expected\n");
484 ok(*sb
.pbase
== 'c', "expected 'c' in the put area, got %c\n", *sb
.pbase
);
485 ok(sb
.pptr
== sb
.pbase
+ 1, "wrong put pointer, expected %p got %p\n", sb
.pbase
+ 1, sb
.pptr
);
487 ret
= (int) call_func2(p_streambuf_sputc
, &sb2
, 'c');
488 ok(ret
== 'c', "wrong return value, expected 'c' got %d\n", ret
);
489 ok(overflow_count
== 1, "expected call to overflow\n");
490 ok(sb2
.pptr
== sb2
.pbase
+ 5, "wrong put pointer, expected %p got %p\n", sb2
.pbase
+ 5, sb2
.pptr
);
492 ret
= (int) call_func2(p_streambuf_sputc
, &sb3
, 'c');
493 ok(ret
== 'c', "wrong return value, expected 'c' got %d\n", ret
);
494 ok(overflow_count
== 2, "expected call to overflow\n");
495 sb3
.pbase
= sb3
.pptr
= sb3
.base
;
496 sb3
.epptr
= sb3
.ebuf
;
497 ret
= (int) call_func2(p_streambuf_sputc
, &sb3
, 'c');
498 ok(ret
== 'c', "wrong return value, expected 'c' got %d\n", ret
);
499 ok(overflow_count
== 2, "no call to overflow expected\n");
500 ok(*sb3
.pbase
== 'c', "expected 'c' in the put area, got %c\n", *sb3
.pbase
);
501 sb3
.pbase
= sb3
.pptr
= sb3
.epptr
= NULL
;
504 sb2
.gptr
= sb2
.egptr
= sb2
.eback
+ 13;
506 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb2
, reserve
, 5);
507 ok(ret
== 5, "wrong return value, expected 5 got %d\n", ret
);
508 ok(!strncmp(reserve
, "Worst", 5), "expected 'Worst' got %s\n", reserve
);
509 ok(sb2
.gptr
== sb2
.eback
+ 5, "wrong get pointer, expected %p got %p\n", sb2
.eback
+ 5, sb2
.gptr
);
510 ok(underflow_count
== 4, "expected call to underflow\n");
511 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb2
, reserve
, 4);
512 ok(ret
== 4, "wrong return value, expected 4 got %d\n", ret
);
513 ok(!strncmp(reserve
, "Test", 4), "expected 'Test' got %s\n", reserve
);
514 ok(sb2
.gptr
== sb2
.eback
+ 9, "wrong get pointer, expected %p got %p\n", sb2
.eback
+ 9, sb2
.gptr
);
515 ok(underflow_count
== 5, "expected call to underflow\n");
517 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb2
, reserve
, 16);
518 ok(ret
== 4, "wrong return value, expected 4 got %d\n", ret
);
519 ok(!strncmp(reserve
, "Ever", 4), "expected 'Ever' got %s\n", reserve
);
520 ok(sb2
.gptr
== sb2
.egptr
, "wrong get pointer, expected %p got %p\n", sb2
.egptr
, sb2
.gptr
);
521 ok(underflow_count
== 7, "expected 2 calls to underflow, got %d\n", underflow_count
- 5);
523 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb3
, reserve
, 11);
524 ok(ret
== 11, "wrong return value, expected 11 got %d\n", ret
);
525 ok(!strncmp(reserve
, "bompuGlobal", 11), "expected 'bompuGlobal' got %s\n", reserve
);
526 ok(sb3
.stored_char
== 'H', "wrong stored character, expected 'H' got %c\n", sb3
.stored_char
);
527 ok(underflow_count
== 18, "expected 11 calls to underflow, got %d\n", underflow_count
- 7);
528 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb3
, reserve
, 16);
529 ok(ret
== 12, "wrong return value, expected 12 got %d\n", ret
);
530 ok(!strncmp(reserve
, "HyperMegaNet", 12), "expected 'HyperMegaNet' got %s\n", reserve
);
531 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
532 ok(underflow_count
== 30, "expected 12 calls to underflow, got %d\n", underflow_count
- 18);
533 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb3
, reserve
, 3);
534 ok(ret
== 0, "wrong return value, expected 0 got %d\n", ret
);
535 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
536 ok(underflow_count
== 31, "expected call to underflow\n");
538 ret
= (int) call_func3(p_streambuf_xsgetn
, &sb3
, reserve
, 5);
539 ok(ret
== 5, "wrong return value, expected 5 got %d\n", ret
);
540 ok(!strncmp(reserve
, "Compu", 5), "expected 'Compu' got %s\n", reserve
);
541 ok(sb3
.stored_char
== 'G', "wrong stored character, expected 'G' got %c\n", sb3
.stored_char
);
542 ok(underflow_count
== 37, "expected 6 calls to underflow, got %d\n", underflow_count
- 31);
545 ret
= (int) call_func3(p_streambuf_xsputn
, &sb
, "Test\0ing", 8);
546 ok(ret
== 8, "wrong return value, expected 8 got %d\n", ret
);
547 ok(sb
.pptr
== sb
.pbase
+ 9, "wrong put pointer, expected %p got %p\n", sb
.pbase
+ 9, sb
.pptr
);
549 sb2
.pptr
= sb2
.epptr
- 7;
550 ret
= (int) call_func3(p_streambuf_xsputn
, &sb2
, "Testing", 7);
551 ok(ret
== 7, "wrong return value, expected 7 got %d\n", ret
);
552 ok(sb2
.pptr
== sb2
.epptr
, "wrong put pointer, expected %p got %p\n", sb2
.epptr
, sb2
.pptr
);
553 ok(overflow_count
== 2, "no call to overflow expected\n");
554 sb2
.pptr
= sb2
.epptr
- 5;
556 ret
= (int) call_func3(p_streambuf_xsputn
, &sb2
, "Testing", 7);
557 ok(ret
== 7, "wrong return value, expected 7 got %d\n", ret
);
558 ok(sb2
.pbase
[5] == 'g', "expected 'g' got %c\n", sb2
.pbase
[5]);
559 ok(sb2
.pptr
== sb2
.pbase
+ 6, "wrong put pointer, expected %p got %p\n", sb2
.pbase
+ 6, sb2
.pptr
);
560 ok(overflow_count
== 3, "expected call to overflow\n");
561 sb2
.pptr
= sb2
.epptr
- 4;
562 ret
= (int) call_func3(p_streambuf_xsputn
, &sb2
, "TestLing", 8);
563 ok(ret
== 4, "wrong return value, expected 4 got %d\n", ret
);
564 ok(sb2
.pptr
== sb2
.epptr
, "wrong put pointer, expected %p got %p\n", sb2
.epptr
, sb2
.pptr
);
565 ok(overflow_count
== 4, "expected call to overflow\n");
567 ret
= (int) call_func3(p_streambuf_xsputn
, &sb3
, "Testing", 7);
568 ok(ret
== 7, "wrong return value, expected 7 got %d\n", ret
);
569 ok(sb3
.stored_char
== 'G', "wrong stored character, expected 'G' got %c\n", sb3
.stored_char
);
570 ok(overflow_count
== 11, "expected 7 calls to overflow, got %d\n", overflow_count
- 4);
571 ret
= (int) call_func3(p_streambuf_xsputn
, &sb3
, "TeLephone", 9);
572 ok(ret
== 2, "wrong return value, expected 2 got %d\n", ret
);
573 ok(sb3
.stored_char
== 'G', "wrong stored character, expected 'G' got %c\n", sb3
.stored_char
);
574 ok(overflow_count
== 14, "expected 3 calls to overflow, got %d\n", overflow_count
- 11);
577 strcpy(sb
.eback
, "Test");
578 ret
= (int) call_func1(p_streambuf_snextc
, &sb
);
579 ok(ret
== 'e', "expected 'e' got '%c'\n", ret
);
580 ok(sb
.gptr
== sb
.eback
+ 1, "wrong get pointer, expected %p got %p\n", sb
.eback
+ 1, sb
.gptr
);
582 ret
= (int) call_func1(p_streambuf_snextc
, &sb2
);
583 ok(ret
== EOF
, "expected EOF got '%c'\n", ret
);
584 ok(sb2
.gptr
== sb2
.egptr
+ 1, "wrong get pointer, expected %p got %p\n", sb2
.egptr
+ 1, sb2
.gptr
);
585 ok(underflow_count
== 39, "expected 2 calls to underflow, got %d\n", underflow_count
- 37);
586 sb2
.gptr
= sb2
.egptr
- 1;
587 ret
= (int) call_func1(p_streambuf_snextc
, &sb2
);
588 ok(ret
== EOF
, "expected EOF got '%c'\n", ret
);
589 ok(sb2
.gptr
== sb2
.egptr
, "wrong get pointer, expected %p got %p\n", sb2
.egptr
, sb2
.gptr
);
590 ok(underflow_count
== 40, "expected call to underflow\n");
592 ret
= (int) call_func1(p_streambuf_snextc
, &sb2
);
593 ok(ret
== 'o', "expected 'o' got '%c'\n", ret
);
594 ok(sb2
.gptr
== sb2
.eback
+ 1, "wrong get pointer, expected %p got %p\n", sb2
.eback
+ 1, sb2
.gptr
);
595 ok(underflow_count
== 41, "expected call to underflow\n");
596 sb2
.gptr
= sb2
.egptr
- 1;
597 ret
= (int) call_func1(p_streambuf_snextc
, &sb2
);
598 ok(ret
== 'W', "expected 'W' got '%c'\n", ret
);
599 ok(sb2
.gptr
== sb2
.eback
, "wrong get pointer, expected %p got %p\n", sb2
.eback
, sb2
.gptr
);
600 ok(underflow_count
== 42, "expected call to underflow\n");
601 sb2
.gptr
= sb2
.egptr
;
603 ret
= (int) call_func1(p_streambuf_snextc
, &sb3
);
604 ok(ret
== 'l', "expected 'l' got '%c'\n", ret
);
605 ok(sb3
.stored_char
== 'l', "wrong stored character, expected 'l' got %c\n", sb3
.stored_char
);
606 ok(underflow_count
== 43, "expected call to underflow\n");
608 ret
= (int) call_func1(p_streambuf_snextc
, &sb3
);
609 ok(ret
== 't', "expected 't' got '%c'\n", ret
);
610 ok(sb3
.stored_char
== 't', "wrong stored character, expected 't' got %c\n", sb3
.stored_char
);
611 ok(underflow_count
== 44, "expected call to underflow\n");
612 ret
= (int) call_func1(p_streambuf_snextc
, &sb3
);
613 ok(ret
== EOF
, "expected EOF got '%c'\n", ret
);
614 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
615 ok(underflow_count
== 45, "expected call to underflow\n");
617 ret
= (int) call_func1(p_streambuf_snextc
, &sb3
);
618 ok(ret
== 'o', "expected 'o' got '%c'\n", ret
);
619 ok(sb3
.stored_char
== 'o', "wrong stored character, expected 'o' got %c\n", sb3
.stored_char
);
620 ok(underflow_count
== 47, "expected 2 calls to underflow, got %d\n", underflow_count
- 45);
621 sb3
.stored_char
= EOF
;
622 ret
= (int) call_func1(p_streambuf_snextc
, &sb3
);
623 ok(ret
== 'p', "expected 'p' got '%c'\n", ret
);
624 ok(sb3
.stored_char
== 'p', "wrong stored character, expected 'p' got %c\n", sb3
.stored_char
);
625 ok(underflow_count
== 49, "expected 2 calls to underflow, got %d\n", underflow_count
- 47);
628 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb
);
629 ok(ret
== 'e', "expected 'e' got '%c'\n", ret
);
630 ok(sb
.gptr
== sb
.eback
+ 2, "wrong get pointer, expected %p got %p\n", sb
.eback
+ 2, sb
.gptr
);
632 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb2
);
633 ok(ret
== 'W', "expected 'W' got '%c'\n", ret
);
634 ok(sb2
.gptr
== sb2
.eback
+ 1, "wrong get pointer, expected %p got %p\n", sb2
.eback
+ 1, sb2
.gptr
);
635 ok(underflow_count
== 50, "expected call to underflow\n");
636 sb2
.gptr
= sb2
.egptr
- 1;
638 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb2
);
639 ok(ret
== 't', "expected 't' got '%c'\n", ret
);
640 ok(sb2
.gptr
== sb2
.egptr
, "wrong get pointer, expected %p got %p\n", sb2
.egptr
, sb2
.gptr
);
641 ok(underflow_count
== 50, "no call to underflow expected\n");
643 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb2
);
644 ok(ret
== EOF
, "expected EOF got '%c'\n", ret
);
645 ok(sb2
.gptr
== sb2
.egptr
+ 1, "wrong get pointer, expected %p got %p\n", sb2
.egptr
+ 1, sb2
.gptr
);
646 ok(underflow_count
== 51, "expected call to underflow\n");
647 sb2
.gptr
= sb2
.egptr
;
649 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb3
);
650 ok(ret
== 'p', "expected 'p' got '%c'\n", ret
);
651 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
652 ok(underflow_count
== 51, "no call to underflow expected\n");
653 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb3
);
654 ok(ret
== 'u', "expected 'u' got '%c'\n", ret
);
655 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
656 ok(underflow_count
== 52, "expected call to underflow\n");
658 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb3
);
659 ok(ret
== EOF
, "expected EOF got '%c'\n", ret
);
660 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
661 ok(underflow_count
== 53, "expected call to underflow\n");
663 ret
= (int) call_func1(p_streambuf_sbumpc
, &sb3
);
664 ok(ret
== 'C', "expected 'C' got '%c'\n", ret
);
665 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
666 ok(underflow_count
== 54, "expected call to underflow\n");
669 call_func1(p_streambuf_stossc
, &sb
);
670 ok(sb
.gptr
== sb
.eback
+ 3, "wrong get pointer, expected %p got %p\n", sb
.eback
+ 3, sb
.gptr
);
672 call_func1(p_streambuf_stossc
, &sb2
);
673 ok(sb2
.gptr
== sb2
.egptr
, "wrong get pointer, expected %p got %p\n", sb2
.egptr
, sb2
.gptr
);
674 ok(underflow_count
== 55, "expected call to underflow\n");
676 call_func1(p_streambuf_stossc
, &sb2
);
677 ok(sb2
.gptr
== sb2
.eback
+ 1, "wrong get pointer, expected %p got %p\n", sb2
.eback
+ 1, sb2
.gptr
);
678 ok(underflow_count
== 56, "expected call to underflow\n");
679 sb2
.gptr
= sb2
.egptr
- 1;
680 call_func1(p_streambuf_stossc
, &sb2
);
681 ok(sb2
.gptr
== sb2
.egptr
, "wrong get pointer, expected %p got %p\n", sb2
.egptr
, sb2
.gptr
);
682 ok(underflow_count
== 56, "no call to underflow expected\n");
684 call_func1(p_streambuf_stossc
, &sb3
);
685 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
686 ok(underflow_count
== 57, "expected call to underflow\n");
687 sb3
.stored_char
= 'a';
688 call_func1(p_streambuf_stossc
, &sb3
);
689 ok(sb3
.stored_char
== EOF
, "wrong stored character, expected EOF got %c\n", sb3
.stored_char
);
690 ok(underflow_count
== 57, "no call to underflow expected\n");
692 SetEvent(lock_arg
.test
[3]);
693 WaitForSingleObject(thread
, INFINITE
);
695 call_func1(p_streambuf_dtor
, &sb
);
696 call_func1(p_streambuf_dtor
, &sb2
);
697 call_func1(p_streambuf_dtor
, &sb3
);
698 for (i
= 0; i
< 4; i
++) {
699 CloseHandle(lock_arg
.lock
[i
]);
700 CloseHandle(lock_arg
.test
[i
]);
712 FreeLibrary(msvcirt
);