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

Huw Davies huw at codeweavers.com
Wed Aug 29 04:21:42 CDT 2018


On Wed, Aug 29, 2018 at 10:08:16AM +0100, Huw Davies wrote:
> 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.

Just to be clear, you'd do this before the calls to IOleCache2_Cache
and _SetData.

Huw.



More information about the wine-devel mailing list