diff --git a/dlls/ole32/stg_bigblockfile.c b/dlls/ole32/stg_bigblockfile.c index df2cea1125e..a208bb8aa10 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 dc2db11474b..408453ad5ba 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; + ULARGE_INTEGER ulOffset; + DWORD wrote; - bigBlockBuffer = StorageImpl_GetBigBlock(This, blockIndex); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); - if (bigBlockBuffer!=0) - { - memcpy(bigBlockBuffer, buffer, This->bigBlockSize); - - StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); - - 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); + TRACE("block %i\n",blockIndex); + ulOffset.u.HighPart = 0; + ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex) + + offsetInBlock; - memcpy(bigBlockBuffer + offsetInBlock, bufferWalker, bytesToWrite); - - 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 569cb36e035..4c893a06a9e 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