Signed-off-by: Sergio Gómez Del Real sdelreal@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,