diff options
Diffstat (limited to 'private/ntos/nbt/nt/tdicnct.c')
-rw-r--r-- | private/ntos/nbt/nt/tdicnct.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/private/ntos/nbt/nt/tdicnct.c b/private/ntos/nbt/nt/tdicnct.c new file mode 100644 index 000000000..3ff5610e4 --- /dev/null +++ b/private/ntos/nbt/nt/tdicnct.c @@ -0,0 +1,530 @@ +// +// +// NBTCONNCT.C +// +// This file contains code relating to opening connections with the transport +// provider. The Code is NT specific. + +#include "nbtprocs.h" + +//******************* Pageable Routine Declarations **************** +#ifdef ALLOC_PRAGMA +#pragma CTEMakePageable(PAGE, NbtTdiOpenConnection) +#pragma CTEMakePageable(PAGE, NbtTdiAssociateConnection) +#pragma CTEMakePageable(PAGE, TdiOpenandAssocConnection) +#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; + OBJECT_ATTRIBUTES ObjectAttributes; + PWSTR pName=L"Tcp"; + PFILE_FULL_EA_INFORMATION EaBuffer; + UNICODE_STRING DeviceName; + PMDL pMdl; + PVOID pBuffer; + BOOLEAN Attached = FALSE; + + CTEPagedCode(); + // zero out the connection data structure + CTEZeroMemory(pLowerConn,sizeof(tLOWERCONNECTION)); + pLowerConn->State = NBT_IDLE; + pLowerConn->pDeviceContext = pDeviceContext; + pLowerConn->RefCount = 1; + pLowerConn->LockNumber = LOWERCON_LOCK; + pLowerConn->Verify = NBT_VERIFY_LOWERCONN; + + Status = CreateDeviceString(pName,&DeviceName); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + // + // 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) + { + CTEMemFree(DeviceName.Buffer); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + pMdl = IoAllocateMdl(pBuffer,NBT_INDICATE_BUFFER_SIZE,FALSE,FALSE,NULL); + + if (pMdl) + { + + MmBuildMdlForNonPagedPool(pMdl); + + pLowerConn->pIndicateMdl = pMdl; + + + InitializeObjectAttributes ( + &ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + + IF_DBG(NBT_DEBUG_TDICNCT) + KdPrint(("tcp device to open = %ws\n",DeviceName.Buffer)); + + // 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_TDICNCT) + KdPrint( ("OpenConnection 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 (NT_SUCCESS(Status)) + { + CTEMemFree(DeviceName.Buffer); + return(Status); + } + + ZwClose(pLowerConn->FileHandle); + + } + + } + + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + + IoFreeMdl(pMdl); + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + CTEMemFree(pBuffer); + CTEMemFree(DeviceName.Buffer); + + 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) + { + KdPrint(("NBT:Failed to build internal device Irp\n")); + return(STATUS_UNSUCCESSFUL); + } + + TdiBuildAssociateAddress ( + pIrp, + pFileObject->DeviceObject, + pFileObject, + CompletionRoutine, + &Event, + Handle); + + status = SubmitTdiRequest(pFileObject,pIrp); + + 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; + + CTEPagedCode(); + // copy device name into the unicode string - either Udp or Tcp + // + Len = (wcslen(NbtConfig.pTcpBindName) + wcslen(AppendingString) + 1) * sizeof(WCHAR); + + pBuffer = NbtAllocMem(Len,NBT_TAG('n')); + if (!pBuffer) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + pucDeviceName->MaximumLength = (USHORT)Len; + pucDeviceName->Length = 0; + pucDeviceName->Buffer = pBuffer; + + // this puts \Device\Streams into the string + // + status = RtlAppendUnicodeToString(pucDeviceName,NbtConfig.pTcpBindName); + if (NT_SUCCESS(status)) + { + status = RtlAppendUnicodeToString (pucDeviceName,AppendingString); + } + else + CTEMemFree(pBuffer); + + return(status); + +} + +//---------------------------------------------------------------------------- +NTSTATUS +TdiOpenandAssocConnection( + IN tCONNECTELE *pConnEle, + IN tDEVICECONTEXT *pDeviceContext, + IN ULONG PortNumber + ) +/*++ + +Routine Description: + + This routine opens and associates an open connection. + + This routine is called with the Spin Lock held on the pConnele. It is + released in this routine. + +Arguments: + + +Return Value: + + Status of the operation. + +--*/ +{ + NTSTATUS status; + NTSTATUS Locstatus; + PDEVICE_OBJECT pDeviceObject; + tLOWERCONNECTION *pLowerConn; + BOOLEAN Attached=FALSE; + + CTEPagedCode(); + + CTEAttachFsp(&Attached); + + // allocate memory for the lower connection block. + // + pConnEle->pLowerConnId = (PVOID)NbtAllocMem(sizeof(tLOWERCONNECTION),NBT_TAG('o')); + + if (!pConnEle->pLowerConnId) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // fill in the lower connection element to point to the upper one and + // vice versa + // + pLowerConn = pConnEle->pLowerConnId; + + status = NbtTdiOpenConnection(pLowerConn,pDeviceContext); + if (!NT_SUCCESS(status)) + { + CTEDetachFsp(Attached); + CTEMemFree((PVOID)pConnEle->pLowerConnId); + pConnEle->pLowerConnId = NULL; + return(status); + } + + pLowerConn->pUpperConnection = pConnEle; + pLowerConn->State = NBT_IDLE; + + // + // until the correct state proc is set (i.e.Outbound), reject any data + // (in other words, don't let this field stay NULL!) + // + SetStateProc( pLowerConn, RejectAnyData ) ; + + + if (NT_SUCCESS(status)) + { + + // Open an address object (aka port) + // + status = NbtTdiOpenAddress( + &pLowerConn->AddrFileHandle, + &pDeviceObject, // dummy argument, not used here + &pLowerConn->pAddrFileObject, + pDeviceContext, + (USHORT)PortNumber, // port + pDeviceContext->IpAddress, + TCP_FLAG); + + if (NT_SUCCESS(status)) + { + // now associate the two + status = NbtTdiAssociateConnection( + pLowerConn->pFileObject, + pLowerConn->AddrFileHandle); + + + if (NT_SUCCESS(status)) + { + CTEDetachFsp(Attached); + // + // put the lower connection on the Q of active lower connections for + // this device + // + ExInterlockedInsertTailList(&pDeviceContext->LowerConnection, + &pLowerConn->Linkage, + &pDeviceContext->SpinLock); + + return(status); + } + + ObDereferenceObject(pLowerConn->pAddrFileObject); + Locstatus = ZwClose(pLowerConn->AddrFileHandle); + + } + KdPrint(("Nbt:Open Xport Address Failed, status %X\n",status)); + + ObDereferenceObject(pLowerConn->pFileObject); + Locstatus = ZwClose(pLowerConn->FileHandle); + + } + + CTEDetachFsp(Attached); + + // Error Path... delete memory + // + pConnEle->pLowerConnId = NULL; + CTEMemFree((PVOID)pLowerConn); + + return(status); + +} + +//---------------------------------------------------------------------------- + +NTSTATUS +NbtTdiCloseConnection( + IN tLOWERCONNECTION * pLowerConn + ) +/*++ + +Routine Description: + + This routine closes a TDI connection + +Arguments: + + +Return Value: + + Status of the operation. + +--*/ +{ + NTSTATUS status; + BOOLEAN Attached= FALSE; + + CTEPagedCode(); + ASSERT( pLowerConn != NULL ) ; + + CTEAttachFsp(&Attached); + + if (pLowerConn->FileHandle) { + status = ZwClose(pLowerConn->FileHandle); + pLowerConn->FileHandle = NULL; + } + +#if DBG + if (!NT_SUCCESS(status)) + KdPrint(("Nbt:Failed to close Connection FileHandle pLower %X, status %X\n",pLowerConn,status)); +#endif + + CTEDetachFsp(Attached); + + 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); + + status = ZwClose(pLowerConn->AddrFileHandle); +#if DBG + if (!NT_SUCCESS(status)) + KdPrint(("Nbt:Failed to close Address FileHandle pLower %X,status %X\n",pLowerConn,status)); +#endif + + CTEDetachFsp(Attached); + + return(status); + +} |