From 838eb4037fe93cef9a063a37dac0e70578224ea3 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Fri, 16 Mar 2007 13:34:28 -0500 Subject: [PATCH] ole32: Rework storage with blockfiles to properly use ILockBytes interfaces. Rework storage to make all its interactions with the underlying data go though ReadAt and WriteAt to allow for an ILockBytes underlying layer. Implement ReadAt and WriteAt in stg_bigblockfile.c for blockfiles. --- dlls/ole32/stg_bigblockfile.c | 373 +++++++++++++++++++--------------- dlls/ole32/storage32.c | 293 +++++++++++++------------- dlls/ole32/storage32.h | 8 +- 3 files changed, 358 insertions(+), 316 deletions(-) diff --git a/dlls/ole32/stg_bigblockfile.c b/dlls/ole32/stg_bigblockfile.c index df2cea1125..a208bb8aa1 100644 --- a/dlls/ole32/stg_bigblockfile.c +++ b/dlls/ole32/stg_bigblockfile.c @@ -91,6 +91,7 @@ struct MappedPage MappedPage *prev; DWORD page_index; + DWORD mapped_bytes; LPVOID lpBytes; LONG refcnt; @@ -108,11 +109,6 @@ static void BIGBLOCKFILE_ReleaseMappedPage(LPBIGBLOCKFILE This, static void BIGBLOCKFILE_FreeAllMappedPages(LPBIGBLOCKFILE This); static void BIGBLOCKFILE_UnmapAllMappedPages(LPBIGBLOCKFILE This); static void BIGBLOCKFILE_RemapAllMappedPages(LPBIGBLOCKFILE This); -static void* BIGBLOCKFILE_GetBigBlockPointer(LPBIGBLOCKFILE This, - ULONG index, - DWORD desired_access); -static MappedPage* BIGBLOCKFILE_GetPageFromPointer(LPBIGBLOCKFILE This, - void* pBlock); static MappedPage* BIGBLOCKFILE_CreatePage(LPBIGBLOCKFILE This, ULONG page_index); static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags); @@ -316,40 +312,6 @@ void BIGBLOCKFILE_Destructor( HeapFree(GetProcessHeap(), 0, This); } -/****************************************************************************** - * BIGBLOCKFILE_GetROBigBlock - * - * Returns the specified block in read only mode. - * Will return NULL if the block doesn't exists. - */ -void* BIGBLOCKFILE_GetROBigBlock( - LPBIGBLOCKFILE This, - ULONG index) -{ - /* - * block index starts at -1 - * translate to zero based index - */ - if (index == 0xffffffff) - index = 0; - else - index++; - - /* - * validate the block index - * - */ - if (This->blocksize * (index + 1) - > ROUND_UP(This->filesize.u.LowPart, This->blocksize)) - { - TRACE("out of range %u vs %u\n", This->blocksize * (index + 1), - This->filesize.u.LowPart); - return NULL; - } - - return BIGBLOCKFILE_GetBigBlockPointer(This, index, FILE_MAP_READ); -} - /****************************************************************************** * BIGBLOCKFILE_EnsureExists * @@ -380,49 +342,6 @@ void BIGBLOCKFILE_EnsureExists(LPBIGBLOCKFILE This, ULONG index) } } -/****************************************************************************** - * BIGBLOCKFILE_GetBigBlock - * - * Returns the specified block. - * Will grow the file if necessary. - */ -void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index) -{ - /* FIXME: is this necessary? */ - BIGBLOCKFILE_EnsureExists(This, index); - - /* - * block index starts at -1 - * translate to zero based index - */ - if (index == 0xffffffff) - index = 0; - else - index++; - - return BIGBLOCKFILE_GetBigBlockPointer(This, index, FILE_MAP_WRITE); -} - -/****************************************************************************** - * BIGBLOCKFILE_ReleaseBigBlock - * - * Releases the specified block. - */ -void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock) -{ - MappedPage *page; - - if (pBlock == NULL) - return; - - page = BIGBLOCKFILE_GetPageFromPointer(This, pBlock); - - if (page == NULL) - return; - - BIGBLOCKFILE_ReleaseMappedPage(This, page); -} - /****************************************************************************** * BIGBLOCKFILE_SetSize * @@ -494,85 +413,6 @@ ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This) return This->filesize; } -/****************************************************************************** - * BIGBLOCKFILE_AccessCheck [PRIVATE] - * - * block_index is the index within the page. - */ -static BOOL BIGBLOCKFILE_AccessCheck(MappedPage *page, ULONG block_index, - DWORD desired_access) -{ - assert(block_index < BLOCKS_PER_PAGE); - - if (desired_access == FILE_MAP_READ) - { - if (BIGBLOCKFILE_TestBit(&page->writable_blocks, block_index)) - return FALSE; - - BIGBLOCKFILE_SetBit(&page->readable_blocks, block_index); - } - else - { - assert(desired_access == FILE_MAP_WRITE); - - if (BIGBLOCKFILE_TestBit(&page->readable_blocks, block_index)) - return FALSE; - - BIGBLOCKFILE_SetBit(&page->writable_blocks, block_index); - } - - return TRUE; -} - -/****************************************************************************** - * BIGBLOCKFILE_GetBigBlockPointer [PRIVATE] - * - * Returns a pointer to the specified block. - */ -static void* BIGBLOCKFILE_GetBigBlockPointer( - LPBIGBLOCKFILE This, - ULONG block_index, - DWORD desired_access) -{ - DWORD page_index = block_index / BLOCKS_PER_PAGE; - DWORD block_on_page = block_index % BLOCKS_PER_PAGE; - - MappedPage *page = BIGBLOCKFILE_GetMappedView(This, page_index); - if (!page || !page->lpBytes) return NULL; - - if (!BIGBLOCKFILE_AccessCheck(page, block_on_page, desired_access)) - { - BIGBLOCKFILE_ReleaseMappedPage(This, page); - return NULL; - } - - return (LPBYTE)page->lpBytes + (block_on_page * This->blocksize); -} - -/****************************************************************************** - * BIGBLOCKFILE_GetMappedPageFromPointer [PRIVATE] - * - * pBlock is a pointer to a block on a page. - * The page has to be on the in-use list. (As oppsed to the victim list.) - * - * Does not increment the usage count. - */ -static MappedPage *BIGBLOCKFILE_GetPageFromPointer(LPBIGBLOCKFILE This, - void *pBlock) -{ - MappedPage *page; - - for (page = This->maplist; page != NULL; page = page->next) - { - if ((LPBYTE)pBlock >= (LPBYTE)page->lpBytes - && (LPBYTE)pBlock <= (LPBYTE)page->lpBytes + PAGE_SIZE) - break; - - } - - return page; -} - /****************************************************************************** * BIGBLOCKFILE_FindPageInList [PRIVATE] * @@ -681,10 +521,12 @@ static BOOL BIGBLOCKFILE_MapPage(LPBIGBLOCKFILE This, MappedPage *page) page->lpBytes = MapViewOfFile(This->hfilemap, desired_access, 0, lowoffset, numBytesToMap); + page->mapped_bytes = numBytesToMap; } else { page->lpBytes = (LPBYTE)This->pbytearray + lowoffset; + page->mapped_bytes = PAGE_SIZE; } TRACE("mapped page %u to %p\n", page->page_index, page->lpBytes); @@ -707,7 +549,11 @@ static MappedPage *BIGBLOCKFILE_CreatePage(LPBIGBLOCKFILE This, page->next = NULL; page->prev = NULL; - BIGBLOCKFILE_MapPage(This, page); + if (!BIGBLOCKFILE_MapPage(This, page)) + { + HeapFree(GetProcessHeap(),0,page); + return NULL; + } BIGBLOCKFILE_Zero(&page->readable_blocks); BIGBLOCKFILE_Zero(&page->writable_blocks); @@ -869,3 +715,206 @@ static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) } return PAGE_READONLY; } + + +/* ILockByte Interfaces */ + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It reads a block of information from the byte array at the specified + * offset. + * + * See the documentation of ILockBytes for more info. + */ +static HRESULT WINAPI ImplBIGBLOCKFILE_ReadAt( + BigBlockFile* const This, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead) /* [out] */ +{ + ULONG first_page = ulOffset.u.LowPart / PAGE_SIZE; + ULONG offset_in_page = ulOffset.u.LowPart % PAGE_SIZE; + ULONG bytes_left = cb; + ULONG page_index = first_page; + ULONG bytes_from_page; + LPVOID writePtr = pv; + + HRESULT rc = S_OK; + + TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbRead); + + /* verify a sane enviroment */ + if (!This) return E_FAIL; + + if (offset_in_page + bytes_left > PAGE_SIZE) + bytes_from_page = PAGE_SIZE - offset_in_page; + else + bytes_from_page = bytes_left; + + if (pcbRead) + *pcbRead = 0; + + while (bytes_left) + { + LPBYTE readPtr; + BOOL eof = FALSE; + MappedPage *page = BIGBLOCKFILE_GetMappedView(This, page_index); + + if (!page || !page->lpBytes) + { + rc = STG_E_READFAULT; + break; + } + + TRACE("page %i, offset %u, bytes_from_page %u, bytes_left %u\n", + page->page_index, offset_in_page, bytes_from_page, bytes_left); + + if (page->mapped_bytes < bytes_from_page) + { + eof = TRUE; + bytes_from_page = page->mapped_bytes; + } + + readPtr = (BYTE*)page->lpBytes + offset_in_page; + memcpy(writePtr,readPtr,bytes_from_page); + BIGBLOCKFILE_ReleaseMappedPage(This, page); + + if (pcbRead) + *pcbRead += bytes_from_page; + bytes_left -= bytes_from_page; + + if (bytes_left && !eof) + { + writePtr = (LPBYTE)writePtr + bytes_from_page; + page_index ++; + offset_in_page = 0; + if (bytes_left > PAGE_SIZE) + bytes_from_page = PAGE_SIZE; + else + bytes_from_page = bytes_left; + } + if (eof) + { + rc = STG_E_READFAULT; + break; + } + } + + TRACE("finished\n"); + return rc; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It writes the specified bytes at the specified offset. + * position. If the file is too small, it will be resized. + * + * See the documentation of ILockBytes for more info. + */ +static HRESULT WINAPI ImplBIGBLOCKFILE_WriteAt( + BigBlockFile* const This, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten) /* [out] */ +{ + ULONG size_needed = ulOffset.u.LowPart + cb; + ULONG first_page = ulOffset.u.LowPart / PAGE_SIZE; + ULONG offset_in_page = ulOffset.u.LowPart % PAGE_SIZE; + ULONG bytes_left = cb; + ULONG page_index = first_page; + ULONG bytes_to_page; + LPCVOID readPtr = pv; + + HRESULT rc = S_OK; + + TRACE("(%p)-> %i %p %i %p\n",This, ulOffset.u.LowPart, pv, cb, pcbWritten); + + /* verify a sane enviroment */ + if (!This) return E_FAIL; + + if (This->flProtect != PAGE_READWRITE) + return STG_E_ACCESSDENIED; + + if (size_needed > This->filesize.u.LowPart) + { + ULARGE_INTEGER newSize; + newSize.u.HighPart = 0; + newSize.u.LowPart = size_needed; + BIGBLOCKFILE_SetSize(This, newSize); + } + + if (offset_in_page + bytes_left > PAGE_SIZE) + bytes_to_page = PAGE_SIZE - offset_in_page; + else + bytes_to_page = bytes_left; + + if (pcbWritten) + *pcbWritten = 0; + + while (bytes_left) + { + LPBYTE writePtr; + MappedPage *page = BIGBLOCKFILE_GetMappedView(This, page_index); + + TRACE("page %i, offset %u, bytes_to_page %u, bytes_left %u\n", + page->page_index, offset_in_page, bytes_to_page, bytes_left); + + if (page->mapped_bytes < bytes_to_page) + { + ERR("Not enough bytes mapped to the page. This should never happen\n"); + rc = E_FAIL; + break; + } + + if (!page) + { + ERR("Unable to get a page to write. This should never happen\n"); + rc = E_FAIL; + break; + } + + writePtr = (BYTE*)page->lpBytes + offset_in_page; + memcpy(writePtr,readPtr,bytes_to_page); + BIGBLOCKFILE_ReleaseMappedPage(This, page); + + if (pcbWritten) + *pcbWritten += bytes_to_page; + bytes_left -= bytes_to_page; + + if (bytes_left) + { + readPtr = (LPBYTE)readPtr + bytes_to_page; + page_index ++; + offset_in_page = 0; + if (bytes_left > PAGE_SIZE) + bytes_to_page = PAGE_SIZE; + else + bytes_to_page = bytes_left; + } + } + + return rc; +} + + +HRESULT BIGBLOCKFILE_ReadAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, + void* buffer, ULONG size, ULONG* bytesRead) +{ + if (This->fileBased) + return ImplBIGBLOCKFILE_ReadAt(This,offset,buffer,size,bytesRead); + else + return ILockBytes_ReadAt(This->pLkbyt,offset,buffer,size,bytesRead); +} + +HRESULT BIGBLOCKFILE_WriteAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, + void* buffer, const ULONG size, ULONG* bytesRead) +{ + if (This->fileBased) + return ImplBIGBLOCKFILE_WriteAt(This,offset,buffer,size,bytesRead); + else + return ILockBytes_WriteAt(This->pLkbyt,offset,buffer,size,bytesRead); +} diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index dc2db11474..408453ad5b 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -84,9 +84,6 @@ typedef struct StorageInternalImpl StorageInternalImpl; static StorageInternalImpl* StorageInternalImpl_Construct(StorageImpl* ancestorStorage, DWORD openFlags, ULONG rootTropertyIndex); static void StorageImpl_Destroy(StorageBaseImpl* iface); -static void* StorageImpl_GetBigBlock(StorageImpl* This, ULONG blockIndex); -static void* StorageImpl_GetROBigBlock(StorageImpl* This, ULONG blockIndex); -static void StorageImpl_ReleaseBigBlock(StorageImpl* This, void* pBigBlock); static BOOL StorageImpl_ReadBigBlock(StorageImpl* This, ULONG blockIndex, void* buffer); static BOOL StorageImpl_WriteBigBlock(StorageImpl* This, ULONG blockIndex, void* buffer); static void StorageImpl_SetNextBlockInChain(StorageImpl* This, ULONG blockIndex, ULONG nextBlock); @@ -104,7 +101,10 @@ static ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This); static ULONG BlockChainStream_GetCount(BlockChainStream* This); static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This); - +static BOOL StorageImpl_WriteDWordToBigBlock( StorageImpl* This, + ULONG blockIndex, ULONG offset, DWORD value); +static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This, + ULONG blockIndex, ULONG offset, DWORD* value); /* OLESTREAM memory structure to use for Get and Put Routines */ /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ @@ -245,10 +245,40 @@ static ULONG IEnumSTATSTGImpl_FindProperty(IEnumSTATSTGImpl* This, const OLECHAR static INT IEnumSTATSTGImpl_FindParentProperty(IEnumSTATSTGImpl *This, ULONG childProperty, StgProperty *currentProperty, ULONG *propertyId); +/************************************************************************ +** Block Functions +*/ + +static ULONG BLOCK_GetBigBlockOffset(ULONG index) +{ + if (index == 0xffffffff) + index = 0; + else + index ++; + + return index * BIG_BLOCK_SIZE; +} /************************************************************************ ** Storage32BaseImpl implementatiion */ +static HRESULT StorageImpl_ReadAt(StorageImpl* This, + ULARGE_INTEGER offset, + void* buffer, + ULONG size, + ULONG* bytesRead) +{ + return BIGBLOCKFILE_ReadAt(This->bigBlockFile,offset,buffer,size,bytesRead); +} + +static HRESULT StorageImpl_WriteAt(StorageImpl* This, + ULARGE_INTEGER offset, + void* buffer, + const ULONG size, + ULONG* bytesWritten) +{ + return BIGBLOCKFILE_WriteAt(This->bigBlockFile,offset,buffer,size,bytesWritten); +} /************************************************************************ * Storage32BaseImpl_QueryInterface (IUnknown) @@ -2417,7 +2447,7 @@ static HRESULT StorageImpl_Construct( if (fileCreate) { ULARGE_INTEGER size; - BYTE* bigBlockBuffer; + BYTE bigBlockBuffer[BIG_BLOCK_SIZE]; /* * Initialize all header variables: @@ -2450,11 +2480,10 @@ static HRESULT StorageImpl_Construct( /* * Initialize the big block depot */ - bigBlockBuffer = StorageImpl_GetBigBlock(This, 0); memset(bigBlockBuffer, BLOCK_UNUSED, This->bigBlockSize); StorageUtl_WriteDWord(bigBlockBuffer, 0, BLOCK_SPECIAL); StorageUtl_WriteDWord(bigBlockBuffer, sizeof(ULONG), BLOCK_END_OF_CHAIN); - StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); + StorageImpl_WriteBigBlock(This, 0, bigBlockBuffer); } else { @@ -2586,7 +2615,8 @@ static ULONG StorageImpl_GetNextFreeBigBlock( StorageImpl* This) { ULONG depotBlockIndexPos; - void *depotBuffer; + BYTE depotBuffer[BIG_BLOCK_SIZE]; + BOOL success; ULONG depotBlockOffset; ULONG blocksPerDepot = This->bigBlockSize / sizeof(ULONG); ULONG nextBlockIndex = BLOCK_SPECIAL; @@ -2679,9 +2709,9 @@ static ULONG StorageImpl_GetNextFreeBigBlock( } } - depotBuffer = StorageImpl_GetROBigBlock(This, depotBlockIndexPos); + success = StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer); - if (depotBuffer != 0) + if (success) { while ( ( (depotBlockOffset/sizeof(ULONG) ) < blocksPerDepot) && ( nextBlockIndex != BLOCK_UNUSED)) @@ -2696,8 +2726,6 @@ static ULONG StorageImpl_GetNextFreeBigBlock( depotBlockOffset += sizeof(ULONG); } - - StorageImpl_ReleaseBigBlock(This, depotBuffer); } depotIndex++; @@ -2722,16 +2750,13 @@ static ULONG StorageImpl_GetNextFreeBigBlock( */ static void Storage32Impl_AddBlockDepot(StorageImpl* This, ULONG blockIndex) { - BYTE* blockBuffer; - - blockBuffer = StorageImpl_GetBigBlock(This, blockIndex); + BYTE blockBuffer[BIG_BLOCK_SIZE]; /* * Initialize blocks as free */ memset(blockBuffer, BLOCK_UNUSED, This->bigBlockSize); - - StorageImpl_ReleaseBigBlock(This, blockBuffer); + StorageImpl_WriteBigBlock(This, blockIndex, blockBuffer); } /****************************************************************************** @@ -2762,20 +2787,8 @@ static ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This, ULONG depotIndex) } if (extBlockIndex != BLOCK_UNUSED) - { - BYTE* depotBuffer; - - depotBuffer = StorageImpl_GetROBigBlock(This, extBlockIndex); - - if (depotBuffer != 0) - { - StorageUtl_ReadDWord(depotBuffer, - extBlockOffset * sizeof(ULONG), - &blockIndex); - - StorageImpl_ReleaseBigBlock(This, depotBuffer); - } - } + StorageImpl_ReadDWordFromBigBlock(This, extBlockIndex, + extBlockOffset * sizeof(ULONG), &blockIndex); return blockIndex; } @@ -2805,18 +2818,9 @@ static void Storage32Impl_SetExtDepotBlock(StorageImpl* This, ULONG depotIndex, if (extBlockIndex != BLOCK_UNUSED) { - BYTE* depotBuffer; - - depotBuffer = StorageImpl_GetBigBlock(This, extBlockIndex); - - if (depotBuffer != 0) - { - StorageUtl_WriteDWord(depotBuffer, - extBlockOffset * sizeof(ULONG), - blockIndex); - - StorageImpl_ReleaseBigBlock(This, depotBuffer); - } + StorageImpl_WriteDWordToBigBlock(This, extBlockIndex, + extBlockOffset * sizeof(ULONG), + blockIndex); } } @@ -2829,7 +2833,7 @@ static ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This) { ULONG numExtBlocks = This->extBigBlockDepotCount; ULONG nextExtBlock = This->extBigBlockDepotStart; - BYTE* depotBuffer = NULL; + BYTE depotBuffer[BIG_BLOCK_SIZE]; ULONG index = BLOCK_UNUSED; ULONG nextBlockOffset = This->bigBlockSize - sizeof(ULONG); ULONG blocksPerDepotBlock = This->bigBlockSize / sizeof(ULONG); @@ -2859,17 +2863,15 @@ static ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This) /* * Add the new extended block to the chain. */ - depotBuffer = StorageImpl_GetBigBlock(This, nextExtBlock); - StorageUtl_WriteDWord(depotBuffer, nextBlockOffset, index); - StorageImpl_ReleaseBigBlock(This, depotBuffer); + StorageImpl_WriteDWordToBigBlock(This, nextExtBlock, nextBlockOffset, + index); } /* * Initialize this block. */ - depotBuffer = StorageImpl_GetBigBlock(This, index); memset(depotBuffer, BLOCK_UNUSED, This->bigBlockSize); - StorageImpl_ReleaseBigBlock(This, depotBuffer); + StorageImpl_WriteBigBlock(This, index, depotBuffer); return index; } @@ -2921,7 +2923,8 @@ static HRESULT StorageImpl_GetNextBlockInChain( ULONG offsetInDepot = blockIndex * sizeof (ULONG); ULONG depotBlockCount = offsetInDepot / This->bigBlockSize; ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize; - void* depotBuffer; + BYTE depotBuffer[BIG_BLOCK_SIZE]; + BOOL success; ULONG depotBlockIndexPos; int index; @@ -2953,9 +2956,9 @@ static HRESULT StorageImpl_GetNextBlockInChain( depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotBlockCount); } - depotBuffer = StorageImpl_GetROBigBlock(This, depotBlockIndexPos); + success = StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer); - if (!depotBuffer) + if (!success) return STG_E_READFAULT; for (index = 0; index < NUM_BLOCKS_PER_DEPOT_BLOCK; index++) @@ -2963,7 +2966,6 @@ static HRESULT StorageImpl_GetNextBlockInChain( StorageUtl_ReadDWord(depotBuffer, index*sizeof(ULONG), nextBlockIndex); This->blockDepotCached[index] = *nextBlockIndex; } - StorageImpl_ReleaseBigBlock(This, depotBuffer); } *nextBlockIndex = This->blockDepotCached[depotBlockOffset/sizeof(ULONG)]; @@ -2990,16 +2992,9 @@ static ULONG Storage32Impl_GetNextExtendedBlock(StorageImpl* This, ULONG blockIn { ULONG nextBlockIndex = BLOCK_SPECIAL; ULONG depotBlockOffset = This->bigBlockSize - sizeof(ULONG); - void* depotBuffer; - depotBuffer = StorageImpl_GetROBigBlock(This, blockIndex); - - if (depotBuffer!=0) - { - StorageUtl_ReadDWord(depotBuffer, depotBlockOffset, &nextBlockIndex); - - StorageImpl_ReleaseBigBlock(This, depotBuffer); - } + StorageImpl_ReadDWordFromBigBlock(This, blockIndex, depotBlockOffset, + &nextBlockIndex); return nextBlockIndex; } @@ -3027,7 +3022,6 @@ static void StorageImpl_SetNextBlockInChain( ULONG depotBlockCount = offsetInDepot / This->bigBlockSize; ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize; ULONG depotBlockIndexPos; - void* depotBuffer; assert(depotBlockCount < This->bigBlockDepotCount); assert(blockIndex != nextBlock); @@ -3044,14 +3038,8 @@ static void StorageImpl_SetNextBlockInChain( depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotBlockCount); } - depotBuffer = StorageImpl_GetBigBlock(This, depotBlockIndexPos); - - if (depotBuffer!=0) - { - StorageUtl_WriteDWord(depotBuffer, depotBlockOffset, nextBlock); - StorageImpl_ReleaseBigBlock(This, depotBuffer); - } - + StorageImpl_WriteDWordToBigBlock(This, depotBlockIndexPos, depotBlockOffset, + nextBlock); /* * Update the cached block depot, if necessary. */ @@ -3070,19 +3058,20 @@ static HRESULT StorageImpl_LoadFileHeader( StorageImpl* This) { HRESULT hr = STG_E_FILENOTFOUND; - void* headerBigBlock = NULL; + BYTE headerBigBlock[BIG_BLOCK_SIZE]; + BOOL success; int index; TRACE("\n"); /* * Get a pointer to the big block of data containing the header. */ - headerBigBlock = StorageImpl_GetROBigBlock(This, -1); + success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock); /* * Extract the information from the header. */ - if (headerBigBlock!=0) + if (success) { /* * Check for the "magic number" signature and return an error if it is not @@ -3090,13 +3079,11 @@ static HRESULT StorageImpl_LoadFileHeader( */ if (memcmp(headerBigBlock, STORAGE_oldmagic, sizeof(STORAGE_oldmagic))==0) { - StorageImpl_ReleaseBigBlock(This, headerBigBlock); return STG_E_OLDFORMAT; } if (memcmp(headerBigBlock, STORAGE_magic, sizeof(STORAGE_magic))!=0) { - StorageImpl_ReleaseBigBlock(This, headerBigBlock); return STG_E_INVALIDHEADER; } @@ -3169,11 +3156,6 @@ static HRESULT StorageImpl_LoadFileHeader( } else hr = S_OK; - - /* - * Release the block. - */ - StorageImpl_ReleaseBigBlock(This, headerBigBlock); } return hr; @@ -3472,20 +3454,33 @@ static BOOL StorageImpl_ReadBigBlock( ULONG blockIndex, void* buffer) { - void* bigBlockBuffer; + ULARGE_INTEGER ulOffset; + DWORD read; - bigBlockBuffer = StorageImpl_GetROBigBlock(This, blockIndex); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); - if (bigBlockBuffer!=0) - { - memcpy(buffer, bigBlockBuffer, This->bigBlockSize); + StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read); + return (read == This->bigBlockSize); +} - StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); +static BOOL StorageImpl_ReadDWordFromBigBlock( + StorageImpl* This, + ULONG blockIndex, + ULONG offset, + DWORD* value) +{ + ULARGE_INTEGER ulOffset; + DWORD read; + DWORD tmp; - return TRUE; - } + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart += offset; - return FALSE; + StorageImpl_ReadAt(This, ulOffset, &tmp, sizeof(DWORD), &read); + *value = le32toh(tmp); + return (read == sizeof(DWORD)); } static BOOL StorageImpl_WriteBigBlock( @@ -3493,41 +3488,32 @@ static BOOL StorageImpl_WriteBigBlock( ULONG blockIndex, void* buffer) { - void* bigBlockBuffer; - - bigBlockBuffer = StorageImpl_GetBigBlock(This, blockIndex); + ULARGE_INTEGER ulOffset; + DWORD wrote; - if (bigBlockBuffer!=0) - { - memcpy(bigBlockBuffer, buffer, This->bigBlockSize); - - StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); - return TRUE; - } - - return FALSE; + StorageImpl_WriteAt(This, ulOffset, buffer, This->bigBlockSize, &wrote); + return (wrote == This->bigBlockSize); } -static void* StorageImpl_GetROBigBlock( +static BOOL StorageImpl_WriteDWordToBigBlock( StorageImpl* This, - ULONG blockIndex) + ULONG blockIndex, + ULONG offset, + DWORD value) { - return BIGBLOCKFILE_GetROBigBlock(This->bigBlockFile, blockIndex); -} + ULARGE_INTEGER ulOffset; + DWORD wrote; -static void* StorageImpl_GetBigBlock( - StorageImpl* This, - ULONG blockIndex) -{ - return BIGBLOCKFILE_GetBigBlock(This->bigBlockFile, blockIndex); -} + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart += offset; -static void StorageImpl_ReleaseBigBlock( - StorageImpl* This, - void* pBigBlock) -{ - BIGBLOCKFILE_ReleaseBigBlock(This->bigBlockFile, pBigBlock); + value = htole32(value); + StorageImpl_WriteAt(This, ulOffset, &value, sizeof(DWORD), &wrote); + return (wrote == sizeof(DWORD)); } /****************************************************************************** @@ -4518,7 +4504,8 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, ULONG bytesToReadInBuffer; ULONG blockIndex; BYTE* bufferWalker; - BYTE* bigBlockBuffer; + + TRACE("(%p)-> %i %p %i %p\n",This, offset.u.LowPart, buffer, size, bytesRead); /* * Find the first block in the stream that contains part of the buffer. @@ -4559,35 +4546,37 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) { + ULARGE_INTEGER ulOffset; + DWORD bytesReadAt; /* * Calculate how many bytes we can copy from this big block. */ bytesToReadInBuffer = min(This->parentStorage->bigBlockSize - offsetInBlock, size); - /* - * Copy those bytes to the buffer - */ - bigBlockBuffer = - StorageImpl_GetROBigBlock(This->parentStorage, blockIndex); - if (!bigBlockBuffer) - return STG_E_READFAULT; - - memcpy(bufferWalker, bigBlockBuffer + offsetInBlock, bytesToReadInBuffer); - - StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); + TRACE("block %i\n",blockIndex); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex) + + offsetInBlock; + StorageImpl_ReadAt(This->parentStorage, + ulOffset, + bufferWalker, + bytesToReadInBuffer, + &bytesReadAt); /* * Step to the next big block. */ - if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, &blockIndex))) + if( size > bytesReadAt && FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, &blockIndex))) return STG_E_DOCFILECORRUPT; - bufferWalker += bytesToReadInBuffer; - size -= bytesToReadInBuffer; - *bytesRead += bytesToReadInBuffer; + bufferWalker += bytesReadAt; + size -= bytesReadAt; + *bytesRead += bytesReadAt; offsetInBlock = 0; /* There is no offset on the next block */ + if (bytesToReadInBuffer != bytesReadAt) + break; } return (size == 0) ? S_OK : STG_E_READFAULT; @@ -4611,7 +4600,6 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This, ULONG bytesToWrite; ULONG blockIndex; const BYTE* bufferWalker; - BYTE* bigBlockBuffer; /* * Find the first block in the stream that contains part of the buffer. @@ -4659,31 +4647,39 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This, while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) { + ULARGE_INTEGER ulOffset; + DWORD bytesWrittenAt; /* * Calculate how many bytes we can copy from this big block. */ bytesToWrite = min(This->parentStorage->bigBlockSize - offsetInBlock, size); - /* - * Copy those bytes to the buffer - */ - bigBlockBuffer = StorageImpl_GetBigBlock(This->parentStorage, blockIndex); - - memcpy(bigBlockBuffer + offsetInBlock, bufferWalker, bytesToWrite); + TRACE("block %i\n",blockIndex); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex) + + offsetInBlock; - StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); + StorageImpl_WriteAt(This->parentStorage, + ulOffset, + (BYTE*)bufferWalker, + bytesToWrite, + &bytesWrittenAt); /* * Step to the next big block. */ - if(FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, + if(size > bytesWrittenAt && FAILED(StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex, &blockIndex))) return STG_E_DOCFILECORRUPT; - bufferWalker += bytesToWrite; - size -= bytesToWrite; - *bytesWritten += bytesToWrite; + + bufferWalker += bytesWrittenAt; + size -= bytesWrittenAt; + *bytesWritten += bytesWrittenAt; offsetInBlock = 0; /* There is no offset on the next block */ + + if (bytesWrittenAt != bytesToWrite) + break; } return (size == 0) ? S_OK : STG_E_WRITEFAULT; @@ -5131,7 +5127,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock( ULONG sbdIndex = This->parentStorage->smallBlockDepotStart; ULONG nextBlock, newsbdIndex; - BYTE* smallBlockDepot; + BYTE smallBlockDepot[BIG_BLOCK_SIZE]; nextBlock = sbdIndex; while (nextBlock != BLOCK_END_OF_CHAIN) @@ -5155,11 +5151,8 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock( /* * Initialize all the small blocks to free */ - smallBlockDepot = - StorageImpl_GetBigBlock(This->parentStorage, newsbdIndex); - memset(smallBlockDepot, BLOCK_UNUSED, This->parentStorage->bigBlockSize); - StorageImpl_ReleaseBigBlock(This->parentStorage, smallBlockDepot); + StorageImpl_WriteBigBlock(This->parentStorage, newsbdIndex, smallBlockDepot); if (count == 0) { diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index 569cb36e03..4c893a06a9 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -191,11 +191,11 @@ BigBlockFile* BIGBLOCKFILE_Construct(HANDLE hFile, BOOL fileBased); void BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This); void BIGBLOCKFILE_EnsureExists(LPBIGBLOCKFILE This, ULONG index); -void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index); -void* BIGBLOCKFILE_GetROBigBlock(LPBIGBLOCKFILE This, ULONG index); -void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock); void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); -ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This); +HRESULT BIGBLOCKFILE_ReadAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, + void* buffer, ULONG size, ULONG* bytesRead); +HRESULT BIGBLOCKFILE_WriteAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, + void* buffer, const ULONG size, ULONG* bytesRead); /************************************************************************* * Ole Convert support -- 2.32.0.93.g670b81a890