From cc0f443088863760e3a879e960d19a835f8ffa95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Mon, 14 Nov 2022 19:53:27 +0200 Subject: [PATCH] mshtml: Handle cNames > 1 in GetIDsOfNames properly. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Native ignores any cNames > 1 and doesn't even fill the dispids for them. Note that it was already wrong; the multiple dispids are supposed to correspond to the member's argument names, not extra dispids. Signed-off-by: Gabriel Ivăncescu --- dlls/mshtml/dispex.c | 13 ++-- dlls/mshtml/htmlwindow.c | 12 ++-- dlls/mshtml/tests/dom.c | 101 +++++++++++++++++++++++++++++ dlls/mshtml/tests/xmlhttprequest.c | 31 +++++++++ 4 files changed, 142 insertions(+), 15 deletions(-) diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index d8aaf819f58..c70deb67209 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1636,19 +1636,16 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LCID lcid, DISPID *rgDispId) { DispatchEx *This = impl_from_IDispatchEx(iface); - UINT i; - HRESULT hres; + HRESULT hres = S_OK; TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); - for(i=0; i < cNames; i++) { - hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i); - if(FAILED(hres)) - return hres; - } + /* Native ignores all cNames > 1, and doesn't even fill them */ + if(cNames) + hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId); - return S_OK; + return hres; } static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 7014a4cd4b4..c2475afd1f6 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3476,19 +3476,17 @@ static HRESULT WINAPI WindowDispEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid LCID lcid, DISPID *rgDispId) { HTMLWindow *This = impl_from_IDispatchEx(iface); - UINT i; - HRESULT hres; + HRESULT hres = S_OK; WARN("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); - for(i=0; i < cNames; i++) { + /* Native ignores all cNames > 1, and doesn't even fill them */ + if(cNames) { /* We shouldn't use script's IDispatchEx here, so we shouldn't use GetDispID */ - hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i); - if(FAILED(hres)) - return hres; + hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId); } - return S_OK; + return hres; } static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index c31de136cd8..4e6ad469b28 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -27,6 +27,7 @@ #include "ole2.h" #include "mshtml.h" #include "mshtmcid.h" +#include "mshtmdid.h" #include "mshtmhst.h" #include "docobj.h" #include "hlink.h" @@ -5288,6 +5289,98 @@ static void _test_doc_set_title(unsigned line, IHTMLDocument2 *doc, const WCHAR SysFreeString(tmp); } +static void test_doc_GetIDsOfNames(IHTMLDocument2 *doc) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"createStyleSheet"); + bstr[1] = SysAllocString(L"bstrHref"); + bstr[2] = SysAllocString(L"lIndex"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLDOCUMENT2_CREATESTYLESHEET, "createStyleSheet dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "bstrHref dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "lIndex dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_window_GetIDsOfNames(IHTMLWindow2 *window) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"showHelp"); + bstr[1] = SysAllocString(L"helpURL"); + bstr[2] = SysAllocString(L"helpArg"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLWindow2_GetIDsOfNames(window, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLWINDOW2_SHOWHELP, "showHelp dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "helpURL dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "helpArg dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_elem_GetIDsOfNames(IHTMLElement *elem) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + /* IE9+ use something like js proxies even on native and have different dispids */ + if(compat_mode >= COMPAT_IE9) + return; + + bstr[0] = SysAllocString(L"insertAdjacentText"); + bstr[1] = SysAllocString(L"where"); + bstr[2] = SysAllocString(L"text"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLElement_GetIDsOfNames(elem, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLELEMENT_INSERTADJACENTTEXT, "insertAdjacentText dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "where dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "text dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_attr_GetIDsOfNames(IHTMLDOMAttribute *attr) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"insertBefore"); + bstr[1] = SysAllocString(L"newChild"); + bstr[2] = SysAllocString(L"refChild"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLDOMAttribute_GetIDsOfNames(attr, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLDOMATTRIBUTE2_INSERTBEFORE, "insertBefore dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "newChild dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "refChild dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + static void test_elem_bounding_client_rect(IUnknown *unk) { IHTMLRectCollection *rects; @@ -5462,6 +5555,7 @@ static IHTMLElement *get_elem_by_id(IHTMLDocument2 *doc, const WCHAR *id, BOOL e elem = get_elem_iface((IUnknown*)disp); IDispatch_Release(disp); + test_elem_GetIDsOfNames(elem); return elem; } @@ -5482,6 +5576,8 @@ static IHTMLElement *get_doc_elem_by_id(IHTMLDocument2 *doc, const WCHAR *id) IHTMLDocument3_Release(doc3); + if(elem) + test_elem_GetIDsOfNames(elem); return elem; } @@ -6854,6 +6950,8 @@ static void test_doc_elem(IHTMLDocument2 *doc) HRESULT hres; BSTR bstr; + test_doc_GetIDsOfNames(doc); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08lx\n", hres); @@ -6875,6 +6973,7 @@ static void test_doc_elem(IHTMLDocument2 *doc) owner_doc = get_owner_doc((IUnknown*)elem); ok(iface_cmp((IUnknown *)doc_node, (IUnknown *)owner_doc), "doc_node != owner_doc\n"); IHTMLDocument2_Release(owner_doc); + test_doc_GetIDsOfNames(doc_node); owner_doc = get_owner_doc((IUnknown*)doc_node); ok(!owner_doc, "owner_doc = %p\n", owner_doc); @@ -7158,6 +7257,7 @@ static void test_window(IHTMLDocument2 *doc) win_skip("IID_ITravelLogClient not supported\n"); test_disp((IUnknown*)window, &DIID_DispHTMLWindow2, &CLSID_HTMLWindow2, L"[object]"); + test_window_GetIDsOfNames(window); hres = IHTMLWindow2_get_document(window, &doc2); ok(hres == S_OK, "get_document failed: %08lx\n", hres); @@ -9796,6 +9896,7 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) test_no_iface((IUnknown*)attr, &IID_IHTMLDOMNode); test_attr_specified(attr, VARIANT_TRUE); test_attr_parent(attr); + test_attr_GetIDsOfNames(attr); attr2 = get_elem_attr_node((IUnknown*)elem, L"id", TRUE); ok(iface_cmp((IUnknown*)attr, (IUnknown*)attr2), "attr != attr2\n"); diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 6aef9f5a35d..a3ec54ffef6 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -25,6 +25,7 @@ #include "winbase.h" #include "ole2.h" #include "mshtml.h" +#include "mshtmdid.h" #include "objsafe.h" #include "wine/test.h" @@ -402,6 +403,35 @@ static void create_xmlhttprequest(IHTMLDocument2 *doc) ok(xhr != NULL, "xhr == NULL\n"); } +static void test_GetIDsOfNames(IHTMLDocument2 *doc) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + create_xmlhttprequest(doc); + if(!xhr) + return; + + bstr[0] = SysAllocString(L"open"); + bstr[1] = SysAllocString(L"bstrMethod"); + bstr[2] = SysAllocString(L"varAsync"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLXMLHttpRequest_GetIDsOfNames(xhr, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLXMLHTTPREQUEST_OPEN, "open dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "bstrMethod dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "varAsync dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); + + IHTMLXMLHttpRequest_Release(xhr); + xhr = NULL; +} + static void test_header(const struct HEADER_TYPE expect[], int num) { int i; @@ -1100,6 +1130,7 @@ START_TEST(xmlhttprequest) content_type = SysAllocString(L"Content-Type"); doc = create_doc_from_url(start_url); if(doc) { + test_GetIDsOfNames(doc); test_sync_xhr(doc, xml_url, expect_response_text); test_sync_xhr(doc, large_page_url, NULL); test_async_xhr(doc, xml_url, expect_response_text);