1 /* 2 * Unit tests for OLE storage 3 * 4 * Copyright (c) 2004 Mike McCormack 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 #include <initguid.h> 24 25 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0); 26 27 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr) 28 29 static CHAR filenameA[MAX_PATH]; 30 static WCHAR filename[MAX_PATH]; 31 32 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0}; 33 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0}; 34 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0}; 35 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0}; 36 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0}; 37 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0}; 38 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0}; 39 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0}; 40 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0}; 41 42 /* Win9x and WinMe don't have lstrcmpW */ 43 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2) 44 { 45 CHAR stra1[512], stra2[512]; 46 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL); 47 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL); 48 return lstrcmpA(stra1, stra2); 49 } 50 51 typedef struct TestLockBytes { 52 ILockBytes ILockBytes_iface; 53 LONG ref; 54 BYTE* contents; 55 ULONG size; 56 ULONG buffer_size; 57 HRESULT lock_hr; 58 ULONG locks_supported; 59 ULONG lock_called; 60 } TestLockBytes; 61 62 static inline TestLockBytes *impl_from_ILockBytes(ILockBytes *iface) 63 { 64 return CONTAINING_RECORD(iface, TestLockBytes, ILockBytes_iface); 65 } 66 67 static HRESULT WINAPI TestLockBytes_QueryInterface(ILockBytes *iface, REFIID iid, 68 void **ppv) 69 { 70 TestLockBytes *This = impl_from_ILockBytes(iface); 71 72 if (!ppv) return E_INVALIDARG; 73 74 if (IsEqualIID(&IID_IUnknown, iid) || 75 IsEqualIID(&IID_ILockBytes, iid)) 76 *ppv = &This->ILockBytes_iface; 77 else 78 return E_NOINTERFACE; 79 80 IUnknown_AddRef((IUnknown*)*ppv); 81 return S_OK; 82 } 83 84 static ULONG WINAPI TestLockBytes_AddRef(ILockBytes *iface) 85 { 86 TestLockBytes *This = impl_from_ILockBytes(iface); 87 ULONG ref = InterlockedIncrement(&This->ref); 88 return ref; 89 } 90 91 static ULONG WINAPI TestLockBytes_Release(ILockBytes *iface) 92 { 93 TestLockBytes *This = impl_from_ILockBytes(iface); 94 ULONG ref = InterlockedDecrement(&This->ref); 95 return ref; 96 } 97 98 static HRESULT WINAPI TestLockBytes_ReadAt(ILockBytes *iface, 99 ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead) 100 { 101 TestLockBytes *This = impl_from_ILockBytes(iface); 102 ULONG dummy; 103 104 if (!pv) return E_INVALIDARG; 105 106 if (!pcbRead) pcbRead = &dummy; 107 108 if (ulOffset.QuadPart >= This->size) 109 { 110 *pcbRead = 0; 111 return S_OK; 112 } 113 114 cb = min(cb, This->size - ulOffset.QuadPart); 115 116 *pcbRead = cb; 117 memcpy(pv, &This->contents[ulOffset.QuadPart], cb); 118 119 return S_OK; 120 } 121 122 static HRESULT WINAPI TestLockBytes_WriteAt(ILockBytes *iface, 123 ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten) 124 { 125 TestLockBytes *This = impl_from_ILockBytes(iface); 126 HRESULT hr; 127 ULONG dummy; 128 129 if (!pv) return E_INVALIDARG; 130 131 if (!pcbWritten) pcbWritten = &dummy; 132 133 if (ulOffset.QuadPart + cb > This->size) 134 { 135 ULARGE_INTEGER new_size; 136 new_size.QuadPart = ulOffset.QuadPart + cb; 137 hr = ILockBytes_SetSize(iface, new_size); 138 if (FAILED(hr)) return hr; 139 } 140 141 *pcbWritten = cb; 142 memcpy(&This->contents[ulOffset.QuadPart], pv, cb); 143 144 return S_OK; 145 } 146 147 static HRESULT WINAPI TestLockBytes_Flush(ILockBytes *iface) 148 { 149 return S_OK; 150 } 151 152 static HRESULT WINAPI TestLockBytes_SetSize(ILockBytes *iface, 153 ULARGE_INTEGER cb) 154 { 155 TestLockBytes *This = impl_from_ILockBytes(iface); 156 157 if (This->buffer_size < cb.QuadPart) 158 { 159 ULONG new_buffer_size = max(This->buffer_size * 2, cb.QuadPart); 160 BYTE* new_buffer = HeapAlloc(GetProcessHeap(), 0, new_buffer_size); 161 if (!new_buffer) return E_OUTOFMEMORY; 162 memcpy(new_buffer, This->contents, This->size); 163 HeapFree(GetProcessHeap(), 0, This->contents); 164 This->contents = new_buffer; 165 } 166 167 if (cb.QuadPart > This->size) 168 memset(&This->contents[This->size], 0, cb.QuadPart - This->size); 169 170 This->size = cb.QuadPart; 171 172 return S_OK; 173 } 174 175 static HRESULT WINAPI TestLockBytes_LockRegion(ILockBytes *iface, 176 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 177 { 178 TestLockBytes *This = impl_from_ILockBytes(iface); 179 This->lock_called++; 180 return This->lock_hr; 181 } 182 183 static HRESULT WINAPI TestLockBytes_UnlockRegion(ILockBytes *iface, 184 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 185 { 186 TestLockBytes *This = impl_from_ILockBytes(iface); 187 return This->lock_hr; 188 } 189 190 static HRESULT WINAPI TestLockBytes_Stat(ILockBytes *iface, 191 STATSTG *pstatstg, DWORD grfStatFlag) 192 { 193 TestLockBytes *This = impl_from_ILockBytes(iface); 194 static const WCHAR dummy_name[] = {'d','u','m','m','y',0}; 195 196 if (!pstatstg) return E_INVALIDARG; 197 198 memset(pstatstg, 0, sizeof(STATSTG)); 199 200 if (!(grfStatFlag & STATFLAG_NONAME)) 201 { 202 pstatstg->pwcsName = CoTaskMemAlloc(sizeof(dummy_name)); 203 if (!pstatstg->pwcsName) return E_OUTOFMEMORY; 204 memcpy(pstatstg->pwcsName, dummy_name, sizeof(dummy_name)); 205 } 206 207 pstatstg->type = STGTY_LOCKBYTES; 208 pstatstg->cbSize.QuadPart = This->size; 209 pstatstg->grfLocksSupported = This->locks_supported; 210 211 return S_OK; 212 } 213 214 static /* const */ ILockBytesVtbl TestLockBytes_Vtbl = { 215 TestLockBytes_QueryInterface, 216 TestLockBytes_AddRef, 217 TestLockBytes_Release, 218 TestLockBytes_ReadAt, 219 TestLockBytes_WriteAt, 220 TestLockBytes_Flush, 221 TestLockBytes_SetSize, 222 TestLockBytes_LockRegion, 223 TestLockBytes_UnlockRegion, 224 TestLockBytes_Stat 225 }; 226 227 static void CreateTestLockBytes(TestLockBytes **This) 228 { 229 *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**This)); 230 231 if (*This) 232 { 233 (*This)->ILockBytes_iface.lpVtbl = &TestLockBytes_Vtbl; 234 (*This)->ref = 1; 235 } 236 } 237 238 static void DeleteTestLockBytes(TestLockBytes *This) 239 { 240 ok(This->ILockBytes_iface.lpVtbl == &TestLockBytes_Vtbl, "test lock bytes %p deleted with incorrect vtable\n", This); 241 ok(This->ref == 1, "test lock bytes %p deleted with %i references instead of 1\n", This, This->ref); 242 HeapFree(GetProcessHeap(), 0, This->contents); 243 HeapFree(GetProcessHeap(), 0, This); 244 } 245 246 static void test_hglobal_storage_stat(void) 247 { 248 ILockBytes *ilb = NULL; 249 IStorage *stg = NULL; 250 HRESULT r; 251 STATSTG stat; 252 DWORD mode, refcount; 253 254 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb ); 255 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n"); 256 257 r = StgIsStorageILockBytes( ilb ); 258 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n"); 259 260 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/ 261 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg ); 262 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n"); 263 264 r = WriteClassStg( stg, &test_stg_cls ); 265 ok( r == S_OK, "WriteClassStg failed\n"); 266 267 r = StgIsStorageILockBytes( ilb ); 268 ok( r == S_OK, "StgIsStorageILockBytes failed\n"); 269 270 memset( &stat, 0, sizeof stat ); 271 r = IStorage_Stat( stg, &stat, 0 ); 272 273 ok( stat.pwcsName == NULL, "storage name not null\n"); 274 ok( stat.type == 1, "type is wrong\n"); 275 ok( stat.grfMode == 0x12, "grf mode is incorrect\n"); 276 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n"); 277 278 refcount = IStorage_Release( stg ); 279 ok( refcount == 0, "IStorage refcount is wrong\n"); 280 refcount = ILockBytes_Release( ilb ); 281 ok( refcount == 0, "ILockBytes refcount is wrong\n"); 282 } 283 284 static void test_create_storage_modes(void) 285 { 286 IStorage *stg = NULL; 287 HRESULT r; 288 289 DeleteFileA(filenameA); 290 291 /* test with some invalid parameters */ 292 r = StgCreateDocfile( NULL, 0, 0, &stg); 293 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 294 r = StgCreateDocfile( filename, 0, 0, &stg); 295 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 296 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg); 297 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 298 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg); 299 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 300 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg); 301 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 302 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL); 303 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n"); 304 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg); 305 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n"); 306 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg); 307 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 308 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg); 309 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 310 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg); 311 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 312 313 /* StgCreateDocfile seems to be very particular about the flags it accepts */ 314 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg); 315 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 316 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg); 317 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 318 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg); 319 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 320 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg); 321 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 322 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg); 323 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 324 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg); 325 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 326 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg); 327 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 328 ok(stg == NULL, "stg was set\n"); 329 330 /* check what happens if the file already exists (which is how it's meant to be used) */ 331 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 332 ok(r==S_OK, "StgCreateDocfile failed\n"); 333 r = IStorage_Release(stg); 334 ok(r == 0, "storage not released\n"); 335 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 336 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */ 337 r = StgCreateDocfile( filename, STGM_READ, 0, &stg); 338 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */ 339 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg); 340 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 341 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg); 342 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 343 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg); 344 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n"); 345 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg); 346 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n"); 347 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg); 348 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n"); 349 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg); 350 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n"); 351 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg); 352 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n"); 353 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg); 354 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n"); 355 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg); 356 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n"); 357 ok(DeleteFileA(filenameA), "failed to delete file\n"); 358 359 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 360 ok(r==S_OK, "StgCreateDocfile failed\n"); 361 r = IStorage_Release(stg); 362 ok(r == 0, "storage not released\n"); 363 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg); 364 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); 365 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg); 366 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); 367 368 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg); 369 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); 370 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 371 ok(r==S_OK, "StgCreateDocfile failed\n"); 372 r = IStorage_Release(stg); 373 ok(r == 0, "storage not released\n"); 374 ok(DeleteFileA(filenameA), "failed to delete file\n"); 375 376 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 377 ok(r==S_OK, "StgCreateDocfile failed\n"); 378 r = IStorage_Release(stg); 379 ok(r == 0, "storage not released\n"); 380 ok(DeleteFileA(filenameA), "failed to delete file\n"); 381 382 /* test the way excel uses StgCreateDocFile */ 383 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg); 384 ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); 385 if(r == S_OK) 386 { 387 r = IStorage_Release(stg); 388 ok(r == 0, "storage not released\n"); 389 ok(DeleteFileA(filenameA), "failed to delete file\n"); 390 } 391 392 /* and the way windows media uses it ... */ 393 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg); 394 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n"); 395 if (r == S_OK) 396 { 397 r = IStorage_Release(stg); 398 ok(r == 0, "storage not released\n"); 399 ok(DeleteFileA(filenameA), "failed to delete file\n"); 400 } 401 402 /* looks like we need STGM_TRANSACTED or STGM_CREATE */ 403 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg); 404 ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); 405 if(r == S_OK) 406 { 407 r = IStorage_Release(stg); 408 ok(r == 0, "storage not released\n"); 409 ok(DeleteFileA(filenameA), "failed to delete file\n"); 410 } 411 412 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg); 413 ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); 414 if(r == S_OK) 415 { 416 r = IStorage_Release(stg); 417 ok(r == 0, "storage not released\n"); 418 ok(DeleteFileA(filenameA), "failed to delete file\n"); 419 } 420 421 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 422 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n"); 423 if(r == S_OK) 424 { 425 r = IStorage_Release(stg); 426 ok(r == 0, "storage not released\n"); 427 ok(DeleteFileA(filenameA), "failed to delete file\n"); 428 } 429 430 /* test the way msi uses StgCreateDocfile */ 431 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg); 432 ok(r==S_OK, "StgCreateDocFile failed\n"); 433 r = IStorage_Release(stg); 434 ok(r == 0, "storage not released\n"); 435 ok(DeleteFileA(filenameA), "failed to delete file\n"); 436 } 437 438 static void test_stgcreatestorageex(void) 439 { 440 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen); 441 HMODULE hOle32 = GetModuleHandleA("ole32"); 442 IStorage *stg = NULL; 443 STGOPTIONS stgoptions = {1, 0, 4096}; 444 HRESULT r; 445 446 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx"); 447 if (!pStgCreateStorageEx) 448 { 449 win_skip("skipping test on NT4\n"); 450 return; 451 } 452 453 DeleteFileA(filenameA); 454 455 /* Verify that StgCreateStorageEx can accept an options param */ 456 r = pStgCreateStorageEx( filename, 457 STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 458 STGFMT_DOCFILE, 459 0, 460 &stgoptions, 461 NULL, 462 &IID_IStorage, 463 (void **) &stg); 464 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n"); 465 if (r==STG_E_UNIMPLEMENTEDFUNCTION) 466 { 467 /* We're on win98 which means all bets are off. Let's get out of here. */ 468 win_skip("skipping test on win9x\n"); 469 return; 470 } 471 472 r = IStorage_Release(stg); 473 ok(r == 0, "storage not released\n"); 474 ok(DeleteFileA(filenameA), "failed to delete file\n"); 475 476 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */ 477 r = pStgCreateStorageEx( filename, 478 STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 479 STGFMT_STORAGE, 480 0, 481 NULL, 482 NULL, 483 &IID_IStorage, 484 (void **) &stg); 485 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n"); 486 r = IStorage_Release(stg); 487 ok(r == 0, "storage not released\n"); 488 ok(DeleteFileA(filenameA), "failed to delete file\n"); 489 } 490 491 static void test_storage_stream(void) 492 { 493 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 494 static const WCHAR longname[] = { 495 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', 496 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0 497 }; 498 IStorage *stg = NULL; 499 HRESULT r; 500 IStream *stm = NULL; 501 IStream *stm2 = NULL; 502 ULONG count = 0; 503 LARGE_INTEGER pos; 504 ULARGE_INTEGER p; 505 unsigned char buffer[0x100]; 506 IUnknown *unk; 507 BOOL ret; 508 509 DeleteFileA(filenameA); 510 511 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 512 ok(r==S_OK, "StgCreateDocfile failed\n"); 513 514 /* try create some invalid streams */ 515 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm ); 516 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n"); 517 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm ); 518 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n"); 519 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL ); 520 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n"); 521 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 522 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n"); 523 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 524 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */, 525 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError()); 526 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm ); 527 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n"); 528 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm ); 529 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n"); 530 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm ); 531 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n"); 532 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm ); 533 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n"); 534 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm ); 535 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n"); 536 537 /* now really create a stream and delete it */ 538 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 539 ok(r==S_OK, "IStorage->CreateStream failed\n"); 540 541 /* test for support interfaces */ 542 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk); 543 ok(r==E_NOINTERFACE, "got 0x%08x\n", r); 544 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk); 545 ok(r==E_NOINTERFACE, "got 0x%08x\n", r); 546 547 r = IStream_Release(stm); 548 ok(r == 0, "wrong ref count\n"); 549 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 550 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n"); 551 r = IStorage_DestroyElement(stg,stmname); 552 ok(r==S_OK, "IStorage->DestroyElement failed\n"); 553 554 /* create a stream and write to it */ 555 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 556 ok(r==S_OK, "IStorage->CreateStream failed\n"); 557 558 r = IStream_Clone(stm, &stm2); 559 ok(r==S_OK, "failed to clone stream\n"); 560 561 r = IStream_Write(stm, NULL, 0, NULL ); 562 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n"); 563 r = IStream_Write(stm, "Hello\n", 0, NULL ); 564 ok(r==S_OK, "failed to write stream\n"); 565 r = IStream_Write(stm, "Hello\n", 0, &count ); 566 ok(r==S_OK, "failed to write stream\n"); 567 r = IStream_Write(stm, "Hello\n", 6, &count ); 568 ok(r==S_OK, "failed to write stream\n"); 569 r = IStream_Commit(stm, STGC_DEFAULT ); 570 ok(r==S_OK, "failed to commit stream\n"); 571 r = IStream_Commit(stm, STGC_DEFAULT ); 572 ok(r==S_OK, "failed to commit stream\n"); 573 574 /* Read past the end of the stream. */ 575 pos.QuadPart = 3; 576 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 577 ok(r==S_OK, "failed to seek stream\n"); 578 ok(p.QuadPart == 3, "at wrong place\n"); 579 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 580 ok(r==S_OK, "failed to read\n"); 581 ok(count == 3, "read bytes past end of stream\n"); 582 pos.QuadPart = 10; 583 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 584 ok(r==S_OK, "failed to seek stream\n"); 585 ok(p.QuadPart == 10, "at wrong place\n"); 586 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 587 ok(r==S_OK, "failed to read\n"); 588 ok(count == 0, "read bytes past end of stream\n"); 589 pos.QuadPart = 10000; 590 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 591 ok(r==S_OK, "failed to seek stream\n"); 592 ok(p.QuadPart == 10000, "at wrong place\n"); 593 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 594 ok(r==S_OK, "failed to read\n"); 595 ok(count == 0, "read bytes past end of stream\n"); 596 597 /* Convert to a big block stream, and read past the end. */ 598 p.QuadPart = 5000; 599 r = IStream_SetSize(stm,p); 600 ok(r==S_OK, "failed to set pos\n"); 601 pos.QuadPart = 4997; 602 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 603 ok(r==S_OK, "failed to seek stream\n"); 604 ok(p.QuadPart == 4997, "at wrong place\n"); 605 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 606 ok(r==S_OK, "failed to read\n"); 607 ok(count == 3, "read bytes past end of stream\n"); 608 pos.QuadPart = 5001; 609 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 610 ok(r==S_OK, "failed to seek stream\n"); 611 ok(p.QuadPart == 5001, "at wrong place\n"); 612 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 613 ok(r==S_OK, "failed to read\n"); 614 ok(count == 0, "read bytes past end of stream\n"); 615 pos.QuadPart = 10000; 616 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 617 ok(r==S_OK, "failed to seek stream\n"); 618 ok(p.QuadPart == 10000, "at wrong place\n"); 619 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 620 ok(r==S_OK, "failed to read\n"); 621 ok(count == 0, "read bytes past end of stream\n"); 622 623 /* seek round a bit, reset the stream size */ 624 pos.QuadPart = 0; 625 r = IStream_Seek(stm, pos, 3, &p ); 626 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n"); 627 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL); 628 ok(r==S_OK, "failed to seek stream\n"); 629 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 630 ok(r==S_OK, "failed to seek stream\n"); 631 r = IStream_SetSize(stm,p); 632 ok(r==S_OK, "failed to set pos\n"); 633 pos.QuadPart = 10; 634 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 635 ok(r==S_OK, "failed to seek stream\n"); 636 ok(p.QuadPart == 10, "at wrong place\n"); 637 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 638 ok(r==S_OK, "failed to set pos\n"); 639 ok(count == 0, "read bytes from empty stream\n"); 640 pos.QuadPart = 10000; 641 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); 642 ok(r==S_OK, "failed to seek stream\n"); 643 ok(p.QuadPart == 10000, "at wrong place\n"); 644 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 645 ok(r==S_OK, "failed to set pos\n"); 646 ok(count == 0, "read bytes from empty stream\n"); 647 pos.QuadPart = 0; 648 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p ); 649 ok(r==S_OK, "failed to seek stream\n"); 650 ok(p.QuadPart == 0, "at wrong place\n"); 651 r = IStream_Read(stm, buffer, sizeof buffer, &count ); 652 ok(r==S_OK, "failed to set pos\n"); 653 ok(count == 0, "read bytes from empty stream\n"); 654 655 /* wrap up */ 656 r = IStream_Release(stm2); 657 ok(r == 0, "wrong ref count\n"); 658 659 /* create a stream and write to it */ 660 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 ); 661 ok(r==S_OK, "IStorage->CreateStream failed\n"); 662 663 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p); 664 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r); 665 666 r = IStream_Release(stm2); 667 ok(r == 0, "wrong ref count\n"); 668 r = IStream_Release(stm); 669 ok(r == 0, "wrong ref count\n"); 670 671 r = IStorage_Release(stg); 672 ok(r == 0, "wrong ref count\n"); 673 674 /* try create some invalid streams */ 675 stg = NULL; 676 stm = NULL; 677 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 678 ok(r == S_OK, "should succeed\n"); 679 if (stg) 680 { 681 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm); 682 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r); 683 IStorage_Release(stg); 684 } 685 686 ret = DeleteFileA(filenameA); 687 ok(ret, "file should exist\n"); 688 } 689 690 static BOOL touch_file(LPCSTR filename) 691 { 692 HANDLE file; 693 694 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, 695 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 696 if (file==INVALID_HANDLE_VALUE) 697 return FALSE; 698 CloseHandle(file); 699 return TRUE; 700 } 701 702 static BOOL is_zero_length(LPCSTR filename) 703 { 704 HANDLE file; 705 DWORD len; 706 707 file = CreateFileA(filename, GENERIC_READ, 0, NULL, 708 OPEN_EXISTING, 0, NULL); 709 if (file==INVALID_HANDLE_VALUE) 710 return FALSE; 711 len = GetFileSize(file, NULL); 712 CloseHandle(file); 713 return len == 0; 714 } 715 716 static BOOL is_existing_file(LPCSTR filename) 717 { 718 HANDLE file; 719 720 file = CreateFileA(filename, GENERIC_READ, 0, NULL, 721 OPEN_EXISTING, 0, NULL); 722 if (file==INVALID_HANDLE_VALUE) 723 return FALSE; 724 CloseHandle(file); 725 return TRUE; 726 } 727 728 static void test_open_storage(void) 729 { 730 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 }; 731 IStorage *stg = NULL, *stg2 = NULL; 732 HRESULT r; 733 DWORD stgm; 734 BOOL ret; 735 736 /* try opening a zero length file - it should stay zero length */ 737 DeleteFileA(filenameA); 738 touch_file(filenameA); 739 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE; 740 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg); 741 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n"); 742 743 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE; 744 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg); 745 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n"); 746 ok(is_zero_length(filenameA), "file length changed\n"); 747 748 DeleteFileA(filenameA); 749 750 /* try opening a nonexistent file - it should not create it */ 751 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE; 752 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg); 753 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r); 754 if (r==S_OK) IStorage_Release(stg); 755 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n"); 756 DeleteFileA(filenameA); 757 758 /* create the file */ 759 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 760 ok(r==S_OK, "StgCreateDocfile failed\n"); 761 IStorage_Release(stg); 762 763 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg); 764 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n"); 765 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); 766 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n"); 767 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL); 768 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n"); 769 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg); 770 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n"); 771 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg); 772 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n"); 773 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg); 774 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n"); 775 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg); 776 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n"); 777 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg); 778 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n"); 779 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg); 780 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n"); 781 782 /* open it for real */ 783 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */ 784 ok(r==S_OK, "StgOpenStorage failed\n"); 785 if(stg) 786 { 787 r = IStorage_Release(stg); 788 ok(r == 0, "wrong ref count\n"); 789 } 790 791 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg); 792 ok(r==S_OK, "StgOpenStorage failed\n"); 793 if(stg) 794 { 795 r = IStorage_Release(stg); 796 ok(r == 0, "wrong ref count\n"); 797 } 798 799 /* test the way word opens its custom dictionary */ 800 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED | 801 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg); 802 ok(r==S_OK, "StgOpenStorage failed\n"); 803 if(stg) 804 { 805 r = IStorage_Release(stg); 806 ok(r == 0, "wrong ref count\n"); 807 } 808 809 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg); 810 ok(r==S_OK, "StgOpenStorage failed\n"); 811 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2); 812 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n"); 813 if(stg) 814 { 815 r = IStorage_Release(stg); 816 ok(r == 0, "wrong ref count\n"); 817 } 818 819 /* now try write to a storage file we opened read-only */ 820 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg); 821 ok(r==S_OK, "StgOpenStorage failed\n"); 822 if(stg) 823 { 824 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0}; 825 IStream *stm = NULL; 826 IStorage *stg2 = NULL; 827 828 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 829 0, 0, &stm ); 830 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n"); 831 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 832 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n"); 833 834 r = IStorage_Release(stg); 835 ok(r == 0, "wrong ref count\n"); 836 } 837 838 /* open like visio 2003 */ 839 stg = NULL; 840 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg); 841 ok(r == S_OK, "should succeed\n"); 842 if (stg) 843 IStorage_Release(stg); 844 845 /* test other sharing modes with STGM_PRIORITY */ 846 stg = NULL; 847 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); 848 ok(r == S_OK, "should succeed\n"); 849 if (stg) 850 IStorage_Release(stg); 851 852 stg = NULL; 853 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 854 ok(r == S_OK, "should succeed\n"); 855 if (stg) 856 IStorage_Release(stg); 857 858 stg = NULL; 859 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg); 860 ok(r == S_OK, "should succeed\n"); 861 if (stg) 862 IStorage_Release(stg); 863 864 /* open like Project 2003 */ 865 stg = NULL; 866 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg); 867 ok(r == S_OK, "should succeed\n"); 868 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2); 869 ok(r == S_OK, "should succeed\n"); 870 if (stg2) 871 IStorage_Release(stg2); 872 if (stg) 873 IStorage_Release(stg); 874 875 stg = NULL; 876 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg); 877 ok(r == STG_E_INVALIDFLAG, "should fail\n"); 878 879 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg); 880 ok(r == STG_E_INVALIDFLAG, "should fail\n"); 881 882 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg); 883 ok(r == STG_E_INVALIDFLAG, "should fail\n"); 884 885 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg); 886 ok(r == STG_E_INVALIDFUNCTION, "should fail\n"); 887 888 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg); 889 ok(r == STG_E_INVALIDFLAG, "should fail\n"); 890 891 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg); 892 ok(r == STG_E_INVALIDFLAG, "should fail\n"); 893 894 ret = DeleteFileA(filenameA); 895 ok(ret, "file didn't exist\n"); 896 } 897 898 static void test_storage_suminfo(void) 899 { 900 IStorage *stg = NULL; 901 IPropertySetStorage *propset = NULL; 902 IPropertyStorage *ps = NULL; 903 HRESULT r; 904 905 DeleteFileA(filenameA); 906 907 /* create the file */ 908 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 909 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 910 ok(r==S_OK, "StgCreateDocfile failed\n"); 911 912 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset ); 913 ok(r == S_OK, "query interface failed\n"); 914 915 /* delete it */ 916 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation ); 917 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n"); 918 919 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 920 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps ); 921 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n"); 922 923 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 924 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps ); 925 ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); 926 927 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 928 STGM_READ, &ps ); 929 ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); 930 931 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps ); 932 ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); 933 934 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 935 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps ); 936 ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); 937 938 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 939 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps ); 940 ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); 941 942 /* now try really creating a property set */ 943 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 944 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps ); 945 ok(r == S_OK, "failed to create property set storage\n"); 946 947 if( ps ) 948 IPropertyStorage_Release(ps); 949 950 /* now try creating the same thing again */ 951 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 952 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps ); 953 ok(r == S_OK, "failed to create property set storage\n"); 954 if( ps ) 955 IPropertyStorage_Release(ps); 956 957 /* should be able to open it */ 958 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 959 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); 960 ok(r == S_OK, "open failed\n"); 961 if(r == S_OK) 962 IPropertyStorage_Release(ps); 963 964 /* delete it */ 965 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation ); 966 ok(r == S_OK, "failed to delete property set storage\n"); 967 968 /* try opening with an invalid FMTID */ 969 r = IPropertySetStorage_Open( propset, NULL, 970 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); 971 ok(r == E_INVALIDARG, "open succeeded\n"); 972 if(r == S_OK) 973 IPropertyStorage_Release(ps); 974 975 /* try a bad guid */ 976 r = IPropertySetStorage_Open( propset, &IID_IStorage, 977 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); 978 ok(r == STG_E_FILENOTFOUND, "open succeeded\n"); 979 if(r == S_OK) 980 IPropertyStorage_Release(ps); 981 982 983 /* try some invalid flags */ 984 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 985 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); 986 ok(r == STG_E_INVALIDFLAG, "open succeeded\n"); 987 if(r == S_OK) 988 IPropertyStorage_Release(ps); 989 990 /* after deleting it, it should be gone */ 991 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 992 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); 993 ok(r == STG_E_FILENOTFOUND, "open failed\n"); 994 if(r == S_OK) 995 IPropertyStorage_Release(ps); 996 997 r = IPropertySetStorage_Release( propset ); 998 ok(r == 1, "ref count wrong\n"); 999 1000 r = IStorage_Release(stg); 1001 ok(r == 0, "ref count wrong\n"); 1002 1003 DeleteFileA(filenameA); 1004 } 1005 1006 static void test_storage_refcount(void) 1007 { 1008 IStorage *stg = NULL; 1009 IStorage *stgprio = NULL; 1010 HRESULT r; 1011 IStream *stm = NULL; 1012 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1013 LARGE_INTEGER pos; 1014 ULARGE_INTEGER upos; 1015 STATSTG stat; 1016 char buffer[10]; 1017 1018 DeleteFileA(filenameA); 1019 1020 /* create the file */ 1021 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1022 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1023 ok(r==S_OK, "StgCreateDocfile failed\n"); 1024 1025 r = WriteClassStg( stg, &test_stg_cls ); 1026 ok( r == S_OK, "WriteClassStg failed\n"); 1027 1028 r = IStorage_Commit( stg, STGC_DEFAULT ); 1029 ok( r == S_OK, "IStorage_Commit failed\n"); 1030 1031 /* now create a stream */ 1032 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1033 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1034 1035 r = IStorage_Release( stg ); 1036 ok (r == 0, "storage not released\n"); 1037 1038 pos.QuadPart = 0; 1039 r = IStream_Seek( stm, pos, 0, &upos ); 1040 ok (r == STG_E_REVERTED, "seek should fail\n"); 1041 1042 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT ); 1043 ok (r == STG_E_REVERTED, "stat should fail\n"); 1044 1045 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL); 1046 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r); 1047 1048 r = IStream_Read( stm, buffer, sizeof(buffer), NULL); 1049 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r); 1050 1051 r = IStream_Release(stm); 1052 ok (r == 0, "stream not released\n"); 1053 1054 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other 1055 * StgOpenStorage calls in transacted mode */ 1056 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio); 1057 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 1058 1059 /* non-transacted mode read/write fails */ 1060 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg); 1061 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r); 1062 1063 /* non-transacted mode read-only succeeds */ 1064 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg); 1065 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 1066 IStorage_Release(stg); 1067 1068 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg); 1069 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 1070 if(stg) 1071 { 1072 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 }; 1073 static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 }; 1074 static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 }; 1075 IStorage *stg2; 1076 IStorage *stg3; 1077 STATSTG statstg; 1078 1079 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME ); 1080 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r); 1081 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type); 1082 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart); 1083 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart); 1084 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE), 1085 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode); 1086 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported); 1087 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n"); 1088 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits); 1089 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved); 1090 1091 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 ); 1092 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r); 1093 1094 r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT ); 1095 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r); 1096 ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)), 1097 "Statstg pwcsName should have been the name the storage was created with\n"); 1098 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type); 1099 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart); 1100 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart); 1101 ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE, 1102 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode); 1103 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported); 1104 ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n"); 1105 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits); 1106 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved); 1107 CoTaskMemFree(statstg.pwcsName); 1108 1109 r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 ); 1110 ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r); 1111 1112 r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 1113 ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r); 1114 1115 IStorage_Release(stg2); 1116 1117 r = IStorage_Release(stg); 1118 ok(r == 0, "wrong ref count\n"); 1119 } 1120 1121 /* Multiple STGM_PRIORITY opens are possible. */ 1122 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg); 1123 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 1124 if(stg) 1125 { 1126 r = IStorage_Release(stg); 1127 ok(r == 0, "wrong ref count\n"); 1128 } 1129 1130 r = StgOpenStorage( NULL, stgprio, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg); 1131 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 1132 if(stg) 1133 { 1134 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 }; 1135 IStorage *stg2; 1136 STATSTG statstg; 1137 1138 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME ); 1139 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r); 1140 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type); 1141 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart); 1142 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart); 1143 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE), 1144 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode); 1145 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported); 1146 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n"); 1147 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits); 1148 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved); 1149 1150 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 ); 1151 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r); 1152 1153 IStorage_Release(stg2); 1154 1155 r = IStorage_Commit( stg, 0 ); 1156 ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r); 1157 1158 r = IStorage_Release(stg); 1159 ok(r == 0, "wrong ref count\n"); 1160 } 1161 /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */ 1162 1163 DeleteFileA(filenameA); 1164 } 1165 1166 static void test_writeclassstg(void) 1167 { 1168 IStorage *stg = NULL; 1169 HRESULT r; 1170 CLSID temp_cls, cls2; 1171 1172 DeleteFileA(filenameA); 1173 1174 /* create the file */ 1175 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1176 STGM_READWRITE, 0, &stg); 1177 ok(r==S_OK, "StgCreateDocfile failed\n"); 1178 1179 r = ReadClassStg( NULL, NULL ); 1180 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r); 1181 1182 memset(&temp_cls, 0xcc, sizeof(temp_cls)); 1183 memset(&cls2, 0xcc, sizeof(cls2)); 1184 r = ReadClassStg( NULL, &temp_cls ); 1185 ok(r == E_INVALIDARG, "got 0x%08x\n", r); 1186 ok(IsEqualCLSID(&temp_cls, &cls2), "got wrong clsid\n"); 1187 1188 r = ReadClassStg( stg, NULL ); 1189 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r); 1190 1191 temp_cls.Data1 = 0xdeadbeef; 1192 r = ReadClassStg( stg, &temp_cls ); 1193 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r); 1194 1195 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n"); 1196 1197 r = WriteClassStg( NULL, NULL ); 1198 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r); 1199 1200 r = WriteClassStg( stg, NULL ); 1201 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r); 1202 1203 r = WriteClassStg( stg, &test_stg_cls ); 1204 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r); 1205 1206 r = ReadClassStg( stg, &temp_cls ); 1207 ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r); 1208 ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n"); 1209 1210 r = IStorage_Release( stg ); 1211 ok (r == 0, "storage not released\n"); 1212 1213 DeleteFileA(filenameA); 1214 } 1215 1216 static void test_streamenum(void) 1217 { 1218 IStorage *stg = NULL; 1219 HRESULT r; 1220 IStream *stm = NULL; 1221 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1222 static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 }; 1223 static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 }; 1224 static const STATSTG stat_null; 1225 STATSTG stat; 1226 IEnumSTATSTG *ee = NULL; 1227 ULONG count; 1228 1229 DeleteFileA(filenameA); 1230 1231 /* create the file */ 1232 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1233 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1234 ok(r==S_OK, "StgCreateDocfile failed\n"); 1235 1236 r = WriteClassStg( stg, &test_stg_cls ); 1237 ok( r == S_OK, "WriteClassStg failed\n"); 1238 1239 r = IStorage_Commit( stg, STGC_DEFAULT ); 1240 ok( r == S_OK, "IStorage_Commit failed\n"); 1241 1242 /* now create a stream */ 1243 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1244 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1245 1246 IStream_Release(stm); 1247 1248 /* first enum ... should be 1 stream */ 1249 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee); 1250 ok(r==S_OK, "IStorage->EnumElements failed\n"); 1251 1252 count = 0xf00; 1253 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1254 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1255 ok(count == 1, "count wrong\n"); 1256 1257 if (r == S_OK) 1258 CoTaskMemFree(stat.pwcsName); 1259 1260 r = IEnumSTATSTG_Release(ee); 1261 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r); 1262 1263 /* second enum... destroy the stream before reading */ 1264 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee); 1265 ok(r==S_OK, "IStorage->EnumElements failed\n"); 1266 1267 r = IStorage_DestroyElement(stg, stmname); 1268 ok(r==S_OK, "IStorage->DestroyElement failed\n"); 1269 1270 memset(&stat, 0xad, sizeof(stat)); 1271 count = 0xf00; 1272 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1273 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n"); 1274 ok(count == 0, "count wrong\n"); 1275 ok(memcmp(&stat, &stat_null, sizeof(stat)) == 0, "stat is not zeroed\n"); 1276 1277 /* reset and try again */ 1278 r = IEnumSTATSTG_Reset(ee); 1279 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n"); 1280 1281 count = 0xf00; 1282 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1283 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n"); 1284 ok(count == 0, "count wrong\n"); 1285 1286 /* add a stream before reading */ 1287 r = IEnumSTATSTG_Reset(ee); 1288 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n"); 1289 1290 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1291 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1292 1293 r = IStream_Release(stm); 1294 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r); 1295 1296 count = 0xf00; 1297 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1298 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1299 ok(count == 1, "count wrong\n"); 1300 1301 if (r == S_OK) 1302 { 1303 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName)); 1304 CoTaskMemFree(stat.pwcsName); 1305 } 1306 1307 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1308 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1309 1310 r = IStream_Release(stm); 1311 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r); 1312 1313 count = 0xf00; 1314 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1315 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1316 ok(count == 1, "count wrong\n"); 1317 1318 if (r == S_OK) 1319 { 1320 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName)); 1321 CoTaskMemFree(stat.pwcsName); 1322 } 1323 1324 /* delete previous and next stream after reading */ 1325 r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1326 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1327 1328 r = IStream_Release(stm); 1329 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r); 1330 1331 r = IEnumSTATSTG_Reset(ee); 1332 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n"); 1333 1334 count = 0xf00; 1335 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1336 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1337 ok(count == 1, "count wrong\n"); 1338 1339 if (r == S_OK) 1340 { 1341 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName)); 1342 CoTaskMemFree(stat.pwcsName); 1343 } 1344 1345 r = IStorage_DestroyElement(stg, stmname); 1346 ok(r==S_OK, "IStorage->DestroyElement failed\n"); 1347 1348 r = IStorage_DestroyElement(stg, stmname2); 1349 ok(r==S_OK, "IStorage->DestroyElement failed\n"); 1350 1351 count = 0xf00; 1352 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1353 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1354 ok(count == 1, "count wrong\n"); 1355 1356 if (r == S_OK) 1357 { 1358 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName)); 1359 CoTaskMemFree(stat.pwcsName); 1360 } 1361 1362 r = IStorage_Release( stg ); 1363 todo_wine ok (r == 0, "storage not released\n"); 1364 1365 /* enumerator is still valid and working after the storage is released */ 1366 r = IEnumSTATSTG_Reset(ee); 1367 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n"); 1368 1369 count = 0xf00; 1370 r = IEnumSTATSTG_Next(ee, 1, &stat, &count); 1371 ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); 1372 ok(count == 1, "count wrong\n"); 1373 1374 if (r == S_OK) 1375 { 1376 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName)); 1377 CoTaskMemFree(stat.pwcsName); 1378 } 1379 1380 /* the storage is left open until the enumerator is freed */ 1381 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | 1382 STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg); 1383 ok(r==STG_E_SHAREVIOLATION || 1384 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */ 1385 "StgCreateDocfile failed, res=%x\n", r); 1386 1387 r = IEnumSTATSTG_Release(ee); 1388 ok (r == 0, "enum not released\n"); 1389 1390 DeleteFileA(filenameA); 1391 } 1392 1393 static void test_transact(void) 1394 { 1395 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL; 1396 HRESULT r; 1397 IStream *stm = NULL; 1398 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1399 static const WCHAR stmname2[] = { 'F','O','O',0 }; 1400 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 1401 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 }; 1402 BOOL ret; 1403 1404 DeleteFileA(filenameA); 1405 1406 /* create the file */ 1407 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1408 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1409 ok(r==S_OK, "StgCreateDocfile failed\n"); 1410 1411 /* commit a new stream and storage */ 1412 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1413 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1414 1415 r = IStream_Write(stm, "this is stream 1\n", 16, NULL); 1416 ok(r==S_OK, "IStream->Write failed\n"); 1417 1418 IStream_Release(stm); 1419 1420 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 1421 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1422 1423 if (r == S_OK) 1424 { 1425 /* Create two substorages but only commit one */ 1426 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1427 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1428 1429 if (r == S_OK) 1430 IStorage_Release(stg3); 1431 1432 r = IStorage_Commit(stg, 0); 1433 ok(r==S_OK, "IStorage->Commit failed\n"); 1434 1435 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1436 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1437 1438 if (r == S_OK) 1439 IStorage_Release(stg3); 1440 1441 IStorage_Release(stg2); 1442 } 1443 1444 /* now create a stream and storage, but don't commit them */ 1445 stm = NULL; 1446 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1447 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1448 1449 r = IStream_Write(stm, "this is stream 2\n", 16, NULL); 1450 ok(r==S_OK, "IStream->Write failed\n"); 1451 1452 /* IStream::Commit does nothing for OLE storage streams */ 1453 r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE); 1454 ok(r==S_OK, "IStream->Commit failed\n"); 1455 1456 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 1457 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1458 1459 if (r == S_OK) 1460 IStorage_Release(stg2); 1461 1462 IStream_Release(stm); 1463 1464 IStorage_Release(stg); 1465 1466 stm = NULL; 1467 stg = NULL; 1468 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); 1469 ok(r==S_OK, "StgOpenStorage failed\n"); 1470 1471 if (!stg) 1472 return; 1473 1474 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm ); 1475 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r); 1476 1477 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1478 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r); 1479 1480 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1481 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r); 1482 1483 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1484 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r); 1485 1486 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1487 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r); 1488 if (r == S_OK) 1489 IStream_Release(stm); 1490 1491 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1492 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r); 1493 if (r == S_OK) 1494 IStorage_Release(stg2); 1495 1496 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1497 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r); 1498 1499 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1500 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r); 1501 if (r == S_OK) 1502 IStream_Release(stm); 1503 1504 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1505 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r); 1506 if (r == S_OK) 1507 { 1508 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 ); 1509 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r); 1510 if (r == S_OK) 1511 IStorage_Release(stg3); 1512 1513 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 ); 1514 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r); 1515 if (r == S_OK) 1516 IStorage_Release(stg3); 1517 1518 IStorage_Release(stg2); 1519 } 1520 1521 IStorage_Release(stg); 1522 1523 ret = DeleteFileA(filenameA); 1524 ok(ret, "deleted file\n"); 1525 } 1526 1527 static void test_substorage_share(void) 1528 { 1529 IStorage *stg, *stg2, *stg3; 1530 IStream *stm, *stm2; 1531 HRESULT r; 1532 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 1533 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1534 static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 }; 1535 BOOL ret; 1536 1537 DeleteFileA(filenameA); 1538 1539 /* create the file */ 1540 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1541 STGM_READWRITE, 0, &stg); 1542 ok(r==S_OK, "StgCreateDocfile failed\n"); 1543 1544 /* create a read/write storage and try to open it again */ 1545 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 1546 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1547 1548 if (r == S_OK) 1549 { 1550 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1551 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r); 1552 1553 if (r == S_OK) 1554 IStorage_Release(stg3); 1555 1556 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1557 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r); 1558 1559 if (r == S_OK) 1560 IStorage_Release(stg3); 1561 1562 /* cannot rename the storage while it's open */ 1563 r = IStorage_RenameElement(stg, stgname, othername); 1564 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r); 1565 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname); 1566 1567 /* destroying an object while it's open invalidates it */ 1568 r = IStorage_DestroyElement(stg, stgname); 1569 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r); 1570 1571 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); 1572 ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r); 1573 1574 if (r == S_OK) 1575 IStream_Release(stm); 1576 1577 IStorage_Release(stg2); 1578 } 1579 1580 /* create a read/write stream and try to open it again */ 1581 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); 1582 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r); 1583 1584 if (r == S_OK) 1585 { 1586 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2); 1587 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r); 1588 1589 if (r == S_OK) 1590 IStream_Release(stm2); 1591 1592 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2); 1593 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r); 1594 1595 if (r == S_OK) 1596 IStream_Release(stm2); 1597 1598 /* cannot rename the stream while it's open */ 1599 r = IStorage_RenameElement(stg, stmname, othername); 1600 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r); 1601 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname); 1602 1603 /* destroying an object while it's open invalidates it */ 1604 r = IStorage_DestroyElement(stg, stmname); 1605 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r); 1606 1607 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL); 1608 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r); 1609 1610 IStream_Release(stm); 1611 } 1612 1613 IStorage_Release(stg); 1614 1615 ret = DeleteFileA(filenameA); 1616 ok(ret, "deleted file\n"); 1617 } 1618 1619 static void test_revert(void) 1620 { 1621 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL; 1622 HRESULT r; 1623 IStream *stm = NULL, *stm2 = NULL; 1624 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1625 static const WCHAR stmname2[] = { 'F','O','O',0 }; 1626 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 1627 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 }; 1628 STATSTG statstg; 1629 BOOL ret; 1630 1631 DeleteFileA(filenameA); 1632 1633 /* create the file */ 1634 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1635 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1636 ok(r==S_OK, "StgCreateDocfile failed\n"); 1637 1638 /* commit a new stream and storage */ 1639 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1640 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1641 1642 r = IStream_Write(stm, "this is stream 1\n", 16, NULL); 1643 ok(r==S_OK, "IStream->Write failed\n"); 1644 1645 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 1646 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1647 1648 if (r == S_OK) 1649 { 1650 /* Create two substorages but only commit one */ 1651 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1652 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1653 1654 if (r == S_OK) 1655 IStorage_Release(stg3); 1656 1657 r = IStorage_Commit(stg, 0); 1658 ok(r==S_OK, "IStorage->Commit failed\n"); 1659 1660 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1661 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1662 1663 if (r == S_OK) 1664 IStorage_Release(stg3); 1665 } 1666 1667 /* now create a stream and storage, then revert */ 1668 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 ); 1669 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1670 1671 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL); 1672 ok(r==S_OK, "IStream->Write failed\n"); 1673 1674 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1675 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1676 1677 r = IStorage_Revert(stg); 1678 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r); 1679 1680 /* all open objects become invalid */ 1681 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL); 1682 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r); 1683 1684 r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL); 1685 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r); 1686 1687 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME); 1688 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); 1689 1690 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME); 1691 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); 1692 1693 IStream_Release(stm); 1694 IStream_Release(stm2); 1695 IStorage_Release(stg2); 1696 IStorage_Release(stg3); 1697 1698 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm ); 1699 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r); 1700 1701 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1702 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r); 1703 1704 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1705 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r); 1706 1707 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1708 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r); 1709 1710 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1711 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r); 1712 if (r == S_OK) 1713 IStream_Release(stm); 1714 1715 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1716 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r); 1717 if (r == S_OK) 1718 IStorage_Release(stg2); 1719 1720 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1721 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r); 1722 1723 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1724 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r); 1725 if (r == S_OK) 1726 IStream_Release(stm); 1727 1728 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 ); 1729 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r); 1730 if (r == S_OK) 1731 { 1732 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 ); 1733 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r); 1734 if (r == S_OK) 1735 IStorage_Release(stg3); 1736 1737 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 ); 1738 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r); 1739 if (r == S_OK) 1740 IStorage_Release(stg3); 1741 1742 IStorage_Release(stg2); 1743 } 1744 1745 IStorage_Release(stg); 1746 1747 ret = DeleteFileA(filenameA); 1748 ok(ret, "deleted file\n"); 1749 1750 /* Revert only invalidates objects in transacted mode */ 1751 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1752 STGM_READWRITE, 0, &stg); 1753 ok(r==S_OK, "StgCreateDocfile failed\n"); 1754 1755 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1756 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1757 1758 r = IStorage_Revert(stg); 1759 ok(r==S_OK, "IStorage->Revert failed %08x\n", r); 1760 1761 r = IStream_Write(stm, "this works\n", 11, NULL); 1762 ok(r==S_OK, "IStream_Write should succeed %08x\n", r); 1763 1764 IStream_Release(stm); 1765 IStorage_Release(stg); 1766 1767 ret = DeleteFileA(filenameA); 1768 ok(ret, "deleted file\n"); 1769 } 1770 1771 static void test_parent_free(void) 1772 { 1773 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL; 1774 HRESULT r; 1775 IStream *stm = NULL; 1776 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1777 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 1778 ULONG ref; 1779 STATSTG statstg; 1780 BOOL ret; 1781 1782 DeleteFileA(filenameA); 1783 1784 /* create the file */ 1785 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1786 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1787 ok(r==S_OK, "StgCreateDocfile failed\n"); 1788 1789 /* create a new storage */ 1790 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 1791 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1792 1793 if (r == S_OK) 1794 { 1795 /* now create a stream inside the new storage */ 1796 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1797 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1798 1799 if (r == S_OK) 1800 { 1801 /* create a storage inside the new storage */ 1802 r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 ); 1803 ok(r==S_OK, "IStorage->CreateStorage failed\n"); 1804 } 1805 1806 /* free the parent */ 1807 ref = IStorage_Release(stg2); 1808 ok(ref == 0, "IStorage still has %u references\n", ref); 1809 1810 /* child objects are invalid */ 1811 if (r == S_OK) 1812 { 1813 r = IStream_Write(stm, "this should fail\n", 17, NULL); 1814 ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r); 1815 1816 IStream_Release(stm); 1817 1818 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME); 1819 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); 1820 1821 r = IStorage_SetStateBits(stg3, 1, 1); 1822 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); 1823 1824 IStorage_Release(stg3); 1825 } 1826 } 1827 1828 IStorage_Release(stg); 1829 1830 ret = DeleteFileA(filenameA); 1831 ok(ret, "deleted file\n"); 1832 } 1833 1834 static void test_nonroot_transacted(void) 1835 { 1836 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL; 1837 HRESULT r; 1838 IStream *stm = NULL; 1839 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 1840 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 1841 static const WCHAR stmname2[] = { 'F','O','O',0 }; 1842 BOOL ret; 1843 1844 DeleteFileA(filenameA); 1845 1846 /* create a transacted file */ 1847 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1848 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 1849 ok(r==S_OK, "StgCreateDocfile failed\n"); 1850 1851 /* create a transacted substorage */ 1852 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2); 1853 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1854 1855 if (r == S_OK) 1856 { 1857 /* create and commit stmname */ 1858 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1859 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1860 if (r == S_OK) 1861 IStream_Release(stm); 1862 1863 IStorage_Commit(stg2, 0); 1864 1865 /* create and revert stmname2 */ 1866 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1867 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1868 if (r == S_OK) 1869 IStream_Release(stm); 1870 1871 IStorage_Revert(stg2); 1872 1873 /* check that Commit and Revert really worked */ 1874 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1875 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r); 1876 if (r == S_OK) 1877 IStream_Release(stm); 1878 1879 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1880 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r); 1881 if (r == S_OK) 1882 IStream_Release(stm); 1883 1884 IStorage_Release(stg2); 1885 } 1886 1887 /* create a read-only transacted substorage */ 1888 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2); 1889 ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r); 1890 1891 if (r == S_OK) 1892 { 1893 /* The storage can be modified. */ 1894 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 1895 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1896 if (r == S_OK) 1897 IStorage_Release(stg3); 1898 1899 /* But changes cannot be committed. */ 1900 r = IStorage_Commit(stg2, 0); 1901 ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r); 1902 1903 IStorage_Release(stg2); 1904 } 1905 1906 IStorage_Release(stg); 1907 1908 /* create a non-transacted file */ 1909 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 1910 STGM_READWRITE, 0, &stg); 1911 ok(r==S_OK, "StgCreateDocfile failed\n"); 1912 1913 /* create a transacted substorage */ 1914 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2); 1915 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 1916 1917 if (r == S_OK) 1918 { 1919 /* create and commit stmname */ 1920 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1921 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1922 if (r == S_OK) 1923 IStream_Release(stm); 1924 1925 IStorage_Commit(stg2, 0); 1926 1927 /* create and revert stmname2 */ 1928 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm ); 1929 ok(r==S_OK, "IStorage->CreateStream failed\n"); 1930 if (r == S_OK) 1931 IStream_Release(stm); 1932 1933 IStorage_Revert(stg2); 1934 1935 /* check that Commit and Revert really worked */ 1936 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1937 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r); 1938 if (r == S_OK) 1939 IStream_Release(stm); 1940 1941 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm ); 1942 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r); 1943 if (r == S_OK) 1944 IStream_Release(stm); 1945 1946 IStorage_Release(stg2); 1947 } 1948 1949 IStorage_Release(stg); 1950 1951 ret = DeleteFileA(filenameA); 1952 ok(ret, "deleted file\n"); 1953 } 1954 1955 static void test_ReadClassStm(void) 1956 { 1957 CLSID clsid, clsid2; 1958 HRESULT hr; 1959 IStream *pStream; 1960 static const LARGE_INTEGER llZero; 1961 1962 hr = ReadClassStm(NULL, &clsid); 1963 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1964 1965 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1966 ok_ole_success(hr, "CreateStreamOnHGlobal"); 1967 hr = WriteClassStm(pStream, &test_stg_cls); 1968 ok_ole_success(hr, "WriteClassStm"); 1969 1970 hr = ReadClassStm(pStream, NULL); 1971 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr); 1972 1973 memset(&clsid, 0xcc, sizeof(clsid)); 1974 memset(&clsid2, 0xcc, sizeof(clsid2)); 1975 hr = ReadClassStm(NULL, &clsid); 1976 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 1977 ok(IsEqualCLSID(&clsid, &clsid2), "got wrong clsid\n"); 1978 1979 /* test not rewound stream */ 1980 hr = ReadClassStm(pStream, &clsid); 1981 ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr); 1982 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n"); 1983 1984 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 1985 ok_ole_success(hr, "IStream_Seek"); 1986 hr = ReadClassStm(pStream, &clsid); 1987 ok_ole_success(hr, "ReadClassStm"); 1988 ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n"); 1989 1990 IStream_Release(pStream); 1991 } 1992 1993 struct access_res 1994 { 1995 BOOL gothandle; 1996 DWORD lasterr; 1997 BOOL ignore; 1998 }; 1999 2000 static const struct access_res create[16] = 2001 { 2002 { TRUE, ERROR_SUCCESS, TRUE }, 2003 { TRUE, ERROR_SUCCESS, TRUE }, 2004 { TRUE, ERROR_SUCCESS, FALSE }, 2005 { TRUE, ERROR_SUCCESS, FALSE }, 2006 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2007 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2008 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2009 { TRUE, ERROR_SUCCESS, FALSE }, 2010 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2011 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2012 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2013 { TRUE, ERROR_SUCCESS, TRUE }, 2014 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2015 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2016 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2017 { TRUE, ERROR_SUCCESS, TRUE } 2018 }; 2019 2020 static const struct access_res create_commit[16] = 2021 { 2022 { TRUE, ERROR_SUCCESS, TRUE }, 2023 { TRUE, ERROR_SUCCESS, TRUE }, 2024 { TRUE, ERROR_SUCCESS, FALSE }, 2025 { TRUE, ERROR_SUCCESS, FALSE }, 2026 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2027 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2028 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2029 { TRUE, ERROR_SUCCESS, FALSE }, 2030 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2031 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2032 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2033 { TRUE, ERROR_SUCCESS, TRUE }, 2034 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2035 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2036 { FALSE, ERROR_SHARING_VIOLATION, FALSE }, 2037 { TRUE, ERROR_SUCCESS, TRUE } 2038 }; 2039 2040 static const struct access_res create_close[16] = 2041 { 2042 { TRUE, ERROR_SUCCESS, FALSE }, 2043 { TRUE, ERROR_SUCCESS, FALSE }, 2044 { TRUE, ERROR_SUCCESS, FALSE }, 2045 { TRUE, ERROR_SUCCESS, FALSE }, 2046 { TRUE, ERROR_SUCCESS, FALSE }, 2047 { TRUE, ERROR_SUCCESS, FALSE }, 2048 { TRUE, ERROR_SUCCESS, FALSE }, 2049 { TRUE, ERROR_SUCCESS, FALSE }, 2050 { TRUE, ERROR_SUCCESS, FALSE }, 2051 { TRUE, ERROR_SUCCESS, FALSE }, 2052 { TRUE, ERROR_SUCCESS, FALSE }, 2053 { TRUE, ERROR_SUCCESS, FALSE }, 2054 { TRUE, ERROR_SUCCESS, FALSE }, 2055 { TRUE, ERROR_SUCCESS, FALSE }, 2056 { TRUE, ERROR_SUCCESS, FALSE }, 2057 { TRUE, ERROR_SUCCESS } 2058 }; 2059 2060 static const DWORD access_modes[4] = { 2061 0, 2062 GENERIC_READ, 2063 GENERIC_WRITE, 2064 GENERIC_READ | GENERIC_WRITE 2065 }; 2066 2067 static const DWORD share_modes[4] = { 2068 0, 2069 FILE_SHARE_READ, 2070 FILE_SHARE_WRITE, 2071 FILE_SHARE_READ | FILE_SHARE_WRITE 2072 }; 2073 2074 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line) 2075 { 2076 int i, j, idx = 0; 2077 2078 for (i = 0; i < sizeof(access_modes)/sizeof(access_modes[0]); i++) 2079 { 2080 for (j = 0; j < sizeof(share_modes)/sizeof(share_modes[0]); j++) 2081 { 2082 DWORD lasterr; 2083 HANDLE hfile; 2084 2085 if (ares[idx].ignore) 2086 continue; 2087 2088 SetLastError(0xdeadbeef); 2089 hfile = CreateFileA(file, access_modes[i], share_modes[j], NULL, OPEN_EXISTING, 2090 FILE_ATTRIBUTE_NORMAL, 0); 2091 lasterr = GetLastError(); 2092 2093 ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle, 2094 "(%d, handle, %d): Expected %d, got %d\n", 2095 line, idx, ares[idx].gothandle, 2096 (hfile != INVALID_HANDLE_VALUE)); 2097 2098 ok(lasterr == ares[idx].lasterr || 2099 broken(lasterr == 0xdeadbeef) /* win9x */, 2100 "(%d, lasterr, %d): Expected %d, got %d\n", 2101 line, idx, ares[idx].lasterr, lasterr); 2102 2103 CloseHandle(hfile); 2104 idx++; 2105 } 2106 } 2107 } 2108 2109 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__) 2110 2111 static void test_access(void) 2112 { 2113 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0}; 2114 static const char fileA[] = "winetest"; 2115 IStorage *stg; 2116 HRESULT hr; 2117 2118 /* STGM_TRANSACTED */ 2119 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | 2120 STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg); 2121 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2122 2123 test_file_access(fileA, create); 2124 2125 hr = IStorage_Commit(stg, STGC_DEFAULT); 2126 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2127 2128 test_file_access(fileA, create_commit); 2129 2130 IStorage_Release(stg); 2131 2132 test_file_access(fileA, create_close); 2133 2134 DeleteFileA(fileA); 2135 2136 /* STGM_DIRECT */ 2137 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | 2138 STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg); 2139 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2140 2141 test_file_access(fileA, create); 2142 2143 hr = IStorage_Commit(stg, STGC_DEFAULT); 2144 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2145 2146 test_file_access(fileA, create_commit); 2147 2148 IStorage_Release(stg); 2149 2150 test_file_access(fileA, create_close); 2151 2152 DeleteFileA(fileA); 2153 2154 /* STGM_SHARE_DENY_NONE */ 2155 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | 2156 STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg); 2157 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2158 2159 test_file_access(fileA, create); 2160 2161 hr = IStorage_Commit(stg, STGC_DEFAULT); 2162 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2163 2164 test_file_access(fileA, create_commit); 2165 2166 IStorage_Release(stg); 2167 2168 test_file_access(fileA, create_close); 2169 2170 DeleteFileA(fileA); 2171 2172 /* STGM_SHARE_DENY_READ */ 2173 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | 2174 STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg); 2175 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2176 2177 test_file_access(fileA, create); 2178 2179 hr = IStorage_Commit(stg, STGC_DEFAULT); 2180 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2181 2182 test_file_access(fileA, create_commit); 2183 2184 IStorage_Release(stg); 2185 2186 test_file_access(fileA, create_close); 2187 2188 DeleteFileA(fileA); 2189 2190 /* STGM_SHARE_DENY_WRITE */ 2191 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | 2192 STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg); 2193 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2194 2195 test_file_access(fileA, create); 2196 2197 hr = IStorage_Commit(stg, STGC_DEFAULT); 2198 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 2199 2200 test_file_access(fileA, create_commit); 2201 2202 IStorage_Release(stg); 2203 2204 test_file_access(fileA, create_close); 2205 2206 DeleteFileA(fileA); 2207 2208 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */ 2209 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg); 2210 ok(hr == S_OK, "got %08x\n", hr); 2211 IStorage_Release(stg); 2212 2213 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg); 2214 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr); 2215 if(hr != S_OK) 2216 return; 2217 2218 test_file_access(fileA, create); 2219 2220 IStorage_Release(stg); 2221 test_file_access(fileA, create_close); 2222 2223 DeleteFileA(fileA); 2224 } 2225 2226 static void test_readonly(void) 2227 { 2228 IStorage *stg, *stg2, *stg3; 2229 IStream *stream; 2230 HRESULT hr; 2231 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0}; 2232 static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0}; 2233 static const WCHAR streamW[] = {'s','t','r','e','a','m',0}; 2234 2235 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 2236 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2237 if (SUCCEEDED(hr)) 2238 { 2239 hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 ); 2240 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2241 if (SUCCEEDED(hr)) 2242 { 2243 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream ); 2244 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2245 if (SUCCEEDED(hr)) 2246 IStream_Release(stream); 2247 IStorage_Release(stg2); 2248 } 2249 IStorage_Release(stg); 2250 } 2251 2252 /* re-open read only */ 2253 hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg); 2254 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2255 if (SUCCEEDED(hr)) 2256 { 2257 hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 ); 2258 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2259 if (SUCCEEDED(hr)) 2260 { 2261 /* CreateStream on read-only storage, name exists */ 2262 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream ); 2263 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr); 2264 if (SUCCEEDED(hr)) 2265 IStream_Release(stream); 2266 2267 /* CreateStream on read-only storage, name does not exist */ 2268 hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream ); 2269 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr); 2270 if (SUCCEEDED(hr)) 2271 IStream_Release(stream); 2272 2273 /* CreateStorage on read-only storage, name exists */ 2274 hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 ); 2275 ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr); 2276 if (SUCCEEDED(hr)) 2277 IStorage_Release(stg3); 2278 2279 /* CreateStorage on read-only storage, name does not exist */ 2280 hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 ); 2281 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr); 2282 if (SUCCEEDED(hr)) 2283 IStorage_Release(stg3); 2284 2285 /* DestroyElement on read-only storage, name exists */ 2286 hr = IStorage_DestroyElement( stg2, streamW ); 2287 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr); 2288 2289 /* DestroyElement on read-only storage, name does not exist */ 2290 hr = IStorage_DestroyElement( stg2, storageW ); 2291 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr); 2292 2293 IStorage_Release(stg2); 2294 } 2295 2296 IStorage_Release(stg); 2297 } 2298 2299 DeleteFileA("winetest"); 2300 } 2301 2302 static void test_simple(void) 2303 { 2304 /* Tests for STGM_SIMPLE mode */ 2305 2306 IStorage *stg, *stg2; 2307 HRESULT r; 2308 IStream *stm; 2309 static const WCHAR stgname[] = { 'S','t','g',0 }; 2310 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 2311 static const WCHAR stmname2[] = { 'S','m','a','l','l',0 }; 2312 LARGE_INTEGER pos; 2313 ULARGE_INTEGER upos; 2314 DWORD count; 2315 STATSTG stat; 2316 2317 DeleteFileA(filenameA); 2318 2319 r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 2320 ok(r == S_OK, "got %08x\n", r); 2321 2322 r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2); 2323 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r); 2324 if (SUCCEEDED(r)) IStorage_Release(stg2); 2325 2326 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm); 2327 ok(r == STG_E_INVALIDFLAG, "got %08x\n", r); 2328 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm); 2329 ok(r == S_OK, "got %08x\n", r); 2330 2331 upos.QuadPart = 6000; 2332 r = IStream_SetSize(stm, upos); 2333 ok(r == S_OK, "got %08x\n", r); 2334 2335 r = IStream_Write(stm, "foo", 3, &count); 2336 ok(r == S_OK, "got %08x\n", r); 2337 ok(count == 3, "got %d\n", count); 2338 2339 pos.QuadPart = 0; 2340 r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos); 2341 ok(r == S_OK, "got %08x\n", r); 2342 ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart); 2343 2344 r = IStream_Stat(stm, &stat, STATFLAG_NONAME); 2345 ok(r == S_OK || 2346 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */ 2347 "got %08x\n", r); 2348 if (r == S_OK) 2349 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart); 2350 2351 pos.QuadPart = 1; 2352 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos); 2353 ok(r == S_OK, "got %08x\n", r); 2354 ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart); 2355 2356 r = IStream_Stat(stm, &stat, STATFLAG_NONAME); 2357 ok(r == S_OK || 2358 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */ 2359 "got %08x\n", r); 2360 if (r == S_OK) 2361 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart); 2362 2363 IStream_Release(stm); 2364 2365 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm); 2366 ok(r == S_OK, "got %08x\n", r); 2367 2368 upos.QuadPart = 100; 2369 r = IStream_SetSize(stm, upos); 2370 ok(r == S_OK, "got %08x\n", r); 2371 2372 r = IStream_Write(stm, "foo", 3, &count); 2373 ok(r == S_OK, "got %08x\n", r); 2374 ok(count == 3, "got %d\n", count); 2375 2376 IStream_Release(stm); 2377 2378 IStorage_Commit(stg, STGC_DEFAULT); 2379 IStorage_Release(stg); 2380 2381 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg); 2382 if (r == STG_E_INVALIDFLAG) 2383 { 2384 win_skip("Flag combination is not supported on NT4 and below\n"); 2385 DeleteFileA(filenameA); 2386 return; 2387 } 2388 ok(r == S_OK, "got %08x\n", r); 2389 2390 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2); 2391 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r); 2392 if (SUCCEEDED(r)) IStorage_Release(stg2); 2393 2394 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm); 2395 ok(r == S_OK, "got %08x\n", r); 2396 2397 r = IStream_Stat(stm, &stat, STATFLAG_NONAME); 2398 ok(r == S_OK, "got %08x\n", r); 2399 ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart); 2400 2401 IStream_Release(stm); 2402 2403 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm); 2404 ok(r == S_OK, "got %08x\n", r); 2405 2406 r = IStream_Stat(stm, &stat, STATFLAG_NONAME); 2407 ok(r == S_OK, "got %08x\n", r); 2408 ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart); 2409 2410 IStream_Release(stm); 2411 2412 2413 IStorage_Release(stg); 2414 2415 DeleteFileA(filenameA); 2416 } 2417 2418 static void test_fmtusertypestg(void) 2419 { 2420 IStorage *stg; 2421 IEnumSTATSTG *stat; 2422 HRESULT hr; 2423 static const char fileA[] = {'f','m','t','t','e','s','t',0}; 2424 static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0}; 2425 static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0}; 2426 static const WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0}; 2427 static const STATSTG statstg_null; 2428 2429 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 2430 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2431 2432 if (SUCCEEDED(hr)) 2433 { 2434 /* try to write the stream */ 2435 hr = WriteFmtUserTypeStg(stg, 0, userTypeW); 2436 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2437 2438 /* check that the stream was created */ 2439 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat); 2440 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2441 if (SUCCEEDED(hr)) 2442 { 2443 BOOL found = FALSE; 2444 STATSTG statstg; 2445 DWORD got; 2446 memset(&statstg, 0xad, sizeof(statstg)); 2447 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1) 2448 { 2449 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0) 2450 found = TRUE; 2451 else 2452 ok(0, "found unexpected stream or storage\n"); 2453 CoTaskMemFree(statstg.pwcsName); 2454 } 2455 ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n"); 2456 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n"); 2457 IEnumSTATSTG_Release(stat); 2458 } 2459 2460 /* re-write the stream */ 2461 hr = WriteFmtUserTypeStg(stg, 0, userTypeW); 2462 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2463 2464 /* check that the stream is still there */ 2465 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat); 2466 ok(hr == S_OK, "should succeed, res=%x\n", hr); 2467 if (SUCCEEDED(hr)) 2468 { 2469 BOOL found = FALSE; 2470 STATSTG statstg; 2471 DWORD got; 2472 memset(&statstg, 0xad, sizeof(statstg)); 2473 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1) 2474 { 2475 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0) 2476 found = TRUE; 2477 else 2478 ok(0, "found unexpected stream or storage\n"); 2479 CoTaskMemFree(statstg.pwcsName); 2480 } 2481 ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n"); 2482 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n"); 2483 IEnumSTATSTG_Release(stat); 2484 } 2485 2486 IStorage_Release(stg); 2487 DeleteFileA( fileA ); 2488 } 2489 } 2490 2491 static void test_references(void) 2492 { 2493 IStorage *stg,*stg2; 2494 HRESULT hr; 2495 unsigned c1,c2; 2496 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 }; 2497 2498 DeleteFileA(filenameA); 2499 2500 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 2501 ok(hr==S_OK, "StgCreateDocfile failed\n"); 2502 2503 if (SUCCEEDED(hr)) 2504 { 2505 IStorage_Release(stg); 2506 2507 hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg); 2508 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr); 2509 2510 if (SUCCEEDED(hr)) 2511 { 2512 hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2); 2513 ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr); 2514 2515 if (SUCCEEDED(hr)) 2516 { 2517 c1 = IStorage_AddRef(stg); 2518 ok(c1 == 2, "creating internal storage added references to ancestor\n"); 2519 c1 = IStorage_AddRef(stg); 2520 IStorage_Release(stg2); 2521 c2 = IStorage_AddRef(stg) - 1; 2522 ok(c1 == c2, "releasing internal storage removed references to ancestor\n"); 2523 } 2524 c1 = IStorage_Release(stg); 2525 while ( c1 ) c1 = IStorage_Release(stg); 2526 } 2527 } 2528 2529 DeleteFileA(filenameA); 2530 } 2531 2532 /* dest 2533 * |-StorageA 2534 * | `StreamA: "StreamA" 2535 * |-StorageB 2536 * | `StreamB: "StreamB" 2537 * `StreamC: "StreamC" 2538 */ 2539 static HRESULT create_test_file(IStorage *dest) 2540 { 2541 IStorage *stgA = NULL, *stgB = NULL; 2542 IStream *strmA = NULL, *strmB = NULL, *strmC = NULL; 2543 const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR); 2544 const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR); 2545 const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR); 2546 ULONG bytes; 2547 HRESULT hr; 2548 2549 hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA); 2550 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr); 2551 if(FAILED(hr)) 2552 goto cleanup; 2553 2554 hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA); 2555 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr); 2556 if(FAILED(hr)) 2557 goto cleanup; 2558 2559 hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes); 2560 ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size); 2561 2562 hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB); 2563 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr); 2564 if(FAILED(hr)) 2565 goto cleanup; 2566 2567 hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB); 2568 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr); 2569 if(FAILED(hr)) 2570 goto cleanup; 2571 2572 hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes); 2573 ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size); 2574 2575 hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC); 2576 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr); 2577 if(FAILED(hr)) 2578 goto cleanup; 2579 2580 hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes); 2581 ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size); 2582 2583 cleanup: 2584 if(strmC) 2585 IStream_Release(strmC); 2586 if(strmB) 2587 IStream_Release(strmB); 2588 if(stgB) 2589 IStorage_Release(stgB); 2590 if(strmA) 2591 IStream_Release(strmA); 2592 if(stgA) 2593 IStorage_Release(stgA); 2594 2595 return hr; 2596 } 2597 2598 static void test_copyto(void) 2599 { 2600 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp; 2601 IStream *strm_tmp; 2602 WCHAR buf[64]; 2603 HRESULT hr; 2604 2605 /* create & populate file1 */ 2606 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1); 2607 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2608 if(FAILED(hr)) 2609 goto cleanup; 2610 2611 hr = create_test_file(file1); 2612 if(FAILED(hr)) 2613 goto cleanup; 2614 2615 /* create file2 */ 2616 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2); 2617 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2618 if(FAILED(hr)) 2619 goto cleanup; 2620 2621 /* copy file1 into file2 */ 2622 hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL); 2623 ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr); 2624 2625 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2); 2626 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr); 2627 if(FAILED(hr)) 2628 goto cleanup; 2629 2630 /* verify that all of file1 was copied */ 2631 hr = IStorage_OpenStorage(file2, stgA_name, NULL, 2632 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2633 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr); 2634 2635 if(SUCCEEDED(hr)){ 2636 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL, 2637 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2638 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr); 2639 2640 if(SUCCEEDED(hr)){ 2641 memset(buf, 0, sizeof(buf)); 2642 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL); 2643 ok(hr == S_OK, "Read failed: 0x%08x\n", hr); 2644 if(SUCCEEDED(hr)) 2645 ok(strcmp_ww(buf, strmA_name) == 0, 2646 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf)); 2647 2648 IStream_Release(strm_tmp); 2649 } 2650 2651 IStorage_Release(stg_tmp); 2652 } 2653 2654 hr = IStorage_OpenStorage(file2, stgB_name, NULL, 2655 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2656 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr); 2657 2658 if(SUCCEEDED(hr)){ 2659 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL, 2660 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2661 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr); 2662 2663 if(SUCCEEDED(hr)){ 2664 memset(buf, 0, sizeof(buf)); 2665 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL); 2666 ok(hr == S_OK, "Read failed: 0x%08x\n", hr); 2667 if(SUCCEEDED(hr)) 2668 ok(strcmp_ww(buf, strmB_name) == 0, 2669 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf)); 2670 2671 IStream_Release(strm_tmp); 2672 } 2673 2674 IStorage_Release(stg_tmp); 2675 } 2676 2677 hr = IStorage_OpenStream(file2, strmC_name, NULL, 2678 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2679 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr); 2680 2681 if(SUCCEEDED(hr)){ 2682 memset(buf, 0, sizeof(buf)); 2683 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL); 2684 ok(hr == S_OK, "Read failed: 0x%08x\n", hr); 2685 if(SUCCEEDED(hr)) 2686 ok(strcmp_ww(buf, strmC_name) == 0, 2687 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf)); 2688 2689 IStream_Release(strm_tmp); 2690 } 2691 2692 cleanup: 2693 if(file1) 2694 IStorage_Release(file1); 2695 if(file2) 2696 IStorage_Release(file2); 2697 2698 DeleteFileA(file1_nameA); 2699 DeleteFileA(file2_nameA); 2700 } 2701 2702 static void test_copyto_snbexclusions(void) 2703 { 2704 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0}; 2705 2706 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp; 2707 IStream *strm_tmp; 2708 WCHAR buf[64]; 2709 HRESULT hr; 2710 2711 /* create & populate file1 */ 2712 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1); 2713 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2714 if(FAILED(hr)) 2715 goto cleanup; 2716 2717 hr = create_test_file(file1); 2718 if(FAILED(hr)) 2719 goto cleanup; 2720 2721 /* create file2 */ 2722 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2); 2723 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2724 if(FAILED(hr)) 2725 goto cleanup; 2726 2727 /* copy file1 to file2 with name exclusions */ 2728 hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2); 2729 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr); 2730 if(FAILED(hr)) 2731 goto cleanup; 2732 2733 /* verify that file1 copied over, respecting exclusions */ 2734 hr = IStorage_OpenStorage(file2, stgA_name, NULL, 2735 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2736 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2737 if(SUCCEEDED(hr)) 2738 IStorage_Release(stg_tmp); 2739 2740 hr = IStorage_OpenStream(file2, strmA_name, NULL, 2741 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2742 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2743 if(SUCCEEDED(hr)) 2744 IStream_Release(strm_tmp); 2745 2746 hr = IStorage_OpenStorage(file2, stgB_name, NULL, 2747 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2748 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr); 2749 2750 if(SUCCEEDED(hr)){ 2751 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL, 2752 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2753 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr); 2754 2755 if(SUCCEEDED(hr)){ 2756 memset(buf, 0, sizeof(buf)); 2757 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL); 2758 ok(hr == S_OK, "Read failed: 0x%08x\n", hr); 2759 if(SUCCEEDED(hr)) 2760 ok(strcmp_ww(buf, strmB_name) == 0, 2761 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf)); 2762 2763 IStream_Release(strm_tmp); 2764 } 2765 2766 IStorage_Release(stg_tmp); 2767 } 2768 2769 hr = IStorage_OpenStream(file2, strmC_name, NULL, 2770 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2771 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2772 if(SUCCEEDED(hr)) 2773 IStream_Release(strm_tmp); 2774 2775 cleanup: 2776 if(file1) 2777 IStorage_Release(file1); 2778 if(file2) 2779 IStorage_Release(file2); 2780 2781 DeleteFileA(file1_nameA); 2782 DeleteFileA(file2_nameA); 2783 } 2784 2785 static void test_copyto_iidexclusions_storage(void) 2786 { 2787 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp; 2788 IStream *strm_tmp; 2789 WCHAR buf[64]; 2790 HRESULT hr; 2791 2792 /* create & populate file1 */ 2793 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1); 2794 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2795 if(FAILED(hr)) 2796 goto cleanup; 2797 2798 hr = create_test_file(file1); 2799 if(FAILED(hr)) 2800 goto cleanup; 2801 2802 /* create file2 */ 2803 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2); 2804 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2805 if(FAILED(hr)) 2806 goto cleanup; 2807 2808 /* copy file1 to file2 with iid exclusions */ 2809 hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2); 2810 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr); 2811 if(FAILED(hr)) 2812 goto cleanup; 2813 2814 /* verify that file1 copied over, respecting exclusions */ 2815 hr = IStorage_OpenStorage(file2, stgA_name, NULL, 2816 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2817 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2818 if(SUCCEEDED(hr)) 2819 IStorage_Release(stg_tmp); 2820 2821 hr = IStorage_OpenStream(file2, strmA_name, NULL, 2822 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2823 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2824 if(SUCCEEDED(hr)) 2825 IStream_Release(strm_tmp); 2826 2827 hr = IStorage_OpenStorage(file2, stgB_name, NULL, 2828 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2829 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2830 if(SUCCEEDED(hr)) 2831 IStorage_Release(stg_tmp); 2832 2833 hr = IStorage_OpenStream(file2, strmB_name, NULL, 2834 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2835 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2836 if(SUCCEEDED(hr)) 2837 IStream_Release(strm_tmp); 2838 2839 hr = IStorage_OpenStream(file2, strmC_name, NULL, 2840 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2841 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr); 2842 2843 if(SUCCEEDED(hr)){ 2844 memset(buf, 0, sizeof(buf)); 2845 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL); 2846 ok(hr == S_OK, "Read failed: 0x%08x\n", hr); 2847 if(SUCCEEDED(hr)) 2848 ok(strcmp_ww(buf, strmC_name) == 0, 2849 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf)); 2850 2851 IStream_Release(strm_tmp); 2852 } 2853 2854 cleanup: 2855 if(file1) 2856 IStorage_Release(file1); 2857 if(file2) 2858 IStorage_Release(file2); 2859 2860 DeleteFileA(file1_nameA); 2861 DeleteFileA(file2_nameA); 2862 } 2863 2864 static void test_copyto_iidexclusions_stream(void) 2865 { 2866 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp; 2867 IStream *strm_tmp; 2868 HRESULT hr; 2869 2870 /* create & populate file1 */ 2871 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1); 2872 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2873 if(FAILED(hr)) 2874 goto cleanup; 2875 2876 hr = create_test_file(file1); 2877 if(FAILED(hr)) 2878 goto cleanup; 2879 2880 /* create file2 */ 2881 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2); 2882 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr); 2883 if(FAILED(hr)) 2884 goto cleanup; 2885 2886 /* copy file1 to file2 with iid exclusions */ 2887 hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2); 2888 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr); 2889 if(FAILED(hr)) 2890 goto cleanup; 2891 2892 /* verify that file1 copied over, respecting exclusions */ 2893 hr = IStorage_OpenStorage(file2, stgA_name, NULL, 2894 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2895 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr); 2896 2897 if(SUCCEEDED(hr)){ 2898 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL, 2899 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2900 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2901 if(SUCCEEDED(hr)) 2902 IStream_Release(strm_tmp); 2903 2904 IStorage_Release(stg_tmp); 2905 } 2906 2907 hr = IStorage_OpenStorage(file2, stgB_name, NULL, 2908 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp); 2909 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr); 2910 2911 if(SUCCEEDED(hr)){ 2912 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL, 2913 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2914 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2915 if(SUCCEEDED(hr)) 2916 IStream_Release(strm_tmp); 2917 2918 IStorage_Release(stg_tmp); 2919 } 2920 2921 hr = IStorage_OpenStream(file2, strmC_name, NULL, 2922 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp); 2923 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr); 2924 if(SUCCEEDED(hr)) 2925 IStream_Release(strm_tmp); 2926 2927 cleanup: 2928 if(file1) 2929 IStorage_Release(file1); 2930 if(file2) 2931 IStorage_Release(file2); 2932 2933 DeleteFileA(file1_nameA); 2934 DeleteFileA(file2_nameA); 2935 } 2936 2937 static void test_rename(void) 2938 { 2939 IStorage *stg, *stg2; 2940 IStream *stm; 2941 HRESULT r; 2942 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 2943 static const WCHAR stgname2[] = { 'S','T','G',0 }; 2944 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 2945 static const WCHAR stmname2[] = { 'E','N','T','S',0 }; 2946 BOOL ret; 2947 2948 DeleteFileA(filenameA); 2949 2950 /* create the file */ 2951 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 2952 STGM_READWRITE, 0, &stg); 2953 ok(r==S_OK, "StgCreateDocfile failed\n"); 2954 2955 /* create a substorage */ 2956 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 2957 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 2958 2959 /* create a stream in the substorage */ 2960 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); 2961 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r); 2962 IStream_Release(stm); 2963 2964 /* rename the stream */ 2965 r = IStorage_RenameElement(stg2, stmname, stmname2); 2966 ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r); 2967 2968 /* cannot open stream with old name */ 2969 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); 2970 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r); 2971 if (SUCCEEDED(r)) IStream_Release(stm); 2972 2973 /* can open stream with new name */ 2974 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); 2975 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r); 2976 if (SUCCEEDED(r)) IStream_Release(stm); 2977 2978 IStorage_Release(stg2); 2979 2980 /* rename the storage */ 2981 IStorage_RenameElement(stg, stgname, stgname2); 2982 2983 /* cannot open storage with old name */ 2984 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2); 2985 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r); 2986 if (SUCCEEDED(r)) IStorage_Release(stg2); 2987 2988 /* can open storage with new name */ 2989 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2); 2990 ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r); 2991 if (SUCCEEDED(r)) 2992 { 2993 /* opened storage still has the stream */ 2994 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); 2995 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r); 2996 if (SUCCEEDED(r)) IStream_Release(stm); 2997 2998 IStorage_Release(stg2); 2999 } 3000 3001 IStorage_Release(stg); 3002 3003 ret = DeleteFileA(filenameA); 3004 ok(ret, "deleted file\n"); 3005 } 3006 3007 static void test_toplevel_stat(void) 3008 { 3009 IStorage *stg = NULL; 3010 HRESULT r; 3011 STATSTG stat; 3012 char prev_dir[MAX_PATH]; 3013 char temp[MAX_PATH]; 3014 char full_path[MAX_PATH]; 3015 LPSTR rel_pathA; 3016 WCHAR rel_path[MAX_PATH]; 3017 3018 DeleteFileA(filenameA); 3019 3020 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 3021 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 3022 ok(r==S_OK, "StgCreateDocfile failed\n"); 3023 3024 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT ); 3025 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r); 3026 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n", 3027 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName)); 3028 CoTaskMemFree(stat.pwcsName); 3029 3030 IStorage_Release( stg ); 3031 3032 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg); 3033 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 3034 3035 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT ); 3036 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r); 3037 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n", 3038 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName)); 3039 CoTaskMemFree(stat.pwcsName); 3040 3041 IStorage_Release( stg ); 3042 3043 DeleteFileA(filenameA); 3044 3045 /* Stat always returns the full path, even for files opened with a relative path. */ 3046 GetCurrentDirectoryA(MAX_PATH, prev_dir); 3047 3048 GetTempPathA(MAX_PATH, temp); 3049 3050 SetCurrentDirectoryA(temp); 3051 3052 GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA); 3053 MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH); 3054 3055 r = StgCreateDocfile( rel_path, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 3056 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 3057 ok(r==S_OK, "StgCreateDocfile failed\n"); 3058 3059 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT ); 3060 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r); 3061 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n", 3062 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName)); 3063 CoTaskMemFree(stat.pwcsName); 3064 3065 IStorage_Release( stg ); 3066 3067 r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg); 3068 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); 3069 3070 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT ); 3071 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r); 3072 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n", 3073 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName)); 3074 CoTaskMemFree(stat.pwcsName); 3075 3076 IStorage_Release( stg ); 3077 3078 SetCurrentDirectoryA(prev_dir); 3079 3080 DeleteFileA(filenameA); 3081 } 3082 3083 static void test_substorage_enum(void) 3084 { 3085 IStorage *stg, *stg2; 3086 IEnumSTATSTG *ee; 3087 HRESULT r; 3088 ULONG ref; 3089 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 }; 3090 BOOL ret; 3091 3092 DeleteFileA(filenameA); 3093 3094 /* create the file */ 3095 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 3096 STGM_READWRITE, 0, &stg); 3097 ok(r==S_OK, "StgCreateDocfile failed\n"); 3098 3099 /* create a substorage */ 3100 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 3101 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3102 3103 /* create an enumelements */ 3104 r = IStorage_EnumElements(stg2, 0, NULL, 0, &ee); 3105 ok(r==S_OK, "IStorage->EnumElements failed, hr=%08x\n", r); 3106 3107 /* release the substorage */ 3108 ref = IStorage_Release(stg2); 3109 todo_wine ok(ref==0, "storage not released\n"); 3110 3111 /* reopening fails, because the substorage is really still open */ 3112 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 3113 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage failed, hr=%08x\n", r); 3114 3115 /* destroying the storage invalidates the enumerator */ 3116 r = IStorage_DestroyElement(stg, stgname); 3117 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3118 3119 r = IEnumSTATSTG_Reset(ee); 3120 ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r); 3121 3122 IEnumSTATSTG_Release(ee); 3123 3124 IStorage_Release(stg); 3125 3126 ret = DeleteFileA(filenameA); 3127 ok(ret, "deleted file\n"); 3128 } 3129 3130 static void test_copyto_locking(void) 3131 { 3132 IStorage *stg, *stg2, *stg3, *stg4; 3133 IStream *stm; 3134 HRESULT r; 3135 static const WCHAR stgname[] = { 'S','T','G','1',0 }; 3136 static const WCHAR stgname2[] = { 'S','T','G','2',0 }; 3137 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 3138 BOOL ret; 3139 3140 DeleteFileA(filenameA); 3141 3142 /* create the file */ 3143 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 3144 STGM_READWRITE, 0, &stg); 3145 ok(r==S_OK, "StgCreateDocfile failed\n"); 3146 3147 /* create a substorage */ 3148 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 3149 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3150 3151 /* create another substorage */ 3152 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3); 3153 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3154 3155 /* add a stream, and leave it open */ 3156 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); 3157 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r); 3158 3159 /* Try to copy the storage while the stream is open */ 3160 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3); 3161 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r); 3162 3163 IStream_Release(stm); 3164 3165 /* create a substorage */ 3166 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg4); 3167 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3168 3169 /* Try to copy the storage while the substorage is open */ 3170 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3); 3171 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r); 3172 3173 IStorage_Release(stg4); 3174 IStorage_Release(stg3); 3175 IStorage_Release(stg2); 3176 IStorage_Release(stg); 3177 3178 ret = DeleteFileA(filenameA); 3179 ok(ret, "deleted file\n"); 3180 } 3181 3182 static void test_copyto_recursive(void) 3183 { 3184 IStorage *stg, *stg2, *stg3, *stg4; 3185 HRESULT r; 3186 static const WCHAR stgname[] = { 'S','T','G','1',0 }; 3187 static const WCHAR stgname2[] = { 'S','T','G','2',0 }; 3188 BOOL ret; 3189 3190 DeleteFileA(filenameA); 3191 3192 /* create the file */ 3193 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 3194 STGM_READWRITE, 0, &stg); 3195 ok(r==S_OK, "StgCreateDocfile failed\n"); 3196 3197 /* create a substorage */ 3198 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2); 3199 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3200 3201 /* copy the parent to the child */ 3202 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2); 3203 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r); 3204 3205 /* create a transacted substorage */ 3206 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg3); 3207 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3208 3209 /* copy the parent to the transacted child */ 3210 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2); 3211 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r); 3212 3213 /* create a transacted subsubstorage */ 3214 r = IStorage_CreateStorage(stg3, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg4); 3215 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r); 3216 3217 /* copy the parent to the transacted child of the transacted child */ 3218 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg4); 3219 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r); 3220 3221 /* copy the parent but exclude storage objects */ 3222 r = IStorage_CopyTo(stg, 1, &IID_IStorage, NULL, stg4); 3223 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r); 3224 3225 IStorage_Release(stg4); 3226 IStorage_Release(stg3); 3227 IStorage_Release(stg2); 3228 IStorage_Release(stg); 3229 3230 ret = DeleteFileA(filenameA); 3231 ok(ret, "deleted file\n"); 3232 } 3233 3234 static void test_hglobal_storage_creation(void) 3235 { 3236 ILockBytes *ilb = NULL; 3237 IStorage *stg = NULL; 3238 HRESULT r; 3239 STATSTG stat; 3240 char junk[512]; 3241 ULARGE_INTEGER offset; 3242 3243 r = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb); 3244 ok(r == S_OK, "CreateILockBytesOnHGlobal failed, hr=%x\n", r); 3245 3246 offset.QuadPart = 0; 3247 memset(junk, 0xaa, 512); 3248 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL); 3249 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r); 3250 3251 offset.QuadPart = 2000; 3252 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL); 3253 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r); 3254 3255 r = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg); 3256 ok(r == S_OK, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r); 3257 3258 IStorage_Release(stg); 3259 3260 r = StgOpenStorageOnILockBytes(ilb, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 3261 NULL, 0, &stg); 3262 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r); 3263 3264 if (SUCCEEDED(r)) 3265 { 3266 r = IStorage_Stat(stg, &stat, STATFLAG_NONAME); 3267 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r); 3268 ok(IsEqualCLSID(&stat.clsid, &GUID_NULL), "unexpected CLSID value\n"); 3269 3270 IStorage_Release(stg); 3271 } 3272 3273 r = ILockBytes_Stat(ilb, &stat, STATFLAG_NONAME); 3274 ok(r == S_OK, "ILockBytes_Stat failed, hr=%x\n", r); 3275 ok(stat.cbSize.u.LowPart < 2512, "expected truncated size, got %d\n", stat.cbSize.u.LowPart); 3276 3277 ILockBytes_Release(ilb); 3278 } 3279 3280 static void test_convert(void) 3281 { 3282 static const WCHAR filename[] = {'s','t','o','r','a','g','e','.','s','t','g',0}; 3283 IStorage *stg; 3284 HRESULT hr; 3285 3286 hr = GetConvertStg(NULL); 3287 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3288 3289 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 3290 ok(hr == S_OK, "StgCreateDocfile failed\n"); 3291 hr = GetConvertStg(stg); 3292 ok(hr == STG_E_FILENOTFOUND, "got 0x%08x\n", hr); 3293 hr = SetConvertStg(stg, TRUE); 3294 ok(hr == S_OK, "got 0x%08x\n", hr); 3295 hr = SetConvertStg(stg, TRUE); 3296 ok(hr == S_OK, "got 0x%08x\n", hr); 3297 hr = GetConvertStg(stg); 3298 ok(hr == S_OK, "got 0x%08x\n", hr); 3299 hr = SetConvertStg(stg, FALSE); 3300 ok(hr == S_OK, "got 0x%08x\n", hr); 3301 hr = GetConvertStg(stg); 3302 ok(hr == S_FALSE, "got 0x%08x\n", hr); 3303 3304 IStorage_Release(stg); 3305 3306 DeleteFileW(filename); 3307 } 3308 3309 static void test_direct_swmr(void) 3310 { 3311 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0}; 3312 IDirectWriterLock *dwlock; 3313 ULONG ref, ref2; 3314 IStorage *stg; 3315 HRESULT hr; 3316 3317 /* it's possible to create in writer mode */ 3318 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_DIRECT_SWMR, 0, &stg); 3319 todo_wine 3320 ok(hr == S_OK, "got %08x\n", hr); 3321 if (hr == S_OK) { 3322 IStorage_Release(stg); 3323 DeleteFileW(fileW); 3324 } 3325 3326 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg); 3327 ok(hr == S_OK, "got %08x\n", hr); 3328 IStorage_Release(stg); 3329 3330 /* reader mode */ 3331 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg); 3332 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr); 3333 if(hr == S_OK) 3334 { 3335 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock); 3336 ok(hr == E_NOINTERFACE, "got %08x\n", hr); 3337 IStorage_Release(stg); 3338 } 3339 3340 /* writer mode */ 3341 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 3342 ok(hr == S_OK, "got %08x\n", hr); 3343 if(hr == S_OK) 3344 { 3345 ref = IStorage_AddRef(stg); 3346 IStorage_Release(stg); 3347 3348 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock); 3349 ok(hr == S_OK, "got %08x\n", hr); 3350 3351 ref2 = IStorage_AddRef(stg); 3352 IStorage_Release(stg); 3353 ok(ref2 == ref + 1, "got %u\n", ref2); 3354 3355 IDirectWriterLock_Release(dwlock); 3356 IStorage_Release(stg); 3357 } 3358 3359 DeleteFileW(fileW); 3360 } 3361 3362 struct lock_test 3363 { 3364 DWORD stg_mode; 3365 BOOL create; 3366 DWORD access; 3367 DWORD sharing; 3368 const int *locked_bytes; 3369 const int *fail_ranges; 3370 BOOL todo; 3371 }; 3372 3373 static const int priority_locked_bytes[] = { 0x158, 0x181, 0x193, -1 }; 3374 static const int rwex_locked_bytes[] = { 0x193, 0x1a7, 0x1bb, 0x1cf, -1 }; 3375 static const int rw_locked_bytes[] = { 0x193, 0x1a7, -1 }; 3376 static const int nosn_locked_bytes[] = { 0x16c, 0x193, 0x1a7, 0x1cf, -1 }; 3377 static const int rwdw_locked_bytes[] = { 0x193, 0x1a7, 0x1cf, -1 }; 3378 static const int wodw_locked_bytes[] = { 0x1a7, 0x1cf, -1 }; 3379 static const int tr_locked_bytes[] = { 0x193, -1 }; 3380 static const int no_locked_bytes[] = { -1 }; 3381 static const int roex_locked_bytes[] = { 0x193, 0x1bb, 0x1cf, -1 }; 3382 3383 static const int rwex_fail_ranges[] = { 0x193,0x1e3, -1 }; 3384 static const int rw_fail_ranges[] = { 0x1bb,0x1e3, -1 }; 3385 static const int rwdw_fail_ranges[] = { 0x1a7,0x1e3, -1 }; 3386 static const int dw_fail_ranges[] = { 0x1a7,0x1cf, -1 }; 3387 static const int tr_fail_ranges[] = { 0x1bb,0x1cf, -1 }; 3388 static const int pr_fail_ranges[] = { 0x180,0x181, 0x1bb,0x1cf, -1 }; 3389 static const int roex_fail_ranges[] = { 0x0,-1 }; 3390 3391 static const struct lock_test lock_tests[] = { 3392 { STGM_PRIORITY, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, priority_locked_bytes, pr_fail_ranges, FALSE }, 3393 { STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE }, 3394 { STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE }, 3395 { STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, 0, FALSE }, 3396 { STGM_CREATE|STGM_READWRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, 0, FALSE }, 3397 { STGM_CREATE|STGM_WRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, wodw_locked_bytes, 0, FALSE }, 3398 { STGM_SHARE_EXCLUSIVE|STGM_READWRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE }, 3399 { STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE }, 3400 { STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, rw_fail_ranges, FALSE }, 3401 { STGM_READWRITE|STGM_TRANSACTED|STGM_NOSNAPSHOT, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nosn_locked_bytes, rwdw_fail_ranges, FALSE }, 3402 { STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, rwdw_fail_ranges, FALSE }, 3403 { STGM_READ|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ, FILE_SHARE_READ, no_locked_bytes, dw_fail_ranges, TRUE }, 3404 { STGM_READ|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, tr_locked_bytes, tr_fail_ranges, FALSE }, 3405 { STGM_READ|STGM_SHARE_EXCLUSIVE, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, FALSE }, 3406 { STGM_READ|STGM_SHARE_EXCLUSIVE|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, FALSE }, 3407 }; 3408 3409 static BOOL can_open(LPCWSTR filename, DWORD access, DWORD sharing) 3410 { 3411 HANDLE hfile; 3412 3413 hfile = CreateFileW(filename, access, sharing, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 3414 3415 if (hfile == INVALID_HANDLE_VALUE) 3416 return FALSE; 3417 3418 CloseHandle(hfile); 3419 return TRUE; 3420 } 3421 3422 static void check_sharing(LPCWSTR filename, const struct lock_test *current, 3423 DWORD access, DWORD sharing, const char *desc, DWORD *open_mode, BOOL *any_failure) 3424 { 3425 if (can_open(filename, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE)) 3426 { 3427 *open_mode = access; 3428 if (!current->todo || (current->sharing & sharing)) 3429 ok(current->sharing & sharing || 3430 broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */, 3431 "file with mode %x should not be openable with %s permission\n", current->stg_mode, desc); 3432 else 3433 { 3434 todo_wine ok(current->sharing & sharing || 3435 broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */, 3436 "file with mode %x should not be openable with %s permission\n", current->stg_mode, desc); 3437 *any_failure = TRUE; 3438 } 3439 } 3440 else 3441 { 3442 if (!current->todo || !(current->sharing & sharing)) 3443 ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc); 3444 else 3445 { 3446 todo_wine ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc); 3447 *any_failure = TRUE; 3448 } 3449 } 3450 } 3451 3452 static void check_access(LPCWSTR filename, const struct lock_test *current, 3453 DWORD access, DWORD sharing, const char *desc, DWORD open_mode, BOOL *any_failure) 3454 { 3455 if (can_open(filename, open_mode, (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) & ~sharing)) 3456 { 3457 if (!current->todo || !(current->access & access)) 3458 ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc); 3459 else 3460 { 3461 todo_wine ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc); 3462 *any_failure = TRUE; 3463 } 3464 } 3465 else 3466 { 3467 if (!current->todo || (current->access & access)) 3468 ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc); 3469 else 3470 { 3471 todo_wine ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc); 3472 *any_failure = TRUE; 3473 } 3474 } 3475 } 3476 3477 static void test_locking(void) 3478 { 3479 static const WCHAR filename[] = {'w','i','n','e','t','e','s','t',0}; 3480 int i; 3481 IStorage *stg; 3482 HRESULT hr; 3483 3484 for (i=0; i<sizeof(lock_tests)/sizeof(lock_tests[0]); i++) 3485 { 3486 const struct lock_test *current = &lock_tests[i]; 3487 BOOL any_failure = FALSE; 3488 DWORD open_mode = 0; 3489 3490 if (current->create) 3491 { 3492 hr = StgCreateDocfile(filename, current->stg_mode, 0, &stg); 3493 ok(SUCCEEDED(hr), "StgCreateDocfile with mode %x failed with hr %x\n", current->stg_mode, hr); 3494 if (FAILED(hr)) continue; 3495 } 3496 else 3497 { 3498 hr = StgCreateDocfile(filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); 3499 ok(SUCCEEDED(hr), "StgCreateDocfile failed with hr %x\n", hr); 3500 if (FAILED(hr)) continue; 3501 IStorage_Release(stg); 3502 3503 hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg); 3504 ok(SUCCEEDED(hr), "StgOpenStorage with mode %x failed with hr %x\n", current->stg_mode, hr); 3505 if (FAILED(hr)) 3506 { 3507 DeleteFileW(filename); 3508 continue; 3509 } 3510 } 3511 3512 check_sharing(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", &open_mode, &any_failure); 3513 check_sharing(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", &open_mode, &any_failure); 3514 check_sharing(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", &open_mode, &any_failure); 3515 3516 if (open_mode != 0) 3517 { 3518 HANDLE hfile; 3519 BOOL locked, expect_locked; 3520 OVERLAPPED ol; 3521 const int* next_lock = current->locked_bytes; 3522 3523 check_access(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", open_mode, &any_failure); 3524 check_access(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", open_mode, &any_failure); 3525 check_access(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", open_mode, &any_failure); 3526 3527 hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 3528 ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode); 3529 3530 ol.OffsetHigh = 0; 3531 ol.hEvent = NULL; 3532 3533 for (ol.Offset = 0x7ffffe00; ol.Offset != 0x80000000; ol.Offset++) 3534 { 3535 if (LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol)) 3536 locked = FALSE; 3537 else 3538 { 3539 ok(!LockFileEx(hfile, LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol), "shared locks should not be used\n"); 3540 locked = TRUE; 3541 } 3542 3543 UnlockFileEx(hfile, 0, 1, 0, &ol); 3544 3545 if ((ol.Offset&0x1ff) == *next_lock) 3546 { 3547 expect_locked = TRUE; 3548 next_lock++; 3549 } 3550 else 3551 expect_locked = FALSE; 3552 3553 if (!current->todo || locked == expect_locked) 3554 ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n", 3555 ol.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not "); 3556 else 3557 { 3558 any_failure = TRUE; 3559 todo_wine ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n", 3560 ol.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not "); 3561 } 3562 } 3563 3564 CloseHandle(hfile); 3565 } 3566 3567 IStorage_Release( stg ); 3568 3569 if (!current->create) 3570 { 3571 HANDLE hfile; 3572 BOOL failed, expect_failed=FALSE; 3573 OVERLAPPED ol; 3574 const int* next_range = current->fail_ranges; 3575 3576 hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 3577 ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode); 3578 3579 ol.OffsetHigh = 0; 3580 ol.hEvent = NULL; 3581 3582 for (ol.Offset = 0x7ffffe00; ol.Offset != 0x80000000; ol.Offset++) 3583 { 3584 if (ol.Offset == 0x7fffff92 || 3585 (ol.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READWRITE)) || 3586 (ol.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READ))) 3587 continue; /* This makes opens hang */ 3588 3589 if (ol.Offset < 0x7fffff00) 3590 LockFileEx(hfile, 0, 0, 1, 0, &ol); 3591 else 3592 LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol); 3593 3594 hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg); 3595 ok(hr == S_OK || hr == STG_E_LOCKVIOLATION || hr == STG_E_SHAREVIOLATION, "failed with unexpected hr %x\n", hr); 3596 if (SUCCEEDED(hr)) IStorage_Release(stg); 3597 3598 UnlockFileEx(hfile, 0, 1, 0, &ol); 3599 3600 failed = FAILED(hr); 3601 3602 if (!expect_failed && (ol.Offset&0x1ff) == next_range[0]) 3603 { 3604 expect_failed = TRUE; 3605 } 3606 else if (expect_failed && (ol.Offset&0x1ff) == next_range[1]) 3607 { 3608 expect_failed = FALSE; 3609 next_range += 2; 3610 } 3611 3612 if (!current->todo || failed == expect_failed) 3613 ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n", 3614 ol.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed"); 3615 else 3616 { 3617 any_failure = TRUE; 3618 todo_wine ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n", 3619 ol.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed"); 3620 } 3621 } 3622 3623 CloseHandle(hfile); 3624 } 3625 3626 DeleteFileW(filename); 3627 3628 if (current->todo && !any_failure) 3629 todo_wine ok(1, "tests succeeded for mode %x\n", current->stg_mode); 3630 } 3631 } 3632 3633 static void test_transacted_shared(void) 3634 { 3635 IStorage *stg = NULL; 3636 IStorage *stgrw = NULL; 3637 HRESULT r; 3638 IStream *stm = NULL; 3639 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 3640 LARGE_INTEGER pos; 3641 ULARGE_INTEGER upos; 3642 char buffer[10]; 3643 ULONG bytesread; 3644 3645 DeleteFileA(filenameA); 3646 3647 /* create a new transacted storage with a stream */ 3648 r = StgCreateDocfile(filename, STGM_CREATE | 3649 STGM_READWRITE |STGM_TRANSACTED, 0, &stg); 3650 ok(r==S_OK, "StgCreateDocfile failed %x\n", r); 3651 3652 r = WriteClassStg(stg, &test_stg_cls); 3653 ok(r == S_OK, "WriteClassStg failed %x\n", r); 3654 3655 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm); 3656 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r); 3657 3658 pos.QuadPart = 0; 3659 r = IStream_Seek(stm, pos, 0, &upos); 3660 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3661 3662 r = IStream_Write(stm, "aaa", 3, NULL); 3663 ok(r==S_OK, "IStream->Write failed %x\n", r); 3664 3665 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT); 3666 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3667 3668 /* open a second transacted read/write storage */ 3669 r = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_NONE, NULL, 0, &stgrw); 3670 ok(r==S_OK, "StgOpenStorage failed %x\n", r); 3671 3672 /* update stream on the first storage and commit */ 3673 pos.QuadPart = 0; 3674 r = IStream_Seek(stm, pos, 0, &upos); 3675 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3676 3677 r = IStream_Write(stm, "ccc", 3, NULL); 3678 ok(r==S_OK, "IStream->Write failed %x\n", r); 3679 3680 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT); 3681 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3682 3683 /* update again without committing */ 3684 pos.QuadPart = 0; 3685 r = IStream_Seek(stm, pos, 0, &upos); 3686 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3687 3688 r = IStream_Write(stm, "ddd", 3, NULL); 3689 ok(r==S_OK, "IStream->Write failed %x\n", r); 3690 3691 IStream_Release(stm); 3692 3693 /* we can still read the old content from the second storage */ 3694 r = IStorage_OpenStream(stgrw, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); 3695 ok(r==S_OK, "IStorage->OpenStream failed %x\n", r); 3696 3697 pos.QuadPart = 0; 3698 r = IStream_Seek(stm, pos, 0, &upos); 3699 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3700 3701 r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread); 3702 ok(r==S_OK, "IStream->Read failed %x\n", r); 3703 ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread); 3704 ok(memcmp(buffer, "aaa", 3) == 0, "wrong data\n"); 3705 3706 /* and overwrite the data */ 3707 pos.QuadPart = 0; 3708 r = IStream_Seek(stm, pos, 0, &upos); 3709 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3710 3711 r = IStream_Write(stm, "bbb", 3, NULL); 3712 ok(r==S_OK, "IStream->Write failed %x\n", r); 3713 3714 IStream_Release(stm); 3715 3716 /* commit fails because we're out of date */ 3717 r = IStorage_Commit(stgrw, STGC_ONLYIFCURRENT); 3718 ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r); 3719 3720 /* unless we force it */ 3721 r = IStorage_Commit(stgrw, STGC_DEFAULT); 3722 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3723 3724 /* reverting gets us back to the last commit from the same storage */ 3725 r = IStorage_Revert(stg); 3726 ok(r==S_OK, "IStorage->Revert failed %x\n", r); 3727 3728 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); 3729 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r); 3730 3731 pos.QuadPart = 0; 3732 r = IStream_Seek(stm, pos, 0, &upos); 3733 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3734 3735 r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread); 3736 ok(r==S_OK, "IStream->Read failed %x\n", r); 3737 ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread); 3738 ok(memcmp(buffer, "ccc", 3) == 0, "wrong data\n"); 3739 3740 /* and committing fails forever */ 3741 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT); 3742 ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r); 3743 3744 IStream_Release(stm); 3745 3746 IStorage_Release(stg); 3747 IStorage_Release(stgrw); 3748 3749 DeleteFileA(filenameA); 3750 } 3751 3752 static void test_overwrite(void) 3753 { 3754 IStorage *stg = NULL; 3755 HRESULT r; 3756 IStream *stm = NULL; 3757 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 3758 static const WCHAR stmname2[] = { 'C','O','N','T','E','N','T','2',0 }; 3759 LARGE_INTEGER pos; 3760 ULARGE_INTEGER upos; 3761 char buffer[4096]; 3762 DWORD orig_size, new_size; 3763 ULONG bytesread; 3764 HANDLE hfile; 3765 int i; 3766 3767 DeleteFileA(filenameA); 3768 3769 r = StgCreateDocfile(filename, STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg); 3770 ok(r==S_OK, "StgCreateDocfile failed %x\n", r); 3771 3772 r = WriteClassStg(stg, &test_stg_cls); 3773 ok(r == S_OK, "WriteClassStg failed %x\n", r); 3774 3775 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm); 3776 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r); 3777 3778 pos.QuadPart = 0; 3779 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos); 3780 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3781 3782 memset(buffer, 'a', sizeof(buffer)); 3783 for (i=0; i<4; i++) 3784 { 3785 /* Write enough bytes to pass the minimum storage file size */ 3786 r = IStream_Write(stm, buffer, sizeof(buffer), NULL); 3787 ok(r==S_OK, "IStream->Write failed %x\n", r); 3788 } 3789 3790 r = IStorage_Commit(stg, STGC_DEFAULT); 3791 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3792 3793 hfile = CreateFileA(filenameA, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 3794 NULL, OPEN_EXISTING, 0, NULL); 3795 ok(hfile != NULL, "couldn't open file %d\n", GetLastError()); 3796 3797 orig_size = GetFileSize(hfile, NULL); 3798 3799 pos.QuadPart = 0; 3800 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos); 3801 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3802 3803 r = IStream_Write(stm, "b", 1, NULL); 3804 ok(r==S_OK, "IStream->Write failed %x\n", r); 3805 3806 r = IStorage_Commit(stg, STGC_OVERWRITE); 3807 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3808 3809 new_size = GetFileSize(hfile, NULL); 3810 3811 todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size); 3812 3813 IStream_Release(stm); 3814 3815 IStorage_RenameElement(stg, stmname, stmname2); 3816 3817 r = IStorage_Commit(stg, STGC_OVERWRITE); 3818 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3819 3820 new_size = GetFileSize(hfile, NULL); 3821 3822 todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size); 3823 3824 IStorage_Release(stg); 3825 3826 r = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); 3827 ok(r==S_OK, "StgOpenStorage failed %x\n", r); 3828 3829 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm); 3830 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r); 3831 3832 r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread); 3833 ok(r==S_OK, "IStream->Write failed %x\n", r); 3834 ok(bytesread == sizeof(buffer), "only read %d bytes\n", bytesread); 3835 ok(buffer[0] == 'b', "unexpected data at byte 0\n"); 3836 3837 for (i=1; i<sizeof(buffer); i++) 3838 if (buffer[i] != 'a') 3839 break; 3840 ok(i == sizeof(buffer), "unexpected data at byte %i\n", i); 3841 3842 pos.QuadPart = 0; 3843 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos); 3844 ok(r==S_OK, "IStream->Seek failed %x\n", r); 3845 3846 r = IStream_Write(stm, "c", 1, NULL); 3847 ok(r==S_OK, "IStream->Write failed %x\n", r); 3848 3849 r = IStorage_Commit(stg, STGC_OVERWRITE); 3850 ok(r==S_OK, "IStorage->Commit failed %x\n", r); 3851 3852 new_size = GetFileSize(hfile, NULL); 3853 3854 todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size); 3855 3856 IStream_Release(stm); 3857 3858 IStorage_Release(stg); 3859 3860 CloseHandle(hfile); 3861 3862 DeleteFileA(filenameA); 3863 } 3864 3865 static void test_custom_lockbytes(void) 3866 { 3867 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; 3868 TestLockBytes* lockbytes; 3869 HRESULT hr; 3870 IStorage* stg; 3871 IStream* stm; 3872 3873 CreateTestLockBytes(&lockbytes); 3874 3875 hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); 3876 ok(hr==S_OK, "StgCreateDocfileOnILockBytes failed %x\n", hr); 3877 3878 hr = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stm); 3879 ok(hr==S_OK, "IStorage_CreateStream failed %x\n", hr); 3880 3881 IStream_Release(stm); 3882 3883 hr = IStorage_Commit(stg, 0); 3884 3885 IStorage_Release(stg); 3886 3887 ok(!lockbytes->lock_called, "unexpected call to LockRegion\n"); 3888 3889 lockbytes->locks_supported = LOCK_WRITE|LOCK_EXCLUSIVE|LOCK_ONLYONCE; 3890 3891 hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); 3892 ok(hr==S_OK, "StgCreateDocfileOnILockBytes failed %x\n", hr); 3893 3894 hr = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stm); 3895 ok(hr==S_OK, "IStorage_CreateStream failed %x\n", hr); 3896 3897 IStream_Release(stm); 3898 3899 hr = IStorage_Commit(stg, 0); 3900 3901 IStorage_Release(stg); 3902 3903 ok(lockbytes->lock_called, "expected LockRegion to be called\n"); 3904 3905 lockbytes->lock_hr = STG_E_INVALIDFUNCTION; 3906 3907 hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); 3908 ok(hr==STG_E_INVALIDFUNCTION, "StgCreateDocfileOnILockBytes failed %x\n", hr); 3909 3910 DeleteTestLockBytes(lockbytes); 3911 } 3912 3913 START_TEST(storage32) 3914 { 3915 CHAR temp[MAX_PATH]; 3916 3917 GetTempPathA(MAX_PATH, temp); 3918 if(!GetTempFileNameA(temp, "stg", 0, filenameA)) 3919 { 3920 win_skip("Could not create temp file, %u\n", GetLastError()); 3921 return; 3922 } 3923 MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH); 3924 DeleteFileA(filenameA); 3925 3926 test_hglobal_storage_stat(); 3927 test_create_storage_modes(); 3928 test_stgcreatestorageex(); 3929 test_storage_stream(); 3930 test_open_storage(); 3931 test_storage_suminfo(); 3932 test_storage_refcount(); 3933 test_streamenum(); 3934 test_transact(); 3935 test_substorage_share(); 3936 test_revert(); 3937 test_parent_free(); 3938 test_nonroot_transacted(); 3939 test_ReadClassStm(); 3940 test_access(); 3941 test_writeclassstg(); 3942 test_readonly(); 3943 test_simple(); 3944 test_fmtusertypestg(); 3945 test_references(); 3946 test_copyto(); 3947 test_copyto_snbexclusions(); 3948 test_copyto_iidexclusions_storage(); 3949 test_copyto_iidexclusions_stream(); 3950 test_rename(); 3951 test_toplevel_stat(); 3952 test_substorage_enum(); 3953 test_copyto_locking(); 3954 test_copyto_recursive(); 3955 test_hglobal_storage_creation(); 3956 test_convert(); 3957 test_direct_swmr(); 3958 test_locking(); 3959 test_transacted_shared(); 3960 test_overwrite(); 3961 test_custom_lockbytes(); 3962 } 3963