Rob Shearman : ole32: Add the external references that the server gave to us to any existing ifproxy ,

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 6 15:23:18 CST 2007


Module: wine
Branch: master
Commit: cb9c40a8cfc4c2cd5973d8dc72f48d1935fe33c1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=cb9c40a8cfc4c2cd5973d8dc72f48d1935fe33c1

Author: Rob Shearman <rob at codeweavers.com>
Date:   Tue Feb  6 19:22:39 2007 +0000

ole32: Add the external references that the server gave to us to any existing ifproxy,

so that the right external reference count is released when the proxy is destroyed.
Protect all changes to refs in the ifproxy using interlocked functions 
and update the thread-safety documentation.

---

 dlls/ole32/compobj_private.h |    2 +-
 dlls/ole32/marshal.c         |   27 +++++++++++++++++----------
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index cfee6e3..b77e05f 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -112,7 +112,7 @@ struct ifproxy
   STDOBJREF stdobjref;     /* marshal data that represents this object (RO) */
   IID iid;                 /* interface ID (RO) */
   LPRPCPROXYBUFFER proxy;  /* interface proxy (RO) */
-  DWORD refs;              /* imported (public) references (MUTEX parent->remoting_mutex) */
+  ULONG refs;              /* imported (public) references (LOCK) */
   IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */
 };
 
diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c
index fc63450..e79e93d 100644
--- a/dlls/ole32/marshal.c
+++ b/dlls/ole32/marshal.c
@@ -498,7 +498,7 @@ static HRESULT ifproxy_get_public_ref(st
             rif.cPrivateRefs = 0;
             hr = IRemUnknown_RemAddRef(remunk, 1, &rif, &hrref);
             if (hr == S_OK && hrref == S_OK)
-                This->refs += NORMALEXTREFS;
+                InterlockedExchangeAdd((LONG *)&This->refs, NORMALEXTREFS);
             else
                 ERR("IRemUnknown_RemAddRef returned with 0x%08x, hrref = 0x%08x\n", hr, hrref);
         }
@@ -511,6 +511,7 @@ static HRESULT ifproxy_get_public_ref(st
 static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
 {
     HRESULT hr = S_OK;
+    LONG public_refs;
 
     if (WAIT_OBJECT_0 != WaitForSingleObject(This->parent->remoting_mutex, INFINITE))
     {
@@ -518,22 +519,23 @@ static HRESULT ifproxy_release_public_re
         return E_UNEXPECTED;
     }
 
-    if (This->refs > 0)
+    public_refs = This->refs;
+    if (public_refs > 0)
     {
         IRemUnknown *remunk = NULL;
 
-        TRACE("releasing %d refs\n", This->refs);
+        TRACE("releasing %d refs\n", public_refs);
 
         hr = proxy_manager_get_remunknown(This->parent, &remunk);
         if (hr == S_OK)
         {
             REMINTERFACEREF rif;
             rif.ipid = This->stdobjref.ipid;
-            rif.cPublicRefs = This->refs;
+            rif.cPublicRefs = public_refs;
             rif.cPrivateRefs = 0;
             hr = IRemUnknown_RemRelease(remunk, 1, &rif);
             if (hr == S_OK)
-                This->refs = 0;
+                InterlockedExchangeAdd((LONG *)&This->refs, -public_refs);
             else if (hr == RPC_E_DISCONNECTED)
                 WARN("couldn't release references because object was "
                      "disconnected: oxid = %s, oid = %s\n",
@@ -751,7 +753,7 @@ static HRESULT proxy_manager_create_ifpr
     ifproxy->parent = This;
     ifproxy->stdobjref = *stdobjref;
     ifproxy->iid = *riid;
-    ifproxy->refs = stdobjref->cPublicRefs;
+    ifproxy->refs = 0;
     ifproxy->proxy = NULL;
 
     assert(channel);
@@ -789,10 +791,6 @@ static HRESULT proxy_manager_create_ifpr
             hr = IRpcProxyBuffer_Connect(ifproxy->proxy, ifproxy->chan);
     }
 
-    /* get at least one external reference to the object to keep it alive */
-    if (hr == S_OK)
-        hr = ifproxy_get_public_ref(ifproxy);
-
     if (hr == S_OK)
     {
         EnterCriticalSection(&This->cs);
@@ -1136,6 +1134,15 @@ static HRESULT unmarshal_object(const ST
             IUnknown_AddRef((IUnknown *)ifproxy->iface);
 
         if (hr == S_OK)
+        {
+            InterlockedExchangeAdd((LONG *)&ifproxy->refs, stdobjref->cPublicRefs);
+            /* get at least one external reference to the object to keep it alive */
+            hr = ifproxy_get_public_ref(ifproxy);
+            if (FAILED(hr))
+                ifproxy_destroy(ifproxy);
+        }
+
+        if (hr == S_OK)
             *object = ifproxy->iface;
     }
 




More information about the wine-cvs mailing list