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