[PATCH v3] ole32: Partially implement OleCreateStaticFromData() for OLERENDER_FORMAT.

Huw Davies huw at codeweavers.com
Wed Aug 29 04:08:16 CDT 2018


On Wed, Aug 29, 2018 at 04:08:57PM +0800, Jactry Zeng wrote:
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42710
> Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
> ---
>  dlls/ole32/ole2impl.c   | 51 ++++++++++++++++++++++++++++++++++--
>  dlls/ole32/tests/ole2.c | 57 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 106 insertions(+), 2 deletions(-)
> 
> diff --git a/dlls/ole32/ole2impl.c b/dlls/ole32/ole2impl.c
> index fa5777beb0..73d8210101 100644
> --- a/dlls/ole32/ole2impl.c
> +++ b/dlls/ole32/ole2impl.c
> @@ -232,9 +232,56 @@ HRESULT WINAPI OleCreateStaticFromData(IDataObject *data, REFIID iid,
>                                         IOleClientSite *client_site, IStorage *stg,
>                                         void **obj)
>  {
> -    FIXME("%p,%s,%08x,%p,%p,%p,%p: semi-stub\n",
> +    HRESULT hr;
> +    IOleCache2 *ole_cache = NULL;
> +    IPersistStorage *persist = NULL;
> +    DWORD connection;
> +    STGMEDIUM stgmedium;
> +
> +    TRACE("(%p, %s, 0x%08x, %p, %p, %p, %p)\n",
>            data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj);
> -    return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
> +
> +    if (!obj || !stg)
> +        return E_INVALIDARG;
> +
> +    if (renderopt != OLERENDER_FORMAT)
> +    {
> +        FIXME("semi-stub\n");
> +        return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
> +    }
> +
> +    if (!fmt)
> +        return E_INVALIDARG;
> +
> +    hr = OleCreateDefaultHandler(&CLSID_NULL, NULL, iid, (void **)obj);

You should call this with the correct CLSID.  A switch on fmt->cFormat with
CF_DIB/CF_BITMAP -> CLSID_PictureDib and the two metafile formats going
to their respective CLSID_Picture* classes should do it.

Also, retrieve the IID_IOleObject interface directly and then QI on iid
near the end of the function.

You'll need to also call IOleObject_SetClientSite() if client_site is non-NULL.

> +    if (FAILED(hr)) goto end;
> +
> +    hr = IUnknown_QueryInterface((IUnknown *)*obj, &IID_IOleCache2, (void **)&ole_cache);

This is now IOleObject_QI

> +    if (FAILED(hr)) goto end;
> +
> +    hr = IOleCache2_Cache(ole_cache, fmt, ADVF_PRIMEFIRST, &connection);
> +    if (FAILED(hr)) goto end;
> +
> +    hr = IDataObject_GetData(data, fmt, &stgmedium);
> +    if (FAILED(hr)) goto end;

I would do the GetData call before creating the default handler, that
way you can bail without the cost of creating the default handler
if GetData fails.  You need to ReleaseStgMedium() if there's a
failure before a successful call to IOleCache2_SetData.

> +
> +    hr = IOleCache2_SetData(ole_cache, fmt, &stgmedium, TRUE);
> +    if (FAILED(hr)) goto end;
> +
> +    hr = IOleCache2_QueryInterface(ole_cache, &IID_IPersistStorage, (void **)&persist);
> +    if (FAILED(hr)) goto end;
> +
> +    hr = IPersistStorage_Save(persist, stg, TRUE);
> +    if (FAILED(hr)) goto end;

Does the storage actually get saved at this point?
I would imagine you'd do a WriteClassStg() and a IPersistStorage_InitNew()
here, but some tests investigating the state of the storage after this
function returns would be good.

> +
> +    hr = IPersistStorage_SaveCompleted(persist, NULL);
> +
> +end:
> +    if (persist)
> +        IPersistStorage_Release(persist);
> +    if (ole_cache)
> +        IOleCache2_Release(ole_cache);
> +    return hr;
>  }
>  



More information about the wine-devel mailing list