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.c... ============================================================================== --- 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.h... ============================================================================== --- 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. *