- 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
This commit is contained in:
Cameron Gutman 2009-12-02 23:57:57 +00:00
parent cf3234d59c
commit 117c56eef3
8 changed files with 555 additions and 194 deletions

View file

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

View file

@ -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;

View file

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

View file

@ -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

View file

@ -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:

View file

@ -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);

View file

@ -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 );

View file

@ -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 );