Rob Shearman : rpcss: Use context handles to automatically free running object table entries if the client process quits without calling IrotRevoke .

Alexandre Julliard julliard at winehq.org
Wed Dec 26 10:05:06 CST 2007


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Tue Dec 25 19:08:25 2007 +0000

rpcss: Use context handles to automatically free running object table entries if the client process quits without calling IrotRevoke.

---

 dlls/ole32/moniker.c   |    9 +++++++--
 include/wine/irot.idl  |    5 ++++-
 programs/rpcss/irotp.c |   46 +++++++++++++++++++++++++++++++++-------------
 3 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c
index 8511a9f..e77c8c4 100644
--- a/dlls/ole32/moniker.c
+++ b/dlls/ole32/moniker.c
@@ -73,6 +73,7 @@ struct rot_entry
     MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
     DWORD              cookie; /* cookie identifying this object */
     FILETIME           last_modified;
+    IrotContextHandle  ctxt_handle;
 };
 
 /* define the RunningObjectTableImpl structure */
@@ -183,7 +184,8 @@ static inline void rot_entry_delete(struct rot_entry *rot_entry)
         InterfaceData *moniker = NULL;
         __TRY
         {
-            IrotRevoke(get_irot_handle(), rot_entry->cookie, &object, &moniker);
+            IrotRevoke(get_irot_handle(), rot_entry->cookie,
+                       &rot_entry->ctxt_handle, &object, &moniker);
         }
         __EXCEPT(rpc_filter)
         {
@@ -554,7 +556,10 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     {
         __TRY
         {
-            hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data, rot_entry->object, moniker, &rot_entry->last_modified, grfFlags, &rot_entry->cookie);
+            hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data,
+                              rot_entry->object, moniker,
+                              &rot_entry->last_modified, grfFlags,
+                              &rot_entry->cookie, &rot_entry->ctxt_handle);
         }
         __EXCEPT(rpc_filter)
         {
diff --git a/include/wine/irot.idl b/include/wine/irot.idl
index e480b45..f14af13 100644
--- a/include/wine/irot.idl
+++ b/include/wine/irot.idl
@@ -51,6 +51,7 @@ interface Irot
 	typedef DWORD IrotCookie;
 
 	typedef handle_t IrotHandle;
+	typedef [context_handle] void *IrotContextHandle;
 
 	HRESULT IrotRegister(
 		[in]  IrotHandle h,
@@ -59,11 +60,13 @@ interface Irot
 		[in]  const InterfaceData *moniker,
 		[in]  const FILETIME *time,
 		[in]  DWORD grfFlags,
-		[out] IrotCookie *cookie);
+		[out] IrotCookie *cookie,
+		[out] IrotContextHandle *ctxt_handle);
 
 	HRESULT IrotRevoke(
 		[in]  IrotHandle h,
 		[in]  IrotCookie cookie,
+		[in, out] IrotContextHandle *ctxt_handle,
 		[out] PInterfaceData *object,
 		[out] PInterfaceData *moniker);
 
diff --git a/programs/rpcss/irotp.c b/programs/rpcss/irotp.c
index fd40625..7832ac7 100644
--- a/programs/rpcss/irotp.c
+++ b/programs/rpcss/irotp.c
@@ -41,6 +41,7 @@ struct rot_entry
     MonikerComparisonData *moniker_data; /* moniker comparison data that identifies this object */
     DWORD              cookie; /* cookie identifying this object */
     FILETIME           last_modified;
+    LONG               refs;
 };
 
 static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
@@ -56,12 +57,15 @@ static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0
 
 static LONG last_cookie = 1;
 
-static inline void rot_entry_delete(struct rot_entry *rot_entry)
+static inline void rot_entry_release(struct rot_entry *rot_entry)
 {
-    HeapFree(GetProcessHeap(), 0, rot_entry->object);
-    HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
-    HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
-    HeapFree(GetProcessHeap(), 0, rot_entry);
+    if (!InterlockedDecrement(&rot_entry->refs))
+    {
+        HeapFree(GetProcessHeap(), 0, rot_entry->object);
+        HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
+        HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
+        HeapFree(GetProcessHeap(), 0, rot_entry);
+    }
 }
 
 HRESULT IrotRegister(
@@ -71,10 +75,11 @@ HRESULT IrotRegister(
     const InterfaceData *mk,
     const FILETIME *time,
     DWORD grfFlags,
-    IrotCookie *cookie)
+    IrotCookie *cookie,
+    IrotContextHandle *ctxt_handle)
 {
     struct rot_entry *rot_entry;
-    const struct rot_entry *existing_rot_entry;
+    struct rot_entry *existing_rot_entry;
     HRESULT hr;
 
     if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
@@ -87,10 +92,11 @@ HRESULT IrotRegister(
     if (!rot_entry)
         return E_OUTOFMEMORY;
 
+    rot_entry->refs = 1;
     rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
     if (!rot_entry->object)
     {
-        rot_entry_delete(rot_entry);
+        rot_entry_release(rot_entry);
         return E_OUTOFMEMORY;
     }
     rot_entry->object->ulCntData = obj->ulCntData;
@@ -101,7 +107,7 @@ HRESULT IrotRegister(
     rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
     if (!rot_entry->moniker)
     {
-        rot_entry_delete(rot_entry);
+        rot_entry_release(rot_entry);
         return E_OUTOFMEMORY;
     }
     rot_entry->moniker->ulCntData = mk->ulCntData;
@@ -110,7 +116,7 @@ HRESULT IrotRegister(
     rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
     if (!rot_entry->moniker_data)
     {
-        rot_entry_delete(rot_entry);
+        rot_entry_release(rot_entry);
         return E_OUTOFMEMORY;
     }
     rot_entry->moniker_data->ulCntData = data->ulCntData;
@@ -120,7 +126,7 @@ HRESULT IrotRegister(
 
     hr = S_OK;
 
-    LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, const struct rot_entry, entry)
+    LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
     {
         if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
             !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
@@ -136,11 +142,14 @@ HRESULT IrotRegister(
         list_add_tail(&RunningObjectTable, &rot_entry->entry);
         /* gives a registration identifier to the registered object*/
         *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
+        *ctxt_handle = rot_entry;
     }
     else
     {
-        rot_entry_delete(rot_entry);
+        rot_entry_release(rot_entry);
         *cookie = existing_rot_entry->cookie;
+        InterlockedIncrement(&existing_rot_entry->refs);
+        *ctxt_handle = existing_rot_entry;
     }
 
 
@@ -152,6 +161,7 @@ HRESULT IrotRegister(
 HRESULT IrotRevoke(
     IrotHandle h,
     IrotCookie cookie,
+    IrotContextHandle *ctxt_handle,
     PInterfaceData *obj,
     PInterfaceData *mk)
 {
@@ -185,7 +195,8 @@ HRESULT IrotRevoke(
                 hr = E_OUTOFMEMORY;
             }
 
-            rot_entry_delete(rot_entry);
+            rot_entry_release(rot_entry);
+            *ctxt_handle = NULL;
             return hr;
         }
     }
@@ -354,6 +365,15 @@ HRESULT IrotEnumRunning(
     return hr;
 }
 
+void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
+{
+    struct rot_entry *rot_entry = ctxt_handle;
+    EnterCriticalSection(&csRunningObjectTable);
+    list_remove(&rot_entry->entry);
+    LeaveCriticalSection(&csRunningObjectTable);
+    rot_entry_release(rot_entry);
+}
+
 void * __RPC_USER MIDL_user_allocate(size_t size)
 {
     return HeapAlloc(GetProcessHeap(), 0, size);




More information about the wine-cvs mailing list