From: Jacek Caban jacek@codeweavers.com
--- dlls/mshtml/dispex.c | 9 +++++++++ dlls/mshtml/htmlevent.c | 19 +++++++------------ dlls/mshtml/htmlevent.h | 1 - dlls/mshtml/htmlwindow.c | 13 ++++++++++--- dlls/mshtml/mshtml_private.h | 4 ++++ 5 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index c34ff889b11..61c86ec47df 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -745,6 +745,15 @@ HRESULT dispex_get_dynid(DispatchEx *This, const WCHAR *name, BOOL hidden, DISPI return S_OK; }
+IWineJSDispatchHost *dispex_outer_iface(DispatchEx *dispex) +{ + if(dispex->info->desc->vtbl->get_outer_iface) + return dispex->info->desc->vtbl->get_outer_iface(dispex); + + IWineJSDispatchHost_AddRef(&dispex->IWineJSDispatchHost_iface); + return &dispex->IWineJSDispatchHost_iface; +} + static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 6eed0916117..8125a3eebc8 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -321,12 +321,13 @@ static void remove_event_listener(EventTarget *event_target, const WCHAR *type_n
static IEventTarget *get_event_target_iface(EventTarget *event_target) { - const event_target_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex); + const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex); IEventTarget *ret;
- if(vtbl->get_dispatch_this) { - IDispatch *disp = vtbl->get_dispatch_this(&event_target->dispex); - IDispatch_QueryInterface(disp, &IID_IEventTarget, (void**)&ret); + if(vtbl->get_outer_iface) { + IWineJSDispatchHost *disp = vtbl->get_outer_iface(&event_target->dispex); + IWineJSDispatchHost_QueryInterface(disp, &IID_IEventTarget, (void**)&ret); + IWineJSDispatchHost_Release(disp); }else { ret = &event_target->IEventTarget_iface; IEventTarget_AddRef(ret); @@ -4191,11 +4192,8 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp skip_onevent_listener = TRUE;
V_VT(&arg) = VT_DISPATCH; - V_DISPATCH(&arg) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface; + V_DISPATCH(&arg) = (IDispatch*)dispex_outer_iface(&event_target->dispex); V_VT(&v) = VT_EMPTY; - if(vtbl->get_dispatch_this) - V_DISPATCH(&arg) = vtbl->get_dispatch_this(&event_target->dispex); - IDispatch_AddRef(V_DISPATCH(&arg));
TRACE("%p %s >>>\n", event_target, debugstr_w(event->type)); hres = call_disp_func(listener->function, &dp, &v); @@ -4272,10 +4270,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp DISPPARAMS dp = {args, &named_arg, 2, 1};
V_VT(args) = VT_DISPATCH; - V_DISPATCH(args) = (IDispatch*)&event_target->dispex.IWineJSDispatchHost_iface; - if(vtbl->get_dispatch_this) - V_DISPATCH(args) = vtbl->get_dispatch_this(&event_target->dispex); - IDispatch_AddRef(V_DISPATCH(args)); + V_DISPATCH(args) = (IDispatch *)dispex_outer_iface(&event_target->dispex);
V_VT(args+1) = VT_DISPATCH; V_DISPATCH(args+1) = dispatch_mode == DISPATCH_LEGACY diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index 324f39ea746..6dec8cf9a9a 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -127,7 +127,6 @@ void detach_nsevent(HTMLDocumentNode*,const WCHAR*); /* We extend dispex vtbl for EventTarget functions to avoid separated vtbl. */ typedef struct { dispex_static_data_vtbl_t dispex_vtbl; - IDispatch *(*get_dispatch_this)(DispatchEx*); nsISupports *(*get_gecko_target)(DispatchEx*); void (*bind_event)(DispatchEx*,eventid_t); EventTarget *(*get_parent_event_target)(DispatchEx*); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index a7a6b0df383..534a0bae9d2 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3970,10 +3970,17 @@ static compat_mode_t HTMLWindow_get_compat_mode(DispatchEx *dispex, HTMLInnerWin return lock_document_mode(This->doc); }
-static IDispatch *HTMLWindow_get_dispatch_this(DispatchEx *dispex) +static IWineJSDispatchHost *HTMLWindow_get_outer_iface(DispatchEx *dispex) { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); - return (IDispatch*)&This->base.outer_window->base.IHTMLWindow2_iface; + IWineJSDispatchHost *ret; + + if(This->base.outer_window) + ret = &This->base.outer_window->IWineJSDispatchHost_iface; + else + ret = &This->event_target.dispex.IWineJSDispatchHost_iface; + IWineJSDispatchHost_AddRef(ret); + return ret; }
static nsISupports *HTMLWindow_get_gecko_target(DispatchEx *dispex) @@ -4152,8 +4159,8 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { .invoke = HTMLWindow_invoke, .next_dispid = HTMLWindow_next_dispid, .get_compat_mode = HTMLWindow_get_compat_mode, + .get_outer_iface = HTMLWindow_get_outer_iface, }, - .get_dispatch_this = HTMLWindow_get_dispatch_this, .get_gecko_target = HTMLWindow_get_gecko_target, .bind_event = HTMLWindow_bind_event, .set_current_event = HTMLWindow_set_current_event diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 9d84cbabe55..2952149d881 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -375,6 +375,9 @@ typedef struct { /* Called on the last release, when the refcount reaches 0 */ void (*last_release)(DispatchEx*);
+ /* Called to get outer interface when it may be different than DispatchEx */ + IWineJSDispatchHost *(*get_outer_iface)(DispatchEx*); + /* Called when the object wants to handle DISPID_VALUE invocations */ HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
@@ -517,6 +520,7 @@ HRESULT dispex_get_id(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, DISPID *ret); HRESULT dispex_prop_name(DispatchEx *dispex, DISPID id, BSTR *ret); HRESULT dispex_index_prop_desc(DispatchEx*,DISPID,struct property_info*); +IWineJSDispatchHost *dispex_outer_iface(DispatchEx *dispex);
typedef enum { DISPEXPROP_CUSTOM,