From 5116b979b212981efa5312ac0fa47147d92f9295 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Sat, 17 Jul 2010 13:07:21 -0500 Subject: [PATCH] ole32: Flush the ILockBytes object of a storage on commit and final release. Some ILockBytes objects will not really write changes until their Flush method is called. Also, further optimizations to the storage implementation will involve caching writes, which will have to be flushed at times. --- dlls/ole32/stg_stream.c | 2 +- dlls/ole32/storage32.c | 55 ++++++++++++++++++++++++++++++++++------- dlls/ole32/storage32.h | 6 +++++ 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/dlls/ole32/stg_stream.c b/dlls/ole32/stg_stream.c index bfecbc72bd1..1fdb963f56b 100644 --- a/dlls/ole32/stg_stream.c +++ b/dlls/ole32/stg_stream.c @@ -517,7 +517,7 @@ static HRESULT WINAPI StgStreamImpl_Commit( return STG_E_REVERTED; } - return S_OK; + return StorageBaseImpl_Flush(This->parentStorage); } /*** diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 64db9f66266..185b8b0d764 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -92,6 +92,7 @@ static StorageInternalImpl* StorageInternalImpl_Construct(StorageBaseImpl* paren DWORD openFlags, DirRef storageDirEntry); static void StorageImpl_Destroy(StorageBaseImpl* iface); static void StorageImpl_Invalidate(StorageBaseImpl* iface); +static HRESULT StorageImpl_Flush(StorageBaseImpl* iface); static BOOL StorageImpl_ReadBigBlock(StorageImpl* This, ULONG blockIndex, void* buffer); static BOOL StorageImpl_WriteBigBlock(StorageImpl* This, ULONG blockIndex, const void* buffer); static void StorageImpl_SetNextBlockInChain(StorageImpl* This, ULONG blockIndex, ULONG nextBlock); @@ -1815,16 +1816,15 @@ static HRESULT WINAPI StorageBaseImpl_MoveElementTo( * Ensures that any changes made to a storage object open in transacted mode * are reflected in the parent storage * - * NOTES - * Wine doesn't implement transacted mode, which seems to be a basic - * optimization, so we can ignore this stub for now. + * In a non-transacted mode, this ensures all cached writes are completed. */ static HRESULT WINAPI StorageImpl_Commit( IStorage* iface, DWORD grfCommitFlags)/* [in] */ { - FIXME("(%p %d): stub\n", iface, grfCommitFlags); - return S_OK; + StorageBaseImpl* const base=(StorageBaseImpl*)iface; + TRACE("(%p %d)\n", iface, grfCommitFlags); + return StorageBaseImpl_Flush(base); } /************************************************************************* @@ -2625,6 +2625,7 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl = { StorageImpl_Destroy, StorageImpl_Invalidate, + StorageImpl_Flush, StorageImpl_GetFilename, StorageImpl_CreateDirEntry, StorageImpl_BaseWriteDirEntry, @@ -2868,6 +2869,8 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface) int i; TRACE("(%p)\n", This); + StorageImpl_Flush(iface); + StorageImpl_Invalidate(iface); BlockChainStream_Destroy(This->smallBlockRootChain); @@ -2882,6 +2885,13 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface) HeapFree(GetProcessHeap(), 0, This); } +static HRESULT StorageImpl_Flush(StorageBaseImpl* iface) +{ + StorageImpl *This = (StorageImpl*) iface; + + return ILockBytes_Flush(This->lockBytes); +} + /****************************************************************************** * Storage32Impl_GetNextFreeBigBlock * @@ -4525,9 +4535,12 @@ static HRESULT WINAPI TransactedSnapshotImpl_Commit( else dir_root_ref = This->entries[root_entry->data.dirRootEntry].newTransactedParentEntry; + hr = StorageBaseImpl_Flush(This->transactedParent); + /* Update the storage to use the new data in one step. */ - hr = StorageBaseImpl_ReadDirEntry(This->transactedParent, - root_entry->transactedParentEntry, &data); + if (SUCCEEDED(hr)) + hr = StorageBaseImpl_ReadDirEntry(This->transactedParent, + root_entry->transactedParentEntry, &data); if (SUCCEEDED(hr)) { @@ -4540,6 +4553,11 @@ static HRESULT WINAPI TransactedSnapshotImpl_Commit( root_entry->transactedParentEntry, &data); } + /* Try to flush after updating the root storage, but if the flush fails, keep + * going, on the theory that it'll either succeed later or the subsequent + * writes will fail. */ + StorageBaseImpl_Flush(This->transactedParent); + if (SUCCEEDED(hr)) { /* Destroy the old now-orphaned data. */ @@ -4579,6 +4597,9 @@ static HRESULT WINAPI TransactedSnapshotImpl_Commit( TransactedSnapshotImpl_DestroyTemporaryCopy(This, DIRENTRY_NULL); } + if (SUCCEEDED(hr)) + hr = StorageBaseImpl_Flush(This->transactedParent); + return hr; } @@ -4642,6 +4663,12 @@ static void TransactedSnapshotImpl_Destroy( StorageBaseImpl *iface) HeapFree(GetProcessHeap(), 0, This); } +static HRESULT TransactedSnapshotImpl_Flush(StorageBaseImpl* iface) +{ + /* We only need to flush when committing. */ + return S_OK; +} + static HRESULT TransactedSnapshotImpl_GetFilename(StorageBaseImpl* iface, LPWSTR *result) { TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) iface; @@ -4896,6 +4923,7 @@ static const StorageBaseImplVtbl TransactedSnapshotImpl_BaseVtbl = { TransactedSnapshotImpl_Destroy, TransactedSnapshotImpl_Invalidate, + TransactedSnapshotImpl_Flush, TransactedSnapshotImpl_GetFilename, TransactedSnapshotImpl_CreateDirEntry, TransactedSnapshotImpl_WriteDirEntry, @@ -5042,6 +5070,13 @@ static void StorageInternalImpl_Destroy( StorageBaseImpl *iface) HeapFree(GetProcessHeap(), 0, This); } +static HRESULT StorageInternalImpl_Flush(StorageBaseImpl* iface) +{ + StorageInternalImpl* This = (StorageInternalImpl*) iface; + + return StorageBaseImpl_Flush(This->parentStorage); +} + static HRESULT StorageInternalImpl_GetFilename(StorageBaseImpl* iface, LPWSTR *result) { StorageInternalImpl* This = (StorageInternalImpl*) iface; @@ -5130,8 +5165,9 @@ static HRESULT WINAPI StorageInternalImpl_Commit( IStorage* iface, DWORD grfCommitFlags) /* [in] */ { - FIXME("(%p,%x): stub\n", iface, grfCommitFlags); - return S_OK; + StorageBaseImpl* base = (StorageBaseImpl*) iface; + TRACE("(%p,%x)\n", iface, grfCommitFlags); + return StorageBaseImpl_Flush(base); } /****************************************************************************** @@ -5474,6 +5510,7 @@ static const StorageBaseImplVtbl StorageInternalImpl_BaseVtbl = { StorageInternalImpl_Destroy, StorageInternalImpl_Invalidate, + StorageInternalImpl_Flush, StorageInternalImpl_GetFilename, StorageInternalImpl_CreateDirEntry, StorageInternalImpl_WriteDirEntry, diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index 4baa0992fe4..9e7fe103fe9 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -234,6 +234,7 @@ struct StorageBaseImpl struct StorageBaseImplVtbl { void (*Destroy)(StorageBaseImpl*); void (*Invalidate)(StorageBaseImpl*); + HRESULT (*Flush)(StorageBaseImpl*); HRESULT (*GetFilename)(StorageBaseImpl*,LPWSTR*); HRESULT (*CreateDirEntry)(StorageBaseImpl*,const DirEntry*,DirRef*); HRESULT (*WriteDirEntry)(StorageBaseImpl*,DirRef,const DirEntry*); @@ -255,6 +256,11 @@ static inline void StorageBaseImpl_Invalidate(StorageBaseImpl *This) This->baseVtbl->Invalidate(This); } +static inline HRESULT StorageBaseImpl_Flush(StorageBaseImpl *This) +{ + return This->baseVtbl->Flush(This); +} + static inline HRESULT StorageBaseImpl_GetFilename(StorageBaseImpl *This, LPWSTR *result) { return This->baseVtbl->GetFilename(This, result);