807 lines
24 KiB
C++
807 lines
24 KiB
C++
|
/////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 2001 Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
// rcvdgram
|
||
|
//
|
||
|
// Abstract:
|
||
|
// This module contains code which deals with receiving datagrams
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
#include "sysvars.h"
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// private constants, types, and prototypes
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
|
||
|
const PCHAR strFunc1 = "TSReceiveDatagram";
|
||
|
const PCHAR strFunc2 = "TSRcvDatagramHandler";
|
||
|
const PCHAR strFunc3 = "TSChainedRcvDatagramHandler";
|
||
|
const PCHAR strFuncP1 = "TSReceiveDgramComplete";
|
||
|
const PCHAR strFuncP2 = "TSGetRestOfDgram";
|
||
|
const PCHAR strFuncP3 = "TSShowDgramInfo";
|
||
|
|
||
|
|
||
|
//
|
||
|
// completion information structure
|
||
|
//
|
||
|
struct RECEIVE_CONTEXT
|
||
|
{
|
||
|
PMDL pLowerMdl; // mdl from lower irp
|
||
|
PRECEIVE_DATA pReceiveData; // above structure
|
||
|
PADDRESS_OBJECT pAddressObject; // associate address object
|
||
|
PIRP_POOL pIrpPool;
|
||
|
};
|
||
|
typedef RECEIVE_CONTEXT *PRECEIVE_CONTEXT;
|
||
|
|
||
|
|
||
|
//
|
||
|
// completion function
|
||
|
//
|
||
|
TDI_STATUS
|
||
|
TSReceiveDgramComplete(
|
||
|
PDEVICE_OBJECT DeviceObject,
|
||
|
PIRP Irp,
|
||
|
PVOID Context
|
||
|
);
|
||
|
|
||
|
|
||
|
PIRP
|
||
|
TSGetRestOfDgram(
|
||
|
PADDRESS_OBJECT pAddressObject,
|
||
|
PRECEIVE_DATA pReceiveData
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
TSShowDgramInfo(
|
||
|
PVOID pvTdiEventContext,
|
||
|
LONG lSourceAddressLength,
|
||
|
PVOID pvSourceAddress,
|
||
|
LONG lOptionsLength,
|
||
|
PVOID pvOptions,
|
||
|
ULONG ulReceiveDatagramFlags
|
||
|
);
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// public functions
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------
|
||
|
//
|
||
|
// Function: TSReceiveDatagram
|
||
|
//
|
||
|
// Arguments: pAddressObject -- address object
|
||
|
// pSendBuffer -- arguments from user dll
|
||
|
// pIrp -- completion information
|
||
|
//
|
||
|
// Returns: STATUS_SUCCESS
|
||
|
//
|
||
|
// Descript: This function checks to see if a datagram has been received
|
||
|
// on this address object. If so, and if it matches certain
|
||
|
// criteria, it returns it. Otherwise it returns with no data.
|
||
|
//
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
TSReceiveDatagram(PADDRESS_OBJECT pAddressObject,
|
||
|
PSEND_BUFFER pSendBuffer,
|
||
|
PRECEIVE_BUFFER pReceiveBuffer)
|
||
|
{
|
||
|
PTRANSPORT_ADDRESS pTransportAddress
|
||
|
= (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.SendArgs.TransAddr;
|
||
|
BOOLEAN fMatchAddress
|
||
|
= (BOOLEAN)(pTransportAddress->TAAddressCount > 0);
|
||
|
PRECEIVE_DATA pReceiveData = NULL;
|
||
|
|
||
|
//
|
||
|
// if need to match to address, return the first packet in the queue
|
||
|
// that was sent from the specified address.
|
||
|
//
|
||
|
if (fMatchAddress)
|
||
|
{
|
||
|
ULONG ulCompareLength
|
||
|
= FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
|
||
|
+ FIELD_OFFSET(TA_ADDRESS, Address)
|
||
|
+ pTransportAddress->Address[0].AddressLength;
|
||
|
|
||
|
if (pTransportAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP)
|
||
|
{
|
||
|
ulCompareLength -= 8; // ignore sin_zero[8]
|
||
|
}
|
||
|
|
||
|
TSAcquireSpinLock(&pAddressObject->TdiSpinLock);
|
||
|
pReceiveData = pAddressObject->pHeadReceiveData;
|
||
|
while(pReceiveData)
|
||
|
{
|
||
|
if (RtlEqualMemory(pTransportAddress,
|
||
|
&pReceiveData->TransAddr,
|
||
|
ulCompareLength))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
pReceiveData = pReceiveData->pNextReceiveData;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// did we find anything?
|
||
|
//
|
||
|
if (pReceiveData)
|
||
|
{
|
||
|
//
|
||
|
// fix up the lists as necessary
|
||
|
//
|
||
|
if (pReceiveData->pPrevReceiveData)
|
||
|
{
|
||
|
pReceiveData->pPrevReceiveData->pNextReceiveData
|
||
|
= pReceiveData->pNextReceiveData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pAddressObject->pHeadReceiveData = pReceiveData->pNextReceiveData;
|
||
|
}
|
||
|
|
||
|
if (pReceiveData->pNextReceiveData)
|
||
|
{
|
||
|
pReceiveData->pNextReceiveData->pPrevReceiveData
|
||
|
= pReceiveData->pPrevReceiveData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pAddressObject->pTailReceiveData = pReceiveData->pPrevReceiveData;
|
||
|
}
|
||
|
}
|
||
|
TSReleaseSpinLock(&pAddressObject->TdiSpinLock);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// if not matching address, just get the first packet from the queue
|
||
|
//
|
||
|
else
|
||
|
{
|
||
|
TSAcquireSpinLock(&pAddressObject->TdiSpinLock);
|
||
|
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)
|
||
|
{
|
||
|
//
|
||
|
// we are only showing debug if we actually return a packet
|
||
|
//
|
||
|
if (ulDebugLevel & ulDebugShowCommand)
|
||
|
{
|
||
|
DebugPrint1("\nCommand = ulRECEIVEDATAGRAM\n"
|
||
|
"FileObject = %p\n",
|
||
|
pAddressObject);
|
||
|
if (pTransportAddress->TAAddressCount)
|
||
|
{
|
||
|
TSPrintTaAddress(pTransportAddress->Address);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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(&pReceiveBuffer->RESULTS.RecvDgramRet.TransAddr,
|
||
|
&pReceiveData->TransAddr,
|
||
|
sizeof(TRANSADDR));
|
||
|
|
||
|
RtlCopyMemory(MmGetSystemAddressForMdl(pMdl),
|
||
|
pReceiveData->pucDataBuffer,
|
||
|
pReceiveData->ulBufferLength);
|
||
|
TSFreeUserBuffer(pMdl);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pReceiveData->ulBufferLength = 0;
|
||
|
}
|
||
|
|
||
|
pReceiveBuffer->RESULTS.RecvDgramRet.ulBufferLength = pReceiveData->ulBufferLength;
|
||
|
|
||
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
||
|
TSFreeMemory(pReceiveData);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pReceiveBuffer->RESULTS.RecvDgramRet.ulBufferLength = 0;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
// -----------------------------------------------
|
||
|
//
|
||
|
// Function: TSRcvDatagramHandler
|
||
|
//
|
||
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
||
|
// lSourceAddressLength -- #bytes of source address
|
||
|
// pvSourceAddress -- TransportAddress
|
||
|
// lOptionsLength -- #bytes of transport-specific options
|
||
|
// pvOptions -- options string
|
||
|
// ulReceiveDatagramFlags -- nature of datagram received
|
||
|
// 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 datagrams
|
||
|
//
|
||
|
// -----------------------------------------------
|
||
|
|
||
|
TDI_STATUS
|
||
|
TSRcvDatagramHandler(PVOID pvTdiEventContext,
|
||
|
LONG lSourceAddressLength,
|
||
|
PVOID pvSourceAddress,
|
||
|
LONG lOptionsLength,
|
||
|
PVOID pvOptions,
|
||
|
ULONG ulReceiveDatagramFlags,
|
||
|
ULONG ulBytesIndicated,
|
||
|
ULONG ulBytesTotal,
|
||
|
PULONG pulBytesTaken,
|
||
|
PVOID pvTsdu,
|
||
|
PIRP *pIoRequestPacket)
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// show debug information
|
||
|
//
|
||
|
if (ulDebugLevel & ulDebugShowHandlers)
|
||
|
{
|
||
|
DebugPrint1("\n >>>> %s\n", strFunc2);
|
||
|
TSShowDgramInfo(pvTdiEventContext,
|
||
|
lSourceAddressLength,
|
||
|
pvSourceAddress,
|
||
|
lOptionsLength,
|
||
|
pvOptions,
|
||
|
ulReceiveDatagramFlags);
|
||
|
|
||
|
DebugPrint3("BytesIndicated = %u\n"
|
||
|
"BytesTotal = %u\n"
|
||
|
"pTSDU = %p\n",
|
||
|
ulBytesIndicated,
|
||
|
ulBytesTotal,
|
||
|
pvTsdu);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// bad situation if more bytes are indicated than the total in the packet
|
||
|
//
|
||
|
if (ulBytesIndicated > ulBytesTotal)
|
||
|
{
|
||
|
DebugPrint2("%d bytes indicated > %u bytes total\n",
|
||
|
ulBytesIndicated,
|
||
|
ulBytesTotal);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// now start doing the work...
|
||
|
//
|
||
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
||
|
PRECEIVE_DATA pReceiveData;
|
||
|
TDI_STATUS TdiStatus = TDI_SUCCESS; // default -- we are done with packet
|
||
|
// (also returned in case of error)
|
||
|
|
||
|
if ((TSAllocateMemory((PVOID *)&pReceiveData,
|
||
|
sizeof(RECEIVE_DATA),
|
||
|
strFunc2,
|
||
|
"ReceiveData")) == STATUS_SUCCESS)
|
||
|
{
|
||
|
PUCHAR pucDataBuffer = NULL;
|
||
|
|
||
|
if ((TSAllocateMemory((PVOID *)&pucDataBuffer,
|
||
|
ulBytesTotal,
|
||
|
strFunc2,
|
||
|
"DataBuffer")) == STATUS_SUCCESS)
|
||
|
{
|
||
|
RtlCopyMemory(&pReceiveData->TransAddr,
|
||
|
pvSourceAddress,
|
||
|
lSourceAddressLength);
|
||
|
|
||
|
pReceiveData->pucDataBuffer = pucDataBuffer;
|
||
|
pReceiveData->ulBufferLength = ulBytesTotal;
|
||
|
|
||
|
TdiCopyLookaheadData(pucDataBuffer,
|
||
|
pvTsdu,
|
||
|
ulBytesIndicated,
|
||
|
ulReceiveDatagramFlags);
|
||
|
|
||
|
pReceiveData->ulBufferUsed = ulBytesIndicated;
|
||
|
|
||
|
|
||
|
if (ulBytesIndicated == ulBytesTotal) // note: should never be >
|
||
|
{
|
||
|
TSPacketReceived(pAddressObject,
|
||
|
pReceiveData,
|
||
|
FALSE);
|
||
|
|
||
|
*pulBytesTaken = ulBytesTotal;
|
||
|
*pIoRequestPacket = NULL;
|
||
|
}
|
||
|
|
||
|
else // not all data is present!!
|
||
|
{
|
||
|
PIRP pLowerIrp = TSGetRestOfDgram(pAddressObject,
|
||
|
pReceiveData);
|
||
|
|
||
|
if (pLowerIrp)
|
||
|
{
|
||
|
//
|
||
|
// need to do this since we are bypassing IoCallDriver
|
||
|
//
|
||
|
IoSetNextIrpStackLocation(pLowerIrp);
|
||
|
|
||
|
*pulBytesTaken = ulBytesIndicated;
|
||
|
*pIoRequestPacket = pLowerIrp;
|
||
|
TdiStatus = TDI_MORE_PROCESSING;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TSFreeMemory(pReceiveData->pucDataBuffer);
|
||
|
TSFreeMemory(pReceiveData);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else // unable to allocate pucDataBuffer
|
||
|
{
|
||
|
TSFreeMemory(pReceiveData);
|
||
|
}
|
||
|
}
|
||
|
return TdiStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ----------------------------------------------
|
||
|
//
|
||
|
// Function: TSChainedRcvDatagramHandler
|
||
|
//
|
||
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
||
|
// lSourceAddressLength -- #bytes of source address
|
||
|
// pvSourceAddress -- TransportAddress
|
||
|
// lOptionsLength -- #bytes of transport-specific options
|
||
|
// pvOptions -- options string
|
||
|
// ulReceiveDatagramFlags -- nature of datagram received
|
||
|
// ulReceiveDatagramLength -- bytes in received datagram
|
||
|
// ulStartingOffset -- starting offset of data within MDL
|
||
|
// pTsdu -- data buffer (as an mdl)
|
||
|
// pvTsduDescriptor -- handle to use when completing if pend
|
||
|
//
|
||
|
// Returns: STATUS_DATA_NOT_ACCEPTED or STATUS_SUCCESS
|
||
|
//
|
||
|
// Descript: Deals with receiving chained datagrams (where the
|
||
|
// entire datagram is always available)
|
||
|
//
|
||
|
// -----------------------------------------------
|
||
|
|
||
|
#pragma warning(disable: UNREFERENCED_PARAM)
|
||
|
|
||
|
TDI_STATUS
|
||
|
TSChainedRcvDatagramHandler(PVOID pvTdiEventContext,
|
||
|
LONG lSourceAddressLength,
|
||
|
PVOID pvSourceAddress,
|
||
|
LONG lOptionsLength,
|
||
|
PVOID pvOptions,
|
||
|
ULONG ulReceiveDatagramFlags,
|
||
|
ULONG ulReceiveDatagramLength,
|
||
|
ULONG ulStartingOffset,
|
||
|
PMDL pMdl,
|
||
|
PVOID pvTsduDescriptor)
|
||
|
{
|
||
|
if (ulDebugLevel & ulDebugShowHandlers)
|
||
|
{
|
||
|
DebugPrint1("\n >>>> %s\n", strFunc3);
|
||
|
TSShowDgramInfo(pvTdiEventContext,
|
||
|
lSourceAddressLength,
|
||
|
pvSourceAddress,
|
||
|
lOptionsLength,
|
||
|
pvOptions,
|
||
|
ulReceiveDatagramFlags);
|
||
|
|
||
|
DebugPrint3("DataLength = %u\n"
|
||
|
"StartingOffset = %u\n"
|
||
|
"pTSDU = %p\n",
|
||
|
ulReceiveDatagramLength,
|
||
|
ulStartingOffset,
|
||
|
pMdl);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// now do the work..
|
||
|
//
|
||
|
PRECEIVE_DATA pReceiveData;
|
||
|
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
|
||
|
|
||
|
if ((TSAllocateMemory((PVOID *)&pReceiveData,
|
||
|
sizeof(RECEIVE_DATA),
|
||
|
strFunc3,
|
||
|
"ReceiveData")) == STATUS_SUCCESS)
|
||
|
{
|
||
|
PUCHAR pucDataBuffer = NULL;
|
||
|
|
||
|
if ((TSAllocateMemory((PVOID *)&pucDataBuffer,
|
||
|
ulReceiveDatagramLength,
|
||
|
strFunc3,
|
||
|
"DataBuffer")) == STATUS_SUCCESS)
|
||
|
{
|
||
|
ULONG ulBytesCopied;
|
||
|
|
||
|
RtlCopyMemory(&pReceiveData->TransAddr,
|
||
|
pvSourceAddress,
|
||
|
lSourceAddressLength);
|
||
|
|
||
|
TdiCopyMdlToBuffer(pMdl,
|
||
|
ulStartingOffset,
|
||
|
pucDataBuffer,
|
||
|
0,
|
||
|
ulReceiveDatagramLength,
|
||
|
&ulBytesCopied);
|
||
|
|
||
|
//
|
||
|
// if successfully copied all data
|
||
|
//
|
||
|
if (ulBytesCopied == ulReceiveDatagramLength)
|
||
|
{
|
||
|
UCHAR ucFirstChar = *pucDataBuffer;
|
||
|
|
||
|
pReceiveData->pucDataBuffer = pucDataBuffer;
|
||
|
pReceiveData->ulBufferLength = ulReceiveDatagramLength;
|
||
|
pReceiveData->ulBufferUsed = ulReceiveDatagramLength;
|
||
|
TSPacketReceived(pAddressObject,
|
||
|
pReceiveData,
|
||
|
FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// error in copying data!
|
||
|
//
|
||
|
else
|
||
|
{
|
||
|
DebugPrint1("%s: error copying data\n", strFunc3);
|
||
|
|
||
|
TSFreeMemory(pucDataBuffer);
|
||
|
TSFreeMemory(pReceiveData);
|
||
|
}
|
||
|
}
|
||
|
else // unable to allocate pucDataBuffer
|
||
|
{
|
||
|
TSFreeMemory(pReceiveData);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return TDI_SUCCESS; // we are done with packet
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma warning(default: UNREFERENCED_PARAM)
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////
|
||
|
// private functions
|
||
|
/////////////////////////////////////////////////////////////
|
||
|
|
||
|
// ---------------------------------------------------------
|
||
|
//
|
||
|
// Function: TSReceiveDgramComplete
|
||
|
//
|
||
|
// Arguments: pDeviceObject -- device object that called ReceiveDatagram
|
||
|
// 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 and adds the packet
|
||
|
// to the receive queue of the address object. Then
|
||
|
// cleans up
|
||
|
//
|
||
|
// ---------------------------------------------------------
|
||
|
|
||
|
#pragma warning(disable: UNREFERENCED_PARAM)
|
||
|
|
||
|
TDI_STATUS
|
||
|
TSReceiveDgramComplete(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,
|
||
|
FALSE);
|
||
|
}
|
||
|
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, pReceiveContext->pIrpPool);
|
||
|
TSFreeBuffer(pReceiveContext->pLowerMdl);
|
||
|
|
||
|
TSFreeMemory(pReceiveContext);
|
||
|
|
||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||
|
|
||
|
}
|
||
|
|
||
|
#pragma warning(default: UNREFERENCED_PARAM)
|
||
|
|
||
|
// ------------------------------------------------------
|
||
|
//
|
||
|
// Function: TSGetRestOfDgram
|
||
|
//
|
||
|
// 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
|
||
|
TSGetRestOfDgram(PADDRESS_OBJECT pAddressObject,
|
||
|
PRECEIVE_DATA pReceiveData)
|
||
|
{
|
||
|
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),
|
||
|
strFuncP2,
|
||
|
"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;
|
||
|
|
||
|
//
|
||
|
// finally, the irp itself
|
||
|
//
|
||
|
PIRP pLowerIrp = TSAllocateIrp(pAddressObject->GenHead.pDeviceObject,
|
||
|
pAddressObject->pIrpPool);
|
||
|
|
||
|
if (pLowerIrp)
|
||
|
{
|
||
|
pReceiveContext->pIrpPool = pAddressObject->pIrpPool;
|
||
|
//
|
||
|
// if made it to here, everything is correctly allocated
|
||
|
// set up the irp for the call
|
||
|
//
|
||
|
#pragma warning(disable: CONSTANT_CONDITIONAL)
|
||
|
|
||
|
TdiBuildReceiveDatagram(pLowerIrp,
|
||
|
pAddressObject->GenHead.pDeviceObject,
|
||
|
pAddressObject->GenHead.pFileObject,
|
||
|
TSReceiveDgramComplete,
|
||
|
pReceiveContext,
|
||
|
pReceiveMdl,
|
||
|
0, /// ulBufferLength, // 0 doesn't work with ipx
|
||
|
NULL,
|
||
|
NULL,
|
||
|
TDI_RECEIVE_NORMAL);
|
||
|
|
||
|
#pragma warning(default: CONSTANT_CONDITIONAL)
|
||
|
|
||
|
//
|
||
|
// mark it pending before returning control to transport
|
||
|
//
|
||
|
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: TSShowDgramInfo
|
||
|
//
|
||
|
// Arguments: pvTdiEventContext -- really pointer to our AddressObject
|
||
|
// lSourceAddressLength -- #bytes of source address
|
||
|
// pvSourceAddress -- TransportAddress
|
||
|
// lOptionsLength -- #bytes of transport-specific options
|
||
|
// pvOptions -- options string
|
||
|
// ulReceiveDatagramFlags -- nature of datagram received
|
||
|
//
|
||
|
// Returns: none
|
||
|
//
|
||
|
// Descript: shows info passed to the dgram handlers
|
||
|
//
|
||
|
// --------------------------------
|
||
|
|
||
|
VOID
|
||
|
TSShowDgramInfo(PVOID pvTdiEventContext,
|
||
|
LONG lSourceAddressLength,
|
||
|
PVOID pvSourceAddress,
|
||
|
LONG lOptionsLength,
|
||
|
PVOID pvOptions,
|
||
|
ULONG ulReceiveDatagramFlags)
|
||
|
{
|
||
|
DebugPrint2("pAddressObject = %p\n"
|
||
|
"SourceAddressLength = %d\n",
|
||
|
pvTdiEventContext,
|
||
|
lSourceAddressLength);
|
||
|
|
||
|
if (lSourceAddressLength)
|
||
|
{
|
||
|
PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)pvSourceAddress;
|
||
|
|
||
|
DebugPrint0("SourceAddress: ");
|
||
|
TSPrintTaAddress(&pTransportAddress->Address[0]);
|
||
|
}
|
||
|
|
||
|
DebugPrint1("OptionsLength = %d\n", lOptionsLength);
|
||
|
|
||
|
if (lOptionsLength)
|
||
|
{
|
||
|
PUCHAR pucTemp = (PUCHAR)pvOptions;
|
||
|
|
||
|
DebugPrint0("Options: ");
|
||
|
for (LONG lCount = 0; lCount < lOptionsLength; lCount++)
|
||
|
{
|
||
|
DebugPrint1("%02x ", *pucTemp);
|
||
|
++pucTemp;
|
||
|
}
|
||
|
DebugPrint0("\n");
|
||
|
}
|
||
|
|
||
|
DebugPrint1("ReceiveDatagramFlags: 0x%08x\n", ulReceiveDatagramFlags);
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_BROADCAST)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_BROADCAST\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_MULTICAST)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_MULTICAST\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_PARTIAL)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_PARTIAL (legacy)\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_NORMAL) // shouldn't see for datagram
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_NORMAL\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_EXPEDITED) // shouldn't see for datagram
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_EXPEDITED\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_PEEK)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_PEEK\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_NO_RESPONSE_EXP) // not for datagrams
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_NO_RESPONSE_EXP\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_COPY_LOOKAHEAD)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_COPY_LOOKAHEAD\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_ENTIRE_MESSAGE)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_ENTIRE_MESSAGE\n");
|
||
|
}
|
||
|
if (ulReceiveDatagramFlags & TDI_RECEIVE_AT_DISPATCH_LEVEL)
|
||
|
{
|
||
|
DebugPrint0("TDI_RECEIVE_AT_DISPATCH_LEVEL\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// end of file rcvdgram.cpp
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|