ReactOS 0.4.16-dev-2354-g16de117
hglobalstream.c
Go to the documentation of this file.
1/*
2 * Stream on HGLOBAL Tests
3 *
4 * Copyright 2006 Robert Shearman (for CodeWeavers)
5 * Copyright 2016 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define COBJMACROS
23
24#include <stdarg.h>
25
26#include "windef.h"
27#include "winbase.h"
28#include "objbase.h"
29
30#include "wine/test.h"
31
32#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error %#08lx\n", hr)
33
34static char const * const *expected_method_list;
35
36#define CHECK_EXPECTED_METHOD(method_name) \
37do { \
38 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
39 if (*expected_method_list) \
40 { \
41 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
42 *expected_method_list, method_name); \
43 expected_method_list++; \
44 } \
45} while(0)
46
47static void test_streamonhglobal(void)
48{
49 const char data[] = "Test String";
51 IStream *pStream;
53 char buffer[128];
54 ULONG read;
55 STATSTG statstg;
56 HRESULT hr;
57
58 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
59 ok(hr == S_OK, "Failed to create a stream, hr %#lx.\n", hr);
60
61 ull.QuadPart = sizeof(data);
62 hr = IStream_SetSize(pStream, ull);
63 ok_ole_success(hr, "IStream_SetSize");
64
65 hr = IStream_Write(pStream, data, sizeof(data), NULL);
66 ok_ole_success(hr, "IStream_Write");
67
68 /* Seek beyond the end of the stream and read from it */
69 ll.QuadPart = sizeof(data) + 16;
70 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, NULL);
71 ok_ole_success(hr, "IStream_Seek");
72
73 hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
74 ok_ole_success(hr, "IStream_Read");
75 ok(read == 0, "IStream_Read returned read %ld\n", read);
76
77 ull.u.HighPart = 0xCAFECAFE;
78 ull.u.LowPart = 0xCAFECAFE;
79 ll.u.HighPart = 0;
80 ll.u.LowPart = 0;
81 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
82 ok_ole_success(hr, "IStream_Seek");
83 ok(ull.u.LowPart == sizeof(data) + 16, "LowPart set to %ld\n", ull.u.LowPart);
84 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
85
86 /* Seek to the start of the stream and read from it */
87 ll.QuadPart = 0;
88 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, NULL);
89 ok_ole_success(hr, "IStream_Seek");
90
91 /* should return S_OK, not S_FALSE */
92 hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
93 ok_ole_success(hr, "IStream_Read");
94 ok(read == sizeof(data), "IStream_Read returned read %ld\n", read);
95
96 /* ignores HighPart */
97 ull.u.HighPart = -1;
98 ull.u.LowPart = 0;
99 hr = IStream_SetSize(pStream, ull);
100 ok_ole_success(hr, "IStream_SetSize");
101
102 /* IStream_Seek -- NULL position argument */
103 ll.u.HighPart = 0;
104 ll.u.LowPart = 0;
105 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, NULL);
106 ok_ole_success(hr, "IStream_Seek");
107
108 /* IStream_Seek -- valid position argument (seek from current position) */
109 ull.u.HighPart = 0xCAFECAFE;
110 ull.u.LowPart = 0xCAFECAFE;
111 ll.u.HighPart = 0;
112 ll.u.LowPart = 0;
113 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
114 ok_ole_success(hr, "IStream_Seek");
115 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
116 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
117
118 /* IStream_Seek -- invalid seek argument */
119 ull.u.HighPart = 0xCAFECAFE;
120 ull.u.LowPart = 0xCAFECAFE;
121 ll.u.HighPart = 0;
122 ll.u.LowPart = 123;
123 hr = IStream_Seek(pStream, ll, STREAM_SEEK_END+1, &ull);
124 ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08lx\n", hr);
125 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
126 ok(ull.u.HighPart == 0, "should not have changed HighPart, got %ld\n", ull.u.HighPart);
127
128 /* IStream_Seek -- valid position argument (seek to beginning) */
129 ull.u.HighPart = 0xCAFECAFE;
130 ull.u.LowPart = 0xCAFECAFE;
131 ll.u.HighPart = 0;
132 ll.u.LowPart = 0;
133 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
134 ok_ole_success(hr, "IStream_Seek");
135 ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %ld\n", ull.u.LowPart);
136 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
137
138 /* IStream_Seek -- valid position argument (seek to end) */
139 ull.u.HighPart = 0xCAFECAFE;
140 ull.u.LowPart = 0xCAFECAFE;
141 ll.u.HighPart = 0;
142 ll.u.LowPart = 0;
143 hr = IStream_Seek(pStream, ll, STREAM_SEEK_END, &ull);
144 ok_ole_success(hr, "IStream_Seek");
145 ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %ld\n", ull.u.LowPart);
146 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
147
148 /* IStream_Seek -- ignore HighPart in the move value (seek from current position) */
149 ll.u.HighPart = 0;
150 ll.u.LowPart = sizeof(data);
151 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
152 ok_ole_success(hr, "IStream_Seek");
153
154 ull.u.HighPart = 0xCAFECAFE;
155 ull.u.LowPart = 0xCAFECAFE;
156 ll.u.HighPart = -1;
157 ll.u.LowPart = 0;
158 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
159 ok_ole_success(hr, "IStream_Seek");
160 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
161 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
162
163 /* IStream_Seek -- ignore HighPart in the move value (seek to beginning) */
164 ll.u.HighPart = 0;
165 ll.u.LowPart = sizeof(data);
166 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
167 ok_ole_success(hr, "IStream_Seek");
168
169 ull.u.HighPart = 0xCAFECAFE;
170 ull.u.LowPart = 0xCAFECAFE;
171 ll.u.HighPart = -1;
172 ll.u.LowPart = 0;
173 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
174 ok_ole_success(hr, "IStream_Seek");
175 ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %ld\n", ull.u.LowPart);
176 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
177
178 /* IStream_Seek -- invalid LowPart value (seek before start of stream) */
179 ll.u.HighPart = 0;
180 ll.u.LowPart = sizeof(data);
181 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
182 ok_ole_success(hr, "IStream_Seek");
183
184 ull.u.HighPart = 0xCAFECAFE;
185 ull.u.LowPart = 0xCAFECAFE;
186 ll.u.HighPart = 0;
187 ll.u.LowPart = 0x80000000;
188 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
189 ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08lx\n", hr);
190 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
191 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
192
193 /* IStream_Seek -- valid LowPart value (seek to start of stream) */
194 ll.u.HighPart = 0;
195 ll.u.LowPart = sizeof(data);
196 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
197 ok_ole_success(hr, "IStream_Seek");
198
199 ull.u.HighPart = 0xCAFECAFE;
200 ull.u.LowPart = 0xCAFECAFE;
201 ll.u.HighPart = 0;
202 ll.u.LowPart = -(DWORD)sizeof(data);
203 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
204 ok_ole_success(hr, "IStream_Seek");
205 ok(ull.u.LowPart == 0, "LowPart set to %ld\n", ull.u.LowPart);
206 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
207
208 /* IStream_Seek -- invalid LowPart value (seek to start of stream-1) */
209 ll.u.HighPart = 0;
210 ll.u.LowPart = sizeof(data);
211 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
212 ok_ole_success(hr, "IStream_Seek");
213
214 ull.u.HighPart = 0xCAFECAFE;
215 ull.u.LowPart = 0xCAFECAFE;
216 ll.u.HighPart = 0;
217 ll.u.LowPart = -(DWORD)sizeof(data)-1;
218 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
219 ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08lx\n", hr);
220 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
221 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
222
223 /* IStream_Seek -- valid LowPart value (seek forward to 0x80000000) */
224 ll.u.HighPart = 0;
225 ll.u.LowPart = sizeof(data);
226 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
227 ok_ole_success(hr, "IStream_Seek");
228
229 ull.u.HighPart = 0xCAFECAFE;
230 ull.u.LowPart = 0xCAFECAFE;
231 ll.u.HighPart = 0;
232 ll.u.LowPart = 0x80000000 - sizeof(data);
233 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
234 ok_ole_success(hr, "IStream_Seek");
235 ok(ull.u.LowPart == 0x80000000, "LowPart set to %ld\n", ull.u.LowPart);
236 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
237
238 /* IStream_Seek -- invalid LowPart value (seek to beginning) */
239 ll.u.HighPart = 0;
240 ll.u.LowPart = sizeof(data);
241 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
242 ok_ole_success(hr, "IStream_Seek");
243
244 ull.u.HighPart = 0xCAFECAFE;
245 ull.u.LowPart = 0xCAFECAFE;
246 ll.u.HighPart = 0;
247 ll.u.LowPart = 0x80000000;
248 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
249 ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08lx\n", hr);
250 ok(ull.u.LowPart == sizeof(data), "LowPart set to %ld\n", ull.u.LowPart);
251 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
252
253 /* IStream_Seek -- valid LowPart value (seek to beginning) */
254 ull.u.HighPart = 0xCAFECAFE;
255 ull.u.LowPart = 0xCAFECAFE;
256 ll.u.HighPart = 0;
257 ll.u.LowPart = 0x7FFFFFFF;
258 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
259 ok_ole_success(hr, "IStream_Seek");
260 ok(ull.u.LowPart == 0x7FFFFFFF, "should have set LowPart to 0x7FFFFFFF instead of %08lx\n", ull.u.LowPart);
261 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
262
263 /* IStream_Seek -- valid LowPart value (seek from current position) */
264 ll.u.HighPart = 0;
265 ll.u.LowPart = 0;
266 hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
267 ok_ole_success(hr, "IStream_Seek");
268
269 ull.u.HighPart = 0xCAFECAFE;
270 ull.u.LowPart = 0xCAFECAFE;
271 ll.u.HighPart = 0;
272 ll.u.LowPart = 0x7FFFFFFF;
273 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
274 ok_ole_success(hr, "IStream_Seek");
275 ok(ull.u.LowPart == 0x7FFFFFFF, "should have set LowPart to 0x7FFFFFFF instead of %08lx\n", ull.u.LowPart);
276 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
277
278 /* IStream_Seek -- second seek allows you to go past 0x7FFFFFFF size */
279 ull.u.HighPart = 0xCAFECAFE;
280 ull.u.LowPart = 0xCAFECAFE;
281 ll.u.HighPart = 0;
282 ll.u.LowPart = 9;
283 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
284 ok_ole_success(hr, "IStream_Seek");
285 ok(ull.u.LowPart == 0x80000008, "should have set LowPart to 0x80000008 instead of %08lx\n", ull.u.LowPart);
286 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
287
288 /* IStream_Seek -- seek wraps position/size on integer overflow, but not on win8 */
289 ull.u.HighPart = 0xCAFECAFE;
290 ull.u.LowPart = 0xCAFECAFE;
291 ll.u.HighPart = 0;
292 ll.u.LowPart = 0x7FFFFFFF;
293 hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
294 ok(hr == S_OK || hr == STG_E_SEEKERROR /* win8 */, "IStream_Seek\n");
295 if (SUCCEEDED(hr))
296 ok(ull.u.LowPart == 0x00000007, "should have set LowPart to 0x00000007 instead of %08lx\n", ull.u.LowPart);
297 else
298 ok(ull.u.LowPart == 0x80000008, "should have set LowPart to 0x80000008 instead of %08lx\n", ull.u.LowPart);
299 ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %ld\n", ull.u.HighPart);
300
301 hr = IStream_Commit(pStream, STGC_DEFAULT);
302 ok_ole_success(hr, "IStream_Commit");
303
304 hr = IStream_Revert(pStream);
305 ok_ole_success(hr, "IStream_Revert");
306
307 hr = IStream_LockRegion(pStream, ull, ull, LOCK_WRITE);
308 ok(hr == STG_E_INVALIDFUNCTION, "IStream_LockRegion should have returned STG_E_INVALIDFUNCTION instead of 0x%08lx\n", hr);
309
310 hr = IStream_Stat(pStream, &statstg, STATFLAG_DEFAULT);
311 ok_ole_success(hr, "IStream_Stat");
312 ok(statstg.type == STGTY_STREAM, "statstg.type should have been STGTY_STREAM instead of %ld\n", statstg.type);
313
314 /* test OOM condition */
315 ull.u.HighPart = -1;
316 ull.u.LowPart = 0;
317 hr = IStream_SetSize(pStream, ull);
318 ok(hr == S_OK, "IStream_SetSize with large size should have returned S_OK instead of 0x%08lx\n", hr);
319
320 IStream_Release(pStream);
321}
322
324{
326 IsEqualIID(riid, &IID_ISequentialStream) ||
327 IsEqualIID(riid, &IID_IStream))
328 {
329 *ppv = iface;
330 IStream_AddRef(iface);
331 return S_OK;
332 }
333 *ppv = NULL;
334 return E_NOINTERFACE;
335}
336
338{
339 return 2;
340}
341
343{
344 return 1;
345}
346
347static HRESULT WINAPI TestStream_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead)
348{
349 CHECK_EXPECTED_METHOD("TestStream_Read");
350 return E_NOTIMPL;
351}
352
353static HRESULT WINAPI TestStream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten)
354{
355 CHECK_EXPECTED_METHOD("TestStream_Write");
356 *pcbWritten = 5;
357 return S_OK;
358}
359
360static HRESULT WINAPI TestStream_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
361{
362 CHECK_EXPECTED_METHOD("TestStream_Seek");
363 return E_NOTIMPL;
364}
365
367{
368 CHECK_EXPECTED_METHOD("TestStream_SetSize");
369 return E_NOTIMPL;
370}
371
373{
374 CHECK_EXPECTED_METHOD("TestStream_CopyTo");
375 return E_NOTIMPL;
376}
377
378static HRESULT WINAPI TestStream_Commit(IStream *iface, DWORD grfCommitFlags)
379{
380 CHECK_EXPECTED_METHOD("TestStream_Commit");
381 return E_NOTIMPL;
382}
383
385{
386 CHECK_EXPECTED_METHOD("TestStream_Revert");
387 return E_NOTIMPL;
388}
389
391{
392 CHECK_EXPECTED_METHOD("TestStream_LockRegion");
393 return E_NOTIMPL;
394}
395
397{
398 CHECK_EXPECTED_METHOD("TestStream_UnlockRegion");
399 return E_NOTIMPL;
400}
401
402static HRESULT WINAPI TestStream_Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
403{
404 CHECK_EXPECTED_METHOD("TestStream_Stat");
405 return E_NOTIMPL;
406}
407
409{
410 CHECK_EXPECTED_METHOD("TestStream_Clone");
411 return E_NOTIMPL;
412}
413
414static /*const*/ IStreamVtbl StreamVtbl =
415{
430};
431
433
434static void test_copyto(void)
435{
436 IStream *pStream, *pStream2;
438 static const char szHello[] = "Hello";
440 static const char *methods_copyto[] =
441 {
442 "TestStream_Write",
443 NULL
444 };
445 ULONG written;
446 ULARGE_INTEGER ullRead;
447 ULARGE_INTEGER ullWritten;
448 ULARGE_INTEGER libNewPosition;
449 static const LARGE_INTEGER llZero;
450 char buffer[15];
451
452 ok_ole_success(hr, "CreateStreamOnHGlobal");
453
454 expected_method_list = methods_copyto;
455
456 hr = IStream_Write(pStream, szHello, sizeof(szHello), &written);
457 ok_ole_success(hr, "IStream_Write");
458 ok(written == sizeof(szHello), "only %ld bytes written\n", written);
459
460 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
461 ok_ole_success(hr, "IStream_Seek");
462
463 cb.QuadPart = sizeof(szHello);
464 hr = IStream_CopyTo(pStream, &Test_Stream, cb, &ullRead, &ullWritten);
465 ok(ullWritten.QuadPart == 5, "ullWritten was %ld instead\n", (ULONG)ullWritten.QuadPart);
466 ok(ullRead.QuadPart == sizeof(szHello), "only %ld bytes read\n", (ULONG)ullRead.QuadPart);
467 ok_ole_success(hr, "IStream_CopyTo");
468
469 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
470
471 hr = IStream_Clone(pStream, &pStream2);
472 ok_ole_success(hr, "IStream_Clone");
473
474 hr = IStream_Seek(pStream2, llZero, STREAM_SEEK_CUR, &libNewPosition);
475 ok_ole_success(hr, "IStream_Seek");
476 ok(libNewPosition.QuadPart == sizeof(szHello), "libNewPosition wasn't set correctly for the cloned stream\n");
477
478 hr = IStream_Seek(pStream2, llZero, STREAM_SEEK_SET, NULL);
479 ok_ole_success(hr, "IStream_Seek");
480
481 hr = IStream_Read(pStream2, buffer, sizeof(buffer), NULL);
482 ok_ole_success(hr, "IStream_Read");
483 ok(!strcmp(buffer, szHello), "read data \"%s\" didn't match originally written data\n", buffer);
484
485 IStream_Release(pStream2);
486 IStream_Release(pStream);
487}
488
489static void test_freed_hglobal(void)
490{
491 static const char teststring[] = "this is a test string";
492 HRESULT hr;
493 IStream *pStream;
494 HGLOBAL hglobal;
495 char *p;
496 char buffer[sizeof(teststring) + 8];
497 ULARGE_INTEGER ull;
498 ULONG read, written;
499
500 hglobal = GlobalAlloc(GMEM_DDESHARE|GMEM_NODISCARD|GMEM_MOVEABLE, strlen(teststring) + 1);
501 ok(hglobal != NULL, "GlobalAlloc failed with error %ld\n", GetLastError());
502 p = GlobalLock(hglobal);
503 strcpy(p, teststring);
504 GlobalUnlock(hglobal);
505
506 hr = CreateStreamOnHGlobal(hglobal, FALSE, &pStream);
507 ok_ole_success(hr, "CreateStreamOnHGlobal");
508
509 hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
510 ok_ole_success(hr, "IStream_Read");
511 ok(!strcmp(buffer, teststring), "buffer data %s differs\n", buffer);
512 ok(read == sizeof(teststring) ||
513 broken(read == ((sizeof(teststring) + 3) & ~3)), /* win9x rounds the size */
514 "read should be sizeof(teststring) instead of %ld\n", read);
515
516 GlobalFree(hglobal);
517
518 memset(buffer, 0, sizeof(buffer));
519 read = -1;
520 hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
521 ok_ole_success(hr, "IStream_Read");
522 ok(buffer[0] == 0, "buffer data should be untouched\n");
523 ok(read == 0, "read should be 0 instead of %ld\n", read);
524
525 ull.QuadPart = sizeof(buffer);
526 hr = IStream_SetSize(pStream, ull);
527 ok(hr == E_OUTOFMEMORY, "IStream_SetSize with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08lx\n", hr);
528
529 hr = IStream_Write(pStream, buffer, sizeof(buffer), &written);
530 ok(hr == E_OUTOFMEMORY, "IStream_Write with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08lx\n", hr);
531 ok(written == 0, "written should be 0 instead of %ld\n", written);
532
533 IStream_Release(pStream);
534}
535
536static void stream_info(IStream *stream, HGLOBAL *hmem, int *size, int *pos)
537{
538 HRESULT hr;
539 STATSTG stat;
541 ULARGE_INTEGER newpos;
542
543 *hmem = 0;
544 *size = *pos = -1;
545
547 ok(hr == S_OK, "unexpected %#lx\n", hr);
548
549 memset(&stat, 0x55, sizeof(stat));
550 hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT);
551 ok(hr == S_OK, "unexpected %#lx\n", hr);
552 ok(stat.type == STGTY_STREAM, "unexpected %#lx\n", stat.type);
553 ok(!stat.pwcsName, "unexpected %p\n", stat.pwcsName);
554 ok(IsEqualIID(&stat.clsid, &GUID_NULL), "unexpected %s\n", wine_dbgstr_guid(&stat.clsid));
555 ok(!stat.cbSize.HighPart, "unexpected %#lx\n", stat.cbSize.HighPart);
556 *size = stat.cbSize.LowPart;
557
558 offset.QuadPart = 0;
559 hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, &newpos);
560 ok(hr == S_OK, "unexpected %#lx\n", hr);
561 ok(!newpos.HighPart, "unexpected %#lx\n", newpos.HighPart);
562 *pos = newpos.LowPart;
563}
564
565static void test_IStream_Clone(void)
566{
567 static const char hello[] = "Hello World!";
568 char buf[32];
569 HRESULT hr;
570 IStream *stream, *clone;
571 HGLOBAL orig_hmem, hmem, hmem_clone;
572 ULARGE_INTEGER newsize;
574 int size, pos, ret;
575
576 /* test simple case for Clone */
577 orig_hmem = GlobalAlloc(GMEM_MOVEABLE, 0);
578 ok(orig_hmem != 0, "unexpected %p\n", orig_hmem);
579 hr = CreateStreamOnHGlobal(orig_hmem, TRUE, &stream);
580 ok(hr == S_OK, "unexpected %#lx\n", hr);
581
583 ok(hr == E_INVALIDARG, "unexpected %#lx\n", hr);
584
585 hr = GetHGlobalFromStream(NULL, &hmem);
586 ok(hr == E_INVALIDARG, "unexpected %#lx\n", hr);
587
588 stream_info(stream, &hmem, &size, &pos);
589 ok(hmem == orig_hmem, "handles should match\n");
590 ok(size == 0, "unexpected %d\n", size);
591 ok(pos == 0, "unexpected %d\n", pos);
592
593 hr = IStream_Clone(stream, &clone);
594 ok(hr == S_OK, "unexpected %#lx\n", hr);
595
596 hr = IStream_Write(stream, hello, sizeof(hello), NULL);
597 ok(hr == S_OK, "unexpected %#lx\n", hr);
598
599 stream_info(stream, &hmem, &size, &pos);
600 ok(hmem == orig_hmem, "handles should match\n");
601 ok(size == 13, "unexpected %d\n", size);
602 ok(pos == 13, "unexpected %d\n", pos);
603
604 stream_info(clone, &hmem_clone, &size, &pos);
605 ok(hmem_clone == hmem, "handles should match\n");
606 ok(size == 13, "unexpected %d\n", size);
607 ok(pos == 0, "unexpected %d\n", pos);
608
609 buf[0] = 0;
610 hr = IStream_Read(clone, buf, sizeof(buf), NULL);
611 ok(hr == S_OK, "unexpected %#lx\n", hr);
612 ok(!strcmp(buf, hello), "wrong stream contents\n");
613
614 newsize.QuadPart = 0x8000;
615 hr = IStream_SetSize(stream, newsize);
616 ok(hr == S_OK, "unexpected %#lx\n", hr);
617
618 stream_info(stream, &hmem, &size, &pos);
619 ok(hmem == orig_hmem, "handles should match\n");
620 ok(size == 0x8000, "unexpected %#x\n", size);
621 ok(pos == 13, "unexpected %d\n", pos);
622
623 stream_info(clone, &hmem_clone, &size, &pos);
624 ok(hmem_clone == hmem, "handles should match\n");
625 ok(size == 0x8000, "unexpected %#x\n", size);
626 ok(pos == 13, "unexpected %d\n", pos);
627
628 IStream_Release(clone);
629 IStream_Release(stream);
630
631 /* exploit GMEM_FIXED forced move for the same base streams */
632 orig_hmem = GlobalAlloc(GMEM_FIXED, 1);
633 ok(orig_hmem != 0, "unexpected %p\n", orig_hmem);
634 hr = CreateStreamOnHGlobal(orig_hmem, TRUE, &stream);
635 ok(hr == S_OK, "unexpected %#lx\n", hr);
636
637 hr = IStream_Clone(stream, &clone);
638 ok(hr == S_OK, "unexpected %#lx\n", hr);
639
640 stream_info(stream, &hmem, &size, &pos);
641 ok(hmem == orig_hmem, "handles should match\n");
642 ok(size == 1, "unexpected %d\n", size);
643 ok(pos == 0, "unexpected %d\n", pos);
644
645 stream_info(clone, &hmem_clone, &size, &pos);
646 ok(hmem_clone == hmem, "handles should match\n");
647 ok(size == 1, "unexpected %d\n", size);
648 ok(pos == 0, "unexpected %d\n", pos);
649
650 newsize.QuadPart = 0x8000;
651 hr = IStream_SetSize(stream, newsize);
652 ok(hr == S_OK, "unexpected %#lx\n", hr);
653
654 stream_info(stream, &hmem, &size, &pos);
655 ok(hmem != 0, "unexpected %p\n", hmem);
656 ok(hmem != orig_hmem, "unexpected %p\n", hmem);
657 ok(size == 0x8000, "unexpected %#x\n", size);
658 ok(pos == 0, "unexpected %d\n", pos);
659
660 stream_info(clone, &hmem_clone, &size, &pos);
661 ok(hmem_clone == hmem, "handles should match\n");
662 ok(size == 0x8000, "unexpected %#x\n", size);
663 ok(pos == 0, "unexpected %d\n", pos);
664
665 IStream_Release(stream);
666 IStream_Release(clone);
667
668 /* test Release of cloned stream */
670 ok(hr == S_OK, "unexpected %#lx\n", hr);
671
672 hr = IStream_Clone(stream, &clone);
673 ok(hr == S_OK, "unexpected %#lx\n", hr);
674
675 stream_info(stream, &hmem, &size, &pos);
676 ok(hmem != 0, "unexpected %p\n", hmem);
677 ok(size == 0, "unexpected %d\n", size);
678 ok(pos == 0, "unexpected %d\n", pos);
679
680 stream_info(clone, &hmem_clone, &size, &pos);
681 ok(hmem_clone == hmem, "handles should match\n");
682 ok(size == 0, "unexpected %#x\n", size);
683 ok(pos == 0, "unexpected %d\n", pos);
684
685 ret = IStream_Release(stream);
686 ok(ret == 0, "unexpected %d\n", ret);
687
688 newsize.QuadPart = 0x8000;
689 hr = IStream_SetSize(clone, newsize);
690 ok(hr == S_OK, "unexpected %#lx\n", hr);
691
692 stream_info(clone, &hmem_clone, &size, &pos);
693 ok(hmem_clone == hmem, "handles should match\n");
694 ok(size == 0x8000, "unexpected %#x\n", size);
695 ok(pos == 0, "unexpected %d\n", pos);
696
697 hr = IStream_Write(clone, hello, sizeof(hello), NULL);
698 ok(hr == S_OK, "unexpected %#lx\n", hr);
699
700 stream_info(clone, &hmem_clone, &size, &pos);
701 ok(hmem_clone == hmem, "handles should match\n");
702 ok(size == 0x8000, "unexpected %#x\n", size);
703 ok(pos == 13, "unexpected %d\n", pos);
704
705 offset.QuadPart = 0;
706 hr = IStream_Seek(clone, offset, STREAM_SEEK_SET, NULL);
707 ok(hr == S_OK, "unexpected %#lx\n", hr);
708
709 buf[0] = 0;
710 hr = IStream_Read(clone, buf, sizeof(buf), NULL);
711 ok(hr == S_OK, "unexpected %#lx\n", hr);
712 ok(!strcmp(buf, hello), "wrong stream contents\n");
713
714 stream_info(clone, &hmem_clone, &size, &pos);
715 ok(hmem_clone == hmem, "handles should match\n");
716 ok(size == 0x8000, "unexpected %#x\n", size);
717 ok(pos == 32, "unexpected %d\n", pos);
718
719 ret = IStream_Release(clone);
720 ok(ret == 0, "unexpected %d\n", ret);
721}
722
723START_TEST(hglobalstream)
724{
726 test_copyto();
729}
#define stat
Definition: acwin.h:99
#define read
Definition: acwin.h:96
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
const GUID IID_IUnknown
w ll
Definition: byte_order.h:167
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI GetHGlobalFromStream(IStream *stream, HGLOBAL *phglobal)
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL delete_on_release, IStream **stream)
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
Definition: ctx.idl:7
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
#define GUID_NULL
Definition: ks.h:106
static HRESULT WINAPI TestStream_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead)
static HRESULT WINAPI TestStream_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
static HRESULT WINAPI TestStream_Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
static void test_IStream_Clone(void)
static HRESULT WINAPI TestStream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
static void test_copyto(void)
static HRESULT WINAPI TestStream_CopyTo(IStream *iface, IStream *pStream, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
static HRESULT WINAPI TestStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
#define ok_ole_success(hr, func)
Definition: hglobalstream.c:32
static HRESULT WINAPI TestStream_Revert(IStream *iface)
static char const *const * expected_method_list
Definition: hglobalstream.c:34
static IStreamVtbl StreamVtbl
#define CHECK_EXPECTED_METHOD(method_name)
Definition: hglobalstream.c:36
static HRESULT WINAPI TestStream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten)
static HRESULT WINAPI TestStream_Commit(IStream *iface, DWORD grfCommitFlags)
static void test_streamonhglobal(void)
Definition: hglobalstream.c:47
static HRESULT WINAPI TestStream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
static void stream_info(IStream *stream, HGLOBAL *hmem, int *size, int *pos)
static ULONG WINAPI TestStream_Release(IStream *iface)
static HRESULT WINAPI TestStream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
static HRESULT WINAPI TestStream_Clone(IStream *iface, IStream **pStream)
static ULONG WINAPI TestStream_AddRef(IStream *iface)
static void test_freed_hglobal(void)
static IStream Test_Stream
static const LARGE_INTEGER llZero
Definition: moniker.c:1425
#define DWORD
Definition: nt_native.h:44
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
strcpy
Definition: string.h:131
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:206
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:582
struct _ULARGE_INTEGER::@4458 u
Definition: stat.h:66
Definition: parse.h:23
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define GMEM_FIXED
Definition: winbase.h:317
#define GMEM_NODISCARD
Definition: winbase.h:326
#define GMEM_MOVEABLE
Definition: winbase.h:318
#define GMEM_DDESHARE
Definition: winbase.h:322
#define WINAPI
Definition: msvc.h:6
#define STG_E_SEEKERROR
Definition: winerror.h:3669
#define E_NOINTERFACE
Definition: winerror.h:3479
#define STG_E_INVALIDFUNCTION
Definition: winerror.h:3659