ole32: Support storage files larger than 4 GB.

Vincent Povirk madewokherd at gmail.com
Wed Jun 11 14:38:19 CDT 2014


-------------- next part --------------
From be82cfd61c0219d8eb82bcf0bf8fa549dd138124 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Tue, 20 May 2014 16:08:09 -0500
Subject: [PATCH 1/3] ole32: Support storage files larger than 4 GB.

---
 dlls/ole32/stg_stream.c |   4 +-
 dlls/ole32/storage32.c  | 100 ++++++++++++++++++++++--------------------------
 dlls/ole32/storage32.h  |   1 +
 3 files changed, 49 insertions(+), 56 deletions(-)

diff --git a/dlls/ole32/stg_stream.c b/dlls/ole32/stg_stream.c
index d7abd0e..b60b17b 100644
--- a/dlls/ole32/stg_stream.c
+++ b/dlls/ole32/stg_stream.c
@@ -166,7 +166,7 @@ static HRESULT WINAPI StgStreamImpl_Read(
     /*
      * Advance the pointer for the number of positions read.
      */
-    This->currentPosition.u.LowPart += *pcbRead;
+    This->currentPosition.QuadPart += *pcbRead;
   }
 
   TRACE("<-- %08x\n", res);
@@ -247,7 +247,7 @@ static HRESULT WINAPI StgStreamImpl_Write(
   /*
    * Advance the position pointer for the number of positions written.
    */
-  This->currentPosition.u.LowPart += *pcbWritten;
+  This->currentPosition.QuadPart += *pcbWritten;
 
   if (SUCCEEDED(res))
     res = StorageBaseImpl_Flush(This->parentStorage);
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index a880e2a..69a2198 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -353,9 +353,9 @@ static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This);
 ** Block Functions
 */
 
-static ULONG StorageImpl_GetBigBlockOffset(StorageImpl* This, ULONG index)
+static ULONGLONG StorageImpl_GetBigBlockOffset(StorageImpl* This, ULONG index)
 {
-    return (index+1) * This->bigBlockSize;
+    return (ULONGLONG)(index+1) * This->bigBlockSize;
 }
 
 /************************************************************************
@@ -1322,8 +1322,7 @@ static HRESULT StorageImpl_CreateDirEntry(
     /*
      * initialize the size used by the directory stream
      */
-    newSize.u.HighPart = 0;
-    newSize.u.LowPart  = storage->bigBlockSize * blockCount;
+    newSize.QuadPart  = (ULONGLONG)storage->bigBlockSize * blockCount;
 
     /*
      * add a block to the directory stream
@@ -2602,7 +2601,6 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
   if (FAILED(hr)) return hr;
 
   /* Grow the stream if necessary */
-  newSize.QuadPart = 0;
   newSize.QuadPart = offset.QuadPart + size;
 
   if (newSize.QuadPart > data.size.QuadPart)
@@ -4156,8 +4154,7 @@ HRESULT StorageImpl_ReadRawDirEntry(StorageImpl *This, ULONG index, BYTE *buffer
   HRESULT hr;
   ULONG bytesRead;
 
-  offset.u.HighPart = 0;
-  offset.u.LowPart  = index * RAW_DIRENTRY_SIZE;
+  offset.QuadPart  = (ULONGLONG)index * RAW_DIRENTRY_SIZE;
 
   hr = BlockChainStream_ReadAt(
                     This->rootBlockChain,
@@ -4184,8 +4181,7 @@ HRESULT StorageImpl_WriteRawDirEntry(StorageImpl *This, ULONG index, const BYTE
   ULARGE_INTEGER offset;
   ULONG bytesRead;
 
-  offset.u.HighPart = 0;
-  offset.u.LowPart  = index * RAW_DIRENTRY_SIZE;
+  offset.QuadPart  = (ULONGLONG)index * RAW_DIRENTRY_SIZE;
 
   return BlockChainStream_WriteAt(
                     This->rootBlockChain,
@@ -4267,6 +4263,11 @@ void UpdateRawDirEntry(BYTE *buffer, const DirEntry *newData)
     buffer,
       OFFSET_PS_SIZE,
       newData->size.u.LowPart);
+
+  StorageUtl_WriteDWord(
+    buffer,
+      OFFSET_PS_SIZE_HIGH,
+      newData->size.u.HighPart);
 }
 
 /******************************************************************************
@@ -4350,7 +4351,10 @@ HRESULT StorageImpl_ReadDirEntry(
       OFFSET_PS_SIZE,
       &buffer->size.u.LowPart);
 
-    buffer->size.u.HighPart = 0;
+    StorageUtl_ReadDWord(
+      currentEntry,
+      OFFSET_PS_SIZE_HIGH,
+      &buffer->size.u.HighPart);
   }
 
   return readRes;
@@ -4381,8 +4385,7 @@ static HRESULT StorageImpl_ReadBigBlock(
   DWORD  read=0;
   HRESULT hr;
 
-  ulOffset.u.HighPart = 0;
-  ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
+  ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
 
   hr = StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read);
 
@@ -4407,9 +4410,8 @@ static BOOL StorageImpl_ReadDWordFromBigBlock(
   DWORD  read;
   DWORD  tmp;
 
-  ulOffset.u.HighPart = 0;
-  ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
-  ulOffset.u.LowPart += offset;
+  ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
+  ulOffset.QuadPart += offset;
 
   StorageImpl_ReadAt(This, ulOffset, &tmp, sizeof(DWORD), &read);
   *value = lendian32toh(tmp);
@@ -4424,8 +4426,7 @@ static BOOL StorageImpl_WriteBigBlock(
   ULARGE_INTEGER ulOffset;
   DWORD  wrote;
 
-  ulOffset.u.HighPart = 0;
-  ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
+  ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
 
   StorageImpl_WriteAt(This, ulOffset, buffer, This->bigBlockSize, &wrote);
   return (wrote == This->bigBlockSize);
@@ -4440,9 +4441,8 @@ static BOOL StorageImpl_WriteDWordToBigBlock(
   ULARGE_INTEGER ulOffset;
   DWORD  wrote;
 
-  ulOffset.u.HighPart = 0;
-  ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
-  ulOffset.u.LowPart += offset;
+  ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
+  ulOffset.QuadPart += offset;
 
   value = htole32(value);
   StorageImpl_WriteAt(This, ulOffset, &value, sizeof(DWORD), &wrote);
@@ -7029,8 +7029,8 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
   void*          buffer,
   ULONG*         bytesRead)
 {
-  ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize;
-  ULONG offsetInBlock     = offset.u.LowPart % This->parentStorage->bigBlockSize;
+  ULONG blockNoInSequence = offset.QuadPart / This->parentStorage->bigBlockSize;
+  ULONG offsetInBlock     = offset.QuadPart % This->parentStorage->bigBlockSize;
   ULONG bytesToReadInBuffer;
   ULONG blockIndex;
   BYTE* bufferWalker;
@@ -7077,8 +7077,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
     if (!cachedBlock)
     {
       /* Not in cache, and we're going to read past the end of the block. */
-      ulOffset.u.HighPart = 0;
-      ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) +
+      ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) +
                                offsetInBlock;
 
       StorageImpl_ReadAt(This->parentStorage,
@@ -7127,8 +7126,8 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This,
   const void*       buffer,
   ULONG*            bytesWritten)
 {
-  ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize;
-  ULONG offsetInBlock     = offset.u.LowPart % This->parentStorage->bigBlockSize;
+  ULONG blockNoInSequence = offset.QuadPart / This->parentStorage->bigBlockSize;
+  ULONG offsetInBlock     = offset.QuadPart % This->parentStorage->bigBlockSize;
   ULONG bytesToWrite;
   ULONG blockIndex;
   const BYTE* bufferWalker;
@@ -7162,8 +7161,7 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This,
     if (!cachedBlock)
     {
       /* Not in cache, and we're going to write past the end of the block. */
-      ulOffset.u.HighPart = 0;
-      ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) +
+      ulOffset.QuadPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) +
                                offsetInBlock;
 
       StorageImpl_WriteAt(This->parentStorage,
@@ -7215,9 +7213,9 @@ static BOOL BlockChainStream_Shrink(BlockChainStream* This,
   /*
    * Figure out how many blocks are needed to contain the new size
    */
-  numBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize;
+  numBlocks = newSize.QuadPart / This->parentStorage->bigBlockSize;
 
-  if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0)
+  if ((newSize.QuadPart % This->parentStorage->bigBlockSize) != 0)
     numBlocks++;
 
   if (numBlocks)
@@ -7346,9 +7344,9 @@ static BOOL BlockChainStream_Enlarge(BlockChainStream* This,
   /*
    * Figure out how many blocks are needed to contain this stream
    */
-  newNumBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize;
+  newNumBlocks = newSize.QuadPart / This->parentStorage->bigBlockSize;
 
-  if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0)
+  if ((newSize.QuadPart % This->parentStorage->bigBlockSize) != 0)
     newNumBlocks++;
 
   /*
@@ -7423,10 +7421,10 @@ BOOL BlockChainStream_SetSize(
 {
   ULARGE_INTEGER size = BlockChainStream_GetSize(This);
 
-  if (newSize.u.LowPart == size.u.LowPart)
+  if (newSize.QuadPart == size.QuadPart)
     return TRUE;
 
-  if (newSize.u.LowPart < size.u.LowPart)
+  if (newSize.QuadPart < size.QuadPart)
   {
     BlockChainStream_Shrink(This, newSize);
   }
@@ -7468,10 +7466,8 @@ static ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This)
      * size of them
      */
     ULARGE_INTEGER result;
-    result.u.HighPart = 0;
-
-    result.u.LowPart  =
-      BlockChainStream_GetCount(This) *
+    result.QuadPart =
+      (ULONGLONG)BlockChainStream_GetCount(This) *
       This->parentStorage->bigBlockSize;
 
     return result;
@@ -7556,8 +7552,7 @@ static HRESULT SmallBlockChainStream_GetNextBlockInChain(
 
   *nextBlockInChain = BLOCK_END_OF_CHAIN;
 
-  offsetOfBlockInDepot.u.HighPart = 0;
-  offsetOfBlockInDepot.u.LowPart  = blockIndex * sizeof(ULONG);
+  offsetOfBlockInDepot.QuadPart  = (ULONGLONG)blockIndex * sizeof(ULONG);
 
   /*
    * Read those bytes in the buffer from the small block file.
@@ -7598,8 +7593,7 @@ static void SmallBlockChainStream_SetNextBlockInChain(
   DWORD  buffer;
   ULONG  bytesWritten;
 
-  offsetOfBlockInDepot.u.HighPart = 0;
-  offsetOfBlockInDepot.u.LowPart  = blockIndex * sizeof(ULONG);
+  offsetOfBlockInDepot.QuadPart  = (ULONGLONG)blockIndex * sizeof(ULONG);
 
   StorageUtl_WriteDWord((BYTE *)&buffer, 0, nextBlock);
 
@@ -7654,7 +7648,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
    */
   while (nextBlockIndex != BLOCK_UNUSED)
   {
-    offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG);
+    offsetOfBlockInDepot.QuadPart = (ULONGLONG)blockIndex * sizeof(ULONG);
 
     res = BlockChainStream_ReadAt(
                 This->parentStorage->smallBlockDepotChain,
@@ -7682,14 +7676,14 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
       ULARGE_INTEGER newSize, offset;
       ULONG bytesWritten;
 
-      newSize.QuadPart = (count + 1) * This->parentStorage->bigBlockSize;
+      newSize.QuadPart = (ULONGLONG)(count + 1) * This->parentStorage->bigBlockSize;
       BlockChainStream_Enlarge(This->parentStorage->smallBlockDepotChain, newSize);
 
       /*
        * Initialize all the small blocks to free
        */
       memset(smallBlockDepot, BLOCK_UNUSED, This->parentStorage->bigBlockSize);
-      offset.QuadPart = count * This->parentStorage->bigBlockSize;
+      offset.QuadPart = (ULONGLONG)count * This->parentStorage->bigBlockSize;
       BlockChainStream_WriteAt(This->parentStorage->smallBlockDepotChain,
         offset, This->parentStorage->bigBlockSize, smallBlockDepot, &bytesWritten);
 
@@ -7707,7 +7701,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
    */
   blocksRequired = (blockIndex / smallBlocksPerBigBlock) + 1;
 
-  size_required.QuadPart = blocksRequired * This->parentStorage->bigBlockSize;
+  size_required.QuadPart = (ULONGLONG)blocksRequired * This->parentStorage->bigBlockSize;
 
   old_size = BlockChainStream_GetSize(This->parentStorage->smallBlockRootChain);
 
@@ -7801,11 +7795,10 @@ HRESULT SmallBlockChainStream_ReadAt(
     /*
      * Calculate the offset of the small block in the small block file.
      */
-    offsetInBigBlockFile.u.HighPart  = 0;
-    offsetInBigBlockFile.u.LowPart   =
-      blockIndex * This->parentStorage->smallBlockSize;
+    offsetInBigBlockFile.QuadPart   =
+      (ULONGLONG)blockIndex * This->parentStorage->smallBlockSize;
 
-    offsetInBigBlockFile.u.LowPart  += offsetInBlock;
+    offsetInBigBlockFile.QuadPart  += offsetInBlock;
 
     /*
      * Read those bytes in the buffer from the small block file.
@@ -7897,11 +7890,10 @@ HRESULT SmallBlockChainStream_WriteAt(
     /*
      * Calculate the offset of the small block in the small block file.
      */
-    offsetInBigBlockFile.u.HighPart  = 0;
-    offsetInBigBlockFile.u.LowPart   =
-      blockIndex * This->parentStorage->smallBlockSize;
+    offsetInBigBlockFile.QuadPart   =
+      (ULONGLONG)blockIndex * This->parentStorage->smallBlockSize;
 
-    offsetInBigBlockFile.u.LowPart  += offsetInBlock;
+    offsetInBigBlockFile.QuadPart  += offsetInBlock;
 
     /*
      * Write those bytes in the buffer to the small block file.
diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h
index cc5b970..108aad7 100644
--- a/dlls/ole32/storage32.h
+++ b/dlls/ole32/storage32.h
@@ -71,6 +71,7 @@ static const ULONG OFFSET_PS_MTIMELOW        = 0x0000006C;
 static const ULONG OFFSET_PS_MTIMEHIGH       = 0x00000070;
 static const ULONG OFFSET_PS_STARTBLOCK	     = 0x00000074;
 static const ULONG OFFSET_PS_SIZE	     = 0x00000078;
+static const ULONG OFFSET_PS_SIZE_HIGH	     = 0x0000007C;
 static const WORD  DEF_BIG_BLOCK_SIZE_BITS   = 0x0009;
 static const WORD  MIN_BIG_BLOCK_SIZE_BITS   = 0x0009;
 static const WORD  MAX_BIG_BLOCK_SIZE_BITS   = 0x000c;
-- 
1.8.3.2



More information about the wine-patches mailing list