Module: wine
Branch: master
Commit: a3dbd5067b4cad48e63b68d17d1598284e05d376
URL:
https://gitlab.winehq.org/wine/wine/-/commit/a3dbd5067b4cad48e63b68d17d1598…
Author: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Date: Mon Oct 31 18:27:37 2022 +0200
mshtml: Allow null or undefined listeners in attachEvent/detachEvent.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/mshtml/dispex.c | 11 ++++++-
dlls/mshtml/htmlevent.c | 5 +++
dlls/mshtml/tests/script.c | 77 +++++++++++++++++++++++++++++++++++++++-------
3 files changed, 81 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index ebb1a675d91..d8aaf819f58 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -1072,7 +1072,8 @@ HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt,
IServiceProvider *ca
if(SUCCEEDED(hres)) {
hres = IVariantChangeType_ChangeType(change_type, dst, src, LOCALE_NEUTRAL,
vt);
IVariantChangeType_Release(change_type);
- return hres;
+ if(SUCCEEDED(hres))
+ return S_OK;
}
}
@@ -1084,6 +1085,14 @@ HRESULT change_type(VARIANT *dst, VARIANT *src, VARTYPE vt,
IServiceProvider *ca
return S_OK;
}
break;
+ case VT_UNKNOWN:
+ case VT_DISPATCH:
+ if(V_VT(src) == VT_EMPTY || V_VT(src) == VT_NULL) {
+ V_VT(dst) = vt;
+ V_DISPATCH(dst) = NULL;
+ return S_OK;
+ }
+ break;
}
return VariantChangeType(dst, src, 0, vt);
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 581d949a447..ebedff82564 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -3870,6 +3870,11 @@ HRESULT attach_event(EventTarget *event_target, BSTR name,
IDispatch *disp, VARI
event_listener_t *listener;
eventid_t eid;
+ if(!disp) {
+ *res = VARIANT_FALSE;
+ return S_OK;
+ }
+
eid = attr_to_eid(name);
if(eid == EVENTID_LAST) {
WARN("Unknown event\n");
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index 14e3a148239..6762cd985d0 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -135,7 +135,8 @@ DEFINE_EXPECT(external_success);
DEFINE_EXPECT(QS_VariantConversion);
DEFINE_EXPECT(QS_IActiveScriptSite);
DEFINE_EXPECT(QS_GetCaller);
-DEFINE_EXPECT(ChangeType);
+DEFINE_EXPECT(ChangeType_bstr);
+DEFINE_EXPECT(ChangeType_dispatch);
DEFINE_EXPECT(GetTypeInfo);
#define TESTSCRIPT_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80746}"
@@ -364,18 +365,29 @@ static ULONG WINAPI VariantChangeType_Release(IVariantChangeType
*iface)
static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT
*dst, VARIANT *src, LCID lcid, VARTYPE vt)
{
- CHECK_EXPECT(ChangeType);
-
ok(dst != NULL, "dst = NULL\n");
ok(V_VT(dst) == VT_EMPTY, "V_VT(dst) = %d\n", V_VT(dst));
ok(src != NULL, "src = NULL\n");
- ok(V_VT(src) == VT_I4, "V_VT(src) = %d\n", V_VT(src));
- ok(V_I4(src) == 0xf0f0f0, "V_I4(src) = %lx\n", V_I4(src));
ok(lcid == LOCALE_NEUTRAL, "lcid = %ld\n", lcid);
- ok(vt == VT_BSTR, "vt = %d\n", vt);
- V_VT(dst) = VT_BSTR;
- V_BSTR(dst) = SysAllocString(L"red");
+ switch(vt) {
+ case VT_BSTR:
+ CHECK_EXPECT(ChangeType_bstr);
+ ok(V_VT(src) == VT_I4, "V_VT(src) = %d\n", V_VT(src));
+ ok(V_I4(src) == 0xf0f0f0, "V_I4(src) = %lx\n", V_I4(src));
+ V_VT(dst) = VT_BSTR;
+ V_BSTR(dst) = SysAllocString(L"red");
+ break;
+ case VT_DISPATCH:
+ CHECK_EXPECT(ChangeType_dispatch);
+ ok(V_VT(src) == VT_NULL, "V_VT(src) = %d\n", V_VT(src));
+ /* native jscript returns E_NOTIMPL, use a "valid" error to test that
it doesn't matter */
+ return E_OUTOFMEMORY;
+ default:
+ ok(0, "unexpected vt %d\n", vt);
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
@@ -2292,10 +2304,13 @@ static void test_global_id(void)
static void test_arg_conv(IHTMLWindow2 *window)
{
+ DISPPARAMS dp = { 0 };
IHTMLDocument2 *doc;
IDispatchEx *dispex;
IHTMLElement *elem;
- VARIANT v;
+ VARIANT v, args[2];
+ DISPID id;
+ BSTR bstr;
HRESULT hres;
hres = IHTMLWindow2_get_document(window, &doc);
@@ -2310,20 +2325,60 @@ static void test_arg_conv(IHTMLWindow2 *window)
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
SET_EXPECT(QS_VariantConversion);
- SET_EXPECT(ChangeType);
+ SET_EXPECT(ChangeType_bstr);
V_VT(&v) = VT_I4;
V_I4(&v) = 0xf0f0f0;
hres = dispex_propput(dispex, DISPID_IHTMLBODYELEMENT_BACKGROUND, 0, &v,
&caller_sp);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
CHECK_CALLED(QS_VariantConversion);
- CHECK_CALLED(ChangeType);
+ CHECK_CALLED(ChangeType_bstr);
V_VT(&v) = VT_EMPTY;
hres = dispex_propget(dispex, DISPID_IHTMLBODYELEMENT_BGCOLOR, &v,
&caller_sp);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_BSTR, "V_VT(var)=%d\n", V_VT(&v));
ok(!V_BSTR(&v), "V_BSTR(&var) = %s\n",
wine_dbgstr_w(V_BSTR(&v)));
+ IDispatchEx_Release(dispex);
+
+ hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx,
(void**)&dispex);
+ ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
+
+ SET_EXPECT(GetScriptDispatch);
+ bstr = SysAllocString(L"attachEvent");
+ hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ CHECK_CALLED(GetScriptDispatch);
+ SysFreeString(bstr);
+
+ SET_EXPECT(QS_VariantConversion);
+ SET_EXPECT(ChangeType_dispatch);
+ dp.cArgs = 2;
+ dp.rgvarg = args;
+ V_VT(&args[1]) = VT_BSTR;
+ V_BSTR(&args[1]) = SysAllocString(L"onload");
+ V_VT(&args[0]) = VT_NULL;
+ hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, DISPATCH_METHOD, &dp,
&v, NULL, &caller_sp);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_BOOL, "V_VT(var) = %d\n", V_VT(&v));
+ ok(V_BOOL(&v) == VARIANT_FALSE, "V_BOOL(var) = %d\n",
V_BOOL(&v));
+ CHECK_CALLED(QS_VariantConversion);
+ CHECK_CALLED(ChangeType_dispatch);
+
+ SET_EXPECT(GetScriptDispatch);
+ bstr = SysAllocString(L"detachEvent");
+ hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ CHECK_CALLED(GetScriptDispatch);
+ SysFreeString(bstr);
+
+ SET_EXPECT(QS_VariantConversion);
+ SET_EXPECT(ChangeType_dispatch);
+ hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, DISPATCH_METHOD, &dp,
NULL, NULL, &caller_sp);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ CHECK_CALLED(QS_VariantConversion);
+ CHECK_CALLED(ChangeType_dispatch);
+ SysFreeString(V_BSTR(&args[1]));
IDispatchEx_Release(dispex);
}