[PATCH v4] ole32: Partially implement OleCreateStaticFromData() for OLERENDER_FORMAT.
Jactry Zeng
jzeng at codeweavers.com
Tue Sep 4 07:57:06 CDT 2018
Thanks Huw's advice!
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42710
Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
dlls/ole32/ole2impl.c | 97 +++++++++++++++++++-
dlls/ole32/tests/ole2.c | 191 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 286 insertions(+), 2 deletions(-)
diff --git a/dlls/ole32/ole2impl.c b/dlls/ole32/ole2impl.c
index fa5777beb0..e3820b9ac2 100644
--- a/dlls/ole32/ole2impl.c
+++ b/dlls/ole32/ole2impl.c
@@ -232,9 +232,102 @@ 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;
+ CLSID clsid;
+ IOleObject * ole_object = NULL;
+ IOleCache2 *ole_cache = NULL;
+ IPersistStorage *persist = NULL;
+ DWORD connection;
+ STGMEDIUM stgmedium;
+ LPOLESTR ole_typename;
+
+ 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 = IDataObject_GetData(data, fmt, &stgmedium);
+ if (FAILED(hr)) return hr;
+
+ switch (fmt->cfFormat)
+ {
+ case CF_BITMAP:
+ case CF_DIB:
+ clsid = CLSID_Picture_Dib;
+ break;
+ case CF_ENHMETAFILE:
+ clsid = CLSID_Picture_EnhMetafile;
+ break;
+ case CF_METAFILEPICT:
+ clsid = CLSID_Picture_Metafile;
+ break;
+ default:
+ ReleaseStgMedium(&stgmedium);
+ return DV_E_CLIPFORMAT;
+ }
+ hr = OleCreateDefaultHandler(&clsid, NULL, &IID_IOleObject, (void **)&ole_object);
+ if (FAILED(hr)) goto end;
+
+ if (client_site)
+ {
+ hr = IOleObject_SetClientSite(ole_object, client_site);
+ if (FAILED(hr)) goto end;
+ }
+
+ hr = IOleObject_QueryInterface(ole_object, &IID_IOleCache2, (void **)&ole_cache);
+ if (FAILED(hr)) goto end;
+
+ hr = IOleObject_QueryInterface(ole_object, &IID_IPersistStorage, (void **)&persist);
+ if (FAILED(hr)) goto end;
+
+ hr = WriteClassStg(stg, &clsid);
+ if (FAILED(hr)) goto end;
+
+ hr = IPersistStorage_InitNew(persist, stg);
+ if (FAILED(hr)) goto end;
+
+ hr = IOleCache2_Cache(ole_cache, fmt, ADVF_PRIMEFIRST, &connection);
+ if (FAILED(hr)) goto end;
+
+ hr = IOleCache2_SetData(ole_cache, fmt, &stgmedium, TRUE);
+ if (FAILED(hr)) goto end;
+ stgmedium.tymed = TYMED_NULL;
+
+ hr = IOleObject_GetUserType(ole_object, USERCLASSTYPE_FULL, &ole_typename);
+ if(FAILED(hr))
+ ole_typename = NULL;
+ hr = WriteFmtUserTypeStg(stg, fmt->cfFormat, ole_typename);
+ CoTaskMemFree(ole_typename);
+ if (FAILED(hr)) goto end;
+
+ hr = IPersistStorage_Save(persist, stg, TRUE);
+ if (FAILED(hr)) goto end;
+
+ hr = IPersistStorage_SaveCompleted(persist, NULL);
+ if (FAILED(hr)) goto end;
+
+ hr = IOleObject_QueryInterface(ole_object, iid, obj);
+
+end:
+ if (stgmedium.tymed == TYMED_NULL)
+ ReleaseStgMedium(&stgmedium);
+ if (persist)
+ IPersistStorage_Release(persist);
+ if (ole_cache)
+ IOleCache2_Release(ole_cache);
+ if (ole_object)
+ IOleObject_Release(ole_object);
+ return hr;
}
/******************************************************************************
diff --git a/dlls/ole32/tests/ole2.c b/dlls/ole32/tests/ole2.c
index 48c9e0cbab..9b82e49b36 100644
--- a/dlls/ole32/tests/ole2.c
+++ b/dlls/ole32/tests/ole2.c
@@ -257,6 +257,21 @@ static void create_mfpict(STGMEDIUM *med)
med->pUnkForRelease = NULL;
}
+static void create_text(STGMEDIUM *med)
+{
+ HGLOBAL handle;
+ char *p;
+
+ handle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
+ p = GlobalLock(handle);
+ strcpy(p, "test");
+ GlobalUnlock(handle);
+
+ med->tymed = TYMED_HGLOBAL;
+ U(med)->hGlobal = handle;
+ med->pUnkForRelease = NULL;
+}
+
static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv)
{
CHECK_EXPECTED_METHOD("OleObject_QueryInterface");
@@ -1490,6 +1505,12 @@ static HRESULT WINAPI DataObject_GetData( IDataObject *iface, FORMATETC *fmt_in,
case CF_BITMAP:
create_bitmap( med );
return S_OK;
+ case CF_ENHMETAFILE:
+ create_emf( med );
+ return S_OK;
+ case CF_TEXT:
+ create_text( med );
+ return S_OK;
default:
trace( "unhandled fmt %d\n", fmt->cfFormat );
}
@@ -4593,6 +4614,175 @@ todo_wine_if(!(test_data[i].in == &stg_def_0 || test_data[i].in == &stg_def_4 ||
}
}
+static void test_OleCreateStaticFromData(void)
+{
+ HRESULT hr;
+ IOleObject *ole_obj = NULL;
+ IStorage *storage;
+ ILockBytes *ilb;
+ IPersist *presist;
+ CLSID clsid;
+ STATSTG statstg;
+ int enumerated_streams, matched_streams;
+ STGMEDIUM stgmed;
+ static FORMATETC dib_fmt[] =
+ {
+ { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
+ { 0 }
+ };
+ static FORMATETC emf_fmt[] =
+ {
+ { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF },
+ { 0 }
+ };
+ static FORMATETC text_fmt[] =
+ {
+ { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
+ { 0 }
+ };
+ static const struct expected_method methods_create_from_dib[] =
+ {
+ { "DataObject_EnumFormatEtc", TEST_TODO },
+ { "DataObject_GetDataHere", 0 },
+ { "DataObject_QueryGetData", 0, { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_ISTORAGE } },
+ { NULL }
+ };
+ static const struct expected_method methods_createstatic_from_dib[] =
+ {
+ { "DataObject_GetData", 0, { CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
+ { NULL }
+ };
+ static const struct expected_method methods_createstatic_from_emf[] =
+ {
+ { "DataObject_GetData", 0, { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
+ { NULL }
+ };
+ static const struct expected_method methods_createstatic_from_text[] =
+ {
+ { "DataObject_GetData", 0, { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
+ { NULL }
+ };
+ static struct storage_def stg_def_dib =
+ {
+ &CLSID_Picture_Dib, 3,
+ {{ "\1Ole", -1, 0, 0, NULL, 0 },
+ { "\1CompObj", -1, 0, 0, NULL, 0 },
+ { "CONTENTS", -1, 0, 0, NULL, 0 }}
+ };
+ static struct storage_def stg_def_emf =
+ {
+ &CLSID_Picture_EnhMetafile, 3,
+ {{ "\1Ole", -1, 0, 0, NULL, 0 },
+ { "\1CompObj", -1, 0, 0, NULL, 0 },
+ { "CONTENTS", -1, 0, 0, NULL, 0 }}
+ };
+
+
+ hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
+ ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
+ hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
+ 0, &storage);
+ ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
+ ILockBytes_Release(ilb);
+
+ hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
+ dib_fmt, NULL, NULL, (void **)&ole_obj);
+ ok(hr == E_INVALIDARG, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
+
+ hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
+ dib_fmt, NULL, storage, NULL);
+ ok(hr == E_INVALIDARG, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
+
+ /* CF_DIB */
+ g_dataobject_fmts = dib_fmt;
+ expected_method_list = methods_createstatic_from_dib;
+ hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
+ dib_fmt, NULL, storage, (void **)&ole_obj);
+ ok(hr == S_OK, "OleCreateStaticFromData failed: 0x%08x.\n", hr);
+ hr = IOleObject_QueryInterface(ole_obj, &IID_IPersist, (void **)&presist);
+ ok(hr == S_OK, "IOleObject_QueryInterface failed: 0x%08x.\n", hr);
+ hr = IPersist_GetClassID(presist, &clsid);
+ ok(hr == S_OK, "IPersist_GetClassID failed: 0x%08x.\n", hr);
+ ok(IsEqualCLSID(&clsid, &CLSID_Picture_Dib), "Got wrong clsid: %s, expected: %s.\n",
+ wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&CLSID_Picture_Dib));
+ hr = IStorage_Stat(storage, &statstg, STATFLAG_NONAME);
+ ok_ole_success(hr, "IStorage_Stat");
+ ok(IsEqualCLSID(&CLSID_Picture_Dib, &statstg.clsid), "Wrong CLSID in storage.\n");
+ enumerated_streams = matched_streams = -1;
+ get_stgmedium(CF_DIB, &stgmed);
+ get_stgdef(&stg_def_dib, CF_DIB, &stgmed, 2);
+ check_storage_contents(storage, &stg_def_dib, &enumerated_streams, &matched_streams);
+ ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
+ enumerated_streams, matched_streams);
+ ok(enumerated_streams == stg_def_dib.stream_count, "created %d != def streams %d\n",
+ enumerated_streams, stg_def_dib.stream_count);
+ ReleaseStgMedium(&stgmed);
+ IPersist_Release(presist);
+ IStorage_Release(storage);
+ IOleObject_Release(ole_obj);
+
+ /* CF_ENHMETAFILE */
+ hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
+ ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
+ hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
+ 0, &storage);
+ ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
+ ILockBytes_Release(ilb);
+ g_dataobject_fmts = emf_fmt;
+ expected_method_list = methods_createstatic_from_emf;
+ hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
+ emf_fmt, NULL, storage, (void **)&ole_obj);
+ ok(hr == S_OK, "OleCreateStaticFromData failed: 0x%08x.\n", hr);
+ hr = IOleObject_QueryInterface(ole_obj, &IID_IPersist, (void **)&presist);
+ ok(hr == S_OK, "IOleObject_QueryInterface failed: 0x%08x.\n", hr);
+ hr = IPersist_GetClassID(presist, &clsid);
+ ok(hr == S_OK, "IPersist_GetClassID failed: 0x%08x.\n", hr);
+ ok(IsEqualCLSID(&clsid, &CLSID_Picture_EnhMetafile), "Got wrong clsid: %s, expected: %s.\n",
+ wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&CLSID_Picture_EnhMetafile));
+ hr = IStorage_Stat(storage, &statstg, STATFLAG_NONAME);
+ ok_ole_success(hr, "IStorage_Stat");
+ ok(IsEqualCLSID(&CLSID_Picture_EnhMetafile, &statstg.clsid), "Wrong CLSID in storage.\n");
+ enumerated_streams = matched_streams = -1;
+ get_stgmedium(CF_ENHMETAFILE, &stgmed);
+ get_stgdef(&stg_def_emf, CF_ENHMETAFILE, &stgmed, 2);
+ check_storage_contents(storage, &stg_def_emf, &enumerated_streams, &matched_streams);
+ ok(enumerated_streams == matched_streams, "enumerated %d != matched %d\n",
+ enumerated_streams, matched_streams);
+ ok(enumerated_streams == stg_def_emf.stream_count, "created %d != def streams %d\n",
+ enumerated_streams, stg_def_emf.stream_count);
+ ReleaseStgMedium(&stgmed);
+ IPersist_Release(presist);
+ IStorage_Release(storage);
+ IOleObject_Release(ole_obj);
+
+ /* CF_TEXT */
+ hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
+ ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
+ hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
+ 0, &storage);
+ ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
+ ILockBytes_Release(ilb);
+ g_dataobject_fmts = text_fmt;
+ expected_method_list = methods_createstatic_from_text;
+ hr = OleCreateStaticFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT,
+ text_fmt, NULL, storage, (void **)&ole_obj);
+ ok(hr == DV_E_CLIPFORMAT, "OleCreateStaticFromData should fail: 0x%08x.\n", hr);
+ IStorage_Release(storage);
+
+ hr = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
+ ok(hr == S_OK, "CreateILockBytesOnHGlobal failed: 0x%08x.\n", hr);
+ hr = StgCreateDocfileOnILockBytes(ilb, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
+ 0, &storage);
+ ok(hr == S_OK, "StgCreateDocfileOnILockBytes failed: 0x%08x.\n", hr);
+ ILockBytes_Release(ilb);
+ g_dataobject_fmts = dib_fmt;
+ expected_method_list = methods_create_from_dib;
+ hr = OleCreateFromData(&DataObject, &IID_IOleObject, OLERENDER_FORMAT, dib_fmt, NULL,
+ storage, (void **)&ole_obj);
+ todo_wine ok(hr == DV_E_FORMATETC, "OleCreateFromData should failed: 0x%08x.\n", hr);
+ IStorage_Release(storage);
+}
+
START_TEST(ole2)
{
DWORD dwRegister;
@@ -4643,6 +4833,7 @@ START_TEST(ole2)
test_data_cache_save();
test_data_cache_save_data();
test_data_cache_contents();
+ test_OleCreateStaticFromData();
CoUninitialize();
}
--
2.18.0
More information about the wine-devel
mailing list