(resubmit) Rework storage with blockfiles to properly use ILockBytes interfaces

Aric Stewart aric at codeweavers.com
Fri Mar 16 13:34:28 CDT 2007


A rework of parts of my previous patch to reduce the diff as a first step.
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 |  376 
+++++++++++++++++++++++------------------
  dlls/ole32/storage32.c        |  295 ++++++++++++++++-----------------
  dlls/ole32/storage32.h        |    8 +-
  3 files changed, 362 insertions(+), 317 deletions(-)
-------------- next part --------------
diff --git a/dlls/ole32/stg_bigblockfile.c b/dlls/ole32/stg_bigblockfile.c
index df2cea1..7744378 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_ReleaseMap
 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);
@@ -317,40 +313,6 @@ void BIGBLOCKFILE_Destructor(
 }
 
 /******************************************************************************
- *      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
  *
  * Grows the file if necessary to make sure the block is valid.
@@ -381,49 +343,6 @@ void BIGBLOCKFILE_EnsureExists(LPBIGBLOC
 }
 
 /******************************************************************************
- *      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
  *
  * Sets the size of the file.
@@ -495,85 +414,6 @@ ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBI
 }
 
 /******************************************************************************
- *      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(LPBIGBL
 
 	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_CreatePa
     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,209 @@ static DWORD BIGBLOCKFILE_GetProtectMode
     }
     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(
+      ILockBytes*    iface,
+      ULARGE_INTEGER ulOffset,  /* [in] */
+      void*          pv,        /* [length_is][size_is][out] */
+      ULONG          cb,        /* [in] */
+      ULONG*         pcbRead)   /* [out] */
+{
+    BigBlockFile* const This=(BigBlockFile*)iface;
+    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(
+      ILockBytes*    iface,
+      ULARGE_INTEGER ulOffset,    /* [in] */
+      const void*    pv,          /* [size_is][in] */
+      ULONG          cb,          /* [in] */
+      ULONG*         pcbWritten)  /* [out] */
+{
+    BigBlockFile* const This=(BigBlockFile*)iface;
+    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 dc2db11..32668f7 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -84,9 +84,6 @@ typedef struct StorageInternalImpl Stora
 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_G
 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_FindProper
 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_GetNextFreeBigB
   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_GetNextFreeBigB
       }
     }
 
-    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_GetNextFreeBigB
 
         depotBlockOffset += sizeof(ULONG);
       }
-
-      StorageImpl_ReleaseBigBlock(This, depotBuffer);
     }
 
     depotIndex++;
@@ -2722,16 +2750,13 @@ static ULONG StorageImpl_GetNextFreeBigB
  */
 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_GetExtDepotBl
   }
 
   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_SetExtDepotBlo
 
   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_AddExtBlockDe
 {
   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_AddExtBlockDe
     /*
      * 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_GetNextBlockI
   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_GetNextBlockI
       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_GetNextBlockI
       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_GetNextExtend
 {
   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_SetNextBlockInCh
   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_SetNextBlockInCh
     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_LoadFileHeade
           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_LoadFileHeade
      */
     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_LoadFileHeade
     }
     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);
-
-  if (bigBlockBuffer!=0)
-  {
-    memcpy(bigBlockBuffer, buffer, This->bigBlockSize);
+  ULARGE_INTEGER ulOffset;
+  DWORD  wrote;
 
-    StorageImpl_ReleaseBigBlock(This, bigBlockBuffer);
+  ulOffset.u.HighPart = 0;
+  ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex);
 
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static void* StorageImpl_GetROBigBlock(
-  StorageImpl* This,
-  ULONG          blockIndex)
-{
-  return BIGBLOCKFILE_GetROBigBlock(This->bigBlockFile, blockIndex);
+  StorageImpl_WriteAt(This, ulOffset, buffer, This->bigBlockSize, &wrote);
+  return (wrote == This->bigBlockSize);
 }
 
-static void* StorageImpl_GetBigBlock(
+static BOOL StorageImpl_WriteDWordToBigBlock(
   StorageImpl* This,
-  ULONG          blockIndex)
+  ULONG         blockIndex,
+  ULONG         offset, 
+  DWORD         value)
 {
-  return BIGBLOCKFILE_GetBigBlock(This->bigBlockFile, blockIndex);
-}
+  ULARGE_INTEGER ulOffset;
+  DWORD  wrote;
 
-static void StorageImpl_ReleaseBigBlock(
-  StorageImpl* This,
-  void*          pBigBlock)
-{
-  BIGBLOCKFILE_ReleaseBigBlock(This->bigBlockFile, pBigBlock);
+  ulOffset.u.HighPart = 0;
+  ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex);
+  ulOffset.u.LowPart += offset;
+  
+  value = htole32(value);
+  StorageImpl_WriteAt(This, ulOffset, &value, sizeof(DWORD), &wrote);
+  return (wrote == sizeof(DWORD));
 }
 
 /******************************************************************************
@@ -4518,7 +4504,8 @@ HRESULT BlockChainStream_ReadAt(BlockCha
   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(BlockCha
 
   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(BlockCh
   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(BlockCh
 
   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_GetNe
 
       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_GetNe
       /*
        * 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 569cb36..4c893a0 100644
--- a/dlls/ole32/storage32.h
+++ b/dlls/ole32/storage32.h
@@ -191,11 +191,11 @@ BigBlockFile*  BIGBLOCKFILE_Construct(HA
                                       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


More information about the wine-patches mailing list