windows-nt/Source/XPSP1/NT/net/tdi/sample/sys/open.cpp

1150 lines
34 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/////////////////////////////////////////////////////////
//
// 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
////////////////////////////////////////////////////////////////////////////////