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