- 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:
Cameron Gutman 2011-07-07 00:29:30 +00:00
parent d7d9b7ec6c
commit 14f58265d2

View file

@ -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;
}
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);
SocketStateUnlock( FCB );
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 );
ExFreePool( TargetAddress );
}
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 );
if( NT_SUCCESS(Status) ) {
FCB->PollState &= ~AFD_EVENT_SEND;
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 (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;
}
@ -394,12 +439,38 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
return UnlockAndMaybeComplete
( 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 );
}