From 722c28cb5de076a4894a0a23500b160531a8b744 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 25 Jan 2017 00:50:36 +0300 Subject: [PATCH] wshom: Added IProvideClassInfo support for implemented interfaces. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/wshom.ocx/shell.c | 93 ++++++++++++++++++++++++---------- dlls/wshom.ocx/tests/wshom.c | 31 +++++++++++- dlls/wshom.ocx/tests/wshom.idl | 8 +++ dlls/wshom.ocx/wshom.idl | 8 +++ dlls/wshom.ocx/wshom_main.c | 72 ++++++++++++++++++++++++-- dlls/wshom.ocx/wshom_private.h | 9 ++++ 6 files changed, 189 insertions(+), 32 deletions(-) diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index f9ec9dcf2d1..f8c2a4bb770 100644 --- a/dlls/wshom.ocx/shell.c +++ b/dlls/wshom.ocx/shell.c @@ -28,16 +28,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(wshom); -static IWshShell3 WshShell3; +typedef struct +{ + struct provideclassinfo classinfo; + IWshShell3 IWshShell3_iface; +} WshShellImpl; +static WshShellImpl WshShell3; typedef struct { + struct provideclassinfo classinfo; IWshCollection IWshCollection_iface; LONG ref; } WshCollection; typedef struct { + struct provideclassinfo classinfo; IWshShortcut IWshShortcut_iface; LONG ref; @@ -47,16 +54,18 @@ typedef struct typedef struct { + struct provideclassinfo classinfo; IWshEnvironment IWshEnvironment_iface; LONG ref; } WshEnvironment; typedef struct { + struct provideclassinfo classinfo; IWshExec IWshExec_iface; LONG ref; PROCESS_INFORMATION info; -} WshExec; +} WshExecImpl; static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface ) { @@ -73,14 +82,14 @@ static inline WshEnvironment *impl_from_IWshEnvironment( IWshEnvironment *iface return CONTAINING_RECORD(iface, WshEnvironment, IWshEnvironment_iface); } -static inline WshExec *impl_from_IWshExec( IWshExec *iface ) +static inline WshExecImpl *impl_from_IWshExec( IWshExec *iface ) { - return CONTAINING_RECORD(iface, WshExec, IWshExec_iface); + return CONTAINING_RECORD(iface, WshExecImpl, IWshExec_iface); } static HRESULT WINAPI WshExec_QueryInterface(IWshExec *iface, REFIID riid, void **obj) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj); @@ -89,19 +98,24 @@ static HRESULT WINAPI WshExec_QueryInterface(IWshExec *iface, REFIID riid, void IsEqualGUID(riid, &IID_IUnknown)) { *obj = iface; - }else { + } + else if (IsEqualIID(riid, &IID_IProvideClassInfo)) + { + *obj = &This->classinfo.IProvideClassInfo_iface; + } + else { FIXME("Unknown iface %s\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } - IWshExec_AddRef(iface); + IUnknown_AddRef((IUnknown *)*obj); return S_OK; } static ULONG WINAPI WshExec_AddRef(IWshExec *iface) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref = %d\n", This, ref); return ref; @@ -109,7 +123,7 @@ static ULONG WINAPI WshExec_AddRef(IWshExec *iface) static ULONG WINAPI WshExec_Release(IWshExec *iface) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref = %d\n", This, ref); @@ -124,7 +138,7 @@ static ULONG WINAPI WshExec_Release(IWshExec *iface) static HRESULT WINAPI WshExec_GetTypeInfoCount(IWshExec *iface, UINT *pctinfo) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); TRACE("(%p)->(%p)\n", This, pctinfo); *pctinfo = 1; return S_OK; @@ -132,7 +146,7 @@ static HRESULT WINAPI WshExec_GetTypeInfoCount(IWshExec *iface, UINT *pctinfo) static HRESULT WINAPI WshExec_GetTypeInfo(IWshExec *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); return get_typeinfo(IWshExec_tid, ppTInfo); } @@ -140,7 +154,7 @@ static HRESULT WINAPI WshExec_GetTypeInfo(IWshExec *iface, UINT iTInfo, LCID lci static HRESULT WINAPI WshExec_GetIDsOfNames(IWshExec *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); ITypeInfo *typeinfo; HRESULT hr; @@ -159,7 +173,7 @@ static HRESULT WINAPI WshExec_GetIDsOfNames(IWshExec *iface, REFIID riid, LPOLES static HRESULT WINAPI WshExec_Invoke(IWshExec *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); ITypeInfo *typeinfo; HRESULT hr; @@ -179,7 +193,7 @@ static HRESULT WINAPI WshExec_Invoke(IWshExec *iface, DISPID dispIdMember, REFII static HRESULT WINAPI WshExec_get_Status(IWshExec *iface, WshExecStatus *status) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); DWORD code; TRACE("(%p)->(%p)\n", This, status); @@ -207,7 +221,7 @@ static HRESULT WINAPI WshExec_get_Status(IWshExec *iface, WshExecStatus *status) static HRESULT WINAPI WshExec_get_StdIn(IWshExec *iface, ITextStream **stream) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); FIXME("(%p)->(%p): stub\n", This, stream); @@ -216,7 +230,7 @@ static HRESULT WINAPI WshExec_get_StdIn(IWshExec *iface, ITextStream **stream) static HRESULT WINAPI WshExec_get_StdOut(IWshExec *iface, ITextStream **stream) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); FIXME("(%p)->(%p): stub\n", This, stream); @@ -225,7 +239,7 @@ static HRESULT WINAPI WshExec_get_StdOut(IWshExec *iface, ITextStream **stream) static HRESULT WINAPI WshExec_get_StdErr(IWshExec *iface, ITextStream **stream) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); FIXME("(%p)->(%p): stub\n", This, stream); @@ -234,7 +248,7 @@ static HRESULT WINAPI WshExec_get_StdErr(IWshExec *iface, ITextStream **stream) static HRESULT WINAPI WshExec_get_ProcessID(IWshExec *iface, DWORD *pid) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); TRACE("(%p)->(%p)\n", This, pid); @@ -247,7 +261,7 @@ static HRESULT WINAPI WshExec_get_ProcessID(IWshExec *iface, DWORD *pid) static HRESULT WINAPI WshExec_get_ExitCode(IWshExec *iface, DWORD *code) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); FIXME("(%p)->(%p): stub\n", This, code); @@ -266,7 +280,7 @@ static BOOL CALLBACK enum_thread_wnd_proc(HWND hwnd, LPARAM lParam) static HRESULT WINAPI WshExec_Terminate(IWshExec *iface) { - WshExec *This = impl_from_IWshExec(iface); + WshExecImpl *This = impl_from_IWshExec(iface); BOOL ret, kill = FALSE; INT count = 0; @@ -307,7 +321,7 @@ static const IWshExecVtbl WshExecVtbl = { static HRESULT WshExec_create(BSTR command, IWshExec **ret) { STARTUPINFOW si = {0}; - WshExec *This; + WshExecImpl *This; *ret = NULL; @@ -323,6 +337,7 @@ static HRESULT WshExec_create(BSTR command, IWshExec **ret) return HRESULT_FROM_WIN32(GetLastError()); } + init_classinfo(&CLSID_WshExec, (IUnknown *)&This->IWshExec_iface, &This->classinfo); *ret = &This->IWshExec_iface; return S_OK; } @@ -338,7 +353,12 @@ static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFI IsEqualGUID(riid, &IID_IWshEnvironment)) { *obj = iface; - }else { + } + else if (IsEqualIID(riid, &IID_IProvideClassInfo)) + { + *obj = &This->classinfo.IProvideClassInfo_iface; + } + else { FIXME("Unknown iface %s\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; @@ -505,6 +525,7 @@ static HRESULT WshEnvironment_Create(IWshEnvironment **env) This->IWshEnvironment_iface.lpVtbl = &WshEnvironmentVtbl; This->ref = 1; + init_classinfo(&IID_IWshEnvironment, (IUnknown *)&This->IWshEnvironment_iface, &This->classinfo); *env = &This->IWshEnvironment_iface; return S_OK; @@ -521,7 +542,12 @@ static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID IsEqualGUID(riid, &IID_IWshCollection)) { *ppv = iface; - }else { + } + else if (IsEqualIID(riid, &IID_IProvideClassInfo)) + { + *ppv = &This->classinfo.IProvideClassInfo_iface; + } + else { FIXME("Unknown iface %s\n", debugstr_guid(riid)); *ppv = NULL; return E_NOINTERFACE; @@ -701,6 +727,7 @@ static HRESULT WshCollection_Create(IWshCollection **collection) This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl; This->ref = 1; + init_classinfo(&IID_IWshCollection, (IUnknown *)&This->IWshCollection_iface, &This->classinfo); *collection = &This->IWshCollection_iface; return S_OK; @@ -718,7 +745,12 @@ static HRESULT WINAPI WshShortcut_QueryInterface(IWshShortcut *iface, REFIID rii IsEqualGUID(riid, &IID_IWshShortcut)) { *ppv = iface; - }else { + } + else if (IsEqualIID(riid, &IID_IProvideClassInfo)) + { + *ppv = &This->classinfo.IProvideClassInfo_iface; + } + else { FIXME("Unknown iface %s\n", debugstr_guid(riid)); *ppv = NULL; return E_NOINTERFACE; @@ -1067,6 +1099,7 @@ static HRESULT WshShortcut_Create(const WCHAR *path, IDispatch **shortcut) return E_OUTOFMEMORY; } + init_classinfo(&IID_IWshShortcut, (IUnknown *)&This->IWshShortcut_iface, &This->classinfo); *shortcut = (IDispatch*)&This->IWshShortcut_iface; return S_OK; @@ -1090,13 +1123,17 @@ static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, v { return E_NOINTERFACE; } + else if (IsEqualIID(riid, &IID_IProvideClassInfo)) + { + *ppv = &WshShell3.classinfo.IProvideClassInfo_iface; + } else { WARN("unknown iface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } - IWshShell3_AddRef(iface); + IUnknown_AddRef((IUnknown *)*ppv); return S_OK; } @@ -1657,11 +1694,11 @@ static const IWshShell3Vtbl WshShell3Vtbl = { WshShell3_put_CurrentDirectory }; -static IWshShell3 WshShell3 = { &WshShell3Vtbl }; - HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) { TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv); - return IWshShell3_QueryInterface(&WshShell3, riid, ppv); + WshShell3.IWshShell3_iface.lpVtbl = &WshShell3Vtbl; + init_classinfo(&IID_IWshShell3, (IUnknown *)&WshShell3.IWshShell3_iface, &WshShell3.classinfo); + return IWshShell3_QueryInterface(&WshShell3.IWshShell3_iface, riid, ppv); } diff --git a/dlls/wshom.ocx/tests/wshom.c b/dlls/wshom.ocx/tests/wshom.c index 61df0c168fd..7e82f30c180 100644 --- a/dlls/wshom.ocx/tests/wshom.c +++ b/dlls/wshom.ocx/tests/wshom.c @@ -31,6 +31,31 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); #define EXPECT_HR(hr,hr_exp) \ ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp) +#define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__) +static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line) +{ + IProvideClassInfo *classinfo; + TYPEATTR *attr; + ITypeInfo *ti; + HRESULT hr; + + hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo); + ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr); + + hr = IProvideClassInfo_GetClassInfo(classinfo, &ti); + ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr); + + hr = ITypeInfo_GetTypeAttr(ti, &attr); + ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr); + + ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid), + wine_dbgstr_guid(guid)); + + IProvideClassInfo_Release(classinfo); + ITypeInfo_ReleaseTypeAttr(ti, attr); + ITypeInfo_Release(ti); +} + static void test_wshshell(void) { static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0}; @@ -66,10 +91,11 @@ static void test_wshshell(void) hr = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell); EXPECT_HR(hr, S_OK); - IDispatch_Release(disp); + test_provideclassinfo(disp, &IID_IWshShell3); hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); EXPECT_HR(hr, E_NOINTERFACE); + IDispatch_Release(disp); hr = IUnknown_QueryInterface(shell, &IID_IWshShell3, (void**)&sh3); EXPECT_HR(hr, S_OK); @@ -87,6 +113,7 @@ static void test_wshshell(void) hr = IWshShell3_get_SpecialFolders(sh3, &coll); EXPECT_HR(hr, S_OK); + test_provideclassinfo(coll, &IID_IWshCollection); hr = IWshCollection_QueryInterface(coll, &IID_IFolderCollection, (void**)&folders); EXPECT_HR(hr, E_NOINTERFACE); @@ -128,6 +155,7 @@ static void test_wshshell(void) SysFreeString(str); hr = IDispatch_QueryInterface(shortcut, &IID_IWshShortcut, (void**)&shcut); EXPECT_HR(hr, S_OK); + test_provideclassinfo(shortcut, &IID_IWshShortcut); hr = IWshShortcut_get_Arguments(shcut, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); @@ -155,6 +183,7 @@ static void test_wshshell(void) hr = IWshEnvironment_get_Item(env, NULL, NULL); ok(hr == E_POINTER, "got 0x%08x\n", hr); + test_provideclassinfo(env, &IID_IWshEnvironment); ret = (BSTR)0x1; hr = IWshEnvironment_get_Item(env, NULL, &ret); diff --git a/dlls/wshom.ocx/tests/wshom.idl b/dlls/wshom.ocx/tests/wshom.idl index c2bc4162212..039938c82b0 100644 --- a/dlls/wshom.ocx/tests/wshom.idl +++ b/dlls/wshom.ocx/tests/wshom.idl @@ -663,4 +663,12 @@ library IWshRuntimeLibrary coclass WshNetwork { [default] interface IWshNetwork2; } + + [ + uuid(08fed191-be19-11d3-a28b-00104bd35090), + threading(apartment) + ] + coclass WshExec { + [default] interface IWshExec; + } } diff --git a/dlls/wshom.ocx/wshom.idl b/dlls/wshom.ocx/wshom.idl index 83f3c7e866b..d9367215890 100644 --- a/dlls/wshom.ocx/wshom.idl +++ b/dlls/wshom.ocx/wshom.idl @@ -663,4 +663,12 @@ library IWshRuntimeLibrary coclass WshNetwork { [default] interface IWshNetwork2; } + + [ + uuid(08fed191-be19-11d3-a28b-00104bd35090), + threading(apartment) + ] + coclass WshExec { + [default] interface IWshExec; + } } diff --git a/dlls/wshom.ocx/wshom_main.c b/dlls/wshom.ocx/wshom_main.c index e2a30edea05..0098b026a0f 100644 --- a/dlls/wshom.ocx/wshom_main.c +++ b/dlls/wshom.ocx/wshom_main.c @@ -28,6 +28,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(wshom); static HINSTANCE wshom_instance; +static inline struct provideclassinfo *impl_from_IProvideClassInfo(IProvideClassInfo *iface) +{ + return CONTAINING_RECORD(iface, struct provideclassinfo, IProvideClassInfo_iface); +} + static ITypeLib *typelib; static ITypeInfo *typeinfos[LAST_tid]; @@ -45,6 +50,9 @@ static HRESULT load_typelib(void) HRESULT hres; ITypeLib *tl; + if(typelib) + return S_OK; + hres = LoadRegTypeLib(&LIBID_IWshRuntimeLibrary, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl); if(FAILED(hres)) { ERR("LoadRegTypeLib failed: %08x\n", hres); @@ -56,13 +64,21 @@ static HRESULT load_typelib(void) return hres; } +static HRESULT get_typeinfo_of_guid(const GUID *guid, ITypeInfo **tinfo) +{ + HRESULT hres; + + if(FAILED(hres = load_typelib())) + return hres; + + return ITypeLib_GetTypeInfoOfGuid(typelib, guid, tinfo); +} + HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) { HRESULT hres; - if (!typelib) - hres = load_typelib(); - if (!typelib) + if (FAILED(hres = load_typelib())) return hres; if(!typeinfos[tid]) { @@ -98,6 +114,56 @@ void release_typelib(void) ITypeLib_Release(typelib); } +static HRESULT WINAPI provideclassinfo_QueryInterface(IProvideClassInfo *iface, REFIID riid, void **obj) +{ + struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IProvideClassInfo)) { + *obj = iface; + IProvideClassInfo_AddRef(iface); + return S_OK; + } + else + return IUnknown_QueryInterface(This->outer, riid, obj); +} + +static ULONG WINAPI provideclassinfo_AddRef(IProvideClassInfo *iface) +{ + struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI provideclassinfo_Release(IProvideClassInfo *iface) +{ + struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); + return IUnknown_Release(This->outer); +} + +static HRESULT WINAPI provideclassinfo_GetClassInfo(IProvideClassInfo *iface, ITypeInfo **ti) +{ + struct provideclassinfo *This = impl_from_IProvideClassInfo(iface); + + TRACE("(%p)->(%p)\n", This, ti); + + return get_typeinfo_of_guid(This->guid, ti); +} + +static const IProvideClassInfoVtbl provideclassinfovtbl = { + provideclassinfo_QueryInterface, + provideclassinfo_AddRef, + provideclassinfo_Release, + provideclassinfo_GetClassInfo +}; + +void init_classinfo(const GUID *guid, IUnknown *outer, struct provideclassinfo *classinfo) +{ + classinfo->IProvideClassInfo_iface.lpVtbl = &provideclassinfovtbl; + classinfo->outer = outer; + classinfo->guid = guid; +} + static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { *ppv = NULL; diff --git a/dlls/wshom.ocx/wshom_private.h b/dlls/wshom.ocx/wshom_private.h index 7cc8d0c499f..a10cf2683a3 100644 --- a/dlls/wshom.ocx/wshom_private.h +++ b/dlls/wshom.ocx/wshom_private.h @@ -23,6 +23,7 @@ #include "windef.h" #include "winbase.h" #include "ole2.h" +#include "olectl.h" /* typelibs */ typedef enum tid_t { @@ -37,4 +38,12 @@ typedef enum tid_t { HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) DECLSPEC_HIDDEN; +struct provideclassinfo { + IProvideClassInfo IProvideClassInfo_iface; + IUnknown *outer; + const GUID *guid; +}; + +extern void init_classinfo(const GUID *guid, IUnknown *outer, struct provideclassinfo *classinfo) DECLSPEC_HIDDEN; + HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;