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