Module: wine Branch: master Commit: 47393c300eaa2c9d713596c01eaee13127b477ef URL: https://gitlab.winehq.org/wine/wine/-/commit/47393c300eaa2c9d713596c01eaee13...
Author: Gabriel Ivăncescu gabrielopcode@gmail.com Date: Thu Sep 7 16:07:00 2023 +0300
mshtml: Introduce query_interface in dispex vtbl and use it for DOM Nodes.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
---
dlls/mshtml/dispex.c | 31 ++++++++++++++++++------------- dlls/mshtml/htmldoc.c | 2 ++ dlls/mshtml/htmlelem.c | 1 + dlls/mshtml/htmlevent.c | 13 +++++++++++++ dlls/mshtml/htmlnode.c | 32 +++++++++++++------------------- dlls/mshtml/htmltextnode.c | 1 + dlls/mshtml/mshtml_private.h | 5 +++++ 7 files changed, 53 insertions(+), 32 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index b5d8ac83346..ec781351291 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1968,9 +1968,15 @@ static IDispatchExVtbl DispatchExVtbl = {
BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv) { - if(IsEqualGUID(&IID_IDispatch, riid)) - *ppv = &This->IDispatchEx_iface; - else if(IsEqualGUID(&IID_IDispatchEx, riid)) + TRACE("%s (%p)->(%s %p)\n", This->info->desc->name, This, debugstr_mshtml_guid(riid), ppv); + + if(This->info->desc->vtbl->query_interface) { + *ppv = This->info->desc->vtbl->query_interface(This, riid); + if(*ppv) + goto ret; + } + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IDispatchEx, riid)) *ppv = &This->IDispatchEx_iface; else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) { *ppv = &dispex_ccp; @@ -1978,19 +1984,18 @@ BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv) }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) { *ppv = &This->IDispatchEx_iface; return TRUE; - }else if(IsEqualGUID(&IID_IDispatchJS, riid)) - *ppv = NULL; - else if(IsEqualGUID(&IID_UndocumentedScriptIface, riid)) - *ppv = NULL; - else if(IsEqualGUID(&IID_IMarshal, riid)) + }else if(IsEqualGUID(&IID_IDispatchJS, riid) || + IsEqualGUID(&IID_UndocumentedScriptIface, riid) || + IsEqualGUID(&IID_IMarshal, riid) || + IsEqualGUID(&IID_IManagedObject, riid)) { *ppv = NULL; - else if(IsEqualGUID(&IID_IManagedObject, riid)) - *ppv = NULL; - else + return TRUE; + }else { return FALSE; + }
- if(*ppv) - IUnknown_AddRef((IUnknown*)*ppv); +ret: + IDispatchEx_AddRef(&This->IDispatchEx_iface); return TRUE; }
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 01199ab4304..bff2452f4cd 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -355,6 +355,7 @@ static IHTMLEventObj *DocumentType_set_current_event(DispatchEx *dispex, IHTMLEv
static const event_target_vtbl_t DocumentType_event_target_vtbl = { { + .query_interface = HTMLDOMNode_query_interface, .destructor = HTMLDOMNode_destructor, .traverse = HTMLDOMNode_traverse, .unlink = HTMLDOMNode_unlink @@ -6067,6 +6068,7 @@ static HRESULT HTMLDocumentNode_location_hook(DispatchEx *dispex, WORD flags, DI
static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = { { + .query_interface = HTMLDOMNode_query_interface, .destructor = HTMLDOMNode_destructor, .traverse = HTMLDOMNode_traverse, .unlink = HTMLDOMNode_unlink, diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index af6551cc9fc..ad71d128266 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7350,6 +7350,7 @@ static const tid_t HTMLElement_iface_tids[] = {
const event_target_vtbl_t HTMLElement_event_target_vtbl = { { + .query_interface = HTMLDOMNode_query_interface, .destructor = HTMLDOMNode_destructor, .traverse = HTMLDOMNode_traverse, .unlink = HTMLDOMNode_unlink, diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 2ba912f5fb3..c64eded6a0a 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -4564,6 +4564,19 @@ static HRESULT get_gecko_target(IEventTarget *target, nsIDOMEventTarget **ret) return S_OK; }
+void *EventTarget_query_interface(EventTarget *event_target, REFIID riid) +{ + if(IsEqualGUID(riid, &IID_IEventTarget)) { + if(use_event_quirks(event_target)) { + WARN("IEventTarget queried, but not supported by in document mode\n"); + return NULL; + } + return &event_target->IEventTarget_iface; + } + + return NULL; +} + HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv) { if(IsEqualGUID(riid, &IID_IEventTarget)) { diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index d9c955691d5..f0dc460d596 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -493,17 +493,11 @@ static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface, { HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
- /* FIXME: Get rid of this when dispex handles QI */ - if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid) || IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) { - dispex_query_interface(&This->event_target.dispex, riid, ppv); - return S_OK; - } - - if((*ppv = This->vtbl->qi(This, riid))) { - IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface); - return S_OK; - } + if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) + return *ppv ? S_OK : E_NOINTERFACE;
+ *ppv = NULL; + WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); return E_NOINTERFACE; }
@@ -1437,6 +1431,13 @@ static inline HTMLDOMNode *HTMLDOMNode_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLDOMNode, event_target.dispex); }
+void *HTMLDOMNode_query_interface(DispatchEx *dispex, REFIID riid) +{ + HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex); + + return This->vtbl->qi(This, riid); +} + void HTMLDOMNode_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) { HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex); @@ -1477,9 +1478,6 @@ void HTMLDOMNode_destructor(DispatchEx *dispex)
void *HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid) { - IUnknown *unk; - HRESULT hres; - if(IsEqualGUID(&IID_IUnknown, riid)) return &This->IHTMLDOMNode_iface; if(IsEqualGUID(&IID_IDispatch, riid)) @@ -1491,12 +1489,7 @@ void *HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid) if(IsEqualGUID(&IID_IHTMLDOMNode3, riid)) return &This->IHTMLDOMNode3_iface;
- hres = EventTarget_QI(&This->event_target, riid, (void**)&unk); - if(hres != S_OK) - return NULL; - - IUnknown_Release(unk); - return unk; + return EventTarget_query_interface(&This->event_target, riid); }
static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret) @@ -1542,6 +1535,7 @@ void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsno }
static const dispex_static_data_vtbl_t HTMLDOMNode_dispex_vtbl = { + .query_interface = HTMLDOMNode_query_interface, .destructor = HTMLDOMNode_destructor, .traverse = HTMLDOMNode_traverse, .unlink = HTMLDOMNode_unlink diff --git a/dlls/mshtml/htmltextnode.c b/dlls/mshtml/htmltextnode.c index 6fd1a102612..f3302fcaf6f 100644 --- a/dlls/mshtml/htmltextnode.c +++ b/dlls/mshtml/htmltextnode.c @@ -352,6 +352,7 @@ static const NodeImplVtbl HTMLDOMTextNodeImplVtbl = { };
static const dispex_static_data_vtbl_t HTMLDOMTextNode_dispex_vtbl = { + .query_interface = HTMLDOMNode_query_interface, .destructor = HTMLDOMNode_destructor, .traverse = HTMLDOMNode_traverse, .unlink = HTMLDOMNode_unlink diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index dfbbd3fec83..0e7ad70e9c2 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -352,6 +352,9 @@ typedef struct { - dynamic props: These props are generally allocated by external code (e.g. 'document.wine = 42' creates 'wine' dynamic prop on document) */ typedef struct { + /* Used to provide object specific interfaces (do not AddRef, just return the iface) */ + void *(*query_interface)(DispatchEx*,REFIID); + /* Used to implement Cycle Collection callbacks; note that the destructor is not optional! Unlike delete_cycle_collectable, unlink is called before the destructor (if available). */ void (*destructor)(DispatchEx*); @@ -1207,10 +1210,12 @@ void HTMLDOMNode_Init(HTMLDocumentNode*,HTMLDOMNode*,nsIDOMNode*,dispex_static_d void HTMLElement_Init(HTMLElement*,HTMLDocumentNode*,nsIDOMElement*,dispex_static_data_t*);
void EventTarget_Init(EventTarget*,IUnknown*,dispex_static_data_t*,compat_mode_t); +void *EventTarget_query_interface(EventTarget*,REFIID); HRESULT EventTarget_QI(EventTarget*,REFIID,void**); void EventTarget_init_dispex_info(dispex_data_t*,compat_mode_t);
void *HTMLDOMNode_QI(HTMLDOMNode*,REFIID); +void *HTMLDOMNode_query_interface(DispatchEx*,REFIID); void HTMLDOMNode_destructor(DispatchEx*); void HTMLDOMNode_traverse(DispatchEx*,nsCycleCollectionTraversalCallback*); void HTMLDOMNode_unlink(DispatchEx*);