Vincent Povirk : ole32: Flush the ILockBytes object of a storage on commit and final release.

Alexandre Julliard julliard at winehq.org
Mon Jul 19 11:05:32 CDT 2010


Module: wine
Branch: master
Commit: 5116b979b212981efa5312ac0fa47147d92f9295
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5116b979b212981efa5312ac0fa47147d92f9295

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Sat Jul 17 13:07:21 2010 -0500

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 bfecbc7..1fdb963 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 64db9f6..185b8b0 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 4baa099..9e7fe10 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);




More information about the wine-cvs mailing list