#include "tdiconn.h"
#include "debug.h"
-static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
- UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
-
- return !BytesAvailable &&
- (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
-}
-
-static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, UINT Information ) {
- if( !NT_SUCCESS(Status) ||
- (Status == STATUS_SUCCESS && Information == 0) ) {
- AFD_DbgPrint(MID_TRACE,("Looks like an EOF\n"));
- FCB->PollState |= AFD_EVENT_DISCONNECT;
+static NTSTATUS RefillSocketBuffer( PAFD_FCB FCB ) {
+ NTSTATUS Status = STATUS_PENDING;
+
+ if( !FCB->ReceiveIrp.InFlightRequest ) {
+ AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
+
+ Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
+ FCB->Connection.Object,
+ TDI_RECEIVE_NORMAL,
+ FCB->Recv.Window,
+ FCB->Recv.Size,
+ &FCB->ReceiveIrp.Iosb,
+ ReceiveComplete,
+ FCB );
+
+ if( ( Status == STATUS_SUCCESS && !FCB->ReceiveIrp.Iosb.Information ) ||
+ ( !NT_SUCCESS( Status ) ) )
+ {
+ /* The socket has been closed */
+ FCB->PollState |= AFD_EVENT_DISCONNECT;
+ FCB->Overread = TRUE;
+ Status = STATUS_FILE_CLOSED;
+ }
+ else if( Status == STATUS_SUCCESS )
+ {
+ FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
+ FCB->PollState |= AFD_EVENT_RECEIVE;
+ }
PollReeval( FCB->DeviceExt, FCB->FileObject );
- }
+ }
+
+ return Status;
}
static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
BytesAvailable));
- if( CantReadMore(FCB) ) return STATUS_SUCCESS;
- if( !BytesAvailable ) return STATUS_PENDING;
+ if( FCB->Overread ) return STATUS_FILE_CLOSED;
+ if( !BytesAvailable ) {
+ FCB->Recv.Content = FCB->Recv.BytesUsed = 0;
+ Status = RefillSocketBuffer( FCB );
+ if ( Status != STATUS_SUCCESS )
+ return Status;
+
+ /* If RefillSocketBuffer returns STATUS_SUCCESS, we're good to go
+ * If RefillSocketBuffer returns STATUS_PENDING, then it's waiting on the transport for data
+ * If RefillSocketBuffer returns STATUS_FILE_CLOSED, then the connection was terminated
+ */
+
+ /* Recalculate BytesAvailable based on new data */
+ BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
+ ASSERT(BytesAvailable);
+ }
Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
if( FCB->Recv.BytesUsed == FCB->Recv.Content ) {
FCB->Recv.BytesUsed = FCB->Recv.Content = 0;
FCB->PollState &= ~AFD_EVENT_RECEIVE;
- PollReeval( FCB->DeviceExt, FCB->FileObject );
- if( !FCB->ReceiveIrp.InFlightRequest ) {
- AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
-
- Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
- FCB->Connection.Object,
- TDI_RECEIVE_NORMAL,
- FCB->Recv.Window,
- FCB->Recv.Size,
- &FCB->ReceiveIrp.Iosb,
- ReceiveComplete,
- FCB );
-
- if( Status == STATUS_SUCCESS )
- FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
- HandleEOFOnIrp( FCB, Status, FCB->ReceiveIrp.Iosb.Information );
- }
+ RefillSocketBuffer( FCB );
}
return STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
- if( CantReadMore( FCB ) ) {
- /* Success here means that we got an EOF. Complete a pending read
- * with zero bytes if we haven't yet overread, then kill the others.
- */
- while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
- NextIrpEntry =
- RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
- NextIrp =
- CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
- NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
- RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-
- AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
- TotalBytesCopied));
- UnlockBuffers( RecvReq->BufferArray,
- RecvReq->BufferCount, FALSE );
- Status = NextIrp->IoStatus.Status =
- FCB->Overread ? STATUS_END_OF_FILE : STATUS_SUCCESS;
- NextIrp->IoStatus.Information = 0;
- if( NextIrp == Irp ) RetStatus = Status;
- if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
- IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
- FCB->Overread = TRUE;
- //FCB->PollState |= AFD_EVENT_DISCONNECT;
- PollReeval( FCB->DeviceExt, FCB->FileObject );
- }
- } else {
- /* Kick the user that receive would be possible now */
- /* XXX Not implemented yet */
-
- AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
- FCB, FCB->Recv.Content));
- /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
-
- /* Try to clear some requests */
- while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
- NextIrpEntry =
- RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
- NextIrp =
- CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
- NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
- RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-
- AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
-
- Status = TryToSatisfyRecvRequestFromBuffer
- ( FCB, RecvReq, &TotalBytesCopied );
-
- if( Status == STATUS_PENDING ) {
- AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
- InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
- &NextIrp->Tail.Overlay.ListEntry);
- break;
- } else {
- AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
- TotalBytesCopied));
- UnlockBuffers( RecvReq->BufferArray,
- RecvReq->BufferCount, FALSE );
- NextIrp->IoStatus.Status = Status;
- NextIrp->IoStatus.Information = TotalBytesCopied;
- if( NextIrp == Irp ) {
- RetStatus = Status;
- RetBytesCopied = TotalBytesCopied;
- }
- if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
- IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
- }
+ /* Kick the user that receive would be possible now */
+ /* XXX Not implemented yet */
+
+ AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
+ FCB, FCB->Recv.Content));
+
+ /* Try to clear some requests */
+ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+ NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+ NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+ NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+ RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+
+ AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
+
+ Status = TryToSatisfyRecvRequestFromBuffer( FCB, RecvReq, &TotalBytesCopied );
+
+ if( Status == STATUS_PENDING ) {
+ AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
+ InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
+ &NextIrp->Tail.Overlay.ListEntry);
+ break;
+ } else {
+ AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
+ TotalBytesCopied));
+ UnlockBuffers( RecvReq->BufferArray,
+ RecvReq->BufferCount, FALSE );
+ NextIrp->IoStatus.Status = Status;
+ NextIrp->IoStatus.Information = TotalBytesCopied;
+ if( NextIrp == Irp ) {
+ RetStatus = Status;
+ RetBytesCopied = TotalBytesCopied;
}
+ if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+ (void)IoSetCancelRoutine(NextIrp, NULL);
+ IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+ }
}
- if( FCB->Recv.Content ) {
+ if( !FCB->Recv.Content ) {
FCB->PollState |= AFD_EVENT_RECEIVE;
} else
FCB->PollState &= ~AFD_EVENT_RECEIVE;
PIRP Irp,
PVOID Context ) {
PAFD_FCB FCB = (PAFD_FCB)Context;
+ PLIST_ENTRY NextIrpEntry;
+ PIRP NextIrp;
+ PAFD_RECV_INFO RecvReq;
+ PIO_STACK_LOCATION NextIrpSp;
AFD_DbgPrint(MID_TRACE,("Called\n"));
- ASSERT_IRQL(APC_LEVEL);
-
- if( !SocketAcquireStateLock( FCB ) ) {
- Irp->IoStatus.Status = STATUS_FILE_CLOSED;
- Irp->IoStatus.Information = 0;
+ if( !SocketAcquireStateLock( FCB ) )
return STATUS_FILE_CLOSED;
- }
FCB->ReceiveIrp.InFlightRequest = NULL;
- if( Irp->Cancel ) {
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- SocketStateUnlock( FCB );
- return STATUS_CANCELLED;
- }
-
FCB->Recv.Content = Irp->IoStatus.Information;
FCB->Recv.BytesUsed = 0;
if( FCB->State == SOCKET_STATE_CLOSED ) {
- AFD_DbgPrint(MIN_TRACE,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
- Irp->IoStatus.Status = STATUS_FILE_CLOSED;
- Irp->IoStatus.Information = 0;
- SocketStateUnlock( FCB );
- DestroySocket( FCB );
- return STATUS_FILE_CLOSED;
+ AFD_DbgPrint(MIN_TRACE,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
+ /* Cleanup our IRP queue because the FCB is being destroyed */
+ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+ NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+ NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+ NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
+ RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+ NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
+ NextIrp->IoStatus.Information = 0;
+ UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
+ if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+ (void)IoSetCancelRoutine(NextIrp, NULL);
+ IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+ }
+ SocketStateUnlock( FCB );
+ return STATUS_FILE_CLOSED;
} else if( FCB->State == SOCKET_STATE_LISTENING ) {
AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
SocketStateUnlock( FCB );
return STATUS_INVALID_PARAMETER;
}
- HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
-
ReceiveActivity( FCB, NULL );
-
- PollReeval( FCB->DeviceExt, FCB->FileObject );
SocketStateUnlock( FCB );
AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n",
FCB->State));
return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
- Irp, 0, NULL );
+ Irp, 0 );
}
if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
{
AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n"));
return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED,
- Irp, 0, NULL );
+ Irp, 0 );
}
- FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
- PollReeval( FCB->DeviceExt, FCB->FileObject );
-
if( !(RecvReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
- Irp, 0, NULL );
+ Irp, 0 );
AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
if( !RecvReq->BufferArray ) {
return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
- Irp, 0, NULL );
+ Irp, 0 );
}
Irp->IoStatus.Status = STATUS_PENDING;
Status = ReceiveActivity( FCB, Irp );
- if( Status == STATUS_PENDING && RecvReq->AfdFlags & AFD_IMMEDIATE ) {
+ if( Status == STATUS_PENDING && (RecvReq->AfdFlags & AFD_IMMEDIATE) ) {
AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
Status = STATUS_CANT_WAIT;
TotalBytesCopied = 0;
RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
return UnlockAndMaybeComplete( FCB, Status, Irp,
- TotalBytesCopied, NULL );
+ TotalBytesCopied );
} else if( Status == STATUS_PENDING ) {
AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
IoMarkIrpPending( Irp );
+ (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
} else {
AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
}
PAFD_RECV_INFO RecvReq;
PAFD_STORED_DATAGRAM DatagramRecv;
UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
+ PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
- if( !SocketAcquireStateLock( FCB ) ) {
- Irp->IoStatus.Status = STATUS_FILE_CLOSED;
- Irp->IoStatus.Information = 0;
+ if( !SocketAcquireStateLock( FCB ) )
return STATUS_FILE_CLOSED;
- }
FCB->ReceiveIrp.InFlightRequest = NULL;
- if( Irp->IoStatus.Status == STATUS_CANCELLED ) {
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- SocketStateUnlock( FCB );
- return STATUS_CANCELLED;
- }
-
if( FCB->State == SOCKET_STATE_CLOSED ) {
- Irp->IoStatus.Status = STATUS_FILE_CLOSED;
- Irp->IoStatus.Information = 0;
- SocketStateUnlock( FCB );
- DestroySocket( FCB );
- return STATUS_FILE_CLOSED;
+ /* Cleanup our IRP queue because the FCB is being destroyed */
+ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+ NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+ NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+ NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+ RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+ NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
+ NextIrp->IoStatus.Information = 0;
+ UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
+ if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+ (void)IoSetCancelRoutine(NextIrp, NULL);
+ IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+ }
+
+ /* Free all items on the datagram list */
+ while( !IsListEmpty( &FCB->DatagramList ) ) {
+ DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
+ DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
+ ExFreePool( DatagramRecv->Address );
+ ExFreePool( DatagramRecv );
+ }
+
+ SocketStateUnlock( FCB );
+ return STATUS_FILE_CLOSED;
}
DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
} else Status = STATUS_NO_MEMORY;
if( !NT_SUCCESS( Status ) ) {
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
if( DatagramRecv ) ExFreePool( DatagramRecv );
SocketStateUnlock( FCB );
return Status;
NextIrp->IoStatus.Information = DatagramRecv->Len;
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+ (void)IoSetCancelRoutine(NextIrp, NULL);
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
} else {
AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
AFD_DbgPrint(MID_TRACE,("Completing\n"));
+ (void)IoSetCancelRoutine(NextIrp, NULL);
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
}
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
- FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
-
/* Check that the socket is bound */
if( FCB->State != SOCKET_STATE_BOUND )
return UnlockAndMaybeComplete
- ( FCB, STATUS_INVALID_PARAMETER, Irp, 0, NULL );
+ ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
if( !(RecvReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete
- ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL );
+ ( FCB, STATUS_NO_MEMORY, Irp, 0 );
AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
if( !RecvReq->BufferArray ) { /* access violation in userspace */
return UnlockAndMaybeComplete
- ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0, NULL );
+ ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 );
}
if( !IsListEmpty( &FCB->DatagramList ) ) {
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
return UnlockAndMaybeComplete
- ( FCB, Status, Irp, Irp->IoStatus.Information, NULL );
+ ( FCB, Status, Irp, Irp->IoStatus.Information );
} else {
Status = SatisfyPacketRecvRequest
( FCB, Irp, DatagramRecv,
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
return UnlockAndMaybeComplete
- ( FCB, Status, Irp, Irp->IoStatus.Information, NULL );
+ ( FCB, Status, Irp, Irp->IoStatus.Information );
}
} else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
Status = STATUS_CANT_WAIT;
+ FCB->PollState &= ~AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
- return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
+ return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
} else {
+ FCB->PollState &= ~AFD_EVENT_RECEIVE;
PollReeval( FCB->DeviceExt, FCB->FileObject );
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
}