diff --git a/dlls/ieframe/ie.c b/dlls/ieframe/ie.c index 42602f992b5..8ee2819d5b2 100644 --- a/dlls/ieframe/ie.c +++ b/dlls/ieframe/ie.c @@ -713,6 +713,31 @@ static inline InternetExplorer *impl_from_IExternalConnection(IExternalConnectio return CONTAINING_RECORD(iface, InternetExplorer, IExternalConnection_iface); } +/* + * Document may keep references to InternetExplorer object causing circular references. + * We keep track of external references and release the document object when all + * external references are released. A visible main window is also considered as + * an external reference. + */ +DWORD release_extern_ref(InternetExplorer *This, BOOL last_closes) +{ + LONG ref = InterlockedDecrement(&This->extern_ref); + + TRACE("ref = %d\n", ref); + + if(ref) + return ref; + + if(!last_closes) { + WARN("Last external connection released with FALSE last_closes.\n"); + return ref; + } + + if(This->doc_host) + deactivate_document(&This->doc_host->doc_host); + return ref; +} + static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv) { InternetExplorer *This = impl_from_IExternalConnection(iface); @@ -734,16 +759,26 @@ static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface) static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved) { InternetExplorer *This = impl_from_IExternalConnection(iface); - FIXME("(%p)\n", This); - return 2; + + TRACE("(%p)->(%x %x)\n", This, extconn, reserved); + + if(extconn != EXTCONN_STRONG) + return 0; + + return InterlockedIncrement(&This->extern_ref); } static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) { InternetExplorer *This = impl_from_IExternalConnection(iface); - FIXME("(%p)\n", This); - return 1; + + TRACE("(%p)->(%x %x %x)\n", This, extconn, reserved, fLastReleaseCloses); + + if(extconn != EXTCONN_STRONG) + return 0; + + return release_extern_ref(This, fLastReleaseCloses); } static const IExternalConnectionVtbl ExternalConnectionVtbl = { diff --git a/dlls/ieframe/ieframe.h b/dlls/ieframe/ieframe.h index 709789cf92a..b879eec7452 100644 --- a/dlls/ieframe/ieframe.h +++ b/dlls/ieframe/ieframe.h @@ -229,6 +229,7 @@ struct InternetExplorer { HlinkFrame hlink_frame; LONG ref; + LONG extern_ref; HWND frame_hwnd; HWND status_hwnd; @@ -288,6 +289,7 @@ LRESULT process_dochost_tasks(DocHost*) DECLSPEC_HIDDEN; void InternetExplorer_WebBrowser_Init(InternetExplorer*) DECLSPEC_HIDDEN; HRESULT update_ie_statustext(InternetExplorer*, LPCWSTR) DECLSPEC_HIDDEN; void released_obj(void) DECLSPEC_HIDDEN; +DWORD release_extern_ref(InternetExplorer*,BOOL) DECLSPEC_HIDDEN; void register_iewindow_class(void) DECLSPEC_HIDDEN; void unregister_iewindow_class(void) DECLSPEC_HIDDEN; diff --git a/dlls/ieframe/iexplore.c b/dlls/ieframe/iexplore.c index c3d519a05c0..3d822ff6ccb 100644 --- a/dlls/ieframe/iexplore.c +++ b/dlls/ieframe/iexplore.c @@ -669,10 +669,13 @@ static LRESULT WINAPI ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM return 0; case WM_SHOWWINDOW: TRACE("WM_SHOWWINDOW %lx\n", wparam); - if(wparam) + if(wparam) { IWebBrowser2_AddRef(&This->IWebBrowser2_iface); - else + InterlockedIncrement(&This->extern_ref); + }else { + release_extern_ref(This, TRUE); IWebBrowser2_Release(&This->IWebBrowser2_iface); + } break; case WM_DESTROY: return iewnd_OnDestroy(This);