Signed-off-by: Sergio Gómez Del Real <sdelreal(a)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