diff --git a/dlls/ole32/stg_stream.c b/dlls/ole32/stg_stream.c index 928028b2597..40f0e81b93d 100644 --- a/dlls/ole32/stg_stream.c +++ b/dlls/ole32/stg_stream.c @@ -273,7 +273,7 @@ static HRESULT WINAPI StgStreamImpl_Read( */ if (This->smallBlockChain!=0) { - SmallBlockChainStream_ReadAt(This->smallBlockChain, + res = SmallBlockChainStream_ReadAt(This->smallBlockChain, This->currentPosition, bytesToReadFromBuffer, pv, @@ -282,7 +282,7 @@ static HRESULT WINAPI StgStreamImpl_Read( } else if (This->bigBlockChain!=0) { - BlockChainStream_ReadAt(This->bigBlockChain, + res = BlockChainStream_ReadAt(This->bigBlockChain, This->currentPosition, bytesToReadFromBuffer, pv, @@ -300,30 +300,19 @@ static HRESULT WINAPI StgStreamImpl_Read( goto end; } - /* - * We should always be able to read the proper amount of data from the - * chain. - */ - assert(bytesToReadFromBuffer == *pcbRead); - - /* - * Advance the pointer for the number of positions read. - */ - This->currentPosition.u.LowPart += *pcbRead; - - if(*pcbRead != cb) + if (SUCCEEDED(res)) { - WARN("read %ld instead of the required %ld bytes !\n", *pcbRead, cb); - /* - * this used to return S_FALSE, however MSDN docu says that an app should - * be prepared to handle error in case of stream end reached, as *some* - * implementations *might* return an error (IOW: most do *not*). - * As some program fails on returning S_FALSE, I better use S_OK here. - */ - res = S_OK; + /* + * We should always be able to read the proper amount of data from the + * chain. + */ + assert(bytesToReadFromBuffer == *pcbRead); + + /* + * Advance the pointer for the number of positions read. + */ + This->currentPosition.u.LowPart += *pcbRead; } - else - res = S_OK; end: TRACE("<-- %08lx\n", res); diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 708d99442e2..c9d696e8c2c 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -3414,7 +3414,8 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks( ULARGE_INTEGER size, offset; ULONG cbRead, cbWritten, cbTotalRead, cbTotalWritten; ULONG propertyIndex; - BOOL successRead, successWrite; + BOOL successWrite; + HRESULT successRead; StgProperty chainProperty; BYTE *buffer; BlockChainStream *bbTempChain = NULL; @@ -3463,7 +3464,7 @@ BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks( offset.u.LowPart += This->smallBlockSize; - } while (successRead && successWrite); + } while (SUCCEEDED(successRead) && successWrite); HeapFree(GetProcessHeap(),0,buffer); assert(cbTotalRead == cbTotalWritten); @@ -4397,6 +4398,9 @@ BOOL BlockChainStream_ReadAt(BlockChainStream* This, blockNoInSequence--; } + if ((blockNoInSequence > 0) && (blockIndex == BLOCK_END_OF_CHAIN)) + return FALSE; /* We failed to find the starting block */ + This->lastBlockNoInSequenceIndex = blockIndex; /* @@ -5098,13 +5102,14 @@ ULONG SmallBlockChainStream_GetNextFreeBlock( * bytesRead may be NULL. * Failure will be returned if the specified number of bytes has not been read. */ -BOOL SmallBlockChainStream_ReadAt( +HRESULT SmallBlockChainStream_ReadAt( SmallBlockChainStream* This, ULARGE_INTEGER offset, ULONG size, void* buffer, ULONG* bytesRead) { + HRESULT rc = S_OK; ULARGE_INTEGER offsetInBigBlockFile; ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->smallBlockSize; @@ -5127,9 +5132,9 @@ BOOL SmallBlockChainStream_ReadAt( while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) { - if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, - &blockIndex))) - return FALSE; + rc = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex); + if(FAILED(rc)) + return rc; blockNoInSequence--; } @@ -5158,27 +5163,32 @@ BOOL SmallBlockChainStream_ReadAt( /* * Read those bytes in the buffer from the small block file. + * The small block has already been identified so it shouldn't fail + * unless the file is corrupt. */ - BlockChainStream_ReadAt(This->parentStorage->smallBlockRootChain, + if (!BlockChainStream_ReadAt(This->parentStorage->smallBlockRootChain, offsetInBigBlockFile, bytesToReadInBuffer, bufferWalker, - &bytesReadFromBigBlockFile); + &bytesReadFromBigBlockFile)) + return STG_E_DOCFILECORRUPT; assert(bytesReadFromBigBlockFile == bytesToReadInBuffer); /* * Step to the next big block. */ - if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex))) - return FALSE; + rc = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex, &blockIndex); + if(FAILED(rc)) + return rc; + bufferWalker += bytesToReadInBuffer; size -= bytesToReadInBuffer; *bytesRead += bytesToReadInBuffer; offsetInBlock = 0; /* There is no offset on the next block */ } - return (size == 0); + return rc; } /****************************************************************************** diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index 4061a064bfd..0472524f3a1 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -667,7 +667,7 @@ void SmallBlockChainStream_FreeBlock( ULONG SmallBlockChainStream_GetNextFreeBlock( SmallBlockChainStream* This); -BOOL SmallBlockChainStream_ReadAt( +HRESULT SmallBlockChainStream_ReadAt( SmallBlockChainStream* This, ULARGE_INTEGER offset, ULONG size, diff --git a/include/winerror.h b/include/winerror.h index bf866daae50..b824c79a60b 100644 --- a/include/winerror.h +++ b/include/winerror.h @@ -1691,6 +1691,7 @@ #define STG_E_SHAREREQUIRED _HRESULT_TYPEDEF_(0x80030106L) #define STG_E_NOTFILEBASEDSTORAGE _HRESULT_TYPEDEF_(0x80030107L) #define STG_E_EXTANTMARSHALLINGS _HRESULT_TYPEDEF_(0x80030108L) +#define STG_E_DOCFILECORRUPT _HRESULT_TYPEDEF_(0x80030109L) #define STG_E_STATUS_COPY_PROTECTION_FAILURE _HRESULT_TYPEDEF_(0x80030305L) #define STG_E_CSS_AUTHENTICATION_FAILURE _HRESULT_TYPEDEF_(0x80030306L)