Author: fireball
Date: Fri Sep 17 20:13:28 2010
New Revision: 48795
URL:
http://svn.reactos.org/svn/reactos?rev=48795&view=rev
Log:
[OLE32]
- Sync to Wine-20100918.
See issue #5592 for more details.
Modified:
trunk/reactos/dll/win32/ole32/ole2.c
trunk/reactos/dll/win32/ole32/stg_stream.c
trunk/reactos/dll/win32/ole32/storage32.c
trunk/reactos/dll/win32/ole32/storage32.h
Modified: trunk/reactos/dll/win32/ole32/ole2.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/ole2.c?rev…
==============================================================================
--- trunk/reactos/dll/win32/ole32/ole2.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/ole32/ole2.c [iso-8859-1] Fri Sep 17 20:13:28 2010
@@ -450,7 +450,9 @@
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
if(FAILED(hr)) return hr;
+ unk = NULL;
hr = IDropTarget_QueryInterface(pDropTarget, &IID_IUnknown, (void**)&unk);
+ if (SUCCEEDED(hr) && !unk) hr = E_NOINTERFACE;
if(FAILED(hr))
{
IStream_Release(stream);
Modified: trunk/reactos/dll/win32/ole32/stg_stream.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/stg_stream…
==============================================================================
--- trunk/reactos/dll/win32/ole32/stg_stream.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/ole32/stg_stream.c [iso-8859-1] Fri Sep 17 20:13:28 2010
@@ -294,6 +294,9 @@
* Advance the position pointer for the number of positions written.
*/
This->currentPosition.u.LowPart += *pcbWritten;
+
+ if (SUCCEEDED(res))
+ res = StorageBaseImpl_Flush(This->parentStorage);
TRACE("<-- S_OK, written %u\n", *pcbWritten);
return res;
@@ -417,6 +420,10 @@
}
hr = StorageBaseImpl_StreamSetSize(This->parentStorage, This->dirEntry,
libNewSize);
+
+ if (SUCCEEDED(hr))
+ hr = StorageBaseImpl_Flush(This->parentStorage);
+
return hr;
}
Modified: trunk/reactos/dll/win32/ole32/storage32.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/storage32.…
==============================================================================
--- trunk/reactos/dll/win32/ole32/storage32.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/ole32/storage32.c [iso-8859-1] Fri Sep 17 20:13:28 2010
@@ -856,7 +856,7 @@
return STG_E_FILENOTFOUND;
}
- return S_OK;
+ return StorageBaseImpl_Flush(This);
}
/************************************************************************
@@ -1011,7 +1011,7 @@
return STG_E_INSUFFICIENTMEMORY;
}
- return S_OK;
+ return StorageBaseImpl_Flush(This);
}
/************************************************************************
@@ -1046,6 +1046,9 @@
This->storageDirEntry,
¤tEntry);
}
+
+ if (SUCCEEDED(hRes))
+ hRes = StorageBaseImpl_Flush(This);
return hRes;
}
@@ -1203,6 +1206,8 @@
return hr;
}
+ if (SUCCEEDED(hr))
+ hr = StorageBaseImpl_Flush(This);
return S_OK;
}
@@ -1916,6 +1921,9 @@
if (SUCCEEDED(hr))
StorageBaseImpl_DestroyDirEntry(This, entryToDeleteRef);
+ if (SUCCEEDED(hr))
+ hr = StorageBaseImpl_Flush(This);
+
return hr;
}
@@ -2849,7 +2857,10 @@
*result = NULL;
}
else
+ {
+ StorageImpl_Flush((StorageBaseImpl*)This);
*result = This;
+ }
return hr;
}
@@ -2888,8 +2899,26 @@
static HRESULT StorageImpl_Flush(StorageBaseImpl* iface)
{
StorageImpl *This = (StorageImpl*) iface;
-
- return ILockBytes_Flush(This->lockBytes);
+ int i;
+ HRESULT hr;
+ TRACE("(%p)\n", This);
+
+ hr = BlockChainStream_Flush(This->smallBlockRootChain);
+
+ if (SUCCEEDED(hr))
+ hr = BlockChainStream_Flush(This->rootBlockChain);
+
+ if (SUCCEEDED(hr))
+ hr = BlockChainStream_Flush(This->smallBlockDepotChain);
+
+ for (i=0; SUCCEEDED(hr) && i<BLOCKCHAIN_CACHE_SIZE; i++)
+ if (This->blockChainCache[i])
+ hr = BlockChainStream_Flush(This->blockChainCache[i]);
+
+ if (SUCCEEDED(hr))
+ hr = ILockBytes_Flush(This->lockBytes);
+
+ return hr;
}
/******************************************************************************
@@ -3846,13 +3875,20 @@
void* buffer)
{
ULARGE_INTEGER ulOffset;
- DWORD read;
+ DWORD read=0;
ulOffset.u.HighPart = 0;
ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read);
- return (read == This->bigBlockSize);
+
+ if (read && read < This->bigBlockSize)
+ {
+ /* File ends during this block; fill the rest with 0's. */
+ memset((LPBYTE)buffer+read, 0, This->bigBlockSize-read);
+ }
+
+ return (read != 0);
}
static BOOL StorageImpl_ReadDWordFromBigBlock(
@@ -5812,6 +5848,53 @@
return This->indexCache[min_run].firstSector + offset -
This->indexCache[min_run].firstOffset;
}
+HRESULT BlockChainStream_GetBlockAtOffset(BlockChainStream *This,
+ ULONG index, BlockChainBlock **block, ULONG *sector, BOOL create)
+{
+ BlockChainBlock *result=NULL;
+ int i;
+
+ for (i=0; i<2; i++)
+ if (This->cachedBlocks[i].index == index)
+ {
+ *sector = This->cachedBlocks[i].sector;
+ *block = &This->cachedBlocks[i];
+ return S_OK;
+ }
+
+ *sector = BlockChainStream_GetSectorOfOffset(This, index);
+ if (*sector == BLOCK_END_OF_CHAIN)
+ return STG_E_DOCFILECORRUPT;
+
+ if (create)
+ {
+ if (This->cachedBlocks[0].index == 0xffffffff)
+ result = &This->cachedBlocks[0];
+ else if (This->cachedBlocks[1].index == 0xffffffff)
+ result = &This->cachedBlocks[1];
+ else
+ {
+ result = &This->cachedBlocks[This->blockToEvict++];
+ if (This->blockToEvict == 2)
+ This->blockToEvict = 0;
+ }
+
+ if (result->dirty)
+ {
+ if (!StorageImpl_WriteBigBlock(This->parentStorage, result->sector,
result->data))
+ return STG_E_WRITEFAULT;
+ result->dirty = 0;
+ }
+
+ result->read = 0;
+ result->index = index;
+ result->sector = *sector;
+ }
+
+ *block = result;
+ return S_OK;
+}
+
BlockChainStream* BlockChainStream_Construct(
StorageImpl* parentStorage,
ULONG* headOfStreamPlaceHolder,
@@ -5827,6 +5910,11 @@
newStream->indexCache = NULL;
newStream->indexCacheLen = 0;
newStream->indexCacheSize = 0;
+ newStream->cachedBlocks[0].index = 0xffffffff;
+ newStream->cachedBlocks[0].dirty = 0;
+ newStream->cachedBlocks[1].index = 0xffffffff;
+ newStream->cachedBlocks[1].dirty = 0;
+ newStream->blockToEvict = 0;
if (FAILED(BlockChainStream_UpdateIndexCache(newStream)))
{
@@ -5838,10 +5926,30 @@
return newStream;
}
+HRESULT BlockChainStream_Flush(BlockChainStream* This)
+{
+ int i;
+ if (!This) return S_OK;
+ for (i=0; i<2; i++)
+ {
+ if (This->cachedBlocks[i].dirty)
+ {
+ if (StorageImpl_WriteBigBlock(This->parentStorage,
This->cachedBlocks[i].sector, This->cachedBlocks[i].data))
+ This->cachedBlocks[i].dirty = 0;
+ else
+ return STG_E_WRITEFAULT;
+ }
+ }
+ return S_OK;
+}
+
void BlockChainStream_Destroy(BlockChainStream* This)
{
if (This)
+ {
+ BlockChainStream_Flush(This);
HeapFree(GetProcessHeap(), 0, This->indexCache);
+ }
HeapFree(GetProcessHeap(), 0, This);
}
@@ -5907,6 +6015,8 @@
ULONG blockIndex;
BYTE* bufferWalker;
ULARGE_INTEGER stream_size;
+ HRESULT hr;
+ BlockChainBlock *cachedBlock;
TRACE("(%p)-> %i %p %i %p\n",This, offset.u.LowPart, buffer, size,
bytesRead);
@@ -5928,32 +6038,50 @@
*/
bufferWalker = buffer;
- while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
+ while (size > 0)
{
ULARGE_INTEGER ulOffset;
DWORD bytesReadAt;
+
/*
* Calculate how many bytes we can copy from this big block.
*/
bytesToReadInBuffer =
min(This->parentStorage->bigBlockSize - offsetInBlock, size);
- TRACE("block %i\n",blockIndex);
- ulOffset.u.HighPart = 0;
- ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage,
blockIndex) +
- offsetInBlock;
-
- StorageImpl_ReadAt(This->parentStorage,
- ulOffset,
- bufferWalker,
- bytesToReadInBuffer,
- &bytesReadAt);
- /*
- * Step to the next big block.
- */
- if( size > bytesReadAt &&
FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
&blockIndex)))
- return STG_E_DOCFILECORRUPT;
-
+ hr = BlockChainStream_GetBlockAtOffset(This, blockNoInSequence, &cachedBlock,
&blockIndex, size == bytesToReadInBuffer);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!cachedBlock)
+ {
+ /* Not in cache, and we're going to read past the end of the block. */
+ ulOffset.u.HighPart = 0;
+ ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage,
blockIndex) +
+ offsetInBlock;
+
+ StorageImpl_ReadAt(This->parentStorage,
+ ulOffset,
+ bufferWalker,
+ bytesToReadInBuffer,
+ &bytesReadAt);
+ }
+ else
+ {
+ if (!cachedBlock->read)
+ {
+ if (!StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector,
cachedBlock->data))
+ return STG_E_READFAULT;
+
+ cachedBlock->read = 1;
+ }
+
+ memcpy(bufferWalker, cachedBlock->data+offsetInBlock, bytesToReadInBuffer);
+ bytesReadAt = bytesToReadInBuffer;
+ }
+
+ blockNoInSequence++;
bufferWalker += bytesReadAt;
size -= bytesReadAt;
*bytesRead += bytesReadAt;
@@ -5983,51 +6111,61 @@
ULONG bytesToWrite;
ULONG blockIndex;
const BYTE* bufferWalker;
-
- /*
- * Find the first block in the stream that contains part of the buffer.
- */
- blockIndex = BlockChainStream_GetSectorOfOffset(This, blockNoInSequence);
-
- /* BlockChainStream_SetSize should have already been called to ensure we have
- * enough blocks in the chain to write into */
- if (blockIndex == BLOCK_END_OF_CHAIN)
- {
- ERR("not enough blocks in chain to write data\n");
- return STG_E_DOCFILECORRUPT;
- }
+ HRESULT hr;
+ BlockChainBlock *cachedBlock;
*bytesWritten = 0;
bufferWalker = buffer;
- while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) )
+ while (size > 0)
{
ULARGE_INTEGER ulOffset;
DWORD bytesWrittenAt;
+
/*
- * Calculate how many bytes we can copy from this big block.
+ * Calculate how many bytes we can copy to this big block.
*/
bytesToWrite =
min(This->parentStorage->bigBlockSize - offsetInBlock, size);
- TRACE("block %i\n",blockIndex);
- ulOffset.u.HighPart = 0;
- ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage,
blockIndex) +
- offsetInBlock;
-
- StorageImpl_WriteAt(This->parentStorage,
- ulOffset,
- bufferWalker,
- bytesToWrite,
- &bytesWrittenAt);
-
- /*
- * Step to the next big block.
- */
- if(size > bytesWrittenAt &&
FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex,
- &blockIndex)))
- return STG_E_DOCFILECORRUPT;
-
+ hr = BlockChainStream_GetBlockAtOffset(This, blockNoInSequence, &cachedBlock,
&blockIndex, size == bytesToWrite);
+
+ /* BlockChainStream_SetSize should have already been called to ensure we have
+ * enough blocks in the chain to write into */
+ if (FAILED(hr))
+ {
+ ERR("not enough blocks in chain to write data\n");
+ return hr;
+ }
+
+ if (!cachedBlock)
+ {
+ /* Not in cache, and we're going to write past the end of the block. */
+ ulOffset.u.HighPart = 0;
+ ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage,
blockIndex) +
+ offsetInBlock;
+
+ StorageImpl_WriteAt(This->parentStorage,
+ ulOffset,
+ bufferWalker,
+ bytesToWrite,
+ &bytesWrittenAt);
+ }
+ else
+ {
+ if (!cachedBlock->read && bytesToWrite !=
This->parentStorage->bigBlockSize)
+ {
+ if (!StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector,
cachedBlock->data))
+ return STG_E_READFAULT;
+ }
+
+ memcpy(cachedBlock->data+offsetInBlock, bufferWalker, bytesToWrite);
+ bytesWrittenAt = bytesToWrite;
+ cachedBlock->read = 1;
+ cachedBlock->dirty = 1;
+ }
+
+ blockNoInSequence++;
bufferWalker += bytesWrittenAt;
size -= bytesWrittenAt;
*bytesWritten += bytesWrittenAt;
@@ -6050,6 +6188,7 @@
{
ULONG blockIndex;
ULONG numBlocks;
+ int i;
/*
* Figure out how many blocks are needed to contain the new size
@@ -6115,6 +6254,18 @@
This->indexCacheLen--;
else
last_run->lastOffset--;
+ }
+
+ /*
+ * Reset the last accessed block cache.
+ */
+ for (i=0; i<2; i++)
+ {
+ if (This->cachedBlocks[i].index >= numBlocks)
+ {
+ This->cachedBlocks[i].index = 0xffffffff;
+ This->cachedBlocks[i].dirty = 0;
+ }
}
return TRUE;
Modified: trunk/reactos/dll/win32/ole32/storage32.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/storage32.…
==============================================================================
--- trunk/reactos/dll/win32/ole32/storage32.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/ole32/storage32.h [iso-8859-1] Fri Sep 17 20:13:28 2010
@@ -512,6 +512,15 @@
ULONG lastOffset;
};
+typedef struct BlockChainBlock
+{
+ ULONG index;
+ ULONG sector;
+ int read;
+ int dirty;
+ BYTE data[MAX_BIG_BLOCK_SIZE];
+} BlockChainBlock;
+
struct BlockChainStream
{
StorageImpl* parentStorage;
@@ -520,6 +529,8 @@
struct BlockChainRun* indexCache;
ULONG indexCacheLen;
ULONG indexCacheSize;
+ BlockChainBlock cachedBlocks[2];
+ ULONG blockToEvict;
ULONG tailIndex;
ULONG numBlocks;
};
@@ -553,6 +564,9 @@
BlockChainStream* This,
ULARGE_INTEGER newSize);
+HRESULT BlockChainStream_Flush(
+ BlockChainStream* This);
+
/****************************************************************************
* SmallBlockChainStream definitions.
*