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

This commit is contained in:
Rob Shearman 2007-12-25 19:08:25 +00:00 committed by Alexandre Julliard
parent 6e7dcde26e
commit 9804aba758
3 changed files with 44 additions and 16 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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);