mirror of
https://github.com/reactos/reactos.git
synced 2024-09-30 22:47:28 +00:00
[AFD]
- Rewrite user-mode send IRP handling so send errors get returned to the user properly - Fixes OskitTCP: ESHUTDOWN/EPIPE debug log spam when a chargen telnet session is terminated by the remote side svn path=/trunk/; revision=52552
This commit is contained in:
parent
d7d9b7ec6c
commit
14f58265d2
|
@ -23,7 +23,7 @@ static NTSTATUS NTAPI SendComplete
|
|||
PIO_STACK_LOCATION NextIrpSp;
|
||||
PAFD_SEND_INFO SendReq = NULL;
|
||||
PAFD_MAPBUF Map;
|
||||
UINT TotalBytesCopied = 0, SpaceAvail, i;
|
||||
UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
|
||||
|
||||
/*
|
||||
* The Irp parameter passed in is the IRP of the stream between AFD and
|
||||
|
@ -99,7 +99,42 @@ static NTSTATUS NTAPI SendComplete
|
|||
RtlMoveMemory( FCB->Send.Window,
|
||||
FCB->Send.Window + FCB->Send.BytesUsed,
|
||||
FCB->Send.BytesUsed - Irp->IoStatus.Information );
|
||||
FCB->Send.BytesUsed -= Irp->IoStatus.Information;
|
||||
|
||||
TotalBytesProcessed = 0;
|
||||
while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) &&
|
||||
TotalBytesProcessed != Irp->IoStatus.Information) {
|
||||
NextIrpEntry =
|
||||
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
|
||||
NextIrp =
|
||||
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
|
||||
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
|
||||
SendReq = GetLockedData(NextIrp, NextIrpSp);
|
||||
Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
|
||||
|
||||
TotalBytesCopied = 0;
|
||||
|
||||
for( i = 0; i < SendReq->BufferCount; i++ )
|
||||
TotalBytesCopied += SendReq->BufferArray[i].len;
|
||||
|
||||
NextIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||
NextIrp->IoStatus.Information = TotalBytesCopied;
|
||||
|
||||
TotalBytesProcessed += TotalBytesCopied;
|
||||
|
||||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
|
||||
UnlockBuffers( SendReq->BufferArray,
|
||||
SendReq->BufferCount,
|
||||
FALSE );
|
||||
|
||||
if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
|
||||
|
||||
IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
|
||||
}
|
||||
|
||||
ASSERT(TotalBytesProcessed == Irp->IoStatus.Information);
|
||||
|
||||
FCB->Send.BytesUsed -= TotalBytesProcessed;
|
||||
|
||||
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
|
||||
NextIrpEntry =
|
||||
|
@ -139,19 +174,6 @@ static NTSTATUS NTAPI SendComplete
|
|||
if (NextIrp != NULL)
|
||||
{
|
||||
FCB->Send.BytesUsed += TotalBytesCopied;
|
||||
|
||||
NextIrp->IoStatus.Status = STATUS_SUCCESS;
|
||||
NextIrp->IoStatus.Information = TotalBytesCopied;
|
||||
|
||||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
|
||||
UnlockBuffers( SendReq->BufferArray,
|
||||
SendReq->BufferCount,
|
||||
FALSE );
|
||||
|
||||
if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
|
||||
|
||||
IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
@ -198,6 +220,7 @@ static NTSTATUS NTAPI PacketSocketSendComplete
|
|||
PAFD_FCB FCB = (PAFD_FCB)Context;
|
||||
PLIST_ENTRY NextIrpEntry;
|
||||
PIRP NextIrp;
|
||||
PAFD_SEND_INFO SendReq;
|
||||
|
||||
AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
|
||||
Irp->IoStatus.Status,
|
||||
|
@ -210,29 +233,47 @@ static NTSTATUS NTAPI PacketSocketSendComplete
|
|||
FCB->SendIrp.InFlightRequest = NULL;
|
||||
/* Request is not in flight any longer */
|
||||
|
||||
if (Irp->IoStatus.Status == STATUS_SUCCESS)
|
||||
{
|
||||
FCB->PollState |= AFD_EVENT_SEND;
|
||||
FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
|
||||
PollReeval( FCB->DeviceExt, FCB->FileObject );
|
||||
}
|
||||
|
||||
if( FCB->State == SOCKET_STATE_CLOSED ) {
|
||||
/* Cleanup our IRP queue because the FCB is being destroyed */
|
||||
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
|
||||
NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
|
||||
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
|
||||
NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
|
||||
NextIrp->IoStatus.Information = 0;
|
||||
if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
|
||||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
|
||||
NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
|
||||
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
|
||||
SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
|
||||
NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
|
||||
NextIrp->IoStatus.Information = 0;
|
||||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
|
||||
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
|
||||
}
|
||||
SocketStateUnlock( FCB );
|
||||
return STATUS_FILE_CLOSED;
|
||||
SocketStateUnlock( FCB );
|
||||
return STATUS_FILE_CLOSED;
|
||||
}
|
||||
|
||||
SocketStateUnlock( FCB );
|
||||
ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
|
||||
|
||||
/* TDI spec guarantees FIFO ordering on IRPs */
|
||||
NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
|
||||
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
|
||||
|
||||
NextIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||
NextIrp->IoStatus.Information = Irp->IoStatus.Information;
|
||||
|
||||
(void)IoSetCancelRoutine(NextIrp, NULL);
|
||||
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
|
||||
UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
|
||||
|
||||
IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
|
||||
|
||||
FCB->PollState |= AFD_EVENT_SEND;
|
||||
FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
|
||||
PollReeval(FCB->DeviceExt, FCB->FileObject);
|
||||
|
||||
SocketStateUnlock(FCB);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -244,7 +285,6 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PAFD_FCB FCB = FileObject->FsContext;
|
||||
PAFD_SEND_INFO SendReq;
|
||||
ULONG Information;
|
||||
UINT TotalBytesCopied = 0, i, SpaceAvail = 0;
|
||||
BOOLEAN NoSpace = FALSE;
|
||||
|
||||
|
@ -278,29 +318,33 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
|
||||
Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
|
||||
|
||||
if( NT_SUCCESS(Status) ) {
|
||||
Status = TdiSendDatagram
|
||||
( &FCB->SendIrp.InFlightRequest,
|
||||
FCB->AddressFile.Object,
|
||||
SendReq->BufferArray[0].buf,
|
||||
SendReq->BufferArray[0].len,
|
||||
TargetAddress,
|
||||
&FCB->SendIrp.Iosb,
|
||||
PacketSocketSendComplete,
|
||||
FCB );
|
||||
if( NT_SUCCESS(Status) ) {
|
||||
FCB->PollState &= ~AFD_EVENT_SEND;
|
||||
|
||||
ExFreePool( TargetAddress );
|
||||
}
|
||||
Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
|
||||
FCB->AddressFile.Object,
|
||||
SendReq->BufferArray[0].buf,
|
||||
SendReq->BufferArray[0].len,
|
||||
TargetAddress,
|
||||
&FCB->SendIrp.Iosb,
|
||||
PacketSocketSendComplete,
|
||||
FCB);
|
||||
}
|
||||
|
||||
if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
|
||||
ExFreePool( TargetAddress );
|
||||
|
||||
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
|
||||
SocketStateUnlock(FCB);
|
||||
|
||||
/* Even if we were pended, we're done with the user buffer at this
|
||||
* point. */
|
||||
Information = SendReq->BufferArray[0].len;
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if (FCB->DisconnectPending && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE))
|
||||
|
@ -370,6 +414,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
|
||||
return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_OVERFLOW, Irp, 0);
|
||||
}
|
||||
SpaceAvail += TotalBytesCopied;
|
||||
NoSpace = TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -395,11 +440,37 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
|
||||
}
|
||||
|
||||
if (SpaceAvail)
|
||||
{
|
||||
FCB->PollState |= AFD_EVENT_SEND;
|
||||
FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
|
||||
PollReeval( FCB->DeviceExt, FCB->FileObject );
|
||||
}
|
||||
else
|
||||
{
|
||||
FCB->PollState &= ~AFD_EVENT_SEND;
|
||||
}
|
||||
|
||||
if (!NoSpace)
|
||||
{
|
||||
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
|
||||
FCB->Send.BytesUsed += TotalBytesCopied;
|
||||
AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
|
||||
AFD_DbgPrint(MID_TRACE,("Copied %d bytes\n", TotalBytesCopied));
|
||||
|
||||
Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
|
||||
if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
|
||||
{
|
||||
TdiSend(&FCB->SendIrp.InFlightRequest,
|
||||
FCB->Connection.Object,
|
||||
0,
|
||||
FCB->Send.Window,
|
||||
FCB->Send.BytesUsed,
|
||||
&FCB->SendIrp.Iosb,
|
||||
SendComplete,
|
||||
FCB);
|
||||
}
|
||||
SocketStateUnlock(FCB);
|
||||
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -414,38 +485,6 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
|
||||
}
|
||||
}
|
||||
|
||||
if (!FCB->SendIrp.InFlightRequest)
|
||||
{
|
||||
Status = TdiSend( &FCB->SendIrp.InFlightRequest,
|
||||
FCB->Connection.Object,
|
||||
0,
|
||||
FCB->Send.Window,
|
||||
FCB->Send.BytesUsed,
|
||||
&FCB->SendIrp.Iosb,
|
||||
SendComplete,
|
||||
FCB );
|
||||
|
||||
if( Status == STATUS_PENDING )
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
|
||||
Status, TotalBytesCopied));
|
||||
}
|
||||
|
||||
if (SpaceAvail)
|
||||
{
|
||||
FCB->PollState |= AFD_EVENT_SEND;
|
||||
FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
|
||||
PollReeval( FCB->DeviceExt, FCB->FileObject );
|
||||
}
|
||||
else
|
||||
{
|
||||
FCB->PollState &= ~AFD_EVENT_SEND;
|
||||
}
|
||||
|
||||
return UnlockAndMaybeComplete
|
||||
( FCB, Status, Irp, TotalBytesCopied );
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
|
@ -456,7 +495,6 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
PAFD_FCB FCB = FileObject->FsContext;
|
||||
PAFD_SEND_INFO_UDP SendReq;
|
||||
ULONG Information;
|
||||
|
||||
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
|
||||
|
||||
|
@ -514,27 +552,29 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
if( NT_SUCCESS(Status) ) {
|
||||
FCB->PollState &= ~AFD_EVENT_SEND;
|
||||
|
||||
Status = TdiSendDatagram
|
||||
( &FCB->SendIrp.InFlightRequest,
|
||||
FCB->AddressFile.Object,
|
||||
SendReq->BufferArray[0].buf,
|
||||
SendReq->BufferArray[0].len,
|
||||
TargetAddress,
|
||||
&FCB->SendIrp.Iosb,
|
||||
PacketSocketSendComplete,
|
||||
FCB );
|
||||
Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
|
||||
FCB->AddressFile.Object,
|
||||
SendReq->BufferArray[0].buf,
|
||||
SendReq->BufferArray[0].len,
|
||||
TargetAddress,
|
||||
&FCB->SendIrp.Iosb,
|
||||
PacketSocketSendComplete,
|
||||
FCB);
|
||||
}
|
||||
|
||||
ExFreePool( TargetAddress );
|
||||
|
||||
SocketStateUnlock(FCB);
|
||||
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
|
||||
}
|
||||
|
||||
if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
|
||||
|
||||
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
|
||||
|
||||
/* Even if we were pended, we're done with the user buffer at this
|
||||
* point. */
|
||||
Information = SendReq->BufferArray[0].len;
|
||||
UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
|
||||
return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue