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