Vincent Povirk : ole32: Use the storage vtable to read streams.

Alexandre Julliard julliard at winehq.org
Tue Dec 8 11:10:36 CST 2009


Module: wine
Branch: master
Commit: 62e54bacba086cf279936c28f75942c019b887cd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=62e54bacba086cf279936c28f75942c019b887cd

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Nov 30 10:35:55 2009 -0600

ole32: Use the storage vtable to read streams.

---

 dlls/ole32/stg_stream.c |   58 ++++++----------------------------------
 dlls/ole32/storage32.c  |   67 +++++++++++++++++++++++++++++++++++++++++++++-
 dlls/ole32/storage32.h  |    8 +++++
 3 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/dlls/ole32/stg_stream.c b/dlls/ole32/stg_stream.c
index 6200126..0888180 100644
--- a/dlls/ole32/stg_stream.c
+++ b/dlls/ole32/stg_stream.c
@@ -264,7 +264,6 @@ static HRESULT WINAPI StgStreamImpl_Read(
   StgStreamImpl* const This=(StgStreamImpl*)iface;
 
   ULONG bytesReadBuffer;
-  ULONG bytesToReadFromBuffer;
   HRESULT res;
 
   TRACE("(%p, %p, %d, %p)\n",
@@ -283,60 +282,21 @@ static HRESULT WINAPI StgStreamImpl_Read(
   if (pcbRead==0)
     pcbRead = &bytesReadBuffer;
 
-  /*
-   * Using the known size of the stream, calculate the number of bytes
-   * to read from the block chain
-   */
-  bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
-
-  /*
-   * Depending on the type of chain that was opened when the stream was constructed,
-   * we delegate the work to the method that reads the block chains.
-   */
-  if (This->smallBlockChain!=0)
-  {
-    res = SmallBlockChainStream_ReadAt(This->smallBlockChain,
-				 This->currentPosition,
-				 bytesToReadFromBuffer,
-				 pv,
-				 pcbRead);
+  res = StorageBaseImpl_StreamReadAt(This->parentStorage,
+                                     This->dirEntry,
+                                     This->currentPosition,
+                                     cb,
+                                     pv,
+                                     pcbRead);
 
-  }
-  else if (This->bigBlockChain!=0)
-  {
-    res = BlockChainStream_ReadAt(This->bigBlockChain,
-                 This->currentPosition,
-                 bytesToReadFromBuffer,
-                 pv,
-                 pcbRead);
-  }
-  else
+  if (SUCCEEDED(res))
   {
     /*
-     * Small and big block chains are both NULL. This case will happen
-     * when a stream starts with BLOCK_END_OF_CHAIN and has size zero.
+     * Advance the pointer for the number of positions read.
      */
-
-    *pcbRead = 0;
-    res = S_OK;
-    goto end;
-  }
-
-  if (SUCCEEDED(res))
-  {
-      /*
-       * We should always be able to read the proper amount of data from the
-       * chain.
-       */
-      assert(bytesToReadFromBuffer == *pcbRead);
-
-      /*
-       * Advance the pointer for the number of positions read.
-       */
-      This->currentPosition.u.LowPart += *pcbRead;
+    This->currentPosition.u.LowPart += *pcbRead;
   }
 
-end:
   TRACE("<-- %08x\n", res);
   return res;
 }
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index 53c2c87..0e5861d 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -2192,6 +2192,60 @@ static HRESULT StorageImpl_BaseReadDirEntry(StorageBaseImpl *base,
   return StorageImpl_ReadDirEntry(This, index, data);
 }
 
+static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
+  ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
+{
+  StorageImpl *This = (StorageImpl*)base;
+  DirEntry data;
+  HRESULT hr;
+  ULONG bytesToRead;
+
+  hr = StorageImpl_ReadDirEntry(This, index, &data);
+  if (FAILED(hr)) return hr;
+
+  if (data.size.QuadPart == 0)
+  {
+    *bytesRead = 0;
+    return S_OK;
+  }
+
+  if (offset.QuadPart + size > data.size.QuadPart)
+  {
+    bytesToRead = data.size.QuadPart - offset.QuadPart;
+  }
+  else
+  {
+    bytesToRead = size;
+  }
+
+  if (data.size.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
+  {
+    SmallBlockChainStream *stream;
+
+    stream = SmallBlockChainStream_Construct(This, NULL, index);
+    if (!stream) return E_OUTOFMEMORY;
+
+    hr = SmallBlockChainStream_ReadAt(stream, offset, bytesToRead, buffer, bytesRead);
+
+    SmallBlockChainStream_Destroy(stream);
+
+    return hr;
+  }
+  else
+  {
+    BlockChainStream *stream;
+
+    stream = BlockChainStream_Construct(This, NULL, index);
+    if (!stream) return E_OUTOFMEMORY;
+
+    hr = BlockChainStream_ReadAt(stream, offset, bytesToRead, buffer, bytesRead);
+
+    BlockChainStream_Destroy(stream);
+
+    return hr;
+  }
+}
+
 /*
  * Virtual function table for the IStorage32Impl class.
  */
@@ -2223,7 +2277,8 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl =
   StorageImpl_CreateDirEntry,
   StorageImpl_BaseWriteDirEntry,
   StorageImpl_BaseReadDirEntry,
-  StorageImpl_DestroyDirEntry
+  StorageImpl_DestroyDirEntry,
+  StorageImpl_StreamReadAt
 };
 
 static HRESULT StorageImpl_Construct(
@@ -3671,6 +3726,13 @@ static HRESULT StorageInternalImpl_DestroyDirEntry(StorageBaseImpl *base,
     index);
 }
 
+static HRESULT StorageInternalImpl_StreamReadAt(StorageBaseImpl *base,
+  DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
+{
+  return StorageBaseImpl_StreamReadAt(&base->ancestorStorage->base,
+    index, offset, size, buffer, bytesRead);
+}
+
 /******************************************************************************
 **
 ** Storage32InternalImpl_Commit
@@ -4117,7 +4179,8 @@ static const StorageBaseImplVtbl StorageInternalImpl_BaseVtbl =
   StorageInternalImpl_CreateDirEntry,
   StorageInternalImpl_WriteDirEntry,
   StorageInternalImpl_ReadDirEntry,
-  StorageInternalImpl_DestroyDirEntry
+  StorageInternalImpl_DestroyDirEntry,
+  StorageInternalImpl_StreamReadAt
 };
 
 /******************************************************************************
diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h
index 12cff71..24070d1 100644
--- a/dlls/ole32/storage32.h
+++ b/dlls/ole32/storage32.h
@@ -252,6 +252,7 @@ struct StorageBaseImplVtbl {
   HRESULT (*WriteDirEntry)(StorageBaseImpl*,DirRef,const DirEntry*);
   HRESULT (*ReadDirEntry)(StorageBaseImpl*,DirRef,DirEntry*);
   HRESULT (*DestroyDirEntry)(StorageBaseImpl*,DirRef);
+  HRESULT (*StreamReadAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,void*,ULONG*);
 };
 
 static inline void StorageBaseImpl_Destroy(StorageBaseImpl *This)
@@ -283,6 +284,13 @@ static inline HRESULT StorageBaseImpl_DestroyDirEntry(StorageBaseImpl *This,
   return This->baseVtbl->DestroyDirEntry(This, index);
 }
 
+/* Read up to size bytes from this directory entry's stream at the given offset. */
+static inline HRESULT StorageBaseImpl_StreamReadAt(StorageBaseImpl *This,
+  DirRef index, ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
+{
+  return This->baseVtbl->StreamReadAt(This, index, offset, size, buffer, bytesRead);
+}
+
 /****************************************************************************
  * StorageBaseImpl stream list handlers
  */




More information about the wine-cvs mailing list