Bunch of misc fixes and preparations for further improvements. The location changes are especially important later when we'll use outer windows everywhere we pass them to external callers (such as script engines, since inner windows are an implementation detail and all operations otherwise should go through the outer window "proxy").
-- v2: mshtml: Embed the HTMLLocation into the outer window. mshtml: Tie window.location to the outer window. mshtml: Return undefined from window.XMLHttpRequest for uninitialized jscript: Pass the correct ServiceProvider when invoking external prop. mshtml: Use Scrollbar_Auto as default for vertical scrollbars. include/mshtml: Add the other IHTMLEventObj* interfaces.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- include/mshtmdid.h | 11 ++ include/mshtml.idl | 357 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+)
diff --git a/include/mshtmdid.h b/include/mshtmdid.h index 1673dd3cea0..a28d706903f 100644 --- a/include/mshtmdid.h +++ b/include/mshtmdid.h @@ -3487,6 +3487,17 @@ /* IHTMLEventObj4 */ #define DISPID_IHTMLEVENTOBJ4_WHEELDELTA DISPID_EVENTOBJ+51
+/* IHTMLEventObj5 */ +#define DISPID_IHTMLEVENTOBJ5_URL DISPID_EVENTOBJ+52 +#define DISPID_IHTMLEVENTOBJ5_DATA DISPID_EVENTOBJ+54 +#define DISPID_IHTMLEVENTOBJ5_SOURCE DISPID_EVENTOBJ+55 +#define DISPID_IHTMLEVENTOBJ5_ORIGIN DISPID_EVENTOBJ+53 +#define DISPID_IHTMLEVENTOBJ5_ISSESSION DISPID_EVENTOBJ+56 + +/* IHTMLEventObj6 */ +#define DISPID_IHTMLEVENTOBJ6_ACTIONURL DISPID_EVENTOBJ+58 +#define DISPID_IHTMLEVENTOBJ6_BUTTONID DISPID_EVENTOBJ+57 + /* IHTMLStyleMedia */ #define DISPID_IHTMLSTYLEMEDIA_TYPE DISPID_STYLEMEDIA+1 #define DISPID_IHTMLSTYLEMEDIA_MATCHMEDIUM DISPID_STYLEMEDIA+2 diff --git a/include/mshtml.idl b/include/mshtml.idl index 1a5c9bbaf28..2a1fccba6be 100644 --- a/include/mshtml.idl +++ b/include/mshtml.idl @@ -19400,6 +19400,327 @@ interface IHTMLEventObj : IDispatch HRESULT srcFilter([retval, out] IDispatch **p); }
+/***************************************************************************** + * IHTMLEventObj2 interface + */ +[ + odl, + oleautomation, + dual, + uuid(3050f48B-98b5-11cf-bb82-00aa00bdce0b) +] +interface IHTMLEventObj2 : IDispatch +{ + [id(DISPID_IHTMLEVENTOBJ2_SETATTRIBUTE)] + HRESULT setAttribute( + [in] BSTR strAttributeName, + [in] VARIANT AttributeValue, + [in, defaultvalue(1)] LONG lFlags); + + [id(DISPID_IHTMLEVENTOBJ2_GETATTRIBUTE)] + HRESULT getAttribute( + [in] BSTR strAttributeName, + [in, defaultvalue(0)] LONG lFlags, + [out, retval] VARIANT *AttributeValue); + + [id(DISPID_IHTMLEVENTOBJ2_REMOVEATTRIBUTE)] + HRESULT removeAttribute( + [in] BSTR strAttributeName, + [in, defaultvalue(1)] LONG lFlags, + [out, retval] VARIANT_BOOL *pfSuccess); + + [propput, id(DISPID_IHTMLEVENTOBJ2_PROPERTYNAME)] + HRESULT propertyName([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_PROPERTYNAME)] + HRESULT propertyName([out, retval] BSTR *p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_BOOKMARKS)] + HRESULT bookmarks([in] IHTMLBookmarkCollection *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_BOOKMARKS)] + HRESULT bookmarks([out, retval] IHTMLBookmarkCollection **p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_RECORDSET)] + HRESULT recordset([in] IDispatch *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_RECORDSET)] + HRESULT recordset([out, retval] IDispatch **p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_DATAFLD)] + HRESULT dataFld([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_DATAFLD)] + HRESULT dataFld([out, retval] BSTR *p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_BOUNDELEMENTS)] + HRESULT boundElements([in] IHTMLElementCollection *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_BOUNDELEMENTS)] + HRESULT boundElements([out, retval] IHTMLElementCollection **p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_REPEAT)] + HRESULT repeat([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_REPEAT)] + HRESULT repeat([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_SRCURN)] + HRESULT srcUrn([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SRCURN)] + HRESULT srcUrn([out, retval] BSTR *p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_SRCELEMENT)] + HRESULT srcElement([in] IHTMLElement *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SRCELEMENT)] + HRESULT srcElement([out, retval] IHTMLElement **p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_ALTKEY)] + HRESULT altKey([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_ALTKEY)] + HRESULT altKey([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_CTRLKEY)] + HRESULT ctrlKey([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_CTRLKEY)] + HRESULT ctrlKey([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_SHIFTKEY)] + HRESULT shiftKey([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SHIFTKEY)] + HRESULT shiftKey([out, retval] VARIANT_BOOL *p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_FROMELEMENT)] + HRESULT fromElement([in] IHTMLElement *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_FROMELEMENT)] + HRESULT fromElement([out, retval] IHTMLElement **p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_TOELEMENT)] + HRESULT toElement([in] IHTMLElement *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_TOELEMENT)] + HRESULT toElement([out, retval] IHTMLElement **p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_BUTTON)] + HRESULT button([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_BUTTON)] + HRESULT button([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_TYPE)] + HRESULT type([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_TYPE)] + HRESULT type([out, retval] BSTR *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_QUALIFIER)] + HRESULT qualifier([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_QUALIFIER)] + HRESULT qualifier([out, retval] BSTR *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_REASON)] + HRESULT reason([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_REASON)] + HRESULT reason([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_X)] + HRESULT x([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_X)] + HRESULT x([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_Y)] + HRESULT y([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_Y)] + HRESULT y([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_CLIENTX)] + HRESULT clientX([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_CLIENTX)] + HRESULT clientX([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_CLIENTY)] + HRESULT clientY([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_CLIENTY)] + HRESULT clientY([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_OFFSETX)] + HRESULT offsetX([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_OFFSETX)] + HRESULT offsetX([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_OFFSETY)] + HRESULT offsetY([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_OFFSETY)] + HRESULT offsetY([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_SCREENX)] + HRESULT screenX([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SCREENX)] + HRESULT screenX([out, retval] long *p); + + [propput, id(DISPID_IHTMLEVENTOBJ2_SCREENY)] + HRESULT screenY([in] long v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SCREENY)] + HRESULT screenY([out, retval] long *p); + + [propputref, id(DISPID_IHTMLEVENTOBJ2_SRCFILTER)] + HRESULT srcFilter([in] IDispatch *v); + + [propget, id(DISPID_IHTMLEVENTOBJ2_SRCFILTER)] + HRESULT srcFilter([out, retval] IDispatch **p); + + [propget, id(DISPID_IHTMLEVENTOBJ2_DATATRANSFER)] + HRESULT dataTransfer([out, retval] IHTMLDataTransfer **p); +} + +/***************************************************************************** + * IHTMLEventObj3 interface + */ +[ + odl, + oleautomation, + dual, + uuid(3050f680-98b5-11cf-bb82-00aa00bdce0b) +] +interface IHTMLEventObj3 : IDispatch +{ + [propget, id(DISPID_IHTMLEVENTOBJ3_CONTENTOVERFLOW)] + HRESULT contentOverflow([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ3_SHIFTLEFT)] + HRESULT shiftLeft([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ3_SHIFTLEFT)] + HRESULT shiftLeft([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ3_ALTLEFT)] + HRESULT altLeft([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ3_ALTLEFT)] + HRESULT altLeft([out, retval] VARIANT_BOOL *p); + + [propput, id(DISPID_IHTMLEVENTOBJ3_CTRLLEFT)] + HRESULT ctrlLeft([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ3_CTRLLEFT)] + HRESULT ctrlLeft([out, retval] VARIANT_BOOL *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_IMECOMPOSITIONCHANGE), hidden, restricted, nonbrowsable] + HRESULT imeCompositionChange([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_IMENOTIFYCOMMAND), hidden, restricted, nonbrowsable] + HRESULT imeNotifyCommand([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_IMENOTIFYDATA), hidden, restricted, nonbrowsable] + HRESULT imeNotifyData([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_IMEREQUEST), hidden, restricted, nonbrowsable] + HRESULT imeRequest([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_IMEREQUESTDATA), hidden, restricted, nonbrowsable] + HRESULT imeRequestData([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_KEYBOARDLAYOUT), hidden, restricted, nonbrowsable] + HRESULT keyboardLayout([out, retval] LONG_PTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_BEHAVIORCOOKIE)] + HRESULT behaviorCookie([out, retval] long *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_BEHAVIORPART)] + HRESULT behaviorPart([out, retval] long *p); + + [propget, id(DISPID_IHTMLEVENTOBJ3_NEXTPAGE)] + HRESULT nextPage([out, retval] BSTR *p); +} + +/***************************************************************************** + * IHTMLEventObj4 interface + */ +[ + odl, + oleautomation, + dual, + uuid(3050f814-98b5-11cf-bb82-00aa00bdce0b) +] +interface IHTMLEventObj4 : IDispatch +{ + [propget, id(DISPID_IHTMLEVENTOBJ4_WHEELDELTA)] + HRESULT wheelDelta([out, retval] long *p); +} + +/***************************************************************************** + * IHTMLEventObj5 interface + */ +[ + odl, + oleautomation, + dual, + uuid(30510478-98b5-11cf-bb82-00aa00bdce0b) +] +interface IHTMLEventObj5 : IDispatch +{ + [propput, id(DISPID_IHTMLEVENTOBJ5_URL)] + HRESULT url([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_URL)] + HRESULT url([out, retval] BSTR *p); + + [propput, id(DISPID_IHTMLEVENTOBJ5_DATA)] + HRESULT data([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_DATA)] + HRESULT data([out, retval] BSTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ5_SOURCE)] + HRESULT source([out, retval] IDispatch **p); + + [propput, id(DISPID_IHTMLEVENTOBJ5_ORIGIN)] + HRESULT origin([in] BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_ORIGIN)] + HRESULT origin([out, retval] BSTR *p); + + [propput, id(DISPID_IHTMLEVENTOBJ5_ISSESSION), hidden, restricted, nonbrowsable] + HRESULT issession([in] VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_ISSESSION), hidden, restricted, nonbrowsable] + HRESULT issession([out, retval] VARIANT_BOOL *p); +} + +/***************************************************************************** + * IHTMLEventObj6 interface + */ +[ + odl, + oleautomation, + dual, + uuid(30510734-98b5-11cf-bb82-00aa00bdce0b) +] +interface IHTMLEventObj6 : IDispatch +{ + [propget, id(DISPID_IHTMLEVENTOBJ6_ACTIONURL)] + HRESULT actionURL([out, retval] BSTR *p); + + [propget, id(DISPID_IHTMLEVENTOBJ6_BUTTONID)] + HRESULT buttonID([out, retval] long *p); +} + /***************************************************************************** * DispCEventObj dispinterface */ @@ -19653,6 +19974,42 @@ methods:
[propget, id(DISPID_IHTMLEVENTOBJ4_WHEELDELTA)] LONG wheelDelta(); + + [propput, id(DISPID_IHTMLEVENTOBJ5_URL)] + void url(BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_URL)] + BSTR url(); + + [propput, id(DISPID_IHTMLEVENTOBJ5_DATA)] + void data(BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_DATA)] + BSTR data(); + + [propget, id(DISPID_IHTMLEVENTOBJ5_SOURCE)] + IDispatch *source(); + + [propput, id(DISPID_IHTMLEVENTOBJ5_ORIGIN)] + void origin(BSTR v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_ORIGIN)] + BSTR origin(); + + [propput, id(DISPID_IHTMLEVENTOBJ5_ISSESSION), hidden, restricted, nonbrowsable] + void issession(VARIANT_BOOL v); + + [propget, id(DISPID_IHTMLEVENTOBJ5_ISSESSION), hidden, restricted, nonbrowsable] + VARIANT_BOOL issession(); + + [propget, id(DISPID_IHTMLEVENTOBJ6_ACTIONURL)] + BSTR actionURL(); + + [propget, id(DISPID_IHTMLEVENTOBJ6_BUTTONID)] + long buttonID(); + + [propget, id(DISPID_IHTMLDOMCONSTRUCTOR_CONSTRUCTOR), hidden] + IDispatch *constructor(); }
/*****************************************************************************
From: Gabriel Ivăncescu gabrielopcode@gmail.com
While Internet Explorer 6 used to default to "always", this hasn't been the case for a long while now.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/nsembed.c | 2 +- dlls/mshtml/oleobj.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index b7518f55ef9..b6d7b53f815 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -2268,7 +2268,7 @@ static HRESULT init_browser(GeckoBrowser *browser) nsres = nsIWebBrowser_QueryInterface(browser->webbrowser, &IID_nsIScrollable, (void**)&scrollable); if(NS_SUCCEEDED(nsres)) { nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, - ScrollOrientation_Y, Scrollbar_Always); + ScrollOrientation_Y, Scrollbar_Auto); if(NS_FAILED(nsres)) ERR("Could not set default Y scrollbar prefs: %08lx\n", nsres);
diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index d1853435606..c01c18b5fa8 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -363,7 +363,7 @@ static void update_hostinfo(HTMLDocumentObj *This, DOCHOSTUIINFO *hostinfo) nsres = nsIWebBrowser_QueryInterface(This->nscontainer->webbrowser, &IID_nsIScrollable, (void**)&scrollable); if(NS_SUCCEEDED(nsres)) { nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable, ScrollOrientation_Y, - (hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO) ? Scrollbar_Never : Scrollbar_Always); + (hostinfo->dwFlags & DOCHOSTUIFLAG_SCROLL_NO) ? Scrollbar_Never : Scrollbar_Auto); if(NS_FAILED(nsres)) ERR("Could not set default Y scrollbar prefs: %08lx\n", nsres);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 33 ++++----- dlls/jscript/jscript.h | 8 ++- dlls/jscript/tests/run.c | 143 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 17 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 4b56ec9fc70..dd91a577159 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -572,9 +572,9 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val));
- return disp_call_value(This->ctx, get_object(prop->u.val), - jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), - flags, argc, argv, r); + return disp_call_value_with_caller(This->ctx, get_object(prop->u.val), + jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), + flags, argc, argv, r, caller); } case PROP_ACCESSOR: case PROP_IDX: { @@ -585,9 +585,9 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return hres;
if(is_object_instance(val)) { - hres = disp_call_value(This->ctx, get_object(val), - jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), - flags, argc, argv, r); + hres = disp_call_value_with_caller(This->ctx, get_object(val), + jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), + flags, argc, argv, r, caller); }else { FIXME("invoke %s\n", debugstr_jsval(val)); hres = E_NOTIMPL; @@ -2364,7 +2364,7 @@ HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_ if(!prop) return DISP_E_MEMBERNOTFOUND;
- return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL); + return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); }
HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) @@ -2379,10 +2379,11 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned if(!prop || prop->type == PROP_DELETED) return JS_E_INVALID_PROPERTY;
- return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL); + return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); }
-static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r) +static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r, + IServiceProvider *caller) { IDispatchEx *dispex; EXCEPINFO ei; @@ -2391,7 +2392,7 @@ static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD f memset(&ei, 0, sizeof(ei)); hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(SUCCEEDED(hres)) { - hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, params, r, &ei, &ctx->jscaller->IServiceProvider_iface); + hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, params, r, &ei, caller); IDispatchEx_Release(dispex); }else { UINT err = 0; @@ -2489,7 +2490,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns }
V_VT(&retv) = VT_EMPTY; - hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL); + hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL, &ctx->jscaller->IServiceProvider_iface);
for(i=0; i<argc; i++) VariantClear(dp.rgvarg+argc-i-1); @@ -2529,8 +2530,8 @@ HRESULT disp_call_name(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, WO return disp_call(ctx, disp, id, flags, argc, argv, ret); }
-HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, - jsval_t *r) +HRESULT disp_call_value_with_caller(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc, + jsval_t *argv, jsval_t *r, IServiceProvider *caller) { VARIANT buf[6], retv, *args = buf; IDispatch *jsthis; @@ -2586,7 +2587,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD
if(SUCCEEDED(hres)) { V_VT(&retv) = VT_EMPTY; - hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL); + hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL, caller); }
for(i = 0; i < argc; i++) @@ -2665,7 +2666,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val) if(V_VT(&var) == VT_DISPATCH) flags |= DISPATCH_PROPERTYPUTREF;
- hres = disp_invoke(ctx, disp, id, flags, &dp, NULL); + hres = disp_invoke(ctx, disp, id, flags, &dp, NULL, &ctx->jscaller->IServiceProvider_iface); VariantClear(&var); }
@@ -2773,7 +2774,7 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val jsdisp_release(jsdisp);
V_VT(&var) = VT_EMPTY; - hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var); + hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var, &ctx->jscaller->IServiceProvider_iface); if(SUCCEEDED(hres)) { hres = variant_to_jsval(ctx, &var, val); VariantClear(&var); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 36a6d23c917..32c2d8eb726 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -240,7 +240,7 @@ HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,js
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; -HRESULT disp_call_value(script_ctx_t*,IDispatch*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; +HRESULT disp_call_value_with_caller(script_ctx_t*,IDispatch*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*) DECLSPEC_HIDDEN; HRESULT jsdisp_call_value(jsdisp_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; @@ -483,6 +483,12 @@ static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags) return ((ctx->version & 0xff) << 28) | flags; }
+static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_t vthis, WORD flags, unsigned argc, + jsval_t *argv, jsval_t *r) +{ + return disp_call_value_with_caller(ctx, disp, vthis, flags, argc, argv, r, &ctx->jscaller->IServiceProvider_iface); +} + #define FACILITY_JSCRIPT 10
#define MAKE_JSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_JSCRIPT, code) diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index 21f09474fee..c5d9c47e63c 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -114,6 +114,9 @@ DEFINE_EXPECT(testobj_newenum); DEFINE_EXPECT(testobj_getidfail_d); DEFINE_EXPECT(testobj_tolocalestr_d); DEFINE_EXPECT(testobj_tolocalestr_i); +DEFINE_EXPECT(test_caller_get); +DEFINE_EXPECT(test_caller_null); +DEFINE_EXPECT(test_caller_obj); DEFINE_EXPECT(testdestrobj); DEFINE_EXPECT(enumvariant_next_0); DEFINE_EXPECT(enumvariant_next_1); @@ -333,6 +336,44 @@ static IEnumVARIANTVtbl testEnumVARIANTVtbl = {
static IEnumVARIANT testEnumVARIANT = { &testEnumVARIANTVtbl };
+static HRESULT WINAPI sp_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IServiceProvider, riid)) { + *ppv = iface; + return S_OK; + } + + ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOTIMPL; +} + +static ULONG WINAPI sp_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI sp_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI sp_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv) +{ + ok(0, "unexpected call %s\n", wine_dbgstr_guid(guidService)); + *ppv = NULL; + return E_NOTIMPL; +} + +static const IServiceProviderVtbl sp_vtbl = { + sp_QueryInterface, + sp_AddRef, + sp_Release, + sp_QueryService +}; + +static IServiceProvider sp_obj = { &sp_vtbl }; + static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -629,6 +670,61 @@ static IDispatchExVtbl testObjVtbl = {
static IDispatchEx testObj = { &testObjVtbl };
+static HRESULT WINAPI testcallerobj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + ok(id == DISPID_VALUE, "id = %ld\n", id); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + if(wFlags == DISPATCH_PROPERTYGET) { + CHECK_EXPECT(test_caller_get); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pei != NULL, "pei == NULL\n"); + ok(pspCaller != NULL, "pspCaller == NULL\n"); + ok(pspCaller != &sp_obj, "pspCaller == sp_obj\n"); + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)iface; + }else if(pspCaller) { + CHECK_EXPECT(test_caller_obj); + ok(wFlags == DISPATCH_METHOD, "wFlags = %04x\n", wFlags); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pspCaller == &sp_obj, "pspCaller != sp_obj\n"); + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = 137; + }else { + CHECK_EXPECT(test_caller_null); + ok(wFlags == DISPATCH_METHOD, "wFlags = %04x\n", wFlags); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + V_VT(pvarRes) = VT_I4; + V_I4(pvarRes) = 42; + } + return S_OK; +} + +static IDispatchExVtbl testcallerobj_vtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + DispatchEx_GetDispID, + testcallerobj_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testcallerobj = { &testcallerobj_vtbl }; + static LONG test_destr_ref;
static ULONG WINAPI testDestrObj_AddRef(IDispatchEx *iface) @@ -3214,6 +3310,7 @@ static void test_script_exprs(void)
static void test_invokeex(void) { + static DISPID propput_dispid = DISPID_PROPERTYPUT; DISPPARAMS dp = {NULL}, dp_max = {NULL}; DISPID func_id, max_id, prop_id; IActiveScript *script; @@ -3442,6 +3539,52 @@ static void test_invokeex(void)
IDispatchEx_Release(dispex); IActiveScript_Release(script); + + /* test InvokeEx with host prop and custom caller */ + hres = parse_script_expr(L"var o = {}; o", &v, &script); + ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres); + ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v)); + + hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres); + VariantClear(&v); + + str = SysAllocString(L"caller"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure, &func_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08lx\n", hres); + + SET_EXPECT(test_caller_get); + dp.cArgs = dp.cNamedArgs = 1; + dp.rgvarg = &arg; + dp.rgdispidNamedArgs = &propput_dispid; + V_VT(&arg) = VT_DISPATCH; + V_DISPATCH(&arg) = (IDispatch*)&testcallerobj; + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + todo_wine + CHECK_CALLED(test_caller_get); + + SET_EXPECT(test_caller_null); + dp.cArgs = dp.cNamedArgs = 0; + dp.rgvarg = NULL; + dp.rgdispidNamedArgs = NULL; + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 42, "V_I4(v) = %s\n", wine_dbgstr_variant(&v)); + CHECK_CALLED(test_caller_null); + V_VT(&v) = VT_EMPTY; + + SET_EXPECT(test_caller_obj); + hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, &sp_obj); + ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 137, "V_I4(v) = %s\n", wine_dbgstr_variant(&v)); + CHECK_CALLED(test_caller_obj); + + IDispatchEx_Release(dispex); + IActiveScript_Release(script); }
static void test_destructors(void)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Add a bunch of tests along the way which verify existing behavior is mostly correct. --- dlls/mshtml/htmlwindow.c | 5 ++ dlls/mshtml/tests/dom.c | 114 +++++++++++++++++++++++++++++- dlls/mshtml/tests/events.c | 139 +++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index f013ba20d1c..c4c6a99f5f3 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2038,6 +2038,11 @@ static HRESULT WINAPI HTMLWindow5_get_XMLHttpRequest(IHTMLWindow5 *iface, VARIAN
TRACE("(%p)->(%p)\n", This, p);
+ if(This->outer_window->readystate == READYSTATE_UNINITIALIZED) { + V_VT(p) = VT_EMPTY; + return S_OK; + } + if(!window->xhr_factory) { HRESULT hres;
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index dc236a27f1c..2efbbbf513c 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11800,12 +11800,23 @@ static void test_quirks_mode(void)
static void test_document_mode_lock(void) { + IHTMLOptionElementFactory *option, *option2; + IHTMLDocument2 *doc, *doc_node, *doc_node2; + IHTMLImageElementFactory *image, *image2; + IOmNavigator *navigator, *navigator2; + IHTMLLocation *location, *location2; + IHTMLPerformance *perf, *perf2; + IOmHistory *history, *history2; + IHTMLScreen *screen, *screen2; IEventTarget *event_target; IPersistStreamInit *init; - IHTMLDocument2 *doc; + IHTMLWindow7 *window7; + IHTMLWindow5 *window5; + IHTMLWindow2 *window; IStream *stream; HRESULT hres; HGLOBAL mem; + VARIANT var; SIZE_T len; MSG msg;
@@ -11818,6 +11829,49 @@ static void test_document_mode_lock(void) ok(hres == E_NOINTERFACE, "QueryInterface(IID_IEventTarget) returned %08lx.\n", hres); ok(event_target == NULL, "event_target != NULL\n");
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_location(window, &location); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_navigator(window, &navigator); + ok(hres == S_OK, "get_navigator failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_history(window, &history); + ok(hres == S_OK, "get_history failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_screen(window, &screen); + ok(hres == S_OK, "get_screen failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_Image(window, &image); + ok(hres == S_OK, "get_image failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_Option(window, &option); + ok(hres == S_OK, "get_option failed: %08lx\n", hres); + + V_VT(&var) = VT_NULL; + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow5, (void**)&window5); + ok(hres == S_OK, "Could not get IHTMLWindow5: %08lx\n", hres); + hres = IHTMLWindow5_get_XMLHttpRequest(window5, &var); + ok(hres == S_OK, "get_XMLHttpRequest failed: %08lx\n", hres); + ok(V_VT(&var) == VT_EMPTY, "V_VT(XMLHttpRequest) = %d\n", V_VT(&var)); + IHTMLWindow5_Release(window5); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); + ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); + hres = IHTMLWindow7_get_performance(window7, &var); + ok(hres == S_OK, "get_performance failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&var)); + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLPerformance, (void**)&perf); + ok(hres == S_OK, "Could not get IHTMLPerformance: %08lx\n", hres); + IHTMLWindow7_Release(window7); + IHTMLWindow2_Release(window); + VariantClear(&var); + len = strlen(doc_blank_ie9); mem = GlobalAlloc(0, len); memcpy(mem, doc_blank_ie9, len); @@ -11844,6 +11898,64 @@ static void test_document_mode_lock(void) ok(event_target != NULL, "event_target == NULL\n"); IEventTarget_Release(event_target);
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node2); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc_node != doc_node2, "doc_node == doc_node2\n"); + IHTMLDocument2_Release(doc_node2); + IHTMLDocument2_Release(doc_node); + + hres = IHTMLWindow2_get_location(window, &location2); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + todo_wine + ok(location == location2, "location != location2\n"); + IHTMLLocation_Release(location2); + IHTMLLocation_Release(location); + + hres = IHTMLWindow2_get_navigator(window, &navigator2); + ok(hres == S_OK, "get_navigator failed: %08lx\n", hres); + ok(navigator != navigator2, "navigator == navigator2\n"); + IOmNavigator_Release(navigator2); + IOmNavigator_Release(navigator); + + hres = IHTMLWindow2_get_history(window, &history2); + ok(hres == S_OK, "get_history failed: %08lx\n", hres); + ok(history != history2, "history == history2\n"); + IOmHistory_Release(history2); + IOmHistory_Release(history); + + hres = IHTMLWindow2_get_screen(window, &screen2); + ok(hres == S_OK, "get_screen failed: %08lx\n", hres); + ok(screen != screen2, "screen == screen2\n"); + IHTMLScreen_Release(screen2); + IHTMLScreen_Release(screen); + + hres = IHTMLWindow2_get_Image(window, &image2); + ok(hres == S_OK, "get_image failed: %08lx\n", hres); + ok(image != image2, "image == image2\n"); + IHTMLImageElementFactory_Release(image2); + IHTMLImageElementFactory_Release(image); + + hres = IHTMLWindow2_get_Option(window, &option2); + ok(hres == S_OK, "get_option failed: %08lx\n", hres); + ok(option != option2, "option == option2\n"); + IHTMLOptionElementFactory_Release(option2); + IHTMLOptionElementFactory_Release(option); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); + ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); + hres = IHTMLWindow7_get_performance(window7, &var); + ok(hres == S_OK, "get_performance failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&var)); + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLPerformance, (void**)&perf2); + ok(hres == S_OK, "Could not get IHTMLPerformance: %08lx\n", hres); + ok(perf != perf2, "perf == perf2\n"); + IHTMLWindow7_Release(window7); + IHTMLWindow2_Release(window); + VariantClear(&var); + set_client_site(doc, FALSE); IHTMLDocument2_Release(doc); } diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 30b6d8799b6..196ab3160a7 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -3135,9 +3135,22 @@ static void test_iframe_connections(IHTMLDocument2 *doc) static void test_doc_obj(IHTMLDocument2 *doc) { DISPID dispid, import_node_id, has_own_prop_id; + IHTMLOptionElementFactory *option, *option2; + IHTMLImageElementFactory *image, *image2; + IHTMLXMLHttpRequestFactory *xhr, *xhr2; + IHTMLDocument2 *doc_node, *doc_node2; + IOmNavigator *navigator, *navigator2; + IHTMLLocation *location, *location2; int orig_doc_mode = document_mode; + IHTMLStorage *storage, *storage2; + IHTMLPerformance *perf, *perf2; + IOmHistory *history, *history2; + IHTMLScreen *screen, *screen2; IEventTarget *event_target; DISPPARAMS dp = { 0 }; + IHTMLWindow7 *window7; + IHTMLWindow6 *window6; + IHTMLWindow5 *window5; IDispatchEx *dispex; IHTMLElement *body; VARIANT res, arg; @@ -3246,6 +3259,54 @@ static void test_doc_obj(IHTMLDocument2 *doc) SysFreeString(V_BSTR(&arg)); }
+ /* test window props during navigation */ + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_location(window, &location); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_navigator(window, &navigator); + ok(hres == S_OK, "get_navigator failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_history(window, &history); + ok(hres == S_OK, "get_history failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_screen(window, &screen); + ok(hres == S_OK, "get_screen failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_Image(window, &image); + ok(hres == S_OK, "get_image failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_Option(window, &option); + ok(hres == S_OK, "get_option failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow5, (void**)&window5); + ok(hres == S_OK, "Could not get IHTMLWindow5: %08lx\n", hres); + hres = IHTMLWindow5_get_XMLHttpRequest(window5, &res); + ok(hres == S_OK, "get_XMLHttpRequest failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(XMLHttpRequest) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLXMLHttpRequestFactory, (void**)&xhr); + ok(hres == S_OK, "Could not get IHTMLXMLHttpRequestFactory: %08lx\n", hres); + IHTMLWindow5_Release(window5); + VariantClear(&res); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + ok(hres == S_OK, "Could not get IHTMLWindow6: %08lx\n", hres); + hres = IHTMLWindow6_get_sessionStorage(window6, &storage); + ok(hres == S_OK, "get_sessionStorage failed: %08lx\n", hres); + IHTMLWindow6_Release(window6); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); + ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); + hres = IHTMLWindow7_get_performance(window7, &res); + ok(hres == S_OK, "get_performance failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLPerformance, (void**)&perf); + ok(hres == S_OK, "Could not get IHTMLPerformance: %08lx\n", hres); + IHTMLWindow7_Release(window7); + VariantClear(&res); + /* Navigate to a different document mode page, checking using the same doc obj. Test that it breaks COM rules, since IEventTarget is conditionally exposed. All the events registered on the old doc node are also removed. @@ -3286,6 +3347,84 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(hres == S_OK, "GetIDsOfNames(importNode) returned: %08lx\n", hres); ok(dispid != import_node_id, "importNode on new doc node == old created importNode\n"); } + + hres = IHTMLWindow2_get_document(window, &doc_node2); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc_node != doc_node2, "doc_node == doc_node2\n"); + IHTMLDocument2_Release(doc_node2); + IHTMLDocument2_Release(doc_node); + + hres = IHTMLWindow2_get_location(window, &location2); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + todo_wine + ok(location == location2, "location != location2\n"); + IHTMLLocation_Release(location2); + IHTMLLocation_Release(location); + + hres = IHTMLWindow2_get_navigator(window, &navigator2); + ok(hres == S_OK, "get_navigator failed: %08lx\n", hres); + ok(navigator != navigator2, "navigator == navigator2\n"); + IOmNavigator_Release(navigator2); + IOmNavigator_Release(navigator); + + hres = IHTMLWindow2_get_history(window, &history2); + ok(hres == S_OK, "get_history failed: %08lx\n", hres); + ok(history != history2, "history == history2\n"); + IOmHistory_Release(history2); + IOmHistory_Release(history); + + hres = IHTMLWindow2_get_screen(window, &screen2); + ok(hres == S_OK, "get_screen failed: %08lx\n", hres); + ok(screen != screen2, "screen == screen2\n"); + IHTMLScreen_Release(screen2); + IHTMLScreen_Release(screen); + + hres = IHTMLWindow2_get_Image(window, &image2); + ok(hres == S_OK, "get_image failed: %08lx\n", hres); + ok(image != image2, "image == image2\n"); + IHTMLImageElementFactory_Release(image2); + IHTMLImageElementFactory_Release(image); + + hres = IHTMLWindow2_get_Option(window, &option2); + ok(hres == S_OK, "get_option failed: %08lx\n", hres); + ok(option != option2, "option == option2\n"); + IHTMLOptionElementFactory_Release(option2); + IHTMLOptionElementFactory_Release(option); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow5, (void**)&window5); + ok(hres == S_OK, "Could not get IHTMLWindow5: %08lx\n", hres); + hres = IHTMLWindow5_get_XMLHttpRequest(window5, &res); + ok(hres == S_OK, "get_XMLHttpRequest failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(XMLHttpRequest) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLXMLHttpRequestFactory, (void**)&xhr2); + ok(hres == S_OK, "Could not get IHTMLXMLHttpRequestFactory: %08lx\n", hres); + ok(xhr != xhr2, "xhr == xhr2\n"); + IHTMLXMLHttpRequestFactory_Release(xhr2); + IHTMLXMLHttpRequestFactory_Release(xhr); + IHTMLWindow5_Release(window5); + VariantClear(&res); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6); + ok(hres == S_OK, "Could not get IHTMLWindow6: %08lx\n", hres); + hres = IHTMLWindow6_get_sessionStorage(window6, &storage2); + ok(hres == S_OK, "get_sessionStorage failed: %08lx\n", hres); + ok(storage != storage2, "storage == storage2\n"); + IHTMLStorage_Release(storage2); + IHTMLStorage_Release(storage); + IHTMLWindow6_Release(window6); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); + ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); + hres = IHTMLWindow7_get_performance(window7, &res); + ok(hres == S_OK, "get_performance failed: %08lx\n", hres); + ok(V_VT(&res) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&res)); + hres = IDispatch_QueryInterface(V_DISPATCH(&res), &IID_IHTMLPerformance, (void**)&perf2); + ok(hres == S_OK, "Could not get IHTMLPerformance: %08lx\n", hres); + ok(perf != perf2, "perf == perf2\n"); + IHTMLPerformance_Release(perf2); + IHTMLPerformance_Release(perf); + IHTMLWindow7_Release(window7); + VariantClear(&res); }
static void test_create_event(IHTMLDocument2 *doc)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Even in IE9+ modes, it's still a non-JS object.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 1 + dlls/mshtml/htmllocation.c | 31 ++++++++++++++----------------- dlls/mshtml/htmlwindow.c | 19 +++++++++++-------- dlls/mshtml/mshtml_private.h | 7 +++---- dlls/mshtml/tests/dom.c | 17 ++++++++++++++++- dlls/mshtml/tests/events.c | 15 ++++++++++++++- 6 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 1d00012572b..bd9e5bdccae 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2020,6 +2020,7 @@ void dispex_unlink(DispatchEx *This) }else { VariantClear(&prop->var); } + prop->flags |= DYNPROP_DELETED; } }
diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 066ebb4f5e6..5c31ee02e04 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -38,18 +38,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
static HRESULT get_url(HTMLLocation *This, const WCHAR **ret) { - if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->url) + if(!This->window || !This->window->url) *ret = L"about:blank"; else - *ret = This->window->base.outer_window->url; + *ret = This->window->url; return S_OK; }
static IUri *get_uri(HTMLLocation *This) { - if(!This->window || !This->window->base.outer_window) - return NULL; - return This->window->base.outer_window->uri; + return This->window ? This->window->uri : NULL; }
static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url) @@ -165,12 +163,12 @@ static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- if(!This->window || !This->window->base.outer_window) { + if(!This->window) { FIXME("No window available\n"); return E_FAIL; }
- return navigate_url(This->window->base.outer_window, v, This->window->base.outer_window->uri, BINDING_NAVIGATED); + return navigate_url(This->window, v, This->window->uri, BINDING_NAVIGATED); }
static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p) @@ -523,7 +521,7 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- if(!This->window || !This->window->base.outer_window) { + if(!This->window) { FIXME("No window available\n"); return E_FAIL; } @@ -536,7 +534,7 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v) memcpy(hash + 1, v, size - sizeof(WCHAR)); }
- hres = navigate_url(This->window->base.outer_window, hash, This->window->base.outer_window->uri, BINDING_NAVIGATED); + hres = navigate_url(This->window, hash, This->window->uri, BINDING_NAVIGATED);
if(hash != v) free(hash); @@ -585,12 +583,12 @@ static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL fla }
/* reload is supposed to fail if called from a script with different origin, but IE doesn't care */ - if(!is_main_content_window(This->window->base.outer_window)) { + if(!is_main_content_window(This->window)) { FIXME("Unsupported on iframe\n"); return E_NOTIMPL; }
- return reload_page(This->window->base.outer_window); + return reload_page(This->window); }
static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr) @@ -599,13 +597,12 @@ static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
- if(!This->window || !This->window->base.outer_window) { + if(!This->window) { FIXME("No window available\n"); return E_FAIL; }
- return navigate_url(This->window->base.outer_window, bstr, This->window->base.outer_window->uri, - BINDING_NAVIGATED|BINDING_REPLACE); + return navigate_url(This->window, bstr, This->window->uri, BINDING_NAVIGATED | BINDING_REPLACE); }
static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr) @@ -659,14 +656,14 @@ static const tid_t HTMLLocation_iface_tids[] = { 0 }; static dispex_static_data_t HTMLLocation_dispex = { - L"Object", + L"Location", NULL, DispHTMLLocation_tid, HTMLLocation_iface_tids };
-HRESULT HTMLLocation_Create(HTMLInnerWindow *window, HTMLLocation **ret) +HRESULT HTMLLocation_Create(HTMLOuterWindow *window, HTMLLocation **ret) { HTMLLocation *location;
@@ -679,7 +676,7 @@ HRESULT HTMLLocation_Create(HTMLInnerWindow *window, HTMLLocation **ret) location->window = window;
init_dispatch(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex, - dispex_compat_mode(&window->event_target.dispex)); + COMPAT_MODE_QUIRKS);
*ret = location; return S_OK; diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index c4c6a99f5f3..e678c9f99e0 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -67,7 +67,7 @@ static inline BOOL is_outer_window(HTMLWindow *window) return &window->outer_window->base == window; }
-static HRESULT get_location(HTMLInnerWindow *This, HTMLLocation **ret) +static HRESULT get_location(HTMLOuterWindow *This, HTMLLocation **ret) { if(!This->location) { HRESULT hres; @@ -133,6 +133,9 @@ static void detach_inner_window(HTMLInnerWindow *window) if(doc) detach_document_node(doc);
+ if(outer_window && outer_window->location) + dispex_unlink(&outer_window->location->dispex); + abort_window_bindings(window); remove_target_tasks(window->task_magic); release_script_hosts(window); @@ -237,6 +240,11 @@ static void release_outer_window(HTMLOuterWindow *This) if(This->base.inner_window) detach_inner_window(This->base.inner_window);
+ if(This->location) { + This->location->window = NULL; + IHTMLLocation_Release(&This->location->IHTMLLocation_iface); + } + if(This->frame_element) This->frame_element->content_window = NULL;
@@ -269,11 +277,6 @@ static void release_inner_window(HTMLInnerWindow *This) free(This->global_props[i].name); free(This->global_props);
- if(This->location) { - This->location->window = NULL; - IHTMLLocation_Release(&This->location->IHTMLLocation_iface); - } - if(This->image_factory) { This->image_factory->window = NULL; IHTMLImageElementFactory_Release(&This->image_factory->IHTMLImageElementFactory_iface); @@ -809,7 +812,7 @@ static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocatio
TRACE("(%p)->(%p)\n", This, p);
- hres = get_location(This->inner_window, &location); + hres = get_location(This->outer_window, &location); if(FAILED(hres)) return hres;
@@ -3922,7 +3925,7 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
TRACE("forwarding to location.href\n");
- hres = get_location(This, &location); + hres = get_location(This->base.outer_window, &location); if(FAILED(hres)) return hres;
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 870ba14c8b4..1ce25d5c862 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -493,7 +493,7 @@ struct HTMLLocation {
LONG ref;
- HTMLInnerWindow *window; + HTMLOuterWindow *window; };
typedef struct { @@ -576,6 +576,7 @@ struct HTMLOuterWindow { unsigned readystate_pending;
HTMLInnerWindow *pending_window; + HTMLLocation *location; IMoniker *mon; IUri *uri; IUri *uri_nofrag; @@ -619,8 +620,6 @@ struct HTMLInnerWindow {
LONG task_magic;
- HTMLLocation *location; - IMoniker *mon; nsChannelBSC *bscallback; struct list bindings; @@ -994,7 +993,7 @@ void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**) DECLSPEC_HIDDEN; HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**) DECLSPEC_HIDDEN; HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**) DECLSPEC_HIDDEN; HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**) DECLSPEC_HIDDEN; -HRESULT HTMLLocation_Create(HTMLInnerWindow*,HTMLLocation**) DECLSPEC_HIDDEN; +HRESULT HTMLLocation_Create(HTMLOuterWindow*,HTMLLocation**) DECLSPEC_HIDDEN; HRESULT create_navigator(compat_mode_t,IOmNavigator**) DECLSPEC_HIDDEN; HRESULT create_html_screen(compat_mode_t,IHTMLScreen**) DECLSPEC_HIDDEN; HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 2efbbbf513c..39af8faa8d5 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11813,11 +11813,14 @@ static void test_document_mode_lock(void) IHTMLWindow7 *window7; IHTMLWindow5 *window5; IHTMLWindow2 *window; + IDispatchEx *dispex; IStream *stream; + DISPID dispid; HRESULT hres; HGLOBAL mem; VARIANT var; SIZE_T len; + BSTR bstr; MSG msg;
notif_doc = doc = create_document(); @@ -11872,6 +11875,14 @@ static void test_document_mode_lock(void) IHTMLWindow2_Release(window); VariantClear(&var);
+ bstr = SysAllocString(L"wineTestProp"); + hres = IHTMLLocation_QueryInterface(location, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameEnsure, &dispid); + ok(hres == S_OK, "GetDispID(wineTestProp) returned: %08lx\n", hres); + IDispatchEx_Release(dispex); + SysFreeString(bstr); + len = strlen(doc_blank_ie9); mem = GlobalAlloc(0, len); memcpy(mem, doc_blank_ie9, len); @@ -11909,10 +11920,14 @@ static void test_document_mode_lock(void)
hres = IHTMLWindow2_get_location(window, &location2); ok(hres == S_OK, "get_location failed: %08lx\n", hres); - todo_wine ok(location == location2, "location != location2\n"); + + bstr = SysAllocString(L"wineTestProp"); + hres = IHTMLLocation_GetIDsOfNames(location2, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames(wineTestProp) returned: %08lx\n", hres); IHTMLLocation_Release(location2); IHTMLLocation_Release(location); + SysFreeString(bstr);
hres = IHTMLWindow2_get_navigator(window, &navigator2); ok(hres == S_OK, "get_navigator failed: %08lx\n", hres); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 196ab3160a7..34082bde871 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -3307,6 +3307,15 @@ static void test_doc_obj(IHTMLDocument2 *doc) IHTMLWindow7_Release(window7); VariantClear(&res);
+ /* Add prop to location, since it gets lost on navigation, despite being same object */ + bstr = SysAllocString(L"wineTestProp"); + hres = IHTMLLocation_QueryInterface(location, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameEnsure, &dispid); + ok(hres == S_OK, "GetDispID(wineTestProp) returned: %08lx\n", hres); + IDispatchEx_Release(dispex); + SysFreeString(bstr); + /* Navigate to a different document mode page, checking using the same doc obj. Test that it breaks COM rules, since IEventTarget is conditionally exposed. All the events registered on the old doc node are also removed. @@ -3356,10 +3365,14 @@ static void test_doc_obj(IHTMLDocument2 *doc)
hres = IHTMLWindow2_get_location(window, &location2); ok(hres == S_OK, "get_location failed: %08lx\n", hres); - todo_wine ok(location == location2, "location != location2\n"); + + bstr = SysAllocString(L"wineTestProp"); + hres = IHTMLLocation_GetIDsOfNames(location2, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames(wineTestProp) returned: %08lx\n", hres); IHTMLLocation_Release(location2); IHTMLLocation_Release(location); + SysFreeString(bstr);
hres = IHTMLWindow2_get_navigator(window, &navigator2); ok(hres == S_OK, "get_navigator failed: %08lx\n", hres);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Gets rid of the issues with the cyclic dependency or detached location.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmllocation.c | 80 ++++++------------------------------ dlls/mshtml/htmlwindow.c | 36 +++++----------- dlls/mshtml/mshtml_private.h | 8 +--- 3 files changed, 25 insertions(+), 99 deletions(-)
diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 5c31ee02e04..d9e458d9c5f 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -36,28 +36,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
-static HRESULT get_url(HTMLLocation *This, const WCHAR **ret) +static inline HTMLOuterWindow *get_window(HTMLLocation *This) { - if(!This->window || !This->window->url) - *ret = L"about:blank"; - else - *ret = This->window->url; - return S_OK; + return CONTAINING_RECORD(This, HTMLOuterWindow, location); }
static IUri *get_uri(HTMLLocation *This) { - return This->window ? This->window->uri : NULL; + return get_window(This)->uri; }
static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url) { - const WCHAR *doc_url; - HRESULT hres; - - hres = get_url(This, &doc_url); - if(FAILED(hres)) - return hres; + const WCHAR *doc_url = get_window(This)->url ? get_window(This)->url : L"about:blank";
if(!InternetCrackUrlW(doc_url, 0, 0, url)) { FIXME("InternetCrackUrlW failed: 0x%08lx\n", GetLastError()); @@ -102,28 +93,13 @@ static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID r static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - LONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - return ref; + return IHTMLWindow2_AddRef(&get_window(This)->base.IHTMLWindow2_iface); }
static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%ld\n", This, ref); - - if(!ref) { - if(This->window) - This->window->location = NULL; - release_dispex(&This->dispex); - free(This); - } - - return ref; + return IHTMLWindow2_Release(&get_window(This)->base.IHTMLWindow2_iface); }
static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo) @@ -163,12 +139,7 @@ static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- if(!This->window) { - FIXME("No window available\n"); - return E_FAIL; - } - - return navigate_url(This->window, v, This->window->uri, BINDING_NAVIGATED); + return navigate_url(get_window(This), v, get_uri(This), BINDING_NAVIGATED); }
static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p) @@ -521,11 +492,6 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- if(!This->window) { - FIXME("No window available\n"); - return E_FAIL; - } - if(hash[0] != '#') { unsigned size = (1 /* # */ + wcslen(v) + 1) * sizeof(WCHAR); if(!(hash = malloc(size))) @@ -534,7 +500,7 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v) memcpy(hash + 1, v, size - sizeof(WCHAR)); }
- hres = navigate_url(This->window, hash, This->window->uri, BINDING_NAVIGATED); + hres = navigate_url(get_window(This), hash, get_uri(This), BINDING_NAVIGATED);
if(hash != v) free(hash); @@ -577,18 +543,13 @@ static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL fla
TRACE("(%p)->(%x)\n", This, flag);
- if(!This->window) { - FIXME("No window available\n"); - return E_FAIL; - } - /* reload is supposed to fail if called from a script with different origin, but IE doesn't care */ - if(!is_main_content_window(This->window)) { + if(!is_main_content_window(get_window(This))) { FIXME("Unsupported on iframe\n"); return E_NOTIMPL; }
- return reload_page(This->window); + return reload_page(get_window(This)); }
static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr) @@ -597,12 +558,7 @@ static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
- if(!This->window) { - FIXME("No window available\n"); - return E_FAIL; - } - - return navigate_url(This->window, bstr, This->window->uri, BINDING_NAVIGATED | BINDING_REPLACE); + return navigate_url(get_window(This), bstr, get_uri(This), BINDING_NAVIGATED | BINDING_REPLACE); }
static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr) @@ -662,22 +618,10 @@ static dispex_static_data_t HTMLLocation_dispex = { HTMLLocation_iface_tids };
- -HRESULT HTMLLocation_Create(HTMLOuterWindow *window, HTMLLocation **ret) +void HTMLLocation_Init(HTMLLocation *location) { - HTMLLocation *location; - - location = malloc(sizeof(*location)); - if(!location) - return E_OUTOFMEMORY; - location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl; - location->ref = 1; - location->window = window;
init_dispatch(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex, COMPAT_MODE_QUIRKS); - - *ret = location; - return S_OK; } diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index e678c9f99e0..ed497eacf4e 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -67,19 +67,13 @@ static inline BOOL is_outer_window(HTMLWindow *window) return &window->outer_window->base == window; }
-static HRESULT get_location(HTMLOuterWindow *This, HTMLLocation **ret) +static void get_location(HTMLOuterWindow *This, HTMLLocation **ret) { - if(!This->location) { - HRESULT hres; + if(!This->location.dispex.outer) + HTMLLocation_Init(&This->location);
- hres = HTMLLocation_Create(This, &This->location); - if(FAILED(hres)) - return hres; - } - - IHTMLLocation_AddRef(&This->location->IHTMLLocation_iface); - *ret = This->location; - return S_OK; + IHTMLLocation_AddRef(&This->location.IHTMLLocation_iface); + *ret = &This->location; }
void get_top_window(HTMLOuterWindow *window, HTMLOuterWindow **ret) @@ -133,8 +127,8 @@ static void detach_inner_window(HTMLInnerWindow *window) if(doc) detach_document_node(doc);
- if(outer_window && outer_window->location) - dispex_unlink(&outer_window->location->dispex); + if(outer_window && outer_window->location.dispex.outer) + dispex_unlink(&outer_window->location.dispex);
abort_window_bindings(window); remove_target_tasks(window->task_magic); @@ -240,10 +234,8 @@ static void release_outer_window(HTMLOuterWindow *This) if(This->base.inner_window) detach_inner_window(This->base.inner_window);
- if(This->location) { - This->location->window = NULL; - IHTMLLocation_Release(&This->location->IHTMLLocation_iface); - } + if(This->location.dispex.outer) + release_dispex(&This->location.dispex);
if(This->frame_element) This->frame_element->content_window = NULL; @@ -808,14 +800,10 @@ static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocatio { HTMLWindow *This = impl_from_IHTMLWindow2(iface); HTMLLocation *location; - HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
- hres = get_location(This->outer_window, &location); - if(FAILED(hres)) - return hres; - + get_location(This->outer_window, &location); *p = &location->IHTMLLocation_iface; return S_OK; } @@ -3925,9 +3913,7 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
TRACE("forwarding to location.href\n");
- hres = get_location(This->base.outer_window, &location); - if(FAILED(hres)) - return hres; + get_location(This->base.outer_window, &location);
hres = IDispatchEx_InvokeEx(&location->dispex.IDispatchEx_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller); IHTMLLocation_Release(&location->IHTMLLocation_iface); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 1ce25d5c862..bec982a75fc 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -490,10 +490,6 @@ typedef struct { struct HTMLLocation { DispatchEx dispex; IHTMLLocation IHTMLLocation_iface; - - LONG ref; - - HTMLOuterWindow *window; };
typedef struct { @@ -576,7 +572,7 @@ struct HTMLOuterWindow { unsigned readystate_pending;
HTMLInnerWindow *pending_window; - HTMLLocation *location; + HTMLLocation location; IMoniker *mon; IUri *uri; IUri *uri_nofrag; @@ -993,7 +989,7 @@ void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**) DECLSPEC_HIDDEN; HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**) DECLSPEC_HIDDEN; HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**) DECLSPEC_HIDDEN; HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**) DECLSPEC_HIDDEN; -HRESULT HTMLLocation_Create(HTMLOuterWindow*,HTMLLocation**) DECLSPEC_HIDDEN; +void HTMLLocation_Init(HTMLLocation*) DECLSPEC_HIDDEN; HRESULT create_navigator(compat_mode_t,IOmNavigator**) DECLSPEC_HIDDEN; HRESULT create_html_screen(compat_mode_t,IHTMLScreen**) DECLSPEC_HIDDEN; HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**) DECLSPEC_HIDDEN;
Jacek Caban (@jacek) commented about dlls/mshtml/htmlwindow.c:
if(doc) detach_document_node(doc);
- if(outer_window && outer_window->location)
dispex_unlink(&outer_window->location->dispex);
There is still a similar problem with location's function objects (although it's more generic: we should probably generally traverse and unlink them).
On Wed Feb 1 14:39:25 2023 +0000, Jacek Caban wrote:
There is still a similar problem with location's function objects (although it's more generic: we should probably generally traverse and unlink them).
Yeah, I forgot that part is FIXME for now. Fixing it would fix this too, without requiring special handling.