|
|
/////////////////////////////////////////////////////////
//
// Copyright (c) 2001 Microsoft Corporation
//
// Module Name:
// requests.cpp
//
// Abstract:
// This module contains code which handles the IRP_MJ_DEVICE_CONTROL
// calls, which corresponds to DeviceIoControl calls make by the dll
//
//////////////////////////////////////////////////////////
#include "sysvars.h"
///////////////////////////////////
// private constants
///////////////////////////////////
const PCHAR strFunc1 = "TSIssueRequest";
const ULONG ulNoHandleUsed = ulINVALID_OBJECT;
ULONG ulCommandHandleUsage[ulNUM_COMMANDS] = { ulNoHandleUsed, // ulNO_COMMAND
ulNoHandleUsed, // ulVERSION_CHECK
ulNoHandleUsed, // ulABORT_COMMAND
ulNoHandleUsed, // ulDEBUGLEVEL
ulNoHandleUsed, // ulGETNUMDEVICES
ulNoHandleUsed, // ulGETDEVICE
ulNoHandleUsed, // ulGETADDRESS
ulNoHandleUsed, // ulOPENCONTROL
ulNoHandleUsed, // ulOPENADDRESS
ulNoHandleUsed, // ulOPENENDPOINT
ulControlChannelObject, // ulCLOSECONTROL
ulAddressObject, // ulCLOSEADDRESS
ulAddressObject, // ulSENDDATAGRAM
ulAddressObject, // ulRECEIVEDATAGRAM
ulEndpointObject, // ulCLOSEENDPOINT
ulEndpointObject, // ulCONNECT
ulEndpointObject, // ulDISCONNECT
ulEndpointObject, // ulISCONNECTED
ulEndpointObject, // ulSEND
ulEndpointObject, // ulRECEIVE
ulEndpointObject, // ulLISTEN
ulControlChannelObject | ulAddressObject | ulEndpointObject, // ulQUERYINFO
ulAddressObject | ulEndpointObject, // ulSETEVENTHANDLER
ulAddressObject | ulEndpointObject, // ulPOSTRECEIVEBUFFER
ulAddressObject | ulEndpointObject // ulFETCHRECEIVEBUFFER
};
//------------------------------------------------------
//
// Function: TSIssueRequest
//
// Arguments: DeviceContext -- DeviceContext for ndistest.sys.
// Irp -- ptr to current irp structure
// IrpSp -- ptr to current irp stack
//
// Returns: final status of whatever operation performed-- STATUS_SUCCESS,
// STATUS_PENDING, or error status (usually STATUS_UNSUCCESSFUL)
//
// Descript: This function calls the appropriate function(s) to deal with
// an IRP_DEVICE_CONTROL request. Basically all commands from
// the dll come thru here.
//
// --------------------------------------------------------
NTSTATUS TSIssueRequest(PDEVICE_CONTEXT pDeviceContext, PIRP pIrp, PIO_STACK_LOCATION pIrpSp)
{ NTSTATUS lStatus; PGENERIC_HEADER pGenericHeader; // node used as main argument
ULONG ulCmdCode // IOCTL command to execute
= ulTdiIoctlToCommand(pIrpSp->Parameters.DeviceIoControl.IoControlCode); PSEND_BUFFER pSendBuffer // arguments for command (inputbuffer)
= TSGetSendBuffer(pIrp); PRECEIVE_BUFFER pReceiveBuffer // data to return to dll (outputbuffer)
= TSGetReceiveBuffer(pIrp); PIRP pLastCommandIrp = pDeviceContext->pLastCommandIrp;
//
// check for an illegal command number
//
if (ulCmdCode >= ulNUM_COMMANDS) { DebugPrint2("\n%s: Illegal command code: 0x%08x\n", strFunc1, ulCmdCode); ulCmdCode = ulNO_COMMAND; }
//
// check for commands that don't require a handle
//
if (ulCommandHandleUsage[ulCmdCode] == ulNoHandleUsed) { pGenericHeader = NULL; }
//
// for commands that require a handle, make sure that they
// have the correct type!
//
else { pGenericHeader = TSGetObjectFromHandle(pSendBuffer->TdiHandle, ulCommandHandleUsage[ulCmdCode]);
if (pGenericHeader) { TSAcquireSpinLock(&pObjectList->TdiSpinLock); if (pGenericHeader->fInCommand) { DebugPrint1("\n%s: ERROR -- command already in progress!\n", strFunc1); ulCmdCode = ulNO_COMMAND; pGenericHeader = NULL; } else { pGenericHeader->fInCommand = TRUE; } TSReleaseSpinLock(&pObjectList->TdiSpinLock); } else { DebugPrint1("\n%s: handle type invalid for command!\n", strFunc1); ulCmdCode = ulNO_COMMAND; } }
//
// if a real command, store as last command
//
if ((ulCmdCode != ulNO_COMMAND) && (ulCmdCode != ulABORT_COMMAND)) { pDeviceContext->pLastCommandIrp = pIrp; pSendBuffer->pvLowerIrp = NULL; pSendBuffer->pvDeviceContext = pDeviceContext; }
//
// now deal with the specific command..
//
switch (ulCmdCode) { //-----------------------------------------------------------
// commands that do not require any handle
//-----------------------------------------------------------
//
// ulNO_COMMAND -- does this if missing required handle type
// (don't want to hit real command OR default..)
//
case ulNO_COMMAND: lStatus = STATUS_INVALID_PARAMETER; break;
//
// ulVERSION_CHECK -- return current version id
//
case ulVERSION_CHECK: //
// Get the Input and buffers for the Incoming command.
// Make sure both lengths are ok..
//
if ((pIrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SEND_BUFFER)) || (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(RECEIVE_BUFFER))) { DebugPrint1("\n%s: IRP buffer size mismatch!\n" "DLL and driver are mismatched!\n", strFunc1); lStatus = STATUS_UNSUCCESSFUL; } else { pReceiveBuffer->RESULTS.ulReturnValue = TDI_SAMPLE_VERSION_ID; lStatus = STATUS_SUCCESS; } break;
//
// ulABORT_COMMAND -- abort the previous command, if possible
//
case ulABORT_COMMAND: lStatus = STATUS_SUCCESS; if (pLastCommandIrp) { PSEND_BUFFER pLastSendBuffer = TSGetSendBuffer(pLastCommandIrp); if (pLastSendBuffer) { if (pLastSendBuffer->pvLowerIrp) { DebugPrint0("\nCommand = ulABORT_COMMAND\n"); IoCancelIrp((PIRP)pLastSendBuffer->pvLowerIrp); break; } } } DebugPrint0("\nCommand = ulABORT_COMMAND w/no command\n"); break;
//
// ulDEBUGLEVEL -- set the current debuglevel
//
case ulDEBUGLEVEL: ulDebugLevel = pSendBuffer->COMMAND_ARGS.ulDebugLevel; DebugPrint1("\nSetting debug level to 0x%x\n", ulDebugLevel); lStatus = STATUS_SUCCESS; break;
//
// ulGETNUMDEVICES -- get number of openable devices
//
case ulGETNUMDEVICES: TSGetNumDevices(pSendBuffer, pReceiveBuffer); lStatus = STATUS_SUCCESS; break;
//
// ulGETDEVICE -- get the name to open for a specific device
//
case ulGETDEVICE: lStatus = TSGetDevice(pSendBuffer, pReceiveBuffer); break;
//
// ulGETADDRESS -- get the address to open for a specific device
//
case ulGETADDRESS: lStatus = TSGetAddress(pSendBuffer, pReceiveBuffer); break;
//
// ulOPENCONTROL -- open a control channel
//
case ulOPENCONTROL: lStatus = TSOpenControl(pSendBuffer, pReceiveBuffer); break;
//
// ulOPENADDRESS -- open an address object
//
case ulOPENADDRESS: lStatus = TSOpenAddress(pSendBuffer, pReceiveBuffer); break;
//
// ulOPENENDPOINT -- open an endpoint object
//
case ulOPENENDPOINT: lStatus = TSOpenEndpoint(pSendBuffer, pReceiveBuffer); break; //-----------------------------------------------------------
// commands that require a control channel handle
//-----------------------------------------------------------
//
// ulCLOSECONTROL -- close a control channel
//
case ulCLOSECONTROL: TSRemoveNode(pSendBuffer->TdiHandle); TSCloseControl((PCONTROL_CHANNEL)pGenericHeader); pGenericHeader = NULL; lStatus = STATUS_SUCCESS; break;
//-----------------------------------------------------------
// commands that require an address handle
//-----------------------------------------------------------
//
// ulCLOSEADDRESS -- close an address object
//
case ulCLOSEADDRESS: TSRemoveNode(pSendBuffer->TdiHandle); TSCloseAddress((PADDRESS_OBJECT)pGenericHeader); pGenericHeader = NULL; lStatus = STATUS_SUCCESS; break;
//
// ulSENDDATAGRAM -- send a datagram
//
case ulSENDDATAGRAM: lStatus = TSSendDatagram((PADDRESS_OBJECT)pGenericHeader, pSendBuffer, pIrp); break;
//
// ulRECEIVEDATAGRAM -- receive a datagram
//
case ulRECEIVEDATAGRAM: lStatus = TSReceiveDatagram((PADDRESS_OBJECT)pGenericHeader, pSendBuffer, pReceiveBuffer); break;
//-----------------------------------------------------------
// commands that require an endpoint
//-----------------------------------------------------------
//
// ulCLOSEENDPOINT -- close an endpoint object
//
case ulCLOSEENDPOINT: TSRemoveNode(pSendBuffer->TdiHandle); TSCloseEndpoint((PENDPOINT_OBJECT)pGenericHeader); pGenericHeader = NULL; lStatus = STATUS_SUCCESS; break;
//
// ulCONNECT -- establish connection between local endpoint and remote endpoint
//
case ulCONNECT: lStatus = TSConnect((PENDPOINT_OBJECT)pGenericHeader, pSendBuffer, pIrp); break;
//
// ulDISCONNECT -- removed connection between local and remote endpoints
//
case ulDISCONNECT: lStatus = TSDisconnect((PENDPOINT_OBJECT)pGenericHeader, pSendBuffer, pIrp); break;
//
// ulISCONNECTED -- check to see if endpoint is connected
//
case ulISCONNECTED: lStatus = TSIsConnected((PENDPOINT_OBJECT)pGenericHeader, pReceiveBuffer); break;
//
// ulSEND -- send data over the connection
//
case ulSEND: lStatus = TSSend((PENDPOINT_OBJECT)pGenericHeader, pSendBuffer, pIrp); break;
//
// ulRECEIVE -- receive a packet over the connection
//
case ulRECEIVE: lStatus = TSReceive((PENDPOINT_OBJECT)pGenericHeader, pSendBuffer, pReceiveBuffer); break;
//
// ulLISTEN -- wait for an incoming call
//
case ulLISTEN: lStatus = TSListen((PENDPOINT_OBJECT)pGenericHeader); break;
//-----------------------------------------------------------
// commands that require a handle, but type may vary
//-----------------------------------------------------------
//
// ulQUERYINFO -- query object for information
//
case ulQUERYINFO: lStatus = TSQueryInfo(pGenericHeader, pSendBuffer, pIrp); break;
//
// ulSETEVENTHANDLER -- enable or disable an event handler
//
case ulSETEVENTHANDLER: lStatus = TSSetEventHandler(pGenericHeader, pSendBuffer, pIrp); break;
//
// ulPOSTRECEIVEBUFFER -- post buffer for receive/recvdgram
//
case ulPOSTRECEIVEBUFFER: lStatus = TSPostReceiveBuffer(pGenericHeader, pSendBuffer); break;
//
// ulFETCHRECEIVEBUFFER -- retrieve a previously posted receive buffer
//
case ulFETCHRECEIVEBUFFER: lStatus = TSFetchReceiveBuffer(pGenericHeader, pReceiveBuffer); break;
// --------------------------------------------
// not a recognized command...
//---------------------------------------------
default: DebugPrint1("\n%s: Invalid Command Received\n", strFunc1); lStatus = STATUS_INVALID_PARAMETER; break; }
if (lStatus != STATUS_PENDING) { pReceiveBuffer->lStatus = lStatus; lStatus = STATUS_SUCCESS; // return SUCCESS or PENDING for DeviceIoControl
}
//
// clear flag to allow another command in on this handle
//
if (pGenericHeader) { TSAcquireSpinLock(&pObjectList->TdiSpinLock); pGenericHeader->fInCommand = FALSE; TSReleaseSpinLock(&pObjectList->TdiSpinLock); }
return lStatus; }
////////////////////////////////////////////////////////////////////////
// end of file requests.cpp
////////////////////////////////////////////////////////////////////////
|