From: Damjan Jovanovic Subject: [PATCH] ieframe: implement COM aggregation in WebBrowser Message-Id: Date: Mon, 2 Dec 2019 04:44:33 +0200 Wine's WebBrowser currently just ignores the "outer" it is passed. Support COM aggregation like Windows does instead. Signed-off-by: Damjan Jovanovic --- dlls/ieframe/classinfo.c | 6 +- dlls/ieframe/ieframe.h | 2 + dlls/ieframe/oleobject.c | 30 +-- dlls/ieframe/persist.c | 18 +- dlls/ieframe/tests/webbrowser.c | 42 +++++ dlls/ieframe/view.c | 12 +- dlls/ieframe/webbrowser.c | 323 ++++++++++++++++++-------------- 7 files changed, 259 insertions(+), 174 deletions(-) diff --git a/dlls/ieframe/classinfo.c b/dlls/ieframe/classinfo.c index 3fa77bb6ce..29544fc940 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->outer_unk, 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->outer_unk); } static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface) { WebBrowser *This = impl_from_IProvideClassInfo2(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI) diff --git a/dlls/ieframe/ieframe.h b/dlls/ieframe/ieframe.h index 2b4861d79b..290bc8fee4 100644 --- a/dlls/ieframe/ieframe.h +++ b/dlls/ieframe/ieframe.h @@ -170,6 +170,8 @@ struct DocHost { }; struct WebBrowser { + IUnknown IUnknown_inner; + IUnknown *outer_unk; IWebBrowser2 IWebBrowser2_iface; IOleObject IOleObject_iface; IOleInPlaceObject IOleInPlaceObject_iface; diff --git a/dlls/ieframe/oleobject.c b/dlls/ieframe/oleobject.c index 22fe4b1848..d6409b9803 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->outer_unk, 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->outer_unk); } static ULONG WINAPI OleObject_Release(IOleObject *iface) { WebBrowser *This = impl_from_IOleObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI OleInPlaceObject_Release(IOleInPlaceObject *iface) { WebBrowser *This = impl_from_IOleInPlaceObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI OleControl_Release(IOleControl *iface) { WebBrowser *This = impl_from_IOleControl(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI InPlaceActiveObject_Release(IOleInPlaceActiveObject *iface) { WebBrowser *This = impl_from_IOleInPlaceActiveObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI WBOleCommandTarget_Release(IOleCommandTarget *iface) { WebBrowser *This = impl_from_IOleCommandTarget(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } static HRESULT WINAPI WBOleCommandTarget_QueryStatus(IOleCommandTarget *iface, diff --git a/dlls/ieframe/persist.c b/dlls/ieframe/persist.c index 4c890d7ebf..a177619261 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->outer_unk, 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->outer_unk); } static ULONG WINAPI PersistStorage_Release(IPersistStorage *iface) { WebBrowser *This = impl_from_IPersistStorage(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI PersistMemory_Release(IPersistMemory *iface) { WebBrowser *This = impl_from_IPersistMemory(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI PersistStreamInit_Release(IPersistStreamInit *iface) { WebBrowser *This = impl_from_IPersistStreamInit(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } static HRESULT WINAPI PersistStreamInit_GetClassID(IPersistStreamInit *iface, CLSID *pClassID) diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c index db47fdf616..a343db5e6d 100644 --- a/dlls/ieframe/tests/webbrowser.c +++ b/dlls/ieframe/tests/webbrowser.c @@ -4136,6 +4136,47 @@ static void test_SetAdvise(void) IWebBrowser2_Release(browser); } +static HRESULT WINAPI Unknown_QueryInterface(IUnknown *pUnknown, REFIID riid, void **ppvObject) +{ + if (IsEqualGUID(&IID_IUnknown, riid)) + { + *ppvObject = pUnknown; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI Unknown_AddRef(IUnknown *pUnknown) +{ + return 2; +} + +static ULONG WINAPI Unknown_Release(IUnknown *pUnknown) +{ + return 1; +} + +static IUnknownVtbl unknownVtbl = { + Unknown_QueryInterface, + Unknown_AddRef, + Unknown_Release +}; + +static IUnknown unknown = { + &unknownVtbl +}; + +static void test_Aggregation(void) +{ + HRESULT hr; + IUnknown *pUnknown = NULL; + + hr = CoCreateInstance(&CLSID_WebBrowser, &unknown, CLSCTX_ALL, &IID_IUnknown, (void**)&pUnknown); + ok(hr == S_OK, "could not create instance of CLSID_WebBrowser with IID_IUnknown, hr = 0x%x\n", hr); + if (pUnknown) + IUnknown_Release(pUnknown); +} + START_TEST(webbrowser) { OleInitialize(NULL); @@ -4167,6 +4208,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..8fe90ef368 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->outer_unk, 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->outer_unk); } static ULONG WINAPI ViewObject_Release(IViewObject2 *iface) { WebBrowser *This = impl_from_IViewObject2(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk, 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->outer_unk); } static ULONG WINAPI DataObject_Release(LPDATAOBJECT iface) { WebBrowser *This = impl_from_IDataObject(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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..360d5acd60 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->outer_unk, 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->outer_unk); } 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->outer_unk); } /* 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->outer_unk, 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->outer_unk); } static ULONG WINAPI WBServiceProvider_Release(IServiceProvider *iface) { WebBrowser *This = impl_from_IServiceProvider(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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->outer_unk); } static ULONG WebBrowser_release(DocHost *iface) { WebBrowser *This = impl_from_DocHost(iface); - return IWebBrowser2_Release(&This->IWebBrowser2_iface); + return IUnknown_Release(This->outer_unk); } 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 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 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 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 = +{ + Internal_QueryInterface, + Internal_AddRef, + 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->outer_unk = outer; + else + ret->outer_unk = &ret->IUnknown_inner; ret->IWebBrowser2_iface.lpVtbl = &WebBrowser2Vtbl; ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl; ret->ref = 1; @@ -1255,9 +1296,9 @@ static HRESULT create_webbrowser(int version, IUnknown *outer, REFIID riid, void 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; }