65cc66c194d8cb4774a8b098845fe2c811c56776
[reactos.git] / rostests / winetests / shlwapi / istream.c
1 /* Unit test suite for SHLWAPI ShCreateStreamOnFile functions.
2 *
3 * Copyright 2008 Reece H. Dunn
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #define WIN32_NO_STATUS
21 #define _INC_WINDOWS
22 #define COM_NO_WINDOWS_H
23
24 #define COBJMACROS
25
26 //#include <stdarg.h>
27 //#include <stdio.h>
28
29 #include <wine/test.h>
30 //#include "windef.h"
31 //#include "winbase.h"
32 #include <winnls.h>
33 #include <winreg.h>
34 #include <objbase.h>
35 //#include "shlwapi.h"
36
37
38 /* Function pointers for the SHCreateStreamOnFile functions */
39 static HMODULE hShlwapi;
40 static HRESULT (WINAPI *pSHCreateStreamOnFileA)(LPCSTR file, DWORD mode, IStream **stream);
41 static HRESULT (WINAPI *pSHCreateStreamOnFileW)(LPCWSTR file, DWORD mode, IStream **stream);
42 static HRESULT (WINAPI *pSHCreateStreamOnFileEx)(LPCWSTR file, DWORD mode, DWORD attributes, BOOL create, IStream *template, IStream **stream);
43
44
45 static void test_IStream_invalid_operations(IStream * stream, DWORD mode)
46 {
47 HRESULT ret;
48 IStream * clone;
49 ULONG refcount;
50 ULARGE_INTEGER uzero;
51 ULARGE_INTEGER uret;
52 LARGE_INTEGER zero;
53 ULONG count;
54 char data[256];
55
56 U(uzero).HighPart = 0;
57 U(uzero).LowPart = 0;
58 U(uret).HighPart = 0;
59 U(uret).LowPart = 0;
60 U(zero).HighPart = 0;
61 U(zero).LowPart = 0;
62
63 /* IStream::Read */
64
65 /* IStream_Read from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Read helper function. */
66
67 ret = stream->lpVtbl->Read(stream, NULL, 0, &count);
68 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
69
70 ret = stream->lpVtbl->Read(stream, data, 5, NULL);
71 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
72
73 ret = stream->lpVtbl->Read(stream, data, 0, NULL);
74 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
75
76 ret = stream->lpVtbl->Read(stream, data, 3, &count);
77 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret);
78
79 /* IStream::Write */
80
81 /* IStream_Write from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Write helper function. */
82
83 ret = stream->lpVtbl->Write(stream, NULL, 0, &count);
84 if (mode == STGM_READ)
85 ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
86 "expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
87 else
88 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
89
90 strcpy(data, "Hello");
91 ret = stream->lpVtbl->Write(stream, data, 5, NULL);
92 if (mode == STGM_READ)
93 ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
94 "expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
95 else
96 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
97
98 strcpy(data, "Hello");
99 ret = stream->lpVtbl->Write(stream, data, 0, NULL);
100 if (mode == STGM_READ)
101 ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
102 "expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
103 else
104 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
105
106 strcpy(data, "Hello");
107 ret = stream->lpVtbl->Write(stream, data, 0, &count);
108 if (mode == STGM_READ)
109 ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
110 "expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
111 else
112 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
113
114 strcpy(data, "Hello");
115 ret = stream->lpVtbl->Write(stream, data, 3, &count);
116 if (mode == STGM_READ)
117 ok(ret == STG_E_ACCESSDENIED /* XP */ || ret == S_OK /* 2000 */,
118 "expected STG_E_ACCESSDENIED or S_OK, got 0x%08x\n", ret);
119 else
120 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
121
122 /* IStream::Seek */
123
124 ret = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
125 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
126
127 ret = IStream_Seek(stream, zero, 20, NULL);
128 ok(ret == E_INVALIDARG /* XP */ || ret == S_OK /* 2000 */,
129 "expected E_INVALIDARG or S_OK, got 0x%08x\n", ret);
130
131 /* IStream::CopyTo */
132
133 ret = IStream_CopyTo(stream, NULL, uzero, &uret, &uret);
134 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
135
136 clone = NULL;
137 ret = IStream_CopyTo(stream, clone, uzero, &uret, &uret);
138 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
139
140 ret = IStream_CopyTo(stream, stream, uzero, &uret, &uret);
141 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
142
143 ret = IStream_CopyTo(stream, stream, uzero, &uret, NULL);
144 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
145
146 ret = IStream_CopyTo(stream, stream, uzero, NULL, &uret);
147 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
148
149 /* IStream::Commit */
150
151 ret = IStream_Commit(stream, STGC_DEFAULT);
152 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
153
154 /* IStream::Revert */
155
156 ret = IStream_Revert(stream);
157 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
158
159 /* IStream::LockRegion */
160
161 ret = IStream_LockRegion(stream, uzero, uzero, 0);
162 ok(ret == E_NOTIMPL /* XP */ || ret == S_OK /* Vista */,
163 "expected E_NOTIMPL or S_OK, got 0x%08x\n", ret);
164
165 /* IStream::UnlockRegion */
166
167 if (ret == E_NOTIMPL) /* XP */ {
168 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
169 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
170 } else /* Vista */ {
171 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
172 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret);
173
174 ret = IStream_UnlockRegion(stream, uzero, uzero, 0);
175 ok(ret == STG_E_LOCKVIOLATION, "expected STG_E_LOCKVIOLATION, got 0x%08x\n", ret);
176 }
177
178 /* IStream::Stat */
179
180 ret = IStream_Stat(stream, NULL, 0);
181 ok(ret == STG_E_INVALIDPOINTER /* XP */ || ret == E_NOTIMPL /* 2000 */,
182 "expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret);
183
184 /* IStream::Clone */
185
186 /* Passing a NULL pointer for the second IStream::Clone param crashes on Win7 */
187
188 clone = NULL;
189 ret = IStream_Clone(stream, &clone);
190 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret);
191 ok(clone == NULL, "expected a NULL IStream object, got %p\n", stream);
192
193 if (clone) {
194 refcount = IStream_Release(clone);
195 ok(refcount == 0, "expected 0, got %d\n", refcount);
196 }
197 }
198
199
200 static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm)
201 {
202 IStream * stream;
203 HRESULT ret;
204 ULONG refcount;
205 char test_file[MAX_PATH];
206 static const CHAR testA_txt[] = "\\testA.txt";
207
208 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode, stgm);
209
210 /* Don't used a fixed path for the testA.txt file */
211 GetTempPathA(MAX_PATH, test_file);
212 lstrcatA(test_file, testA_txt);
213
214 /* invalid arguments */
215
216 stream = NULL;
217 ret = (*pSHCreateStreamOnFileA)(NULL, mode | stgm, &stream);
218 if (ret == E_INVALIDARG) /* Win98 SE */ {
219 win_skip("Not supported\n");
220 return;
221 }
222
223 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) /* NT */ ||
224 ret == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME) /* 9x */,
225 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) "
226 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret);
227 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
228
229 #if 0 /* This test crashes on WinXP SP2 */
230 ret = (*pSHCreateStreamOnFileA)(test_file, mode | stgm, NULL);
231 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
232 #endif
233
234 stream = NULL;
235 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CONVERT | stgm, &stream);
236 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
237 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
238
239 stream = NULL;
240 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
241 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
242 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
243
244 stream = NULL;
245 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
246 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret);
247 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
248
249 /* file does not exist */
250
251 stream = NULL;
252 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
253 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
254 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream);
255
256 stream = NULL;
257 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | stgm, &stream);
258 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
259 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
260
261 if (stream) {
262 test_IStream_invalid_operations(stream, mode);
263
264 refcount = IStream_Release(stream);
265 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
266 }
267
268 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
269
270 /* file exists */
271
272 stream = NULL;
273 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
274 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
275 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
276
277 if (stream) {
278 test_IStream_invalid_operations(stream, mode);
279
280 refcount = IStream_Release(stream);
281 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
282 }
283
284 stream = NULL;
285 ret = (*pSHCreateStreamOnFileA)(test_file, mode | STGM_CREATE | stgm, &stream);
286 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret);
287 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n");
288
289 if (stream) {
290 BOOL delret;
291 test_IStream_invalid_operations(stream, mode);
292
293 refcount = IStream_Release(stream);
294 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount);
295
296 delret = DeleteFileA(test_file);
297 ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n",
298 test_file, GetLastError());
299 }
300 }
301
302
303 static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm)
304 {
305 IStream * stream;
306 HRESULT ret;
307 ULONG refcount;
308 WCHAR test_file[MAX_PATH];
309 CHAR test_fileA[MAX_PATH];
310 static const CHAR testW_txt[] = "\\testW.txt";
311
312 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode, stgm);
313
314 /* Don't used a fixed path for the testW.txt file */
315 GetTempPathA(MAX_PATH, test_fileA);
316 lstrcatA(test_fileA, testW_txt);
317 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
318
319 /* invalid arguments */
320
321 if (0)
322 {
323 /* Crashes on NT4 */
324 stream = NULL;
325 ret = (*pSHCreateStreamOnFileW)(NULL, mode | stgm, &stream);
326 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
327 ret == E_INVALIDARG /* Vista */,
328 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
329 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
330 }
331
332 if (0)
333 {
334 /* This test crashes on WinXP SP2 */
335 ret = (*pSHCreateStreamOnFileW)(test_file, mode | stgm, NULL);
336 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
337 }
338
339 stream = NULL;
340 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CONVERT | stgm, &stream);
341 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
342 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
343
344 stream = NULL;
345 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream);
346 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
347 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
348
349 stream = NULL;
350 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_TRANSACTED | stgm, &stream);
351 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret);
352 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
353
354 /* file does not exist */
355
356 stream = NULL;
357 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
358 if (ret == E_INVALIDARG) /* Win98 SE */ {
359 win_skip("Not supported\n");
360 return;
361 }
362
363 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
364 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream);
365
366 stream = NULL;
367 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | stgm, &stream);
368 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
369 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
370
371 if (stream) {
372 test_IStream_invalid_operations(stream, mode);
373
374 refcount = IStream_Release(stream);
375 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
376 }
377
378 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
379
380 /* file exists */
381
382 stream = NULL;
383 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_FAILIFTHERE | stgm, &stream);
384 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
385 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
386
387 if (stream) {
388 test_IStream_invalid_operations(stream, mode);
389
390 refcount = IStream_Release(stream);
391 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
392 }
393
394 stream = NULL;
395 ret = (*pSHCreateStreamOnFileW)(test_file, mode | STGM_CREATE | stgm, &stream);
396 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret);
397 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n");
398
399 if (stream) {
400 BOOL delret;
401 test_IStream_invalid_operations(stream, mode);
402
403 refcount = IStream_Release(stream);
404 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount);
405
406 delret = DeleteFileA(test_fileA);
407 ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n",
408 GetLastError());
409 }
410 }
411
412
413 static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm)
414 {
415 IStream * stream;
416 IStream * template = NULL;
417 HRESULT ret;
418 ULONG refcount;
419 WCHAR test_file[MAX_PATH];
420 CHAR test_fileA[MAX_PATH];
421 static const CHAR testEx_txt[] = "\\testEx.txt";
422 BOOL delret;
423
424 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm);
425
426 /* Don't used a fixed path for the testEx.txt file */
427 GetTempPathA(MAX_PATH, test_fileA);
428 lstrcatA(test_fileA, testEx_txt);
429 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH);
430
431 /* invalid arguments */
432
433 if (0)
434 {
435 /* Crashes on NT4 */
436 stream = NULL;
437 ret = (*pSHCreateStreamOnFileEx)(NULL, mode, 0, FALSE, NULL, &stream);
438 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */
439 ret == E_INVALIDARG /* Vista */,
440 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret);
441 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
442 }
443
444 stream = NULL;
445 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
446 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
447 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
448 Sleep(1000);
449 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, template, &stream);
450 }
451 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
452 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
453 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
454 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
455
456 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
457
458 if (0)
459 {
460 /* This test crashes on WinXP SP2 */
461 ret = (*pSHCreateStreamOnFileEx)(test_file, mode, 0, FALSE, NULL, NULL);
462 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret);
463 }
464
465 /* file does not exist */
466
467 stream = NULL;
468 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
469 if ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED && mode == STGM_READ) {
470 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* XP */ || ret == E_INVALIDARG /* Vista */,
471 "SHCreateStreamOnFileEx: expected E_INVALIDARG or HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret);
472
473 if (ret == E_INVALIDARG) {
474 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n");
475 return;
476 }
477 } else {
478 ok( ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
479 ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
480 "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) or "
481 "HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got 0x%08x\n", ret);
482 }
483 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
484
485 stream = NULL;
486 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
487 /* not supported on win9x */
488 if (broken(ret == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) && stream == NULL)) {
489 skip("Not supported\n");
490 DeleteFileA(test_fileA);
491 return;
492 }
493
494 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
495 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
496
497 if (stream) {
498 test_IStream_invalid_operations(stream, mode);
499
500 refcount = IStream_Release(stream);
501 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
502
503 delret = DeleteFileA(test_fileA);
504 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
505 GetLastError());
506 }
507
508 stream = NULL;
509 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
510 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
511 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
512 Sleep(1000);
513 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
514 }
515 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
516 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
517
518 if (stream) {
519 test_IStream_invalid_operations(stream, mode);
520
521 refcount = IStream_Release(stream);
522 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
523
524 delret = DeleteFileA(test_fileA);
525 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
526 GetLastError());
527 }
528
529 stream = NULL;
530 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
531 if (ret == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) {
532 win_skip("File probably locked by Anti-Virus/Spam software, trying again\n");
533 Sleep(1000);
534 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
535 }
536 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
537 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
538
539 if (stream) {
540 test_IStream_invalid_operations(stream, mode);
541
542 refcount = IStream_Release(stream);
543 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
544 }
545
546 /* NOTE: don't delete the file, as it will be used for the file exists tests. */
547
548 /* file exists */
549
550 stream = NULL;
551 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, FALSE, NULL, &stream);
552 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
553 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
554
555 if (stream) {
556 test_IStream_invalid_operations(stream, mode);
557
558 refcount = IStream_Release(stream);
559 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
560 }
561
562 stream = NULL;
563 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_FAILIFTHERE | stgm, 0, TRUE, NULL, &stream);
564 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "SHCreateStreamOnFileEx: expected HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), got 0x%08x\n", ret);
565 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream);
566
567 stream = NULL;
568 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream);
569 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
570 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
571
572 if (stream) {
573 test_IStream_invalid_operations(stream, mode);
574
575 refcount = IStream_Release(stream);
576 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
577 }
578
579 stream = NULL;
580 ret = (*pSHCreateStreamOnFileEx)(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream);
581 ok(ret == S_OK, "SHCreateStreamOnFileEx: expected S_OK, got 0x%08x\n", ret);
582 ok(stream != NULL, "SHCreateStreamOnFileEx: expected a valid IStream object, got NULL\n");
583
584 if (stream) {
585 test_IStream_invalid_operations(stream, mode);
586
587 refcount = IStream_Release(stream);
588 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount);
589 }
590
591 delret = DeleteFileA(test_fileA);
592 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n",
593 GetLastError());
594 }
595
596
597 START_TEST(istream)
598 {
599 static const DWORD stgm_access[] = {
600 STGM_READ,
601 STGM_WRITE,
602 STGM_READWRITE
603 };
604
605 static const DWORD stgm_sharing[] = {
606 0,
607 STGM_SHARE_DENY_NONE,
608 STGM_SHARE_DENY_READ,
609 STGM_SHARE_DENY_WRITE,
610 STGM_SHARE_EXCLUSIVE
611 };
612
613 static const DWORD stgm_flags[] = {
614 0,
615 STGM_CONVERT,
616 STGM_DELETEONRELEASE,
617 STGM_CONVERT | STGM_DELETEONRELEASE,
618 STGM_TRANSACTED | STGM_CONVERT,
619 STGM_TRANSACTED | STGM_DELETEONRELEASE,
620 STGM_TRANSACTED | STGM_CONVERT | STGM_DELETEONRELEASE
621 };
622
623 int i, j, k;
624
625 hShlwapi = GetModuleHandleA("shlwapi.dll");
626
627 pSHCreateStreamOnFileA = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileA");
628 pSHCreateStreamOnFileW = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileW");
629 pSHCreateStreamOnFileEx = (void*)GetProcAddress(hShlwapi, "SHCreateStreamOnFileEx");
630
631 if (!pSHCreateStreamOnFileA)
632 skip("SHCreateStreamOnFileA not found.\n");
633
634 if (!pSHCreateStreamOnFileW)
635 skip("SHCreateStreamOnFileW not found.\n");
636
637 if (!pSHCreateStreamOnFileEx)
638 skip("SHCreateStreamOnFileEx not found.\n");
639
640 for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) {
641 for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) {
642 if (pSHCreateStreamOnFileA)
643 test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]);
644
645 if (pSHCreateStreamOnFileW)
646 test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]);
647
648 if (pSHCreateStreamOnFileEx) {
649 for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++)
650 test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]);
651 }
652 }
653 }
654 }