rpcrt4: Implement RpcServerUnregisterIf.

This commit is contained in:
Rob Shearman 2006-11-13 11:46:04 +00:00 committed by Alexandre Julliard
parent 0b1cc1061b
commit 29a9abff8a
2 changed files with 65 additions and 3 deletions

View File

@ -133,7 +133,10 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object,
LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&
(check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) &&
std_listen) break;
std_listen) {
InterlockedIncrement(&cif->CurrentCalls);
break;
}
}
LeaveCriticalSection(&server_cs);
if (&cif->entry == &server_interfaces) cif = NULL;
@ -141,6 +144,17 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object,
return cif;
}
static void RPCRT4_release_server_interface(RpcServerInterface *sif)
{
if (!InterlockedDecrement(&sif->CurrentCalls) &&
sif->CallsCompletedEvent) {
/* sif must have been removed from server_interfaces before
* CallsCompletedEvent is set */
SetEvent(sif->CallsCompletedEvent);
HeapFree(GetProcessHeap(), 0, sif);
}
}
static WINE_EXCEPTION_FILTER(rpc_filter)
{
WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode());
@ -190,6 +204,8 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
/* save the interface for later use */
conn->ActiveInterface = hdr->bind.abstract;
conn->MaxTransmissionSize = hdr->bind.max_tsize;
RPCRT4_release_server_interface(sif);
}
status = RPCRT4_Send(conn, response, NULL, 0);
@ -219,6 +235,10 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
}
sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE);
if (!sif) {
/* FIXME: send fault packet? */
break;
}
msg->RpcInterfaceInformation = sif->If;
/* copy the endpoint vector from sif to msg so that midl-generated code will use it */
msg->ManagerEpv = sif->MgrEpv;
@ -262,6 +282,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
I_RpcSend(msg);
msg->RpcInterfaceInformation = NULL;
RPCRT4_release_server_interface(sif);
break;
@ -798,8 +819,45 @@ RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid,
*/
RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
{
FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n",
IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
HANDLE event = NULL;
BOOL found = FALSE;
BOOL completed = TRUE;
RpcServerInterface *cif;
RPC_STATUS status;
TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n",
IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
EnterCriticalSection(&server_cs);
LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
if (!memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&
UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) {
list_remove(&cif->entry);
if (cif->CurrentCalls) {
completed = FALSE;
if (WaitForCallsToComplete)
cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL);
}
found = TRUE;
break;
}
}
LeaveCriticalSection(&server_cs);
if (!found) {
ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid));
return RPC_S_UNKNOWN_IF;
}
if (completed)
HeapFree(GetProcessHeap(), 0, cif);
else if (event) {
/* sif will be freed when the last call is completed, so be careful not to
* touch that memory here as that could happen before we get here */
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
return RPC_S_OK;
}

View File

@ -69,6 +69,10 @@ typedef struct _RpcServerInterface
UINT MaxCalls;
UINT MaxRpcSize;
RPC_IF_CALLBACK_FN* IfCallbackFn;
LONG CurrentCalls; /* number of calls currently executing */
/* set when unregistering interface to let the caller of
* RpcServerUnregisterIf* know that all calls have finished */
HANDLE CallsCompletedEvent;
} RpcServerInterface;
void RPCRT4_new_client(RpcConnection* conn);