[SHLWAPI_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / winetests / shlwapi / istream.c
1 /* Unit test suite for SHLWAPI ShCreateStreamOnFile functions.
2 *
3 * Copyright 2008 Reece H. Dunn
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #define WIN32_NO_STATUS
21 #define _INC_WINDOWS
22 #define COM_NO_WINDOWS_H
23
24 #define COBJMACROS
25
26 //#include <stdarg.h>
27 //#include <stdio.h>
28
29 #include <wine/test.h>
30 //#include "windef.h"
31 //#include "winbase.h"
32 #include <winnls.h>
33 #include <winreg.h>
34 #include <objbase.h>
35 #include <shlwapi.h>
36
37 static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
38 {
39 HRESULT ret;
40 IStream * clone;
41 ULONG refcount;
42 ULARGE_INTEGER uzero;
43 ULARGE_INTEGER uret;
44 LARGE_INTEGER zero;
45 ULONG count;
46 char data[256];
47
48 U(uzero).HighPart = 0;
49 U(uzero).LowPart = 0;
50 U(uret).HighPart = 0;
51 U(uret).LowPart = 0;
52 U(zero).HighPart = 0;
53 U(zero).LowPart = 0;
54
55 /* IStream::Read */
56
57 /* IStream_Read from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Read helper function. */
58
59 ret = stream->lpVtbl->Read(stream, NULL, 0, &count);
60 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
61
62 ret = stream->lpVtbl->Read(stream, data, 5, NULL);
63 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
64
65 ret = stream->lpVtbl->Read(stream, data, 0, NULL);
66 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
67
68 ret = stream->lpVtbl->Read(stream, data, 3, &count);
69 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
70
71 /* IStream::Write */
72
73 /* IStream_Write from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Write helper function. */
74
75 ret = stream->lpVtbl->Write(stream, NULL, 0, &count);
76 if (mode == STGM_READ)
77 {
78 ok(ret == STG_E_ACCESSDENIED /* XP */ || broken(ret == S_OK) /* Win2000 + IE5 */,
79 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
80 }
81 else
82 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
83
84 strcpy(data, "Hello");
85 ret = stream->lpVtbl->Write(stream, data, 5, NULL);
86 if (mode == STGM_READ)
87 ok(ret == STG_E_ACCESSDENIED,
88 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
89 else
90 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
91
92 strcpy(data, "Hello");
93 ret = stream->lpVtbl->Write(stream, data, 0, NULL);
94 if (mode == STGM_READ)
95 ok(ret == STG_E_ACCESSDENIED,
96 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
97 else
98 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
99
100 strcpy(data, "Hello");
101 ret = stream->lpVtbl->Write(stream, data, 0, &count);
102 if (mode == STGM_READ)
103 ok(ret == STG_E_ACCESSDENIED,
104 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
105 else
106 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
107
108 strcpy(data, "Hello");
109 ret = stream->lpVtbl->Write(stream, data, 3, &count);
110 if (mode == STGM_READ)
111 ok(ret == STG_E_ACCESSDENIED,
112 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
113 else
114 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
115
116 /* IStream::Seek */
117
118 ret = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
119 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
120
121 ret = IStream_Seek(stream, zero, 20, NULL);
122 ok(ret == E_INVALIDARG,
123 "expected E_INVALIDARG, got 0x%08x\n", ret);
124
125 /* IStream::CopyTo */
126
127 ret = IStream_CopyTo(stream, NULL, uzero, &uret, &uret);
128 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
129
130 clone = NULL;
131 ret = IStream_CopyTo(stream, clone, uzero, &uret, &uret);
132 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
133
134 ret = IStream_CopyTo(stream, stream, uzero, &uret, &uret);
135 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
136
137 ret = IStream_CopyTo(stream, stream, uzero, &uret, NULL);
138 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
139
140 ret = IStream_CopyTo(stream, stream, uzero, NULL, &uret);
141 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
142
143 /* IStream::Commit */
144
145 ret = IStream_Commit(stream, STGC_DEFAULT);
146 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
147
148 /* IStream::Revert */
149
150 ret = IStream_Revert(stream);
151 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
152
153 /* IStream::LockRegion */
154
155 ret = IStream_LockRegion(stream, uzero, uzero, 0);
156 ok(ret == E_NOTIMPL /* XP */ || ret == S_OK /* Vista */,
157 "expected E_NOTIMPL or S_OK, got 0x%08x\n", ret);
158
159 /* IStream::UnlockRegion */
160
161 if (ret == E_NOTIMPL) /* XP */ {
162 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
163 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
164 } else /* Vista */ {
165 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
166 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
167
168 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
169 ok(ret == STG_E_LOCKVIOLATION, "expected STG_E_LOCKVIOLATION, got 0x%08x\n", ret);
170 }
171
172 /* IStream::Stat */
173
174 ret = IStream_Stat(stream, NULL, 0);
175 ok(ret == STG_E_INVALIDPOINTER,
176 "expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret);
177
178 /* IStream::Clone */
179
180 /* Passing a NULL pointer for the second IStream::Clone param crashes on Win7 */
181
182 clone = NULL;
183 ret = IStream_Clone(stream, &clone);
184 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
185 ok(clone == NULL, "expected a NULL IStream object, got %p\n", stream);
186
187 if (clone) {
188 refcount = IStream_Release(clone);
189 ok(refcount == 0, "expected 0, got %d\n", refcount);
190 }
191 }
192
193
194 static void test_stream_read_write(IStream *stream, DWORD mode)
195 {
196 static const LARGE_INTEGER start;
197 HRESULT ret;
198 unsigned char buf[16];
199 DWORD written, count;
200
201 /* IStream_Read/Write from the COBJMACROS is undefined by shlwapi.h */
202
203 written = 0xdeadbeaf;
204 ret = stream->lpVtbl->Write(stream, "\x5e\xa7", 2, &written);
205 if (mode == STGM_WRITE || mode == STGM_READWRITE)
206 {
207 ok(ret == S_OK, "IStream_Write error %#x (access %#x)\n", ret, mode);
208 ok(written == 2, "expected 2, got %u\n", written);
209 }
210 else
211 {
212 ok(ret == STG_E_ACCESSDENIED || broken(ret == S_OK) /* win2000 */, "expected STG_E_ACCESSDENIED, got %#x (access %#x)\n", ret, mode);
213 ok(written == 0xdeadbeaf || broken(written == 2) /* win2000 */, "expected 0xdeadbeaf, got %#x\n", written);
214 written = 0;
215 if (ret == S_OK) return; /* no point in further testing */
216 }
217
218 ret = stream->lpVtbl->Seek(stream, start, STREAM_SEEK_SET, NULL);
219 ok(ret == S_OK, "Seek error %#x\n", ret);
220
221 count = 0xdeadbeaf;
222 ret = stream->lpVtbl->Read(stream, buf, 2, &count);
223 if (written != 0)
224 {
225 ok(ret == S_OK || broken(ret == S_FALSE) /* win2000 */, "IStream_Read error %#x (access %#x, written %u)\n", ret, mode, written);
226 if (ret == S_OK && (mode == STGM_WRITE || mode == STGM_READWRITE))
227 {
228 ok(count == 2, "expected 2, got %u\n", count);
229 ok(buf[0] == 0x5e && buf[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf[0], buf[1]);
230 }
231 else
232 ok(count == 0, "expected 0, got %u\n", count);
233 }
234 else
235 {
236 ok(ret == S_FALSE, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret, mode, written);
237 ok(count == 0, "expected 0, got %u\n", count);
238 }
239
240 ret = stream->lpVtbl->Seek(stream, start, STREAM_SEEK_SET, NULL);
241 ok(ret == S_OK, "Seek error %#x\n", ret);
242
243 count = 0xdeadbeaf;
244 ret = stream->lpVtbl->Read(stream, buf, 0, &count);
245 ok(ret == S_OK, "IStream_Read error %#x (access %#x, written %u)\n", ret, mode, written);
246 ok(count == 0, "expected 0, got %u\n", count);
247
248 count = 0xdeadbeaf;
249 ret = stream->lpVtbl->Read(stream, buf, sizeof(buf), &count);
250 ok(ret == S_FALSE, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret, mode, written);
251 ok(count == written, "expected %u, got %u\n", written, count);
252 if (count)
253 ok(buf[0] == 0x5e && buf[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf[0], buf[1]);
254 }
255
256 static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm)
257 {
258 IStream * stream;
259 HRESULT ret;
260 ULONG refcount;
261 char test_file[MAX_PATH];
262 static const CHAR testA_txt[] = "\\testA.txt";
263
264 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode, stgm);
265
266 /* Don't used a fixed path for the testA.txt file */
267 GetTempPathA(MAX_PATH, test_file);
268 lstrcatA(test_file, testA_txt);
269
270 /* invalid arguments */
271
272 stream = NULL;
273 ret = SHCreateStreamOnFileA(NULL, mode | stgm, &stream);
274 if (ret == E_INVALIDARG) /* Win98 SE */ {
275 win_skip("Not supported\n");
276 return;
277 }
278
279 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) /* NT */ ||
280 ret == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME) /* 9x */,
281 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) "
282 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret);
283 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
284
285 if (0) /* This test crashes on WinXP SP2 */
286 {
287 ret = SHCreateStreamOnFileA(test_file, mode | stgm, NULL);
288 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
289 }
290
291 stream = NULL;
292 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CONVERT | stgm, &stream);
293 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
294 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
295
296 stream = NULL;
297 ret = SHCreateStreamOnFileA(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
298 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
299 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
300
301 stream = NULL;
302 ret = SHCreateStreamOnFileA(test_file, mode | STGM_TRANSACTED | stgm, &stream);
303 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
304 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
305
306 /* file does not exist */
307
308 stream = NULL;
309 ret = SHCreateStreamOnFileA(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
310 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
311 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
312
313 stream = NULL;
314 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CREATE | stgm, &stream);
315 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
316 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
317
318 if (stream) {
319 test_IStream_invalid_operations(stream, mode);
320
321 refcount = IStream_Release(stream);
322 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
323 }
324
325 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
326
327 /* file exists */
328
329 stream = NULL;
330 ret = SHCreateStreamOnFileA(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
331 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
332 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
333
334 if (stream) {
335 test_IStream_invalid_operations(stream, mode);
336
337 refcount = IStream_Release(stream);
338 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
339 }
340
341 stream = NULL;
342 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CREATE | stgm, &stream);
343 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
344 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
345
346 if (stream) {
347 BOOL delret;
348
349 test_stream_read_write(stream, mode);
350 test_IStream_invalid_operations(stream, mode);
351
352 refcount = IStream_Release(stream);
353 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
354
355 delret = DeleteFileA(test_file);
356 ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
357 test_file, GetLastError());
358 }
359 }
360
361
362 static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm)
363 {
364 IStream * stream;
365 HRESULT ret;
366 ULONG refcount;
367 WCHAR test_file[MAX_PATH];
368 CHAR test_fileA[MAX_PATH];
369 static const CHAR testW_txt[] = "\\testW.txt";
370
371 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode, stgm);
372
373 /* Don't used a fixed path for the testW.txt file */
374 GetTempPathA(MAX_PATH, test_fileA);
375 lstrcatA(test_fileA, testW_txt);
376 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
377
378 /* invalid arguments */
379
380 if (0)
381 {
382 /* Crashes on NT4 */
383 stream = NULL;
384 ret = SHCreateStreamOnFileW(NULL, mode | stgm, &stream);
385 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
386 ret == E_INVALIDARG /* Vista */,
387 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
388 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
389 }
390
391 if (0)
392 {
393 /* This test crashes on WinXP SP2 */
394 ret = SHCreateStreamOnFileW(test_file, mode | stgm, NULL);
395 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
396 }
397
398 stream = NULL;
399 ret = SHCreateStreamOnFileW(test_file, mode | STGM_CONVERT | stgm, &stream);
400 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
401 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
402
403 stream = NULL;
404 ret = SHCreateStreamOnFileW(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
405 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
406 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
407
408 stream = NULL;
409 ret = SHCreateStreamOnFileW(test_file, mode | STGM_TRANSACTED | stgm, &stream);
410 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
411 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
412
413 /* file does not exist */
414
415 stream = NULL;
416 ret = SHCreateStreamOnFileW(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
417 if (ret == E_INVALIDARG) /* Win98 SE */ {
418 win_skip("Not supported\n");
419 return;
420 }
421
422 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
423 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
424
425 stream = NULL;
426 ret = SHCreateStreamOnFileW(test_file, mode | STGM_CREATE | stgm, &stream);
427 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
428 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
429
430 if (stream) {
431 test_IStream_invalid_operations(stream, mode);
432
433 refcount = IStream_Release(stream);
434 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
435 }
436
437 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
438
439 /* file exists */
440
441 stream = NULL;
442 ret = SHCreateStreamOnFileW(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
443 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
444 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
445
446 if (stream) {
447 test_IStream_invalid_operations(stream, mode);
448
449 refcount = IStream_Release(stream);
450 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
451 }
452
453 stream = NULL;
454 ret = SHCreateStreamOnFileW(test_file, mode | STGM_CREATE | stgm, &stream);
455 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
456 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
457
458 if (stream) {
459 BOOL delret;
460
461 test_stream_read_write(stream, mode);
462 test_IStream_invalid_operations(stream, mode);
463
464 refcount = IStream_Release(stream);
465 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
466
467 delret = DeleteFileA(test_fileA);
468 ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
469 GetLastError());
470 }
471 }
472
473
474 static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
475 {
476 IStream * stream;
477 IStream * template = NULL;
478 HRESULT ret;
479 ULONG refcount;
480 WCHAR test_file[MAX_PATH];
481 CHAR test_fileA[MAX_PATH];
482 static const CHAR testEx_txt[] = "\\testEx.txt";
483 BOOL delret;
484
485 if (winetest_debug > 1)
486 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
487
488 /* Don't used a fixed path for the testEx.txt file */
489 GetTempPathA(MAX_PATH, test_fileA);
490 lstrcatA(test_fileA, testEx_txt);
491 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
492
493 /* invalid arguments */
494
495 if (0)
496 {
497 /* Crashes on NT4 */
498 stream = NULL;
499 ret = SHCreateStreamOnFileEx(NULL, mode, 0, FALSE, NULL, &stream);
500 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
501 ret == E_INVALIDARG /* Vista */,
502 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
503 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
504 }
505
506 stream = NULL;
507 ret = SHCreateStreamOnFileEx(test_file, mode, 0, FALSE, template, &stream);
508 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
509 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
510 Sleep(1000);
511 ret = SHCreateStreamOnFileEx(test_file, mode, 0, FALSE, template, &stream);
512 }
513 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
514 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
515 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
516 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
517
518 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
519
520 if (0)
521 {
522 /* This test crashes on WinXP SP2 */
523 ret = SHCreateStreamOnFileEx(test_file, mode, 0, FALSE, NULL, NULL);
524 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret);
525 }
526
527 /* file does not exist */
528
529 stream = NULL;
530 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
531 if ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED && mode == STGM_READ) {
532 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* XP */ || ret == E_INVALIDARG /* Vista */,
533 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
534
535 if (ret == E_INVALIDARG) {
536 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
537 return;
538 }
539 } else {
540 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
541 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
542 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
543 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
544 }
545 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
546
547 stream = NULL;
548 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
549 /* not supported on win9x */
550 if (broken(ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) && stream == NULL)) {
551 skip("Not supported\n");
552 DeleteFileA(test_fileA);
553 return;
554 }
555
556 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
557 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
558
559 if (stream) {
560 test_IStream_invalid_operations(stream, mode);
561
562 refcount = IStream_Release(stream);
563 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
564
565 delret = DeleteFileA(test_fileA);
566 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
567 GetLastError());
568 }
569
570 stream = NULL;
571 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
572 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
573 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
574 Sleep(1000);
575 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
576 }
577 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
578 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
579
580 if (stream) {
581 test_IStream_invalid_operations(stream, mode);
582
583 refcount = IStream_Release(stream);
584 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
585
586 delret = DeleteFileA(test_fileA);
587 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
588 GetLastError());
589 }
590
591 stream = NULL;
592 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
593 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
594 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
595 Sleep(1000);
596 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
597 }
598 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
599 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
600
601 if (stream) {
602 test_IStream_invalid_operations(stream, mode);
603
604 refcount = IStream_Release(stream);
605 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
606 }
607
608 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
609
610 /* file exists */
611
612 stream = NULL;
613 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
614 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
615 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
616
617 if (stream) {
618 test_IStream_invalid_operations(stream, mode);
619
620 refcount = IStream_Release(stream);
621 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
622 }
623
624 stream = NULL;
625 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
626 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret);
627 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
628
629 stream = NULL;
630 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
631 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
632 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
633
634 if (stream) {
635 test_IStream_invalid_operations(stream, mode);
636
637 refcount = IStream_Release(stream);
638 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
639 }
640
641 stream = NULL;
642 ret = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
643 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
644 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
645
646 if (stream) {
647 test_IStream_invalid_operations(stream, mode);
648
649 refcount = IStream_Release(stream);
650 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
651 }
652
653 delret = DeleteFileA(test_fileA);
654 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
655 GetLastError());
656 }
657
658
659 static void test_SHCreateStreamOnFileEx_CopyTo(void)
660 {
661 HRESULT ret;
662 IStream *src, *dst;
663 WCHAR tmpPath[MAX_PATH];
664 WCHAR srcFileName[MAX_PATH];
665 WCHAR dstFileName[MAX_PATH];
666 ULARGE_INTEGER count, read, written;
667 LARGE_INTEGER distance;
668 static const char srcContents[1];
669 static const WCHAR prefix[] = { 'T', 'S', 'T', 0 };
670
671 GetTempPathW(MAX_PATH, tmpPath);
672 GetTempFileNameW(tmpPath, prefix, 0, srcFileName);
673 GetTempFileNameW(tmpPath, prefix, 0, dstFileName);
674
675 ret = SHCreateStreamOnFileEx(srcFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &src);
676 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
677
678 written.QuadPart = 0;
679 ret = IStream_Write(src, srcContents, sizeof(srcContents), &U(written).LowPart);
680 ok(SUCCEEDED(ret), "ISequentialStream_Write failed with ret=0x%08x\n", ret);
681
682 distance.QuadPart = 0;
683 ret = IStream_Seek(src, distance, STREAM_SEEK_SET, &written);
684 ok(SUCCEEDED(ret), "ISequentialStream_Seek failed with ret=0x%08x\n", ret);
685
686 ret = SHCreateStreamOnFileEx(dstFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &dst);
687 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
688
689 /* Test using a count larger than the source file, so that the Read operation will fall short */
690 count.QuadPart = 2;
691
692 ret = IStream_CopyTo(src, dst, count, &read, &written);
693 ok(SUCCEEDED(ret), "CopyTo failed with ret=0x%08x\n", ret);
694
695 ok(read.QuadPart == 1, "read does not match size: %d != 1\n", U(read).LowPart);
696 ok(written.QuadPart == 1, "written does not match size: %d != 1\n", U(written).LowPart);
697
698 IStream_Release(dst);
699 IStream_Release(src);
700 DeleteFileW( srcFileName );
701 DeleteFileW( dstFileName );
702 }
703
704
705 START_TEST(istream)
706 {
707 static const DWORD stgm_access[] = {
708 STGM_READ,
709 STGM_WRITE,
710 STGM_READWRITE
711 };
712
713 static const DWORD stgm_sharing[] = {
714 0,
715 STGM_SHARE_DENY_NONE,
716 STGM_SHARE_DENY_READ,
717 STGM_SHARE_DENY_WRITE,
718 STGM_SHARE_EXCLUSIVE
719 };
720
721 static const DWORD stgm_flags[] = {
722 0,
723 STGM_CONVERT,
724 STGM_DELETEONRELEASE,
725 STGM_CONVERT | STGM_DELETEONRELEASE,
726 STGM_TRANSACTED | STGM_CONVERT,
727 STGM_TRANSACTED | STGM_DELETEONRELEASE,
728 STGM_TRANSACTED | STGM_CONVERT | STGM_DELETEONRELEASE
729 };
730
731 int i, j, k;
732
733 for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) {
734 for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) {
735 test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]);
736 test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]);
737
738 for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++)
739 test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]);
740 }
741 }
742
743 test_SHCreateStreamOnFileEx_CopyTo();
744 }