windows-nt/Source/XPSP1/NT/net/tdi/sample/sys/receive.cpp
2020-09-26 16:20:57 +08:00

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
///////////////////////////////////////////////////////////////////////////////