[PATCH 4/9] mshtml: Use builtin hooks even when calling function dispatch objects.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Dec 3 07:57:37 CST 2021


This fixes a discrepancy between builtins called via a function dispatch
object and others.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/mshtml/dispex.c              | 37 ++++++++++++++++++++-----------
 dlls/mshtml/htmlelem.c            |  7 +++---
 dlls/mshtml/htmlevent.c           | 10 ++++-----
 dlls/mshtml/mshtml_private.h      |  6 +++--
 dlls/mshtml/tests/documentmode.js | 14 +++++++++++-
 dlls/mshtml/xmlhttprequest.c      |  5 ++---
 6 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 9f56a56..4ba00f8 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -49,7 +49,7 @@ typedef struct {
     VARIANT default_value;
 } func_arg_info_t;
 
-typedef struct {
+struct func_info_t {
     DISPID id;
     BSTR name;
     tid_t tid;
@@ -63,7 +63,7 @@ typedef struct {
     VARTYPE prop_vt;
     VARTYPE *arg_types;
     func_arg_info_t *arg_info;
-} func_info_t;
+};
 
 struct dispex_data_t {
     dispex_static_data_t *desc;
@@ -837,6 +837,11 @@ static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPAR
     case DISPATCH_METHOD:
         if(!This->obj)
             return E_UNEXPECTED;
+        if(This->info->hook) {
+            hres = This->info->hook(This->obj, This->info, lcid, flags, params, res, ei, caller);
+            if(hres != S_FALSE)
+                break;
+        }
         hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
         break;
     case DISPATCH_PROPERTYGET: {
@@ -1163,13 +1168,17 @@ 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)
+HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, WORD flags, 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->call_vtbl_off)
+        return typeinfo_invoke(This, func, flags, dp, res, ei);
+
     if(dp->cNamedArgs) {
         FIXME("Named arguments not supported\n");
         return E_NOTIMPL;
@@ -1265,8 +1274,8 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP
     return V_ERROR(&vhres);
 }
 
-static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
-        EXCEPINFO *ei, IServiceProvider *caller)
+static HRESULT function_invoke(DispatchEx *This, func_info_t *func, LCID lcid, WORD flags, DISPPARAMS *dp,
+        VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
 {
     HRESULT hres;
 
@@ -1296,10 +1305,12 @@ 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);
+        if(func->hook) {
+            hres = func->hook(This, func, lcid, flags, dp, res, ei, caller);
+            if(hres != S_FALSE)
+                break;
+        }
+        hres = invoke_builtin_function(This, func, flags, dp, res, ei, caller);
         break;
     case DISPATCH_PROPERTYGET: {
         func_obj_entry_t *entry;
@@ -1364,15 +1375,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, lcid, flags, dp, res, ei, caller);
+
     if(func->hook) {
-        hres = func->hook(This, lcid, flags, dp, res, ei, caller);
+        hres = func->hook(This, func, lcid, 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)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index a205728..5b14550 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -6643,8 +6643,8 @@ 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,
-        VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+static HRESULT IHTMLElement6_setAttribute_hook(DispatchEx *dispex, func_info_t *func, LCID lcid, WORD flags,
+        DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
 {
     VARIANT args[2];
     HRESULT hres;
@@ -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 = invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller);
     VariantClear(&args[0]);
     return hres;
 }
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 3f545bb..653aed3 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, func_info_t *func, LCID lcid, 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 invoke_builtin_function(dispex, func, flags, &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, func_info_t *func, LCID lcid, 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 invoke_builtin_function(dispex, func, flags, &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 6978ed7..e18db4b 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -312,6 +312,7 @@ extern const compat_mode_info_t compat_mode_info[COMPAT_MODE_CNT] DECLSPEC_HIDDE
 
 typedef struct dispex_data_t dispex_data_t;
 typedef struct dispex_dynamic_data_t dispex_dynamic_data_t;
+typedef struct func_info_t func_info_t;
 
 #define MSHTML_DISPID_CUSTOM_MIN 0x60000000
 #define MSHTML_DISPID_CUSTOM_MAX 0x6fffffff
@@ -337,8 +338,8 @@ typedef struct {
     dispex_data_t *delayed_init_info;
 } dispex_static_data_t;
 
-typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,
-                                        EXCEPINFO*,IServiceProvider*);
+typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,func_info_t*,LCID,WORD,DISPPARAMS*,
+                                        VARIANT*,EXCEPINFO*,IServiceProvider*);
 
 typedef struct {
     DISPID dispid;
@@ -387,6 +388,7 @@ BOOL dispex_query_interface(DispatchEx*,REFIID,void**) DECLSPEC_HIDDEN;
 HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*) DECLSPEC_HIDDEN;
 HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**) DECLSPEC_HIDDEN;
 HRESULT get_dispids(tid_t,DWORD*,DISPID**) DECLSPEC_HIDDEN;
+HRESULT invoke_builtin_function(DispatchEx*,func_info_t*,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*) DECLSPEC_HIDDEN;
 HRESULT remove_attribute(DispatchEx*,DISPID,VARIANT_BOOL*) DECLSPEC_HIDDEN;
 HRESULT dispex_get_dynid(DispatchEx*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;
 void dispex_traverse(DispatchEx*,nsCycleCollectionTraversalCallback*) DECLSPEC_HIDDEN;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 6555e8b..2af5fae 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 56e18d0..f28d9c3 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, func_info_t *func, LCID lcid, 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 invoke_builtin_function(dispex, func, flags, &new_dp, res, ei, caller);
     }
 
     return S_FALSE; /* fallback to default */
-- 
2.31.1




More information about the wine-devel mailing list