From: Damjan Jovanovic Subject: [PATCH v2] ieframe: implement COM aggregation in WebBrowser Message-Id: Date: Sun, 8 Dec 2019 01:43:49 +0200 Wine's WebBrowser currently just ignores the "outer" it is passed. Support COM aggregation like Windows does instead. Try 2 renames the internal IUnknown functions, uses the hlink_frame to store the outer, and beefs up the unit tests. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=12406 Signed-off-by: Damjan Jovanovic --- dlls/ieframe/classinfo.c | 6 +- dlls/ieframe/ieframe.h | 1 + dlls/ieframe/oleobject.c | 30 +-- dlls/ieframe/persist.c | 18 +- dlls/ieframe/tests/webbrowser.c | 60 ++++++ dlls/ieframe/view.c | 12 +- dlls/ieframe/webbrowser.c | 325 ++++++++++++++++++-------------- 7 files changed, 277 insertions(+), 175 deletions(-) diff --git a/dlls/ieframe/classinfo.c b/dlls/ieframe/classinfo.c index 3fa77bb6ce..c6698af890 100644 --- a/dlls/ieframe/classinfo.c +++ b/dlls/ieframe/classinfo.c @@ -37,19 +37,19 @@ static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IProvideClassInfo2(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface) { WebBrowser *This = impl_from_IProvideClassInfo2(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface) { WebBrowser *This = impl_from_IProvideClassInfo2(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI) diff --git a/dlls/ieframe/ieframe.h b/dlls/ieframe/ieframe.h index 2b4861d79b..8d238863be 100644 --- a/dlls/ieframe/ieframe.h +++ b/dlls/ieframe/ieframe.h @@ -170,6 +170,7 @@ struct DocHost { }; struct WebBrowser { + IUnknown IUnknown_inner; IWebBrowser2 IWebBrowser2_iface; IOleObject IOleObject_iface; IOleInPlaceObject IOleInPlaceObject_iface; diff --git a/dlls/ieframe/oleobject.c b/dlls/ieframe/oleobject.c index 22fe4b1848..5c49845aa7 100644 --- a/dlls/ieframe/oleobject.c +++ b/dlls/ieframe/oleobject.c @@ -439,19 +439,19 @@ static inline WebBrowser *impl_from_IOleObject(IOleObject *iface) static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **ppv) { WebBrowser *This = impl_from_IOleObject(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI OleObject_AddRef(IOleObject *iface) { WebBrowser *This = impl_from_IOleObject(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI OleObject_Release(IOleObject *iface) { WebBrowser *This = impl_from_IOleObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, LPOLECLIENTSITE pClientSite) @@ -838,19 +838,19 @@ static HRESULT WINAPI OleInPlaceObject_QueryInterface(IOleInPlaceObject *iface, REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IOleInPlaceObject(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI OleInPlaceObject_AddRef(IOleInPlaceObject *iface) { WebBrowser *This = impl_from_IOleInPlaceObject(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObject *iface) { WebBrowser *This = impl_from_IOleInPlaceObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI OleInPlaceObject_GetWindow(IOleInPlaceObject *iface, HWND* phwnd) @@ -947,19 +947,19 @@ static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IOleControl(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI OleControl_AddRef(IOleControl *iface) { WebBrowser *This = impl_from_IOleControl(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI OleControl_Release(IOleControl *iface) { WebBrowser *This = impl_from_IOleControl(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, LPCONTROLINFO pCI) @@ -1030,19 +1030,19 @@ static HRESULT WINAPI InPlaceActiveObject_QueryInterface(IOleInPlaceActiveObject REFIID riid, void **ppv) { WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI InPlaceActiveObject_AddRef(IOleInPlaceActiveObject *iface) { WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI InPlaceActiveObject_Release(IOleInPlaceActiveObject *iface) { WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI InPlaceActiveObject_GetWindow(IOleInPlaceActiveObject *iface, @@ -1137,19 +1137,19 @@ static HRESULT WINAPI WBOleCommandTarget_QueryInterface(IOleCommandTarget *iface REFIID riid, void **ppv) { WebBrowser *This = impl_from_IOleCommandTarget(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI WBOleCommandTarget_AddRef(IOleCommandTarget *iface) { WebBrowser *This = impl_from_IOleCommandTarget(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI WBOleCommandTarget_Release(IOleCommandTarget *iface) { WebBrowser *This = impl_from_IOleCommandTarget(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI WBOleCommandTarget_QueryStatus(IOleCommandTarget *iface, diff --git a/dlls/ieframe/persist.c b/dlls/ieframe/persist.c index 4c890d7ebf..bef5ef7344 100644 --- a/dlls/ieframe/persist.c +++ b/dlls/ieframe/persist.c @@ -38,19 +38,19 @@ static HRESULT WINAPI PersistStorage_QueryInterface(IPersistStorage *iface, REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IPersistStorage(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI PersistStorage_AddRef(IPersistStorage *iface) { WebBrowser *This = impl_from_IPersistStorage(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI PersistStorage_Release(IPersistStorage *iface) { WebBrowser *This = impl_from_IPersistStorage(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI PersistStorage_GetClassID(IPersistStorage *iface, CLSID *pClassID) @@ -122,19 +122,19 @@ static HRESULT WINAPI PersistMemory_QueryInterface(IPersistMemory *iface, REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IPersistMemory(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI PersistMemory_AddRef(IPersistMemory *iface) { WebBrowser *This = impl_from_IPersistMemory(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI PersistMemory_Release(IPersistMemory *iface) { WebBrowser *This = impl_from_IPersistMemory(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI PersistMemory_GetClassID(IPersistMemory *iface, CLSID *pClassID) @@ -206,19 +206,19 @@ static HRESULT WINAPI PersistStreamInit_QueryInterface(IPersistStreamInit *iface REFIID riid, LPVOID *ppobj) { WebBrowser *This = impl_from_IPersistStreamInit(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppobj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppobj); } static ULONG WINAPI PersistStreamInit_AddRef(IPersistStreamInit *iface) { WebBrowser *This = impl_from_IPersistStreamInit(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI PersistStreamInit_Release(IPersistStreamInit *iface) { WebBrowser *This = impl_from_IPersistStreamInit(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI PersistStreamInit_GetClassID(IPersistStreamInit *iface, CLSID *pClassID) diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c index a99c68ac5e..d8e157f489 100644 --- a/dlls/ieframe/tests/webbrowser.c +++ b/dlls/ieframe/tests/webbrowser.c @@ -45,6 +45,7 @@ #include "docobjectservice.h" DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +DEFINE_GUID(outer_test_iid,0x06d4cd6c,0x18dd,0x11ea,0x8e,0x76,0xfc,0xaa,0x14,0x72,0x2d,0xac); DEFINE_OLEGUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0); #define DEFINE_EXPECT(func) \ @@ -155,6 +156,7 @@ DEFINE_EXPECT(ControlSite_TranslateAccelerator); DEFINE_EXPECT(OnFocus_TRUE); DEFINE_EXPECT(OnFocus_FALSE); DEFINE_EXPECT(GetExternal); +DEFINE_EXPECT(outer_QI_test); static const WCHAR wszItem[] = {'i','t','e','m',0}; @@ -4136,6 +4138,63 @@ static void test_SetAdvise(void) IWebBrowser2_Release(browser); } +static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &outer_test_iid)) { + CHECK_EXPECT(outer_QI_test); + *ppv = (IUnknown*)0xdeadbeef; + return S_OK; + } + ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI outer_AddRef(IUnknown *iface) +{ + return 2; +} + +static ULONG WINAPI outer_Release(IUnknown *iface) +{ + return 1; +} + +static IUnknownVtbl outer_vtbl = { + outer_QueryInterface, + outer_AddRef, + outer_Release +}; + +static void test_Aggregation(void) +{ + HRESULT hr; + IClassFactory *class_factory; + IUnknown outer = { &outer_vtbl }; + IUnknown *unk = NULL; + IWebBrowser *web_browser = NULL; + IUnknown *unk2 = NULL; + + hr = CoGetClassObject(&CLSID_WebBrowser, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&class_factory); + ok(hr == S_OK, "CoGetClassObject failed: %08x\n", hr); + + hr = IClassFactory_CreateInstance(class_factory, &outer, &IID_IUnknown, (void**)&unk); + ok(hr == S_OK, "CreateInstance returned hr = %08x\n", hr); + ok(unk != NULL, "result NULL, hr = %08x\n", hr); + + hr = IUnknown_QueryInterface(unk, &IID_IWebBrowser, (void**)&web_browser); + ok(hr == S_OK, "QI to IWebBrowser failed, hr=%08x\n", hr); + + SET_EXPECT(outer_QI_test); + hr = IWebBrowser_QueryInterface(web_browser, &outer_test_iid, (void**)&unk2); + CHECK_CALLED(outer_QI_test); + ok(hr == S_OK, "Could not get test iface: %08x\n", hr); + ok(unk2 == (IUnknown*)0xdeadbeef, "unexpected unk2\n"); + + IWebBrowser_Release(web_browser); + IUnknown_Release(unk); + IClassFactory_Release(class_factory); +} + START_TEST(webbrowser) { OleInitialize(NULL); @@ -4167,6 +4226,7 @@ START_TEST(webbrowser) test_FileProtocol(); trace("Testing SetAdvise...\n"); test_SetAdvise(); + test_Aggregation(); OleUninitialize(); } diff --git a/dlls/ieframe/view.c b/dlls/ieframe/view.c index 546e2511a3..d307bb5a00 100644 --- a/dlls/ieframe/view.c +++ b/dlls/ieframe/view.c @@ -35,19 +35,19 @@ static inline WebBrowser *impl_from_IViewObject2(IViewObject2 *iface) static HRESULT WINAPI ViewObject_QueryInterface(IViewObject2 *iface, REFIID riid, void **ppv) { WebBrowser *This = impl_from_IViewObject2(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI ViewObject_AddRef(IViewObject2 *iface) { WebBrowser *This = impl_from_IViewObject2(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI ViewObject_Release(IViewObject2 *iface) { WebBrowser *This = impl_from_IViewObject2(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI ViewObject_Draw(IViewObject2 *iface, DWORD dwDrawAspect, @@ -157,19 +157,19 @@ static inline WebBrowser *impl_from_IDataObject(IDataObject *iface) static HRESULT WINAPI DataObject_QueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj) { WebBrowser *This = impl_from_IDataObject(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppvObj); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppvObj); } static ULONG WINAPI DataObject_AddRef(LPDATAOBJECT iface) { WebBrowser *This = impl_from_IDataObject(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI DataObject_Release(LPDATAOBJECT iface) { WebBrowser *This = impl_from_IDataObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT WINAPI DataObject_GetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) diff --git a/dlls/ieframe/webbrowser.c b/dlls/ieframe/webbrowser.c index 03acf38869..5f12318bc4 100644 --- a/dlls/ieframe/webbrowser.c +++ b/dlls/ieframe/webbrowser.c @@ -37,151 +37,21 @@ static HRESULT WINAPI WebBrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid { WebBrowser *This = impl_from_IWebBrowser2(iface); - if (ppv == NULL) - return E_POINTER; - *ppv = NULL; - - if(IsEqualGUID(&IID_IUnknown, riid)) { - TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IWebBrowser2_iface; - }else if(IsEqualGUID(&IID_IDispatch, riid)) { - TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); - *ppv = &This->IWebBrowser2_iface; - }else if(IsEqualGUID(&IID_IWebBrowser, riid)) { - TRACE("(%p)->(IID_IWebBrowser %p)\n", This, ppv); - *ppv = &This->IWebBrowser2_iface; - }else if(IsEqualGUID(&IID_IWebBrowserApp, riid)) { - TRACE("(%p)->(IID_IWebBrowserApp %p)\n", This, ppv); - *ppv = &This->IWebBrowser2_iface; - }else if(IsEqualGUID(&IID_IWebBrowser2, riid)) { - TRACE("(%p)->(IID_IWebBrowser2 %p)\n", This, ppv); - *ppv = &This->IWebBrowser2_iface; - }else if(IsEqualGUID(&IID_IOleObject, riid)) { - TRACE("(%p)->(IID_IOleObject %p)\n", This, ppv); - *ppv = &This->IOleObject_iface; - }else if(IsEqualGUID(&IID_IOleWindow, riid)) { - TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv); - *ppv = &This->IOleInPlaceObject_iface; - }else if(IsEqualGUID (&IID_IOleInPlaceObject, riid)) { - TRACE("(%p)->(IID_IOleInPlaceObject %p)\n", This, ppv); - *ppv = &This->IOleInPlaceObject_iface; - }else if(IsEqualGUID(&IID_IOleControl, riid)) { - TRACE("(%p)->(IID_IOleControl %p)\n", This, ppv); - *ppv = &This->IOleControl_iface; - }else if(IsEqualGUID(&IID_IPersist, riid)) { - TRACE("(%p)->(IID_IPersist %p)\n", This, ppv); - *ppv = &This->IPersistStorage_iface; - }else if(IsEqualGUID(&IID_IPersistStorage, riid)) { - TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv); - *ppv = &This->IPersistStorage_iface; - }else if(IsEqualGUID(&IID_IPersistMemory, riid)) { - TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv); - *ppv = &This->IPersistMemory_iface; - }else if(IsEqualGUID (&IID_IPersistStreamInit, riid)) { - TRACE("(%p)->(IID_IPersistStreamInit %p)\n", This, ppv); - *ppv = &This->IPersistStreamInit_iface; - }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) { - TRACE("(%p)->(IID_IProvideClassInfo %p)\n", This, ppv); - *ppv = &This->IProvideClassInfo2_iface; - }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) { - TRACE("(%p)->(IID_IProvideClassInfo2 %p)\n", This, ppv); - *ppv = &This->IProvideClassInfo2_iface; - }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { - TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv); - *ppv = &This->doc_host.cps.IConnectionPointContainer_iface; - }else if(IsEqualGUID(&IID_IViewObject, riid)) { - TRACE("(%p)->(IID_IViewObject %p)\n", This, ppv); - *ppv = &This->IViewObject2_iface; - }else if(IsEqualGUID(&IID_IViewObject2, riid)) { - TRACE("(%p)->(IID_IViewObject2 %p)\n", This, ppv); - *ppv = &This->IViewObject2_iface; - }else if(IsEqualGUID(&IID_IOleInPlaceActiveObject, riid)) { - TRACE("(%p)->(IID_IOleInPlaceActiveObject %p)\n", This, ppv); - *ppv = &This->IOleInPlaceActiveObject_iface; - }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) { - TRACE("(%p)->(IID_IOleCommandTarget %p)\n", This, ppv); - *ppv = &This->IOleCommandTarget_iface; - }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { - *ppv = &This->IServiceProvider_iface; - TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); - }else if(IsEqualGUID(&IID_IDataObject, riid)) { - *ppv = &This->IDataObject_iface; - TRACE("(%p)->(IID_IDataObject %p)\n", This, ppv); - }else if(IsEqualGUID(&IID_IQuickActivate, riid)) { - TRACE("(%p)->(IID_IQuickActivate %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IRunnableObject, riid)) { - TRACE("(%p)->(IID_IRunnableObject %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IPerPropertyBrowsing, riid)) { - TRACE("(%p)->(IID_IPerPropertyBrowsing %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IOleCache, riid)) { - TRACE("(%p)->(IID_IOleCache %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) { - TRACE("(%p)->(IID_IOleInPlaceSite %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) { - TRACE("(%p)->(IID_IObjectWithSite %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IViewObjectEx, riid)) { - TRACE("(%p)->(IID_IViewObjectEx %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IOleLink, riid)) { - TRACE("(%p)->(IID_IOleLink %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IMarshal, riid)) { - TRACE("(%p)->(IID_IMarshal %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(IsEqualGUID(&IID_IStdMarshalInfo, riid)) { - /* This is implemented since IE10 */ - WARN("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv); - return E_NOINTERFACE; - }else if(HlinkFrame_QI(&This->hlink_frame, riid, ppv)) { - return S_OK; - } - - if(*ppv) { - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - FIXME("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv); - return E_NOINTERFACE; + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI WebBrowser_AddRef(IWebBrowser2 *iface) { WebBrowser *This = impl_from_IWebBrowser2(iface); - LONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) ref=%d\n", This, ref); - return ref; + + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI WebBrowser_Release(IWebBrowser2 *iface) { WebBrowser *This = impl_from_IWebBrowser2(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - if(!ref) { - if(This->sink) - IAdviseSink_Release(This->sink); - - if(This->doc_host.document) - IUnknown_Release(This->doc_host.document); - DocHost_Release(&This->doc_host); - - WebBrowser_OleObject_Destroy(This); - - heap_free(This); - unlock_module(); - } - - return ref; + return IUnknown_Release(This->hlink_frame.outer); } /* IDispatch methods */ @@ -1136,19 +1006,19 @@ static HRESULT WINAPI WBServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, LPVOID *ppv) { WebBrowser *This = impl_from_IServiceProvider(iface); - return IWebBrowser2_QueryInterface(&This->IWebBrowser2_iface, riid, ppv); + return IUnknown_QueryInterface(This->hlink_frame.outer, riid, ppv); } static ULONG WINAPI WBServiceProvider_AddRef(IServiceProvider *iface) { WebBrowser *This = impl_from_IServiceProvider(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WINAPI WBServiceProvider_Release(IServiceProvider *iface) { WebBrowser *This = impl_from_IServiceProvider(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static HRESULT STDMETHODCALLTYPE WBServiceProvider_QueryService(IServiceProvider *iface, @@ -1188,13 +1058,13 @@ static inline WebBrowser *impl_from_DocHost(DocHost *iface) static ULONG WebBrowser_addref(DocHost *iface) { WebBrowser *This = impl_from_DocHost(iface); - return IWebBrowser2_AddRef(&This->IWebBrowser2_iface); + return IUnknown_AddRef(This->hlink_frame.outer); } static ULONG WebBrowser_release(DocHost *iface) { WebBrowser *This = impl_from_DocHost(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->hlink_frame.outer); } static void DocHostContainer_get_docobj_rect(DocHost *This, RECT *rc) @@ -1224,6 +1094,169 @@ static const IDocHostContainerVtbl DocHostContainerVtbl = { DocHostContainer_set_url }; +static inline WebBrowser *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, WebBrowser, IUnknown_inner); +} + +static HRESULT WINAPI WebBrowser_Internal_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + WebBrowser *This = impl_from_IUnknown(iface); + + if (ppv == NULL) + return E_POINTER; + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IUnknown_inner; + }else if(IsEqualGUID(&IID_IDispatch, riid)) { + TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); + *ppv = &This->IWebBrowser2_iface; + }else if(IsEqualGUID(&IID_IWebBrowser, riid)) { + TRACE("(%p)->(IID_IWebBrowser %p)\n", This, ppv); + *ppv = &This->IWebBrowser2_iface; + }else if(IsEqualGUID(&IID_IWebBrowserApp, riid)) { + TRACE("(%p)->(IID_IWebBrowserApp %p)\n", This, ppv); + *ppv = &This->IWebBrowser2_iface; + }else if(IsEqualGUID(&IID_IWebBrowser2, riid)) { + TRACE("(%p)->(IID_IWebBrowser2 %p)\n", This, ppv); + *ppv = &This->IWebBrowser2_iface; + }else if(IsEqualGUID(&IID_IOleObject, riid)) { + TRACE("(%p)->(IID_IOleObject %p)\n", This, ppv); + *ppv = &This->IOleObject_iface; + }else if(IsEqualGUID(&IID_IOleWindow, riid)) { + TRACE("(%p)->(IID_IOleWindow %p)\n", This, ppv); + *ppv = &This->IOleInPlaceObject_iface; + }else if(IsEqualGUID (&IID_IOleInPlaceObject, riid)) { + TRACE("(%p)->(IID_IOleInPlaceObject %p)\n", This, ppv); + *ppv = &This->IOleInPlaceObject_iface; + }else if(IsEqualGUID(&IID_IOleControl, riid)) { + TRACE("(%p)->(IID_IOleControl %p)\n", This, ppv); + *ppv = &This->IOleControl_iface; + }else if(IsEqualGUID(&IID_IPersist, riid)) { + TRACE("(%p)->(IID_IPersist %p)\n", This, ppv); + *ppv = &This->IPersistStorage_iface; + }else if(IsEqualGUID(&IID_IPersistStorage, riid)) { + TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv); + *ppv = &This->IPersistStorage_iface; + }else if(IsEqualGUID(&IID_IPersistMemory, riid)) { + TRACE("(%p)->(IID_IPersistStorage %p)\n", This, ppv); + *ppv = &This->IPersistMemory_iface; + }else if(IsEqualGUID (&IID_IPersistStreamInit, riid)) { + TRACE("(%p)->(IID_IPersistStreamInit %p)\n", This, ppv); + *ppv = &This->IPersistStreamInit_iface; + }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) { + TRACE("(%p)->(IID_IProvideClassInfo %p)\n", This, ppv); + *ppv = &This->IProvideClassInfo2_iface; + }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) { + TRACE("(%p)->(IID_IProvideClassInfo2 %p)\n", This, ppv); + *ppv = &This->IProvideClassInfo2_iface; + }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { + TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv); + *ppv = &This->doc_host.cps.IConnectionPointContainer_iface; + }else if(IsEqualGUID(&IID_IViewObject, riid)) { + TRACE("(%p)->(IID_IViewObject %p)\n", This, ppv); + *ppv = &This->IViewObject2_iface; + }else if(IsEqualGUID(&IID_IViewObject2, riid)) { + TRACE("(%p)->(IID_IViewObject2 %p)\n", This, ppv); + *ppv = &This->IViewObject2_iface; + }else if(IsEqualGUID(&IID_IOleInPlaceActiveObject, riid)) { + TRACE("(%p)->(IID_IOleInPlaceActiveObject %p)\n", This, ppv); + *ppv = &This->IOleInPlaceActiveObject_iface; + }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) { + TRACE("(%p)->(IID_IOleCommandTarget %p)\n", This, ppv); + *ppv = &This->IOleCommandTarget_iface; + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + *ppv = &This->IServiceProvider_iface; + TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); + }else if(IsEqualGUID(&IID_IDataObject, riid)) { + *ppv = &This->IDataObject_iface; + TRACE("(%p)->(IID_IDataObject %p)\n", This, ppv); + }else if(IsEqualGUID(&IID_IQuickActivate, riid)) { + TRACE("(%p)->(IID_IQuickActivate %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IRunnableObject, riid)) { + TRACE("(%p)->(IID_IRunnableObject %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IPerPropertyBrowsing, riid)) { + TRACE("(%p)->(IID_IPerPropertyBrowsing %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IOleCache, riid)) { + TRACE("(%p)->(IID_IOleCache %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IOleInPlaceSite, riid)) { + TRACE("(%p)->(IID_IOleInPlaceSite %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) { + TRACE("(%p)->(IID_IObjectWithSite %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IViewObjectEx, riid)) { + TRACE("(%p)->(IID_IViewObjectEx %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IOleLink, riid)) { + TRACE("(%p)->(IID_IOleLink %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IMarshal, riid)) { + TRACE("(%p)->(IID_IMarshal %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IStdMarshalInfo, riid)) { + /* This is implemented since IE10 */ + WARN("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv); + return E_NOINTERFACE; + }else if(HlinkFrame_QI(&This->hlink_frame, riid, ppv)) { + return S_OK; + } + + if(*ppv) { + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + + FIXME("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static ULONG WINAPI WebBrowser_Internal_AddRef(IUnknown *iface) +{ + WebBrowser *This = impl_from_IUnknown(iface); + LONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) ref=%d\n", This, ref); + return ref; +} + +static ULONG WINAPI WebBrowser_Internal_Release(IUnknown *iface) +{ + WebBrowser *This = impl_from_IUnknown(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + if(This->sink) + IAdviseSink_Release(This->sink); + + if(This->doc_host.document) + IUnknown_Release(This->doc_host.document); + + DocHost_Release(&This->doc_host); + + WebBrowser_OleObject_Destroy(This); + + heap_free(This); + unlock_module(); + } + + return ref; +} + +static const struct IUnknownVtbl internal_unk_vtbl = +{ + WebBrowser_Internal_QueryInterface, + WebBrowser_Internal_AddRef, + WebBrowser_Internal_Release +}; + static HRESULT create_webbrowser(int version, IUnknown *outer, REFIID riid, void **ppv) { WebBrowser *ret; @@ -1231,8 +1264,16 @@ static HRESULT create_webbrowser(int version, IUnknown *outer, REFIID riid, void TRACE("(%p %s %p) version=%d\n", outer, debugstr_guid(riid), ppv, version); + if (outer && !IsEqualIID(riid, &IID_IUnknown)) + return CLASS_E_NOAGGREGATION; + ret = heap_alloc_zero(sizeof(WebBrowser)); + ret->IUnknown_inner.lpVtbl = &internal_unk_vtbl; + if (outer) + ret->hlink_frame.outer = outer; + else + ret->hlink_frame.outer = &ret->IUnknown_inner; ret->IWebBrowser2_iface.lpVtbl = &WebBrowser2Vtbl; ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; @@ -1251,13 +1292,13 @@ static HRESULT create_webbrowser(int version, IUnknown *outer, REFIID riid, void WebBrowser_Persist_Init(ret); WebBrowser_ClassInfo_Init(ret); - HlinkFrame_Init(&ret->hlink_frame, (IUnknown*)&ret->IWebBrowser2_iface, &ret->doc_host); + HlinkFrame_Init(&ret->hlink_frame, ret->hlink_frame.outer, &ret->doc_host); lock_module(); - hres = IWebBrowser2_QueryInterface(&ret->IWebBrowser2_iface, riid, ppv); + hres = IUnknown_QueryInterface(&ret->IUnknown_inner, riid, ppv); - IWebBrowser2_Release(&ret->IWebBrowser2_iface); + IUnknown_Release(&ret->IUnknown_inner); return hres; }