From b650e768bea8a2fc855c005ef6c9bce0c9131dc6 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 10 Dec 2021 20:36:49 +0100 Subject: [PATCH] mshtml: Fix dispex hooks handling for function objects. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on patch by Gabriel Ivăncescu. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/mshtml/dispex.c | 40 +++++++++++++++++++++++-------- dlls/mshtml/htmlelem.c | 5 ++-- dlls/mshtml/htmlevent.c | 10 ++++---- dlls/mshtml/mshtml_private.h | 4 +++- dlls/mshtml/tests/documentmode.js | 14 ++++++++++- dlls/mshtml/xmlhttprequest.c | 5 ++-- 6 files changed, 54 insertions(+), 24 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index b7bc75104ad..2fff4d444b2 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -842,7 +842,7 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR case DISPATCH_METHOD: if(!This->obj) return E_UNEXPECTED; - hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); + hres = dispex_call_builtin(This->obj, This->info->id, params, res, ei, caller); break; case DISPATCH_PROPERTYGET: { unsigned name_len; @@ -1168,13 +1168,23 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * return hres; } -static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, VARIANT *res, IServiceProvider *caller) +static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { VARIANT arg_buf[MAX_ARGS], *arg_ptrs[MAX_ARGS], *arg, retv, ret_ref, vhres; unsigned i, nconv = 0; IUnknown *iface; HRESULT hres; + if(func->hook) { + hres = func->hook(This, DISPATCH_METHOD, dp, res, ei, caller); + if(hres != S_FALSE) + return hres; + } + + if(!func->call_vtbl_off) + return typeinfo_invoke(This, func, DISPATCH_METHOD, dp, res, ei); + if(dp->cArgs + func->default_value_cnt < func->argc) { FIXME("Invalid argument count (expected %u, got %u)\n", func->argc, dp->cArgs); return E_INVALIDARG; @@ -1296,10 +1306,7 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, } } - if(func->call_vtbl_off) - hres = invoke_builtin_function(This, func, dp, res, caller); - else - hres = typeinfo_invoke(This, func, flags, dp, res, ei); + hres = invoke_builtin_function(This, func, dp, res, ei, caller); break; case DISPATCH_PROPERTYGET: { func_obj_entry_t *entry; @@ -1364,15 +1371,15 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD if(FAILED(hres)) return hres; + if(func->func_disp_idx != -1) + return function_invoke(This, func, flags, dp, res, ei, caller); + if(func->hook) { - hres = func->hook(This, lcid, flags, dp, res, ei, caller); + hres = func->hook(This, flags, dp, res, ei, caller); if(hres != S_FALSE) return hres; } - if(func->func_disp_idx != -1) - return function_invoke(This, func, flags, dp, res, ei, caller); - switch(flags) { case DISPATCH_PROPERTYPUT: if(res) @@ -1412,6 +1419,19 @@ static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD return hres; } +HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + func_info_t *func; + HRESULT hres; + + hres = get_builtin_func(dispex->info, id, &func); + if(FAILED(hres)) + return hres; + + return invoke_builtin_function(dispex, func, dp, res, ei, caller); +} + HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) { switch(get_dispid_type(id)) { diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index a205728e280..2a73c6a2d33 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6643,7 +6643,7 @@ static IHTMLEventObj *HTMLElement_set_current_event(DispatchEx *dispex, IHTMLEve return default_set_current_event(This->node.doc->window, event); } -static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, +static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { VARIANT args[2]; @@ -6667,8 +6667,7 @@ static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, LCID lcid, WO return hres; args[1] = dp->rgvarg[dp->cArgs - 1]; - hres = IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, - lcid, flags, &new_dp, res, ei, caller); + hres = dispex_call_builtin(dispex, DISPID_IHTMLELEMENT6_IE9_SETATTRIBUTE, &new_dp, res, ei, caller); VariantClear(&args[0]); return hres; } diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 3f545bbb3fd..7ed1dfd2adc 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -3314,7 +3314,7 @@ static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent * return dispatch_event_object(This, event, DISPATCH_STANDARD, result); } -static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set capture to false */ @@ -3328,14 +3328,13 @@ static HRESULT IEventTarget_addEventListener_hook(DispatchEx *dispex, LCID lcid, TRACE("implicit capture\n"); - return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IEVENTTARGET_ADDEVENTLISTENER, - lcid, flags, &new_dp, res, ei, caller); + return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_ADDEVENTLISTENER, &new_dp, res, ei, caller); } return S_FALSE; /* fallback to default */ } -static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set capture to false */ @@ -3349,8 +3348,7 @@ static HRESULT IEventTarget_removeEventListener_hook(DispatchEx *dispex, LCID lc TRACE("implicit capture\n"); - return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, - lcid, flags, &new_dp, res, ei, caller); + return dispex_call_builtin(dispex, DISPID_IEVENTTARGET_REMOVEEVENTLISTENER, &new_dp, res, ei, caller); } return S_FALSE; /* fallback to default */ diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 6978ed77c85..7ce97e01053 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -337,7 +337,7 @@ typedef struct { dispex_data_t *delayed_init_info; } dispex_static_data_t; -typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*, +typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,WORD,DISPPARAMS*,VARIANT*, EXCEPINFO*,IServiceProvider*); typedef struct { @@ -397,6 +397,8 @@ const void *dispex_get_vtbl(DispatchEx*) DECLSPEC_HIDDEN; void dispex_info_add_interface(dispex_data_t*,tid_t,const dispex_hook_t*) DECLSPEC_HIDDEN; compat_mode_t dispex_compat_mode(DispatchEx*) DECLSPEC_HIDDEN; HRESULT dispex_to_string(DispatchEx*,BSTR*) DECLSPEC_HIDDEN; +HRESULT dispex_call_builtin(DispatchEx *dispex, DISPID id, DISPPARAMS *dp, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) DECLSPEC_HIDDEN; typedef enum { DISPEXPROP_CUSTOM, diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index af057f2cb3d..6dcda4a8be0 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1166,6 +1166,18 @@ sync_test("elem_attr", function() { r = elem.removeAttribute("testattr"); ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r); ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr); + + var func = elem.setAttribute; + try { + func("testattr", arr); + todo_wine_if(v >= 9). + ok(v < 9, "expected exception setting testattr via func"); + }catch(ex) { + ok(v >= 9, "did not expect exception setting testattr via func"); + elem.setAttribute("testattr", arr); + } + r = elem.getAttribute("testattr"); + ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r); delete arr.valueOf; delete arr.toString; @@ -1177,7 +1189,7 @@ sync_test("elem_attr", function() { ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r); ok(elem.id === "", "removed id = " + elem.id); - var func = function() { }; + func = function() { }; elem.onclick = func; ok(elem.onclick === func, "onclick = " + elem.onclick); r = elem.getAttribute("onclick"); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 56e18d0432e..4cd47acd107 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -475,7 +475,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface) return S_OK; } -static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, LCID lcid, WORD flags, +static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { /* If only two arguments were given, implicitly set async to false */ @@ -491,8 +491,7 @@ static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, LCID lcid, WORD TRACE("implicit async\n"); - return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IHTMLXMLHTTPREQUEST_OPEN, - lcid, flags, &new_dp, res, ei, caller); + return dispex_call_builtin(dispex, DISPID_IHTMLXMLHTTPREQUEST_OPEN, &new_dp, res, ei, caller); } return S_FALSE; /* fallback to default */