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