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@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;
}