windows-nt/Source/XPSP1/NT/net/tdi/sample/sys/connect.cpp
2020-09-26 16:20:57 +08:00

1045 lines
30 KiB
C++

/////////////////////////////////////////////////////////
//
// Copyright (c) 2001 Microsoft Corporation
//
// Module Name:
// connect.cpp
//
// Abstract:
// This module contains code which deals with making and breaking
// connections
//
//////////////////////////////////////////////////////////
#include "sysvars.h"
//////////////////////////////////////////////////////////////
// private constants, types, and prototypes
//////////////////////////////////////////////////////////////
const PCHAR strFunc1 = "TSConnect";
const PCHAR strFunc2 = "TSDisconnect";
// const PCHAR strFunc3 = "TSIsConnected";
const PCHAR strFunc4 = "TSConnectHandler";
const PCHAR strFunc5 = "TSDisconnectHandler";
const PCHAR strFunc6 = "TSListen";
// const PCHAR strFuncP1 = "TSGenAcceptComplete";
const PCHAR strFuncP2 = "TSGenConnectComplete";
//
// this context structure stores information needed to complete
// the request in the completion handler
//
struct CONNECT_CONTEXT
{
PIRP pUpperIrp; // irp from dll to complete
ULONG ulWhichCommand; // command that is being completed
ULONG ulListenFlag; // 0 or TDI_QUERY_ACCEPT
PENDPOINT_OBJECT pEndpoint; // connection endpoint
PIRP_POOL pIrpPool;
PTDI_CONNECTION_INFORMATION
pTdiConnectInfo;
};
typedef CONNECT_CONTEXT *PCONNECT_CONTEXT;
//
// completion functions
//
TDI_STATUS
TSGenConnectComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
TDI_STATUS
TSGenAcceptComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
/////////////////////////////////////////////////////////////
// public functions
//////////////////////////////////////////////////////////////
// -----------------------------------------------------------------
//
// Function: TSConnect
//
// Arguments: pEndpoint -- connection endpoint structure
// pSendBuffer -- arguments from user dll
// pIrp -- completion information
//
// Returns: NTSTATUS (normally pending)
//
// Descript: This function attempts to connect the local endpoint object
// with a remote endpoint
//
// -----------------------------------------------------------------
NTSTATUS
TSConnect(PENDPOINT_OBJECT pEndpoint,
PSEND_BUFFER pSendBuffer,
PIRP pUpperIrp)
{
PTRANSPORT_ADDRESS pTransportAddress
= (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.ConnectArgs.TransAddr;
ULONG ulTimeout
= pSendBuffer->COMMAND_ARGS.ConnectArgs.ulTimeout;
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulCONNECT\n"
"FileObject = %p\n"
"Timeout = %u\n",
pEndpoint,
ulTimeout);
TSPrintTaAddress(pTransportAddress->Address);
}
//
// make sure all is kosher
//
if (pEndpoint->fIsConnected)
{
DebugPrint1("%s: endpoint already connected\n", strFunc1);
return STATUS_UNSUCCESSFUL;
}
if (!pEndpoint->pAddressObject)
{
DebugPrint1("%s: endpoint not associated with transport address\n",
strFunc1);
return STATUS_UNSUCCESSFUL;
}
//
// allocate all the necessary structures
//
PCONNECT_CONTEXT pConnectContext;
PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL;
//
// our context
//
if ((TSAllocateMemory((PVOID *)&pConnectContext,
sizeof(CONNECT_CONTEXT),
strFunc1,
"ConnectContext")) != STATUS_SUCCESS)
{
goto cleanup;
}
//
// the connection information structure
//
if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo,
sizeof(TDI_CONNECTION_INFORMATION)
+ sizeof(TRANSADDR),
strFunc1,
"TdiConnectionInformation")) == STATUS_SUCCESS)
//
// set up the TdiConnectionInformation
//
{
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;
}
//
// set up the completion context
//
pConnectContext->pUpperIrp = pUpperIrp;
pConnectContext->pTdiConnectInfo = pTdiConnectInfo;
pConnectContext->pEndpoint = pEndpoint;
pConnectContext->ulWhichCommand = TDI_CONNECT;
//
// finally, the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
NULL);
if (pLowerIrp)
{
LONGLONG llTimeout;
PLONGLONG pllTimeout = NULL;
if (ulTimeout)
{
llTimeout = Int32x32To64(ulTimeout, -10000);
pllTimeout = &llTimeout;
}
//
// if made it to here, everything is correctly allocated
// set up irp and and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildConnect(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSGenConnectComplete,
pConnectContext,
pllTimeout,
pTdiConnectInfo,
NULL); // ReturnConnectionInfo
#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",
strFunc1,
lStatus);
}
return STATUS_PENDING;
}
//
// get here if there was an allocation failure
// need to clean up everything else...
//
cleanup:
if (pConnectContext)
{
TSFreeMemory(pConnectContext);
}
if (pTdiConnectInfo)
{
TSFreeMemory(pTdiConnectInfo);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
// -----------------------------------------------------------------
//
// Function: TSDisconnect
//
// Arguments: pEndpoint -- connection endpoint structure
// pIrp -- completion information
//
// Returns: NTSTATUS (normally pending)
//
// Descript: This function attempts to disconnect a local endpoint from
// a remote endpoint
//
// -----------------------------------------------------------------
NTSTATUS
TSDisconnect(PENDPOINT_OBJECT pEndpoint,
PSEND_BUFFER pSendBuffer,
PIRP pUpperIrp)
{
ULONG ulFlags = pSendBuffer->COMMAND_ARGS.ulFlags;
if (ulFlags != TDI_DISCONNECT_RELEASE)
{
ulFlags = TDI_DISCONNECT_ABORT;
}
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulDISCONNECT\n"
"EndpointObject = %p\n"
"Flags = 0x%x\n",
pEndpoint,
ulFlags);
}
//
// make sure all is kosher
//
if (!pEndpoint->fIsConnected)
{
DebugPrint1("%s: endpoint not currently connected\n", strFunc2);
return STATUS_SUCCESS;
}
//
// allocate all the necessary structures
//
PCONNECT_CONTEXT pConnectContext;
//
// first, our context
//
if ((TSAllocateMemory((PVOID *)&pConnectContext,
sizeof(CONNECT_CONTEXT),
strFunc2,
"ConnectContext")) == STATUS_SUCCESS)
{
pConnectContext->pUpperIrp = pUpperIrp;
pConnectContext->ulWhichCommand = TDI_DISCONNECT;
pConnectContext->pEndpoint = pEndpoint;
//
// then the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
NULL);
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up everything and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildDisconnect(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSGenConnectComplete,
pConnectContext,
NULL, // pLargeInteger Time
ulFlags, // TDI_DISCONNECT _ABORT or _RELEASE
NULL, // RequestConnectionInfo
NULL); // ReturnConnectionInfo
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// make the call to the tdi provider
//
pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
pEndpoint->fStartedDisconnect = TRUE;
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;
}
TSFreeMemory(pConnectContext);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
// --------------------------------------------------
//
// Function: TSListen
//
// Arguments: pEndpoint -- connection endpoint structure
//
// Returns: status of operation (usually success)
//
// Descript: Wait for an incoming call request
//
// --------------------------------------------------
NTSTATUS
TSListen(PENDPOINT_OBJECT pEndpoint)
{
ULONG ulListenFlag = 0;
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint1("\nCommand = ulLISTEN\n"
"FileObject = %p\n",
pEndpoint);
}
//
// make sure all is kosher
//
if (pEndpoint->fIsConnected)
{
DebugPrint1("%s: endpoint already connected\n", strFunc6);
return STATUS_UNSUCCESSFUL;
}
if (!pEndpoint->pAddressObject)
{
DebugPrint1("%s: endpoint not associated with transport address\n",
strFunc6);
return STATUS_UNSUCCESSFUL;
}
//
// allocate all the necessary structures
//
PCONNECT_CONTEXT pConnectContext;
PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL;
//
// our context
//
if ((TSAllocateMemory((PVOID *)&pConnectContext,
sizeof(CONNECT_CONTEXT),
strFunc6,
"ConnectContext")) != STATUS_SUCCESS)
{
goto cleanup;
}
//
// the connection information structure
//
if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo,
sizeof(TDI_CONNECTION_INFORMATION),
strFunc6,
"TdiConnectionInformation")) == STATUS_SUCCESS)
//
// set up the TdiConnectionInformation
//
{
pTdiConnectInfo->UserData = NULL;
pTdiConnectInfo->UserDataLength = 0;
pTdiConnectInfo->RemoteAddress = NULL;
pTdiConnectInfo->RemoteAddressLength = 0;
pTdiConnectInfo->Options = &pConnectContext->ulListenFlag;
pTdiConnectInfo->OptionsLength = sizeof(ULONG);
//
// set up the completion context
// note that the upper irp is NOT passed!
//
pConnectContext->pUpperIrp = NULL;
pConnectContext->pTdiConnectInfo = pTdiConnectInfo;
pConnectContext->pEndpoint = pEndpoint;
pConnectContext->ulWhichCommand = TDI_LISTEN;
pConnectContext->ulListenFlag = ulListenFlag;
if (!pEndpoint->pAddressObject->pIrpPool)
{
pEndpoint->pAddressObject->pIrpPool
= TSAllocateIrpPool(pEndpoint->pAddressObject->GenHead.pDeviceObject,
ulIrpPoolSize);
pConnectContext->pIrpPool = pEndpoint->pAddressObject->pIrpPool;
}
//
// finally, the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
pEndpoint->pAddressObject->pIrpPool);
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up irp and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildListen(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSGenAcceptComplete,
pConnectContext,
ulListenFlag,
pTdiConnectInfo,
NULL); // ReturnConnectionInfo
#pragma warning(default: CONSTANT_CONDITIONAL)
NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
pLowerIrp);
if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
{
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
strFunc6,
lStatus);
}
return STATUS_SUCCESS;
}
}
//
// get here if there was an allocation failure
// need to clean up everything else...
//
cleanup:
if (pConnectContext)
{
TSFreeMemory(pConnectContext);
}
if (pTdiConnectInfo)
{
TSFreeMemory(pTdiConnectInfo);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
// --------------------------------------------------
//
// Function: TSIsConnected
//
// Arguments: pEndpoint -- connection endpoint structure
// pReceiveBuffer -- put results in here
//
// Returns: STATUS_SUCCESS
//
// Descript: Checks to see if endpoint is currently connected
//
// --------------------------------------------------
NTSTATUS
TSIsConnected(PENDPOINT_OBJECT pEndpoint,
PRECEIVE_BUFFER pReceiveBuffer)
{
pReceiveBuffer->RESULTS.ulReturnValue = pEndpoint->fIsConnected;
return STATUS_SUCCESS;
}
// --------------------------------------------------
//
// Function: TSConnectHandler
//
// Arguments: pvTdiEventContext -- here, ptr to address object
// lRemoteAddressLength -- # bytes in remote address
// pvRemoteAddress -- pTransportAddress of remote
// lUserDataLength -- length of data at pvUserData
// pvUserData -- connect data from remote
// lOptionsLength -- length of data in pvOptions
// pvOptions -- transport-specific connect options
// pConnectionContext -- return ptr to connection context
// ppAcceptIrp -- return ptr to TdiBuildAccept irp
//
// Returns: STATUS_CONNECTION_REFUSED if are rejecting connection
// STATUS_MORE_PROCESSING_REQUIRED is accepting and have supplied
// a ppAcceptIrp
//
// Descript: listens for an offerred connection, then
// accepts it or rejects it
//
// --------------------------------------------------
TDI_STATUS
TSConnectHandler(PVOID pvTdiEventContext,
LONG lRemoteAddressLength,
PVOID pvRemoteAddress,
LONG lUserDataLength,
PVOID pvUserData,
LONG lOptionsLength,
PVOID pvOptions,
CONNECTION_CONTEXT *pConnectionContext,
PIRP *ppAcceptIrp)
{
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
PENDPOINT_OBJECT pEndpoint = pAddressObject->pEndpoint;
//
// show the information passed in.
// Note that we actually use very little of it..
//
if (ulDebugLevel & ulDebugShowHandlers)
{
DebugPrint1("\n >>>> %s\n", strFunc4);
DebugPrint2("pAddressObject = %p\n"
"RemoteAddressLength = %d\n",
pAddressObject,
lRemoteAddressLength);
if (lRemoteAddressLength)
{
PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)pvRemoteAddress;
DebugPrint0("RemoteAddress: ");
TSPrintTaAddress(&pTransportAddress->Address[0]);
}
DebugPrint1("UserDataLength = %d\n", lUserDataLength);
if (lUserDataLength)
{
PUCHAR pucTemp = (PUCHAR)pvUserData;
DebugPrint0("UserData: ");
for (LONG lCount = 0; lCount < lUserDataLength; lCount++)
{
DebugPrint1("%02x ", *pucTemp);
++pucTemp;
}
DebugPrint0("\n");
}
DebugPrint1("OptionsLength = %d\n", lOptionsLength);
if (lOptionsLength)
{
PUCHAR pucTemp = (PUCHAR)pvOptions;
DebugPrint0("Options: ");
for (LONG lCount = 0; lCount < (LONG)lOptionsLength; lCount++)
{
DebugPrint1("%02x ", *pucTemp);
++pucTemp;
}
DebugPrint0("\n");
}
}
//
// now do the work
//
if (pEndpoint->fIsConnected || pEndpoint->fAcceptInProgress)
{
return TDI_CONN_REFUSED;
}
pEndpoint->fAcceptInProgress = TRUE;
//
// allocate all the necessary structures
//
PCONNECT_CONTEXT pConnectContext;
//
// first, our context
//
if ((TSAllocateMemory((PVOID *)&pConnectContext,
sizeof(CONNECT_CONTEXT),
strFunc4,
"ConnectContext")) == STATUS_SUCCESS)
{
pConnectContext->pUpperIrp = NULL;
pConnectContext->ulWhichCommand = TDI_ACCEPT;
pConnectContext->pEndpoint = pEndpoint;
//
// then the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
pAddressObject->pIrpPool);
pConnectContext->pIrpPool = pAddressObject->pIrpPool;
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up irp and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildAccept(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSGenAcceptComplete,
pConnectContext,
NULL, // RequestConnectionInfo
NULL); // ReturnConnectionInfo
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// need to do this since we are not calling IoCallDriver
//
IoSetNextIrpStackLocation(pLowerIrp);
*pConnectionContext = pEndpoint;
*ppAcceptIrp = pLowerIrp;
return TDI_MORE_PROCESSING;
}
TSFreeMemory(pConnectContext);
}
pEndpoint->fAcceptInProgress = FALSE;
return TDI_CONN_REFUSED;
}
// --------------------------------------------------
//
// Function: TdiDisconnectHandler
//
// Arguments: pvTdiEventContext -- here, our address object
// ConnectionContext -- here, our connection object
// lDisconnectDataLength -- length of data in pvDisconnectData
// pvDisconnectData -- data sent by remote as part of disconnect
// lDisconnectInformationLength -- length of pvDisconnectInformation
// pvDisconnectInformation -- transport-specific sidconnect info
// ulDisconnectFlags -- nature of disconnect
//
// Returns: STATUS_SUCCESS
//
// Descript: deals with an incoming disconnect. Note that the disconnect
// is really complete at this point, as far as the protocol
// is concerned. We just need to clean up our stuff
//
// --------------------------------------------------
TDI_STATUS
TSDisconnectHandler(PVOID pvTdiEventContext,
CONNECTION_CONTEXT ConnectionContext,
LONG lDisconnectDataLength,
PVOID pvDisconnectData,
LONG lDisconnectInformationLength,
PVOID pvDisconnectInformation,
ULONG ulDisconnectFlags)
{
PENDPOINT_OBJECT pEndpoint = (PENDPOINT_OBJECT)ConnectionContext;
//
// show info in arguments
//
if (ulDebugLevel & ulDebugShowHandlers)
{
DebugPrint1("\n >>>> %s\n", strFunc5);
DebugPrint3("pAddressObject = %p\n"
"pEndpoint = %p\n"
"DisconnectDataLength = %d\n",
pvTdiEventContext,
pEndpoint,
lDisconnectDataLength);
if (lDisconnectDataLength)
{
PUCHAR pucTemp = (PUCHAR)pvDisconnectData;
DebugPrint0("DisconnectData: ");
for (LONG lCount = 0; lCount < (LONG)lDisconnectDataLength; lCount++)
{
DebugPrint1("%02x ", *pucTemp);
++pucTemp;
}
DebugPrint0("\n");
}
DebugPrint1("DisconnectInformationLength = %d\n",
lDisconnectInformationLength);
if (lDisconnectInformationLength)
{
PUCHAR pucTemp = (PUCHAR)pvDisconnectInformation;
DebugPrint0("DisconnectInformation: ");
for (LONG lCount = 0; lCount < (LONG)lDisconnectInformationLength; lCount++)
{
DebugPrint1("%02x ", *pucTemp);
++pucTemp;
}
DebugPrint0("\n");
}
DebugPrint1("DisconnectFlags = 0x%08x\n", ulDisconnectFlags);
if (ulDisconnectFlags & TDI_DISCONNECT_ABORT)
{
DebugPrint0(" TDI_DISCONNECT_ABORT\n");
}
if (ulDisconnectFlags & TDI_DISCONNECT_RELEASE)
{
DebugPrint0(" TDI_DISCONNECT_RELEASE\n");
}
}
//
// do our cleanup..
//
pEndpoint->fIsConnected = FALSE;
if ((ulDisconnectFlags & TDI_DISCONNECT_RELEASE) &&
(!pEndpoint->fStartedDisconnect))
{
//
// allocate all the necessary structures
//
PCONNECT_CONTEXT pConnectContext;
//
// first, our context
//
if ((TSAllocateMemory((PVOID *)&pConnectContext,
sizeof(CONNECT_CONTEXT),
strFunc5,
"ConnectContext")) == STATUS_SUCCESS)
{
pConnectContext->pUpperIrp = NULL;
pConnectContext->ulWhichCommand = TDI_DISCONNECT;
pConnectContext->pEndpoint = pEndpoint;
//
// then the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
pEndpoint->pAddressObject->pIrpPool);
pConnectContext->pIrpPool = pEndpoint->pAddressObject->pIrpPool;
if (pLowerIrp)
{
//
// if made it to here, everything is correctly allocated
// set up irp and call the tdi provider
//
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildDisconnect(pLowerIrp,
pEndpoint->GenHead.pDeviceObject,
pEndpoint->GenHead.pFileObject,
TSGenAcceptComplete,
pConnectContext,
NULL, // pLargeInteger Time
TDI_DISCONNECT_RELEASE,
NULL, // RequestConnectionInfo
NULL); // ReturnConnectionInfo
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// make the call to the tdi provider
//
NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
pLowerIrp);
if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
{
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
strFunc5,
lStatus);
}
}
else
{
TSFreeMemory(pConnectContext);
}
}
}
//
// get here if do NOT need to send TDI_DISCONNECT_RELEASE message back
// to other end of connection
//
else
{
pEndpoint->fAcceptInProgress = FALSE;
pEndpoint->fIsConnected = FALSE;
}
return TDI_SUCCESS;
}
/////////////////////////////////////////////////////////////
// private functions
/////////////////////////////////////////////////////////////
// ---------------------------------------------------------
//
// Function: TSGenAcceptComplete
//
// Arguments: pDeviceObject -- device object on which call was made
// 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 command, stuffs results into
// receive buffer, cleans up the Irp and associated data
// structures, etc
// This is used to complete cases where this no IRP from the
// dll to complete (ie, connect handler, listen, listen-accept,
// listen-disconnect)
//
// ---------------------------------------------------------
#pragma warning(disable: UNREFERENCED_PARAM)
TDI_STATUS
TSGenAcceptComplete(PDEVICE_OBJECT pDeviceObject,
PIRP pLowerIrp,
PVOID pvContext)
{
PCONNECT_CONTEXT pConnectContext = (PCONNECT_CONTEXT)pvContext;
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
//
// dealing with completions where there is no DLL irp associated
//
switch (pConnectContext->ulWhichCommand)
{
case TDI_ACCEPT:
if (NT_SUCCESS(lStatus))
{
pConnectContext->pEndpoint->fIsConnected = TRUE;
}
pConnectContext->pEndpoint->fAcceptInProgress = FALSE;
break;
case TDI_LISTEN:
if (NT_SUCCESS(lStatus))
{
pConnectContext->pEndpoint->fIsConnected = TRUE;
}
else
{
DebugPrint1("Failure in TSListen: status = 0x%08x\n", lStatus);
}
break;
case TDI_DISCONNECT:
pConnectContext->pEndpoint->fAcceptInProgress = FALSE;
pConnectContext->pEndpoint->fIsConnected = FALSE;
pConnectContext->pEndpoint->fStartedDisconnect = FALSE;
break;
}
TSFreeIrp(pLowerIrp, pConnectContext->pIrpPool);
//
// generic cleanup
//
if (pConnectContext->pTdiConnectInfo)
{
TSFreeMemory(pConnectContext->pTdiConnectInfo);
}
TSFreeMemory(pConnectContext);
return TDI_MORE_PROCESSING;
}
#pragma warning(default: UNREFERENCED_PARAM)
// ---------------------------------------------------------
//
// Function: TSGenConnectComplete
//
// Arguments: pDeviceObject -- device object on which call was made
// 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 command, stuffs results into
// receive buffer, completes the IRP from the dll,
// cleans up the Irp and associated data structures, etc
// Deals only with commands that carry an IRP from the dll
//
// ---------------------------------------------------------
#pragma warning(disable: UNREFERENCED_PARAM)
TDI_STATUS
TSGenConnectComplete(PDEVICE_OBJECT pDeviceObject,
PIRP pLowerIrp,
PVOID pvContext)
{
PCONNECT_CONTEXT pConnectContext = (PCONNECT_CONTEXT)pvContext;
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
//
// this is completing a command from the dll
//
PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pConnectContext->pUpperIrp);
pReceiveBuffer->lStatus = lStatus;
if (NT_SUCCESS(lStatus))
{
if (ulDebugLevel & ulDebugShowCommand)
{
if (pLowerIrp->IoStatus.Information)
{
DebugPrint2("%s: Information = 0x%08x\n",
strFuncP2,
pLowerIrp->IoStatus.Information);
}
}
switch (pConnectContext->ulWhichCommand)
{
case TDI_CONNECT:
pConnectContext->pEndpoint->fIsConnected = TRUE;
break;
case TDI_DISCONNECT:
pConnectContext->pEndpoint->fIsConnected = FALSE;
break;
default:
DebugPrint2("%s: invalid command value [0x%08x]\n",
strFuncP2,
pConnectContext->ulWhichCommand);
DbgBreakPoint();
break;
}
}
else
{
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("%s: Completed with status 0x%08x\n",
strFuncP2,
lStatus);
}
}
TSCompleteIrp(pConnectContext->pUpperIrp);
TSFreeIrp(pLowerIrp, NULL);
//
// generic cleanup
//
if (pConnectContext->pTdiConnectInfo)
{
TSFreeMemory(pConnectContext->pTdiConnectInfo);
}
TSFreeMemory(pConnectContext);
return TDI_MORE_PROCESSING;
}
#pragma warning(default: UNREFERENCED_PARAM)
///////////////////////////////////////////////////////////////////////////////
// end of file connect.cpp
///////////////////////////////////////////////////////////////////////////////