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