Gabriel Ivăncescu : mshtml: Implement window.setTimeout with a hook.

Alexandre Julliard julliard at winehq.org
Sat Aug 13 14:19:16 CDT 2022


Module: wine
Branch: master
Commit: 8dbdded67366fce7e1e459570d99e90a72cf52cd
URL:    https://gitlab.winehq.org/wine/wine/-/commit/8dbdded67366fce7e1e459570d99e90a72cf52cd

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Fri Aug 12 17:07:29 2022 +0300

mshtml: Implement window.setTimeout with a hook.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>

---

 dlls/mshtml/htmlwindow.c   | 56 ++++++++++++++++++++++------------------------
 dlls/mshtml/tests/events.c | 26 ++++++++++++++++++++-
 2 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index c3267e1e4ca..0043fb79731 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -3614,34 +3614,7 @@ static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID
         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
 {
     HTMLWindow *This = impl_from_IDispatchEx(iface);
-    HTMLInnerWindow *window = This->inner_window;
-
-    TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
-
-    switch(id) {
-    case DISPID_IHTMLWINDOW2_SETTIMEOUT:
-    case DISPID_IHTMLWINDOW3_SETTIMEOUT: {
-        VARIANT args[2];
-        DISPPARAMS dp = {args, NULL, 2, 0};
-
-        /*
-         * setTimeout calls should use default value 0 for the second argument if only one is provided,
-         * but IDL file does not reflect that. We fixup arguments here instead.
-         */
-        if(!(wFlags & DISPATCH_METHOD) || pdp->cArgs != 1 || pdp->cNamedArgs)
-            break;
-
-        TRACE("Fixing args\n");
-
-        V_VT(args) = VT_I4;
-        V_I4(args) = 0;
-        args[1] = *pdp->rgvarg;
-        return IDispatchEx_InvokeEx(&window->event_target.dispex.IDispatchEx_iface, id, lcid,
-                wFlags, &dp, pvarRes, pei, pspCaller);
-    }
-    }
-
-    return IDispatchEx_InvokeEx(&window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
+    return IDispatchEx_InvokeEx(&This->inner_window->event_target.dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
 }
 
 static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
@@ -3915,12 +3888,37 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
     return hres;
 }
 
+static HRESULT IHTMLWindow3_setTimeout_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res,
+        EXCEPINFO *ei, IServiceProvider *caller)
+{
+    VARIANT args[2];
+    DISPPARAMS new_dp = { args, NULL, 2, 0 };
+
+    /*
+     * setTimeout calls should use default value 0 for the second argument if only one is provided,
+     * but IDL file does not reflect that. We fixup arguments here instead.
+     */
+    if(!(flags & DISPATCH_METHOD) || dp->cArgs != 1 || dp->cNamedArgs)
+        return S_FALSE;
+
+    TRACE("Fixing args\n");
+
+    V_VT(args) = VT_I4;
+    V_I4(args) = 0;
+    args[1] = dp->rgvarg[0];
+    return dispex_call_builtin(dispex, DISPID_IHTMLWINDOW3_SETTIMEOUT, &new_dp, res, ei, caller);
+}
+
 static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
 {
     static const dispex_hook_t window2_hooks[] = {
         {DISPID_IHTMLWINDOW2_LOCATION, IHTMLWindow2_location_hook},
         {DISPID_UNKNOWN}
     };
+    static const dispex_hook_t window3_hooks[] = {
+        {DISPID_IHTMLWINDOW3_SETTIMEOUT, IHTMLWindow3_setTimeout_hook},
+        {DISPID_UNKNOWN}
+    };
 
     if(compat_mode >= COMPAT_MODE_IE9)
         dispex_info_add_interface(info, IHTMLWindow7_tid, NULL);
@@ -3930,7 +3928,7 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa
         dispex_info_add_interface(info, IWineHTMLWindowPrivate_tid, NULL);
 
     dispex_info_add_interface(info, IHTMLWindow5_tid, NULL);
-    dispex_info_add_interface(info, IHTMLWindow3_tid, NULL);
+    dispex_info_add_interface(info, IHTMLWindow3_tid, window3_hooks);
     dispex_info_add_interface(info, IHTMLWindow2_tid, window2_hooks);
     EventTarget_init_dispex_info(info, compat_mode);
 }
diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c
index 95ed071bf78..c5210e721d2 100644
--- a/dlls/mshtml/tests/events.c
+++ b/dlls/mshtml/tests/events.c
@@ -2523,11 +2523,35 @@ static void test_submit(IHTMLDocument2 *doc)
 
 static void test_timeout(IHTMLDocument2 *doc)
 {
+    VARIANT expr, var, args[2];
+    DISPPARAMS dp = { args, NULL, 2, 0 };
     IHTMLWindow3 *win3;
-    VARIANT expr, var;
+    IDispatch *disp;
+    UINT argerr;
     LONG id;
     HRESULT hres;
 
+    /* First try the IHTMLWindow2 DISPIDs via IDispatch, since they're not exposed */
+    hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatch, (void**)&disp);
+    ok(hres == S_OK, "Could not get IDispatch iface: %08lx\n", hres);
+
+    V_VT(&args[1]) = VT_BSTR;
+    V_BSTR(&args[1]) = SysAllocString(L"");
+    V_VT(&args[0]) = VT_I4;
+    V_I4(&args[0]) = 1;
+    V_VT(&var) = VT_EMPTY;
+    hres = IDispatch_Invoke(disp, DISPID_IHTMLWINDOW2_SETINTERVAL, &IID_NULL, LOCALE_USER_DEFAULT,
+                            DISPATCH_METHOD, &dp, &var, NULL, &argerr);
+    todo_wine
+    ok(hres == DISP_E_MEMBERNOTFOUND, "Invoke(DISPID_IHTMLWINDOW2_SETINTERVAL) returned: %08lx\n", hres);
+
+    hres = IDispatch_Invoke(disp, DISPID_IHTMLWINDOW2_SETTIMEOUT, &IID_NULL, LOCALE_USER_DEFAULT,
+                            DISPATCH_METHOD, &dp, &var, NULL, &argerr);
+    todo_wine
+    ok(hres == DISP_E_MEMBERNOTFOUND, "Invoke(DISPID_IHTMLWINDOW2_SETTIMEOUT) returned: %08lx\n", hres);
+    SysFreeString(V_BSTR(&args[1]));
+    IDispatch_Release(disp);
+
     hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow3, (void**)&win3);
     ok(hres == S_OK, "Could not get IHTMLWindow3 iface: %08lx\n", hres);
 




More information about the wine-cvs mailing list