From 7863247ec682522cde5677e4eaf6bd04d626a3a4 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 20 Mar 2016 21:07:40 +0300 Subject: [PATCH] ole32: Make CoGetInstanceFromFile() propagate failure codes to returned MULTI_QI data (Coverity). Signed-off-by: Nikolay Sivov Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/ole32/compobj.c | 34 +++-- dlls/ole32/tests/compobj.c | 252 ++++++++++++++++++++++++++++++++++++- 2 files changed, 273 insertions(+), 13 deletions(-) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 857f985a003..ced6f7d84aa 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3203,14 +3203,14 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance( return hres; } -static void init_multi_qi(DWORD count, MULTI_QI *mqi) +static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr) { ULONG i; for (i = 0; i < count; i++) { mqi[i].pItf = NULL; - mqi[i].hr = E_NOINTERFACE; + mqi[i].hr = hr; } } @@ -3266,7 +3266,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx( if (pServerInfo) FIXME("() non-NULL pServerInfo not supported!\n"); - init_multi_qi(cmq, pResults); + init_multi_qi(cmq, pResults, E_NOINTERFACE); hres = CoGetTreatAsClass(rclsid, &clsid); if(FAILED(hres)) @@ -3350,7 +3350,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile( if (server_info) FIXME("() non-NULL server_info not supported\n"); - init_multi_qi(count, results); + init_multi_qi(count, results, E_NOINTERFACE); /* optionally get CLSID from a file */ if (!rclsid) @@ -3372,20 +3372,30 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile( (void**)&unk); if (hr != S_OK) - return hr; + { + init_multi_qi(count, results, hr); + return hr; + } /* init from file */ hr = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&pf); if (FAILED(hr)) - ERR("failed to get IPersistFile\n"); - - if (pf) { - IPersistFile_Load(pf, filename, grfmode); - IPersistFile_Release(pf); + init_multi_qi(count, results, hr); + IUnknown_Release(unk); + return hr; } - return return_multi_qi(unk, count, results, FALSE); + hr = IPersistFile_Load(pf, filename, grfmode); + IPersistFile_Release(pf); + if (SUCCEEDED(hr)) + return return_multi_qi(unk, count, results, FALSE); + else + { + init_multi_qi(count, results, hr); + IUnknown_Release(unk); + return hr; + } } /*********************************************************************** @@ -3412,7 +3422,7 @@ HRESULT WINAPI CoGetInstanceFromIStorage( if (server_info) FIXME("() non-NULL server_info not supported\n"); - init_multi_qi(count, results); + init_multi_qi(count, results, E_NOINTERFACE); /* optionally get CLSID from a file */ if (!rclsid) diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 43556d9aa9e..215d68fade6 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -95,6 +95,7 @@ static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0 static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } }; DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); +DEFINE_GUID(CLSID_testclsid, 0xacd014c7,0x9535,0x4fac,0x8b,0x53,0xa4,0x8c,0xa7,0xf4,0xd7,0x26); static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0}; static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0}; @@ -2966,7 +2967,6 @@ static void test_CoGetApartmentType(void) CoUninitialize(); } - static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown)) @@ -3261,6 +3261,255 @@ todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); } +static HRESULT g_persistfile_qi_ret; +static HRESULT g_persistfile_load_ret; +static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *obj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + if (IsEqualIID(riid, &IID_IPersistFile)) { + if (SUCCEEDED(g_persistfile_qi_ret)) { + *obj = iface; + IUnknown_AddRef(iface); + } + else + *obj = NULL; + return g_persistfile_qi_ret; + } + + ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI testinstance_AddRef(IPersistFile *iface) +{ + return 2; +} + +static ULONG WINAPI testinstance_Release(IPersistFile *iface) +{ + return 1; +} + +static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode) +{ + return g_persistfile_load_ret; +} + +static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IPersistFileVtbl testpersistfilevtbl = { + testinstance_QI, + testinstance_AddRef, + testinstance_Release, + testinstance_GetClassID, + testinstance_IsDirty, + testinstance_Load, + testinstance_Save, + testinstance_SaveCompleted, + testinstance_GetCurFile +}; + +static IPersistFile testpersistfile = { &testpersistfilevtbl }; + +static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { + *obj = iface; + IClassFactory_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, + REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *obj = &testpersistfile; + return S_OK; + } + + ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid)); + *obj = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IClassFactoryVtbl getinstance_cf_vtbl = { + getinstance_cf_QI, + getinstance_cf_AddRef, + getinstance_cf_Release, + getinstance_cf_CreateInstance, + getinstance_cf_LockServer +}; + +static IClassFactory getinstance_cf = { &getinstance_cf_vtbl }; + +static void test_CoGetInstanceFromFile(void) +{ + static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0}; + CLSID *clsid = (CLSID*)&CLSID_testclsid; + MULTI_QI mqi[2]; + DWORD cookie; + HRESULT hr; + + hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* CLSID is not specified, file does not exist */ + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = E_NOTIMPL; + hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); +todo_wine + ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr); + ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr); + + /* class is not available */ + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = E_NOTIMPL; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); + ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr); + ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr); + + hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, + &cookie); + ok(hr == S_OK, "got 0x%08x\n", hr); + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = (void*)0xdeadbeef; + mqi[0].hr = S_OK; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); +todo_wine { + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf); +} + ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = (void*)0xdeadbeef; + mqi[0].hr = E_NOTIMPL; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); +todo_wine { + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr); +} + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = E_NOTIMPL; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = S_OK; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = S_OK; + g_persistfile_qi_ret = S_FALSE; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr); + g_persistfile_qi_ret = S_OK; + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = S_OK; + mqi[1].pIID = &IID_IUnknown; + mqi[1].pItf = NULL; + mqi[1].hr = S_OK; + g_persistfile_qi_ret = 0x8000efef; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi); + ok(hr == 0x8000efef, "got 0x%08x\n", hr); + ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr); + ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf); + ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr); + g_persistfile_qi_ret = S_OK; + + mqi[0].pIID = &IID_IUnknown; + mqi[0].pItf = NULL; + mqi[0].hr = S_OK; + mqi[1].pIID = &IID_IUnknown; + mqi[1].pItf = NULL; + mqi[1].hr = S_OK; + g_persistfile_load_ret = 0x8000fefe; + hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi); + ok(hr == 0x8000fefe, "got 0x%08x\n", hr); + ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf); + ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr); + ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf); + ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr); + g_persistfile_load_ret = S_OK; + + hr = CoRevokeClassObject(cookie); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CoUninitialize(); +} + static void init_funcs(void) { HMODULE hOle32 = GetModuleHandleA("ole32"); @@ -3331,4 +3580,5 @@ START_TEST(compobj) test_IMallocSpy(); test_CoGetCurrentLogicalThreadId(); test_IInitializeSpy(); + test_CoGetInstanceFromFile(); }