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

Huw Davies huw at codeweavers.com
Thu Apr 5 13:47:26 CDT 2018


On 5 Apr 2018, at 14:05, Sergio Gómez Del Real <sdelreal at codeweavers.com> wrote:
> Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
> ---
> dlls/ole32/datacache.c | 184 ++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 121 insertions(+), 63 deletions(-)
> 
> diff --git a/dlls/ole32/datacache.c b/dlls/ole32/datacache.c
> index 325a98b33b..3d97473c10 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)

This doesn’t need to be moved anymore right?

> +{
> +    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,61 @@ 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 );
> +            ReleaseStgMedium( &cache_entry->stgmedium );
> +        }
> +        if (SUCCEEDED( hr ))
> +            cache_entry->stgmedium = stgmed;
> +    }
> +    else
> +    {
> +        STATSTG stat;
> +        BYTE *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, data + (read - size_bits) );
> +            cache_entry->stgmedium.tymed = TYMED_ENHMF;
> +            cache_entry->stgmedium.pUnkForRelease = NULL;
> +
> +            HeapFree( GetProcessHeap(), 0, data );
> +        }
> +    }
> +
> +    return hr;
> }
> 
> /************************************************************************
> @@ -736,6 +853,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 +1151,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 +1200,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