diff --git a/reactos/drivers/network/afd/afd/listen.c b/reactos/drivers/network/afd/afd/listen.c index ce1ceaf7b8d..9a429991fa8 100644 --- a/reactos/drivers/network/afd/afd/listen.c +++ b/reactos/drivers/network/afd/afd/listen.c @@ -367,13 +367,16 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); ExFreePool( PendingConnObj ); + + FCB->EventSelectDisabled &= ~AFD_EVENT_ACCEPT; - if( !IsListEmpty( &FCB->PendingConnections ) ) { - FCB->PollState |= AFD_EVENT_ACCEPT; - FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; + if( !IsListEmpty( &FCB->PendingConnections ) ) + { + FCB->PollState |= AFD_EVENT_ACCEPT; + FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_ACCEPT; + } else + FCB->PollState &= ~AFD_EVENT_ACCEPT; SocketStateUnlock( FCB ); return Status; diff --git a/reactos/drivers/network/afd/afd/read.c b/reactos/drivers/network/afd/afd/read.c index c6f12e6b1e7..10f947f0743 100644 --- a/reactos/drivers/network/afd/afd/read.c +++ b/reactos/drivers/network/afd/afd/read.c @@ -408,9 +408,19 @@ SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, *TotalBytesCopied = BytesToCopy; } - - Status = Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = BytesToCopy; + + if (*TotalBytesCopied == DatagramRecv->Len) + { + /* We copied the whole datagram */ + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + /* We only copied part of the datagram */ + Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + } + + Irp->IoStatus.Information = *TotalBytesCopied; if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) { @@ -464,62 +474,46 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Irp, 0 ); } + FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { - if( !IsListEmpty( &FCB->DatagramList ) ) { - ListEntry = RemoveHeadList( &FCB->DatagramList ); - DatagramRecv = CONTAINING_RECORD - ( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = DatagramRecv->Len; - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); - - AFD_DbgPrint(MIN_TRACE,("Partial datagram not read\n")); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } else { - Status = SatisfyPacketRecvRequest - ( FCB, Irp, DatagramRecv, - (PUINT)&Irp->IoStatus.Information ); - - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); + if (!IsListEmpty(&FCB->DatagramList)) + { + ListEntry = RemoveHeadList(&FCB->DatagramList); + DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); + Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, + (PUINT)&Irp->IoStatus.Information); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); } - } else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { + + if (IsListEmpty(&FCB->DatagramList)) + { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); + + return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); + } + else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) + { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); Status = STATUS_CANT_WAIT; FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } else { + } + else + { FCB->PollState &= ~AFD_EVENT_RECEIVE; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } @@ -652,34 +646,26 @@ PacketSocketRecvComplete( AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n", RecvReq, DatagramRecv)); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - NextIrp->IoStatus.Information = DatagramRecv->Len; - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); - if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); - (void)IoSetCancelRoutine(NextIrp, NULL); - AFD_DbgPrint(MIN_TRACE,("Partial datagram failed\n")); - IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); - } else { - AFD_DbgPrint(MID_TRACE,("Satisfying\n")); - Status = SatisfyPacketRecvRequest - ( FCB, NextIrp, DatagramRecv, - (PUINT)&NextIrp->IoStatus.Information ); - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - AFD_DbgPrint(MID_TRACE,("Unlocking\n")); - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); - if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); - AFD_DbgPrint(MID_TRACE,("Completing\n")); - (void)IoSetCancelRoutine(NextIrp, NULL); - IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); - } + AFD_DbgPrint(MID_TRACE,("Satisfying\n")); + Status = SatisfyPacketRecvRequest + ( FCB, NextIrp, DatagramRecv, + (PUINT)&NextIrp->IoStatus.Information ); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + AFD_DbgPrint(MID_TRACE,("Unlocking\n")); + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); + if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); + + AFD_DbgPrint(MID_TRACE,("Completing\n")); + (void)IoSetCancelRoutine(NextIrp, NULL); + NextIrp->IoStatus.Status = Status; + + IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { @@ -747,61 +733,45 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } - if( !IsListEmpty( &FCB->DatagramList ) ) { - ListEntry = RemoveHeadList( &FCB->DatagramList ); - DatagramRecv = CONTAINING_RECORD - ( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = DatagramRecv->Len; + FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); - - AFD_DbgPrint(MIN_TRACE,("Partial datagram failed\n")); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } else { - Status = SatisfyPacketRecvRequest - ( FCB, Irp, DatagramRecv, - (PUINT)&Irp->IoStatus.Information ); - - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } - } else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { - AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); - Status = STATUS_CANT_WAIT; - FCB->PollState &= ~AFD_EVENT_RECEIVE; - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); - return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } else { - FCB->PollState &= ~AFD_EVENT_RECEIVE; - return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); + if (!IsListEmpty(&FCB->DatagramList)) + { + ListEntry = RemoveHeadList(&FCB->DatagramList); + DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); + Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, + (PUINT)&Irp->IoStatus.Information); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + if (IsListEmpty(&FCB->DatagramList)) + { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); + + return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); + } + else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) + { + AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); + Status = STATUS_CANT_WAIT; + FCB->PollState &= ~AFD_EVENT_RECEIVE; + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); + } + else + { + FCB->PollState &= ~AFD_EVENT_RECEIVE; + return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } } diff --git a/reactos/drivers/network/afd/afd/select.c b/reactos/drivers/network/afd/afd/select.c index 7a0cc65ea1e..b6842b9f5f2 100644 --- a/reactos/drivers/network/afd/afd/select.c +++ b/reactos/drivers/network/afd/afd/select.c @@ -305,8 +305,15 @@ AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = STATUS_SUCCESS; } - if( FCB->EventSelect && (FCB->PollState & FCB->EventSelectTriggers) ) { + if((FCB->EventSelect) && + (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) + { AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); + + /* Disable the events that triggered the select until the reenabling function is called */ + FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); + + /* Set the application's event */ KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); } @@ -408,8 +415,15 @@ VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); - if( FCB->EventSelect && (FCB->PollState & FCB->EventSelectTriggers) ) { + if((FCB->EventSelect) && + (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) + { AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); + + /* Disable the events that triggered the select until the reenabling function is called */ + FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); + + /* Set the application's event */ KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); } diff --git a/reactos/drivers/network/afd/afd/write.c b/reactos/drivers/network/afd/afd/write.c index a6f27b496e7..a0358195572 100644 --- a/reactos/drivers/network/afd/afd/write.c +++ b/reactos/drivers/network/afd/afd/write.c @@ -322,6 +322,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { + FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); @@ -438,6 +439,8 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, SpaceAvail -= SendReq->BufferArray[i].len; } + FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; + if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); @@ -558,6 +561,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check the size of the Address given ... */ if( NT_SUCCESS(Status) ) { + FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); diff --git a/reactos/drivers/network/afd/include/afd.h b/reactos/drivers/network/afd/include/afd.h index aa9bcff6cea..c8bad4ec7ef 100644 --- a/reactos/drivers/network/afd/include/afd.h +++ b/reactos/drivers/network/afd/include/afd.h @@ -193,6 +193,7 @@ typedef struct _AFD_FCB { KMUTEX Mutex; PKEVENT EventSelect; DWORD EventSelectTriggers; + DWORD EventSelectDisabled; UNICODE_STRING TdiDeviceName; PVOID Context; DWORD PollState;