[PATCH 1/2] ole32: Don't keep the streams open.

Huw Davies huw at codeweavers.com
Wed Jan 24 03:31:29 CST 2018


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/ole32/datacache.c | 156 ++++++++++++++-----------------------------------
 1 file changed, 44 insertions(+), 112 deletions(-)

diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 60ddd386ba..ba253d9330 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -90,12 +90,8 @@ typedef struct PresentationDataHeader
   DWORD dwSize;
 } PresentationDataHeader;
 
-enum stream_type
-{
-    no_stream,
-    pres_stream,
-    contents_stream
-};
+#define STREAM_NUMBER_NOT_SET -2
+#define STREAM_NUMBER_CONTENTS -1 /* CONTENTS stream */
 
 typedef struct DataCacheEntry
 {
@@ -104,19 +100,16 @@ typedef struct DataCacheEntry
   FORMATETC fmtetc;
   /* cached data */
   STGMEDIUM stgmedium;
-  /*
-   * This stream pointer is set through a call to
-   * IPersistStorage_Load. This is where the visual
-   * representation of the object is stored.
-   */
-  IStream *stream;
-  enum stream_type stream_type;
   /* connection ID */
   DWORD id;
   /* dirty flag */
   BOOL dirty;
-  /* stream number (-1 if not set ) */
-  unsigned short stream_number;
+  /* stream number that the entry was loaded from.
+     This is used to defer loading until the data is actually needed. */
+  int load_stream_num;
+  /* stream number that the entry will be saved to.
+     This may differ from above if cache entries have been Uncache()d for example. */
+  int save_stream_num;
   /* sink id set when object is running */
   DWORD sink_id;
   /* Advise sink flags */
@@ -260,8 +253,6 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
 static void DataCacheEntry_Destroy(DataCache *cache, DataCacheEntry *cache_entry)
 {
     list_remove(&cache_entry->entry);
-    if (cache_entry->stream)
-        IStream_Release(cache_entry->stream);
     CoTaskMemFree(cache_entry->fmtetc.ptd);
     ReleaseStgMedium(&cache_entry->stgmedium);
     if(cache_entry->sink_id)
@@ -355,11 +346,10 @@ static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC *fmt, DWORD
 
     entry->stgmedium.tymed = TYMED_NULL;
     entry->stgmedium.pUnkForRelease = NULL;
-    entry->stream = NULL;
-    entry->stream_type = no_stream;
     entry->id = id;
     entry->dirty = TRUE;
-    entry->stream_number = -1;
+    entry->load_stream_num = STREAM_NUMBER_NOT_SET;
+    entry->save_stream_num = STREAM_NUMBER_NOT_SET;
     entry->sink_id = 0;
     entry->advise_flags = advf;
 
@@ -518,60 +508,18 @@ static HRESULT write_clipformat(IStream *stream, CLIPFORMAT clipformat)
     return hr;
 }
 
-/************************************************************************
- * DataCacheEntry_OpenPresStream
- *
- * This method will find the stream for the given presentation. It makes
- * no attempt at fallback.
- *
- * Param:
- *   this       - Pointer to the DataCache object
- *   drawAspect - The aspect of the object that we wish to draw.
- *   pStm       - A returned stream. It points to the beginning of the
- *              - presentation data, including the header.
- *
- * Errors:
- *   S_OK		The requested stream has been opened.
- *   OLE_E_BLANK	The requested stream could not be found.
- *   Quite a few others I'm too lazy to map correctly.
- *
- * Notes:
- *   Algorithm:	Scan the elements of the presentation storage, looking
- *		for presentation streams. For each presentation stream,
- *		load the header and check to see if the aspect matches.
- *
- *   If a fallback is desired, just opening the first presentation stream
- *   is a possibility.
- */
-static HRESULT DataCacheEntry_OpenPresStream(DataCacheEntry *cache_entry, IStream **ppStm)
-{
-    HRESULT hr;
-    LARGE_INTEGER offset;
-
-    if (cache_entry->stream)
-    {
-        /* Rewind the stream before returning it. */
-        offset.QuadPart = 0;
-
-        hr = IStream_Seek( cache_entry->stream, offset, STREAM_SEEK_SET, NULL );
-        if (SUCCEEDED( hr ))
-        {
-            *ppStm = cache_entry->stream;
-            IStream_AddRef( cache_entry->stream );
-        }
-    }
-    else
-        hr = OLE_E_BLANK;
-
-    return hr;
-}
+static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
 
 static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm )
 {
-    WCHAR name[] = {2,'O','l','e','P','r','e','s',
+    WCHAR pres[] = {2,'O','l','e','P','r','e','s',
                     '0' + (stream_number / 100) % 10,
                     '0' + (stream_number / 10) % 10,
                     '0' + stream_number % 10, 0};
+    const WCHAR *name = pres;
+
+    if (stream_number == STREAM_NUMBER_NOT_SET) return E_FAIL;
+    if (stream_number == STREAM_NUMBER_CONTENTS) name = CONTENTS;
 
     return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
 }
@@ -589,9 +537,9 @@ static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
     static const LARGE_INTEGER offset_zero;
     ULONG read;
 
-    if (cache_entry->stream_type != pres_stream)
+    if (cache_entry->load_stream_num == STREAM_NUMBER_CONTENTS)
     {
-        FIXME( "Unimplemented for stream type %d\n", cache_entry->stream_type );
+        FIXME( "Unimplemented for CONTENTS stream\n" );
         return E_FAIL;
     }
 
@@ -658,9 +606,9 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
     BITMAPFILEHEADER file;
     BITMAPINFOHEADER *info;
 
-    if (cache_entry->stream_type != contents_stream)
+    if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
     {
-        FIXME( "Unimplemented for stream type %d\n", cache_entry->stream_type );
+        FIXME( "Unimplemented for presentation stream\n" );
         return E_FAIL;
     }
 
@@ -746,12 +694,13 @@ fail:
  *   This method returns a metafile handle if it is successful.
  *   it will return 0 if not.
  */
-static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry)
+static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry, IStorage *stg)
 {
     HRESULT hr;
     IStream *stm;
 
-    hr = DataCacheEntry_OpenPresStream( cache_entry, &stm );
+    if (!stg) return OLE_E_BLANK;
+    hr = open_pres_stream( stg, cache_entry->load_stream_num, &stm );
     if (FAILED(hr)) return hr;
 
     switch (cache_entry->fmtetc.cfFormat)
@@ -1004,14 +953,13 @@ static HRESULT save_view_cache(DataCacheEntry *entry, IStream *stream)
     return hr;
 }
 
-static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
 static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
                              BOOL contents, IStream **stream)
 {
     WCHAR pres[] = {2,'O','l','e','P','r','e','s',
-        '0' + (cache_entry->stream_number / 100) % 10,
-        '0' + (cache_entry->stream_number / 10) % 10,
-        '0' + cache_entry->stream_number % 10, 0};
+        '0' + (cache_entry->save_stream_num / 100) % 10,
+        '0' + (cache_entry->save_stream_num / 10) % 10,
+        '0' + cache_entry->save_stream_num % 10, 0};
     const WCHAR *name;
 
     if (contents)
@@ -1031,7 +979,7 @@ static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storag
     IStream *stream;
     BOOL contents = (cache_entry->id == 1);
 
-    TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number, debugstr_formatetc(&cache_entry->fmtetc));
+    TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->save_stream_num, debugstr_formatetc(&cache_entry->fmtetc));
 
     hr = create_stream(cache_entry, storage, contents, &stream);
     if (FAILED(hr))
@@ -1216,11 +1164,11 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
         return copy_stg_medium(cache_entry->fmtetc.cfFormat, &cache_entry->stgmedium, stgmedium);
 }
 
-static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, FORMATETC *fmt, STGMEDIUM *stgmedium)
+static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, IStorage *stg, FORMATETC *fmt, STGMEDIUM *stgmedium)
 {
-    if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->stream)
+    if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET)
     {
-        HRESULT hr = DataCacheEntry_LoadData(cache_entry);
+        HRESULT hr = DataCacheEntry_LoadData(cache_entry, stg);
         if (FAILED(hr))
             return hr;
     }
@@ -1239,15 +1187,6 @@ static inline HRESULT DataCacheEntry_DiscardData(DataCacheEntry *cache_entry)
     return S_OK;
 }
 
-static inline void DataCacheEntry_HandsOffStorage(DataCacheEntry *cache_entry)
-{
-    if (cache_entry->stream)
-    {
-        IStream_Release(cache_entry->stream);
-        cache_entry->stream = NULL;
-    }
-}
-
 static inline DWORD tymed_from_cf( DWORD cf )
 {
     switch( cf )
@@ -1470,7 +1409,7 @@ static HRESULT WINAPI DataCache_GetData(
     if (!cache_entry)
         return OLE_E_BLANK;
 
-    return DataCacheEntry_GetData(cache_entry, pformatetcIn, pmedium);
+    return DataCacheEntry_GetData(cache_entry, This->presentationStorage, pformatetcIn, pmedium);
 }
 
 static HRESULT WINAPI DataCache_GetDataHere(
@@ -1703,8 +1642,7 @@ static HRESULT WINAPI DataCache_InitNew(
 }
 
 
-static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, IStream *stm,
-                                enum stream_type type )
+static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, int stream_number )
 {
     DataCacheEntry *cache_entry;
     HRESULT hr = S_OK;
@@ -1717,10 +1655,8 @@ static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD adv
     if (SUCCEEDED( hr ))
     {
         DataCacheEntry_DiscardData( cache_entry );
-        if (cache_entry->stream) IStream_Release( cache_entry->stream );
-        cache_entry->stream = stm;
-        IStream_AddRef( stm );
-        cache_entry->stream_type = type;
+        cache_entry->load_stream_num = stream_number;
+        cache_entry->save_stream_num = stream_number;
         cache_entry->dirty = FALSE;
     }
     return hr;
@@ -1753,7 +1689,7 @@ static HRESULT parse_pres_streams( DataCache *cache, IStorage *stg )
             fmtetc.lindex = header.lindex;
             fmtetc.tymed = tymed_from_cf( clipformat );
 
-            add_cache_entry( cache, &fmtetc, header.advf, stm, pres_stream );
+            add_cache_entry( cache, &fmtetc, header.advf, stream_number );
         }
         IStream_Release( stm );
         stream_number++;
@@ -1771,7 +1707,7 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg )
     const FORMATETC *fmt;
     IStream *stm;
 
-    hr = IStorage_OpenStream( stg, CONTENTS, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
+    hr = open_pres_stream( stg, STREAM_NUMBER_CONTENTS, &stm );
     if (FAILED( hr )) return hr;
 
     hr = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
@@ -1786,7 +1722,7 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg )
         goto done;
     }
 
-    hr = add_cache_entry( This, fmt, 0, stm, contents_stream );
+    hr = add_cache_entry( This, fmt, 0, STREAM_NUMBER_CONTENTS );
 
 done:
     IStream_Release( stm );
@@ -1852,17 +1788,17 @@ static HRESULT WINAPI DataCache_Save(IPersistStorage* iface, IStorage *stg, BOOL
     DataCache *This = impl_from_IPersistStorage(iface);
     DataCacheEntry *cache_entry;
     HRESULT hr = S_OK;
-    unsigned short stream_number = 0;
+    int stream_number = 0;
 
     TRACE("(%p, %p, %d)\n", iface, stg, same_as_load);
 
     /* assign stream numbers to the cache entries */
     LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
     {
-        if (cache_entry->stream_number != stream_number)
+        if (cache_entry->save_stream_num != stream_number)
         {
             cache_entry->dirty = TRUE; /* needs to be written out again */
-            cache_entry->stream_number = stream_number;
+            cache_entry->save_stream_num = stream_number;
         }
         stream_number++;
     }
@@ -1916,7 +1852,6 @@ static HRESULT WINAPI DataCache_HandsOffStorage(
             IPersistStorage* iface)
 {
   DataCache *this = impl_from_IPersistStorage(iface);
-  DataCacheEntry *cache_entry;
 
   TRACE("(%p)\n", iface);
 
@@ -1926,9 +1861,6 @@ static HRESULT WINAPI DataCache_HandsOffStorage(
     this->presentationStorage = NULL;
   }
 
-  LIST_FOR_EACH_ENTRY(cache_entry, &this->cache_list, DataCacheEntry, entry)
-    DataCacheEntry_HandsOffStorage(cache_entry);
-
   return S_OK;
 }
 
@@ -2018,9 +1950,9 @@ static HRESULT WINAPI DataCache_Draw(
       continue;
 
     /* if the data hasn't been loaded yet, do it now */
-    if ((cache_entry->stgmedium.tymed == TYMED_NULL) && cache_entry->stream)
+    if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
     {
-      hres = DataCacheEntry_LoadData(cache_entry);
+      hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
       if (FAILED(hres))
         continue;
     }
@@ -2278,9 +2210,9 @@ static HRESULT WINAPI DataCache_GetExtent(
       continue;
 
     /* if the data hasn't been loaded yet, do it now */
-    if ((cache_entry->stgmedium.tymed == TYMED_NULL) && cache_entry->stream)
+    if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
     {
-      hres = DataCacheEntry_LoadData(cache_entry);
+      hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
       if (FAILED(hres))
         continue;
     }
-- 
2.12.0




More information about the wine-devel mailing list