Rob Shearman : rpcrt4: Bind to the server interface in I_RpcGetBuffer, not I_RpcSendReceive.

Alexandre Julliard julliard at winehq.org
Tue Jan 8 10:21:47 CST 2008


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Tue Jan  8 12:26:19 2008 +0000

rpcrt4: Bind to the server interface in I_RpcGetBuffer, not I_RpcSendReceive.

The actual sending of the request is still done in I_RpcSendReceive though.

Disallow the server from calling I_RpcSend and I_RpcReceive to allow 
simplification of the code. The releasing of the connection is now done 
in I_RpcFreeBuffer.

Implement I_RpcNegotiateTransferSyntax.

---

 dlls/rpcrt4/rpc_assoc.c   |    2 +-
 dlls/rpcrt4/rpc_message.c |  165 ++++++++++++++++++++++++++-------------------
 dlls/rpcrt4/rpc_server.c  |    4 +-
 3 files changed, 98 insertions(+), 73 deletions(-)

diff --git a/dlls/rpcrt4/rpc_assoc.c b/dlls/rpcrt4/rpc_assoc.c
index 1bffb85..6075278 100644
--- a/dlls/rpcrt4/rpc_assoc.c
+++ b/dlls/rpcrt4/rpc_assoc.c
@@ -332,7 +332,7 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *
         break;
     }
 
-    I_RpcFreeBuffer(&msg);
+    I_RpcFree(msg.Buffer);
     RPCRT4_FreeHeader(response_hdr);
     return status;
 }
diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c
index bbcc798..9246afd 100644
--- a/dlls/rpcrt4/rpc_message.c
+++ b/dlls/rpcrt4/rpc_message.c
@@ -754,8 +754,12 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
 
   TRACE("buffer length = %u\n", pMsg->BufferLength);
 
-  status = I_RpcGetBuffer(pMsg);
-  if (status != RPC_S_OK) goto fail;
+  pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength);
+  if (!pMsg->Buffer)
+  {
+    status = ERROR_OUTOFMEMORY;
+    goto fail;
+  }
 
   first_flag = RPC_FLG_FIRST;
   auth_length = common_hdr.auth_len;
@@ -891,6 +895,54 @@ fail:
 }
 
 /***********************************************************************
+ *           I_RpcNegotiateTransferSyntax [RPCRT4.@]
+ *
+ * Negotiates the transfer syntax used by a client connection by connecting
+ * to the server.
+ *
+ * PARAMS
+ *  pMsg   [I] RPC Message structure.
+ *  pAsync [I] Asynchronous state to set.
+ *
+ * RETURNS
+ *  Success: RPC_S_OK.
+ *  Failure: Any error code.
+ */
+RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg)
+{
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+  RpcConnection* conn;
+  RPC_STATUS status = RPC_S_OK;
+
+  TRACE("(%p)\n", pMsg);
+
+  if (!bind || bind->server)
+    return RPC_S_INVALID_BINDING;
+
+  /* if we already have a connection, we don't need to negotiate again */
+  if (!pMsg->ReservedForRuntime)
+  {
+    RPC_CLIENT_INTERFACE *cif = pMsg->RpcInterfaceInformation;
+    if (!cif) return RPC_S_INTERFACE_NOT_FOUND;
+
+    if (!bind->Endpoint || !bind->Endpoint[0])
+    {
+      TRACE("automatically resolving partially bound binding\n");
+      status = RpcEpResolveBinding(bind, cif);
+      if (status != RPC_S_OK) return status;
+    }
+
+    status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,
+                                &cif->InterfaceId);
+
+    if (status == RPC_S_OK)
+      pMsg->ReservedForRuntime = conn;
+  }
+
+  return status;
+}
+
+/***********************************************************************
  *           I_RpcGetBuffer [RPCRT4.@]
  *
  * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the
@@ -916,11 +968,30 @@ fail:
  */
 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
 {
+  RPC_STATUS status;
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+
   TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
-  pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);
 
+  if (!bind)
+    return RPC_S_INVALID_BINDING;
+
+  pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength);
   TRACE("Buffer=%p\n", pMsg->Buffer);
-  return pMsg->Buffer ? RPC_S_OK : ERROR_OUTOFMEMORY;
+
+  if (!pMsg->Buffer)
+    return ERROR_OUTOFMEMORY;
+
+  if (!bind->server)
+  {
+    status = I_RpcNegotiateTransferSyntax(pMsg);
+    if (status != RPC_S_OK)
+      I_RpcFree(pMsg->Buffer);
+  }
+  else
+    status = RPC_S_OK;
+
+  return status;
 }
 
 /***********************************************************************
@@ -952,8 +1023,19 @@ static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg)
  */
 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
 {
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+
   TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
-  HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
+
+  if (!bind) return RPC_S_INVALID_BINDING;
+
+  if (pMsg->ReservedForRuntime)
+  {
+    RpcConnection *conn = pMsg->ReservedForRuntime;
+    RPCRT4_CloseBinding(bind, conn);
+    pMsg->ReservedForRuntime = NULL;
+  }
+  I_RpcFree(pMsg->Buffer);
   return RPC_S_OK;
 }
 
@@ -978,44 +1060,26 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
 {
   RpcBinding* bind = (RpcBinding*)pMsg->Handle;
   RpcConnection* conn;
-  RPC_CLIENT_INTERFACE* cif = NULL;
   RPC_STATUS status;
   RpcPktHdr *hdr;
 
   TRACE("(%p)\n", pMsg);
-  if (!bind || bind->server) return RPC_S_INVALID_BINDING;
-
-  cif = pMsg->RpcInterfaceInformation;
-  if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
-
-  if (!bind->Endpoint || !bind->Endpoint[0])
-  {
-    TRACE("automatically resolving partially bound binding\n");
-    status = RpcEpResolveBinding(bind, cif);
-    if (status != RPC_S_OK) return status;
-  }
+  if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING;
 
-  status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,
-                              &cif->InterfaceId);
-  if (status != RPC_S_OK) return status;
+  conn = pMsg->ReservedForRuntime;
 
   hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,
                                   pMsg->BufferLength,
                                   pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT,
                                   &bind->ObjectUuid);
   if (!hdr)
-  {
-    RPCRT4_CloseBinding(bind, conn);
     return ERROR_OUTOFMEMORY;
-  }
   hdr->common.call_id = conn->NextCallId++;
 
   status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength);
 
   RPCRT4_FreeHeader(hdr);
 
-  /* save the connection, so the response can be read from it */
-  pMsg->ReservedForRuntime = conn;
   return status;
 }
 
@@ -1043,41 +1107,14 @@ static inline BOOL is_hard_error(RPC_STATUS status)
 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
 {
   RpcBinding* bind = (RpcBinding*)pMsg->Handle;
-  RpcConnection* conn;
-  RPC_CLIENT_INTERFACE* cif = NULL;
-  RPC_SERVER_INTERFACE* sif = NULL;
   RPC_STATUS status;
   RpcPktHdr *hdr = NULL;
+  RpcConnection *conn;
 
   TRACE("(%p)\n", pMsg);
-  if (!bind) return RPC_S_INVALID_BINDING;
-
-  if (pMsg->ReservedForRuntime) {
-    conn = pMsg->ReservedForRuntime;
-    pMsg->ReservedForRuntime = NULL;
-  } else {
-    if (bind->server) {
-      sif = pMsg->RpcInterfaceInformation;
-      if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
-      status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,
-                                  &sif->InterfaceId);
-    } else {
-      cif = pMsg->RpcInterfaceInformation;
-      if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
-
-      if (!bind->Endpoint || !bind->Endpoint[0])
-      {
-        TRACE("automatically resolving partially bound binding\n");
-        status = RpcEpResolveBinding(bind, cif);
-        if (status != RPC_S_OK) return status;
-      }
-
-      status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,
-                                  &cif->InterfaceId);
-    }
-    if (status != RPC_S_OK) return status;
-  }
+  if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING;
 
+  conn = pMsg->ReservedForRuntime;
   status = RPCRT4_Receive(conn, &hdr, pMsg);
   if (status != RPC_S_OK) {
     WARN("receive failed with error %lx\n", status);
@@ -1086,16 +1123,6 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
 
   switch (hdr->common.ptype) {
   case PKT_RESPONSE:
-    if (bind->server) {
-        status = RPC_S_PROTOCOL_ERROR;
-        goto fail;
-    }
-    break;
-  case PKT_REQUEST:
-    if (!bind->server) {
-        status = RPC_S_PROTOCOL_ERROR;
-        goto fail;
-    }
     break;
   case PKT_FAULT:
     ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status);
@@ -1110,13 +1137,13 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
   }
 
   /* success */
-  RPCRT4_CloseBinding(bind, conn);
   RPCRT4_FreeHeader(hdr);
   return status;
 
 fail:
   RPCRT4_FreeHeader(hdr);
   RPCRT4_DestroyConnection(conn);
+  pMsg->ReservedForRuntime = NULL;
   return status;
 }
 
@@ -1141,17 +1168,17 @@ fail:
 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
 {
   RPC_STATUS status;
-  RPC_MESSAGE original_message;
+  void *original_buffer;
 
   TRACE("(%p)\n", pMsg);
 
-  original_message = *pMsg;
+  original_buffer = pMsg->Buffer;
   status = I_RpcSend(pMsg);
   if (status == RPC_S_OK)
     status = I_RpcReceive(pMsg);
   /* free the buffer replaced by a new buffer in I_RpcReceive */
   if (status == RPC_S_OK)
-    I_RpcFreeBuffer(&original_message);
+    I_RpcFree(original_buffer);
   return status;
 }
 
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index 3db7365..fcac3dd 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -335,10 +335,8 @@ fail:
   /* clean up */
   if (msg->Buffer == buf) msg->Buffer = NULL;
   TRACE("freeing Buffer=%p\n", buf);
-  HeapFree(GetProcessHeap(), 0, buf);
-  msg->Handle = 0;
+  I_RpcFree(buf);
   I_RpcFreeBuffer(msg);
-  msg->Buffer = NULL;
   RPCRT4_FreeHeader(hdr);
   HeapFree(GetProcessHeap(), 0, msg);
 }




More information about the wine-cvs mailing list