shlwapi/tests: Avoid preprocessor check to ensure it compiles.
[wine/multimedia.git] / dlls / shlwapi / tests / istream.c
blob95485b9535455da1b86b761c7a7cc7f891b84a19
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 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
488 /* Don't used a fixed path for the testEx.txt file */
489 GetTempPathA(MAX_PATH, test_fileA);
490 lstrcatA(test_fileA, testEx_txt);
491 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
493 /* invalid arguments */
495 if (0)
497 /* Crashes on NT4 */
498 stream = NULL;
499 ret = (*pSHCreateStreamOnFileEx)(NULL, mode, 0, FALSE, NULL, &stream);
500 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
501 ret == E_INVALIDARG /* Vista */,
502 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
503 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
506 stream = NULL;
507 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
508 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
509 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
510 Sleep(1000);
511 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
513 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
514 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
515 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
516 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
518 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
520 if (0)
522 /* This test crashes on WinXP SP2 */
523 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, NULL, NULL);
524 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret);
527 /* file does not exist */
529 stream = NULL;
530 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
531 if ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED && mode == STGM_READ) {
532 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* XP */ || ret == E_INVALIDARG /* Vista */,
533 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
535 if (ret == E_INVALIDARG) {
536 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
537 return;
539 } else {
540 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
541 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
542 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
543 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
545 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
547 stream = NULL;
548 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
549 /* not supported on win9x */
550 if (broken(ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) && stream == NULL)) {
551 skip("Not supported\n");
552 DeleteFileA(test_fileA);
553 return;
556 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
557 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
559 if (stream) {
560 test_IStream_invalid_operations(stream, mode);
562 refcount = IStream_Release(stream);
563 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
565 delret = DeleteFileA(test_fileA);
566 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
567 GetLastError());
570 stream = NULL;
571 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
572 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
573 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
574 Sleep(1000);
575 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
577 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
578 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
580 if (stream) {
581 test_IStream_invalid_operations(stream, mode);
583 refcount = IStream_Release(stream);
584 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
586 delret = DeleteFileA(test_fileA);
587 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
588 GetLastError());
591 stream = NULL;
592 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
593 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
594 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
595 Sleep(1000);
596 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
598 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
599 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
601 if (stream) {
602 test_IStream_invalid_operations(stream, mode);
604 refcount = IStream_Release(stream);
605 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
608 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
610 /* file exists */
612 stream = NULL;
613 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
614 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
615 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
617 if (stream) {
618 test_IStream_invalid_operations(stream, mode);
620 refcount = IStream_Release(stream);
621 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
624 stream = NULL;
625 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
626 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret);
627 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
629 stream = NULL;
630 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
631 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
632 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
634 if (stream) {
635 test_IStream_invalid_operations(stream, mode);
637 refcount = IStream_Release(stream);
638 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
641 stream = NULL;
642 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
643 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
644 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
646 if (stream) {
647 test_IStream_invalid_operations(stream, mode);
649 refcount = IStream_Release(stream);
650 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
653 delret = DeleteFileA(test_fileA);
654 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
655 GetLastError());
659 static void test_SHCreateStreamOnFileEx_CopyTo(void)
661 HRESULT ret;
662 IStream *src, *dst;
663 WCHAR tmpPath[MAX_PATH];
664 WCHAR srcFileName[MAX_PATH];
665 WCHAR dstFileName[MAX_PATH];
666 ULARGE_INTEGER count, read, written;
667 LARGE_INTEGER distance;
668 static const char srcContents[1];
669 static const WCHAR prefix[] = { 'T', 'S', 'T', 0 };
671 GetTempPathW(MAX_PATH, tmpPath);
672 GetTempFileNameW(tmpPath, prefix, 0, srcFileName);
673 GetTempFileNameW(tmpPath, prefix, 0, dstFileName);
675 ret = pSHCreateStreamOnFileEx(srcFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &src);
676 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
678 written.QuadPart = 0;
679 ret = IStream_Write(src, srcContents, sizeof(srcContents), &U(written).LowPart);
680 ok(SUCCEEDED(ret), "ISequentialStream_Write failed with ret=0x%08x\n", ret);
682 distance.QuadPart = 0;
683 ret = IStream_Seek(src, distance, STREAM_SEEK_SET, &written);
684 ok(SUCCEEDED(ret), "ISequentialStream_Seek failed with ret=0x%08x\n", ret);
686 ret = pSHCreateStreamOnFileEx(dstFileName, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, FILE_ATTRIBUTE_TEMPORARY, FALSE, NULL, &dst);
687 ok(SUCCEEDED(ret), "SHCreateStreamOnFileEx failed with ret=0x%08x\n", ret);
689 /* Test using a count larger than the source file, so that the Read operation will fall short */
690 count.QuadPart = 2;
692 ret = IStream_CopyTo(src, dst, count, &read, &written);
693 ok(SUCCEEDED(ret), "CopyTo failed with ret=0x%08x\n", ret);
695 ok(read.QuadPart == 1, "read does not match size: %d != 1\n", U(read).LowPart);
696 ok(written.QuadPart == 1, "written does not match size: %d != 1\n", U(written).LowPart);
698 IStream_Release(dst);
699 IStream_Release(src);
700 DeleteFileW( srcFileName );
701 DeleteFileW( dstFileName );
705 START_TEST(istream)
707 static const DWORD stgm_access[] = {
708 STGM_READ,
709 STGM_WRITE,
710 STGM_READWRITE
713 static const DWORD stgm_sharing[] = {
715 STGM_SHARE_DENY_NONE,
716 STGM_SHARE_DENY_READ,
717 STGM_SHARE_DENY_WRITE,
718 STGM_SHARE_EXCLUSIVE
721 static const DWORD stgm_flags[] = {
723 STGM_CONVERT,
724 STGM_DELETEONRELEASE,
725 STGM_CONVERT | STGM_DELETEONRELEASE,
726 STGM_TRANSACTED | STGM_CONVERT,
727 STGM_TRANSACTED | STGM_DELETEONRELEASE,
728 STGM_TRANSACTED | STGM_CONVERT | STGM_DELETEONRELEASE
731 int i, j, k;
733 hShlwapi = LoadLibraryA("shlwapi.dll");
735 pSHCreateStreamOnFileA = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileA");
736 pSHCreateStreamOnFileW = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileW");
737 pSHCreateStreamOnFileEx = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx");
739 if (!pSHCreateStreamOnFileA)
740 skip("SHCreateStreamOnFileA not found.\n");
742 if (!pSHCreateStreamOnFileW)
743 skip("SHCreateStreamOnFileW not found.\n");
745 if (!pSHCreateStreamOnFileEx)
746 skip("SHCreateStreamOnFileEx not found.\n");
748 for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) {
749 for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) {
750 if (pSHCreateStreamOnFileA)
751 test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]);
753 if (pSHCreateStreamOnFileW)
754 test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]);
756 if (pSHCreateStreamOnFileEx) {
757 for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++)
758 test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]);
763 if (pSHCreateStreamOnFileEx) test_SHCreateStreamOnFileEx_CopyTo();