From e434cbaecdef6d0753e82afbb246ceca3366e9bb Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 2 Dec 2009 10:59:47 -0600 Subject: [PATCH 3/6] ole32: Add a stub transacted storage type. TransactedSnapshotImpl acts as a proxy between the user and the storage interfaces that modify the file directly (or another transacted storage). Currently, it does not change the operations. --- dlls/ole32/storage32.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++-- dlls/ole32/storage32.h | 5 + 2 files changed, 271 insertions(+), 10 deletions(-) diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index e16b9f8..faed984 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -118,6 +118,22 @@ static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This, static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEntry); static BOOL StorageBaseImpl_IsStorageOpen(StorageBaseImpl * stg, DirRef storageEntry); +/**************************************************************************** + * Transacted storage object that reads/writes a snapshot file. + */ +typedef struct TransactedSnapshotImpl +{ + struct StorageBaseImpl base; + + /* + * Changes are committed to the transacted parent. + */ + StorageBaseImpl *transactedParent; +} TransactedSnapshotImpl; + +/* Generic function to create a transacted wrapper for a direct storage object. */ +static HRESULT Storage_ConstructTransacted(StorageBaseImpl* parent, StorageBaseImpl** result); + /* OLESTREAM memory structure to use for Get and Put Routines */ /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ typedef struct @@ -508,7 +524,8 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage( IStorage** ppstg) /* [out] */ { StorageBaseImpl *This = (StorageBaseImpl *)iface; - StorageInternalImpl* newStorage; + StorageInternalImpl* newStorage; + StorageBaseImpl* newTransactedStorage; DirEntry currentEntry; DirRef storageEntryRef; HRESULT res = STG_E_UNKNOWN; @@ -593,7 +610,22 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage( if (newStorage != 0) { - *ppstg = (IStorage*)newStorage; + if (grfMode & STGM_TRANSACTED) + { + res = Storage_ConstructTransacted(&newStorage->base, &newTransactedStorage); + + if (FAILED(res)) + { + HeapFree(GetProcessHeap(), 0, newStorage); + goto end; + } + + *ppstg = (IStorage*)newTransactedStorage; + } + else + { + *ppstg = (IStorage*)newStorage; + } list_add_tail(&This->storageHead, &newStorage->ParentListEntry); @@ -1886,6 +1918,13 @@ static void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg) childstg = LIST_ENTRY(cur,StorageInternalImpl,ParentListEntry); StorageBaseImpl_Invalidate( &childstg->base ); } + + if (stg->transactedChild) + { + StorageBaseImpl_Invalidate(stg->transactedChild); + + stg->transactedChild = NULL; + } } @@ -3822,6 +3861,223 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks( return SmallBlockChainStream_Construct(This, NULL, streamEntryRef); } +static HRESULT WINAPI TransactedSnapshotImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags) /* [in] */ +{ + FIXME("(%p,%x): stub\n", iface, grfCommitFlags); + return S_OK; +} + +static HRESULT WINAPI TransactedSnapshotImpl_Revert( + IStorage* iface) +{ + FIXME("(%p): stub\n", iface); + return S_OK; +} + +static void TransactedSnapshotImpl_Invalidate(StorageBaseImpl* This) +{ + if (!This->reverted) + { + TRACE("Storage invalidated (stg=%p)\n", This); + + This->reverted = 1; + + StorageBaseImpl_DeleteAll(This); + } +} + +static void TransactedSnapshotImpl_Destroy( StorageBaseImpl *iface) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) iface; + + TransactedSnapshotImpl_Invalidate(iface); + + IStorage_Release((IStorage*)This->transactedParent); + + HeapFree(GetProcessHeap(), 0, This); +} + +static HRESULT TransactedSnapshotImpl_CreateDirEntry(StorageBaseImpl *base, + const DirEntry *newData, DirRef *index) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_CreateDirEntry(This->transactedParent, + newData, index); +} + +static HRESULT TransactedSnapshotImpl_WriteDirEntry(StorageBaseImpl *base, + DirRef index, const DirEntry *data) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_WriteDirEntry(This->transactedParent, + index, data); +} + +static HRESULT TransactedSnapshotImpl_ReadDirEntry(StorageBaseImpl *base, + DirRef index, DirEntry *data) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_ReadDirEntry(This->transactedParent, + index, data); +} + +static HRESULT TransactedSnapshotImpl_DestroyDirEntry(StorageBaseImpl *base, + DirRef index) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_DestroyDirEntry(This->transactedParent, + index); +} + +static HRESULT TransactedSnapshotImpl_StreamReadAt(StorageBaseImpl *base, + DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_StreamReadAt(This->transactedParent, + index, offset, size, buffer, bytesRead); +} + +static HRESULT TransactedSnapshotImpl_StreamWriteAt(StorageBaseImpl *base, + DirRef index, ULARGE_INTEGER offset, ULONG size, const void *buffer, ULONG *bytesWritten) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_StreamWriteAt(This->transactedParent, + index, offset, size, buffer, bytesWritten); +} + +static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base, + DirRef index, ULARGE_INTEGER newsize) +{ + TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base; + + return StorageBaseImpl_StreamSetSize(This->transactedParent, + index, newsize); +} + +static const IStorageVtbl TransactedSnapshotImpl_Vtbl = +{ + StorageBaseImpl_QueryInterface, + StorageBaseImpl_AddRef, + StorageBaseImpl_Release, + StorageBaseImpl_CreateStream, + StorageBaseImpl_OpenStream, + StorageBaseImpl_CreateStorage, + StorageBaseImpl_OpenStorage, + StorageBaseImpl_CopyTo, + StorageBaseImpl_MoveElementTo, + TransactedSnapshotImpl_Commit, + TransactedSnapshotImpl_Revert, + StorageBaseImpl_EnumElements, + StorageBaseImpl_DestroyElement, + StorageBaseImpl_RenameElement, + StorageBaseImpl_SetElementTimes, + StorageBaseImpl_SetClass, + StorageBaseImpl_SetStateBits, + StorageBaseImpl_Stat +}; + +static const StorageBaseImplVtbl TransactedSnapshotImpl_BaseVtbl = +{ + TransactedSnapshotImpl_Destroy, + TransactedSnapshotImpl_Invalidate, + TransactedSnapshotImpl_CreateDirEntry, + TransactedSnapshotImpl_WriteDirEntry, + TransactedSnapshotImpl_ReadDirEntry, + TransactedSnapshotImpl_DestroyDirEntry, + TransactedSnapshotImpl_StreamReadAt, + TransactedSnapshotImpl_StreamWriteAt, + TransactedSnapshotImpl_StreamSetSize +}; + +static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage, + TransactedSnapshotImpl** result) +{ + *result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TransactedSnapshotImpl)); + if (*result) + { + (*result)->base.lpVtbl = &TransactedSnapshotImpl_Vtbl; + + /* This is OK because the property set storage functions use the IStorage functions. */ + (*result)->base.pssVtbl = parentStorage->pssVtbl; + + (*result)->base.baseVtbl = &TransactedSnapshotImpl_BaseVtbl; + + list_init(&(*result)->base.strmHead); + + list_init(&(*result)->base.storageHead); + + (*result)->base.ref = 1; + + (*result)->base.storageDirEntry = parentStorage->storageDirEntry; + + (*result)->base.openFlags = parentStorage->openFlags; + + (*result)->base.filename = parentStorage->filename; + + /* parentStorage already has 1 reference, which we take over here. */ + (*result)->transactedParent = parentStorage; + + parentStorage->transactedChild = (StorageBaseImpl*)*result; + + return S_OK; + } + else + return E_OUTOFMEMORY; +} + +static HRESULT Storage_ConstructTransacted(StorageBaseImpl *parentStorage, + StorageBaseImpl** result) +{ + static int fixme=0; + + if (parentStorage->openFlags & (STGM_NOSCRATCH|STGM_NOSNAPSHOT) && !fixme++) + { + FIXME("Unimplemented flags %x\n", parentStorage->openFlags); + } + + return TransactedSnapshotImpl_Construct(parentStorage, + (TransactedSnapshotImpl**)result); +} + +static HRESULT Storage_Construct( + HANDLE hFile, + LPCOLESTR pwcsName, + ILockBytes* pLkbyt, + DWORD openFlags, + BOOL fileBased, + BOOL create, + StorageBaseImpl** result) +{ + StorageImpl *newStorage; + StorageBaseImpl *newTransactedStorage; + HRESULT hr; + + hr = StorageImpl_Construct(hFile, pwcsName, pLkbyt, openFlags, fileBased, create, &newStorage); + if (FAILED(hr)) goto end; + + if (openFlags & STGM_TRANSACTED) + { + hr = Storage_ConstructTransacted(&newStorage->base, &newTransactedStorage); + if (FAILED(hr)) + IStorage_Release((IStorage*)newStorage); + else + *result = newTransactedStorage; + } + else + *result = &newStorage->base; + +end: + return hr; +} + static void StorageInternalImpl_Invalidate( StorageBaseImpl *base ) { StorageInternalImpl* This = (StorageInternalImpl*) base; @@ -5866,7 +6122,7 @@ HRESULT WINAPI StgCreateDocfile( DWORD reserved, IStorage **ppstgOpen) { - StorageImpl* newStorage = 0; + StorageBaseImpl* newStorage = 0; HANDLE hFile = INVALID_HANDLE_VALUE; HRESULT hr = STG_E_INVALIDFLAG; DWORD shareMode; @@ -5975,7 +6231,7 @@ HRESULT WINAPI StgCreateDocfile( /* * Allocate and initialize the new IStorage32object. */ - hr = StorageImpl_Construct( + hr = Storage_Construct( hFile, pwcsName, NULL, @@ -6108,7 +6364,7 @@ HRESULT WINAPI StgOpenStorage( DWORD reserved, IStorage **ppstgOpen) { - StorageImpl* newStorage = 0; + StorageBaseImpl* newStorage = 0; HRESULT hr = S_OK; HANDLE hFile = 0; DWORD shareMode; @@ -6247,7 +6503,7 @@ HRESULT WINAPI StgOpenStorage( /* * Allocate and initialize the new IStorage32object. */ - hr = StorageImpl_Construct( + hr = Storage_Construct( hFile, pwcsName, NULL, @@ -6285,7 +6541,7 @@ HRESULT WINAPI StgCreateDocfileOnILockBytes( DWORD reserved, IStorage** ppstgOpen) { - StorageImpl* newStorage = 0; + StorageBaseImpl* newStorage = 0; HRESULT hr = S_OK; if ((ppstgOpen == 0) || (plkbyt == 0)) @@ -6294,7 +6550,7 @@ HRESULT WINAPI StgCreateDocfileOnILockBytes( /* * Allocate and initialize the new IStorage object. */ - hr = StorageImpl_Construct( + hr = Storage_Construct( 0, 0, plkbyt, @@ -6327,7 +6583,7 @@ HRESULT WINAPI StgOpenStorageOnILockBytes( DWORD reserved, IStorage **ppstgOpen) { - StorageImpl* newStorage = 0; + StorageBaseImpl* newStorage = 0; HRESULT hr = S_OK; if ((plkbyt == 0) || (ppstgOpen == 0)) @@ -6341,7 +6597,7 @@ HRESULT WINAPI StgOpenStorageOnILockBytes( /* * Allocate and initialize the new IStorage object. */ - hr = StorageImpl_Construct( + hr = Storage_Construct( 0, 0, plkbyt, diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index dcd460c..07a4b33 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -243,6 +243,11 @@ struct StorageBaseImpl BOOL create; /* Was the storage created or opened. The behaviour of STGM_SIMPLE depends on this */ + /* + * If this storage was opened in transacted mode, the object that implements + * the transacted snapshot or cache. + */ + StorageBaseImpl *transactedChild; }; /* virtual methods for StorageBaseImpl objects */ -- 1.6.3.3