This should fix some rare crashes in e.g. FFXIV Launcher (requires Proton patches to have it working though).
-- v2: mshtml: Use already available window local variable in refresh task. mshtml: Grab refs to windows upfront before sending pagehide events. mshtml: Hold ref to the frame element during readyState notifications. mshtml: Check if browser was detached during notifications while navigating. mshtml: Hold ref to outer window when navigating. mshtml: Hold ref to inner window when calling external code. mshtml: Hold ref to HTMLDocumentObj when calling external code.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
It's possible for it (and the GeckoBrowser) to get detached and destroyed while processing an external callback notification.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/editor.c | 10 +++++++--- dlls/mshtml/mutation.c | 3 +++ dlls/mshtml/navigate.c | 43 ++++++++++++++++++++++++++++++------------ dlls/mshtml/nsevents.c | 15 +++++++++------ dlls/mshtml/nsio.c | 11 +++++++++-- dlls/mshtml/persist.c | 22 +++++++++++++++------ dlls/mshtml/view.c | 3 +++ 7 files changed, 78 insertions(+), 29 deletions(-)
diff --git a/dlls/mshtml/editor.c b/dlls/mshtml/editor.c index 478c30932c1..b478bfdebf6 100644 --- a/dlls/mshtml/editor.c +++ b/dlls/mshtml/editor.c @@ -1195,6 +1195,7 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) return S_OK;
doc->nscontainer->usermode = EDITMODE; + IUnknown_AddRef(doc->outer_unk);
if(doc->window->mon) { CLSID clsid = IID_NULL; @@ -1250,14 +1251,14 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) hres = CreateURLMoniker(NULL, L"about:blank", &mon); if(FAILED(hres)) { FIXME("CreateURLMoniker failed: %08lx\n", hres); - return hres; + goto done; } }
hres = IPersistMoniker_Load(&doc->IPersistMoniker_iface, TRUE, mon, NULL, 0); IMoniker_Release(mon); if(FAILED(hres)) - return hres; + goto done;
if(doc->ui_active) { if(doc->ip_window) @@ -1281,6 +1282,9 @@ HRESULT setup_edit_mode(HTMLDocumentObj *doc) if(doc->frame) IOleInPlaceFrame_SetBorderSpace(doc->frame, &rcBorderWidths); } + hres = S_OK;
- return S_OK; +done: + IUnknown_Release(doc->outer_unk); + return hres; } diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index e308c1af31b..79850447f64 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -295,6 +295,7 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo
if(!This->doc_obj) return NS_OK; + IUnknown_AddRef(This->doc_obj->outer_unk);
if(This == This->doc_obj->doc_node) { /* @@ -308,6 +309,8 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo
This->window->performance_timing->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE); + + IUnknown_Release(This->doc_obj->outer_unk); return NS_OK; }
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index b8d7937f071..68fd8a796c0 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1651,6 +1651,7 @@ static void handle_extern_mime_navigation(nsChannelBSC *This) return;
doc_obj = This->bsc.window->base.outer_window->browser->doc; + IUnknown_AddRef(doc_obj->outer_unk);
hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg); if(SUCCEEDED(hres)) { @@ -1662,17 +1663,17 @@ static void handle_extern_mime_navigation(nsChannelBSC *This)
if(!doc_obj->webbrowser) { FIXME("unimplemented in non-webbrowser mode\n"); - return; + goto done; }
uri = get_moniker_uri(This->bsc.mon); if(!uri) - return; + goto done;
hres = CreateBindCtx(0, &bind_ctx); if(FAILED(hres)) { IUri_Release(uri); - return; + goto done; }
V_VT(&flags) = VT_I4; @@ -1701,6 +1702,9 @@ static void handle_extern_mime_navigation(nsChannelBSC *This) }
IUri_Release(uri); + +done: + IUnknown_Release(doc_obj->outer_unk); }
static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG total, ULONG status_code, LPCWSTR status_text) @@ -2066,25 +2070,31 @@ static void navigate_javascript_proc(task_t *_task) { navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task; HTMLOuterWindow *window = task->window; + HTMLDocumentObj *doc = NULL; BSTR code = NULL; VARIANT v; HRESULT hres;
- task->window->readystate = READYSTATE_COMPLETE; + window->readystate = READYSTATE_COMPLETE; + if(window->browser) { + doc = window->browser->doc; + IUnknown_AddRef(doc->outer_unk); + }
hres = IUri_GetPath(task->uri, &code); if(hres != S_OK) { SysFreeString(code); - return; + goto done; }
hres = UrlUnescapeW(code, NULL, NULL, URL_UNESCAPE_INPLACE); if(FAILED(hres)) { SysFreeString(code); - return; + goto done; }
- set_download_state(window->browser->doc, 1); + if(doc) + set_download_state(doc, 1);
V_VT(&v) = VT_EMPTY; hres = exec_script(window->base.inner_window, code, L"jscript", &v); @@ -2094,10 +2104,16 @@ static void navigate_javascript_proc(task_t *_task) VariantClear(&v); }
- if(window->browser->doc->view_sink) - IAdviseSink_OnViewChange(window->browser->doc->view_sink, DVASPECT_CONTENT, -1); + if(doc) { + if(doc->view_sink) + IAdviseSink_OnViewChange(doc->view_sink, DVASPECT_CONTENT, -1); + + set_download_state(doc, 0); + }
- set_download_state(window->browser->doc, 0); +done: + if(doc) + IUnknown_Release(doc->outer_unk); }
static void navigate_javascript_task_destr(task_t *_task) @@ -2199,9 +2215,12 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri) SysFreeString(frag);
if(window->browser->doc->doc_object_service) { - IDocObjectService_FireNavigateComplete2(window->browser->doc->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10); - IDocObjectService_FireDocumentComplete(window->browser->doc->doc_object_service, &window->base.IHTMLWindow2_iface, 0); + HTMLDocumentObj *doc_obj = window->browser->doc;
+ IUnknown_AddRef(doc_obj->outer_unk); + IDocObjectService_FireNavigateComplete2(doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10); + IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0); + IUnknown_Release(doc_obj->outer_unk); }
return S_OK; diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index b3616b64964..177981acc25 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -339,9 +339,10 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event)
if(!doc->outer_window) return NS_ERROR_FAILURE; - if(doc->doc_obj && doc->doc_obj->doc_node == doc) + if(doc->doc_obj && doc->doc_obj->doc_node == doc) { doc_obj = doc->doc_obj; - + IUnknown_AddRef(doc_obj->outer_unk); + } connect_scripts(doc->window);
if(doc_obj) @@ -357,11 +358,13 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event) set_statustext(doc_obj, IDS_STATUS_DONE, NULL);
update_title(doc_obj); - }
- if(doc_obj && doc_obj->doc_object_service && !(doc->outer_window->load_flags & BINDING_REFRESH)) - IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, - &doc->outer_window->base.IHTMLWindow2_iface, 0); + if(doc_obj->doc_object_service && !(doc->outer_window->load_flags & BINDING_REFRESH)) + IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, + &doc->outer_window->base.IHTMLWindow2_iface, 0); + + IUnknown_Release(doc_obj->outer_unk); + }
doc->window->performance_timing->load_event_start_time = get_time_stamp();
diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index 509a83efbd3..d29bb43544e 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -217,6 +217,9 @@ static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, BSTR url) IOleCommandTarget *cmdtrg = NULL; HRESULT hres;
+ if(!doc->client) + return TRUE; + hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg); if(SUCCEEDED(hres)) { VARIANT varUrl, varRes; @@ -252,6 +255,7 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B hres = IUri_GetDisplayUri(channel->uri->uri, &display_uri); if(FAILED(hres)) return NS_ERROR_FAILURE; + IUnknown_AddRef(doc->outer_unk);
if(doc->hostui) { OLECHAR *new_url; @@ -261,7 +265,7 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(display_uri), debugstr_w(new_url)); CoTaskMemFree(new_url); *cancel = TRUE; - return NS_OK; + goto done; } CoTaskMemFree(new_url); } @@ -270,13 +274,16 @@ static nsresult before_async_open(nsChannel *channel, GeckoBrowser *container, B if(!exec_shldocvw_67(doc, display_uri)) { SysFreeString(display_uri); *cancel = FALSE; - return NS_OK; + goto done; }
hres = hlink_frame_navigate(doc, display_uri, channel, 0, cancel); SysFreeString(display_uri); if(FAILED(hres)) *cancel = TRUE; + +done: + IUnknown_Release(doc->outer_unk); return NS_OK; }
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 486643d8b21..94b52e3a476 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -208,6 +208,8 @@ static void set_progress_proc(task_t *_task)
TRACE("(%p)\n", doc);
+ IUnknown_AddRef(doc->outer_unk); + if(doc->client) IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
@@ -238,6 +240,8 @@ static void set_progress_proc(task_t *_task) hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick, debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS)); } + + IUnknown_Release(doc->outer_unk); }
static void set_progress_destr(task_t *_task) @@ -252,13 +256,14 @@ static void set_downloading_proc(task_t *_task)
TRACE("(%p)\n", doc);
+ IUnknown_AddRef(doc->outer_unk); set_statustext(doc, IDS_STATUS_DOWNLOADINGFROM, task->url);
if(task->set_download) set_download_state(doc, 1);
if(!doc->client) - return; + goto done;
if(doc->view_sink) IAdviseSink_OnViewChange(doc->view_sink, DVASPECT_CONTENT, -1); @@ -272,6 +277,9 @@ static void set_downloading_proc(task_t *_task) IDropTarget_Release(drop_target); } } + +done: + IUnknown_Release(doc->outer_unk); }
static void set_downloading_task_destr(task_t *_task) @@ -285,6 +293,8 @@ void prepare_for_binding(HTMLDocumentObj *This, IMoniker *mon, DWORD flags) { HRESULT hres;
+ IUnknown_AddRef(This->outer_unk); + if(This->client) { VARIANT silent, offline;
@@ -335,22 +345,20 @@ void prepare_for_binding(HTMLDocumentObj *This, IMoniker *mon, DWORD flags) IOleCommandTarget_Release(cmdtrg); } } + + IUnknown_Release(This->outer_unk); }
HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBindCtx *pibc, nsChannelBSC *async_bsc, BOOL set_download) { download_proc_task_t *download_task; - HTMLDocumentObj *doc_obj = NULL; nsChannelBSC *bscallback; nsWineURI *nsuri; LPOLESTR url; IUri *uri; HRESULT hres;
- if(is_main_content_window(window)) - doc_obj = window->browser->doc; - hres = IMoniker_GetDisplayName(mon, pibc, NULL, &url); if(FAILED(hres)) { WARN("GetDisplayName failed: %08lx\n", hres); @@ -401,7 +409,9 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind return hres; }
- if(doc_obj) { + if(is_main_content_window(window)) { + HTMLDocumentObj *doc_obj = window->browser->doc; + HTMLDocument_LockContainer(doc_obj, TRUE);
if(doc_obj->frame) { diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 6b7ecb0bc27..346fccf4955 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -117,6 +117,7 @@ static LRESULT on_timer(HTMLDocumentObj *This)
if(!This->update) return 0; + IUnknown_AddRef(This->outer_unk);
if(This->update & UPDATE_UI) { if(This->hostui) @@ -138,6 +139,8 @@ static LRESULT on_timer(HTMLDocumentObj *This)
update_title(This); This->update = 0; + + IUnknown_Release(This->outer_unk); return 0; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
It's possible for it to get detached while processing an external callback notification, such as when navigation happens during it.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mutation.c | 5 +++-- dlls/mshtml/navigate.c | 12 ++++++++++-- dlls/mshtml/persist.c | 8 ++++++-- 3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 79850447f64..74424bb8afc 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -296,6 +296,7 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo if(!This->doc_obj) return NS_OK; IUnknown_AddRef(This->doc_obj->outer_unk); + IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
if(This == This->doc_obj->doc_node) { /* @@ -310,6 +311,7 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo This->window->performance_timing->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE);
+ IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); IUnknown_Release(This->doc_obj->outer_unk); return NS_OK; } @@ -367,14 +369,13 @@ static nsresult run_insert_script(HTMLDocumentNode *doc, nsISupports *script_ifa free(iter); }
- IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); - if(nsparser) { window->parser_callback_cnt--; nsIParser_EndEvaluatingParserInsertedScript(nsparser); nsIParser_Release(nsparser); }
+ IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface);
return NS_OK; diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 68fd8a796c0..e7575790a8a 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1419,8 +1419,11 @@ static void stop_request_task_destr(task_t *_task)
static HRESULT async_stop_request(nsChannelBSC *This) { + HTMLInnerWindow *window = This->bsc.window; stop_request_task_t *task; + HRESULT hres;
+ IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); if(!This->bsc.read) { TRACE("No data read, calling OnStartRequest\n"); on_start_nsrequest(This); @@ -1433,7 +1436,9 @@ static HRESULT async_stop_request(nsChannelBSC *This) IBindStatusCallback_AddRef(&This->bsc.IBindStatusCallback_iface); task->bsc = This;
- return push_task(&task->header, stop_request_proc, stop_request_task_destr, This->bsc.window->task_magic); + hres = push_task(&task->header, stop_request_proc, stop_request_task_destr, window->task_magic); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + return hres; }
static void handle_navigation_error(nsChannelBSC *This, DWORD result) @@ -2069,6 +2074,7 @@ typedef struct { static void navigate_javascript_proc(task_t *_task) { navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task; + HTMLInnerWindow *inner_window = task->window->base.inner_window; HTMLOuterWindow *window = task->window; HTMLDocumentObj *doc = NULL; BSTR code = NULL; @@ -2080,6 +2086,7 @@ static void navigate_javascript_proc(task_t *_task) doc = window->browser->doc; IUnknown_AddRef(doc->outer_unk); } + IHTMLWindow2_AddRef(&inner_window->base.IHTMLWindow2_iface);
hres = IUri_GetPath(task->uri, &code); if(hres != S_OK) { @@ -2097,7 +2104,7 @@ static void navigate_javascript_proc(task_t *_task) set_download_state(doc, 1);
V_VT(&v) = VT_EMPTY; - hres = exec_script(window->base.inner_window, code, L"jscript", &v); + hres = exec_script(inner_window, code, L"jscript", &v); SysFreeString(code); if(SUCCEEDED(hres) && V_VT(&v) != VT_EMPTY) { FIXME("javascirpt URL returned %s\n", debugstr_variant(&v)); @@ -2112,6 +2119,7 @@ static void navigate_javascript_proc(task_t *_task) }
done: + IHTMLWindow2_Release(&inner_window->base.IHTMLWindow2_iface); if(doc) IUnknown_Release(doc->outer_unk); } diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 94b52e3a476..da9dafedfa1 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -441,20 +441,24 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind
static void notif_readystate(HTMLOuterWindow *window) { + HTMLInnerWindow *inner_window = window->base.inner_window; DOMEvent *event; HRESULT hres;
window->readystate_pending = FALSE;
+ IHTMLWindow2_AddRef(&inner_window->base.IHTMLWindow2_iface); + if(is_main_content_window(window)) call_property_onchanged(&window->browser->doc->cp_container, DISPID_READYSTATE);
- hres = create_document_event(window->base.inner_window->doc, EVENTID_READYSTATECHANGE, &event); + hres = create_document_event(inner_window->doc, EVENTID_READYSTATECHANGE, &event); if(SUCCEEDED(hres)) { event->no_event_obj = TRUE; - dispatch_event(&window->base.inner_window->doc->node.event_target, event); + dispatch_event(&inner_window->doc->node.event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } + IHTMLWindow2_Release(&inner_window->base.IHTMLWindow2_iface);
if(window->frame_element) { hres = create_document_event(window->frame_element->element.node.doc, EVENTID_READYSTATECHANGE, &event);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
It's possible for it to get destroyed while processing an external callback notification.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/navigate.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index e7575790a8a..464a42db3a0 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1948,8 +1948,12 @@ typedef struct { static void start_doc_binding_proc(task_t *_task) { start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task; + HTMLOuterWindow *window = task->window; + + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + set_current_mon(window, task->pending_window->bscallback->bsc.mon, task->flags); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
- set_current_mon(task->window, task->pending_window->bscallback->bsc.mon, task->flags); start_binding(task->pending_window, &task->pending_window->bscallback->bsc, NULL); }
@@ -2016,6 +2020,7 @@ void abort_window_bindings(HTMLInnerWindow *window)
HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, IStream *stream) { + HTMLOuterWindow *window = pending_window->base.outer_window; nsChannelBSC *bscallback = pending_window->bscallback; HRESULT hres = S_OK;
@@ -2028,7 +2033,9 @@ HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, I if(!bscallback->nschannel->content_type) return E_OUTOFMEMORY;
- set_current_mon(pending_window->base.outer_window, mon, 0); + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + set_current_mon(window, mon, 0); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
bscallback->bsc.window = pending_window; if(stream) @@ -2143,14 +2150,19 @@ typedef struct { static void navigate_proc(task_t *_task) { navigate_task_t *task = (navigate_task_t*)_task; + HTMLOuterWindow *window = task->window; HRESULT hres;
- hres = set_moniker(task->window, task->mon, task->uri, NULL, task->bscallback, TRUE); + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + + hres = set_moniker(window, task->mon, task->uri, NULL, task->bscallback, TRUE); if(SUCCEEDED(hres)) { - set_current_mon(task->window, task->bscallback->bsc.mon, task->flags); - set_current_uri(task->window, task->uri); - start_binding(task->window->pending_window, &task->bscallback->bsc, NULL); + set_current_mon(window, task->bscallback->bsc.mon, task->flags); + set_current_uri(window, task->uri); + start_binding(window->pending_window, &task->bscallback->bsc, NULL); } + + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); }
static void navigate_task_destr(task_t *_task) @@ -2666,14 +2678,16 @@ HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_u hres = create_uri(new_url, 0, &nav_uri); if(FAILED(hres)) return hres; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
hres = translate_uri(window, nav_uri, &display_uri, &uri); IUri_Release(nav_uri); - if(FAILED(hres)) - return hres; + if(SUCCEEDED(hres)) { + hres = navigate_uri(window, uri, display_uri, NULL, flags); + IUri_Release(uri); + SysFreeString(display_uri); + }
- hres = navigate_uri(window, uri, display_uri, NULL, flags); - IUri_Release(uri); - SysFreeString(display_uri); + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); return hres; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/navigate.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 464a42db3a0..1eb9222b68a 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -2279,6 +2279,9 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC SysFreeString(url_str); } } + + if(!window->browser) + return S_OK; }
if(!(flags & BINDING_NOFRAG) && window->uri_nofrag && !post_data_size) { @@ -2307,6 +2310,11 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC }
prepare_for_binding(window->browser->doc, mon, flags); + if(!window->browser) { + IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface); + IMoniker_Release(mon); + return S_OK; + }
hres = IUri_GetScheme(uri, &scheme); if(hres == S_OK && scheme == URL_SCHEME_JAVASCRIPT) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/persist.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index da9dafedfa1..bbecc8ce1c2 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -442,12 +442,15 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind static void notif_readystate(HTMLOuterWindow *window) { HTMLInnerWindow *inner_window = window->base.inner_window; + HTMLFrameBase *frame_element = window->frame_element; DOMEvent *event; HRESULT hres;
window->readystate_pending = FALSE;
IHTMLWindow2_AddRef(&inner_window->base.IHTMLWindow2_iface); + if(frame_element) + IHTMLDOMNode_AddRef(&frame_element->element.node.IHTMLDOMNode_iface);
if(is_main_content_window(window)) call_property_onchanged(&window->browser->doc->cp_container, DISPID_READYSTATE); @@ -460,12 +463,13 @@ static void notif_readystate(HTMLOuterWindow *window) } IHTMLWindow2_Release(&inner_window->base.IHTMLWindow2_iface);
- if(window->frame_element) { - hres = create_document_event(window->frame_element->element.node.doc, EVENTID_READYSTATECHANGE, &event); + if(frame_element) { + hres = create_document_event(frame_element->element.node.doc, EVENTID_READYSTATECHANGE, &event); if(SUCCEEDED(hres)) { - dispatch_event(&window->frame_element->element.node.event_target, event); + dispatch_event(&frame_element->element.node.event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } + IHTMLDOMNode_Release(&frame_element->element.node.IHTMLDOMNode_iface); } }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/view.c | 74 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 346fccf4955..3f31e609e39 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -414,45 +414,73 @@ HRESULT call_set_active_object(IOleInPlaceUIWindow *window, IOleInPlaceActiveObj return IOleInPlaceUIWindow_SetActiveObject(window, act_obj, act_obj ? html_documentW : NULL); }
-static void send_unload_events_impl(HTMLInnerWindow *window) +static unsigned get_window_list_num(HTMLInnerWindow *window) { HTMLOuterWindow *child; + unsigned ret = 1; + + LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) + ret += get_window_list_num(child->base.inner_window); + return ret; +} + +static HTMLInnerWindow **get_window_list(HTMLInnerWindow *window, HTMLInnerWindow **output) +{ + HTMLOuterWindow *child; + + *output++ = window; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); + + LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) + output = get_window_list(child->base.inner_window, output); + return output; +} + +static void send_unload_events(HTMLDocumentObj *doc) +{ + HTMLInnerWindow **windows, *window; DOMEvent *event; + unsigned i, num; HRESULT hres;
- if(!window) + if(!doc->window || !doc->doc_node->content_ready) + return; + window = doc->window->base.inner_window; + + /* Grab list of all windows ahead, and keep refs, + since it can be detached from under our feet. */ + num = get_window_list_num(window); + if(!(windows = malloc(num * sizeof(*windows)))) return; + get_window_list(window, windows); + + for(i = 0; i < num; i++) { + window = windows[i];
- if(window->doc && !window->doc->unload_sent) { - window->doc->unload_sent = TRUE; + if(window->doc && !window->doc->unload_sent) { + window->doc->unload_sent = TRUE; + + /* Native sends pagehide events prior to unload on the same window + before it moves on to the next window, so they're interleaved. */ + if(window->doc->document_mode >= COMPAT_MODE_IE11) { + hres = create_document_event(window->doc, EVENTID_PAGEHIDE, &event); + if(SUCCEEDED(hres)) { + dispatch_event(&window->event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + }
- /* Native sends pagehide events prior to unload on the same window - before it moves on to the next window, so they're interleaved. */ - if(window->doc->document_mode >= COMPAT_MODE_IE11) { - hres = create_document_event(window->doc, EVENTID_PAGEHIDE, &event); + hres = create_document_event(window->doc, EVENTID_UNLOAD, &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); } }
- hres = create_document_event(window->doc, EVENTID_UNLOAD, &event); - if(SUCCEEDED(hres)) { - dispatch_event(&window->event_target, event); - IDOMEvent_Release(&event->IDOMEvent_iface); - } + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); }
- LIST_FOR_EACH_ENTRY(child, &window->children, HTMLOuterWindow, sibling_entry) - send_unload_events_impl(child->base.inner_window); -} - -static void send_unload_events(HTMLDocumentObj *doc) -{ - if(!doc->window || !doc->doc_node->content_ready) - return; - - send_unload_events_impl(doc->window->base.inner_window); + free(windows); }
/**********************************************************
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/olecmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mshtml/olecmd.c b/dlls/mshtml/olecmd.c index 9e59778ccb9..ff900c76c04 100644 --- a/dlls/mshtml/olecmd.c +++ b/dlls/mshtml/olecmd.c @@ -438,7 +438,7 @@ static void refresh_proc(task_t *_task) IOleCommandTarget_Exec(window->browser->doc->client_cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL); }
- load_uri(task->window, task->window->uri, BINDING_REFRESH|BINDING_NOFRAG); + load_uri(window, window->uri, BINDING_REFRESH|BINDING_NOFRAG); }
static void refresh_destr(task_t *_task)
Jacek Caban (@jacek) commented about dlls/mshtml/editor.c:
return S_OK; doc->nscontainer->usermode = EDITMODE;
- IUnknown_AddRef(doc->outer_unk);
In principle, it's caller responsibility to own a reference to "this-alike" objects. The root of the problem is that when using things like This->doc, it's owned by This object, not the caller. I'd suggest to move that AddRef to callers.
Jacek Caban (@jacek) commented about dlls/mshtml/mutation.c:
if(!This->doc_obj) return NS_OK;
- IUnknown_AddRef(This->doc_obj->outer_unk);
Please store doc_obj in a local variable when you need an extra reference. This makes it much easier to follow as otherwise you need to be sure that the pointer didn't change between AddRef and Release. You also need extra reference only around `parse_complete()` call.