From 117c56eef3b18be363212ef72e47be5d924be086 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 2 Dec 2009 23:57:57 +0000 Subject: [PATCH] - Implement IOCTL_AFD_GET_CONNECT_DATA, IOCTL_AFD_SET_CONNECT_DATA, IOCTL_AFD_SET_CONNECT_DATA_SIZE, IOCTL_AFD_GET_DISCONNECT_DATA, IOCTL_AFD_SET_DISCONNECT_DATA, IOCTL_AFD_SET_DISCONNECT_DATA_SIZE, IOCTL_AFD_SET_CONNECT_OPTIONS, IOCTL_AFD_GET_CONNECT_OPTIONS, IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE, IOCTL_AFD_SET_DISCONNECT_OPTIONS, IOCTL_AFD_GET_DISCONNECT_OPTIONS, IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE - Check that the socket allows connections in AfdDisconnect and AfdStreamSocketConnect - Allocate the receive window in connectionless sockets when the socket is bound instead of at FCB creation - Remove a horrible hack in UnlockRequest - Remove an incorrect call to MmUnmapLockedPages (the pages aren't mapped!) - Replace the recursive mutex with a KMUTEX for now (eventually I want to move to a fast mutex) - Fix a leak in LockRequest in failure case svn path=/branches/aicom-network-branch/; revision=44370 --- drivers/network/afd/afd/bind.c | 25 +- drivers/network/afd/afd/connect.c | 224 ++++++++++++++- drivers/network/afd/afd/listen.c | 3 + drivers/network/afd/afd/lock.c | 87 +----- drivers/network/afd/afd/main.c | 360 ++++++++++++++++++------ drivers/network/afd/afd/tdi.c | 7 +- drivers/network/afd/include/afd.h | 40 ++- drivers/network/afd/include/tdi_proto.h | 3 +- 8 files changed, 555 insertions(+), 194 deletions(-) diff --git a/drivers/network/afd/afd/bind.c b/drivers/network/afd/afd/bind.c index 1b5072f6e43..d7504b8ca65 100644 --- a/drivers/network/afd/afd/bind.c +++ b/drivers/network/afd/afd/bind.c @@ -57,24 +57,22 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->LocalAddress = TaCopyTransportAddress( &BindReq->Address ); if( FCB->LocalAddress ) - Status = WarmSocketForBind( FCB ); - else Status = STATUS_NO_MEMORY; - - if( NT_SUCCESS(Status) ) - FCB->State = SOCKET_STATE_BOUND; - else return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - - AFD_DbgPrint(MID_TRACE,("FCB->Flags %x\n", FCB->Flags)); - - if( FCB->Flags & SGID_CONNECTIONLESS ) { - /* This will be the from address for subsequent recvfrom calls */ TdiBuildConnectionInfo( &FCB->AddressFrom, FCB->LocalAddress ); - if( !FCB->AddressFrom ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); + if( FCB->AddressFrom ) + Status = WarmSocketForBind( FCB ); + else return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + AFD_DbgPrint(MID_TRACE,("FCB->Flags %x\n", FCB->Flags)); + + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { AFD_DbgPrint(MID_TRACE,("Calling TdiReceiveDatagram\n")); + FCB->Recv.Window = ExAllocatePool(PagedPool, FCB->Recv.Size); + if (!FCB->Recv.Window) + return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + Status = TdiReceiveDatagram ( &FCB->ReceiveIrp.InFlightRequest, FCB->AddressFile.Object, @@ -90,6 +88,9 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; } + if (NT_SUCCESS(Status)) + FCB->State = SOCKET_STATE_BOUND; + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } diff --git a/drivers/network/afd/afd/connect.c b/drivers/network/afd/afd/connect.c index 9b0beebbb0a..1da57e2ac4b 100644 --- a/drivers/network/afd/afd/connect.c +++ b/drivers/network/afd/afd/connect.c @@ -12,6 +12,179 @@ #include "tdiconn.h" #include "debug.h" +NTSTATUS NTAPI +AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->ConnectOptionsSize == 0) + return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + + ASSERT(FCB->ConnectOptions); + + if (FCB->FilledConnectOptions < BufferSize) BufferSize = FCB->FilledConnectOptions; + + RtlCopyMemory(Irp->UserBuffer, + FCB->ConnectOptions, + BufferSize); + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); +} + +NTSTATUS +NTAPI +AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PVOID ConnectOptions = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT ConnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->ConnectOptions) + { + ExFreePool(FCB->ConnectOptions); + FCB->ConnectOptions = NULL; + FCB->ConnectOptionsSize = 0; + FCB->FilledConnectOptions = 0; + } + + FCB->ConnectOptions = ExAllocatePool(PagedPool, ConnectOptionsSize); + if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + RtlCopyMemory(FCB->ConnectOptions, + ConnectOptions, + ConnectOptionsSize); + + FCB->ConnectOptionsSize = ConnectOptionsSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS +NTAPI +AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PUINT ConnectOptionsSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (BufferSize < sizeof(UINT)) + return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + + if (FCB->ConnectOptions) + { + ExFreePool(FCB->ConnectOptions); + FCB->ConnectOptionsSize = 0; + FCB->FilledConnectOptions = 0; + } + + FCB->ConnectOptions = ExAllocatePool(PagedPool, *ConnectOptionsSize); + if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + FCB->ConnectOptionsSize = *ConnectOptionsSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS NTAPI +AfdGetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->ConnectDataSize == 0) + return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + + ASSERT(FCB->ConnectData); + + if (FCB->FilledConnectData < BufferSize) BufferSize = FCB->FilledConnectData; + + RtlCopyMemory(Irp->UserBuffer, + FCB->ConnectData, + BufferSize); + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); +} + +NTSTATUS +NTAPI +AfdSetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PVOID ConnectData = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT ConnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->ConnectData) + { + ExFreePool(FCB->ConnectData); + FCB->ConnectData = NULL; + FCB->ConnectDataSize = 0; + FCB->FilledConnectData = 0; + } + + FCB->ConnectData = ExAllocatePool(PagedPool, ConnectDataSize); + if (!FCB->ConnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + RtlCopyMemory(FCB->ConnectData, + ConnectData, + ConnectDataSize); + + FCB->ConnectDataSize = ConnectDataSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS +NTAPI +AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PUINT ConnectDataSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (BufferSize < sizeof(UINT)) + return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + + if (FCB->ConnectData) + { + ExFreePool(FCB->ConnectData); + FCB->ConnectDataSize = 0; + FCB->FilledConnectData = 0; + } + + FCB->ConnectData = ExAllocatePool(PagedPool, *ConnectDataSize); + if (!FCB->ConnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + FCB->ConnectDataSize = *ConnectDataSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + + NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) { NTSTATUS Status; @@ -35,6 +208,9 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) { NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) { NTSTATUS Status; + ASSERT(!FCB->Recv.Window); + ASSERT(!FCB->Send.Window); + /* Allocate the receive area and start receiving */ FCB->Recv.Window = ExAllocatePool( PagedPool, FCB->Recv.Size ); @@ -133,6 +309,22 @@ static NTSTATUS NTAPI StreamSocketConnectComplete return Status; } + FCB->FilledConnectData = MIN(FCB->ConnectInfo->UserDataLength, FCB->ConnectDataSize); + if (FCB->FilledConnectData) + { + RtlCopyMemory(FCB->ConnectData, + FCB->ConnectInfo->UserData, + FCB->FilledConnectData); + } + + FCB->FilledConnectOptions = MIN(FCB->ConnectInfo->OptionsLength, FCB->ConnectOptionsSize); + if (FCB->FilledConnectOptions) + { + RtlCopyMemory(FCB->ConnectOptions, + FCB->ConnectInfo->Options, + FCB->FilledConnectOptions); + } + if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, @@ -162,10 +354,10 @@ NTSTATUS NTAPI AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { NTSTATUS Status = STATUS_INVALID_PARAMETER; - PTDI_CONNECTION_INFORMATION TargetAddress; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_CONNECT_INFO ConnectReq; + PTDI_CONNECTION_INFORMATION TargetAddress; AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); @@ -180,6 +372,9 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, IrpSp->Parameters.DeviceIoControl.InputBufferLength ); #endif + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) + return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + switch( FCB->State ) { case SOCKET_STATE_CONNECTED: Status = STATUS_SUCCESS; @@ -216,37 +411,42 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, break; } - if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) - { - Status = STATUS_SUCCESS; - break; - } - Status = WarmSocketForConnection( FCB ); if( !NT_SUCCESS(Status) ) break; - FCB->State = SOCKET_STATE_CONNECTING; - TdiBuildConnectionInfo - ( &TargetAddress, + ( &FCB->ConnectInfo, &ConnectReq->RemoteAddress ); + if( FCB->ConnectInfo ) + TdiBuildConnectionInfo(&TargetAddress, + &ConnectReq->RemoteAddress); + + if( TargetAddress ) { + TargetAddress->UserData = FCB->ConnectData; + TargetAddress->UserDataLength = FCB->ConnectDataSize; + TargetAddress->Options = FCB->ConnectOptions; + TargetAddress->OptionsLength = FCB->ConnectOptionsSize; + Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, FCB->Connection.Object, TargetAddress, + FCB->ConnectInfo, &FCB->ConnectIrp.Iosb, StreamSocketConnectComplete, FCB ); - ExFreePool( TargetAddress ); + ExFreePool(TargetAddress); AFD_DbgPrint(MID_TRACE,("Queueing IRP %x\n", Irp)); - if( Status == STATUS_PENDING ) + if( Status == STATUS_PENDING ) { + FCB->State = SOCKET_STATE_CONNECTING; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT ); + } } else Status = STATUS_NO_MEMORY; break; diff --git a/drivers/network/afd/afd/listen.c b/drivers/network/afd/afd/listen.c index 65c49eba842..d16550e47e4 100644 --- a/drivers/network/afd/afd/listen.c +++ b/drivers/network/afd/afd/listen.c @@ -36,6 +36,9 @@ static NTSTATUS SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt, else Status = MakeSocketIntoConnection( FCB ); + if (NT_SUCCESS(Status)) + Status = TdiBuildConnectionInfo(&FCB->ConnectInfo, FCB->RemoteAddress); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } diff --git a/drivers/network/afd/afd/lock.c b/drivers/network/afd/afd/lock.c index bdfc20ef7d7..7605f8d0774 100644 --- a/drivers/network/afd/afd/lock.c +++ b/drivers/network/afd/afd/lock.c @@ -40,6 +40,7 @@ PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority ); if( !IrpSp->Parameters.DeviceIoControl.Type3InputBuffer ) { + MmUnlockPages( Irp->MdlAddress ); IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; return NULL; @@ -49,14 +50,10 @@ PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { } else return NULL; } -VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { - PVOID Buffer = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority ); - if( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer == Buffer || Buffer == NULL ) { - MmUnmapLockedPages( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer, Irp->MdlAddress ); - MmUnlockPages( Irp->MdlAddress ); - IoFreeMdl( Irp->MdlAddress ); - } - +VOID UnlockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) +{ + MmUnlockPages( Irp->MdlAddress ); + IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; } @@ -213,78 +210,18 @@ VOID UnlockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) { HandleArray = NULL; } -/* Returns transitioned state or SOCKET_STATE_INVALID_TRANSITION */ -UINT SocketAcquireStateLock( PAFD_FCB FCB ) { - NTSTATUS Status = STATUS_SUCCESS; - PVOID CurrentThread = KeGetCurrentThread(); - - ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - - AFD_DbgPrint(MAX_TRACE,("Called on %x, attempting to lock\n", FCB)); - - /* Wait for the previous user to unlock the FCB state. There might be - * multiple waiters waiting to change the state. We need to check each - * time we get the event whether somebody still has the state locked */ - +BOOLEAN SocketAcquireStateLock( PAFD_FCB FCB ) { if( !FCB ) return FALSE; - if( CurrentThread == FCB->CurrentThread ) { - FCB->LockCount++; - AFD_DbgPrint(MID_TRACE, - ("Same thread, lock count %d\n", FCB->LockCount)); - return TRUE; - } else { - AFD_DbgPrint(MID_TRACE, - ("Thread %x opposes lock thread %x\n", - CurrentThread, FCB->CurrentThread)); - } - - - ExAcquireFastMutex( &FCB->Mutex ); - - while( FCB->Locked ) { - AFD_DbgPrint - (MID_TRACE,("FCB %x is locked, waiting for notification\n", - FCB)); - ExReleaseFastMutex( &FCB->Mutex ); - Status = KeWaitForSingleObject( &FCB->StateLockedEvent, - UserRequest, - KernelMode, - FALSE, - NULL ); - ExAcquireFastMutex( &FCB->Mutex ); - } - FCB->Locked = TRUE; - FCB->CurrentThread = CurrentThread; - FCB->LockCount++; - ExReleaseFastMutex( &FCB->Mutex ); - - AFD_DbgPrint(MAX_TRACE,("Got lock (%d).\n", FCB->LockCount)); - - return TRUE; + return !KeWaitForMutexObject(&FCB->Mutex, + Executive, + KernelMode, + FALSE, + NULL); } VOID SocketStateUnlock( PAFD_FCB FCB ) { -#if DBG - PVOID CurrentThread = KeGetCurrentThread(); -#endif - ASSERT(FCB->LockCount > 0); - ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - - ExAcquireFastMutex( &FCB->Mutex ); - FCB->LockCount--; - - if( !FCB->LockCount ) { - FCB->CurrentThread = NULL; - FCB->Locked = FALSE; - - AFD_DbgPrint(MAX_TRACE,("Unlocked.\n")); - KePulseEvent( &FCB->StateLockedEvent, IO_NETWORK_INCREMENT, FALSE ); - } else { - AFD_DbgPrint(MAX_TRACE,("New lock count: %d (Thr: %x)\n", - FCB->LockCount, CurrentThread)); - } - ExReleaseFastMutex( &FCB->Mutex ); + KeReleaseMutex(&FCB->Mutex, FALSE); } NTSTATUS NTAPI UnlockAndMaybeComplete diff --git a/drivers/network/afd/afd/main.c b/drivers/network/afd/afd/main.c index fb4fc91d67b..10ebe9a5ae5 100644 --- a/drivers/network/afd/afd/main.c +++ b/drivers/network/afd/afd/main.c @@ -41,6 +41,178 @@ void OskitDumpBuffer( PCHAR Data, UINT Len ) { NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +NTSTATUS NTAPI +AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->DisconnectOptionsSize == 0) + return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + + ASSERT(FCB->DisconnectOptions); + + if (FCB->FilledDisconnectOptions < BufferSize) BufferSize = FCB->FilledDisconnectOptions; + + RtlCopyMemory(Irp->UserBuffer, + FCB->DisconnectOptions, + BufferSize); + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); +} + +NTSTATUS +NTAPI +AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PVOID DisconnectOptions = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->DisconnectOptions) + { + ExFreePool(FCB->DisconnectOptions); + FCB->DisconnectOptions = NULL; + FCB->DisconnectOptionsSize = 0; + FCB->FilledDisconnectOptions = 0; + } + + FCB->DisconnectOptions = ExAllocatePool(PagedPool, DisconnectOptionsSize); + if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + RtlCopyMemory(FCB->DisconnectOptions, + DisconnectOptions, + DisconnectOptionsSize); + + FCB->DisconnectOptionsSize = DisconnectOptionsSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS +NTAPI +AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PUINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (BufferSize < sizeof(UINT)) + return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + + if (FCB->DisconnectOptions) + { + ExFreePool(FCB->DisconnectOptions); + FCB->DisconnectOptionsSize = 0; + FCB->FilledDisconnectOptions = 0; + } + + FCB->DisconnectOptions = ExAllocatePool(PagedPool, *DisconnectOptionsSize); + if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + FCB->DisconnectOptionsSize = *DisconnectOptionsSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS NTAPI +AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->DisconnectDataSize == 0) + return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + + ASSERT(FCB->DisconnectData); + + if (FCB->FilledDisconnectData < BufferSize) BufferSize = FCB->FilledDisconnectData; + + RtlCopyMemory(Irp->UserBuffer, + FCB->DisconnectData, + BufferSize); + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize); +} + +NTSTATUS +NTAPI +AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PVOID DisconnectData = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (FCB->DisconnectData) + { + ExFreePool(FCB->DisconnectData); + FCB->DisconnectData = NULL; + FCB->DisconnectDataSize = 0; + FCB->FilledDisconnectData = 0; + } + + FCB->DisconnectData = ExAllocatePool(PagedPool, DisconnectDataSize); + if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + RtlCopyMemory(FCB->DisconnectData, + DisconnectData, + DisconnectDataSize); + + FCB->DisconnectDataSize = DisconnectDataSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + +NTSTATUS +NTAPI +AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PUINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (BufferSize < sizeof(UINT)) + return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + + if (FCB->DisconnectData) + { + ExFreePool(FCB->DisconnectData); + FCB->DisconnectDataSize = 0; + FCB->FilledDisconnectData = 0; + } + + FCB->DisconnectData = ExAllocatePool(PagedPool, *DisconnectDataSize); + if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + + FCB->DisconnectDataSize = *DisconnectDataSize; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + static NTSTATUS NTAPI AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -101,9 +273,7 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->AddressFile.Handle = INVALID_HANDLE_VALUE; FCB->Connection.Handle = INVALID_HANDLE_VALUE; - KeInitializeSpinLock( &FCB->SpinLock ); - ExInitializeFastMutex( &FCB->Mutex ); - KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE ); + KeInitializeMutex( &FCB->Mutex, 0 ); for( i = 0; i < MAX_FUNCTIONS; i++ ) { InitializeListHead( &FCB->PendingIrpList[i] ); @@ -141,22 +311,15 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FileObject->FsContext = FCB; /* It seems that UDP sockets are writable from inception */ - if( FCB->Flags & SGID_CONNECTIONLESS ) { + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n")); - /* Allocate our backup buffer */ - FCB->Recv.Window = ExAllocatePool( PagedPool, FCB->Recv.Size ); - if( !FCB->Recv.Window ) Status = STATUS_NO_MEMORY; - if( NT_SUCCESS(Status) ) + FCB->Send.Window = ExAllocatePool( PagedPool, FCB->Send.Size ); + if (FCB->Send.Window) { - FCB->Send.Window = ExAllocatePool( PagedPool, FCB->Send.Size ); - if( !FCB->Send.Window ) { - if( FCB->Recv.Window ) ExFreePool( FCB->Recv.Window ); - Status = STATUS_NO_MEMORY; - } - } - /* A datagram socket is always sendable */ - FCB->PollState |= AFD_EVENT_SEND; - PollReeval( FCB->DeviceExt, FCB->FileObject ); + /* A datagram socket is always sendable */ + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } else Status = STATUS_NO_MEMORY; } if( !NT_SUCCESS(Status) ) { @@ -254,6 +417,21 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( FCB->AddressFrom ) ExFreePool( FCB->AddressFrom ); + if( FCB->ConnectInfo ) + ExFreePool( FCB->ConnectInfo ); + + if( FCB->ConnectData ) + ExFreePool( FCB->ConnectData ); + + if( FCB->DisconnectData ) + ExFreePool( FCB->DisconnectData ); + + if( FCB->ConnectOptions ) + ExFreePool( FCB->ConnectOptions ); + + if( FCB->DisconnectOptions ) + ExFreePool( FCB->DisconnectOptions ); + if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); @@ -303,8 +481,8 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_FCB FCB = FileObject->FsContext; PAFD_DISCONNECT_INFO DisReq; IO_STATUS_BLOCK Iosb; - PTDI_CONNECTION_INFORMATION ConnInfo; - NTSTATUS Status; + PTDI_CONNECTION_INFORMATION ConnectionReturnInfo; + NTSTATUS Status = STATUS_SUCCESS; USHORT Flags = 0; if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); @@ -313,39 +491,65 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); - if (NULL == FCB->RemoteAddress) - { - ConnInfo = NULL; - } - else - { - Status = TdiBuildNullConnectionInfo - ( &ConnInfo, FCB->RemoteAddress->Address[0].AddressType ); + if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) + { + if( !FCB->ConnectInfo ) + return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, + Irp, 0 ); - if( !NT_SUCCESS(Status) || !ConnInfo ) + ASSERT(FCB->RemoteAddress); + + Status = TdiBuildNullConnectionInfo + ( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType ); + + if( !NT_SUCCESS(Status) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, - Irp, 0 ); - } + Irp, 0 ); - if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) - Flags |= TDI_DISCONNECT_RELEASE; - if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || - DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) - Flags |= TDI_DISCONNECT_ABORT; + if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) + Flags |= TDI_DISCONNECT_RELEASE; + if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || + DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) + Flags |= TDI_DISCONNECT_ABORT; - Status = TdiDisconnect( FCB->Connection.Object, - &DisReq->Timeout, - Flags, - &Iosb, - NULL, - NULL, - FCB->AddressFrom, - ConnInfo); + FCB->ConnectInfo->UserData = FCB->DisconnectData; + FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize; + FCB->ConnectInfo->Options = FCB->DisconnectOptions; + FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize; - if (ConnInfo) ExFreePool( ConnInfo ); + Status = TdiDisconnect( FCB->Connection.Object, + &DisReq->Timeout, + Flags, + &Iosb, + NULL, + NULL, + FCB->ConnectInfo, + ConnectionReturnInfo); - FCB->PollState |= AFD_EVENT_DISCONNECT; - PollReeval( FCB->DeviceExt, FCB->FileObject ); + if (NT_SUCCESS(Status)) { + FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength); + if (FCB->FilledDisconnectData) + { + RtlCopyMemory(FCB->DisconnectData, + ConnectionReturnInfo->UserData, + FCB->FilledDisconnectData); + } + + FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength); + if (FCB->FilledDisconnectOptions) + { + RtlCopyMemory(FCB->DisconnectOptions, + ConnectionReturnInfo->Options, + FCB->FilledDisconnectOptions); + } + } + + ExFreePool( ConnectionReturnInfo ); + + FCB->PollState |= AFD_EVENT_DISCONNECT; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } else + Status = STATUS_INVALID_PARAMETER; return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } @@ -455,56 +659,44 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) case IOCTL_AFD_GET_PEER_NAME: return AfdGetPeerName( DeviceObject, Irp, IrpSp ); - case IOCTL_AFD_GET_TDI_HANDLES: - DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n"); - break; + case IOCTL_AFD_GET_CONNECT_DATA: + return AfdGetConnectData(DeviceObject, Irp, IrpSp); case IOCTL_AFD_SET_CONNECT_DATA: - DbgPrint("IOCTL_AFD_SET_CONNECT_DATA is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_SET_CONNECT_OPTIONS: - DbgPrint("IOCTL_AFD_SET_CONNECT_OPTIONS is UNIMPLEMENTED!\n"); - break; + return AfdSetConnectData(DeviceObject, Irp, IrpSp); case IOCTL_AFD_SET_DISCONNECT_DATA: - DbgPrint("IOCTL_AFD_SET_DISCONNECT_DATA is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_SET_DISCONNECT_OPTIONS: - DbgPrint("IOCTL_AFD_SET_DISCONNECT_OPTIONS is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_GET_CONNECT_DATA: - DbgPrint("IOCTL_AFD_GET_CONNECT_DATA is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_GET_CONNECT_OPTIONS: - DbgPrint("IOCTL_AFD_GET_CONNECT_OPTIONS is UNIMPLEMENTED!\n"); - break; + return AfdSetDisconnectData(DeviceObject, Irp, IrpSp); case IOCTL_AFD_GET_DISCONNECT_DATA: - DbgPrint("IOCTL_AFD_GET_DISCONNECT_DATA is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_GET_DISCONNECT_OPTIONS: - DbgPrint("IOCTL_AFD_GET_DISCONNECT_OPTIONS is UNIMPLEMENTED!\n"); - break; + return AfdGetDisconnectData(DeviceObject, Irp, IrpSp); case IOCTL_AFD_SET_CONNECT_DATA_SIZE: - DbgPrint("IOCTL_AFD_SET_CONNECT_DATA_SIZE is UNIMPLEMENTED!\n"); - break; - - case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE: - DbgPrint("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE is UNIMPLEMENTED!\n"); - break; + return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp); case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE: - DbgPrint("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE is UNIMPLEMENTED!\n"); - break; + return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_SET_CONNECT_OPTIONS: + return AfdSetConnectOptions(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_SET_DISCONNECT_OPTIONS: + return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_GET_CONNECT_OPTIONS: + return AfdGetConnectOptions(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_GET_DISCONNECT_OPTIONS: + return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE: + return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp); case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE: - DbgPrint("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE is UNIMPLEMENTED!\n"); + return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp); + + case IOCTL_AFD_GET_TDI_HANDLES: + DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n"); break; case IOCTL_AFD_DEFER_ACCEPT: diff --git a/drivers/network/afd/afd/tdi.c b/drivers/network/afd/afd/tdi.c index 4516e2cf2da..7367e55c7fa 100644 --- a/drivers/network/afd/afd/tdi.c +++ b/drivers/network/afd/afd/tdi.c @@ -260,7 +260,8 @@ NTSTATUS TdiOpenConnectionEndpointFile( NTSTATUS TdiConnect( PIRP *Irp, PFILE_OBJECT ConnectionObject, - PTDI_CONNECTION_INFORMATION RemoteAddress, + PTDI_CONNECTION_INFORMATION ConnectionCallInfo, + PTDI_CONNECTION_INFORMATION ConnectionReturnInfo, PIO_STATUS_BLOCK Iosb, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext) @@ -306,8 +307,8 @@ NTSTATUS TdiConnect( CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion routine context */ NULL, /* Time */ - RemoteAddress, /* Request connection information */ - RemoteAddress); /* Return connection information */ + ConnectionCallInfo, /* Request connection information */ + ConnectionReturnInfo); /* Return connection information */ Status = TdiCall(*Irp, DeviceObject, NULL, Iosb); diff --git a/drivers/network/afd/include/afd.h b/drivers/network/afd/include/afd.h index d75b147bb77..c16afb6e7d3 100644 --- a/drivers/network/afd/include/afd.h +++ b/drivers/network/afd/include/afd.h @@ -111,8 +111,6 @@ typedef struct IPADDR_ENTRY { #define DEFAULT_SEND_WINDOW_SIZE 16384 #define DEFAULT_RECEIVE_WINDOW_SIZE 16384 -#define SGID_CONNECTIONLESS 1 /* XXX Find this flag */ - /* XXX This is a hack we should clean up later * We do this in order to get some storage for the locked handle table * Maybe I'll use some tail item in the irp instead */ @@ -182,24 +180,34 @@ typedef struct _AFD_FCB { KIRQL OldIrql; UINT LockCount; PVOID CurrentThread; - KSPIN_LOCK SpinLock; PFILE_OBJECT FileObject; PAFD_DEVICE_EXTENSION DeviceExt; BOOLEAN DelayedAccept, NeedsNewListen; UINT ConnSeq; PTRANSPORT_ADDRESS LocalAddress, RemoteAddress; - PTDI_CONNECTION_INFORMATION AddressFrom; + PTDI_CONNECTION_INFORMATION AddressFrom, ConnectInfo; AFD_TDI_OBJECT AddressFile, Connection; AFD_IN_FLIGHT_REQUEST ConnectIrp, ListenIrp, ReceiveIrp, SendIrp; AFD_DATA_WINDOW Send, Recv; - FAST_MUTEX Mutex; - KEVENT StateLockedEvent; + KMUTEX Mutex; PKEVENT EventSelect; DWORD EventSelectTriggers; UNICODE_STRING TdiDeviceName; PVOID Context; DWORD PollState; UINT ContextSize; + PVOID ConnectData; + UINT FilledConnectData; + UINT ConnectDataSize; + PVOID DisconnectData; + UINT FilledDisconnectData; + UINT DisconnectDataSize; + PVOID ConnectOptions; + UINT FilledConnectOptions; + UINT ConnectOptionsSize; + PVOID DisconnectOptions; + UINT FilledDisconnectOptions; + UINT DisconnectOptionsSize; LIST_ENTRY PendingIrpList[MAX_FUNCTIONS]; LIST_ENTRY DatagramList; LIST_ENTRY PendingConnections; @@ -219,6 +227,24 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ); NTSTATUS NTAPI AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdGetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdSetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); +NTSTATUS NTAPI +AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp); /* context.c */ @@ -266,7 +292,7 @@ PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, PVOID AddressBuf, PINT AddressLen, BOOLEAN Write, BOOLEAN LockAddress ); VOID UnlockBuffers( PAFD_WSABUF Buf, UINT Count, BOOL Address ); -UINT SocketAcquireStateLock( PAFD_FCB FCB ); +BOOLEAN SocketAcquireStateLock( PAFD_FCB FCB ); NTSTATUS NTAPI UnlockAndMaybeComplete ( PAFD_FCB FCB, NTSTATUS Status, PIRP Irp, UINT Information ); diff --git a/drivers/network/afd/include/tdi_proto.h b/drivers/network/afd/include/tdi_proto.h index aa029e25f7f..93354baef25 100644 --- a/drivers/network/afd/include/tdi_proto.h +++ b/drivers/network/afd/include/tdi_proto.h @@ -3,7 +3,8 @@ NTSTATUS TdiConnect( PIRP *PendingIrp, PFILE_OBJECT ConnectionObject, - PTDI_CONNECTION_INFORMATION RemoteAddress, + PTDI_CONNECTION_INFORMATION ConnectionCallInfo, + PTDI_CONNECTION_INFORMATION ConnectionReturnInfo, PIO_STATUS_BLOCK Iosb, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext );