windows-nt/Source/XPSP1/NT/net/netbt/sys/nt/tdicnct.c
2020-09-26 16:20:57 +08:00

433 lines
12 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
//
// 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);
}