1045 lines
30 KiB
C++
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
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|