Jacek Caban : ieframe: Keep track of InternetExplore external references and use that to release document .
Alexandre Julliard
julliard at winehq.org
Fri May 24 11:12:44 CDT 2013
Module: wine
Branch: master
Commit: b51af0b1c9e56e7bea16a7a53831401f8f75de8e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b51af0b1c9e56e7bea16a7a53831401f8f75de8e
Author: Jacek Caban <jacek at codeweavers.com>
Date: Fri May 24 10:39:20 2013 +0200
ieframe: Keep track of InternetExplore external references and use that to release document.
---
dlls/ieframe/ie.c | 43 +++++++++++++++++++++++++++++++++++++++----
dlls/ieframe/ieframe.h | 2 ++
dlls/ieframe/iexplore.c | 7 +++++--
3 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/dlls/ieframe/ie.c b/dlls/ieframe/ie.c
index 42602f9..8ee2819 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 709789c..b879eec 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 c3d519a..3d822ff 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);
More information about the wine-cvs
mailing list