Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

416 lines
12 KiB

/////////////////////////////////////////////////////////
//
// Copyright (c) 2001 Microsoft Corporation
//
// Module Name:
// send
//
// Abstract:
// This module contains code which deals with sending data
//
//////////////////////////////////////////////////////////
#include "sysvars.h"
//////////////////////////////////////////////////////////////
// private constants, types, and prototypes
//////////////////////////////////////////////////////////////
const PCHAR strFunc1 = "TSSendDatagram";
const PCHAR strFunc2 = "TSSend";
const PCHAR strFuncP1 = "TSSendComplete";
//
// completion context
//
struct SEND_CONTEXT
{
PIRP pUpperIrp; // irp from dll to complete
PMDL pLowerMdl; // mdl from lower irp
PTDI_CONNECTION_INFORMATION
pTdiConnectInfo;
};
typedef SEND_CONTEXT *PSEND_CONTEXT;
//
// completion function
//
TDI_STATUS
TSSendComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
//////////////////////////////////////////////////////////////
// public functions
//////////////////////////////////////////////////////////////
// -----------------------------------------------------------------
//
// Function: TSSendDatagram
//
// Arguments: pAddressObject -- address object
// pSendBuffer -- arguments from user dll
// pIrp -- completion information
//
// Returns: NTSTATUS (normally pending)
//
// Descript: This function sends a datagram
//
// ---------------------------------------------------------------------------
NTSTATUS
TSSendDatagram(PADDRESS_OBJECT pAddressObject,
PSEND_BUFFER pSendBuffer,
PIRP pUpperIrp)
{
ULONG ulDataLength = pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength;
PUCHAR pucDataBuffer = pSendBuffer->COMMAND_ARGS.SendArgs.pucUserModeBuffer;
PTRANSPORT_ADDRESS pTransportAddress
= (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.SendArgs.TransAddr;
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulSENDDATAGRAM\n"
"FileObject = %p\n"
"DataLength = %u\n",
pAddressObject,
ulDataLength);
TSPrintTaAddress(pTransportAddress->Address);
}
//
// allocate all the necessary structures
//
PSEND_CONTEXT pSendContext = NULL;
PMDL pSendMdl = NULL;
PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL;
//
// our context
//
if ((TSAllocateMemory((PVOID *)&pSendContext,
sizeof(SEND_CONTEXT),
strFunc1,
"SendContext")) != STATUS_SUCCESS)
{
goto cleanup;
}
//
// the connection information structure
//
if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo,
sizeof(TDI_CONNECTION_INFORMATION)
+ sizeof(TRANSADDR),
strFunc1,
"TdiConnectionInformation")) == STATUS_SUCCESS)
{
PUCHAR pucTemp = (PUCHAR)pTdiConnectInfo;
ULONG ulAddrLength
= FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
+ FIELD_OFFSET(TA_ADDRESS, Address)
+ pTransportAddress->Address[0].AddressLength;
pucTemp += sizeof(TDI_CONNECTION_INFORMATION);
pTdiConnectInfo->RemoteAddress = pucTemp;
pTdiConnectInfo->RemoteAddressLength = ulAddrLength;
RtlCopyMemory(pucTemp,
pTransportAddress,
ulAddrLength);
}
else
{
goto cleanup;
}
//
// create the message "packet" to send
//
pSendMdl = TSMakeMdlForUserBuffer(pucDataBuffer,
ulDataLength,
IoReadAccess);
if (pSendMdl)
{
//
// set up the completion context
//
pSendContext->pUpperIrp = pUpperIrp;
pSendContext->pLowerMdl = pSendMdl;
pSendContext->pTdiConnectInfo = pTdiConnectInfo;
//
// finally, the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pAddressObject->GenHead.pDeviceObject,
NULL);
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up the irp and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildSendDatagram(pLowerIrp,
pAddressObject->GenHead.pDeviceObject,
pAddressObject->GenHead.pFileObject,
TSSendComplete,
pSendContext,
pSendMdl,
ulDataLength,
pTdiConnectInfo);
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// make the call to the tdi provider
//
pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
NTSTATUS lStatus = IoCallDriver(pAddressObject->GenHead.pDeviceObject,
pLowerIrp);
if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
{
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
strFunc1,
lStatus);
}
return STATUS_PENDING;
}
}
//
// get here if there was an allocation failure
// need to clean up everything else...
//
cleanup:
if (pSendContext)
{
TSFreeMemory(pSendContext);
}
if (pTdiConnectInfo)
{
TSFreeMemory(pTdiConnectInfo);
}
if (pSendMdl)
{
TSFreeUserBuffer(pSendMdl);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
// -----------------------------------------------------------------
//
// Function: TSSend
//
// Arguments: pEndpointObject -- endpoint object
// pSendBuffer -- arguments from user dll
// pIrp -- completion information
//
// Returns: NTSTATUS (normally pending)
//
// Descript: This function sends data over a connection
//
// ----------------------------------------------------------------------------
NTSTATUS
TSSend(PENDPOINT_OBJECT pEndpoint,
PSEND_BUFFER pSendBuffer,
PIRP pUpperIrp)
{
ULONG ulDataLength = pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength;
PUCHAR pucDataBuffer = pSendBuffer->COMMAND_ARGS.SendArgs.pucUserModeBuffer;
ULONG ulSendFlags = pSendBuffer->COMMAND_ARGS.SendArgs.ulFlags;
//
// currently only support TDI_SEND_EXPEDITED
//
ulSendFlags &= TDI_SEND_EXPEDITED;
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint3("\nCommand = ulSEND\n"
"Endpoint = %p\n"
"DataLength = %u\n"
"SendFlags = 0x%08x\n",
pEndpoint,
ulDataLength,
ulSendFlags);
}
//
// allocate all the necessary structures
//
PSEND_CONTEXT pSendContext = NULL;
PMDL pSendMdl = NULL;
//
// our context
//
if ((TSAllocateMemory((PVOID *)&pSendContext,
sizeof(SEND_CONTEXT),
strFunc2,
"SendContext")) != STATUS_SUCCESS)
{
goto cleanup;
}
pSendMdl = TSMakeMdlForUserBuffer(pucDataBuffer,
ulDataLength,
IoReadAccess);
if (pSendMdl)
{
//
// set up the completion context
//
pSendContext->pUpperIrp = pUpperIrp;
pSendContext->pLowerMdl = pSendMdl;
//
// finally, the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
NULL);
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up the irp for the call
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildSend(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSSendComplete,
pSendContext,
pSendMdl,
ulSendFlags, // flags
ulDataLength);
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// make the call to the tdi provider
//
pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
pLowerIrp);
if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
{
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
strFunc2,
lStatus);
}
return STATUS_PENDING;
}
}
//
// get here if there was an allocation failure
// need to clean up everything else...
//
cleanup:
if (pSendContext)
{
TSFreeMemory(pSendContext);
}
if (pSendMdl)
{
TSFreeUserBuffer(pSendMdl);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/////////////////////////////////////////////////////////////
// private functions
/////////////////////////////////////////////////////////////
// ---------------------------------------------------------
//
// Function: TSSendComplete
//
// Arguments: pDeviceObject -- device object that called protocol
// 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 send, stuffs result into
// receive buffer, completes the IRP from the dll, and
// cleans up the Irp and associated data from the send
//
// ---------------------------------------------------------
#pragma warning(disable: UNREFERENCED_PARAM)
TDI_STATUS
TSSendComplete(PDEVICE_OBJECT pDeviceObject,
PIRP pLowerIrp,
PVOID pvContext)
{
PSEND_CONTEXT pSendContext = (PSEND_CONTEXT)pvContext;
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
ULONG ulBytesSent = (ULONG)pLowerIrp->IoStatus.Information;
PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pSendContext->pUpperIrp);
pReceiveBuffer->lStatus = lStatus;
if (ulDebugLevel & ulDebugShowCommand)
{
if (NT_SUCCESS(lStatus))
{
DebugPrint2("%s: BytesSent = 0x%08x\n",
strFuncP1,
ulBytesSent);
}
else
{
DebugPrint2("%s: Completed with status 0x%08x\n",
strFuncP1,
lStatus);
}
}
TSCompleteIrp(pSendContext->pUpperIrp);
//
// now cleanup
//
TSFreeUserBuffer(pSendContext->pLowerMdl);
if (pSendContext->pTdiConnectInfo)
{
TSFreeMemory(pSendContext->pTdiConnectInfo);
}
TSFreeMemory(pSendContext);
TSFreeIrp(pLowerIrp, NULL);
return TDI_MORE_PROCESSING;
}
#pragma warning(default: UNREFERENCED_PARAM)
///////////////////////////////////////////////////////////////////////////////
// end of file send.cpp
///////////////////////////////////////////////////////////////////////////////