Rob Shearman : rpcrt4: The allocation hint in request and response packets is just that - a hint.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Oct 27 05:49:21 CDT 2006


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Thu Oct 26 23:16:25 2006 +0100

rpcrt4: The allocation hint in request and response packets is just that - a hint.

It is not an error if the stub data exceeds this size, so reallocate the 
buffer with the newly calculated size and continue.

---

 dlls/rpcrt4/rpc_message.c |   35 +++++++++++++++++++++++++++--------
 1 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c
index 6d434c0..80fbcc0 100644
--- a/dlls/rpcrt4/rpc_message.c
+++ b/dlls/rpcrt4/rpc_message.c
@@ -50,6 +50,8 @@ #define AUTH_ALIGNMENT 16
 #define ROUND_UP_AMOUNT(value, alignment) \
     (((alignment) - (((value) % (alignment)))) % (alignment))
 
+static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg);
+
 static DWORD RPCRT4_GetHeaderSize(RpcPktHdr *Header)
 {
   static const DWORD header_sizes[] = {
@@ -476,7 +478,6 @@ RPC_STATUS RPCRT4_Receive(RpcConnection
   unsigned long data_length;
   unsigned long buffer_length;
   unsigned long auth_length;
-  unsigned char *buffer_ptr;
   unsigned char *auth_data = NULL;
   RpcPktCommonHdr common_hdr;
 
@@ -545,7 +546,6 @@ RPC_STATUS RPCRT4_Receive(RpcConnection
     }
   }
   buffer_length = 0;
-  buffer_ptr = pMsg->Buffer;
   while (TRUE)
   {
     unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&(*Header)->common);
@@ -567,16 +567,24 @@ RPC_STATUS RPCRT4_Receive(RpcConnection
       goto fail;
     }
 
-    data_length = (*Header)->common.frag_len - hdr_length - header_auth_len;
-    if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag ||
-        data_length + buffer_length > pMsg->BufferLength) {
-      TRACE("invalid packet flags or buffer length\n");
+    if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag) {
+      TRACE("invalid packet flags\n");
       status = RPC_S_PROTOCOL_ERROR;
       goto fail;
     }
 
+    data_length = (*Header)->common.frag_len - hdr_length - header_auth_len;
+    if (data_length + buffer_length > pMsg->BufferLength) {
+      TRACE("allocation hint exceeded, new buffer length = %ld\n",
+        data_length + buffer_length);
+      pMsg->BufferLength = data_length + buffer_length;
+      status = I_RpcReAllocateBuffer(pMsg);
+      if (status != RPC_S_OK) goto fail;
+    }
+
     if (data_length == 0) dwRead = 0; else
-    dwRead = rpcrt4_conn_read(Connection, buffer_ptr, data_length);
+    dwRead = rpcrt4_conn_read(Connection,
+        (unsigned char *)pMsg->Buffer + buffer_length, data_length);
     if (dwRead != data_length) {
       WARN("bad data length, %ld/%ld\n", dwRead, data_length);
       status = RPC_S_PROTOCOL_ERROR;
@@ -610,7 +618,6 @@ RPC_STATUS RPCRT4_Receive(RpcConnection
         goto fail;
       }
 
-      buffer_ptr += data_length;
       first_flag = 0;
     } else {
       break;
@@ -655,6 +662,18 @@ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_ME
 }
 
 /***********************************************************************
+ *           I_RpcReAllocateBuffer (internal)
+ */
+static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg)
+{
+  TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
+  pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
+
+  TRACE("Buffer=%p\n", pMsg->Buffer);
+  return pMsg->Buffer ? RPC_S_OK : RPC_S_OUT_OF_RESOURCES;
+}
+
+/***********************************************************************
  *           I_RpcFreeBuffer [RPCRT4.@]
  */
 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)




More information about the wine-cvs mailing list