[PATCH v2 1/5] ole32: Add support for loading enhmetafiles from presentation and contents streams to data cache.

Sergio Gómez Del Real sdelreal at codeweavers.com
Fri Mar 30 12:11:33 CDT 2018


Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
 dlls/ole32/datacache.c | 185 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 122 insertions(+), 63 deletions(-)

diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
index 325a98b33b..799e14a867 100644
--- a/dlls/ole32/datacache.c
+++ b/dlls/ole32/datacache.c
@@ -459,6 +459,45 @@ static void DataCache_FireOnViewChange(
   }
 }
 
+/* helper for copying STGMEDIUM of type bitmap, MF, EMF or HGLOBAL.
+* does no checking of whether src_stgm has a supported tymed, so this should be
+* done in the caller */
+static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm,
+                               const STGMEDIUM *src_stgm)
+{
+    if (src_stgm->tymed == TYMED_MFPICT)
+    {
+        const METAFILEPICT *src_mfpict = GlobalLock(src_stgm->u.hMetaFilePict);
+        METAFILEPICT *dest_mfpict;
+
+        if (!src_mfpict)
+            return DV_E_STGMEDIUM;
+        dest_stgm->u.hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
+        dest_mfpict = GlobalLock(dest_stgm->u.hMetaFilePict);
+        if (!dest_mfpict)
+        {
+            GlobalUnlock(src_stgm->u.hMetaFilePict);
+            return E_OUTOFMEMORY;
+        }
+        *dest_mfpict = *src_mfpict;
+        dest_mfpict->hMF = CopyMetaFileW(src_mfpict->hMF, NULL);
+        GlobalUnlock(src_stgm->u.hMetaFilePict);
+        GlobalUnlock(dest_stgm->u.hMetaFilePict);
+    }
+    else if (src_stgm->tymed != TYMED_NULL)
+    {
+        dest_stgm->u.hGlobal = OleDuplicateData(src_stgm->u.hGlobal, cf,
+                                                GMEM_MOVEABLE);
+        if (!dest_stgm->u.hGlobal)
+            return E_OUTOFMEMORY;
+    }
+    dest_stgm->tymed = src_stgm->tymed;
+    dest_stgm->pUnkForRelease = src_stgm->pUnkForRelease;
+    if (dest_stgm->pUnkForRelease)
+        IUnknown_AddRef(dest_stgm->pUnkForRelease);
+    return S_OK;
+}
+
 static HRESULT read_clipformat(IStream *stream, CLIPFORMAT *clipformat)
 {
     DWORD length;
@@ -547,6 +586,30 @@ static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm
     return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
 }
 
+static HRESULT synthesize_emf( HMETAFILEPICT data, STGMEDIUM *med )
+{
+    METAFILEPICT *pict;
+    HRESULT hr = E_FAIL;
+    UINT size;
+    void *bits;
+
+    if (!(pict = GlobalLock( data ))) return hr;
+
+    size = GetMetaFileBitsEx( pict->hMF, 0, NULL );
+    if ((bits = HeapAlloc( GetProcessHeap(), 0, size )))
+    {
+        GetMetaFileBitsEx( pict->hMF, size, bits );
+        med->u.hEnhMetaFile = SetWinMetaFileBits( size, bits, NULL, pict );
+        HeapFree( GetProcessHeap(), 0, bits );
+        med->tymed = TYMED_ENHMF;
+        med->pUnkForRelease = NULL;
+        hr = S_OK;
+    }
+
+    GlobalUnlock( data );
+    return hr;
+}
+
 static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
 {
     HRESULT hr;
@@ -701,7 +764,62 @@ fail:
     GlobalUnlock( hglobal );
     GlobalFree( hglobal );
     return E_FAIL;
+}
 
+static HRESULT load_emf( DataCacheEntry *cache_entry, IStream *stm )
+{
+    HRESULT hr;
+
+    if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
+    {
+        STGMEDIUM stgmed;
+
+        hr = load_mf_pict( cache_entry, stm );
+        if (SUCCEEDED( hr ))
+            hr = synthesize_emf( cache_entry->stgmedium.u.hMetaFilePict, &stgmed );
+        if (SUCCEEDED( hr ))
+        {
+            ReleaseStgMedium( &cache_entry->stgmedium );
+            hr = copy_stg_medium( CF_ENHMETAFILE, &cache_entry->stgmedium, &stgmed );
+            ReleaseStgMedium( &stgmed );
+        }
+    }
+    else
+    {
+        STATSTG stat;
+        void *data;
+        DWORD size_bits;
+        ULONG read;
+
+        hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
+
+        if (SUCCEEDED( hr ))
+        {
+            data = HeapAlloc( GetProcessHeap(), 0, stat.cbSize.u.LowPart );
+            if (!data) return E_OUTOFMEMORY;
+
+            hr = IStream_Read( stm, data, stat.cbSize.u.LowPart, &read );
+            if (hr != S_OK || read != stat.cbSize.u.LowPart)
+            {
+                HeapFree( GetProcessHeap(), 0, data );
+                return E_FAIL;
+            }
+
+            size_bits = read - sizeof(DWORD) - sizeof(ENHMETAHEADER);
+            if (size_bits <= 0)
+            {
+                HeapFree( GetProcessHeap(), 0, data );
+                return E_FAIL;
+            }
+            cache_entry->stgmedium.u.hEnhMetaFile = SetEnhMetaFileBits( size_bits, (BYTE *)data + (read - size_bits) );
+            cache_entry->stgmedium.tymed = TYMED_ENHMF;
+            cache_entry->stgmedium.pUnkForRelease = NULL;
+
+            HeapFree( GetProcessHeap(), 0, data );
+        }
+    }
+
+    return hr;
 }
 
 /************************************************************************
@@ -736,6 +854,10 @@ static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry, IStorage *st
         hr = load_dib( cache_entry, stm );
         break;
 
+    case CF_ENHMETAFILE:
+        hr = load_emf( cache_entry, stm );
+        break;
+
     default:
         FIXME( "Unimplemented clip format %x\n", cache_entry->fmtetc.cfFormat );
         hr = E_NOTIMPL;
@@ -1030,45 +1152,6 @@ static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storag
     return hr;
 }
 
-/* helper for copying STGMEDIUM of type bitmap, MF, EMF or HGLOBAL.
-* does no checking of whether src_stgm has a supported tymed, so this should be
-* done in the caller */
-static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm,
-                               const STGMEDIUM *src_stgm)
-{
-    if (src_stgm->tymed == TYMED_MFPICT)
-    {
-        const METAFILEPICT *src_mfpict = GlobalLock(src_stgm->u.hMetaFilePict);
-        METAFILEPICT *dest_mfpict;
-
-        if (!src_mfpict)
-            return DV_E_STGMEDIUM;
-        dest_stgm->u.hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
-        dest_mfpict = GlobalLock(dest_stgm->u.hMetaFilePict);
-        if (!dest_mfpict)
-        {
-            GlobalUnlock(src_stgm->u.hMetaFilePict);
-            return E_OUTOFMEMORY;
-        }
-        *dest_mfpict = *src_mfpict;
-        dest_mfpict->hMF = CopyMetaFileW(src_mfpict->hMF, NULL);
-        GlobalUnlock(src_stgm->u.hMetaFilePict);
-        GlobalUnlock(dest_stgm->u.hMetaFilePict);
-    }
-    else if (src_stgm->tymed != TYMED_NULL)
-    {
-        dest_stgm->u.hGlobal = OleDuplicateData(src_stgm->u.hGlobal, cf,
-                                                GMEM_MOVEABLE);
-        if (!dest_stgm->u.hGlobal)
-            return E_OUTOFMEMORY;
-    }
-    dest_stgm->tymed = src_stgm->tymed;
-    dest_stgm->pUnkForRelease = src_stgm->pUnkForRelease;
-    if (dest_stgm->pUnkForRelease)
-        IUnknown_AddRef(dest_stgm->pUnkForRelease);
-    return S_OK;
-}
-
 static HRESULT synthesize_dib( HBITMAP bm, STGMEDIUM *med )
 {
     HDC hdc = GetDC( 0 );
@@ -1118,30 +1201,6 @@ static HRESULT synthesize_bitmap( HGLOBAL dib, STGMEDIUM *med )
     return hr;
 }
 
-static HRESULT synthesize_emf( HMETAFILEPICT data, STGMEDIUM *med )
-{
-    METAFILEPICT *pict;
-    HRESULT hr = E_FAIL;
-    UINT size;
-    void *bits;
-
-    if (!(pict = GlobalLock( data ))) return hr;
-
-    size = GetMetaFileBitsEx( pict->hMF, 0, NULL );
-    if ((bits = HeapAlloc( GetProcessHeap(), 0, size )))
-    {
-        GetMetaFileBitsEx( pict->hMF, size, bits );
-        med->u.hEnhMetaFile = SetWinMetaFileBits( size, bits, NULL, pict );
-        HeapFree( GetProcessHeap(), 0, bits );
-        med->tymed = TYMED_ENHMF;
-        med->pUnkForRelease = NULL;
-        hr = S_OK;
-    }
-
-    GlobalUnlock( data );
-    return hr;
-}
-
 static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
                                       const FORMATETC *formatetc,
                                       STGMEDIUM *stgmedium,
-- 
2.14.1




More information about the wine-devel mailing list