433 lines
12 KiB
C
433 lines
12 KiB
C
|
//
|
|||
|
//
|
|||
|
// NBTCONNCT.C
|
|||
|
//
|
|||
|
// This file contains code relating to opening connections with the transport
|
|||
|
// provider. The Code is NT specific.
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma CTEMakePageable(PAGE, NbtTdiOpenConnection)
|
|||
|
#pragma CTEMakePageable(PAGE, NbtTdiAssociateConnection)
|
|||
|
#pragma CTEMakePageable(PAGE, NbtTdiCloseConnection)
|
|||
|
#pragma CTEMakePageable(PAGE, CreateDeviceString)
|
|||
|
#pragma CTEMakePageable(PAGE, NbtTdiCloseAddress)
|
|||
|
#endif
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
NTSTATUS
|
|||
|
NbtTdiOpenConnection (
|
|||
|
IN tLOWERCONNECTION *pLowerConn,
|
|||
|
IN tDEVICECONTEXT *pDeviceContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine opens a connection with the transport provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLowerConn - Pointer to where the handle to the Transport for this virtual
|
|||
|
connection should be stored.
|
|||
|
|
|||
|
pNbtConfig - the name of the adapter to connect to is in this structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
NTSTATUS Status, Status1;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
PWSTR pName=L"Tcp";
|
|||
|
PFILE_FULL_EA_INFORMATION EaBuffer;
|
|||
|
UNICODE_STRING RelativeDeviceName = {0,0,NULL};
|
|||
|
PMDL pMdl;
|
|||
|
PVOID pBuffer;
|
|||
|
BOOLEAN Attached = FALSE;
|
|||
|
|
|||
|
CTEPagedCode();
|
|||
|
// zero out the connection data structure
|
|||
|
CTEZeroMemory(pLowerConn,sizeof(tLOWERCONNECTION));
|
|||
|
SET_STATE_LOWER (pLowerConn, NBT_IDLE);
|
|||
|
pLowerConn->pDeviceContext = pDeviceContext;
|
|||
|
CTEInitLock(&pLowerConn->LockInfo.SpinLock);
|
|||
|
#if DBG
|
|||
|
pLowerConn->LockInfo.LockNumber = LOWERCON_LOCK;
|
|||
|
#endif
|
|||
|
pLowerConn->Verify = NBT_VERIFY_LOWERCONN;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate an MDL for the Indication buffer since we may need to buffer
|
|||
|
// up to 128 bytes
|
|||
|
//
|
|||
|
pBuffer = NbtAllocMem(NBT_INDICATE_BUFFER_SIZE,NBT_TAG('l'));
|
|||
|
if (!pBuffer)
|
|||
|
{
|
|||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|||
|
}
|
|||
|
|
|||
|
pMdl = IoAllocateMdl(pBuffer,NBT_INDICATE_BUFFER_SIZE,FALSE,FALSE,NULL);
|
|||
|
|
|||
|
if (pMdl)
|
|||
|
{
|
|||
|
|
|||
|
MmBuildMdlForNonPagedPool(pMdl);
|
|||
|
|
|||
|
pLowerConn->pIndicateMdl = pMdl;
|
|||
|
|
|||
|
#ifdef HDL_FIX
|
|||
|
InitializeObjectAttributes (&ObjectAttributes,
|
|||
|
&RelativeDeviceName,
|
|||
|
OBJ_KERNEL_HANDLE,
|
|||
|
pDeviceContext->hSession, // Use a relative File Handle
|
|||
|
NULL);
|
|||
|
#else
|
|||
|
InitializeObjectAttributes (&ObjectAttributes,
|
|||
|
&RelativeDeviceName,
|
|||
|
0,
|
|||
|
pDeviceContext->hSession, // Use a relative File Handle
|
|||
|
NULL);
|
|||
|
#endif // HDL_FIX
|
|||
|
|
|||
|
// Allocate memory for the address info to be passed to the transport
|
|||
|
EaBuffer = (PFILE_FULL_EA_INFORMATION)NbtAllocMem (
|
|||
|
sizeof(FILE_FULL_EA_INFORMATION) - 1 +
|
|||
|
TDI_CONNECTION_CONTEXT_LENGTH + 1 +
|
|||
|
sizeof(CONNECTION_CONTEXT),NBT_TAG('m'));
|
|||
|
|
|||
|
if (EaBuffer)
|
|||
|
{
|
|||
|
EaBuffer->NextEntryOffset = 0;
|
|||
|
EaBuffer->Flags = 0;
|
|||
|
EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
|
|||
|
EaBuffer->EaValueLength = sizeof (CONNECTION_CONTEXT);
|
|||
|
|
|||
|
// TdiConnectionContext is a macro that = "ConnectionContext" - so move
|
|||
|
// this text to EaName
|
|||
|
RtlMoveMemory( EaBuffer->EaName, TdiConnectionContext, EaBuffer->EaNameLength + 1 );
|
|||
|
|
|||
|
// put the context value into the EaBuffer too - i.e. the value that the
|
|||
|
// transport returns with each indication on this connection
|
|||
|
RtlMoveMemory (
|
|||
|
(PVOID)&EaBuffer->EaName[EaBuffer->EaNameLength + 1],
|
|||
|
(CONST PVOID)&pLowerConn,
|
|||
|
sizeof (CONNECTION_CONTEXT));
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
Status = ZwCreateFile (&pLowerConn->FileHandle,
|
|||
|
GENERIC_READ | GENERIC_WRITE,
|
|||
|
&ObjectAttributes, // object attributes.
|
|||
|
&IoStatusBlock, // returned status information.
|
|||
|
NULL, // block size (unused).
|
|||
|
FILE_ATTRIBUTE_NORMAL, // file attributes.
|
|||
|
0,
|
|||
|
FILE_CREATE,
|
|||
|
0, // create options.
|
|||
|
(PVOID)EaBuffer, // EA buffer.
|
|||
|
sizeof(FILE_FULL_EA_INFORMATION) - 1 +
|
|||
|
TDI_CONNECTION_CONTEXT_LENGTH + 1 +
|
|||
|
sizeof(CONNECTION_CONTEXT));
|
|||
|
}
|
|||
|
|
|||
|
IF_DBG(NBT_DEBUG_HANDLES)
|
|||
|
KdPrint (("\t===><%x>\tNbtTdiOpenConnection->ZwCreateFile, Status = <%x>\n", pLowerConn->FileHandle, Status));
|
|||
|
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint( ("Nbt.NbtTdiOpenConnection: CreateFile Status:%X, IoStatus:%X\n", Status, IoStatusBlock.Status));
|
|||
|
|
|||
|
CTEMemFree((PVOID)EaBuffer);
|
|||
|
|
|||
|
if ( NT_SUCCESS( Status ))
|
|||
|
{
|
|||
|
|
|||
|
// if the ZwCreate passed set the status to the IoStatus
|
|||
|
//
|
|||
|
Status = IoStatusBlock.Status;
|
|||
|
|
|||
|
if (NT_SUCCESS(Status))
|
|||
|
{
|
|||
|
// get a reference to the file object and save it since we can't
|
|||
|
// dereference a file handle at DPC level so we do it now and keep
|
|||
|
// the ptr around for later.
|
|||
|
Status = ObReferenceObjectByHandle (pLowerConn->FileHandle,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
KernelMode,
|
|||
|
(PVOID *)&pLowerConn->pFileObject,
|
|||
|
NULL);
|
|||
|
|
|||
|
IF_DBG(NBT_DEBUG_HANDLES)
|
|||
|
KdPrint (("\t ++<%x>====><%x>\tNbtTdiOpenConnection->ObReferenceObjectByHandle, Status = <%x>\n", pLowerConn->FileHandle, pLowerConn->pFileObject, Status));
|
|||
|
|
|||
|
if (NT_SUCCESS(Status))
|
|||
|
{
|
|||
|
#if FAST_DISP
|
|||
|
// Go ahead and query transport for fast dispath path.
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint(("Nbt.NbtTdiOpenConnection: Querying for TCPSendData File object %x\n",pLowerConn->pFileObject ));
|
|||
|
|
|||
|
pLowerConn->FastSend = pDeviceContext->pFastSend;
|
|||
|
#endif
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
Status1 = ZwClose(pLowerConn->FileHandle);
|
|||
|
IF_DBG(NBT_DEBUG_HANDLES)
|
|||
|
KdPrint (("\t<===<%x>\tNbtTdiOpenConnection->ZwClose, status = <%x>\n", pLowerConn->FileHandle, Status1));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
IoFreeMdl(pMdl);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
CTEMemFree(pBuffer);
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} /* NbtTdiOpenConnection */
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
NTSTATUS
|
|||
|
NbtTdiAssociateConnection(
|
|||
|
IN PFILE_OBJECT pFileObject,
|
|||
|
IN HANDLE Handle
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine associates an open connection with the address object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
pFileObject - the connection file object
|
|||
|
Handle - the address object to associate the connection with
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
PIRP pIrp;
|
|||
|
KEVENT Event;
|
|||
|
BOOLEAN Attached = FALSE;
|
|||
|
|
|||
|
CTEPagedCode();
|
|||
|
|
|||
|
KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
|
|||
|
|
|||
|
pIrp = NTAllocateNbtIrp(IoGetRelatedDeviceObject(pFileObject));
|
|||
|
|
|||
|
if (!pIrp)
|
|||
|
{
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint(("Nbt.NbtTdiAssociateConnection: Failed to build internal device Irp\n"));
|
|||
|
return(STATUS_UNSUCCESSFUL);
|
|||
|
}
|
|||
|
|
|||
|
TdiBuildAssociateAddress (pIrp,
|
|||
|
pFileObject->DeviceObject,
|
|||
|
pFileObject,
|
|||
|
NbtTdiCompletionRoutine,
|
|||
|
&Event,
|
|||
|
Handle);
|
|||
|
|
|||
|
status = SubmitTdiRequest(pFileObject,pIrp);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint (("Nbt.NbtTdiAssociateConnection: ERROR -- SubmitTdiRequest returned <%x>\n", status));
|
|||
|
}
|
|||
|
|
|||
|
IoFreeIrp(pIrp);
|
|||
|
return status;
|
|||
|
}
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
NTSTATUS
|
|||
|
CreateDeviceString(
|
|||
|
IN PWSTR AppendingString,
|
|||
|
IN OUT PUNICODE_STRING pucDeviceName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a string name for the transport device such as
|
|||
|
"\Device\Streams\Tcp"
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
ULONG Len;
|
|||
|
PVOID pBuffer;
|
|||
|
PWSTR pTcpBindName = NbtConfig.pTcpBindName;
|
|||
|
|
|||
|
CTEPagedCode();
|
|||
|
|
|||
|
if (!pTcpBindName)
|
|||
|
{
|
|||
|
pTcpBindName = NBT_TCP_BIND_NAME;
|
|||
|
}
|
|||
|
|
|||
|
// copy device name into the unicode string - either Udp or Tcp
|
|||
|
//
|
|||
|
Len = (wcslen(pTcpBindName) + wcslen(AppendingString) + 1) * sizeof(WCHAR);
|
|||
|
if (pBuffer = NbtAllocMem(Len,NBT_TAG('n')))
|
|||
|
{
|
|||
|
pucDeviceName->MaximumLength = (USHORT)Len;
|
|||
|
pucDeviceName->Length = 0;
|
|||
|
pucDeviceName->Buffer = pBuffer;
|
|||
|
|
|||
|
// this puts \Device\Streams into the string
|
|||
|
//
|
|||
|
if ((NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, pTcpBindName))) &&
|
|||
|
(NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, AppendingString))))
|
|||
|
{
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
CTEMemFree(pBuffer);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Error case -- cleanup!
|
|||
|
//
|
|||
|
pucDeviceName->MaximumLength = 0;
|
|||
|
pucDeviceName->Length = 0;
|
|||
|
pucDeviceName->Buffer = NULL;
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbtTdiCloseConnection(
|
|||
|
IN tLOWERCONNECTION * pLowerConn
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes a TDI connection
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
BOOLEAN Attached= FALSE;
|
|||
|
|
|||
|
CTEPagedCode();
|
|||
|
ASSERT( pLowerConn != NULL ) ;
|
|||
|
|
|||
|
CTEAttachFsp(&Attached, REF_FSP_CLOSE_CONNECTION);
|
|||
|
|
|||
|
if (pLowerConn->FileHandle)
|
|||
|
{
|
|||
|
status = ZwClose(pLowerConn->FileHandle);
|
|||
|
IF_DBG(NBT_DEBUG_HANDLES)
|
|||
|
KdPrint (("\t<===<%x>\tNbtTdiCloseConnection->ZwClose, status = <%x>\n", pLowerConn->FileHandle, status));
|
|||
|
pLowerConn->FileHandle = NULL;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint(("Nbt.NbtTdiCloseConnection: Failed to close LowerConn FileHandle pLower %X, status %X\n",
|
|||
|
pLowerConn,status));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
CTEDetachFsp(Attached, REF_FSP_CLOSE_CONNECTION);
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
NTSTATUS
|
|||
|
NbtTdiCloseAddress(
|
|||
|
IN tLOWERCONNECTION * pLowerConn
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes a TDI address
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
BOOLEAN Attached= FALSE;
|
|||
|
|
|||
|
CTEPagedCode();
|
|||
|
|
|||
|
ASSERT( pLowerConn != NULL ) ;
|
|||
|
|
|||
|
CTEAttachFsp(&Attached, REF_FSP_CLOSE_ADDRESS);
|
|||
|
|
|||
|
status = ZwClose(pLowerConn->AddrFileHandle);
|
|||
|
IF_DBG(NBT_DEBUG_HANDLES)
|
|||
|
KdPrint (("\t<===<%x>\tNbtTdiCloseAddress->ZwClose, status = <%x>\n", pLowerConn->AddrFileHandle, status));
|
|||
|
#if DBG
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
IF_DBG(NBT_DEBUG_TDICNCT)
|
|||
|
KdPrint(("Nbt.NbtTdiCloseAddress: Failed to close Address FileHandle pLower %X,status %X\n",
|
|||
|
pLowerConn,status));
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
CTEDetachFsp(Attached, REF_FSP_CLOSE_ADDRESS);
|
|||
|
|
|||
|
return(status);
|
|||
|
|
|||
|
}
|