1150 lines
34 KiB
C++
1150 lines
34 KiB
C++
/////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// open.cpp
|
|
//
|
|
// Abstract:
|
|
// This module contains code which deals with opening and closing
|
|
// of the various types of tdi objects
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "sysvars.h"
|
|
extern "C"
|
|
{
|
|
#pragma warning(disable: NAMELESS_STRUCT_UNION)
|
|
#include "tdiinfo.h"
|
|
#pragma warning(default: NAMELESS_STRUCT_UNION)
|
|
}
|
|
|
|
|
|
//
|
|
// defines stolen from include files not in ddk
|
|
//
|
|
#define AO_OPTION_IP_UCASTIF 17
|
|
#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
|
|
|
|
#define _TCP_CTL_CODE(function, method, access) \
|
|
CTL_CODE(FSCTL_TCP_BASE, function, method, access)
|
|
#define IOCTL_TCP_WSH_SET_INFORMATION_EX \
|
|
_TCP_CTL_CODE(10, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
|
|
//
|
|
// end of stolen defines
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// private constants and prototypes
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
const PCHAR strFunc1 = "TSOpenControl";
|
|
const PCHAR strFunc2 = "TSCloseControl";
|
|
const PCHAR strFunc3 = "TSOpenAddress";
|
|
const PCHAR strFunc4 = "TSCloseAddress";
|
|
const PCHAR strFunc5 = "TSOpenEndpoint";
|
|
const PCHAR strFunc6 = "TSCloseEndpoint";
|
|
|
|
//const PCHAR strFuncP1 = "TSCompleteCommand";
|
|
const PCHAR strFuncP2 = "TSPerformOpenControl";
|
|
const PCHAR strFuncP3 = "TSPerformOpenAddress";
|
|
const PCHAR strFuncP4 = "TSPerformOpenEndpoint";
|
|
const PCHAR strFuncP5 = "TSPerformAssociate";
|
|
const PCHAR strFuncP6 = "TSPerformDisassociate";
|
|
|
|
|
|
TDI_STATUS
|
|
TSCompleteCommand(
|
|
PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pLowerIrp,
|
|
PVOID pvContext
|
|
);
|
|
|
|
NTSTATUS
|
|
TSPerformOpenControl(
|
|
PCONTROL_CHANNEL pControlChannel,
|
|
PUCNTSTRING pucString
|
|
);
|
|
|
|
NTSTATUS
|
|
TSPerformOpenAddress(
|
|
PADDRESS_OBJECT pAddressObject,
|
|
PUCNTSTRING pucString,
|
|
PTRANSPORT_ADDRESS pTransportAddress,
|
|
BOOLEAN fIsConnect
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
TSPerformOpenEndpoint(
|
|
PENDPOINT_OBJECT pEndpointObject,
|
|
PUCNTSTRING pucString
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
TSPerformAssociate(
|
|
PENDPOINT_OBJECT pEndpoint
|
|
);
|
|
|
|
VOID
|
|
TSPerformDisassociate(
|
|
PENDPOINT_OBJECT pEndpoint
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// public functions
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// Function: TSOpenControl
|
|
//
|
|
// Arguments: pSendBuffer -- arguments from user dll for open command
|
|
// pIrp -- completion information
|
|
//
|
|
// Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
|
|
//
|
|
// Descript: This function sets up the structure for a new control channel,
|
|
// and attempts to open the specified control channel
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSOpenControl(PSEND_BUFFER pSendBuffer,
|
|
PRECEIVE_BUFFER pReceiveBuffer)
|
|
{
|
|
PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
|
|
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulOPENCONTROL\n"
|
|
"DeviceName = %ws\n",
|
|
pucString->wcBuffer);
|
|
}
|
|
|
|
//
|
|
// allocate our structure and put it in the linked list...
|
|
//
|
|
PCONTROL_CHANNEL pControlChannel;
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pControlChannel,
|
|
sizeof(CONTROL_CHANNEL),
|
|
strFunc1,
|
|
"ControlChannel");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pControlChannel->GenHead.ulSignature = ulControlChannelObject;
|
|
|
|
ULONG ulTdiHandle = TSInsertNode(&pControlChannel->GenHead);
|
|
|
|
if (ulTdiHandle)
|
|
{
|
|
lStatus = TSPerformOpenControl(pControlChannel, pucString);
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// handle errors in PerformOpenControl
|
|
//
|
|
TSRemoveNode(ulTdiHandle);
|
|
}
|
|
else
|
|
{
|
|
lStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
TSFreeMemory(pControlChannel);
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSCloseControl
|
|
//
|
|
// Arguments: pControlChannel -- our control channel object to close
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Descript: This function frees the resources for a control channel,
|
|
// and calls the tdi provider to close it
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
TSCloseControl(PCONTROL_CHANNEL pControlChannel)
|
|
{
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulCLOSECONTROL\n"
|
|
"ControlChannel = %p\n",
|
|
pControlChannel);
|
|
}
|
|
|
|
|
|
ObDereferenceObject(pControlChannel->GenHead.pFileObject);
|
|
|
|
|
|
NTSTATUS lStatus = ZwClose(pControlChannel->GenHead.FileHandle);
|
|
|
|
if (lStatus != STATUS_SUCCESS)
|
|
{
|
|
DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
|
|
strFunc2,
|
|
lStatus);
|
|
}
|
|
|
|
TSFreeMemory(pControlChannel);
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSOpenAddress
|
|
//
|
|
// Arguments: pSendBuffer -- arguments from user dll for open command
|
|
// pIrp -- completion information
|
|
//
|
|
// Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
|
|
//
|
|
// Descript: This function sets up the structure for a new address object,
|
|
// and attempts to open the specified address object
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSOpenAddress(PSEND_BUFFER pSendBuffer,
|
|
PRECEIVE_BUFFER pReceiveBuffer)
|
|
{
|
|
PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
|
|
PTRANSPORT_ADDRESS pTransportAddress
|
|
= (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr;
|
|
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulOPENADDRESS\n"
|
|
"DeviceName = %ws\n",
|
|
pucString->wcBuffer);
|
|
TSPrintTaAddress(pTransportAddress->Address);
|
|
}
|
|
|
|
//
|
|
// allocate our structure and put it in the linked list...
|
|
//
|
|
PADDRESS_OBJECT pAddressObject;
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pAddressObject,
|
|
sizeof(ADDRESS_OBJECT),
|
|
strFunc3,
|
|
"AddressObject");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pAddressObject->GenHead.ulSignature = ulAddressObject;
|
|
|
|
ULONG ulTdiHandle = TSInsertNode(&pAddressObject->GenHead);
|
|
|
|
if (ulTdiHandle)
|
|
{
|
|
lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, FALSE);
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// handle error in PerformOpenAddress
|
|
//
|
|
TSRemoveNode(ulTdiHandle);
|
|
}
|
|
else
|
|
{
|
|
lStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
TSFreeMemory(pAddressObject);
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSCloseAddress
|
|
//
|
|
// Arguments: pAddressObject -- address object to close
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Descript: This function frees the resources for an address object,
|
|
// and calls the tdi provider to close it
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
VOID
|
|
TSCloseAddress(PADDRESS_OBJECT pAddressObject)
|
|
{
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulCLOSEADDRESS\n"
|
|
"AddressObject = %p\n",
|
|
pAddressObject);
|
|
}
|
|
|
|
TSFreeSpinLock(&pAddressObject->TdiSpinLock);
|
|
TSFreePacketData(pAddressObject);
|
|
|
|
ObDereferenceObject(pAddressObject->GenHead.pFileObject);
|
|
|
|
if (pAddressObject->pIrpPool)
|
|
{
|
|
TSFreeIrpPool(pAddressObject->pIrpPool);
|
|
}
|
|
|
|
NTSTATUS lStatus = ZwClose(pAddressObject->GenHead.FileHandle);
|
|
|
|
if (lStatus != STATUS_SUCCESS)
|
|
{
|
|
DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
|
|
strFunc4,
|
|
lStatus);
|
|
}
|
|
TSFreeMemory(pAddressObject);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSOpenEndpoint
|
|
//
|
|
// Arguments: pSendBuffer -- arguments from user dll for open command
|
|
// pIrp -- completion information
|
|
//
|
|
// Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
|
|
//
|
|
// Descript: This function sets up the structure for an endpoint. This
|
|
// involves opening an endpoint, opening an address object, and
|
|
// associating them...
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSOpenEndpoint(PSEND_BUFFER pSendBuffer,
|
|
PRECEIVE_BUFFER pReceiveBuffer)
|
|
{
|
|
PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
|
|
PTRANSPORT_ADDRESS pTransportAddress
|
|
= (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr;
|
|
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulOPENENDPOINT\n"
|
|
"DeviceName = %ws\n",
|
|
pucString->wcBuffer);
|
|
TSPrintTaAddress(pTransportAddress->Address);
|
|
}
|
|
|
|
//
|
|
// set up for the file open
|
|
// need to do our "context" structure first, since the
|
|
// eabuffer requires it...
|
|
//
|
|
PENDPOINT_OBJECT pEndpoint;
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pEndpoint,
|
|
sizeof(ENDPOINT_OBJECT),
|
|
strFunc5,
|
|
"EndpointObject");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pEndpoint->GenHead.ulSignature = ulEndpointObject;
|
|
|
|
ULONG ulTdiHandle = TSInsertNode(&pEndpoint->GenHead);
|
|
|
|
if (ulTdiHandle)
|
|
{
|
|
lStatus = TSPerformOpenEndpoint(pEndpoint, pucString);
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
PADDRESS_OBJECT pAddressObject;
|
|
|
|
lStatus = TSAllocateMemory((PVOID *)&pAddressObject,
|
|
sizeof(ADDRESS_OBJECT),
|
|
strFunc5,
|
|
"AddressObject");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pAddressObject->GenHead.ulSignature = ulAddressObject;
|
|
|
|
lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, TRUE);
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pEndpoint->pAddressObject = pAddressObject;
|
|
pAddressObject->pEndpoint = pEndpoint;
|
|
lStatus = TSPerformAssociate(pEndpoint);
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// fall thru to here on open/associate failures
|
|
//
|
|
}
|
|
else
|
|
{
|
|
TSRemoveNode(ulTdiHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
TSCloseEndpoint(pEndpoint); // also frees it!
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSCloseEndpoint
|
|
//
|
|
// Arguments: pEndpoint -- endpoint object to close
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Descript: This function frees the resources for a connection object,
|
|
// and calls the tdi provider to close it
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
VOID
|
|
TSCloseEndpoint(PENDPOINT_OBJECT pEndpoint)
|
|
{
|
|
//
|
|
// show debug, if it is turned on
|
|
//
|
|
if (ulDebugLevel & ulDebugShowCommand)
|
|
{
|
|
DebugPrint1("\nCommand = ulCLOSEENDPOINT\n"
|
|
"Endpoint = %p\n",
|
|
pEndpoint);
|
|
}
|
|
|
|
if (pEndpoint->pAddressObject)
|
|
{
|
|
if (pEndpoint->fIsAssociated)
|
|
{
|
|
TSPerformDisassociate(pEndpoint);
|
|
}
|
|
TSCloseAddress(pEndpoint->pAddressObject);
|
|
pEndpoint->pAddressObject = NULL;
|
|
}
|
|
|
|
if (pEndpoint->GenHead.pFileObject)
|
|
{
|
|
ObDereferenceObject(pEndpoint->GenHead.pFileObject);
|
|
|
|
NTSTATUS lStatus = ZwClose(pEndpoint->GenHead.FileHandle);
|
|
if (lStatus != STATUS_SUCCESS)
|
|
{
|
|
DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
|
|
strFunc6,
|
|
lStatus);
|
|
}
|
|
}
|
|
|
|
TSFreeMemory(pEndpoint);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// Private Functions
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
|
// ------------------------------------------------------
|
|
//
|
|
// Function: TSCompleteCommand
|
|
//
|
|
// Arguments: ptr to address object or endpoint to close for command
|
|
// lstatus = status of close attempt (as TDI_STATUS)
|
|
// param = 0
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Descript: This function is called to complete a CloseAddress or
|
|
// a CloseEndpoint on Win98
|
|
//
|
|
// -------------------------------------------------------
|
|
|
|
#pragma warning(disable: UNREFERENCED_PARAM)
|
|
|
|
TDI_STATUS
|
|
TSCompleteCommand(PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pLowerIrp,
|
|
PVOID pvContext)
|
|
{
|
|
TDI_STATUS TdiStatus = pLowerIrp->IoStatus.Status;
|
|
PGENERIC_HEADER pGenHead = (PGENERIC_HEADER)pvContext;
|
|
|
|
TSSetEvent(&pGenHead->TdiEvent);
|
|
pGenHead->lStatus = TdiStatus;
|
|
|
|
TSFreeIrp(pLowerIrp, NULL);
|
|
return TDI_MORE_PROCESSING;
|
|
}
|
|
|
|
#pragma warning(default: UNREFERENCED_PARAM)
|
|
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSPerformOpenControl
|
|
//
|
|
// Arguments: pControlChannel -- used to store file information
|
|
// pucString -- name of device to open
|
|
//
|
|
// Returns: status of operation
|
|
//
|
|
// Descript: Actually opens the control channel, and then sets the
|
|
// appropriate fields in our structure
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSPerformOpenControl(PCONTROL_CHANNEL pControlChannel,
|
|
PUCNTSTRING pucString)
|
|
{
|
|
UNICODE_STRING ustrDeviceName;
|
|
|
|
//
|
|
// we need a unicode string to actually do the open
|
|
//
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
|
|
pucString->usLength + 2,
|
|
strFuncP2,
|
|
"StringBuffer");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
HANDLE FileHandle;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
//
|
|
// create the unicode string
|
|
//
|
|
ustrDeviceName.Length = pucString->usLength;
|
|
ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
|
|
RtlCopyMemory(ustrDeviceName.Buffer,
|
|
pucString->wcBuffer,
|
|
ustrDeviceName.Length);
|
|
|
|
//
|
|
// set up the object attributes needed to open this...
|
|
//
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&ustrDeviceName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
lStatus = ZwCreateFile(&FileHandle,
|
|
GENERIC_READ | GENERIC_WRITE, // desired access.
|
|
&ObjectAttributes, // object attributes.
|
|
&IoStatusBlock, // returned status information.
|
|
NULL, // Allocation size (unused).
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes.
|
|
FILE_SHARE_WRITE,
|
|
FILE_CREATE,
|
|
0, // create options.
|
|
NULL,
|
|
0);
|
|
|
|
//
|
|
// make sure it really succeeded
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
lStatus = IoStatusBlock.Status;
|
|
}
|
|
|
|
//
|
|
// clean up this now (don't need it anymore)
|
|
//
|
|
TSFreeMemory(ustrDeviceName.Buffer);
|
|
|
|
//
|
|
// if it succeeded, then set up our node structure
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
PFILE_OBJECT pFileObject;
|
|
|
|
lStatus = ObReferenceObjectByHandle(FileHandle,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
(PVOID *)&pFileObject,
|
|
NULL);
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
pControlChannel->GenHead.FileHandle = FileHandle;
|
|
pControlChannel->GenHead.pFileObject = pFileObject;
|
|
pControlChannel->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
|
|
return STATUS_SUCCESS; // only successful exit point
|
|
}
|
|
else
|
|
{
|
|
DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
|
|
lStatus);
|
|
}
|
|
}
|
|
//
|
|
// get here if ZwCreateFile failed
|
|
//
|
|
else
|
|
{
|
|
DebugPrint3("OpenControlChannel failed for %ws with code %x iostatus %x\n",
|
|
pucString->wcBuffer,
|
|
lStatus,
|
|
IoStatusBlock.Status);
|
|
}
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSPerformOpenAddress
|
|
//
|
|
// Arguments: pAddressObject -- used to store file information
|
|
// pucString -- name of device to open
|
|
// pTransportAddr -- address to open on the device
|
|
// fIsConnect -- TRUE for connection, false for datagram
|
|
//
|
|
// Returns: status of operation
|
|
//
|
|
// Descript: Actually opens the address object, and then sets the
|
|
// appropriate fields in our structure
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSPerformOpenAddress(PADDRESS_OBJECT pAddressObject,
|
|
PUCNTSTRING pucString,
|
|
PTRANSPORT_ADDRESS pTransportAddress,
|
|
BOOLEAN fIsConnect)
|
|
{
|
|
|
|
//
|
|
// address open uses an ea buffer that contains the transport address
|
|
//
|
|
ULONG ulAddressLength
|
|
= FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
|
|
+ FIELD_OFFSET(TA_ADDRESS, Address)
|
|
+ pTransportAddress->Address[0].AddressLength;
|
|
ULONG ulEaLengthNeeded
|
|
= FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0])
|
|
+ (TDI_TRANSPORT_ADDRESS_LENGTH + 1)
|
|
+ ulAddressLength;
|
|
|
|
//
|
|
// allocate the ea buffer first...
|
|
//
|
|
PFILE_FULL_EA_INFORMATION EaBuffer;
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer,
|
|
ulEaLengthNeeded,
|
|
strFuncP3,
|
|
"EaBuffer");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
UNICODE_STRING ustrDeviceName;
|
|
|
|
//
|
|
// setup the ea buffer
|
|
//
|
|
EaBuffer->NextEntryOffset = 0;
|
|
EaBuffer->Flags = 0;
|
|
EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
|
|
EaBuffer->EaValueLength = (USHORT)ulAddressLength;
|
|
RtlCopyMemory(&EaBuffer->EaName[0],
|
|
TdiTransportAddress,
|
|
TDI_TRANSPORT_ADDRESS_LENGTH + 1);
|
|
|
|
RtlCopyMemory(&EaBuffer->EaName[TDI_TRANSPORT_ADDRESS_LENGTH+1],
|
|
pTransportAddress,
|
|
ulAddressLength);
|
|
|
|
//
|
|
// we need a unicode string to actually do the open
|
|
//
|
|
lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
|
|
pucString->usLength + 2,
|
|
strFuncP3,
|
|
"StringBuffer");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE FileHandle;
|
|
|
|
//
|
|
// create the unicode string
|
|
//
|
|
ustrDeviceName.Length = pucString->usLength;
|
|
ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
|
|
RtlCopyMemory(ustrDeviceName.Buffer,
|
|
pucString->wcBuffer,
|
|
ustrDeviceName.Length);
|
|
|
|
//
|
|
// set up the object attributes needed to open this...
|
|
//
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&ustrDeviceName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
lStatus = ZwCreateFile(&FileHandle,
|
|
GENERIC_READ | GENERIC_WRITE, // desired access.
|
|
&ObjectAttributes, // object attributes.
|
|
&IoStatusBlock, // returned status information.
|
|
NULL, // Allocation size (unused).
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes.
|
|
FILE_SHARE_WRITE,
|
|
FILE_CREATE,
|
|
0, // create options.
|
|
EaBuffer,
|
|
ulEaLengthNeeded);
|
|
|
|
//
|
|
// make sure it really succeeded
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
lStatus = IoStatusBlock.Status;
|
|
}
|
|
|
|
//
|
|
// clean up what we can here...
|
|
//
|
|
TSFreeMemory(ustrDeviceName.Buffer);
|
|
TSFreeMemory(EaBuffer);
|
|
|
|
//
|
|
// if it succeeded, then set up our node structure
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
PFILE_OBJECT pFileObject;
|
|
|
|
lStatus = ObReferenceObjectByHandle(FileHandle,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
(PVOID *)&pFileObject,
|
|
NULL);
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
pAddressObject->GenHead.FileHandle = FileHandle;
|
|
pAddressObject->GenHead.pFileObject = pFileObject;
|
|
pAddressObject->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
|
|
TSAllocateSpinLock(&pAddressObject->TdiSpinLock);
|
|
|
|
//
|
|
// if ipv4, set up socket for strong host
|
|
//
|
|
if (fIsConnect && (pTransportAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP))
|
|
{
|
|
TCP_REQUEST_SET_INFORMATION_EX* pInfo;
|
|
CHAR achBuf[ sizeof(*pInfo) + sizeof(ULONG) ];
|
|
ULONG ulValue = 1;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
pInfo = (TCP_REQUEST_SET_INFORMATION_EX* )achBuf;
|
|
pInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY;
|
|
pInfo->ID.toi_entity.tei_instance = 0;
|
|
pInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
|
|
pInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
|
|
pInfo->ID.toi_id = AO_OPTION_IP_UCASTIF;
|
|
|
|
RtlCopyMemory(pInfo->Buffer, &ulValue, sizeof(ULONG));
|
|
pInfo->BufferSize = sizeof(ULONG);
|
|
|
|
PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_TCP_WSH_SET_INFORMATION_EX,
|
|
pAddressObject->GenHead.pDeviceObject,
|
|
(PVOID )pInfo,
|
|
sizeof(*pInfo) + sizeof(ULONG),
|
|
NULL,
|
|
0,
|
|
FALSE,
|
|
NULL,
|
|
&iosb);
|
|
|
|
if (pIrp)
|
|
{
|
|
PIO_STACK_LOCATION pIrpSp = IoGetNextIrpStackLocation(pIrp);
|
|
pIrpSp->FileObject = pFileObject;
|
|
|
|
IoCallDriver(pAddressObject->GenHead.pDeviceObject, pIrp);
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS; // only successful exit
|
|
}
|
|
else
|
|
{
|
|
DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
|
|
lStatus);
|
|
}
|
|
ZwClose(FileHandle);
|
|
}
|
|
|
|
//
|
|
// get here if ZwCreateFile failed
|
|
//
|
|
else
|
|
{
|
|
DebugPrint3("OpenAddressObject failed for %ws with code %x iostatus %x\n",
|
|
pucString->wcBuffer,
|
|
lStatus,
|
|
IoStatusBlock.Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// get here if cannot allocate unicode string buffer
|
|
//
|
|
else
|
|
{
|
|
TSFreeMemory(EaBuffer);
|
|
}
|
|
}
|
|
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------
|
|
//
|
|
// Function: TSPerformOpenEndpoint
|
|
//
|
|
// Arguments: pEndpoint -- used to store file information
|
|
// pucString -- name of device to open
|
|
//
|
|
// Returns: status of operation
|
|
//
|
|
// Descript: Actually opens the endpoint object, and then sets the
|
|
// appropriate fields in our structure
|
|
//
|
|
// -----------------------------------------------
|
|
|
|
|
|
NTSTATUS
|
|
TSPerformOpenEndpoint(PENDPOINT_OBJECT pEndpoint,
|
|
PUCNTSTRING pucString)
|
|
{
|
|
|
|
//
|
|
// NOTE: CONNECTION_CONTEXT == PVOID
|
|
//
|
|
ULONG ulEaLengthNeeded
|
|
= FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0])
|
|
+ (TDI_CONNECTION_CONTEXT_LENGTH + 1)
|
|
+ sizeof(CONNECTION_CONTEXT);
|
|
|
|
//
|
|
// allocate the ea buffer...
|
|
//
|
|
PFILE_FULL_EA_INFORMATION EaBuffer;
|
|
NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer,
|
|
ulEaLengthNeeded,
|
|
strFunc5,
|
|
"EaBuffer");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
UNICODE_STRING ustrDeviceName;
|
|
|
|
//
|
|
// setup the ea buffer
|
|
//
|
|
EaBuffer->NextEntryOffset = 0;
|
|
EaBuffer->Flags = 0;
|
|
EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
|
|
EaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
|
|
RtlCopyMemory(&EaBuffer->EaName[0],
|
|
TdiConnectionContext,
|
|
TDI_CONNECTION_CONTEXT_LENGTH + 1);
|
|
|
|
RtlCopyMemory(&EaBuffer->EaName[TDI_CONNECTION_CONTEXT_LENGTH+1],
|
|
&pEndpoint,
|
|
sizeof(CONNECTION_CONTEXT));
|
|
|
|
//
|
|
// we need a unicode string to actually do the open
|
|
//
|
|
lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
|
|
pucString->usLength + 2,
|
|
strFunc5,
|
|
"StringBuffer");
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
HANDLE FileHandle;
|
|
|
|
//
|
|
// create the unicode string
|
|
//
|
|
ustrDeviceName.Length = pucString->usLength;
|
|
ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
|
|
RtlCopyMemory(ustrDeviceName.Buffer,
|
|
pucString->wcBuffer,
|
|
ustrDeviceName.Length);
|
|
|
|
//
|
|
// set up the object attributes needed to open this...
|
|
//
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&ustrDeviceName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
lStatus = ZwCreateFile(&FileHandle,
|
|
GENERIC_READ | GENERIC_WRITE, // desired access.
|
|
&ObjectAttributes, // object attributes.
|
|
&IoStatusBlock, // returned status information.
|
|
NULL, // Allocation size (unused).
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes.
|
|
FILE_SHARE_WRITE,
|
|
FILE_CREATE,
|
|
0, // create options.
|
|
EaBuffer,
|
|
ulEaLengthNeeded);
|
|
|
|
//
|
|
// make sure it really succeeded
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
lStatus = IoStatusBlock.Status;
|
|
}
|
|
|
|
//
|
|
// free up what we can here...
|
|
//
|
|
TSFreeMemory(ustrDeviceName.Buffer);
|
|
TSFreeMemory(EaBuffer);
|
|
|
|
//
|
|
// if it succeeded, then set up our node structure
|
|
//
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
PFILE_OBJECT pFileObject;
|
|
|
|
lStatus = ObReferenceObjectByHandle(FileHandle,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
(PVOID *)&pFileObject,
|
|
NULL);
|
|
if (NT_SUCCESS(lStatus))
|
|
{
|
|
pEndpoint->GenHead.FileHandle = FileHandle;
|
|
pEndpoint->GenHead.pFileObject = pFileObject;
|
|
pEndpoint->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
|
|
return STATUS_SUCCESS; // only successful exit
|
|
}
|
|
|
|
else
|
|
{
|
|
DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
|
|
lStatus);
|
|
}
|
|
ZwClose(FileHandle);
|
|
}
|
|
|
|
//
|
|
// get here if ZwCreateFile failed
|
|
//
|
|
else
|
|
{
|
|
DebugPrint3("OpenEndpointObject failed for %ws with code %x iostatus %x\n",
|
|
pucString->wcBuffer,
|
|
lStatus,
|
|
IoStatusBlock.Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// get here if cannot allocate unicode string buffer
|
|
//
|
|
else
|
|
{
|
|
TSFreeMemory(EaBuffer);
|
|
}
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSPerformAssociate
|
|
//
|
|
// Arguments: pEndpoint -- connection endpoint structure
|
|
//
|
|
// Returns: NTSTATUS (normally success)
|
|
//
|
|
// Descript: This function attempts to associate a transport address
|
|
// object with an endpoint object
|
|
//
|
|
// -----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
TSPerformAssociate(PENDPOINT_OBJECT pEndpoint)
|
|
{
|
|
TSInitializeEvent(&pEndpoint->GenHead.TdiEvent);
|
|
|
|
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
|
|
NULL);
|
|
|
|
if (!pLowerIrp)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// set up everything and call the tdi provider
|
|
//
|
|
|
|
#pragma warning(disable: CONSTANT_CONDITIONAL)
|
|
|
|
TdiBuildAssociateAddress(pLowerIrp,
|
|
pEndpoint->GenHead.pDeviceObject,
|
|
pEndpoint->GenHead.pFileObject,
|
|
TSCompleteCommand,
|
|
pEndpoint,
|
|
pEndpoint->pAddressObject->GenHead.FileHandle);
|
|
|
|
#pragma warning(default: CONSTANT_CONDITIONAL)
|
|
|
|
//
|
|
// (should ALWAYS be pending)
|
|
//
|
|
NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
|
|
pLowerIrp);
|
|
|
|
if (lStatus == STATUS_PENDING)
|
|
{
|
|
TSWaitEvent(&pEndpoint->GenHead.TdiEvent);
|
|
lStatus = pEndpoint->GenHead.lStatus;
|
|
}
|
|
|
|
if (lStatus == STATUS_SUCCESS)
|
|
{
|
|
pEndpoint->fIsAssociated = TRUE;
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
//
|
|
// Function: TSPerformDisassociateAddress
|
|
//
|
|
// Arguments: pEndpoint -- connection endpoint structure
|
|
//
|
|
// Returns: NTSTATUS (normally pending)
|
|
//
|
|
// Descript: This function attempts to disassociate a transport address
|
|
// object from its associated endpoint object
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
VOID
|
|
TSPerformDisassociate(PENDPOINT_OBJECT pEndpoint)
|
|
{
|
|
TSInitializeEvent(&pEndpoint->GenHead.TdiEvent);
|
|
|
|
PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
|
|
NULL);
|
|
|
|
if (!pLowerIrp)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// set up everything and call the tdi provider
|
|
//
|
|
|
|
#pragma warning(disable: CONSTANT_CONDITIONAL)
|
|
|
|
TdiBuildDisassociateAddress(pLowerIrp,
|
|
pEndpoint->GenHead.pDeviceObject,
|
|
pEndpoint->GenHead.pFileObject,
|
|
TSCompleteCommand,
|
|
pEndpoint);
|
|
|
|
#pragma warning(default: CONSTANT_CONDITIONAL)
|
|
|
|
NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
|
|
pLowerIrp);
|
|
|
|
if (lStatus == STATUS_PENDING)
|
|
{
|
|
TSWaitEvent(&pEndpoint->GenHead.TdiEvent);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// end of file open.cpp
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|