- Fix a nasty datagram corruption bug that would result in an uninitialized buffer data being returned instead of packet data if the client read buffer was smaller than the datagram received
- Fix broken user-mode send datagram IRP completion code which didn't set the completion status
- Implement disabling/enabling event select triggers

svn path=/trunk/; revision=52723
This commit is contained in:
Cameron Gutman 2011-07-18 04:21:40 +00:00
parent 521309797d
commit e37e340708
5 changed files with 133 additions and 141 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -193,6 +193,7 @@ typedef struct _AFD_FCB {
KMUTEX Mutex;
PKEVENT EventSelect;
DWORD EventSelectTriggers;
DWORD EventSelectDisabled;
UNICODE_STRING TdiDeviceName;
PVOID Context;
DWORD PollState;