Rob Shearman : rpcrt4: Implement RpcServerUnregisterIf.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Nov 13 09:24:23 CST 2006
Module: wine
Branch: master
Commit: 29a9abff8aaeb08edfc94725e93d28debacfdbba
URL: http://source.winehq.org/git/wine.git/?a=commit;h=29a9abff8aaeb08edfc94725e93d28debacfdbba
Author: Rob Shearman <rob at codeweavers.com>
Date: Mon Nov 13 11:46:04 2006 +0000
rpcrt4: Implement RpcServerUnregisterIf.
---
dlls/rpcrt4/rpc_server.c | 64 +++++++++++++++++++++++++++++++++++++++++++--
dlls/rpcrt4/rpc_server.h | 4 +++
2 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index acf0f2e..50549ea 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -133,7 +133,10 @@ static RpcServerInterface* RPCRT4_find_i
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_i
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(RpcCon
/* 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(RpcCon
}
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(RpcCon
I_RpcSend(msg);
msg->RpcInterfaceInformation = NULL;
+ RPCRT4_release_server_interface(sif);
break;
@@ -798,8 +819,45 @@ RPC_STATUS WINAPI RpcServerRegisterIf2(
*/
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;
}
diff --git a/dlls/rpcrt4/rpc_server.h b/dlls/rpcrt4/rpc_server.h
index d9460e7..eb32be6 100644
--- a/dlls/rpcrt4/rpc_server.h
+++ b/dlls/rpcrt4/rpc_server.h
@@ -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);
More information about the wine-cvs
mailing list