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/htmldoc.c | 6 +++- dlls/mshtml/mutation.c | 10 ++++-- dlls/mshtml/navigate.c | 75 +++++++++++++++++++++++++++++------------- dlls/mshtml/nsevents.c | 15 +++++---- dlls/mshtml/nsio.c | 11 +++++-- dlls/mshtml/olecmd.c | 9 ++++- dlls/mshtml/persist.c | 18 ++++++---- dlls/mshtml/view.c | 3 ++ 8 files changed, 105 insertions(+), 42 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 2b885d479ab..f3a370848da 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -854,6 +854,7 @@ static HRESULT WINAPI HTMLDocument_get_scripts(IHTMLDocument2 *iface, IHTMLEleme static HRESULT WINAPI HTMLDocument_put_designMode(IHTMLDocument2 *iface, BSTR v) { HTMLDocumentNode *This = impl_from_IHTMLDocument2(iface); + HTMLDocumentObj *doc_obj; HRESULT hres;
TRACE("(%p)->(%s)\n", This, debugstr_w(v)); @@ -863,7 +864,10 @@ static HRESULT WINAPI HTMLDocument_put_designMode(IHTMLDocument2 *iface, BSTR v) return E_NOTIMPL; }
- hres = setup_edit_mode(This->doc_obj); + doc_obj = This->doc_obj; + IUnknown_AddRef(doc_obj->outer_unk); + hres = setup_edit_mode(doc_obj); + IUnknown_Release(doc_obj->outer_unk); if(FAILED(hres)) return hres;
diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index e308c1af31b..05ebf706dd0 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -291,17 +291,21 @@ static void parse_complete(HTMLDocumentObj *doc)
static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISupports *arg2) { + HTMLDocumentObj *doc_obj = This->doc_obj; + TRACE("(%p)\n", This);
- if(!This->doc_obj) + if(!doc_obj) return NS_OK;
- if(This == This->doc_obj->doc_node) { + if(This == doc_obj->doc_node) { /* * This should be done in the worker thread that parses HTML, * but we don't have such thread (Gecko parses HTML for us). */ - parse_complete(This->doc_obj); + IUnknown_AddRef(doc_obj->outer_unk); + parse_complete(doc_obj); + IUnknown_Release(doc_obj->outer_unk); }
bind_event_scripts(This); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index b8d7937f071..b2fc0473aa1 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; @@ -2209,6 +2228,7 @@ static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WCHAR *headers, BYTE *post_data, DWORD post_data_size) { + HTMLDocumentObj *doc_obj; nsChannelBSC *bsc; IUri *uri_nofrag; IMoniker *mon; @@ -2219,10 +2239,13 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC if(!uri_nofrag) return E_FAIL;
- if(window->browser->doc->client && !(flags & BINDING_REFRESH)) { + doc_obj = window->browser->doc; + IUnknown_AddRef(doc_obj->outer_unk); + + if(doc_obj->client && !(flags & BINDING_REFRESH)) { IOleCommandTarget *cmdtrg;
- hres = IOleClientSite_QueryInterface(window->browser->doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg); + hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg); if(SUCCEEDED(hres)) { VARIANT in, out; BSTR url_str; @@ -2249,14 +2272,15 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC if(SUCCEEDED(hres) && eq) { IUri_Release(uri_nofrag); TRACE("fragment navigate\n"); - return navigate_fragment(window, uri); + hres = navigate_fragment(window, uri); + goto done; } }
hres = CreateURLMonikerEx2(NULL, uri_nofrag, &mon, URL_MK_UNIFORM); IUri_Release(uri_nofrag); if(FAILED(hres)) - return hres; + goto done;
/* FIXME: Why not set_ready_state? */ window->readystate = READYSTATE_UNINITIALIZED; @@ -2264,10 +2288,10 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC hres = create_channelbsc(mon, headers, post_data, post_data_size, TRUE, &bsc); if(FAILED(hres)) { IMoniker_Release(mon); - return hres; + goto done; }
- prepare_for_binding(window->browser->doc, mon, flags); + prepare_for_binding(doc_obj, mon, flags);
hres = IUri_GetScheme(uri, &scheme); if(hres == S_OK && scheme == URL_SCHEME_JAVASCRIPT) { @@ -2277,13 +2301,15 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC IMoniker_Release(mon);
task = malloc(sizeof(*task)); - if(!task) - return E_OUTOFMEMORY; + if(!task) { + hres = E_OUTOFMEMORY; + goto done; + }
/* Why silently? */ window->readystate = READYSTATE_COMPLETE; if(!(flags & BINDING_FROMHIST)) - call_docview_84(window->browser->doc); + call_docview_84(doc_obj);
IUri_AddRef(uri); task->window = window; @@ -2302,13 +2328,14 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC if(!task) { IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface); IMoniker_Release(mon); - return E_OUTOFMEMORY; + hres = E_OUTOFMEMORY; + goto done; }
/* Silently and repeated when real loading starts? */ window->readystate = READYSTATE_LOADING; if(!(flags & (BINDING_FROMHIST|BINDING_REFRESH))) - call_docview_84(window->browser->doc); + call_docview_84(doc_obj);
task->window = window; task->bscallback = bsc; @@ -2320,6 +2347,8 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WC hres = push_task(&task->header, navigate_proc, navigate_task_destr, window->task_magic); }
+done: + IUnknown_Release(doc_obj->outer_unk); return hres; }
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/olecmd.c b/dlls/mshtml/olecmd.c index 9e59778ccb9..8f51292e5fc 100644 --- a/dlls/mshtml/olecmd.c +++ b/dlls/mshtml/olecmd.c @@ -687,12 +687,19 @@ static HRESULT exec_browsemode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT
static HRESULT exec_editmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out) { + HTMLDocumentObj *doc_obj; + HRESULT hres; + TRACE("(%p)->(%08lx %p %p)\n", doc, cmdexecopt, in, out);
if(in || out) FIXME("unsupported args\n");
- return setup_edit_mode(doc->browser->doc); + doc_obj = doc->browser->doc; + IUnknown_AddRef(doc_obj->outer_unk); + hres = setup_edit_mode(doc_obj); + IUnknown_Release(doc_obj->outer_unk); + return hres; }
static HRESULT exec_htmleditmode(HTMLDocumentNode *doc, DWORD cmdexecopt, VARIANT *in, VARIANT *out) diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 486643d8b21..620f6428d35 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) @@ -341,16 +349,12 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind 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 +405,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; }