1 /* Unit test suite for SHLWAPI ShCreateStreamOnFile functions.
3 * Copyright 2008 Reece H. Dunn
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/test.h"
31 static void test_IStream_invalid_operations(IStream
* stream
, DWORD mode
)
42 U(uzero
).HighPart
= 0;
51 /* IStream_Read from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Read helper function. */
53 ret
= stream
->lpVtbl
->Read(stream
, NULL
, 0, &count
);
54 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
56 ret
= stream
->lpVtbl
->Read(stream
, data
, 5, NULL
);
57 ok(ret
== S_FALSE
|| ret
== S_OK
, "expected S_FALSE or S_OK, got 0x%08x\n", ret
);
59 ret
= stream
->lpVtbl
->Read(stream
, data
, 0, NULL
);
60 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
62 ret
= stream
->lpVtbl
->Read(stream
, data
, 3, &count
);
63 ok(ret
== S_FALSE
|| ret
== S_OK
, "expected S_FALSE or S_OK, got 0x%08x\n", ret
);
67 /* IStream_Write from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Write helper function. */
69 ret
= stream
->lpVtbl
->Write(stream
, NULL
, 0, &count
);
70 if (mode
== STGM_READ
)
72 ok(ret
== STG_E_ACCESSDENIED
/* XP */ || broken(ret
== S_OK
) /* Win2000 + IE5 */,
73 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret
);
76 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
78 strcpy(data
, "Hello");
79 ret
= stream
->lpVtbl
->Write(stream
, data
, 5, NULL
);
80 if (mode
== STGM_READ
)
81 ok(ret
== STG_E_ACCESSDENIED
,
82 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret
);
84 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
86 strcpy(data
, "Hello");
87 ret
= stream
->lpVtbl
->Write(stream
, data
, 0, NULL
);
88 if (mode
== STGM_READ
)
89 ok(ret
== STG_E_ACCESSDENIED
,
90 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret
);
92 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
94 strcpy(data
, "Hello");
95 ret
= stream
->lpVtbl
->Write(stream
, data
, 0, &count
);
96 if (mode
== STGM_READ
)
97 ok(ret
== STG_E_ACCESSDENIED
,
98 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret
);
100 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
102 strcpy(data
, "Hello");
103 ret
= stream
->lpVtbl
->Write(stream
, data
, 3, &count
);
104 if (mode
== STGM_READ
)
105 ok(ret
== STG_E_ACCESSDENIED
,
106 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret
);
108 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
112 ret
= IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
113 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
115 ret
= IStream_Seek(stream
, zero
, 20, NULL
);
116 ok(ret
== E_INVALIDARG
,
117 "expected E_INVALIDARG, got 0x%08x\n", ret
);
119 /* IStream::CopyTo */
121 ret
= IStream_CopyTo(stream
, NULL
, uzero
, &uret
, &uret
);
122 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
125 ret
= IStream_CopyTo(stream
, clone
, uzero
, &uret
, &uret
);
126 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
128 ret
= IStream_CopyTo(stream
, stream
, uzero
, &uret
, &uret
);
129 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
131 ret
= IStream_CopyTo(stream
, stream
, uzero
, &uret
, NULL
);
132 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
134 ret
= IStream_CopyTo(stream
, stream
, uzero
, NULL
, &uret
);
135 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
137 /* IStream::Commit */
139 ret
= IStream_Commit(stream
, STGC_DEFAULT
);
140 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
142 /* IStream::Revert */
144 ret
= IStream_Revert(stream
);
145 ok(ret
== E_NOTIMPL
, "expected E_NOTIMPL, got 0x%08x\n", ret
);
147 /* IStream::LockRegion */
149 ret
= IStream_LockRegion(stream
, uzero
, uzero
, 0);
150 ok(ret
== E_NOTIMPL
/* XP */ || ret
== S_OK
/* Vista */,
151 "expected E_NOTIMPL or S_OK, got 0x%08x\n", ret
);
153 /* IStream::UnlockRegion */
155 if (ret
== E_NOTIMPL
) /* XP */ {
156 ret
= IStream_UnlockRegion(stream
, uzero
, uzero
, 0);
157 ok(ret
== E_NOTIMPL
, "expected E_NOTIMPL, got 0x%08x\n", ret
);
159 ret
= IStream_UnlockRegion(stream
, uzero
, uzero
, 0);
160 ok(ret
== S_OK
, "expected S_OK, got 0x%08x\n", ret
);
162 ret
= IStream_UnlockRegion(stream
, uzero
, uzero
, 0);
163 ok(ret
== STG_E_LOCKVIOLATION
, "expected STG_E_LOCKVIOLATION, got 0x%08x\n", ret
);
168 ret
= IStream_Stat(stream
, NULL
, 0);
169 ok(ret
== STG_E_INVALIDPOINTER
,
170 "expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret
);
174 /* Passing a NULL pointer for the second IStream::Clone param crashes on Win7 */
177 ret
= IStream_Clone(stream
, &clone
);
178 ok(ret
== E_NOTIMPL
, "expected E_NOTIMPL, got 0x%08x\n", ret
);
179 ok(clone
== NULL
, "expected a NULL IStream object, got %p\n", stream
);
182 refcount
= IStream_Release(clone
);
183 ok(refcount
== 0, "expected 0, got %d\n", refcount
);
188 static void test_stream_read_write(IStream
*stream
, DWORD mode
)
190 static const LARGE_INTEGER start
;
192 unsigned char buf
[16];
193 DWORD written
, count
;
195 /* IStream_Read/Write from the COBJMACROS is undefined by shlwapi.h */
197 written
= 0xdeadbeaf;
198 ret
= stream
->lpVtbl
->Write(stream
, "\x5e\xa7", 2, &written
);
199 if (mode
== STGM_WRITE
|| mode
== STGM_READWRITE
)
201 ok(ret
== S_OK
, "IStream_Write error %#x (access %#x)\n", ret
, mode
);
202 ok(written
== 2, "expected 2, got %u\n", written
);
206 ok(ret
== STG_E_ACCESSDENIED
|| broken(ret
== S_OK
) /* win2000 */, "expected STG_E_ACCESSDENIED, got %#x (access %#x)\n", ret
, mode
);
207 ok(written
== 0xdeadbeaf || broken(written
== 2) /* win2000 */, "expected 0xdeadbeaf, got %#x\n", written
);
209 if (ret
== S_OK
) return; /* no point in further testing */
212 ret
= stream
->lpVtbl
->Seek(stream
, start
, STREAM_SEEK_SET
, NULL
);
213 ok(ret
== S_OK
, "Seek error %#x\n", ret
);
216 ret
= stream
->lpVtbl
->Read(stream
, buf
, 2, &count
);
219 ok(ret
== S_OK
|| broken(ret
== S_FALSE
) /* win2000 */, "IStream_Read error %#x (access %#x, written %u)\n", ret
, mode
, written
);
220 if (ret
== S_OK
&& (mode
== STGM_WRITE
|| mode
== STGM_READWRITE
))
222 ok(count
== 2, "expected 2, got %u\n", count
);
223 ok(buf
[0] == 0x5e && buf
[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf
[0], buf
[1]);
226 ok(count
== 0, "expected 0, got %u\n", count
);
230 ok(ret
== S_FALSE
, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret
, mode
, written
);
231 ok(count
== 0, "expected 0, got %u\n", count
);
234 ret
= stream
->lpVtbl
->Seek(stream
, start
, STREAM_SEEK_SET
, NULL
);
235 ok(ret
== S_OK
, "Seek error %#x\n", ret
);
238 ret
= stream
->lpVtbl
->Read(stream
, buf
, 0, &count
);
239 ok(ret
== S_OK
, "IStream_Read error %#x (access %#x, written %u)\n", ret
, mode
, written
);
240 ok(count
== 0, "expected 0, got %u\n", count
);
243 ret
= stream
->lpVtbl
->Read(stream
, buf
, sizeof(buf
), &count
);
244 ok(ret
== S_FALSE
, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret
, mode
, written
);
245 ok(count
== written
, "expected %u, got %u\n", written
, count
);
247 ok(buf
[0] == 0x5e && buf
[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf
[0], buf
[1]);
250 static void test_SHCreateStreamOnFileA(DWORD mode
, DWORD stgm
)
255 char test_file
[MAX_PATH
];
256 static const CHAR testA_txt
[] = "\\testA.txt";
258 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode
, stgm
);
260 /* Don't used a fixed path for the testA.txt file */
261 GetTempPathA(MAX_PATH
, test_file
);
262 lstrcatA(test_file
, testA_txt
);
264 /* invalid arguments */
267 ret
= SHCreateStreamOnFileA(NULL
, mode
| stgm
, &stream
);
268 if (ret
== E_INVALIDARG
) /* Win98 SE */ {
269 win_skip("Not supported\n");
273 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) /* NT */ ||
274 ret
== HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME
) /* 9x */,
275 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) "
276 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret
);
277 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
279 if (0) /* This test crashes on WinXP SP2 */
281 ret
= SHCreateStreamOnFileA(test_file
, mode
| stgm
, NULL
);
282 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
286 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CONVERT
| stgm
, &stream
);
287 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
288 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
291 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_DELETEONRELEASE
| stgm
, &stream
);
292 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
293 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
296 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_TRANSACTED
| stgm
, &stream
);
297 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
298 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
300 /* file does not exist */
303 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
304 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
305 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
308 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
309 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
310 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
313 test_IStream_invalid_operations(stream
, mode
);
315 refcount
= IStream_Release(stream
);
316 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
319 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
324 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
325 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
326 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
329 test_IStream_invalid_operations(stream
, mode
);
331 refcount
= IStream_Release(stream
);
332 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
336 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
337 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
338 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
343 test_stream_read_write(stream
, mode
);
344 test_IStream_invalid_operations(stream
, mode
);
346 refcount
= IStream_Release(stream
);
347 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
349 delret
= DeleteFileA(test_file
);
350 ok(delret
, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
351 test_file
, GetLastError());
356 static void test_SHCreateStreamOnFileW(DWORD mode
, DWORD stgm
)
361 WCHAR test_file
[MAX_PATH
];
362 CHAR test_fileA
[MAX_PATH
];
363 static const CHAR testW_txt
[] = "\\testW.txt";
365 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode
, stgm
);
367 /* Don't used a fixed path for the testW.txt file */
368 GetTempPathA(MAX_PATH
, test_fileA
);
369 lstrcatA(test_fileA
, testW_txt
);
370 MultiByteToWideChar(CP_ACP
, 0, test_fileA
, -1, test_file
, MAX_PATH
);
372 /* invalid arguments */
378 ret
= SHCreateStreamOnFileW(NULL
, mode
| stgm
, &stream
);
379 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) || /* XP */
380 ret
== E_INVALIDARG
/* Vista */,
381 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret
);
382 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
387 /* This test crashes on WinXP SP2 */
388 ret
= SHCreateStreamOnFileW(test_file
, mode
| stgm
, NULL
);
389 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
393 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_CONVERT
| stgm
, &stream
);
394 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
395 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
398 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_DELETEONRELEASE
| stgm
, &stream
);
399 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
400 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
403 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_TRANSACTED
| stgm
, &stream
);
404 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
405 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
407 /* file does not exist */
410 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
411 if (ret
== E_INVALIDARG
) /* Win98 SE */ {
412 win_skip("Not supported\n");
416 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
417 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
420 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
421 ok(ret
== S_OK
, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret
);
422 ok(stream
!= NULL
, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
425 test_IStream_invalid_operations(stream
, mode
);
427 refcount
= IStream_Release(stream
);
428 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
431 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
436 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
437 ok(ret
== S_OK
, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret
);
438 ok(stream
!= NULL
, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
441 test_IStream_invalid_operations(stream
, mode
);
443 refcount
= IStream_Release(stream
);
444 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
448 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
449 ok(ret
== S_OK
, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret
);
450 ok(stream
!= NULL
, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
455 test_stream_read_write(stream
, mode
);
456 test_IStream_invalid_operations(stream
, mode
);
458 refcount
= IStream_Release(stream
);
459 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
461 delret
= DeleteFileA(test_fileA
);
462 ok(delret
, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
468 static void test_SHCreateStreamOnFileEx(DWORD mode
, DWORD stgm
)
471 IStream
* template = NULL
;
474 WCHAR test_file
[MAX_PATH
];
475 CHAR test_fileA
[MAX_PATH
];
476 static const CHAR testEx_txt
[] = "\\testEx.txt";
479 if (winetest_debug
> 1)
480 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode
, stgm
);
482 /* Don't used a fixed path for the testEx.txt file */
483 GetTempPathA(MAX_PATH
, test_fileA
);
484 lstrcatA(test_fileA
, testEx_txt
);
485 MultiByteToWideChar(CP_ACP
, 0, test_fileA
, -1, test_file
, MAX_PATH
);
487 /* invalid arguments */
493 ret
= SHCreateStreamOnFileEx(NULL
, mode
, 0, FALSE
, NULL
, &stream
);
494 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) || /* XP */
495 ret
== E_INVALIDARG
/* Vista */,
496 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret
);
497 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
501 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, template, &stream
);
502 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
503 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
505 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, template, &stream
);
507 ok( ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
508 ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
509 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
510 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret
);
512 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
516 /* This test crashes on WinXP SP2 */
517 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, NULL
, NULL
);
518 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret
);
521 /* file does not exist */
524 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, FALSE
, NULL
, &stream
);
525 if ((stgm
& STGM_TRANSACTED
) == STGM_TRANSACTED
&& mode
== STGM_READ
) {
526 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) /* XP */ || ret
== E_INVALIDARG
/* Vista */,
527 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
529 if (ret
== E_INVALIDARG
) {
530 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
534 ok( ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
535 ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
536 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
537 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret
);
539 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
542 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, TRUE
, NULL
, &stream
);
543 /* not supported on win9x */
544 if (broken(ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
) && stream
== NULL
)) {
545 skip("Not supported\n");
546 DeleteFileA(test_fileA
);
550 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
551 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
554 test_IStream_invalid_operations(stream
, mode
);
556 refcount
= IStream_Release(stream
);
557 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
559 delret
= DeleteFileA(test_fileA
);
560 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
565 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
566 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
567 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
569 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
571 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
572 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
575 test_IStream_invalid_operations(stream
, mode
);
577 refcount
= IStream_Release(stream
);
578 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
580 delret
= DeleteFileA(test_fileA
);
581 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
586 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, TRUE
, NULL
, &stream
);
587 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
588 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
590 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, TRUE
, NULL
, &stream
);
592 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
593 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
596 test_IStream_invalid_operations(stream
, mode
);
598 refcount
= IStream_Release(stream
);
599 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
602 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
607 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, FALSE
, NULL
, &stream
);
608 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
609 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
612 test_IStream_invalid_operations(stream
, mode
);
614 refcount
= IStream_Release(stream
);
615 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
619 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, TRUE
, NULL
, &stream
);
620 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret
);
621 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
624 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
625 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
626 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
629 test_IStream_invalid_operations(stream
, mode
);
631 refcount
= IStream_Release(stream
);
632 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
636 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, TRUE
, NULL
, &stream
);
637 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
638 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
641 test_IStream_invalid_operations(stream
, mode
);
643 refcount
= IStream_Release(stream
);
644 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
647 delret
= DeleteFileA(test_fileA
);
648 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
653 static void test_SHCreateStreamOnFileEx_CopyTo(void)
657 WCHAR tmpPath
[MAX_PATH
];
658 WCHAR srcFileName
[MAX_PATH
];
659 WCHAR dstFileName
[MAX_PATH
];
660 ULARGE_INTEGER count
, read
, written
;
661 LARGE_INTEGER distance
;
662 static const char srcContents
[1];
663 static const WCHAR prefix
[] = { 'T', 'S', 'T', 0 };
665 GetTempPathW(MAX_PATH
, tmpPath
);
666 GetTempFileNameW(tmpPath
, prefix
, 0, srcFileName
);
667 GetTempFileNameW(tmpPath
, prefix
, 0, dstFileName
);
669 ret
= SHCreateStreamOnFileEx(srcFileName
, STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
, FILE_ATTRIBUTE_TEMPORARY
, FALSE
, NULL
, &src
);
670 ok(SUCCEEDED(ret
), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret
);
672 written
.QuadPart
= 0;
673 ret
= IStream_Write(src
, srcContents
, sizeof(srcContents
), &U(written
).LowPart
);
674 ok(SUCCEEDED(ret
), "ISequentialStream_Write failed with ret=0x%08x\n", ret
);
676 distance
.QuadPart
= 0;
677 ret
= IStream_Seek(src
, distance
, STREAM_SEEK_SET
, &written
);
678 ok(SUCCEEDED(ret
), "ISequentialStream_Seek failed with ret=0x%08x\n", ret
);
680 ret
= SHCreateStreamOnFileEx(dstFileName
, STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
, FILE_ATTRIBUTE_TEMPORARY
, FALSE
, NULL
, &dst
);
681 ok(SUCCEEDED(ret
), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret
);
683 /* Test using a count larger than the source file, so that the Read operation will fall short */
686 ret
= IStream_CopyTo(src
, dst
, count
, &read
, &written
);
687 ok(SUCCEEDED(ret
), "CopyTo failed with ret=0x%08x\n", ret
);
689 ok(read
.QuadPart
== 1, "read does not match size: %d != 1\n", U(read
).LowPart
);
690 ok(written
.QuadPart
== 1, "written does not match size: %d != 1\n", U(written
).LowPart
);
692 IStream_Release(dst
);
693 IStream_Release(src
);
694 DeleteFileW( srcFileName
);
695 DeleteFileW( dstFileName
);
701 static const DWORD stgm_access
[] = {
707 static const DWORD stgm_sharing
[] = {
709 STGM_SHARE_DENY_NONE
,
710 STGM_SHARE_DENY_READ
,
711 STGM_SHARE_DENY_WRITE
,
715 static const DWORD stgm_flags
[] = {
718 STGM_DELETEONRELEASE
,
719 STGM_CONVERT
| STGM_DELETEONRELEASE
,
720 STGM_TRANSACTED
| STGM_CONVERT
,
721 STGM_TRANSACTED
| STGM_DELETEONRELEASE
,
722 STGM_TRANSACTED
| STGM_CONVERT
| STGM_DELETEONRELEASE
727 for (i
= 0; i
!= sizeof(stgm_access
)/sizeof(stgm_access
[0]); i
++) {
728 for (j
= 0; j
!= sizeof(stgm_sharing
)/sizeof(stgm_sharing
[0]); j
++) {
729 test_SHCreateStreamOnFileA(stgm_access
[i
], stgm_sharing
[j
]);
730 test_SHCreateStreamOnFileW(stgm_access
[i
], stgm_sharing
[j
]);
732 for (k
= 0; k
!= sizeof(stgm_flags
)/sizeof(stgm_flags
[0]); k
++)
733 test_SHCreateStreamOnFileEx(stgm_access
[i
], stgm_sharing
[j
] | stgm_flags
[k
]);
737 test_SHCreateStreamOnFileEx_CopyTo();