Module: wine Branch: master Commit: 35f218c39eb6707f43eb4917539003c7df8250b1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=35f218c39eb6707f43eb491753...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Feb 6 08:44:46 2014 +0400
ole32: Implement CoGetInstanceFromFile().
---
dlls/ole32/compobj.c | 116 +++++++++++++++++++++++++++++++++++++------------ dlls/ole32/ole32.spec | 2 +- 2 files changed, 89 insertions(+), 29 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 3c0c085..4149ecb 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3196,6 +3196,36 @@ HRESULT WINAPI CoCreateInstance( return hres; }
+static void init_multi_qi(DWORD count, MULTI_QI *mqi) +{ + ULONG i; + + for (i = 0; i < count; i++) + { + mqi[i].pItf = NULL; + mqi[i].hr = E_NOINTERFACE; + } +} + +static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi) +{ + ULONG index, fetched = 0; + + for (index = 0; index < count; index++) + { + mqi[index].hr = IUnknown_QueryInterface(unk, mqi[index].pIID, (void**)&mqi[index].pItf); + if (mqi[index].hr == S_OK) + fetched++; + } + + IUnknown_Release(unk); + + if (fetched == 0) + return E_NOINTERFACE; + + return fetched == count ? S_OK : CO_S_NOTALLINTERFACES; +} + /*********************************************************************** * CoCreateInstanceEx [OLE32.@] */ @@ -3209,8 +3239,6 @@ HRESULT WINAPI CoCreateInstanceEx( { IUnknown* pUnk = NULL; HRESULT hr; - ULONG index; - ULONG successCount = 0;
/* * Sanity check @@ -3221,14 +3249,7 @@ HRESULT WINAPI CoCreateInstanceEx( if (pServerInfo!=NULL) FIXME("() non-NULL pServerInfo not supported!\n");
- /* - * Initialize all the "out" parameters. - */ - for (index = 0; index < cmq; index++) - { - pResults[index].pItf = NULL; - pResults[index].hr = E_NOINTERFACE; - } + init_multi_qi(cmq, pResults);
/* * Get the object and get its IUnknown pointer. @@ -3242,31 +3263,70 @@ HRESULT WINAPI CoCreateInstanceEx( if (hr != S_OK) return hr;
- /* - * Then, query for all the interfaces requested. - */ - for (index = 0; index < cmq; index++) + return return_multi_qi(pUnk, cmq, pResults); +} + +/*********************************************************************** + * CoGetInstanceFromFile [OLE32.@] + */ +HRESULT WINAPI CoGetInstanceFromFile( + COSERVERINFO *server_info, + CLSID *rclsid, + IUnknown *outer, + DWORD cls_context, + DWORD grfmode, + OLECHAR *filename, + DWORD count, + MULTI_QI *results +) +{ + IPersistFile *pf = NULL; + IUnknown* unk = NULL; + CLSID clsid; + HRESULT hr; + + if (count == 0 || !results) + return E_INVALIDARG; + + if (server_info) + FIXME("() non-NULL server_info not supported\n"); + + init_multi_qi(count, results); + + /* optionaly get CLSID from a file */ + if (!rclsid) { - pResults[index].hr = IUnknown_QueryInterface(pUnk, - pResults[index].pIID, - (VOID**)&(pResults[index].pItf)); + hr = GetClassFile(filename, &clsid); + if (FAILED(hr)) + { + ERR("failed to get CLSID from a file\n"); + return hr; + }
- if (pResults[index].hr == S_OK) - successCount++; + rclsid = &clsid; }
- /* - * Release our temporary unknown pointer. - */ - IUnknown_Release(pUnk); + hr = CoCreateInstance(rclsid, + outer, + cls_context, + &IID_IUnknown, + (void**)&unk);
- if (successCount == 0) - return E_NOINTERFACE; + if (hr != S_OK) + return hr;
- if (successCount!=cmq) - return CO_S_NOTALLINTERFACES; + /* init from file */ + hr = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&pf); + if (FAILED(hr)) + ERR("failed to get IPersistFile\n");
- return S_OK; + if (pf) + { + IPersistFile_Load(pf, filename, grfmode); + IPersistFile_Release(pf); + } + + return return_multi_qi(unk, count, results); }
/*********************************************************************** diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index d71168e..28a84a1 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -29,7 +29,7 @@ @ stdcall CoGetCurrentLogicalThreadId(ptr) @ stdcall CoGetCurrentProcess() @ stdcall CoGetDefaultContext(long ptr ptr) -@ stub CoGetInstanceFromFile #@ stdcall (ptr ptr ptr long wstr long ptr) return 0,ERR_NOTIMPLEMENTED +@ stdcall CoGetInstanceFromFile(ptr ptr ptr long long wstr long ptr) @ stub CoGetInstanceFromIStorage #@ stdcall (ptr ptr ptr long ptr long ptr) return 0,ERR_NOTIMPLEMENTED @ stdcall CoGetInterfaceAndReleaseStream(ptr ptr ptr) @ stdcall CoGetMalloc(long ptr)