783 lines
20 KiB
C++
783 lines
20 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
CoTrans.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Common connection-oriented helper functions
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mario Goertzel [MarioGo]
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
MarioGo 11/11/1996 Async RPC
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <precomp.hxx>
|
|||
|
#include <trans.hxx>
|
|||
|
#include <cotrans.hxx>
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
RPC_ENTRY
|
|||
|
CO_Send(
|
|||
|
RPC_TRANSPORT_CONNECTION ThisConnection,
|
|||
|
UINT Length,
|
|||
|
BUFFER Buffer,
|
|||
|
PVOID SendContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Submits a send of the buffer on the connection. Will complete with
|
|||
|
ConnectionServerSend or ConnectionClientSend event either when
|
|||
|
the data has been sent on the network or when the send fails.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ThisConnection - The connection to send the data on.
|
|||
|
Length - The length of the data to send.
|
|||
|
Buffer - The data to send.
|
|||
|
SendContext - A buffer to use as the CO_SEND_CONTEXT for
|
|||
|
this operation.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK
|
|||
|
|
|||
|
RPC_P_SEND_FAILED - Connection aborted
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCONNECTION pConnection = (PCONNECTION)ThisConnection;
|
|||
|
CO_SEND_CONTEXT *pSend = (CO_SEND_CONTEXT *)SendContext;
|
|||
|
BOOL b;
|
|||
|
DWORD ignored;
|
|||
|
RPC_STATUS status;
|
|||
|
|
|||
|
pConnection->StartingWriteIO();
|
|||
|
|
|||
|
if (pConnection->fAborted)
|
|||
|
{
|
|||
|
pConnection->WriteIOFinished();
|
|||
|
return(RPC_P_SEND_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
pSend->maxWriteBuffer = Length;
|
|||
|
pSend->pWriteBuffer = Buffer;
|
|||
|
pSend->Write.pAsyncObject = pConnection;
|
|||
|
pSend->Write.ol.hEvent = 0;
|
|||
|
pSend->Write.ol.Offset = 0;
|
|||
|
pSend->Write.ol.OffsetHigh = 0;
|
|||
|
pSend->Write.thread = I_RpcTransProtectThread();
|
|||
|
|
|||
|
#ifdef _INTERNAL_RPC_BUILD_
|
|||
|
if (gpfnFilter)
|
|||
|
{
|
|||
|
(*gpfnFilter) (Buffer, Length, 0);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
status = pConnection->Send(
|
|||
|
pConnection->Conn.Handle,
|
|||
|
Buffer,
|
|||
|
Length,
|
|||
|
&ignored,
|
|||
|
&pSend->Write.ol
|
|||
|
);
|
|||
|
|
|||
|
pConnection->WriteIOFinished();
|
|||
|
|
|||
|
if ( (status != RPC_S_OK)
|
|||
|
&& (status != ERROR_IO_PENDING) )
|
|||
|
{
|
|||
|
RpcpErrorAddRecord(EEInfoGCIO,
|
|||
|
status,
|
|||
|
EEInfoDLCOSend10,
|
|||
|
(ULONGLONG)pConnection,
|
|||
|
(ULONGLONG)Buffer,
|
|||
|
Length);
|
|||
|
|
|||
|
VALIDATE(status)
|
|||
|
{
|
|||
|
ERROR_NETNAME_DELETED,
|
|||
|
ERROR_BROKEN_PIPE,
|
|||
|
ERROR_GRACEFUL_DISCONNECT,
|
|||
|
ERROR_NO_DATA,
|
|||
|
ERROR_NO_SYSTEM_RESOURCES,
|
|||
|
ERROR_WORKING_SET_QUOTA,
|
|||
|
ERROR_BAD_COMMAND,
|
|||
|
ERROR_OPERATION_ABORTED,
|
|||
|
ERROR_WORKING_SET_QUOTA,
|
|||
|
ERROR_PIPE_NOT_CONNECTED,
|
|||
|
WSAECONNABORTED,
|
|||
|
WSAECONNRESET
|
|||
|
} END_VALIDATE;
|
|||
|
|
|||
|
I_RpcTransUnprotectThread(pSend->Write.thread);
|
|||
|
|
|||
|
pConnection->Abort();
|
|||
|
|
|||
|
return(RPC_P_SEND_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
RPC_ENTRY
|
|||
|
CO_SubmitRead(
|
|||
|
PCONNECTION pConnection
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Generic routine to submit an async read on an existing connection.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConnection - The connection to submit the read on.
|
|||
|
pConnection->pReadBuffer - valid buffer to receive into or null.
|
|||
|
pConnection->maxReadBuffer - size of pReadBuffer or null.
|
|||
|
pConnection->iLastRead is an offset into pReadBuffer of
|
|||
|
data already read.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK - Read pending
|
|||
|
|
|||
|
RPC_P_RECEIVE_FAILED - Connection aborted
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL b;
|
|||
|
DWORD ignored;
|
|||
|
RPC_STATUS status;
|
|||
|
|
|||
|
if (pConnection->pReadBuffer == 0)
|
|||
|
{
|
|||
|
ASSERT(pConnection->iLastRead == 0);
|
|||
|
|
|||
|
pConnection->pReadBuffer = TransConnectionAllocatePacket(pConnection,
|
|||
|
pConnection->iPostSize);
|
|||
|
if (pConnection->pReadBuffer == 0)
|
|||
|
{
|
|||
|
pConnection->Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
pConnection->maxReadBuffer = pConnection->iPostSize;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ASSERT(pConnection->iLastRead < pConnection->maxReadBuffer);
|
|||
|
}
|
|||
|
|
|||
|
pConnection->StartingReadIO();
|
|||
|
if (pConnection->fAborted)
|
|||
|
{
|
|||
|
pConnection->ReadIOFinished();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
pConnection->Read.thread = I_RpcTransProtectThread();
|
|||
|
pConnection->Read.ol.hEvent = 0;
|
|||
|
|
|||
|
ASSERT(pConnection->Read.ol.Internal != STATUS_PENDING);
|
|||
|
|
|||
|
status = pConnection->Receive(
|
|||
|
pConnection->Conn.Handle,
|
|||
|
pConnection->pReadBuffer + pConnection->iLastRead,
|
|||
|
pConnection->maxReadBuffer - pConnection->iLastRead,
|
|||
|
&ignored,
|
|||
|
&pConnection->Read.ol
|
|||
|
);
|
|||
|
|
|||
|
pConnection->ReadIOFinished();
|
|||
|
|
|||
|
if ( (status != RPC_S_OK)
|
|||
|
&& (status != ERROR_IO_PENDING)
|
|||
|
&& (status != ERROR_MORE_DATA) )
|
|||
|
{
|
|||
|
if ( status != ERROR_NETNAME_DELETED
|
|||
|
&& status != ERROR_BROKEN_PIPE
|
|||
|
&& status != ERROR_GRACEFUL_DISCONNECT)
|
|||
|
{
|
|||
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|||
|
DPFLTR_WARNING_LEVEL,
|
|||
|
RPCTRANS "UTIL_ReadFile failed %d on %p\n",
|
|||
|
status,
|
|||
|
pConnection));
|
|||
|
}
|
|||
|
|
|||
|
RpcpErrorAddRecord(EEInfoGCIO,
|
|||
|
status,
|
|||
|
EEInfoDLCOSubmitRead10);
|
|||
|
|
|||
|
// the IO system does not necessarily reset the Internal on sync failure.
|
|||
|
// Reset it because in HTTP when we encounted a sync failure on RTS receive
|
|||
|
// we may submit a second receive after a failed receive and this will
|
|||
|
// trigger the ASSERT above
|
|||
|
pConnection->Read.ol.Internal = status;
|
|||
|
|
|||
|
I_RpcTransUnprotectThread(pConnection->Read.thread);
|
|||
|
|
|||
|
pConnection->Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
// Even if the read completed here, it will also be posted to the
|
|||
|
// completion port. This means we don't need to handle the read here.
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
RPC_ENTRY
|
|||
|
CO_Recv(
|
|||
|
RPC_TRANSPORT_CONNECTION ThisConnection
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called be the runtime on a connection without a currently
|
|||
|
pending recv.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ThisConnection - A connection without a read pending on it.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK
|
|||
|
RPC_P_RECEIVE_FAILED
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCONNECTION p = (PCONNECTION)ThisConnection;
|
|||
|
|
|||
|
if ( p->iLastRead
|
|||
|
&& p->iLastRead == p->maxReadBuffer)
|
|||
|
{
|
|||
|
ASSERT(p->pReadBuffer);
|
|||
|
|
|||
|
// This means we received a coalesced read of a complete
|
|||
|
// message. (Or that we received a coalesced read < header size)
|
|||
|
// We should complete that as it's own IO. This is very
|
|||
|
// rare.
|
|||
|
|
|||
|
TransDbgDetail((DPFLTR_RPCPROXY_ID,
|
|||
|
DPFLTR_INFO_LEVEL,
|
|||
|
RPCTRANS "Posted coalesced data in %p of %d byte\n",
|
|||
|
p,
|
|||
|
p->iLastRead));
|
|||
|
|
|||
|
UINT bytes;
|
|||
|
|
|||
|
bytes = p->iLastRead;
|
|||
|
p->iLastRead = 0;
|
|||
|
p->Read.thread = I_RpcTransProtectThread();
|
|||
|
|
|||
|
// This means we want to process this as a new receive
|
|||
|
BOOL b = PostQueuedCompletionStatus(RpcCompletionPort,
|
|||
|
bytes,
|
|||
|
TRANSPORT_POSTED_KEY,
|
|||
|
&p->Read.ol);
|
|||
|
|
|||
|
ASSERT(b); // See complete.cxx - we can handle it here if needed.
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(p->iLastRead == 0 || (p->iLastRead < p->maxReadBuffer));
|
|||
|
|
|||
|
return(CO_SubmitRead(p));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS BASE_CONNECTION::ProcessRead(IN DWORD bytes, OUT BUFFER *pBuffer,
|
|||
|
OUT PUINT pBufferLength)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Receives a message from a message or byte mode protocol.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
bytes - The number of read (not including those in iLastRead).
|
|||
|
pBuffer - When returning RPC_S_OK will contain the message.
|
|||
|
pBufferLength - When return RPC_S_OK will contain the message length.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK - A complete message has been returned.
|
|||
|
|
|||
|
RPC_P_RECEIVE_FAILED - something failed.
|
|||
|
|
|||
|
RPC_P_PARTIAL_RECEIVE - Partial message recv'd, need to submit another recv.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD message_size;
|
|||
|
RPC_STATUS status;
|
|||
|
|
|||
|
bytes += iLastRead;
|
|||
|
|
|||
|
if (bytes < sizeof(CONN_RPC_HEADER))
|
|||
|
{
|
|||
|
// Not a whole header, resubmit the read and continue.
|
|||
|
|
|||
|
iLastRead = bytes;
|
|||
|
|
|||
|
return(RPC_P_PARTIAL_RECEIVE);
|
|||
|
}
|
|||
|
|
|||
|
message_size = MessageLength((PCONN_RPC_HEADER)pReadBuffer);
|
|||
|
|
|||
|
if (message_size < sizeof(CONN_RPC_HEADER))
|
|||
|
{
|
|||
|
ASSERT(message_size >= sizeof(CONN_RPC_HEADER));
|
|||
|
Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
if (bytes == message_size)
|
|||
|
{
|
|||
|
// All set, have a complete request.
|
|||
|
*pBuffer = pReadBuffer;
|
|||
|
*pBufferLength = message_size;
|
|||
|
|
|||
|
iLastRead = 0;
|
|||
|
pReadBuffer = 0;
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
else if (message_size > bytes)
|
|||
|
{
|
|||
|
// Don't have a complete message, realloc if needed and
|
|||
|
// resubmit a read for the remaining bytes.
|
|||
|
|
|||
|
if (maxReadBuffer < message_size)
|
|||
|
{
|
|||
|
// Buffer too small for the message.
|
|||
|
status = TransConnectionReallocPacket(this,
|
|||
|
&pReadBuffer,
|
|||
|
bytes,
|
|||
|
message_size);
|
|||
|
|
|||
|
if (status != RPC_S_OK)
|
|||
|
{
|
|||
|
ASSERT(status == RPC_S_OUT_OF_MEMORY);
|
|||
|
Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
// increase the post size, but not if we are in paged
|
|||
|
// buffer mode.
|
|||
|
if (!fPagedBCacheMode)
|
|||
|
iPostSize = message_size;
|
|||
|
}
|
|||
|
|
|||
|
// Setup to receive exactly the remaining bytes of the message.
|
|||
|
iLastRead = bytes;
|
|||
|
maxReadBuffer = message_size;
|
|||
|
|
|||
|
return(RPC_P_PARTIAL_RECEIVE);
|
|||
|
}
|
|||
|
|
|||
|
// Coalesced read, save extra data. Very uncommon, impossible for
|
|||
|
// message mode protocols.
|
|||
|
|
|||
|
ASSERT(bytes > message_size);
|
|||
|
|
|||
|
#ifdef SPX_ON
|
|||
|
ASSERT((id == TCP) || (id == SPX) || (id == HTTP) || (id == TCP_IPv6) || (id == HTTPv2));
|
|||
|
#else
|
|||
|
ASSERT((id == TCP) || (id == HTTP) || (id == TCP_IPv6) || (id == HTTPv2));
|
|||
|
#endif
|
|||
|
|
|||
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|||
|
DPFLTR_WARNING_LEVEL,
|
|||
|
RPCTRANS "Coalesced read of %d bytes, connection %p\n",
|
|||
|
bytes - message_size,
|
|||
|
this));
|
|||
|
|
|||
|
// The first message and size will be returned
|
|||
|
|
|||
|
*pBuffer = pReadBuffer;
|
|||
|
*pBufferLength = message_size;
|
|||
|
|
|||
|
UINT extra = bytes - message_size;
|
|||
|
UINT alloc_size;
|
|||
|
|
|||
|
// Try to find a good size of the extra PDU(s)
|
|||
|
if (extra < sizeof(CONN_RPC_HEADER))
|
|||
|
{
|
|||
|
// Not a whole header, we'll assume iPostSize;
|
|||
|
|
|||
|
alloc_size = iPostSize;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
#ifdef _M_IA64
|
|||
|
// The first packet may not contain a number of bytes
|
|||
|
// that align the second on an 8-byte boundary. Hence, the
|
|||
|
// structure may end up unaligned.
|
|||
|
alloc_size = MessageLengthUnaligned((PCONN_RPC_HEADER)(pReadBuffer
|
|||
|
+ message_size));
|
|||
|
#else
|
|||
|
alloc_size = MessageLength((PCONN_RPC_HEADER)(pReadBuffer
|
|||
|
+ message_size));
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if (alloc_size < extra)
|
|||
|
{
|
|||
|
// This can happen if there are more than two PDUs coalesced together
|
|||
|
// in the buffer. Or if the PDU is invalid. Or if the iPostSize is
|
|||
|
// smaller than the next PDU.
|
|||
|
alloc_size = extra;
|
|||
|
}
|
|||
|
|
|||
|
// Allocate a new buffer to save the extra data for the next read.
|
|||
|
PBYTE pNewBuffer;
|
|||
|
|
|||
|
pNewBuffer = TransConnectionAllocatePacket(this,
|
|||
|
alloc_size);
|
|||
|
|
|||
|
if (0 == pNewBuffer)
|
|||
|
{
|
|||
|
// We have a complete request. We could process the request and
|
|||
|
// close the connection only after trying to send the reply.
|
|||
|
|
|||
|
*pBuffer = 0;
|
|||
|
*pBufferLength = 0;
|
|||
|
|
|||
|
Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(*pBuffer);
|
|||
|
|
|||
|
// Save away extra data for the next receive
|
|||
|
RpcpMemoryCopy(pNewBuffer,
|
|||
|
pReadBuffer + *pBufferLength,
|
|||
|
extra);
|
|||
|
pReadBuffer = pNewBuffer;
|
|||
|
iLastRead = extra;
|
|||
|
maxReadBuffer = alloc_size;
|
|||
|
|
|||
|
ASSERT(iLastRead <= maxReadBuffer);
|
|||
|
|
|||
|
ASSERT(pReadBuffer != *pBuffer);
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
CO_SubmitSyncRead(
|
|||
|
IN PCONNECTION pConnection,
|
|||
|
OUT BUFFER *pBuffer,
|
|||
|
OUT PUINT pMessageLength
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called in the synchronous receive path when more data is needed
|
|||
|
in to complete the message. This function is non-blocking but
|
|||
|
it will try to read as much data as it can and may return a
|
|||
|
completed PDU.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConnection - The connection to receive from.
|
|||
|
->pReadBuffer
|
|||
|
->maxReadBuffer
|
|||
|
->iLastRead
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK - Ok and a complete PDU has arrived
|
|||
|
|
|||
|
RPC_P_IO_PENDING - A receive is now outstanding on the connection.
|
|||
|
Wait for it to complete..
|
|||
|
|
|||
|
RPC_P_RECEIVE_FAILED - Failure
|
|||
|
RPC_P_CONNECTION_SHUTDOWN - Failure - graceful close received.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
|
|||
|
ASSERT(pConnection->pReadBuffer);
|
|||
|
|
|||
|
if (pConnection->maxReadBuffer == pConnection->iLastRead)
|
|||
|
{
|
|||
|
// Coalesced receive and we've got one (or more) PDUs
|
|||
|
status = pConnection->ProcessRead(0, pBuffer, pMessageLength);
|
|||
|
|
|||
|
ASSERT(status != RPC_P_PARTIAL_RECEIVE);
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
DWORD bytes;
|
|||
|
DWORD readbytes;
|
|||
|
|
|||
|
ASSERT_READ_EVENT_IS_THERE(pConnection);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
BOOL b;
|
|||
|
|
|||
|
readbytes = pConnection->maxReadBuffer - pConnection->iLastRead;
|
|||
|
|
|||
|
pConnection->StartingReadIO();
|
|||
|
if (pConnection->fAborted)
|
|||
|
{
|
|||
|
pConnection->ReadIOFinished();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
status = pConnection->Receive(pConnection->Conn.Handle,
|
|||
|
pConnection->pReadBuffer + pConnection->iLastRead,
|
|||
|
readbytes,
|
|||
|
&bytes,
|
|||
|
&pConnection->Read.ol);
|
|||
|
|
|||
|
pConnection->ReadIOFinished();
|
|||
|
|
|||
|
if ((status == ERROR_IO_PENDING) || (status == ERROR_IO_INCOMPLETE))
|
|||
|
{
|
|||
|
// The most common path
|
|||
|
return(RPC_P_IO_PENDING);
|
|||
|
}
|
|||
|
|
|||
|
if (status != RPC_S_OK)
|
|||
|
{
|
|||
|
switch (status)
|
|||
|
{
|
|||
|
case ERROR_MORE_DATA:
|
|||
|
// Treat as success
|
|||
|
|
|||
|
// Note: ReadFile doesn't return the number of bytes read in this
|
|||
|
// case even though the data is available...
|
|||
|
// It should still be right, but this double checks it.
|
|||
|
|
|||
|
ASSERT(pConnection->Read.ol.InternalHigh == readbytes);
|
|||
|
|
|||
|
ASSERT(MessageLength((PCONN_RPC_HEADER)pConnection->pReadBuffer) >
|
|||
|
pConnection->maxReadBuffer);
|
|||
|
|
|||
|
bytes = readbytes;
|
|||
|
|
|||
|
status = RPC_S_OK;
|
|||
|
break;
|
|||
|
|
|||
|
case ERROR_GRACEFUL_DISCONNECT:
|
|||
|
RpcpErrorAddRecord(EEInfoGCIO,
|
|||
|
status,
|
|||
|
EEInfoDLCOSubmitSyncRead10);
|
|||
|
status = RPC_P_CONNECTION_SHUTDOWN;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
RpcpErrorAddRecord(EEInfoGCIO,
|
|||
|
status,
|
|||
|
EEInfoDLCOSubmitSyncRead20);
|
|||
|
VALIDATE(status)
|
|||
|
{
|
|||
|
ERROR_NETNAME_DELETED,
|
|||
|
ERROR_BROKEN_PIPE,
|
|||
|
ERROR_PIPE_NOT_CONNECTED,
|
|||
|
ERROR_NO_SYSTEM_RESOURCES,
|
|||
|
ERROR_COMMITMENT_LIMIT,
|
|||
|
WSAECONNRESET,
|
|||
|
WSAESHUTDOWN,
|
|||
|
WSAECONNABORTED,
|
|||
|
ERROR_UNEXP_NET_ERR,
|
|||
|
ERROR_WORKING_SET_QUOTA
|
|||
|
} END_VALIDATE;
|
|||
|
status = RPC_P_RECEIVE_FAILED;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (bytes == 0)
|
|||
|
{
|
|||
|
status = RPC_P_CONNECTION_SHUTDOWN;
|
|||
|
}
|
|||
|
|
|||
|
if (status != RPC_S_OK)
|
|||
|
{
|
|||
|
pConnection->Abort();
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
// Read completed, process the data now..
|
|||
|
status = pConnection->ProcessRead(bytes, pBuffer, pMessageLength);
|
|||
|
}
|
|||
|
while (status == RPC_P_PARTIAL_RECEIVE );
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
RPC_ENTRY
|
|||
|
CO_SyncRecv(
|
|||
|
IN RPC_TRANSPORT_CONNECTION ThisConnection,
|
|||
|
OUT BUFFER *pBuffer,
|
|||
|
OUT PUINT pBufferLength,
|
|||
|
IN DWORD dwTimeout
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Receive the next PDU to arrive at the connection.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ThisConnection - The connection to read from.
|
|||
|
|
|||
|
pBuffer - If successful, points to a buffer containing the next PDU.
|
|||
|
pBufferLength - If successful, contains the length of the message.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK
|
|||
|
|
|||
|
RPC_P_RECEIVE_FAILED - Connection aborted.
|
|||
|
RPC_S_CALL_CANCELLED - Connection aborted.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCONNECTION p = (PCONNECTION)ThisConnection;
|
|||
|
DWORD bytes;
|
|||
|
RPC_STATUS status;
|
|||
|
HANDLE hEvent;
|
|||
|
|
|||
|
ASSERT((p->type & TYPE_MASK) == CLIENT);
|
|||
|
|
|||
|
ASSERT(p->pReadBuffer == 0);
|
|||
|
|
|||
|
p->pReadBuffer = TransConnectionAllocatePacket(p, p->iPostSize);
|
|||
|
|
|||
|
hEvent = I_RpcTransGetThreadEvent();
|
|||
|
|
|||
|
if (p->pReadBuffer == 0)
|
|||
|
{
|
|||
|
p->Abort();
|
|||
|
return(RPC_P_RECEIVE_FAILED);
|
|||
|
}
|
|||
|
|
|||
|
p->maxReadBuffer = p->iPostSize;
|
|||
|
p->iLastRead = 0;
|
|||
|
p->Read.ol.hEvent = (HANDLE)((ULONG_PTR)hEvent | 0x01);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
status = CO_SubmitSyncRead(p, pBuffer, pBufferLength);
|
|||
|
|
|||
|
if (status != RPC_P_IO_PENDING)
|
|||
|
{
|
|||
|
ASSERT(status != RPC_S_CALL_CANCELLED);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
status = UTIL_GetOverlappedResultEx(ThisConnection,
|
|||
|
&p->Read.ol,
|
|||
|
&bytes,
|
|||
|
TRUE, // Alertable
|
|||
|
dwTimeout);
|
|||
|
|
|||
|
if (status != RPC_S_OK)
|
|||
|
{
|
|||
|
if (status != ERROR_MORE_DATA)
|
|||
|
{
|
|||
|
RpcpErrorAddRecord(EEInfoGCIO,
|
|||
|
status,
|
|||
|
EEInfoDLCOSyncRecv10);
|
|||
|
if ((status != RPC_S_CALL_CANCELLED) && (status != RPC_P_TIMEOUT))
|
|||
|
{
|
|||
|
status = RPC_P_RECEIVE_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// ERROR_MORE_DATA is success
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status = p->ProcessRead(bytes, pBuffer, pBufferLength);
|
|||
|
|
|||
|
}
|
|||
|
while (status == RPC_P_PARTIAL_RECEIVE);
|
|||
|
|
|||
|
if (status == RPC_S_OK)
|
|||
|
{
|
|||
|
ASSERT(p->pReadBuffer == 0);
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
p->Abort();
|
|||
|
|
|||
|
if ((status == RPC_S_CALL_CANCELLED) || (status == RPC_P_TIMEOUT))
|
|||
|
{
|
|||
|
// Wait for the read to complete. Since the connection has
|
|||
|
// just been closed this won't take very long.
|
|||
|
UTIL_WaitForSyncIO(&p->Read.ol,
|
|||
|
FALSE,
|
|||
|
INFINITE);
|
|||
|
}
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
BASE_CONNECTION::Initialize (
|
|||
|
void
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initializes a base connection. Prior initialization
|
|||
|
ensures orderly cleanup.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
type = CLIENT | CONNECTION;
|
|||
|
pReadBuffer = 0;
|
|||
|
Conn.Handle = 0;
|
|||
|
fAborted = FALSE;
|
|||
|
pReadBuffer = 0;
|
|||
|
maxReadBuffer = 0;
|
|||
|
iPostSize = gPostSize;
|
|||
|
iLastRead = 0;
|
|||
|
RpcpMemorySet(&Read.ol, 0, sizeof(Read.ol));
|
|||
|
Read.pAsyncObject = this;
|
|||
|
Read.thread = 0;
|
|||
|
InitIoCounter();
|
|||
|
}
|