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
;
196 /* IStream_Read/Write from the COBJMACROS is undefined by shlwapi.h */
198 written
= 0xdeadbeaf;
199 ret
= stream
->lpVtbl
->Write(stream
, "\x5e\xa7", 2, &written
);
200 if (mode
== STGM_WRITE
|| mode
== STGM_READWRITE
)
202 ok(ret
== S_OK
, "IStream_Write error %#x (access %#x)\n", ret
, mode
);
203 ok(written
== 2, "expected 2, got %u\n", written
);
207 ok(ret
== STG_E_ACCESSDENIED
|| broken(ret
== S_OK
) /* win2000 */, "expected STG_E_ACCESSDENIED, got %#x (access %#x)\n", ret
, mode
);
208 ok(written
== 0xdeadbeaf || broken(written
== 2) /* win2000 */, "expected 0xdeadbeaf, got %#x\n", written
);
210 if (ret
== S_OK
) return; /* no point in further testing */
213 ret
= stream
->lpVtbl
->Seek(stream
, start
, STREAM_SEEK_SET
, NULL
);
214 ok(ret
== S_OK
, "Seek error %#x\n", ret
);
217 ret
= stream
->lpVtbl
->Read(stream
, buf
, 2, &count
);
220 ok(ret
== S_OK
|| broken(ret
== S_FALSE
) /* win2000 */, "IStream_Read error %#x (access %#x, written %u)\n", ret
, mode
, written
);
221 if (ret
== S_OK
&& (mode
== STGM_WRITE
|| mode
== STGM_READWRITE
))
223 ok(count
== 2, "expected 2, got %u\n", count
);
224 ok(buf
[0] == 0x5e && buf
[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf
[0], buf
[1]);
227 ok(count
== 0, "expected 0, got %u\n", count
);
231 ok(ret
== S_FALSE
, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret
, mode
, written
);
232 ok(count
== 0, "expected 0, got %u\n", count
);
235 ret
= stream
->lpVtbl
->Seek(stream
, start
, STREAM_SEEK_SET
, NULL
);
236 ok(ret
== S_OK
, "Seek error %#x\n", ret
);
239 ret
= stream
->lpVtbl
->Read(stream
, buf
, 0, &count
);
240 ok(ret
== S_OK
, "IStream_Read error %#x (access %#x, written %u)\n", ret
, mode
, written
);
241 ok(count
== 0, "expected 0, got %u\n", count
);
244 ret
= stream
->lpVtbl
->Read(stream
, buf
, sizeof(buf
), &count
);
245 ok(ret
== S_FALSE
, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret
, mode
, written
);
246 ok(count
== written
, "expected %u, got %u\n", written
, count
);
248 ok(buf
[0] == 0x5e && buf
[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf
[0], buf
[1]);
250 memset(&statstg
, 0xff, sizeof(statstg
));
251 ret
= IStream_Stat(stream
, &statstg
, 0);
252 ok(ret
== S_OK
, "Stat failed, hr %#x.\n", ret
);
253 ok(statstg
.pwcsName
!= NULL
, "Unexpected name %s.\n", wine_dbgstr_w(statstg
.pwcsName
));
254 CoTaskMemFree(statstg
.pwcsName
);
256 memset(&statstg
, 0xff, sizeof(statstg
));
257 ret
= IStream_Stat(stream
, &statstg
, STATFLAG_NONAME
);
258 ok(ret
== S_OK
, "Stat failed, hr %#x.\n", ret
);
259 ok(statstg
.pwcsName
== NULL
, "Unexpected name %s.\n", wine_dbgstr_w(statstg
.pwcsName
));
262 static void test_stream_qi(IStream
*stream
)
267 hr
= IStream_QueryInterface(stream
, &IID_IStream
, (void **)&unk
);
268 ok(SUCCEEDED(hr
), "Failed to get IStream interface, hr %#x.\n", hr
);
269 IUnknown_Release(unk
);
272 hr
= IStream_QueryInterface(stream
, &IID_ISequentialStream
, (void **)&unk
);
274 ok(SUCCEEDED(hr
) || broken(hr
== E_NOINTERFACE
) /* XP */, "Failed to get ISequentialStream interface, hr %#x.\n", hr
);
276 IUnknown_Release(unk
);
278 hr
= IStream_QueryInterface(stream
, &IID_IUnknown
, (void **)&unk
);
279 ok(SUCCEEDED(hr
), "Failed to get IUnknown interface, hr %#x.\n", hr
);
280 IUnknown_Release(unk
);
283 static void test_SHCreateStreamOnFileA(DWORD mode
, DWORD stgm
)
288 char test_file
[MAX_PATH
];
289 static const CHAR testA_txt
[] = "\\testA.txt";
291 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode
, stgm
);
293 /* Don't used a fixed path for the testA.txt file */
294 GetTempPathA(MAX_PATH
, test_file
);
295 lstrcatA(test_file
, testA_txt
);
297 /* invalid arguments */
300 ret
= SHCreateStreamOnFileA(NULL
, mode
| stgm
, &stream
);
301 if (ret
== E_INVALIDARG
) /* Win98 SE */ {
302 win_skip("Not supported\n");
306 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) /* NT */ ||
307 ret
== HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME
) /* 9x */,
308 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) "
309 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret
);
310 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
312 if (0) /* This test crashes on WinXP SP2 */
314 ret
= SHCreateStreamOnFileA(test_file
, mode
| stgm
, NULL
);
315 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
319 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CONVERT
| stgm
, &stream
);
320 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
321 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
324 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_DELETEONRELEASE
| stgm
, &stream
);
325 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
326 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
329 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_TRANSACTED
| stgm
, &stream
);
330 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret
);
331 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
333 /* file does not exist */
336 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
337 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
338 ok(stream
== NULL
, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream
);
341 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
342 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
343 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
346 test_stream_qi(stream
);
347 test_IStream_invalid_operations(stream
, mode
);
349 refcount
= IStream_Release(stream
);
350 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
353 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
358 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
359 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
360 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
363 test_IStream_invalid_operations(stream
, mode
);
365 refcount
= IStream_Release(stream
);
366 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
370 ret
= SHCreateStreamOnFileA(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
371 ok(ret
== S_OK
, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret
);
372 ok(stream
!= NULL
, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
377 test_stream_read_write(stream
, mode
);
378 test_IStream_invalid_operations(stream
, mode
);
380 refcount
= IStream_Release(stream
);
381 ok(refcount
== 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount
);
383 delret
= DeleteFileA(test_file
);
384 ok(delret
, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
385 test_file
, GetLastError());
390 static void test_SHCreateStreamOnFileW(DWORD mode
, DWORD stgm
)
395 WCHAR test_file
[MAX_PATH
];
396 CHAR test_fileA
[MAX_PATH
];
397 static const CHAR testW_txt
[] = "\\testW.txt";
399 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode
, stgm
);
401 /* Don't used a fixed path for the testW.txt file */
402 GetTempPathA(MAX_PATH
, test_fileA
);
403 lstrcatA(test_fileA
, testW_txt
);
404 MultiByteToWideChar(CP_ACP
, 0, test_fileA
, -1, test_file
, MAX_PATH
);
406 /* invalid arguments */
412 ret
= SHCreateStreamOnFileW(NULL
, mode
| stgm
, &stream
);
413 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) || /* XP */
414 ret
== E_INVALIDARG
/* Vista */,
415 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret
);
416 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
421 /* This test crashes on WinXP SP2 */
422 ret
= SHCreateStreamOnFileW(test_file
, mode
| stgm
, NULL
);
423 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
427 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_CONVERT
| stgm
, &stream
);
428 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
429 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
432 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_DELETEONRELEASE
| stgm
, &stream
);
433 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
434 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
437 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_TRANSACTED
| stgm
, &stream
);
438 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret
);
439 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
441 /* file does not exist */
444 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
445 if (ret
== E_INVALIDARG
) /* Win98 SE */ {
446 win_skip("Not supported\n");
450 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
451 ok(stream
== NULL
, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream
);
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");
459 test_stream_qi(stream
);
460 test_IStream_invalid_operations(stream
, mode
);
462 refcount
= IStream_Release(stream
);
463 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
466 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
471 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, &stream
);
472 ok(ret
== S_OK
, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret
);
473 ok(stream
!= NULL
, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
476 test_IStream_invalid_operations(stream
, mode
);
478 refcount
= IStream_Release(stream
);
479 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
483 ret
= SHCreateStreamOnFileW(test_file
, mode
| STGM_CREATE
| stgm
, &stream
);
484 ok(ret
== S_OK
, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret
);
485 ok(stream
!= NULL
, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
490 test_stream_read_write(stream
, mode
);
491 test_IStream_invalid_operations(stream
, mode
);
493 refcount
= IStream_Release(stream
);
494 ok(refcount
== 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount
);
496 delret
= DeleteFileA(test_fileA
);
497 ok(delret
, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
503 static void test_SHCreateStreamOnFileEx(DWORD mode
, DWORD stgm
)
506 IStream
* template = NULL
;
509 WCHAR test_file
[MAX_PATH
];
510 CHAR test_fileA
[MAX_PATH
];
511 static const CHAR testEx_txt
[] = "\\testEx.txt";
514 if (winetest_debug
> 1)
515 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode
, stgm
);
517 /* Don't used a fixed path for the testEx.txt file */
518 GetTempPathA(MAX_PATH
, test_fileA
);
519 lstrcatA(test_fileA
, testEx_txt
);
520 MultiByteToWideChar(CP_ACP
, 0, test_fileA
, -1, test_file
, MAX_PATH
);
522 /* invalid arguments */
528 ret
= SHCreateStreamOnFileEx(NULL
, mode
, 0, FALSE
, NULL
, &stream
);
529 ok(ret
== HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
) || /* XP */
530 ret
== E_INVALIDARG
/* Vista */,
531 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret
);
532 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
536 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, template, &stream
);
537 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
538 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
540 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, template, &stream
);
542 ok( ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
543 ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
544 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
545 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret
);
547 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
551 /* This test crashes on WinXP SP2 */
552 ret
= SHCreateStreamOnFileEx(test_file
, mode
, 0, FALSE
, NULL
, NULL
);
553 ok(ret
== E_INVALIDARG
, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret
);
556 /* file does not exist */
559 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, FALSE
, NULL
, &stream
);
560 if ((stgm
& STGM_TRANSACTED
) == STGM_TRANSACTED
&& mode
== STGM_READ
) {
561 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) /* XP */ || ret
== E_INVALIDARG
/* Vista */,
562 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret
);
564 if (ret
== E_INVALIDARG
) {
565 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
569 ok( ret
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
) ||
570 ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
571 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
572 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret
);
574 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
577 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, TRUE
, NULL
, &stream
);
578 /* not supported on win9x */
579 if (broken(ret
== HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
) && stream
== NULL
)) {
580 skip("Not supported\n");
581 DeleteFileA(test_fileA
);
585 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
586 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
589 test_stream_qi(stream
);
590 test_IStream_invalid_operations(stream
, mode
);
592 refcount
= IStream_Release(stream
);
593 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
595 delret
= DeleteFileA(test_fileA
);
596 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
601 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
602 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
603 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
605 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
607 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
608 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
611 test_IStream_invalid_operations(stream
, mode
);
613 refcount
= IStream_Release(stream
);
614 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
616 delret
= DeleteFileA(test_fileA
);
617 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
622 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, TRUE
, NULL
, &stream
);
623 if (ret
== HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
)) {
624 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
626 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");
632 test_IStream_invalid_operations(stream
, mode
);
634 refcount
= IStream_Release(stream
);
635 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
638 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
643 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, FALSE
, NULL
, &stream
);
644 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
645 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
648 test_IStream_invalid_operations(stream
, mode
);
650 refcount
= IStream_Release(stream
);
651 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
655 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_FAILIFTHERE
| stgm
, 0, TRUE
, NULL
, &stream
);
656 ok(ret
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret
);
657 ok(stream
== NULL
, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream
);
660 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, FALSE
, NULL
, &stream
);
661 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
662 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
665 test_IStream_invalid_operations(stream
, mode
);
667 refcount
= IStream_Release(stream
);
668 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
672 ret
= SHCreateStreamOnFileEx(test_file
, mode
| STGM_CREATE
| stgm
, 0, TRUE
, NULL
, &stream
);
673 ok(ret
== S_OK
, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret
);
674 ok(stream
!= NULL
, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
677 test_IStream_invalid_operations(stream
, mode
);
679 refcount
= IStream_Release(stream
);
680 ok(refcount
== 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount
);
683 delret
= DeleteFileA(test_fileA
);
684 ok(delret
, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
689 static void test_SHCreateStreamOnFileEx_CopyTo(void)
693 WCHAR tmpPath
[MAX_PATH
];
694 WCHAR srcFileName
[MAX_PATH
];
695 WCHAR dstFileName
[MAX_PATH
];
696 ULARGE_INTEGER count
, read
, written
;
697 LARGE_INTEGER distance
;
698 static const char srcContents
[1];
699 static const WCHAR prefix
[] = { 'T', 'S', 'T', 0 };
701 GetTempPathW(MAX_PATH
, tmpPath
);
702 ret
= GetTempFileNameW(tmpPath
, prefix
, 0, srcFileName
);
703 ok(ret
!= 0, "GetTempFileName failed, got error %d\n", GetLastError());
704 ret
= GetTempFileNameW(tmpPath
, prefix
, 0, dstFileName
);
705 ok(ret
!= 0, "GetTempFileName failed, got error %d\n", GetLastError());
707 ret
= SHCreateStreamOnFileEx(srcFileName
, STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
, FILE_ATTRIBUTE_TEMPORARY
, FALSE
, NULL
, &src
);
708 ok(SUCCEEDED(ret
), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret
);
710 written
.QuadPart
= 0;
711 ret
= IStream_Write(src
, srcContents
, sizeof(srcContents
), &U(written
).LowPart
);
712 ok(SUCCEEDED(ret
), "ISequentialStream_Write failed with ret=0x%08x\n", ret
);
714 distance
.QuadPart
= 0;
715 ret
= IStream_Seek(src
, distance
, STREAM_SEEK_SET
, &written
);
716 ok(SUCCEEDED(ret
), "ISequentialStream_Seek failed with ret=0x%08x\n", ret
);
718 ret
= SHCreateStreamOnFileEx(dstFileName
, STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
, FILE_ATTRIBUTE_TEMPORARY
, FALSE
, NULL
, &dst
);
719 ok(SUCCEEDED(ret
), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret
);
721 /* Test using a count larger than the source file, so that the Read operation will fall short */
724 ret
= IStream_CopyTo(src
, dst
, count
, &read
, &written
);
725 ok(SUCCEEDED(ret
), "CopyTo failed with ret=0x%08x\n", ret
);
727 ok(read
.QuadPart
== 1, "read does not match size: %d != 1\n", U(read
).LowPart
);
728 ok(written
.QuadPart
== 1, "written does not match size: %d != 1\n", U(written
).LowPart
);
730 IStream_Release(dst
);
731 IStream_Release(src
);
732 DeleteFileW( srcFileName
);
733 DeleteFileW( dstFileName
);
736 static void test_SHCreateMemStream(void)
738 static const BYTE initial
[10];
739 IStream
*stream
, *stream2
;
744 stream
= SHCreateMemStream(initial
, 0);
745 ok(stream
!= NULL
, "Failed to create a stream.\n");
746 IStream_Release(stream
);
748 stream
= SHCreateMemStream(NULL
, 10);
749 ok(stream
!= NULL
, "Failed to create a stream.\n");
750 IStream_Release(stream
);
752 stream
= SHCreateMemStream(NULL
, 0);
753 ok(stream
!= NULL
, "Failed to create a stream.\n");
755 hr
= IStream_QueryInterface(stream
, &IID_ISequentialStream
, (void **)&unk
);
757 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* WinXP */, "Failed to QI, hr %#x.\n", hr
);
759 IUnknown_Release(unk
);
761 hr
= IStream_Read(stream
, buff
, sizeof(buff
), NULL
);
763 ok(hr
== S_FALSE
|| broken(hr
== S_OK
) /* WinXP */, "Unexpected hr %#x.\n", hr
);
765 hr
= IStream_Clone(stream
, &stream2
);
767 ok(hr
== S_OK
|| broken(hr
== E_NOTIMPL
) /* < Win8 */, "Failed to clone a stream, hr %#x.\n", hr
);
769 IStream_Release(stream2
);
771 IStream_Release(stream
);
776 static const DWORD stgm_access
[] = {
782 static const DWORD stgm_sharing
[] = {
784 STGM_SHARE_DENY_NONE
,
785 STGM_SHARE_DENY_READ
,
786 STGM_SHARE_DENY_WRITE
,
790 static const DWORD stgm_flags
[] = {
793 STGM_DELETEONRELEASE
,
794 STGM_CONVERT
| STGM_DELETEONRELEASE
,
795 STGM_TRANSACTED
| STGM_CONVERT
,
796 STGM_TRANSACTED
| STGM_DELETEONRELEASE
,
797 STGM_TRANSACTED
| STGM_CONVERT
| STGM_DELETEONRELEASE
802 for (i
= 0; i
!= ARRAY_SIZE(stgm_access
); i
++) {
803 for (j
= 0; j
!= ARRAY_SIZE(stgm_sharing
); j
++) {
804 test_SHCreateStreamOnFileA(stgm_access
[i
], stgm_sharing
[j
]);
805 test_SHCreateStreamOnFileW(stgm_access
[i
], stgm_sharing
[j
]);
807 for (k
= 0; k
!= ARRAY_SIZE(stgm_flags
); k
++)
808 test_SHCreateStreamOnFileEx(stgm_access
[i
], stgm_sharing
[j
] | stgm_flags
[k
]);
812 test_SHCreateStreamOnFileEx_CopyTo();
813 test_SHCreateMemStream();