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.
This commit is contained in:
Vincent Povirk 2010-07-17 13:07:21 -05:00 committed by Alexandre Julliard
parent b7dbfcbd48
commit 5116b979b2
3 changed files with 53 additions and 10 deletions

View file

@ -517,7 +517,7 @@ static HRESULT WINAPI StgStreamImpl_Commit(
return STG_E_REVERTED;
}
return S_OK;
return StorageBaseImpl_Flush(This->parentStorage);
}
/***

View file

@ -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,

View file

@ -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);