305 lines
8.2 KiB
C++
305 lines
8.2 KiB
C++
//////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// receive.cpp
|
|
//
|
|
// Abstract:
|
|
// This module contains code which implements receive
|
|
// commands from the dll
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// Public functions
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// --------------------------------------------------------------------
|
|
//
|
|
// Function: DoReceiveDatagram
|
|
//
|
|
// Arguments: TdiHandle -- handle of address object
|
|
// pInTransportAddress -- TA for receiving on
|
|
// pOutTransportAddress -- full TA data was received on
|
|
// ppucBuffer -- buffer to stuff with received data
|
|
//
|
|
// Returns: length of data in buffer (0 if none or error)
|
|
//
|
|
// Descript: This function causes the driver to receive a datagram
|
|
//
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
ULONG
|
|
DoReceiveDatagram(ULONG ulTdiHandle,
|
|
PTRANSPORT_ADDRESS pInTransportAddress,
|
|
PTRANSPORT_ADDRESS pOutTransportAddress,
|
|
PUCHAR *ppucBuffer)
|
|
{
|
|
PUCHAR pucBuffer = (PUCHAR)LocalAllocateMemory(ulMAX_BUFFER_LENGTH);
|
|
|
|
if (!pucBuffer)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SEND_BUFFER SendBuffer; // arguments for command
|
|
|
|
//
|
|
// set up arguments
|
|
//
|
|
SendBuffer.TdiHandle = ulTdiHandle;
|
|
SendBuffer.COMMAND_ARGS.SendArgs.ulBufferLength = ulMAX_BUFFER_LENGTH;
|
|
SendBuffer.COMMAND_ARGS.SendArgs.pucUserModeBuffer = pucBuffer;
|
|
|
|
//
|
|
// if passed in a transport address to receive on
|
|
//
|
|
if (pInTransportAddress)
|
|
{
|
|
memcpy(&SendBuffer.COMMAND_ARGS.SendArgs.TransAddr,
|
|
pInTransportAddress,
|
|
(FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
|
|
+ FIELD_OFFSET(TA_ADDRESS, Address)
|
|
+ pInTransportAddress->Address[0].AddressLength));
|
|
|
|
}
|
|
//
|
|
// else, set the number of addresses field to 0
|
|
//
|
|
else
|
|
{
|
|
SendBuffer.COMMAND_ARGS.SendArgs.TransAddr.TAAddressCount = 0;
|
|
}
|
|
|
|
//
|
|
// call the driver
|
|
//
|
|
RECEIVE_BUFFER ReceiveBuffer; // return info from command
|
|
NTSTATUS lStatus = TdiLibDeviceIO(ulRECEIVEDATAGRAM,
|
|
&SendBuffer,
|
|
&ReceiveBuffer);
|
|
|
|
//
|
|
// deal with results -- assume no packet received or error occurred
|
|
//
|
|
ULONG ulBufferLength = 0;
|
|
*ppucBuffer = NULL;
|
|
|
|
|
|
//
|
|
// will return with success but ulBufferLength = 0 if there is no
|
|
// packet available
|
|
//
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
ulBufferLength = ReceiveBuffer.RESULTS.RecvDgramRet.ulBufferLength;
|
|
}
|
|
|
|
if (ulBufferLength)
|
|
{
|
|
if (pOutTransportAddress)
|
|
{
|
|
memcpy(pOutTransportAddress,
|
|
&ReceiveBuffer.RESULTS.RecvDgramRet.TransAddr,
|
|
(FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
|
|
+ FIELD_OFFSET(TA_ADDRESS, Address)
|
|
+ ReceiveBuffer.RESULTS.RecvDgramRet.TransAddr.TaAddress.AddressLength));
|
|
}
|
|
*ppucBuffer = pucBuffer;
|
|
}
|
|
else
|
|
{
|
|
LocalFreeMemory(pucBuffer);
|
|
}
|
|
return ulBufferLength;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
//
|
|
// Function: DoReceive
|
|
//
|
|
// Arguments: TdiHandle -- handle of endpoint object
|
|
// ppucBuffer -- buffer to stuff with received data
|
|
//
|
|
// Returns: length of data in buffer (0 if error)
|
|
//
|
|
// Descript: This function causes the driver to receive data sent
|
|
// over a connection
|
|
//
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
ULONG
|
|
DoReceive(ULONG ulTdiHandle,
|
|
PUCHAR *ppucBuffer)
|
|
{
|
|
PUCHAR pucBuffer = (PUCHAR)LocalAllocateMemory(ulMAX_BUFFER_LENGTH);
|
|
|
|
if (!pucBuffer)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SEND_BUFFER SendBuffer; // arguments for command
|
|
|
|
//
|
|
// set up arguments
|
|
//
|
|
SendBuffer.TdiHandle = ulTdiHandle;
|
|
SendBuffer.COMMAND_ARGS.SendArgs.ulBufferLength = ulMAX_BUFFER_LENGTH;
|
|
SendBuffer.COMMAND_ARGS.SendArgs.pucUserModeBuffer = pucBuffer;
|
|
|
|
//
|
|
// call the driver
|
|
//
|
|
RECEIVE_BUFFER ReceiveBuffer; // return info from command
|
|
NTSTATUS lStatus = TdiLibDeviceIO(ulRECEIVE,
|
|
&SendBuffer,
|
|
&ReceiveBuffer);
|
|
|
|
//
|
|
// deal with results -- assume no data or error
|
|
//
|
|
*ppucBuffer = NULL;
|
|
ULONG ulBufferLength = 0; // data length to return
|
|
|
|
//
|
|
// will return success with 0 bufferlength if no packet available
|
|
//
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
ulBufferLength = ReceiveBuffer.RESULTS.RecvDgramRet.ulBufferLength;
|
|
}
|
|
|
|
if (ulBufferLength)
|
|
{
|
|
*ppucBuffer = pucBuffer;
|
|
}
|
|
else
|
|
{
|
|
LocalFreeMemory(pucBuffer);
|
|
}
|
|
return ulBufferLength;
|
|
}
|
|
|
|
|
|
// ---------------------------------------
|
|
//
|
|
// Function: DoPostReceiveBuffer
|
|
//
|
|
// Arguments: TdiHandle -- handle for address object or endpoint
|
|
// ulBufferLength -- length of buffer to post for receive
|
|
//
|
|
// Returns: status of command
|
|
//
|
|
// Descript: This function allocates a buffer, which it then passed to
|
|
// the driver. The driver locks the buffer down, and posts it
|
|
// for a receive or receivedatagram.
|
|
//
|
|
// ----------------------------------------
|
|
|
|
|
|
VOID
|
|
DoPostReceiveBuffer(ULONG ulTdiHandle,
|
|
ULONG ulBufferLength)
|
|
{
|
|
NTSTATUS lStatus; // status of command
|
|
RECEIVE_BUFFER ReceiveBuffer; // return info from command
|
|
SEND_BUFFER SendBuffer; // arguments for command
|
|
|
|
//
|
|
// set up arguments
|
|
//
|
|
SendBuffer.TdiHandle = ulTdiHandle;
|
|
SendBuffer.COMMAND_ARGS.SendArgs.ulBufferLength = ulBufferLength;
|
|
|
|
PUCHAR pucBuffer = (PUCHAR)LocalAllocateMemory(ulBufferLength);
|
|
if (pucBuffer)
|
|
{
|
|
SendBuffer.COMMAND_ARGS.SendArgs.pucUserModeBuffer = pucBuffer;
|
|
|
|
//
|
|
// call the driver
|
|
//
|
|
lStatus = TdiLibDeviceIO(ulPOSTRECEIVEBUFFER,
|
|
&SendBuffer,
|
|
&ReceiveBuffer);
|
|
|
|
if (lStatus != STATUS_SUCCESS)
|
|
{
|
|
_tprintf(TEXT("DoPostReceiveBuffer: failure, status = %s\n"), TdiLibStatusMessage(lStatus));
|
|
LocalFreeMemory(pucBuffer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_putts(TEXT("DoPostReceiveBuffer: failed to allocate buffer\n"));
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------
|
|
//
|
|
// Function: DoFetchReceiveBuffer
|
|
//
|
|
// Arguments: TdiHandle -- handle of address object or endpoint
|
|
// pulBufferLength -- length of data returned
|
|
// ppDataBuffer -- allocated buffer with data
|
|
//
|
|
// Returns: status of operation
|
|
//
|
|
// Descript: This function retrieves the oldest posted buffer. If no
|
|
// data is available, it will cancel the appropriate irp
|
|
// It then returns the data to the caller as appropriate
|
|
//
|
|
// -------------------------------------------
|
|
|
|
ULONG
|
|
DoFetchReceiveBuffer(ULONG ulTdiHandle,
|
|
PUCHAR *ppDataBuffer)
|
|
{
|
|
NTSTATUS lStatus; // status of command
|
|
RECEIVE_BUFFER ReceiveBuffer; // return info from command
|
|
SEND_BUFFER SendBuffer; // arguments for command
|
|
ULONG ulBufferLength = 0;
|
|
//
|
|
// set up arguments
|
|
//
|
|
SendBuffer.TdiHandle = ulTdiHandle;
|
|
*ppDataBuffer = NULL;
|
|
|
|
//
|
|
// call the driver
|
|
//
|
|
lStatus = TdiLibDeviceIO(ulFETCHRECEIVEBUFFER,
|
|
&SendBuffer,
|
|
&ReceiveBuffer);
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
PUCHAR pucTempBuffer = ReceiveBuffer.RESULTS.RecvDgramRet.pucUserModeBuffer;
|
|
|
|
ulBufferLength = ReceiveBuffer.RESULTS.RecvDgramRet.ulBufferLength;
|
|
if (ulBufferLength)
|
|
{
|
|
*ppDataBuffer = pucTempBuffer;
|
|
}
|
|
else if (pucTempBuffer)
|
|
{
|
|
LocalFreeMemory(pucTempBuffer);
|
|
}
|
|
}
|
|
|
|
return ulBufferLength;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// end of file receive.cpp
|
|
////////////////////////////////////////////////////////////////////
|
|
|