msvcp110: Add tr2_sys__File_size_wchar implementation and test.
[wine/multimedia.git] / dlls / shlwapi / tests / istream.c
blob48a292afbc02d9ebc8d17833557876233444bb92
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
20 #define COBJMACROS
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "shlwapi.h"
32 /* Function pointers for the SHCreateStreamOnFile functions */
33 static HMODULE hShlwapi;
34 static HRESULT (WINAPI *pSHCreateStreamOnFileA)(LPCSTR file, DWORD mode, IStream **stream);
35 static HRESULT (WINAPI *pSHCreateStreamOnFileW)(LPCWSTR file, DWORD mode, IStream **stream);
36 static HRESULT (WINAPI *pSHCreateStreamOnFileEx)(LPCWSTR file, DWORD mode, DWORD attributes, BOOL create, IStream *template, IStream **stream);
38 static BOOL is_win2000_IE5 = FALSE;
40 static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
42 HRESULT ret;
43 IStream * clone;
44 ULONG refcount;
45 ULARGE_INTEGER uzero;
46 ULARGE_INTEGER uret;
47 LARGE_INTEGER zero;
48 ULONG count;
49 char data[256];
51 U(uzero).HighPart = 0;
52 U(uzero).LowPart = 0;
53 U(uret).HighPart = 0;
54 U(uret).LowPart = 0;
55 U(zero).HighPart = 0;
56 U(zero).LowPart = 0;
58 /* IStream::Read */
60 /* IStream_Read from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Read helper function. */
62 ret = stream->lpVtbl->Read(stream, NULL, 0, &count);
63 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
65 ret = stream->lpVtbl->Read(stream, data, 5, NULL);
66 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
68 ret = stream->lpVtbl->Read(stream, data, 0, NULL);
69 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
71 ret = stream->lpVtbl->Read(stream, data, 3, &count);
72 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
74 /* IStream::Write */
76 /* IStream_Write from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Write helper function. */
78 ret = stream->lpVtbl->Write(stream, NULL, 0, &count);
79 if (mode == STGM_READ)
81 ok(ret == STG_E_ACCESSDENIED /* XP */ || broken(ret == S_OK) /* Win2000 + IE5 */,
82 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
83 if (ret == S_OK)
84 is_win2000_IE5 = TRUE;
86 else
87 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
89 /* IStream::Write calls below hang under Win2000 + IE5, Win2000 + IE6 SP1
90 * and newer Windows versions pass these tests.
92 if (is_win2000_IE5)
94 win_skip("broken IStream::Write implementation (win2000)\n");
95 return;
98 strcpy(data, "Hello");
99 ret = stream->lpVtbl->Write(stream, data, 5, NULL);
100 if (mode == STGM_READ)
101 ok(ret == STG_E_ACCESSDENIED,
102 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
103 else
104 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
106 strcpy(data, "Hello");
107 ret = stream->lpVtbl->Write(stream, data, 0, NULL);
108 if (mode == STGM_READ)
109 ok(ret == STG_E_ACCESSDENIED,
110 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
111 else
112 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
114 strcpy(data, "Hello");
115 ret = stream->lpVtbl->Write(stream, data, 0, &count);
116 if (mode == STGM_READ)
117 ok(ret == STG_E_ACCESSDENIED,
118 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
119 else
120 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
122 strcpy(data, "Hello");
123 ret = stream->lpVtbl->Write(stream, data, 3, &count);
124 if (mode == STGM_READ)
125 ok(ret == STG_E_ACCESSDENIED,
126 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret);
127 else
128 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
130 /* IStream::Seek */
132 ret = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
133 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
135 ret = IStream_Seek(stream, zero, 20, NULL);
136 ok(ret == E_INVALIDARG,
137 "expected E_INVALIDARG, got 0x%08x\n", ret);
139 /* IStream::CopyTo */
141 ret = IStream_CopyTo(stream, NULL, uzero, &uret, &uret);
142 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
144 clone = NULL;
145 ret = IStream_CopyTo(stream, clone, uzero, &uret, &uret);
146 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
148 ret = IStream_CopyTo(stream, stream, uzero, &uret, &uret);
149 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
151 ret = IStream_CopyTo(stream, stream, uzero, &uret, NULL);
152 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
154 ret = IStream_CopyTo(stream, stream, uzero, NULL, &uret);
155 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
157 /* IStream::Commit */
159 ret = IStream_Commit(stream, STGC_DEFAULT);
160 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
162 /* IStream::Revert */
164 ret = IStream_Revert(stream);
165 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
167 /* IStream::LockRegion */
169 ret = IStream_LockRegion(stream, uzero, uzero, 0);
170 ok(ret == E_NOTIMPL /* XP */ || ret == S_OK /* Vista */,
171 "expected E_NOTIMPL or S_OK, got 0x%08x\n", ret);
173 /* IStream::UnlockRegion */
175 if (ret == E_NOTIMPL) /* XP */ {
176 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
177 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
178 } else /* Vista */ {
179 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
180 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
182 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
183 ok(ret == STG_E_LOCKVIOLATION, "expected STG_E_LOCKVIOLATION, got 0x%08x\n", ret);
186 /* IStream::Stat */
188 ret = IStream_Stat(stream, NULL, 0);
189 ok(ret == STG_E_INVALIDPOINTER,
190 "expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret);
192 /* IStream::Clone */
194 /* Passing a NULL pointer for the second IStream::Clone param crashes on Win7 */
196 clone = NULL;
197 ret = IStream_Clone(stream, &clone);
198 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
199 ok(clone == NULL, "expected a NULL IStream object, got %p\n", stream);
201 if (clone) {
202 refcount = IStream_Release(clone);
203 ok(refcount == 0, "expected 0, got %d\n", refcount);
208 static void test_stream_read_write(IStream *stream, DWORD mode)
210 static const LARGE_INTEGER start;
211 HRESULT ret;
212 unsigned char buf[16];
213 DWORD written, count;
215 /* IStream_Read/Write from the COBJMACROS is undefined by shlwapi.h */
217 written = 0xdeadbeaf;
218 ret = stream->lpVtbl->Write(stream, "\x5e\xa7", 2, &written);
219 if (mode == STGM_WRITE || mode == STGM_READWRITE)
221 ok(ret == S_OK, "IStream_Write error %#x (access %#x)\n", ret, mode);
222 ok(written == 2, "expected 2, got %u\n", written);
224 else
226 ok(ret == STG_E_ACCESSDENIED || broken(ret == S_OK) /* win2000 */, "expected STG_E_ACCESSDENIED, got %#x (access %#x)\n", ret, mode);
227 ok(written == 0xdeadbeaf || broken(written == 2) /* win2000 */, "expected 0xdeadbeaf, got %#x\n", written);
228 written = 0;
229 if (ret == S_OK) return; /* no point in further testing */
232 ret = stream->lpVtbl->Seek(stream, start, STREAM_SEEK_SET, NULL);
233 ok(ret == S_OK, "Seek error %#x\n", ret);
235 count = 0xdeadbeaf;
236 ret = stream->lpVtbl->Read(stream, buf, 2, &count);
237 if (written != 0)
239 ok(ret == S_OK || broken(ret == S_FALSE) /* win2000 */, "IStream_Read error %#x (access %#x, written %u)\n", ret, mode, written);
240 if (ret == S_OK && (mode == STGM_WRITE || mode == STGM_READWRITE))
242 ok(count == 2, "expected 2, got %u\n", count);
243 ok(buf[0] == 0x5e && buf[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf[0], buf[1]);
245 else
246 ok(count == 0, "expected 0, got %u\n", count);
248 else
250 todo_wine
251 ok(ret == S_FALSE, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret, mode, written);
252 ok(count == 0, "expected 0, got %u\n", count);
257 static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm)
259 IStream * stream;
260 HRESULT ret;
261 ULONG refcount;
262 char test_file[MAX_PATH];
263 static const CHAR testA_txt[] = "\\testA.txt";
265 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode, stgm);
267 /* Don't used a fixed path for the testA.txt file */
268 GetTempPathA(MAX_PATH, test_file);
269 lstrcatA(test_file, testA_txt);
271 /* invalid arguments */
273 stream = NULL;
274 ret = (*pSHCreateStreamOnFileA)(NULL, mode | stgm, &stream);
275 if (ret == E_INVALIDARG) /* Win98 SE */ {
276 win_skip("Not supported\n");
277 return;
280 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) /* NT */ ||
281 ret == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME) /* 9x */,
282 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) "
283 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret);
284 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
286 if (0) /* This test crashes on WinXP SP2 */
288 ret = (*pSHCreateStreamOnFileA)(test_file, mode | stgm, NULL);
289 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
292 stream = NULL;
293 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CONVERT | stgm, &stream);
294 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
295 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
297 stream = NULL;
298 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
299 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
300 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
302 stream = NULL;
303 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
304 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
305 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
307 /* file does not exist */
309 stream = NULL;
310 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
311 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
312 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
314 stream = NULL;
315 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | 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");
319 if (stream) {
320 test_IStream_invalid_operations(stream, mode);
322 refcount = IStream_Release(stream);
323 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
326 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
328 /* file exists */
330 stream = NULL;
331 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
332 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
333 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
335 if (stream) {
336 test_IStream_invalid_operations(stream, mode);
338 refcount = IStream_Release(stream);
339 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
342 stream = NULL;
343 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | stgm, &stream);
344 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
345 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
347 if (stream) {
348 BOOL delret;
350 test_stream_read_write(stream, mode);
351 test_IStream_invalid_operations(stream, mode);
353 refcount = IStream_Release(stream);
354 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
356 delret = DeleteFileA(test_file);
357 ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
358 test_file, GetLastError());
363 static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm)
365 IStream * stream;
366 HRESULT ret;
367 ULONG refcount;
368 WCHAR test_file[MAX_PATH];
369 CHAR test_fileA[MAX_PATH];
370 static const CHAR testW_txt[] = "\\testW.txt";
372 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode, stgm);
374 /* Don't used a fixed path for the testW.txt file */
375 GetTempPathA(MAX_PATH, test_fileA);
376 lstrcatA(test_fileA, testW_txt);
377 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
379 /* invalid arguments */
381 if (0)
383 /* Crashes on NT4 */
384 stream = NULL;
385 ret = (*pSHCreateStreamOnFileW)(NULL, mode | stgm, &stream);
386 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
387 ret == E_INVALIDARG /* Vista */,
388 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
389 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
392 if (0)
394 /* This test crashes on WinXP SP2 */
395 ret = (*pSHCreateStreamOnFileW)(test_file, mode | stgm, NULL);
396 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
399 stream = NULL;
400 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CONVERT | stgm, &stream);
401 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
402 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
404 stream = NULL;
405 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
406 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
407 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
409 stream = NULL;
410 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
411 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
412 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
414 /* file does not exist */
416 stream = NULL;
417 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
418 if (ret == E_INVALIDARG) /* Win98 SE */ {
419 win_skip("Not supported\n");
420 return;
423 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
424 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
426 stream = NULL;
427 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | 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");
431 if (stream) {
432 test_IStream_invalid_operations(stream, mode);
434 refcount = IStream_Release(stream);
435 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
438 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
440 /* file exists */
442 stream = NULL;
443 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
444 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
445 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
447 if (stream) {
448 test_IStream_invalid_operations(stream, mode);
450 refcount = IStream_Release(stream);
451 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
454 stream = NULL;
455 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | stgm, &stream);
456 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
457 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
459 if (stream) {
460 BOOL delret;
462 test_stream_read_write(stream, mode);
463 test_IStream_invalid_operations(stream, mode);
465 refcount = IStream_Release(stream);
466 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
468 delret = DeleteFileA(test_fileA);
469 ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
470 GetLastError());
475 static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
477 IStream * stream;
478 IStream * template = NULL;
479 HRESULT ret;
480 ULONG refcount;
481 WCHAR test_file[MAX_PATH];
482 CHAR test_fileA[MAX_PATH];
483 static const CHAR testEx_txt[] = "\\testEx.txt";
484 BOOL delret;
486 if (winetest_debug > 1)
487 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
489 /* Don't used a fixed path for the testEx.txt file */
490 GetTempPathA(MAX_PATH, test_fileA);
491 lstrcatA(test_fileA, testEx_txt);
492 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
494 /* invalid arguments */
496 if (0)
498 /* Crashes on NT4 */
499 stream = NULL;
500 ret = (*pSHCreateStreamOnFileEx)(NULL, mode, 0, FALSE, NULL, &stream);
501 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
502 ret == E_INVALIDARG /* Vista */,
503 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
504 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
507 stream = NULL;
508 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
509 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
510 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
511 Sleep(1000);
512 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
514 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
515 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
516 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
517 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
519 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
521 if (0)
523 /* This test crashes on WinXP SP2 */
524 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, NULL, NULL);
525 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret);
528 /* file does not exist */
530 stream = NULL;
531 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
532 if ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED && mode == STGM_READ) {
533 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* XP */ || ret == E_INVALIDARG /* Vista */,
534 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
536 if (ret == E_INVALIDARG) {
537 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
538 return;
540 } else {
541 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
542 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
543 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
544 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
546 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
548 stream = NULL;
549 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
550 /* not supported on win9x */
551 if (broken(ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) && stream == NULL)) {
552 skip("Not supported\n");
553 DeleteFileA(test_fileA);
554 return;
557 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
558 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
560 if (stream) {
561 test_IStream_invalid_operations(stream, mode);
563 refcount = IStream_Release(stream);
564 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
566 delret = DeleteFileA(test_fileA);
567 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
568 GetLastError());
571 stream = NULL;
572 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
573 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
574 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
575 Sleep(1000);
576 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
578 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
579 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
581 if (stream) {
582 test_IStream_invalid_operations(stream, mode);
584 refcount = IStream_Release(stream);
585 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
587 delret = DeleteFileA(test_fileA);
588 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
589 GetLastError());
592 stream = NULL;
593 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
594 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
595 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
596 Sleep(1000);
597 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, 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");
602 if (stream) {
603 test_IStream_invalid_operations(stream, mode);
605 refcount = IStream_Release(stream);
606 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
609 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
611 /* file exists */
613 stream = NULL;
614 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
615 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
616 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
618 if (stream) {
619 test_IStream_invalid_operations(stream, mode);
621 refcount = IStream_Release(stream);
622 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
625 stream = NULL;
626 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
627 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret);
628 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
630 stream = NULL;
631 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
632 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
633 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
635 if (stream) {
636 test_IStream_invalid_operations(stream, mode);
638 refcount = IStream_Release(stream);
639 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
642 stream = NULL;
643 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, 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");
647 if (stream) {
648 test_IStream_invalid_operations(stream, mode);
650 refcount = IStream_Release(stream);
651 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
654 delret = DeleteFileA(test_fileA);
655 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
656 GetLastError());
660 static void test_SHCreateStreamOnFileEx_CopyTo(void)
662 HRESULT ret;
663 IStream *src, *dst;
664 WCHAR tmpPath[MAX_PATH];
665 WCHAR srcFileName[MAX_PATH];
666 WCHAR dstFileName[MAX_PATH];
667 ULARGE_INTEGER count, read, written;
668 LARGE_INTEGER distance;
669 static const char srcContents[1];
670 static const WCHAR prefix[] = { 'T', 'S', 'T', 0 };
672 GetTempPathW(MAX_PATH, tmpPath);
673 GetTempFileNameW(tmpPath, prefix, 0, srcFileName);
674 GetTempFileNameW(tmpPath, prefix, 0, dstFileName);
676 ret = pSHCreateStreamOnFileEx(srcFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &src);
677 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
679 written.QuadPart = 0;
680 ret = IStream_Write(src, srcContents, sizeof(srcContents), &U(written).LowPart);
681 ok(SUCCEEDED(ret), "ISequentialStream_Write failed with ret=0x%08x\n", ret);
683 distance.QuadPart = 0;
684 ret = IStream_Seek(src, distance, STREAM_SEEK_SET, &written);
685 ok(SUCCEEDED(ret), "ISequentialStream_Seek failed with ret=0x%08x\n", ret);
687 ret = pSHCreateStreamOnFileEx(dstFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &dst);
688 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
690 /* Test using a count larger than the source file, so that the Read operation will fall short */
691 count.QuadPart = 2;
693 ret = IStream_CopyTo(src, dst, count, &read, &written);
694 ok(SUCCEEDED(ret), "CopyTo failed with ret=0x%08x\n", ret);
696 ok(read.QuadPart == 1, "read does not match size: %d != 1\n", U(read).LowPart);
697 ok(written.QuadPart == 1, "written does not match size: %d != 1\n", U(written).LowPart);
699 IStream_Release(dst);
700 IStream_Release(src);
701 DeleteFileW( srcFileName );
702 DeleteFileW( dstFileName );
706 START_TEST(istream)
708 static const DWORD stgm_access[] = {
709 STGM_READ,
710 STGM_WRITE,
711 STGM_READWRITE
714 static const DWORD stgm_sharing[] = {
716 STGM_SHARE_DENY_NONE,
717 STGM_SHARE_DENY_READ,
718 STGM_SHARE_DENY_WRITE,
719 STGM_SHARE_EXCLUSIVE
722 static const DWORD stgm_flags[] = {
724 STGM_CONVERT,
725 STGM_DELETEONRELEASE,
726 STGM_CONVERT | STGM_DELETEONRELEASE,
727 STGM_TRANSACTED | STGM_CONVERT,
728 STGM_TRANSACTED | STGM_DELETEONRELEASE,
729 STGM_TRANSACTED | STGM_CONVERT | STGM_DELETEONRELEASE
732 int i, j, k;
734 hShlwapi = LoadLibraryA("shlwapi.dll");
736 pSHCreateStreamOnFileA = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileA");
737 pSHCreateStreamOnFileW = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileW");
738 pSHCreateStreamOnFileEx = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx");
740 if (!pSHCreateStreamOnFileA)
741 skip("SHCreateStreamOnFileA not found.\n");
743 if (!pSHCreateStreamOnFileW)
744 skip("SHCreateStreamOnFileW not found.\n");
746 if (!pSHCreateStreamOnFileEx)
747 skip("SHCreateStreamOnFileEx not found.\n");
749 for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) {
750 for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) {
751 if (pSHCreateStreamOnFileA)
752 test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]);
754 if (pSHCreateStreamOnFileW)
755 test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]);
757 if (pSHCreateStreamOnFileEx) {
758 for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++)
759 test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]);
764 if (pSHCreateStreamOnFileEx) test_SHCreateStreamOnFileEx_CopyTo();