From 2514b5140069b68a20c219bfa966de70cf1d72a8 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov@etersoft.ru>
Date: Tue, 7 Dec 2010 20:41:16 +0300
Subject: [PATCH] oleaut32: MSDN says that Load can only seek and read from stream (eterbug #6343).

---
 dlls/oleaut32/olepicture.c |   94 +++++++++++++++-----------------------------
 1 files changed, 32 insertions(+), 62 deletions(-)

diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c
index fbec73d..f9ad70d 100644
--- a/dlls/oleaut32/olepicture.c
+++ b/dlls/oleaut32/olepicture.c
@@ -1322,15 +1322,15 @@ static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
  * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
  */
 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
+  LARGE_INTEGER cur, zero = {{0, 0}};
+  ULARGE_INTEGER ucur, end;
   HRESULT	hr;
   BOOL		headerisdata;
-  BOOL		statfailed = FALSE;
   ULONG		xread, toread;
   ULONG 	headerread;
   BYTE 		*xbuf;
   DWORD		header[2];
   WORD		magic;
-  STATSTG       statstg;
   OLEPictureImpl *This = impl_from_IPersistStream(iface);
   
   TRACE("(%p,%p)\n",This,pStm);
@@ -1347,17 +1347,17 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm)
    * At least in Visual Basic 6, resource streams, valid headers are
    *    header[0] == "lt\0\0",
    *    header[1] == length_of_stream.
-   *
-   * Also handle streams where we do not have a working "Stat" method by
-   * reading all data until the end of the stream.
    */
-  hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
-  if (hr != S_OK) {
-      TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
-      statfailed = TRUE;
-      /* we will read at least 8 byte ... just right below */
-      statstg.cbSize.QuadPart = 8;
-  }
+  hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &ucur);
+  if (hr != S_OK)
+      return hr;
+  hr = IStream_Seek(pStm, zero, STREAM_SEEK_END, &end);
+  if (hr != S_OK)
+      return hr;
+  cur.QuadPart = ucur.QuadPart;
+  hr = IStream_Seek(pStm, cur, STREAM_SEEK_SET, NULL);
+  if (hr != S_OK)
+      return hr;
 
   toread = 0;
   headerread = 0;
@@ -1371,7 +1371,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm)
       headerread += xread;
       xread = 0;
       
-      if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
+      if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] + headerread <= end.QuadPart)) {
           if (toread != 0 && toread != header[1]) 
               FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
                   toread, header[1]);
@@ -1382,12 +1382,12 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm)
               !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
               !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
               (header[0] == EMR_HEADER)            ||   /* EMF header */
-              (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
+              (header[1] > end.QuadPart)           ||   /* invalid size */
               (header[1]==0)
           ) {/* Found start of bitmap data */
               headerisdata = TRUE;
               if (toread == 0) 
-              	  toread = statstg.cbSize.QuadPart-8;
+                  toread = end.QuadPart-8;
               else toread -= 8;
               xread = 8;
           } else {
@@ -1397,54 +1397,24 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm)
       }
   } while (!headerisdata);
 
-  if (statfailed) { /* we don't know the size ... read all we get */
-      int sizeinc = 4096;
-      int origsize = sizeinc;
-      ULONG nread = 42;
-
-      TRACE("Reading all data from stream.\n");
-      xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
-      if (headerisdata)
-          memcpy (xbuf, header, 8);
-      while (1) {
-          while (xread < origsize) {
-              hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
-              xread += nread;
-              if (hr != S_OK || !nread)
-                  break;
-          }
-          if (!nread || hr != S_OK) /* done, or error */
-              break;
-          if (xread == origsize) {
-              origsize += sizeinc;
-              sizeinc = 2*sizeinc; /* exponential increase */
-              xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
-          }
-      }
-      if (hr != S_OK)
-          TRACE("hr in no-stat loader case is %08x\n", hr);
-      TRACE("loaded %d bytes.\n", xread);
-      This->datalen = xread;
-      This->data    = xbuf;
-  } else {
-      This->datalen = toread+(headerisdata?8:0);
-      xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
-      if (!xbuf)
-          return E_OUTOFMEMORY;
-
-      if (headerisdata)
-          memcpy (xbuf, header, 8);
-
-      while (xread < This->datalen) {
-          ULONG nread;
-          hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
-          xread += nread;
-          if (hr != S_OK || !nread)
-              break;
-      }
-      if (xread != This->datalen)
-          ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
+  This->datalen = toread+(headerisdata?8:0);
+  xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
+  if (!xbuf)
+      return E_OUTOFMEMORY;
+
+  if (headerisdata)
+      memcpy (xbuf, header, 8);
+
+  while (xread < This->datalen) {
+      ULONG nread;
+      hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
+      xread += nread;
+      if (hr != S_OK || !nread)
+          break;
   }
+  if (xread != This->datalen)
+      ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
+
   if (This->datalen == 0) { /* Marks the "NONE" picture */
       This->desc.picType = PICTYPE_NONE;
       return S_OK;
-- 
1.7.3.2