From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/oleobj.c | 59 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/dom.c | 18 +++++++++++ 3 files changed, 78 insertions(+)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 7df5c5e8b30..e7f5481b886 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -677,6 +677,7 @@ struct HTMLDocumentObj { IObjectSafety IObjectSafety_iface; IServiceProvider IServiceProvider_iface; ITargetContainer ITargetContainer_iface; + IEventTarget IEventTarget_iface;
IWindowForBindingUI IWindowForBindingUI_iface;
diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index de6fd028218..4044604aae2 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -3238,6 +3238,58 @@ static const IDocumentRangeVtbl DocObjDocumentRangeVtbl = { DocObjDocumentRange_createRange };
+/********************************************************** + * IEventTarget implementation + */ +static inline HTMLDocumentObj *impl_from_IEventTarget(IEventTarget *iface) +{ + return CONTAINING_RECORD(iface, HTMLDocumentObj, IEventTarget_iface); +} + +HTMLDOCUMENTOBJ_IDISPATCH_METHODS(EventTarget) + +static HRESULT WINAPI DocObjEventTarget_addEventListener(IEventTarget *iface, BSTR type, IDispatch *listener, + VARIANT_BOOL capture) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + if(!This->doc_node) + return E_UNEXPECTED; + return IEventTarget_addEventListener(&This->doc_node->node.event_target.IEventTarget_iface, type, listener, capture); +} + +static HRESULT WINAPI DocObjEventTarget_removeEventListener(IEventTarget *iface, BSTR type, IDispatch *listener, + VARIANT_BOOL capture) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + if(!This->doc_node) + return E_UNEXPECTED; + return IEventTarget_removeEventListener(&This->doc_node->node.event_target.IEventTarget_iface, type, listener, capture); +} + +static HRESULT WINAPI DocObjEventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event_iface, VARIANT_BOOL *result) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + if(!This->doc_node) + return E_UNEXPECTED; + return IEventTarget_dispatchEvent(&This->doc_node->node.event_target.IEventTarget_iface, event_iface, result); +} + +static const IEventTargetVtbl DocObjEventTargetVtbl = { + DocObjEventTarget_QueryInterface, + DocObjEventTarget_AddRef, + DocObjEventTarget_Release, + DocObjEventTarget_GetTypeInfoCount, + DocObjEventTarget_GetTypeInfo, + DocObjEventTarget_GetIDsOfNames, + DocObjEventTarget_Invoke, + DocObjEventTarget_addEventListener, + DocObjEventTarget_removeEventListener, + DocObjEventTarget_dispatchEvent +}; + static inline HTMLDocumentObj *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, HTMLDocumentObj, IUnknown_inner); @@ -3339,6 +3391,12 @@ static HRESULT WINAPI HTMLDocumentObj_QueryInterface(IUnknown *iface, REFIID rii *ppv = &This->ITargetContainer_iface; }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { *ppv = &This->cp_container.IConnectionPointContainer_iface; + }else if(IsEqualGUID(&IID_IEventTarget, riid)) { + if(!This->doc_node || dispex_compat_mode(&This->doc_node->node.event_target.dispex) < COMPAT_MODE_IE9) { + *ppv = NULL; + return E_NOINTERFACE; + } + *ppv = &This->IEventTarget_iface; }else if(IsEqualGUID(&CLSID_CMarkup, riid)) { FIXME("(%p)->(CLSID_CMarkup %p)\n", This, ppv); *ppv = NULL; @@ -3734,6 +3792,7 @@ static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID rii doc->IMarkupContainer_iface.lpVtbl = &DocObjMarkupContainerVtbl; doc->IDisplayServices_iface.lpVtbl = &DocObjDisplayServicesVtbl; doc->IDocumentRange_iface.lpVtbl = &DocObjDocumentRangeVtbl; + doc->IEventTarget_iface.lpVtbl = &DocObjEventTargetVtbl;
doc->outer_unk = outer ? outer : &doc->IUnknown_inner;
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 70b047ccbe1..c18eb590cc8 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -10913,6 +10913,22 @@ static void test_docfrag(IHTMLDocument2 *doc) IHTMLDocument2_Release(frag); }
+static void test_doc_obj(IHTMLDocument2 *doc) +{ + IEventTarget *event_target = (void*)0xdeadbeef; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IEventTarget, (void**)&event_target); + if(compat_mode < COMPAT_IE9) { + ok(hres == E_NOINTERFACE, "hres = %08lx, expected E_NOINTERFACE\n", hres); + ok(!event_target, "event_target = %p\n", event_target); + }else { + ok(hres == S_OK, "hres = %08lx, expected S_OK\n", hres); + ok(!!event_target, "event_target = %p\n", event_target); + IEventTarget_Release(event_target); + } +} + static void test_about_blank_storage(IHTMLDocument2 *doc) { IHTMLStorage *storage; @@ -11678,10 +11694,12 @@ START_TEST(dom) if (winetest_interactive || ! is_ie_hardened()) { run_domtest(elem_test_str, test_elems); run_domtest(elem_test2_str, test_elems2); + run_domtest(doc_blank, test_doc_obj); run_domtest(doc_blank, test_dom_elements); run_domtest(doc_blank, test_about_blank_storage); if(is_ie9plus) { compat_mode = COMPAT_IE9; + run_domtest(doc_blank_ie9, test_doc_obj); run_domtest(doc_blank_ie9, test_dom_elements); run_domtest(doc_blank_ie9, test_about_blank_storage); compat_mode = COMPAT_NONE;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/oleobj.c | 11 +---------- dlls/mshtml/tests/dom.c | 8 ++++++++ 2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index 4044604aae2..90a109fcfc0 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -2384,16 +2384,7 @@ HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, put_onbeforeupdate, VARIANT) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, get_onbeforeupdate, VARIANT*) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, put_onerrorupdate, VARIANT) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, get_onerrorupdate, VARIANT*) - -static HRESULT WINAPI DocObjHTMLDocument2_toString(IHTMLDocument2 *iface, BSTR *String) -{ - HTMLDocumentObj *This = impl_from_IHTMLDocument2(iface); - - TRACE("(%p)->(%p)\n", This, String); - - return dispex_to_string(&This->dispex, String); -} - +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, toString, BSTR*) HTMLDOCUMENTOBJ_FWD_TO_NODE_3(HTMLDocument2, createStyleSheet, BSTR,LONG,IHTMLStyleSheet**)
static const IHTMLDocument2Vtbl DocObjHTMLDocument2Vtbl = { diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index c18eb590cc8..7fb12c445ea 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -10917,6 +10917,7 @@ static void test_doc_obj(IHTMLDocument2 *doc) { IEventTarget *event_target = (void*)0xdeadbeef; HRESULT hres; + BSTR bstr;
hres = IHTMLDocument2_QueryInterface(doc, &IID_IEventTarget, (void**)&event_target); if(compat_mode < COMPAT_IE9) { @@ -10927,6 +10928,13 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(!!event_target, "event_target = %p\n", event_target); IEventTarget_Release(event_target); } + + bstr = NULL; + hres = IHTMLDocument2_toString(doc, &bstr); + ok(hres == S_OK, "toString failed: %08lx\n", hres); + todo_wine_if(compat_mode >= COMPAT_IE9) + ok(!wcscmp(bstr, (compat_mode < COMPAT_IE9 ? L"[object]" : L"[object Document]")), "toString returned %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); }
static void test_about_blank_storage(IHTMLDocument2 *doc)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
And get rid of the dispex since it's useless now.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 - dlls/mshtml/oleobj.c | 161 ++++++----------------------------- dlls/mshtml/tests/dom.c | 102 +++++++++++++++++++++- 3 files changed, 125 insertions(+), 139 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e7f5481b886..e3971258b13 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -640,7 +640,6 @@ struct ConnectionPoint { };
struct HTMLDocumentObj { - DispatchEx dispex; IUnknown IUnknown_inner; IDispatchEx IDispatchEx_iface; ICustomDoc ICustomDoc_iface; diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index 90a109fcfc0..1f348ff0f77 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -27,6 +27,7 @@ #include "ole2.h" #include "shlguid.h" #include "shdeprecated.h" +#include "mscoree.h" #include "mshtmdid.h" #include "idispids.h"
@@ -3408,8 +3409,12 @@ static HRESULT WINAPI HTMLDocumentObj_QueryInterface(IUnknown *iface, REFIID rii TRACE("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv); *ppv = NULL; return E_NOINTERFACE; - }else if(dispex_query_interface(&This->dispex, riid, ppv)) { - return *ppv ? S_OK : E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IDispatchJS, riid) || + IsEqualGUID(&IID_UndocumentedScriptIface, riid) || + IsEqualGUID(&IID_IMarshal, riid) || + IsEqualGUID(&IID_IManagedObject, riid)) { + *ppv = NULL; + return E_NOINTERFACE; }else { FIXME("Unimplemented interface %s\n", debugstr_mshtml_guid(riid)); *ppv = NULL; @@ -3470,7 +3475,6 @@ static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface)
remove_target_tasks(This->task_magic); ConnectionPointContainer_Destroy(&This->cp_container); - release_dispex(&This->dispex);
if(This->nscontainer) detach_gecko_browser(This->nscontainer); @@ -3494,117 +3498,40 @@ static inline HTMLDocumentObj *impl_from_IDispatchEx(IDispatchEx *iface) return CONTAINING_RECORD(iface, HTMLDocumentObj, IDispatchEx_iface); }
-static HRESULT WINAPI DocObjDispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_QueryInterface(This->outer_unk, riid, ppv); -} - -static ULONG WINAPI DocObjDispatchEx_AddRef(IDispatchEx *iface) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_AddRef(This->outer_unk); -} - -static ULONG WINAPI DocObjDispatchEx_Release(IDispatchEx *iface) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_Release(This->outer_unk); -} - -static HRESULT WINAPI DocObjDispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); -} - -static HRESULT WINAPI DocObjDispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, - ITypeInfo **ppTInfo) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); -} - -static HRESULT WINAPI DocObjDispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, - UINT cNames, LCID lcid, DISPID *rgDispId) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, lcid, rgDispId); -} +HTMLDOCUMENTOBJ_IUNKNOWN_METHODS(DispatchEx) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, GetTypeInfoCount, UINT*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetTypeInfo, UINT,LCID,ITypeInfo**) +HTMLDOCUMENTOBJ_FWD_TO_NODE_5(DispatchEx, GetIDsOfNames, REFIID,LPOLESTR*,UINT,LCID,DISPID*)
static HRESULT WINAPI DocObjDispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams, + + if(!This->doc_node) + return E_UNEXPECTED; + return IDispatchEx_InvokeEx(&This->doc_node->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL); }
-static HRESULT WINAPI DocObjDispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetDispID(&This->dispex.IDispatchEx_iface, bstrName, grfdex, pid); -} +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetDispID, BSTR,DWORD,DISPID*)
static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
- if(This->window) { - switch(id) { - case DISPID_READYSTATE: - TRACE("DISPID_READYSTATE\n"); - - if(!(wFlags & DISPATCH_PROPERTYGET)) - return E_INVALIDARG; - - V_VT(pvarRes) = VT_I4; - V_I4(pvarRes) = This->window->readystate; - return S_OK; - default: - break; - } - } - - return IDispatchEx_InvokeEx(&This->dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); -} - -static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_DeleteMemberByName(&This->dispex.IDispatchEx_iface, bstrName, grfdex); -} - -static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_DeleteMemberByDispID(&This->dispex.IDispatchEx_iface, id); -} - -static HRESULT WINAPI DocObjDispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetMemberProperties(&This->dispex.IDispatchEx_iface, id, grfdexFetch, pgrfdex); -} - -static HRESULT WINAPI DocObjDispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetMemberName(&This->dispex.IDispatchEx_iface, id, pbstrName); -} - -static HRESULT WINAPI DocObjDispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetNextDispID(&This->dispex.IDispatchEx_iface, grfdex, id, pid); + if(!This->doc_node) + return E_UNEXPECTED; + return IDispatchEx_InvokeEx(&This->doc_node->IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); }
-static HRESULT WINAPI DocObjDispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetNameSpaceParent(&This->dispex.IDispatchEx_iface, ppunk); -} +HTMLDOCUMENTOBJ_FWD_TO_NODE_2(DispatchEx, DeleteMemberByName, BSTR,DWORD) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, DeleteMemberByDispID, DISPID) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetMemberProperties, DISPID,DWORD,DWORD*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_2(DispatchEx, GetMemberName, DISPID,BSTR*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetNextDispID, DWORD,DISPID,DISPID*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, GetNameSpaceParent, IUnknown**)
static const IDispatchExVtbl DocObjDispatchExVtbl = { DocObjDispatchEx_QueryInterface, @@ -3710,43 +3637,6 @@ static const cpc_entry_t HTMLDocumentObj_cpc[] = { {NULL} };
-static HRESULT HTMLDocumentObj_location_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) -{ - HTMLDocumentObj *This = CONTAINING_RECORD(dispex, HTMLDocumentObj, dispex); - - if(!(flags & DISPATCH_PROPERTYPUT) || !This->window) - return S_FALSE; - - return IDispatchEx_InvokeEx(&This->window->base.IDispatchEx_iface, DISPID_IHTMLWINDOW2_LOCATION, - 0, flags, dp, res, ei, caller); -} - -static const tid_t HTMLDocumentObj_iface_tids[] = { - IHTMLDocument3_tid, - IHTMLDocument4_tid, - IHTMLDocument5_tid, - 0 -}; - -static void HTMLDocumentObj_init_dispex_info(dispex_data_t *info, compat_mode_t mode) -{ - static const dispex_hook_t document2_hooks[] = { - {DISPID_IHTMLDOCUMENT2_URL, NULL, L"URL"}, - {DISPID_IHTMLDOCUMENT2_LOCATION, HTMLDocumentObj_location_hook}, - {DISPID_UNKNOWN} - }; - dispex_info_add_interface(info, IHTMLDocument2_tid, document2_hooks); -} - -static dispex_static_data_t HTMLDocumentObj_dispex = { - L"HTMLDocumentObj", - NULL, - DispHTMLDocument_tid, - HTMLDocumentObj_iface_tids, - HTMLDocumentObj_init_dispex_info -}; - static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID riid, void **ppv) { HTMLDocumentObj *doc; @@ -3787,7 +3677,6 @@ static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID rii
doc->outer_unk = outer ? outer : &doc->IUnknown_inner;
- init_dispatch(&doc->dispex, (IUnknown*)&doc->ICustomDoc_iface, &HTMLDocumentObj_dispex, COMPAT_MODE_QUIRKS); ConnectionPointContainer_Init(&doc->cp_container, &doc->IUnknown_inner, HTMLDocumentObj_cpc); HTMLDocumentObj_Persist_Init(doc); HTMLDocumentObj_Service_Init(doc); diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 7fb12c445ea..bb69e3504ea 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -61,6 +61,19 @@ static const char doc_blank_ie9[] = " </body>" "</html>";
+static const char doc_prop[] = + "<html>" + " <body onload="document.prop = 137;"></body>" + "</html>"; + +static const char doc_prop_ie9[] = + "<html>" + " <head>" + " <meta http-equiv="x-ua-compatible" content="IE=9" />" + " </head>" + " <body onload="document.prop = 137;"></body>" + "</html>"; + static const char doc_str1[] = "<html><body>test</body></html>"; static const char elem_test_str[] = "<html><head><title>test</title><style id="styleid">.body { margin-right: 0px; }</style>" @@ -9477,10 +9490,37 @@ static void test_elems(IHTMLDocument2 *doc) elem = get_doc_elem_by_id(doc, L"objid"); ok(elem != NULL, "elem == NULL\n"); if(elem) { + IDispatchEx *dispex = get_dispex_iface((IUnknown*)doc); + DISPPARAMS dp = { 0 }; + DISPID dispid; + VARIANT var; + BSTR name; + test_object_vspace((IUnknown*)elem, 100); test_object_name(elem, L"objname"); + + name = SysAllocString(L"objname"); + hres = IDispatchEx_GetDispID(dispex, name, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID(objname) returned: %08lx\n", hres); + SysFreeString(name); + + hres = IDispatchEx_Invoke(dispex, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok(hres == S_OK, "Invoke(objname) failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "VT = %d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "objname = null\n"); + + elem2 = get_elem_iface((IUnknown*)V_DISPATCH(&var)); + IDispatch_Release(V_DISPATCH(&var)); + + test_object_vspace((IUnknown*)elem2, 100); + test_object_name(elem2, L"objname"); + todo_wine + ok(elem != elem2, "elem == elem2\n"); + IHTMLElement_Release(elem2); + set_object_name(elem, L"test"); set_object_name(elem, NULL); + IDispatchEx_Release(dispex); IHTMLElement_Release(elem); }
@@ -10916,6 +10956,9 @@ static void test_docfrag(IHTMLDocument2 *doc) static void test_doc_obj(IHTMLDocument2 *doc) { IEventTarget *event_target = (void*)0xdeadbeef; + DISPID dispid, has_own_prop_id; + DISPPARAMS dp = { 0 }; + VARIANT res, arg; HRESULT hres; BSTR bstr;
@@ -10935,6 +10978,61 @@ static void test_doc_obj(IHTMLDocument2 *doc) todo_wine_if(compat_mode >= COMPAT_IE9) ok(!wcscmp(bstr, (compat_mode < COMPAT_IE9 ? L"[object]" : L"[object Document]")), "toString returned %s\n", wine_dbgstr_w(bstr)); SysFreeString(bstr); + + /* IHTMLDocument6 prop */ + bstr = SysAllocString(L"onstoragecommit"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(onstoragecommit) returned: %08lx\n", hres); + SysFreeString(bstr); + + /* IHTMLDocument7 method */ + if(is_ie9plus) { + bstr = SysAllocString(L"importNode"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == (compat_mode < COMPAT_IE9 ? DISP_E_UNKNOWNNAME : S_OK), "GetIDsOfNames(importNode) returned: %08lx\n", hres); + SysFreeString(bstr); + } + + /* prop set via script on node */ + bstr = SysAllocString(L"prop"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(prop) returned: %08lx\n", hres); + SysFreeString(bstr); + + hres = IHTMLDocument2_Invoke(doc, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(prop) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_I4, "VT(prop) = %d\n", V_VT(&res)); + ok(V_I4(&res) == 137, "prop = %ld\n", V_I4(&res)); + + /* jscript prop on prototype chain */ + bstr = SysAllocString(L"hasOwnProperty"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &has_own_prop_id); + todo_wine_if(compat_mode >= COMPAT_IE9) + ok(hres == (compat_mode < COMPAT_IE9 ? DISP_E_UNKNOWNNAME : S_OK), "GetIDsOfNames(hasOwnProperty) returned: %08lx\n", hres); + SysFreeString(bstr); + + if(hres == S_OK) { + dp.cArgs = 1; + dp.rgvarg = &arg; + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = SysAllocString(L"createElement"); + hres = IHTMLDocument2_Invoke(doc, has_own_prop_id, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(hasOwnProperty("createElement")) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_BOOL, "VT = %d\n", V_VT(&res)); + todo_wine + ok(V_BOOL(&res) == VARIANT_FALSE, "hasOwnProperty("createElement") = %d\n", V_BOOL(&res)); + + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &V_BSTR(&arg), 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(createElement) returned: %08lx\n", hres); + SysFreeString(V_BSTR(&arg)); + + V_BSTR(&arg) = SysAllocString(L"prop"); + hres = IHTMLDocument2_Invoke(doc, has_own_prop_id, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(hasOwnProperty("prop")) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_BOOL, "VT = %d\n", V_VT(&res)); + ok(V_BOOL(&res) == VARIANT_TRUE, "hasOwnProperty("prop") = %d\n", V_BOOL(&res)); + SysFreeString(V_BSTR(&arg)); + } }
static void test_about_blank_storage(IHTMLDocument2 *doc) @@ -11702,12 +11800,12 @@ START_TEST(dom) if (winetest_interactive || ! is_ie_hardened()) { run_domtest(elem_test_str, test_elems); run_domtest(elem_test2_str, test_elems2); - run_domtest(doc_blank, test_doc_obj); + run_domtest(doc_prop, test_doc_obj); run_domtest(doc_blank, test_dom_elements); run_domtest(doc_blank, test_about_blank_storage); if(is_ie9plus) { compat_mode = COMPAT_IE9; - run_domtest(doc_blank_ie9, test_doc_obj); + run_domtest(doc_prop_ie9, test_doc_obj); run_domtest(doc_blank_ie9, test_dom_elements); run_domtest(doc_blank_ie9, test_about_blank_storage); compat_mode = COMPAT_NONE;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
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 gabrielopcode@gmail.com --- 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 bb69e3504ea..58a4f127399 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" @@ -5301,6 +5302,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; @@ -5475,6 +5568,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; }
@@ -5495,6 +5589,8 @@ static IHTMLElement *get_doc_elem_by_id(IHTMLDocument2 *doc, const WCHAR *id)
IHTMLDocument3_Release(doc3);
+ if(elem) + test_elem_GetIDsOfNames(elem); return elem; }
@@ -6867,6 +6963,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);
@@ -6888,6 +6986,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); @@ -7171,6 +7270,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); @@ -9809,6 +9909,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);
Jacek Caban (@jacek) commented about dlls/mshtml/oleobj.c:
*ppv = &This->ITargetContainer_iface; }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { *ppv = &This->cp_container.IConnectionPointContainer_iface;
- }else if(IsEqualGUID(&IID_IEventTarget, riid)) {
if(!This->doc_node || dispex_compat_mode(&This->doc_node->node.event_target.dispex) < COMPAT_MODE_IE9) {
This breaks COM rule: it's possible that we'd return IEventTarget in one QI call, then navigate to other page and then return failure for QI on the same object. We avoid this problem for document node by locking compat mode, but this won't work here, because doc_node may change as a result of navigation to other page. Do you know if native also breaks those rules? It would be also interesting to know what happens to registered events in this case: if we register an event handler on document object and then document node changes, should those events handlers still work or are they dropped (they will be dropped with this patch)?
On Wed Nov 9 16:36:36 2022 +0000, Jacek Caban wrote:
This breaks COM rule: it's possible that we'd return IEventTarget in one QI call, then navigate to other page and then return failure for QI on the same object. We avoid this problem for document node by locking compat mode, but this won't work here, because doc_node may change as a result of navigation to other page. Do you know if native also breaks those rules? It would be also interesting to know what happens to registered events in this case: if we register an event handler on document object and then document node changes, should those events handlers still work or are they dropped (they will be dropped with this patch)?
Good point, I haven't really tested that, mostly because I don't know how to write a proper test that navigates to a different doc node on same doc obj. Do you have tips or should I just test it "manually"?
On Wed Nov 9 16:48:17 2022 +0000, Gabriel Ivăncescu wrote:
Good point, I haven't really tested that, mostly because I don't know how to write a proper test that navigates to a different doc node on same doc obj. Do you have tips or should I just test it "manually"?
Any navigation (except for fragment-only) should do that, basically every web page has its own document object. You could use document.location.href = "..."; or anything alike. We already have `test_put_href()`, but I'm not sure if it will be convenient as it also tests all embedding API effects of navigation.
On Wed Nov 9 21:43:30 2022 +0000, Jacek Caban wrote:
Any navigation (except for fragment-only) should do that, basically every web page has its own document object. You could use document.location.href = "..."; or anything alike. We already have `test_put_href()`, but I'm not sure if it will be convenient as it also tests all embedding API effects of navigation.
It looks like native IE indeed breaks COM rules here. I moved the tests to `events.c` since we have pluggable protocol handler and we're testing events anyway, but for some reason I couldn't use `put_href`, `replace` or `superNavigate` on native to navigate using the pluggable protocol; it just spawned a new IE process with the destination?!? (even though it's a "virtual" page on the same domain)
Navigation worked fine on Wine and did call the custom pluggable protocol handler…
Using `IPersistMoniker_Load` seems to work fine, though. I'm not sure if this actually "navigates" the page. Should I be concerned? However, testing this on native:
* The same IHTMLDocument2 doc obj is used after the "navigation", and * It does change the compat mode (I navigate to diff compat mode page) for that doc obj, and * It stops exposing `IEventTarget` (if navigating to a quirks page from ie9) or starts exposing it (if navigation to a ie9 page from quirks)
This means it does break the COM rules, right? Or is my test messed up?
I haven't yet added tests for events to see what happens, but I should also look into DISPIDs forwarding since they suffer from same problem with breaking the "rules" (but this time of IDispatch), since the same name will map to a potentially different DISPID (some aren't even available in quirks mode). Wouldn't surprise me if native also breaks those though.
Is using `IPersistMoniker_Load` to navigate fine? Or at the very least, for what I'm testing, even if it's not a real navigation. It does change the document node, so I guess it's enough to test this, right?
On Thu Nov 10 18:16:38 2022 +0000, Gabriel Ivăncescu wrote:
It looks like native IE indeed breaks COM rules here. I moved the tests to `events.c` since we have pluggable protocol handler and we're testing events anyway, but for some reason I couldn't use `put_href`, `replace` or `superNavigate` on native to navigate using the pluggable protocol; it just spawned a new IE process with the destination?!? (even though it's a "virtual" page on the same domain) Navigation worked fine on Wine and did call the custom pluggable protocol handler… Using `IPersistMoniker_Load` seems to work fine, though. I'm not sure if this actually "navigates" the page. Should I be concerned? However, testing this on native:
- The same IHTMLDocument2 doc obj is used after the "navigation", and
- It does change the compat mode (I navigate to diff compat mode page)
for that doc obj, and
- It stops exposing `IEventTarget` (if navigating to a quirks page from
ie9) or starts exposing it (if navigation to a ie9 page from quirks) This means it does break the COM rules, right? Or is my test messed up? I haven't yet added tests for events to see what happens, but I should also look into DISPIDs forwarding since they suffer from same problem with breaking the "rules" (but this time of IDispatch), since the same name will map to a potentially different DISPID (some aren't even available in quirks mode). Wouldn't surprise me if native also breaks those though. Is using `IPersistMoniker_Load` to navigate fine? Or at the very least, for what I'm testing, even if it's not a real navigation. It does change the document node, so I guess it's enough to test this, right?
`IPersistMoniker_Load` probably gives valid results in this case, but it's less similar to real-world use, so I think it would be interesting to try find out what's wrong with using `put_href`. One thing I can think of is to report MIME type from our pluggable protocol handler, does reporting `BINDSTATUS_MIMETYPEAVAILABLE` (or even `BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE`) help?
And yes, it sounds like native indeed breaks COM rules.
On Fri Nov 11 10:13:58 2022 +0000, Jacek Caban wrote:
`IPersistMoniker_Load` probably gives valid results in this case, but it's less similar to real-world use, so I think it would be interesting to try find out what's wrong with using `put_href`. One thing I can think of is to report MIME type from our pluggable protocol handler, does reporting `BINDSTATUS_MIMETYPEAVAILABLE` (or even `BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE`) help? And yes, it sounds like native indeed breaks COM rules.
Unfortunately those don't help. The Protocol handler is not called at all after the navigation is issued (tracing all the methods). Even reporting the mime type on the old page didn't change a thing.
It's also useful to note that this happens on all navigations, not just `put_href`. `replace` for example, but also `window.navigate` or `window.open` (with _self obviously). However, I looked at why `navigation.js` works, since it navigates, but it turns out this is only an issue on top-level windows. iframes work fine and do use the protocol handler (I changed the URL from `about:blank` to something with http for the handler, traced and it gets called…).
I don't know if this is deliberate or a bug in Windows' urlmon. But it seems it ignores temporary pluggable namespace handlers when doing any sort of navigation on the top level window. But only the top-level.
I resorted to keep the `IPersistMoniker_Load` way, but I had to add `IHlinkTarget_Navigate`, otherwise unload events wouldn't be dispatched (this is for next MR, not tested here).