From: Gabriel Ivăncescu <gabrielopcode(a)gmail.com> Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com> --- dlls/mshtml/htmllocation.c | 50 +++++++++++++++++++++++++----------- dlls/mshtml/htmlwindow.c | 32 +++++++++++++++-------- dlls/mshtml/mshtml_private.h | 8 ++++-- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 1e340487f0b..5473ecebebb 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -36,19 +36,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); -static inline HTMLOuterWindow *get_window(HTMLLocation *This) -{ - return CONTAINING_RECORD(This, HTMLOuterWindow, location); -} - static IUri *get_uri(HTMLLocation *This) { - return get_window(This)->uri; + return This->window->uri; } static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url) { - const WCHAR *doc_url = get_window(This)->url ? get_window(This)->url : L"about:blank"; + const WCHAR *doc_url = This->window->url ? This->window->url : L"about:blank"; if(!InternetCrackUrlW(doc_url, 0, 0, url)) { FIXME("InternetCrackUrlW failed: 0x%08lx\n", GetLastError()); @@ -93,13 +88,27 @@ static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID r static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - return IHTMLWindow2_AddRef(&get_window(This)->base.IHTMLWindow2_iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; } static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - return IHTMLWindow2_Release(&get_window(This)->base.IHTMLWindow2_iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); + release_dispex(&This->dispex); + free(This); + } + + return ref; } static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo) @@ -139,7 +148,7 @@ static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v) TRACE("(%p)->(%s)\n", This, debugstr_w(v)); - return navigate_url(get_window(This), v, get_uri(This), BINDING_NAVIGATED); + return navigate_url(This->window, v, get_uri(This), BINDING_NAVIGATED); } static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p) @@ -500,7 +509,7 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v) memcpy(hash + 1, v, size - sizeof(WCHAR)); } - hres = navigate_url(get_window(This), hash, get_uri(This), BINDING_NAVIGATED); + hres = navigate_url(This->window, hash, get_uri(This), BINDING_NAVIGATED); if(hash != v) free(hash); @@ -544,12 +553,12 @@ static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL fla TRACE("(%p)->(%x)\n", This, flag); /* reload is supposed to fail if called from a script with different origin, but IE doesn't care */ - if(!is_main_content_window(get_window(This))) { + if(!is_main_content_window(This->window)) { FIXME("Unsupported on iframe\n"); return E_NOTIMPL; } - return reload_page(get_window(This)); + return reload_page(This->window); } static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr) @@ -558,7 +567,7 @@ static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr) TRACE("(%p)->(%s)\n", This, debugstr_w(bstr)); - return navigate_url(get_window(This), bstr, get_uri(This), BINDING_NAVIGATED | BINDING_REPLACE); + return navigate_url(This->window, bstr, get_uri(This), BINDING_NAVIGATED | BINDING_REPLACE); } static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr) @@ -618,10 +627,21 @@ static dispex_static_data_t HTMLLocation_dispex = { HTMLLocation_iface_tids }; -void HTMLLocation_Init(HTMLLocation *location) +HRESULT create_location(HTMLOuterWindow *window, HTMLLocation **ret) { + HTMLLocation *location; + + if(!(location = calloc(1, sizeof(*location)))) + return E_OUTOFMEMORY; + location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl; + location->ref = 1; + location->window = window; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); 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 d139cc51fd7..a6b204881d2 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -67,13 +67,17 @@ static inline BOOL is_outer_window(HTMLWindow *window) return &window->outer_window->base == window; } -static void get_location(HTMLOuterWindow *This, HTMLLocation **ret) +static HRESULT get_location(HTMLOuterWindow *This, HTMLLocation **ret) { - if(!This->location.dispex.outer) - HTMLLocation_Init(&This->location); + if(!This->location) { + HRESULT hres = create_location(This, &This->location); + if(FAILED(hres)) + return hres; + } - IHTMLLocation_AddRef(&This->location.IHTMLLocation_iface); - *ret = &This->location; + IHTMLLocation_AddRef(&This->location->IHTMLLocation_iface); + *ret = This->location; + return S_OK; } void get_top_window(HTMLOuterWindow *window, HTMLOuterWindow **ret) @@ -127,8 +131,8 @@ static void detach_inner_window(HTMLInnerWindow *window) if(doc) detach_document_node(doc); - if(outer_window && outer_window->location.dispex.outer) - dispex_unlink(&outer_window->location.dispex); + if(outer_window && outer_window->location) + dispex_unlink(&outer_window->location->dispex); abort_window_bindings(window); remove_target_tasks(window->task_magic); @@ -234,8 +238,8 @@ static void release_outer_window(HTMLOuterWindow *This) if(This->base.inner_window) detach_inner_window(This->base.inner_window); - if(This->location.dispex.outer) - release_dispex(&This->location.dispex); + if(This->location) + IHTMLLocation_Release(&This->location->IHTMLLocation_iface); if(This->frame_element) This->frame_element->content_window = NULL; @@ -737,10 +741,14 @@ 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); - get_location(This->outer_window, &location); + hres = get_location(This->outer_window, &location); + if(FAILED(hres)) + return hres; + *p = &location->IHTMLLocation_iface; return S_OK; } @@ -3956,7 +3964,9 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA TRACE("forwarding to location.href\n"); - get_location(This->base.outer_window, &location); + hres = get_location(This->base.outer_window, &location); + if(FAILED(hres)) + return hres; 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 9aa36f3d30f..32ab0fa871a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -513,6 +513,10 @@ typedef struct { struct HTMLLocation { DispatchEx dispex; IHTMLLocation IHTMLLocation_iface; + + LONG ref; + + HTMLOuterWindow *window; }; typedef struct { @@ -568,7 +572,7 @@ struct HTMLOuterWindow { BOOL readystate_pending; HTMLInnerWindow *pending_window; - HTMLLocation location; + HTMLLocation *location; IMoniker *mon; IUri *uri; IUri *uri_nofrag; @@ -1005,7 +1009,7 @@ void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**); HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**); HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**); -void HTMLLocation_Init(HTMLLocation*); +HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(compat_mode_t,IOmNavigator**); HRESULT create_html_screen(compat_mode_t,IHTMLScreen**); HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/3542