914 lines
28 KiB
C++
914 lines
28 KiB
C++
/////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// receive
|
|
//
|
|
// Abstract:
|
|
// This module contains code which deals with receiving data
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "sysvars.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// private constants, types, and prototypes
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
const PCHAR strFunc1 = "TSReceive";
|
|
const PCHAR strFunc2 = "TSReceiveHandler";
|
|
const PCHAR strFunc3 = "TSRcvExpeditedHandler";
|
|
const PCHAR strFunc4 = "TSChainedReceiveHandler";
|
|
const PCHAR strFunc5 = "TSChainedRcvExpeditedHandler";
|
|
const PCHAR strFuncP1 = "TSReceiveComplete";
|
|
const PCHAR strFuncP2 = "TSShowReceiveInfo";
|
|
const PCHAR strFuncP3 = "TSGetRestOfData";
|
|
const PCHAR strFuncP4 = "TSCommonReceive";
|
|
const PCHAR strFuncP5 = "TSCommonChainedReceive";
|
|
|
|
//
|
|
// completion context
|
|
//
|
|
struct RECEIVE_CONTEXT
|
|
{
|
|
PMDL pLowerMdl; // mdl from lower irp
|
|
PRECEIVE_DATA pReceiveData; // above structure
|
|
PADDRESS_OBJECT pAddressObject;
|
|
BOOLEAN fIsExpedited;
|
|
};
|
|
typedef RECEIVE_CONTEXT *PRECEIVE_CONTEXT;
|
|
|
|
|
|
//
|
|
// completion function
|
|
//
|
|
TDI_STATUS
|
|
TSReceiveComplete(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp,
|
|
PVOID Context
|
|
);
|
|
|
|
|
|
PIRP
|
|
TSGetRestOfData(
|
|
PADDRESS_OBJECT pAddressObject,
|
|
PRECEIVE_DATA pReceiveData,
|
|
BOOLEAN fIsExpedited
|
|
);
|
|
|
|
VOID
|
|
TSShowReceiveInfo(
|
|
PADDRESS_OBJECT pAddressObject,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulBytesAvailable,
|
|
PVOID pvTsdu,
|
|
BOOLEAN fIsChained
|
|
);
|
|
|
|
|
|
TDI_STATUS
|
|
TSCommonReceive(
|
|
PADDRESS_OBJECT pAddressObject,
|
|
ULONG ulBytesTotal,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulReceiveFlags,
|
|
PVOID pvTsdu,
|
|
BOOLEAN fIsExpedited,
|
|
PULONG pulBytesTaken,
|
|
PIRP *pIoRequestPacket
|
|
);
|
|
|
|
|
|
|
|
TDI_STATUS
|
|
TSCommonChainedReceive(
|
|
PADDRESS_OBJECT pAddressObject,
|
|
ULONG ulReceiveLength,
|
|
ULONG ulStartingOffset,
|
|
PMDL pReceiveMdl,
|
|
BOOLEAN fIsExpedited,
|
|
PVOID pvTsduDescriptor
|
|
);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// public functions
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSReceive
|
|
//
|
|
// Arguments: pEndpointObject -- current endpoint
|
|
// pIrp -- completion information
|
|
//
|
|
// Returns: NTSTATUS (normally pending)
|
|
//
|
|
// Descript: This function receives data over a connection
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSReceive(PENDPOINT_OBJECT pEndpoint,
|
|
PSEND_BUFFER pSendBuffer,
|
|
PRECEIVE_BUFFER pReceiveBuffer)
|
|
{
|
|
PADDRESS_OBJECT pAddressObject = pEndpoint->pAddressObject;
|
|
|
|
//
|
|
// assume no packet
|
|
//
|
|
pReceiveBuffer->RESULTS.RecvDgramRet.ulBufferLength = 0;
|
|
|
|
if (pAddressObject)
|
|
{
|
|
PRECEIVE_DATA pReceiveData;
|
|
|
|
//
|
|
// just get the first packet from the queue
|
|
// check expedited list First
|
|
//
|
|
TSAcquireSpinLock(&pAddressObject->TdiSpinLock);
|
|
pReceiveData = pAddressObject->pHeadRcvExpData;
|
|
if (pReceiveData)
|
|
{
|
|
//
|
|
// fix up the lists as necessary
|
|
//
|
|
if (pReceiveData->pNextReceiveData)
|
|
{
|
|
pReceiveData->pNextReceiveData->pPrevReceiveData = NULL;
|
|
}
|
|
else
|
|
{
|
|
pAddressObject->pTailRcvExpData = NULL;
|
|
}
|
|
pAddressObject->pHeadRcvExpData = pReceiveData->pNextReceiveData;
|
|
}
|
|
|
|
//
|
|
// if no expedited receives, check normal list
|
|
//
|
|
else
|
|
{
|
|
pReceiveData = pAddressObject->pHeadReceiveData;
|
|
if (pReceiveData)
|
|
{
|
|
//
|
|
// fix up the lists as necessary
|
|
//
|
|
if (pReceiveData->pNextReceiveData)
|
|
{
|
|
pReceiveData->pNextReceiveData->pPrevReceiveData = NULL;
|
|
}
|
|
else
|
|
{
|
|
pAddressObject->pTailReceiveData = NULL;
|
|
}
|
|
pAddressObject->pHeadReceiveData = pReceiveData->pNextReceiveData;
|
|
}
|
|
}
|
|
TSReleaseSpinLock(&pAddressObject->TdiSpinLock);
|
|
|
|
//
|
|
// if we got a packet to return, then lets return it..
|
|
// and release its memory
|
|
//
|
|
if (pReceiveData)
|
|
{
|
|
//
|
|
// show debug, if it is turned on, and only if we actually
|
|
// are returning a packet
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulRECEIVE\n"
|
|
"FileObject = %p\n",
|
|
pEndpoint);
|
|
}
|
|
|
|
if (pReceiveData->ulBufferLength > pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength)
|
|
{
|
|
pReceiveData->ulBufferLength = pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength;
|
|
}
|
|
|
|
//
|
|
// attempt to lock down the memory
|
|
//
|
|
PMDL pMdl = TSMakeMdlForUserBuffer(pSendBuffer->COMMAND_ARGS.SendArgs.pucUserModeBuffer,
|
|
pReceiveData->ulBufferLength,
|
|
IoModifyAccess);
|
|
if (pMdl)
|
|
{
|
|
RtlCopyMemory(MmGetSystemAddressForMdl(pMdl),
|
|
pReceiveData->pucDataBuffer,
|
|
pReceiveData->ulBufferLength);
|
|
TSFreeUserBuffer(pMdl);
|
|
}
|
|
else
|
|
{
|
|
pReceiveData->ulBufferLength = 0;
|
|
}
|
|
|
|
pReceiveBuffer->RESULTS.RecvDgramRet.ulBufferLength = pReceiveData->ulBufferLength;
|
|
|
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
|
TSFreeMemory(pReceiveData);
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSReceiveHandler
|
|
//
|
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
|
// Connection_Context -- really pointer to our Endpoint
|
|
// ReceiveFlags -- nature of received data
|
|
// ulBytesIndicated --- length of data in buffer
|
|
// ulBytesTotal -- total length of datagram
|
|
// pulBytesTaken -- stuff with bytes used by this driver
|
|
// pvTsdu -- data buffer
|
|
// pIoRequestPacket -- pIrp in case not all data received
|
|
//
|
|
// Returns: STATUS_DATA_NOT_ACCEPTED (we didn't want data)
|
|
// STATUS_SUCCESS (we used all data & are done with it)
|
|
// STATUS_MORE_PROCESSING_REQUIRED -- we supplied an IRP for rest
|
|
//
|
|
// Descript: Event handler for incoming receives on connection
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
TDI_STATUS
|
|
TSReceiveHandler(PVOID pvTdiEventContext,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulBytesTotal,
|
|
PULONG pulBytesTaken,
|
|
PVOID pvTsdu,
|
|
PIRP *ppIoRequestPacket)
|
|
|
|
{
|
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
|
|
|
if (ulDebugLevel & ulDebugShowHandlers)
|
|
{
|
|
DebugPrint1("\n >>>> %s\n", strFunc2);
|
|
TSShowReceiveInfo(pAddressObject,
|
|
ConnectionContext,
|
|
ulReceiveFlags,
|
|
ulBytesIndicated,
|
|
ulBytesTotal,
|
|
pvTsdu,
|
|
FALSE);
|
|
}
|
|
|
|
return TSCommonReceive(pAddressObject,
|
|
ulBytesTotal,
|
|
ulBytesIndicated,
|
|
ulReceiveFlags,
|
|
pvTsdu,
|
|
((ulReceiveFlags & TDI_RECEIVE_EXPEDITED) != 0),
|
|
pulBytesTaken,
|
|
ppIoRequestPacket);
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSRcvExpeditedHandler
|
|
//
|
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
|
// Connection_Context -- really pointer to our Endpoint
|
|
// ReceiveFlags -- nature of received data
|
|
// ulBytesIndicated --- length of data in buffer
|
|
// ulBytesTotal -- total length of datagram
|
|
// pulBytesTaken -- stuff with bytes used by this driver
|
|
// pvTsdu -- data buffer
|
|
// pIoRequestPacket -- pIrp in case not all data received
|
|
//
|
|
// Returns: STATUS_DATA_NOT_ACCEPTED (we didn't want data)
|
|
// STATUS_SUCCESS (we used all data & are done with it)
|
|
// STATUS_MORE_PROCESSING_REQUIRED -- we supplied an IRP for rest
|
|
//
|
|
// Descript: Event handler for incoming expedited receives on connection
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
TDI_STATUS
|
|
TSRcvExpeditedHandler(PVOID pvTdiEventContext,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulBytesTotal,
|
|
PULONG pulBytesTaken,
|
|
PVOID pvTsdu,
|
|
PIRP *ppIoRequestPacket)
|
|
|
|
{
|
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
|
|
|
if (ulDebugLevel & ulDebugShowHandlers)
|
|
{
|
|
DebugPrint1("\n >>>> %s\n", strFunc3);
|
|
TSShowReceiveInfo(pAddressObject,
|
|
ConnectionContext,
|
|
ulReceiveFlags,
|
|
ulBytesIndicated,
|
|
ulBytesTotal,
|
|
pvTsdu,
|
|
FALSE);
|
|
}
|
|
|
|
return TSCommonReceive(pAddressObject,
|
|
ulBytesTotal,
|
|
ulBytesIndicated,
|
|
ulReceiveFlags,
|
|
pvTsdu,
|
|
TRUE,
|
|
pulBytesTaken,
|
|
ppIoRequestPacket);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSChainedReceiveHandler
|
|
//
|
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
|
// Connection_Context -- really pointer to our Endpoint
|
|
// ReceiveFlags -- nature of received data
|
|
// ulReceiveLength --- length of data in buffer
|
|
// ulStartingOffset -- total length of datagram
|
|
// pReceiveMdl -- data buffer
|
|
// pTsduDescriptor -- returns value for TdiReturnChainedReceives
|
|
//
|
|
// Returns: STATUS_DATA_NOT_ACCEPTED (we didn't want data)
|
|
// STATUS_SUCCESS (we used all data & are done with it)
|
|
// STATUS_MORE_PROCESSING_REQUIRED -- we supplied an IRP for rest
|
|
//
|
|
// Descript: Event handler for incoming receives on connection
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
TDI_STATUS
|
|
TSChainedReceiveHandler(PVOID pvTdiEventContext,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulReceiveLength,
|
|
ULONG ulStartingOffset,
|
|
PMDL pReceiveMdl,
|
|
PVOID pvTsduDescriptor)
|
|
{
|
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
|
|
|
if (ulDebugLevel & ulDebugShowHandlers)
|
|
{
|
|
DebugPrint1("\n >>>> %s\n", strFunc4);
|
|
TSShowReceiveInfo(pAddressObject,
|
|
ConnectionContext,
|
|
ulReceiveFlags,
|
|
ulReceiveLength,
|
|
ulStartingOffset,
|
|
pReceiveMdl,
|
|
TRUE);
|
|
}
|
|
|
|
return TSCommonChainedReceive(pAddressObject,
|
|
ulReceiveLength,
|
|
ulStartingOffset,
|
|
pReceiveMdl,
|
|
((ulReceiveFlags & TDI_RECEIVE_EXPEDITED) != 0),
|
|
pvTsduDescriptor);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSChainedRcvExpeditedHandler
|
|
//
|
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
|
// Connection_Context -- really pointer to our Endpoint
|
|
// ReceiveFlags -- nature of received data
|
|
// ulReceiveLength --- length of data in buffer
|
|
// ulStartingOffset -- total length of datagram
|
|
// pReceiveMdl -- data buffer
|
|
// pTsduDescriptor -- returns value for TdiReturnChainedReceives
|
|
//
|
|
// Returns: STATUS_DATA_NOT_ACCEPTED (we didn't want data)
|
|
// STATUS_SUCCESS (we used all data & are done with it)
|
|
// STATUS_MORE_PROCESSING_REQUIRED -- we supplied an IRP for rest
|
|
//
|
|
// Descript: Event handler for incoming receives on connection
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
|
|
TDI_STATUS
|
|
TSChainedRcvExpeditedHandler(PVOID pvTdiEventContext,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulReceiveLength,
|
|
ULONG ulStartingOffset,
|
|
PMDL pReceiveMdl,
|
|
PVOID pvTsduDescriptor)
|
|
{
|
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
|
|
|
if (ulDebugLevel & ulDebugShowHandlers)
|
|
{
|
|
DebugPrint1("\n >>>> %s\n", strFunc5);
|
|
TSShowReceiveInfo(pAddressObject,
|
|
ConnectionContext,
|
|
ulReceiveFlags,
|
|
ulReceiveLength,
|
|
ulStartingOffset,
|
|
pReceiveMdl,
|
|
TRUE);
|
|
}
|
|
|
|
return TSCommonChainedReceive(pAddressObject,
|
|
ulReceiveLength,
|
|
ulStartingOffset,
|
|
pReceiveMdl,
|
|
TRUE,
|
|
pvTsduDescriptor);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// private functions
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
// ---------------------------------------------------------
|
|
//
|
|
// Function: TSReceiveComplete
|
|
//
|
|
// Arguments: pDeviceObject -- device object that called Receive/Datagram
|
|
// pIrp -- IRP used in the call
|
|
// pContext -- context used for the call
|
|
//
|
|
// Returns: status of operation (STATUS_MORE_PROCESSING_REQUIRED)
|
|
//
|
|
// Descript: Gets the result of the receive, stuffs result into
|
|
// receive buffer, completes the IRP from the dll, and
|
|
// cleans up the Irp and associated data from the receive
|
|
//
|
|
// ---------------------------------------------------------
|
|
|
|
#pragma warning(disable: UNREFERENCED_PARAM)
|
|
|
|
|
|
TDI_STATUS
|
|
TSReceiveComplete(PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pLowerIrp,
|
|
PVOID pvContext)
|
|
|
|
{
|
|
PRECEIVE_CONTEXT pReceiveContext = (PRECEIVE_CONTEXT)pvContext;
|
|
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
|
|
ULONG ulBytesCopied = (ULONG)pLowerIrp->IoStatus.Information;
|
|
PADDRESS_OBJECT pAddressObject = pReceiveContext->pAddressObject;
|
|
PRECEIVE_DATA pReceiveData = pReceiveContext->pReceiveData;
|
|
|
|
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint2("%s: %u BytesCopied\n",
|
|
strFuncP1,
|
|
ulBytesCopied);
|
|
}
|
|
pReceiveData->ulBufferUsed += ulBytesCopied;
|
|
if (pReceiveData->ulBufferUsed >= pReceiveData->ulBufferLength)
|
|
{
|
|
TSPacketReceived(pAddressObject,
|
|
pReceiveData,
|
|
pReceiveContext->fIsExpedited);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint1("%s: Data Incomplete\n", strFuncP1);
|
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
|
TSFreeMemory(pReceiveData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugPrint2("%s: Completed with status 0x%08x\n",
|
|
strFuncP1,
|
|
lStatus);
|
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
|
TSFreeMemory(pReceiveData);
|
|
}
|
|
|
|
//
|
|
// now cleanup
|
|
//
|
|
TSFreeIrp(pLowerIrp, pAddressObject->pIrpPool);
|
|
TSFreeBuffer(pReceiveContext->pLowerMdl);
|
|
|
|
TSFreeMemory(pReceiveContext);
|
|
|
|
return TDI_MORE_PROCESSING;
|
|
}
|
|
|
|
#pragma warning(default: UNREFERENCED_PARAM)
|
|
|
|
|
|
// ---------------------------------
|
|
//
|
|
// Function: TSShowReceiveInfo
|
|
//
|
|
// Arguments: pAddressObject -- the address object associated with this endpoint
|
|
// ConnectionContext -- endpoint of this connection
|
|
// ulReceiveFlags -- info about the receive
|
|
// ulBytesIndicated -- bytes indicated up
|
|
// ulBytesAvailable -- total bytes (or starting offset)
|
|
// pvTsdu -- ptr to the data (or to its mdl)
|
|
// fIsChained -- if TRUE, then this is chained receive
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Descript: shows info passed to receive handler
|
|
//
|
|
// --------------------------------
|
|
|
|
VOID
|
|
TSShowReceiveInfo(PADDRESS_OBJECT pAddressObject,
|
|
CONNECTION_CONTEXT ConnectionContext,
|
|
ULONG ulReceiveFlags,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulBytesAvailable,
|
|
PVOID pvTsdu,
|
|
BOOLEAN fIsChained)
|
|
{
|
|
DebugPrint3("pAddressObject = %p\n"
|
|
"pEndpoint = %p\n"
|
|
"ulReceiveFlags = 0x%08x\n",
|
|
pAddressObject,
|
|
ConnectionContext,
|
|
ulReceiveFlags);
|
|
|
|
if (ulReceiveFlags & TDI_RECEIVE_NORMAL)
|
|
{
|
|
DebugPrint0(" TDI_RECEIVE_NORMAL\n");
|
|
}
|
|
|
|
if (ulReceiveFlags & TDI_RECEIVE_EXPEDITED)
|
|
{
|
|
DebugPrint0(" TDI_RECEIVE_EXPEDITED\n");
|
|
}
|
|
|
|
if (ulReceiveFlags & TDI_RECEIVE_ENTIRE_MESSAGE)
|
|
{
|
|
DebugPrint0(" TDI_RECEIVE_ENTIRE_MESSAGE\n");
|
|
}
|
|
|
|
if (ulReceiveFlags & TDI_RECEIVE_AT_DISPATCH_LEVEL)
|
|
{
|
|
DebugPrint0(" TDI_RECEIVE_AT_DISPATCH_LEVEL\n");
|
|
}
|
|
|
|
if (fIsChained)
|
|
{
|
|
DebugPrint3("ReceiveLength = %u\n"
|
|
"StartingOffset = 0x%08x\n"
|
|
"pMdl = %p\n",
|
|
ulBytesIndicated,
|
|
ulBytesAvailable,
|
|
pvTsdu);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint3("BytesIndicated = %u\n"
|
|
"TotalBytes = %u\n"
|
|
"pDataBuffer = %p\n",
|
|
ulBytesIndicated,
|
|
ulBytesAvailable,
|
|
pvTsdu);
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------
|
|
//
|
|
// Function: TSGetRestOfData
|
|
//
|
|
// Arguments: pAddressObject -- address object we are receiving on
|
|
// pReceiveData -- what we have received so far..
|
|
//
|
|
// Returns: Irp to return to transport, to get rest of data (NULL if error)
|
|
//
|
|
// Descript: This function sets up the IRP to get the rest of a datagram
|
|
// that was only partially delivered via the event handler
|
|
//
|
|
// -------------------------------------------------
|
|
|
|
PIRP
|
|
TSGetRestOfData(PADDRESS_OBJECT pAddressObject,
|
|
PRECEIVE_DATA pReceiveData,
|
|
BOOLEAN fIsExpedited)
|
|
|
|
{
|
|
PUCHAR pucDataBuffer = pReceiveData->pucDataBuffer + pReceiveData->ulBufferUsed;
|
|
ULONG ulBufferLength = pReceiveData->ulBufferLength - pReceiveData->ulBufferUsed;
|
|
PRECEIVE_CONTEXT pReceiveContext = NULL;
|
|
PMDL pReceiveMdl = NULL;
|
|
|
|
|
|
//
|
|
// allocate all the necessary structures
|
|
// our context
|
|
//
|
|
if ((TSAllocateMemory((PVOID *)&pReceiveContext,
|
|
sizeof(RECEIVE_CONTEXT),
|
|
strFuncP3,
|
|
"ReceiveContext")) != STATUS_SUCCESS)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// then the actual mdl
|
|
//
|
|
pReceiveMdl = TSAllocateBuffer(pucDataBuffer,
|
|
ulBufferLength);
|
|
|
|
if (pReceiveMdl)
|
|
{
|
|
//
|
|
// set up the completion context
|
|
//
|
|
pReceiveContext->pLowerMdl = pReceiveMdl;
|
|
pReceiveContext->pReceiveData = pReceiveData;
|
|
pReceiveContext->pAddressObject = pAddressObject;
|
|
pReceiveContext->fIsExpedited = fIsExpedited;
|
|
|
|
//
|
|
// finally, the irp itself
|
|
//
|
|
PIRP pLowerIrp = TSAllocateIrp(pAddressObject->pEndpoint->GenHead.pDeviceObject,
|
|
pAddressObject->pIrpPool);
|
|
|
|
if (pLowerIrp)
|
|
{
|
|
//
|
|
// if made it to here, everything is correctly allocated
|
|
// set up the irp for the call
|
|
//
|
|
#pragma warning(disable: CONSTANT_CONDITIONAL)
|
|
|
|
TdiBuildReceive(pLowerIrp,
|
|
pAddressObject->pEndpoint->GenHead.pDeviceObject,
|
|
pAddressObject->pEndpoint->GenHead.pFileObject,
|
|
TSReceiveComplete,
|
|
pReceiveContext,
|
|
pReceiveMdl,
|
|
TDI_RECEIVE_NORMAL,
|
|
ulBufferLength);
|
|
|
|
#pragma warning(default: CONSTANT_CONDITIONAL)
|
|
|
|
return pLowerIrp;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get here if there was an allocation failure
|
|
// need to clean up everything else...
|
|
//
|
|
cleanup:
|
|
if (pReceiveContext)
|
|
{
|
|
TSFreeMemory(pReceiveContext);
|
|
}
|
|
if (pReceiveMdl)
|
|
{
|
|
TSFreeBuffer(pReceiveMdl);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------
|
|
//
|
|
// Function: TSCommonReceive
|
|
//
|
|
// Arguments: see TSReceiveHandler
|
|
//
|
|
// Returns: status to return to protocol
|
|
//
|
|
// Descript: Common code for TSReceiveHandler and
|
|
// TSRcvExpeditedHandler. Pretty much all the work is
|
|
// done here
|
|
//
|
|
// ---------------------------------------------
|
|
|
|
|
|
TDI_STATUS
|
|
TSCommonReceive(PADDRESS_OBJECT pAddressObject,
|
|
ULONG ulBytesTotal,
|
|
ULONG ulBytesIndicated,
|
|
ULONG ulReceiveFlags,
|
|
PVOID pvTsdu,
|
|
BOOLEAN fIsExpedited,
|
|
PULONG pulBytesTaken,
|
|
PIRP *pIoRequestPacket)
|
|
{
|
|
//
|
|
// check for a bad condition -- more bytes indicated that total
|
|
//
|
|
if (ulBytesIndicated > ulBytesTotal)
|
|
{
|
|
DebugPrint2("%u bytes indicated > %u bytes total\n",
|
|
ulBytesIndicated,
|
|
ulBytesTotal);
|
|
return TDI_NOT_ACCEPTED;
|
|
}
|
|
|
|
|
|
PRECEIVE_DATA pReceiveData;
|
|
|
|
if ( (TSAllocateMemory((PVOID *)&pReceiveData,
|
|
sizeof(RECEIVE_DATA),
|
|
strFuncP4,
|
|
"ReceiveData")) == STATUS_SUCCESS)
|
|
{
|
|
PUCHAR pucDataBuffer = NULL;
|
|
|
|
if ((TSAllocateMemory((PVOID *)&pucDataBuffer,
|
|
ulBytesTotal,
|
|
strFuncP4,
|
|
"DataBuffer")) == STATUS_SUCCESS)
|
|
{
|
|
pReceiveData->pucDataBuffer = pucDataBuffer;
|
|
pReceiveData->ulBufferLength = ulBytesTotal;
|
|
}
|
|
else
|
|
{
|
|
TSFreeMemory(pReceiveData);
|
|
return TDI_NOT_ACCEPTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return TDI_NOT_ACCEPTED;
|
|
}
|
|
|
|
//
|
|
// copy the data indicated to us into the buffer
|
|
//
|
|
TdiCopyLookaheadData(pReceiveData->pucDataBuffer,
|
|
pvTsdu,
|
|
ulBytesIndicated,
|
|
ulReceiveFlags);
|
|
|
|
pReceiveData->ulBufferUsed = ulBytesIndicated;
|
|
|
|
//
|
|
// first case -- entire packet indicated to us
|
|
//
|
|
if (ulBytesIndicated == ulBytesTotal)
|
|
{
|
|
TSPacketReceived(pAddressObject,
|
|
pReceiveData,
|
|
fIsExpedited);
|
|
|
|
*pulBytesTaken = ulBytesTotal;
|
|
*pIoRequestPacket = NULL;
|
|
return TDI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// second case -- only part of data indicated up
|
|
//
|
|
else
|
|
{
|
|
PIRP pLowerIrp = TSGetRestOfData(pAddressObject,
|
|
pReceiveData,
|
|
fIsExpedited);
|
|
|
|
if (pLowerIrp)
|
|
{
|
|
//
|
|
// need to do this since we are bypassing IoCallDriver
|
|
//
|
|
IoSetNextIrpStackLocation(pLowerIrp);
|
|
|
|
*pulBytesTaken = ulBytesIndicated;
|
|
*pIoRequestPacket = pLowerIrp;
|
|
return TDI_MORE_PROCESSING;
|
|
}
|
|
else
|
|
{
|
|
DebugPrint1("%s: unable to get rest of packet\n", strFuncP4);
|
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
|
TSFreeMemory(pReceiveData);
|
|
return TDI_NOT_ACCEPTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------
|
|
//
|
|
// Function: TSCommonChainedReceive
|
|
//
|
|
// Arguments: see TStChainedRcvhandler
|
|
//
|
|
// Returns: status
|
|
//
|
|
// Descript: Common code for TSChainedReceiveHandler and
|
|
// TSChainedRcvExpeditedHandler. Pretty much all the work is
|
|
// done here
|
|
//
|
|
// ---------------------------------------------
|
|
|
|
TDI_STATUS
|
|
TSCommonChainedReceive(PADDRESS_OBJECT pAddressObject,
|
|
ULONG ulReceiveLength,
|
|
ULONG ulStartingOffset,
|
|
PMDL pReceiveMdl,
|
|
BOOLEAN fIsExpedited,
|
|
PVOID pvTsduDescriptor)
|
|
{
|
|
PRECEIVE_DATA pReceiveData;
|
|
|
|
|
|
if ((TSAllocateMemory((PVOID *)&pReceiveData,
|
|
sizeof(RECEIVE_DATA),
|
|
strFuncP5,
|
|
"ReceiveData")) == STATUS_SUCCESS)
|
|
{
|
|
PUCHAR pucDataBuffer;
|
|
|
|
if((TSAllocateMemory((PVOID *)&pucDataBuffer,
|
|
ulReceiveLength,
|
|
strFuncP5,
|
|
"DataBuffer")) == STATUS_SUCCESS)
|
|
{
|
|
ULONG ulBytesCopied;
|
|
|
|
TdiCopyMdlToBuffer(pReceiveMdl,
|
|
ulStartingOffset,
|
|
pucDataBuffer,
|
|
0,
|
|
ulReceiveLength,
|
|
&ulBytesCopied);
|
|
|
|
//
|
|
// if successfully copied all data
|
|
//
|
|
if (ulBytesCopied == ulReceiveLength)
|
|
{
|
|
pReceiveData->pucDataBuffer = pucDataBuffer;
|
|
pReceiveData->ulBufferLength = ulReceiveLength;
|
|
pReceiveData->ulBufferUsed = ulReceiveLength;
|
|
TSPacketReceived(pAddressObject,
|
|
pReceiveData,
|
|
fIsExpedited);
|
|
|
|
return TDI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// error in copying data!
|
|
//
|
|
else
|
|
{
|
|
DebugPrint1("%s: error copying data\n", strFuncP5);
|
|
TSFreeMemory(pucDataBuffer);
|
|
TSFreeMemory(pReceiveData);
|
|
}
|
|
}
|
|
else // unable to allocate pucDataBuffer
|
|
{
|
|
TSFreeMemory(pReceiveData);
|
|
}
|
|
}
|
|
return TDI_NOT_ACCEPTED;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// end of file receive.cpp
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|