Andrew Eikum : ole32: Add big block chain to small block chain conversion routine.

Alexandre Julliard julliard at winehq.org
Thu Aug 20 12:59:18 CDT 2009


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

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Wed Aug 19 15:19:10 2009 -0500

ole32: Add big block chain to small block chain conversion routine.

---

 dlls/ole32/stg_stream.c |   15 +++++++-
 dlls/ole32/storage32.c  |   81 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ole32/storage32.h  |    4 ++
 3 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/dlls/ole32/stg_stream.c b/dlls/ole32/stg_stream.c
index f9a959d..36486f9 100644
--- a/dlls/ole32/stg_stream.c
+++ b/dlls/ole32/stg_stream.c
@@ -537,8 +537,6 @@ static HRESULT WINAPI StgStreamImpl_Seek(
  *
  * It will change the size of a stream.
  *
- * TODO: Switch from small blocks to big blocks and vice versa.
- *
  * See the documentation of IStream for more info.
  */
 static HRESULT WINAPI StgStreamImpl_SetSize(
@@ -626,6 +624,19 @@ static HRESULT WINAPI StgStreamImpl_SetSize(
                                 &This->smallBlockChain);
     }
   }
+  else if ( (This->bigBlockChain!=0) &&
+            (curProperty.size.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK) )
+  {
+    if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK)
+    {
+      /*
+       * Transform the big block chain into a small block chain
+       */
+      This->smallBlockChain = Storage32Impl_BigBlocksToSmallBlocks(
+                                This->parentStorage->ancestorStorage,
+                                &This->bigBlockChain);
+    }
+  }
 
   if (This->smallBlockChain!=0)
   {
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index d8c1d0b..4a27317 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -104,6 +104,7 @@ static ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This);
 static ULONG BlockChainStream_GetCount(BlockChainStream* This);
 
 static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This);
+static ULONG SmallBlockChainStream_GetHeadOfChain(SmallBlockChainStream* This);
 static BOOL StorageImpl_WriteDWordToBigBlock( StorageImpl* This,
     ULONG blockIndex, ULONG offset, DWORD value);
 static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl*  This,
@@ -3627,6 +3628,86 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
   return bigBlockChain;
 }
 
+/******************************************************************************
+ *              Storage32Impl_BigBlocksToSmallBlocks
+ *
+ * This method will convert a big block chain to a small block chain.
+ * The big block chain will be destroyed on success.
+ */
+SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
+                           StorageImpl* This,
+                           BlockChainStream** ppbbChain)
+{
+    ULARGE_INTEGER size, offset, cbTotalRead;
+    ULONG cbRead, cbWritten, propertyIndex, sbHeadOfChain = BLOCK_END_OF_CHAIN;
+    HRESULT resWrite = S_OK, resRead;
+    StgProperty chainProperty;
+    BYTE* buffer;
+    SmallBlockChainStream* sbTempChain;
+
+    TRACE("%p %p\n", This, ppbbChain);
+
+    sbTempChain = SmallBlockChainStream_Construct(This, &sbHeadOfChain,
+            PROPERTY_NULL);
+
+    if(!sbTempChain)
+        return NULL;
+
+    size = BlockChainStream_GetSize(*ppbbChain);
+    SmallBlockChainStream_SetSize(sbTempChain, size);
+
+    offset.u.HighPart = 0;
+    offset.u.LowPart = 0;
+    cbTotalRead.QuadPart = 0;
+    buffer = HeapAlloc(GetProcessHeap(), 0, This->bigBlockSize);
+    do
+    {
+        resRead = BlockChainStream_ReadAt(*ppbbChain, offset,
+                This->bigBlockSize, buffer, &cbRead);
+
+        if(FAILED(resRead))
+            break;
+
+        if(cbRead > 0)
+        {
+            cbTotalRead.QuadPart += cbRead;
+
+            resWrite = SmallBlockChainStream_WriteAt(sbTempChain, offset,
+                    cbRead, buffer, &cbWritten);
+
+            if(FAILED(resWrite))
+                break;
+
+            offset.u.LowPart += This->bigBlockSize;
+        }
+    }while(cbTotalRead.QuadPart < size.QuadPart);
+    HeapFree(GetProcessHeap(), 0, buffer);
+
+    size.u.HighPart = 0;
+    size.u.LowPart = 0;
+
+    if(FAILED(resRead) || FAILED(resWrite))
+    {
+        ERR("conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite);
+        SmallBlockChainStream_SetSize(sbTempChain, size);
+        SmallBlockChainStream_Destroy(sbTempChain);
+        return NULL;
+    }
+
+    /* destroy the original big block chain */
+    propertyIndex = (*ppbbChain)->ownerPropertyIndex;
+    BlockChainStream_SetSize(*ppbbChain, size);
+    BlockChainStream_Destroy(*ppbbChain);
+    *ppbbChain = NULL;
+
+    StorageImpl_ReadProperty(This, propertyIndex, &chainProperty);
+    chainProperty.startingBlock = sbHeadOfChain;
+    StorageImpl_WriteProperty(This, propertyIndex, &chainProperty);
+
+    SmallBlockChainStream_Destroy(sbTempChain);
+    return SmallBlockChainStream_Construct(This, NULL, propertyIndex);
+}
+
 static void StorageInternalImpl_Destroy( StorageBaseImpl *iface)
 {
   StorageInternalImpl* This = (StorageInternalImpl*) iface;
diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h
index 68a82bb..fc4af32 100644
--- a/dlls/ole32/storage32.h
+++ b/dlls/ole32/storage32.h
@@ -306,6 +306,10 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks(
                       StorageImpl* This,
                       SmallBlockChainStream** ppsbChain);
 
+SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
+                      StorageImpl* This,
+                      BlockChainStream** ppbbChain);
+
 /****************************************************************************
  * StgStreamImpl definitions.
  *




More information about the wine-cvs mailing list