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.
This commit is contained in:
Aric Stewart 2007-03-16 13:34:28 -05:00 committed by Alexandre Julliard
parent 921edab758
commit 838eb4037f
3 changed files with 358 additions and 316 deletions

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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