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 static void test_IStream_invalid_operations(IStream * stream, DWORD mode) 38 { 39 HRESULT ret; 40 IStream * clone; 41 ULONG refcount; 42 ULARGE_INTEGER uzero; 43 ULARGE_INTEGER uret; 44 LARGE_INTEGER zero; 45 ULONG count; 46 char data[256]; 47 48 U(uzero).HighPart = 0; 49 U(uzero).LowPart = 0; 50 U(uret).HighPart = 0; 51 U(uret).LowPart = 0; 52 U(zero).HighPart = 0; 53 U(zero).LowPart = 0; 54 55 /* IStream::Read */ 56 57 /* IStream_Read from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Read helper function. */ 58 59 ret = stream->lpVtbl->Read(stream, NULL, 0, &count); 60 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 61 62 ret = stream->lpVtbl->Read(stream, data, 5, NULL); 63 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret); 64 65 ret = stream->lpVtbl->Read(stream, data, 0, NULL); 66 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 67 68 ret = stream->lpVtbl->Read(stream, data, 3, &count); 69 ok(ret == S_FALSE || ret == S_OK, "expected S_FALSE or S_OK, got 0x%08x\n", ret); 70 71 /* IStream::Write */ 72 73 /* IStream_Write from the COBJMACROS is undefined by shlwapi.h, replaced by the IStream_Write helper function. */ 74 75 ret = stream->lpVtbl->Write(stream, NULL, 0, &count); 76 if (mode == STGM_READ) 77 { 78 ok(ret == STG_E_ACCESSDENIED /* XP */ || broken(ret == S_OK) /* Win2000 + IE5 */, 79 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret); 80 } 81 else 82 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 83 84 strcpy(data, "Hello"); 85 ret = stream->lpVtbl->Write(stream, data, 5, NULL); 86 if (mode == STGM_READ) 87 ok(ret == STG_E_ACCESSDENIED, 88 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret); 89 else 90 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 91 92 strcpy(data, "Hello"); 93 ret = stream->lpVtbl->Write(stream, data, 0, NULL); 94 if (mode == STGM_READ) 95 ok(ret == STG_E_ACCESSDENIED, 96 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret); 97 else 98 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 99 100 strcpy(data, "Hello"); 101 ret = stream->lpVtbl->Write(stream, data, 0, &count); 102 if (mode == STGM_READ) 103 ok(ret == STG_E_ACCESSDENIED, 104 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret); 105 else 106 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 107 108 strcpy(data, "Hello"); 109 ret = stream->lpVtbl->Write(stream, data, 3, &count); 110 if (mode == STGM_READ) 111 ok(ret == STG_E_ACCESSDENIED, 112 "expected STG_E_ACCESSDENIED, got 0x%08x\n", ret); 113 else 114 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 115 116 /* IStream::Seek */ 117 118 ret = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 119 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 120 121 ret = IStream_Seek(stream, zero, 20, NULL); 122 ok(ret == E_INVALIDARG, 123 "expected E_INVALIDARG, got 0x%08x\n", ret); 124 125 /* IStream::CopyTo */ 126 127 ret = IStream_CopyTo(stream, NULL, uzero, &uret, &uret); 128 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 129 130 clone = NULL; 131 ret = IStream_CopyTo(stream, clone, uzero, &uret, &uret); 132 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 133 134 ret = IStream_CopyTo(stream, stream, uzero, &uret, &uret); 135 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 136 137 ret = IStream_CopyTo(stream, stream, uzero, &uret, NULL); 138 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 139 140 ret = IStream_CopyTo(stream, stream, uzero, NULL, &uret); 141 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 142 143 /* IStream::Commit */ 144 145 ret = IStream_Commit(stream, STGC_DEFAULT); 146 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 147 148 /* IStream::Revert */ 149 150 ret = IStream_Revert(stream); 151 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret); 152 153 /* IStream::LockRegion */ 154 155 ret = IStream_LockRegion(stream, uzero, uzero, 0); 156 ok(ret == E_NOTIMPL /* XP */ || ret == S_OK /* Vista */, 157 "expected E_NOTIMPL or S_OK, got 0x%08x\n", ret); 158 159 /* IStream::UnlockRegion */ 160 161 if (ret == E_NOTIMPL) /* XP */ { 162 ret = IStream_UnlockRegion(stream, uzero, uzero, 0); 163 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret); 164 } else /* Vista */ { 165 ret = IStream_UnlockRegion(stream, uzero, uzero, 0); 166 ok(ret == S_OK, "expected S_OK, got 0x%08x\n", ret); 167 168 ret = IStream_UnlockRegion(stream, uzero, uzero, 0); 169 ok(ret == STG_E_LOCKVIOLATION, "expected STG_E_LOCKVIOLATION, got 0x%08x\n", ret); 170 } 171 172 /* IStream::Stat */ 173 174 ret = IStream_Stat(stream, NULL, 0); 175 ok(ret == STG_E_INVALIDPOINTER, 176 "expected STG_E_INVALIDPOINTER or E_NOTIMPL, got 0x%08x\n", ret); 177 178 /* IStream::Clone */ 179 180 /* Passing a NULL pointer for the second IStream::Clone param crashes on Win7 */ 181 182 clone = NULL; 183 ret = IStream_Clone(stream, &clone); 184 ok(ret == E_NOTIMPL, "expected E_NOTIMPL, got 0x%08x\n", ret); 185 ok(clone == NULL, "expected a NULL IStream object, got %p\n", stream); 186 187 if (clone) { 188 refcount = IStream_Release(clone); 189 ok(refcount == 0, "expected 0, got %d\n", refcount); 190 } 191 } 192 193 194 static void test_stream_read_write(IStream *stream, DWORD mode) 195 { 196 static const LARGE_INTEGER start; 197 HRESULT ret; 198 unsigned char buf[16]; 199 DWORD written, count; 200 201 /* IStream_Read/Write from the COBJMACROS is undefined by shlwapi.h */ 202 203 written = 0xdeadbeaf; 204 ret = stream->lpVtbl->Write(stream, "\x5e\xa7", 2, &written); 205 if (mode == STGM_WRITE || mode == STGM_READWRITE) 206 { 207 ok(ret == S_OK, "IStream_Write error %#x (access %#x)\n", ret, mode); 208 ok(written == 2, "expected 2, got %u\n", written); 209 } 210 else 211 { 212 ok(ret == STG_E_ACCESSDENIED || broken(ret == S_OK) /* win2000 */, "expected STG_E_ACCESSDENIED, got %#x (access %#x)\n", ret, mode); 213 ok(written == 0xdeadbeaf || broken(written == 2) /* win2000 */, "expected 0xdeadbeaf, got %#x\n", written); 214 written = 0; 215 if (ret == S_OK) return; /* no point in further testing */ 216 } 217 218 ret = stream->lpVtbl->Seek(stream, start, STREAM_SEEK_SET, NULL); 219 ok(ret == S_OK, "Seek error %#x\n", ret); 220 221 count = 0xdeadbeaf; 222 ret = stream->lpVtbl->Read(stream, buf, 2, &count); 223 if (written != 0) 224 { 225 ok(ret == S_OK || broken(ret == S_FALSE) /* win2000 */, "IStream_Read error %#x (access %#x, written %u)\n", ret, mode, written); 226 if (ret == S_OK && (mode == STGM_WRITE || mode == STGM_READWRITE)) 227 { 228 ok(count == 2, "expected 2, got %u\n", count); 229 ok(buf[0] == 0x5e && buf[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf[0], buf[1]); 230 } 231 else 232 ok(count == 0, "expected 0, got %u\n", count); 233 } 234 else 235 { 236 ok(ret == S_FALSE, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret, mode, written); 237 ok(count == 0, "expected 0, got %u\n", count); 238 } 239 240 ret = stream->lpVtbl->Seek(stream, start, STREAM_SEEK_SET, NULL); 241 ok(ret == S_OK, "Seek error %#x\n", ret); 242 243 count = 0xdeadbeaf; 244 ret = stream->lpVtbl->Read(stream, buf, 0, &count); 245 ok(ret == S_OK, "IStream_Read error %#x (access %#x, written %u)\n", ret, mode, written); 246 ok(count == 0, "expected 0, got %u\n", count); 247 248 count = 0xdeadbeaf; 249 ret = stream->lpVtbl->Read(stream, buf, sizeof(buf), &count); 250 ok(ret == S_FALSE, "expected S_FALSE, got %#x (access %#x, written %u)\n", ret, mode, written); 251 ok(count == written, "expected %u, got %u\n", written, count); 252 if (count) 253 ok(buf[0] == 0x5e && buf[1] == 0xa7, "expected 5ea7, got %02x%02x\n", buf[0], buf[1]); 254 } 255 256 static void test_SHCreateStreamOnFileA(DWORD mode, DWORD stgm) 257 { 258 IStream * stream; 259 HRESULT ret; 260 ULONG refcount; 261 char test_file[MAX_PATH]; 262 static const CHAR testA_txt[] = "\\testA.txt"; 263 264 trace("SHCreateStreamOnFileA: testing mode %d, STGM flags %08x\n", mode, stgm); 265 266 /* Don't used a fixed path for the testA.txt file */ 267 GetTempPathA(MAX_PATH, test_file); 268 lstrcatA(test_file, testA_txt); 269 270 /* invalid arguments */ 271 272 stream = NULL; 273 ret = SHCreateStreamOnFileA(NULL, mode | stgm, &stream); 274 if (ret == E_INVALIDARG) /* Win98 SE */ { 275 win_skip("Not supported\n"); 276 return; 277 } 278 279 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) /* NT */ || 280 ret == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME) /* 9x */, 281 "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) " 282 "or HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME), got 0x%08x\n", ret); 283 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream); 284 285 if (0) /* This test crashes on WinXP SP2 */ 286 { 287 ret = SHCreateStreamOnFileA(test_file, mode | stgm, NULL); 288 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret); 289 } 290 291 stream = NULL; 292 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CONVERT | stgm, &stream); 293 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret); 294 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream); 295 296 stream = NULL; 297 ret = SHCreateStreamOnFileA(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream); 298 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret); 299 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream); 300 301 stream = NULL; 302 ret = SHCreateStreamOnFileA(test_file, mode | STGM_TRANSACTED | stgm, &stream); 303 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileA: expected E_INVALIDARG, got 0x%08x\n", ret); 304 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream); 305 306 /* file does not exist */ 307 308 stream = NULL; 309 ret = SHCreateStreamOnFileA(test_file, mode | STGM_FAILIFTHERE | stgm, &stream); 310 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileA: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret); 311 ok(stream == NULL, "SHCreateStreamOnFileA: expected a NULL IStream object, got %p\n", stream); 312 313 stream = NULL; 314 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CREATE | stgm, &stream); 315 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret); 316 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n"); 317 318 if (stream) { 319 test_IStream_invalid_operations(stream, mode); 320 321 refcount = IStream_Release(stream); 322 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount); 323 } 324 325 /* NOTE: don't delete the file, as it will be used for the file exists tests. */ 326 327 /* file exists */ 328 329 stream = NULL; 330 ret = SHCreateStreamOnFileA(test_file, mode | STGM_FAILIFTHERE | stgm, &stream); 331 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret); 332 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n"); 333 334 if (stream) { 335 test_IStream_invalid_operations(stream, mode); 336 337 refcount = IStream_Release(stream); 338 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount); 339 } 340 341 stream = NULL; 342 ret = SHCreateStreamOnFileA(test_file, mode | STGM_CREATE | stgm, &stream); 343 ok(ret == S_OK, "SHCreateStreamOnFileA: expected S_OK, got 0x%08x\n", ret); 344 ok(stream != NULL, "SHCreateStreamOnFileA: expected a valid IStream object, got NULL\n"); 345 346 if (stream) { 347 BOOL delret; 348 349 test_stream_read_write(stream, mode); 350 test_IStream_invalid_operations(stream, mode); 351 352 refcount = IStream_Release(stream); 353 ok(refcount == 0, "SHCreateStreamOnFileA: expected 0, got %d\n", refcount); 354 355 delret = DeleteFileA(test_file); 356 ok(delret, "SHCreateStreamOnFileA: could not delete file '%s', got error %d\n", 357 test_file, GetLastError()); 358 } 359 } 360 361 362 static void test_SHCreateStreamOnFileW(DWORD mode, DWORD stgm) 363 { 364 IStream * stream; 365 HRESULT ret; 366 ULONG refcount; 367 WCHAR test_file[MAX_PATH]; 368 CHAR test_fileA[MAX_PATH]; 369 static const CHAR testW_txt[] = "\\testW.txt"; 370 371 trace("SHCreateStreamOnFileW: testing mode %d, STGM flags %08x\n", mode, stgm); 372 373 /* Don't used a fixed path for the testW.txt file */ 374 GetTempPathA(MAX_PATH, test_fileA); 375 lstrcatA(test_fileA, testW_txt); 376 MultiByteToWideChar(CP_ACP, 0, test_fileA, -1, test_file, MAX_PATH); 377 378 /* invalid arguments */ 379 380 if (0) 381 { 382 /* Crashes on NT4 */ 383 stream = NULL; 384 ret = SHCreateStreamOnFileW(NULL, mode | stgm, &stream); 385 ok(ret == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* XP */ 386 ret == E_INVALIDARG /* Vista */, 387 "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) or E_INVALIDARG, got 0x%08x\n", ret); 388 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream); 389 } 390 391 if (0) 392 { 393 /* This test crashes on WinXP SP2 */ 394 ret = SHCreateStreamOnFileW(test_file, mode | stgm, NULL); 395 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret); 396 } 397 398 stream = NULL; 399 ret = SHCreateStreamOnFileW(test_file, mode | STGM_CONVERT | stgm, &stream); 400 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret); 401 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream); 402 403 stream = NULL; 404 ret = SHCreateStreamOnFileW(test_file, mode | STGM_DELETEONRELEASE | stgm, &stream); 405 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret); 406 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream); 407 408 stream = NULL; 409 ret = SHCreateStreamOnFileW(test_file, mode | STGM_TRANSACTED | stgm, &stream); 410 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileW: expected E_INVALIDARG, got 0x%08x\n", ret); 411 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream); 412 413 /* file does not exist */ 414 415 stream = NULL; 416 ret = SHCreateStreamOnFileW(test_file, mode | STGM_FAILIFTHERE | stgm, &stream); 417 if (ret == E_INVALIDARG) /* Win98 SE */ { 418 win_skip("Not supported\n"); 419 return; 420 } 421 422 ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "SHCreateStreamOnFileW: expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%08x\n", ret); 423 ok(stream == NULL, "SHCreateStreamOnFileW: expected a NULL IStream object, got %p\n", stream); 424 425 stream = NULL; 426 ret = SHCreateStreamOnFileW(test_file, mode | STGM_CREATE | stgm, &stream); 427 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret); 428 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n"); 429 430 if (stream) { 431 test_IStream_invalid_operations(stream, mode); 432 433 refcount = IStream_Release(stream); 434 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount); 435 } 436 437 /* NOTE: don't delete the file, as it will be used for the file exists tests. */ 438 439 /* file exists */ 440 441 stream = NULL; 442 ret = SHCreateStreamOnFileW(test_file, mode | STGM_FAILIFTHERE | stgm, &stream); 443 ok(ret == S_OK, "SHCreateStreamOnFileW: expected S_OK, got 0x%08x\n", ret); 444 ok(stream != NULL, "SHCreateStreamOnFileW: expected a valid IStream object, got NULL\n"); 445 446 if (stream) { 447 test_IStream_invalid_operations(stream, mode); 448 449 refcount = IStream_Release(stream); 450 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount); 451 } 452 453 stream = NULL; 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"); 457 458 if (stream) { 459 BOOL delret; 460 461 test_stream_read_write(stream, mode); 462 test_IStream_invalid_operations(stream, mode); 463 464 refcount = IStream_Release(stream); 465 ok(refcount == 0, "SHCreateStreamOnFileW: expected 0, got %d\n", refcount); 466 467 delret = DeleteFileA(test_fileA); 468 ok(delret, "SHCreateStreamOnFileW: could not delete the test file, got error %d\n", 469 GetLastError()); 470 } 471 } 472 473 474 static void test_SHCreateStreamOnFileEx(DWORD mode, DWORD stgm) 475 { 476 IStream * stream; 477 IStream * template = NULL; 478 HRESULT ret; 479 ULONG refcount; 480 WCHAR test_file[MAX_PATH]; 481 CHAR test_fileA[MAX_PATH]; 482 static const CHAR testEx_txt[] = "\\testEx.txt"; 483 BOOL delret; 484 485 if (winetest_debug > 1) 486 trace("SHCreateStreamOnFileEx: testing mode %d, STGM flags %08x\n", mode, stgm); 487 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); 492 493 /* invalid arguments */ 494 495 if (0) 496 { 497 /* Crashes on NT4 */ 498 stream = NULL; 499 ret = SHCreateStreamOnFileEx(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); 504 } 505 506 stream = NULL; 507 ret = SHCreateStreamOnFileEx(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 = SHCreateStreamOnFileEx(test_file, mode, 0, FALSE, template, &stream); 512 } 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); 517 518 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream); 519 520 if (0) 521 { 522 /* This test crashes on WinXP SP2 */ 523 ret = SHCreateStreamOnFileEx(test_file, mode, 0, FALSE, NULL, NULL); 524 ok(ret == E_INVALIDARG, "SHCreateStreamOnFileEx: expected E_INVALIDARG, got 0x%08x\n", ret); 525 } 526 527 /* file does not exist */ 528 529 stream = NULL; 530 ret = SHCreateStreamOnFileEx(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); 534 535 if (ret == E_INVALIDARG) { 536 skip("SHCreateStreamOnFileEx: STGM_TRANSACTED not supported in this configuration.\n"); 537 return; 538 } 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); 544 } 545 ok(stream == NULL, "SHCreateStreamOnFileEx: expected a NULL IStream object, got %p\n", stream); 546 547 stream = NULL; 548 ret = SHCreateStreamOnFileEx(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; 554 } 555 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"); 558 559 if (stream) { 560 test_IStream_invalid_operations(stream, mode); 561 562 refcount = IStream_Release(stream); 563 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 564 565 delret = DeleteFileA(test_fileA); 566 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n", 567 GetLastError()); 568 } 569 570 stream = NULL; 571 ret = SHCreateStreamOnFileEx(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 = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, FALSE, NULL, &stream); 576 } 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"); 579 580 if (stream) { 581 test_IStream_invalid_operations(stream, mode); 582 583 refcount = IStream_Release(stream); 584 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 585 586 delret = DeleteFileA(test_fileA); 587 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n", 588 GetLastError()); 589 } 590 591 stream = NULL; 592 ret = SHCreateStreamOnFileEx(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 = SHCreateStreamOnFileEx(test_file, mode | STGM_CREATE | stgm, 0, TRUE, NULL, &stream); 597 } 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"); 600 601 if (stream) { 602 test_IStream_invalid_operations(stream, mode); 603 604 refcount = IStream_Release(stream); 605 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 606 } 607 608 /* NOTE: don't delete the file, as it will be used for the file exists tests. */ 609 610 /* file exists */ 611 612 stream = NULL; 613 ret = SHCreateStreamOnFileEx(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"); 616 617 if (stream) { 618 test_IStream_invalid_operations(stream, mode); 619 620 refcount = IStream_Release(stream); 621 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 622 } 623 624 stream = NULL; 625 ret = SHCreateStreamOnFileEx(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); 628 629 stream = NULL; 630 ret = SHCreateStreamOnFileEx(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"); 633 634 if (stream) { 635 test_IStream_invalid_operations(stream, mode); 636 637 refcount = IStream_Release(stream); 638 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 639 } 640 641 stream = NULL; 642 ret = SHCreateStreamOnFileEx(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"); 645 646 if (stream) { 647 test_IStream_invalid_operations(stream, mode); 648 649 refcount = IStream_Release(stream); 650 ok(refcount == 0, "SHCreateStreamOnFileEx: expected 0, got %d\n", refcount); 651 } 652 653 delret = DeleteFileA(test_fileA); 654 ok(delret, "SHCreateStreamOnFileEx: could not delete the test file, got error %d\n", 655 GetLastError()); 656 } 657 658 659 static void test_SHCreateStreamOnFileEx_CopyTo(void) 660 { 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 }; 670 671 GetTempPathW(MAX_PATH, tmpPath); 672 GetTempFileNameW(tmpPath, prefix, 0, srcFileName); 673 GetTempFileNameW(tmpPath, prefix, 0, dstFileName); 674 675 ret = SHCreateStreamOnFileEx(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); 677 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); 681 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); 685 686 ret = SHCreateStreamOnFileEx(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); 688 689 /* Test using a count larger than the source file, so that the Read operation will fall short */ 690 count.QuadPart = 2; 691 692 ret = IStream_CopyTo(src, dst, count, &read, &written); 693 ok(SUCCEEDED(ret), "CopyTo failed with ret=0x%08x\n", ret); 694 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); 697 698 IStream_Release(dst); 699 IStream_Release(src); 700 DeleteFileW( srcFileName ); 701 DeleteFileW( dstFileName ); 702 } 703 704 705 START_TEST(istream) 706 { 707 static const DWORD stgm_access[] = { 708 STGM_READ, 709 STGM_WRITE, 710 STGM_READWRITE 711 }; 712 713 static const DWORD stgm_sharing[] = { 714 0, 715 STGM_SHARE_DENY_NONE, 716 STGM_SHARE_DENY_READ, 717 STGM_SHARE_DENY_WRITE, 718 STGM_SHARE_EXCLUSIVE 719 }; 720 721 static const DWORD stgm_flags[] = { 722 0, 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 729 }; 730 731 int i, j, k; 732 733 for (i = 0; i != sizeof(stgm_access)/sizeof(stgm_access[0]); i++) { 734 for (j = 0; j != sizeof(stgm_sharing)/sizeof(stgm_sharing[0]); j ++) { 735 test_SHCreateStreamOnFileA(stgm_access[i], stgm_sharing[j]); 736 test_SHCreateStreamOnFileW(stgm_access[i], stgm_sharing[j]); 737 738 for (k = 0; k != sizeof(stgm_flags)/sizeof(stgm_flags[0]); k++) 739 test_SHCreateStreamOnFileEx(stgm_access[i], stgm_sharing[j] | stgm_flags[k]); 740 } 741 } 742 743 test_SHCreateStreamOnFileEx_CopyTo(); 744 } 745