2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/read.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
13 static VOID
RefillSocketBuffer( PAFD_FCB FCB
)
15 /* Make sure nothing's in flight first */
16 if (FCB
->ReceiveIrp
.InFlightRequest
) return;
18 /* Now ensure that receive is still allowed */
19 if (FCB
->TdiReceiveClosed
) return;
21 /* Check if the buffer is full */
22 if (FCB
->Recv
.Content
== FCB
->Recv
.Size
)
24 /* If there are bytes used, we can solve this problem */
25 if (FCB
->Recv
.BytesUsed
!= 0)
27 /* Reposition the unused portion to the beginning of the receive window */
28 RtlMoveMemory(FCB
->Recv
.Window
,
29 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
30 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
);
32 FCB
->Recv
.Content
-= FCB
->Recv
.BytesUsed
;
33 FCB
->Recv
.BytesUsed
= 0;
37 /* No space in the buffer to receive */
42 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
44 TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
45 FCB
->Connection
.Object
,
47 FCB
->Recv
.Window
+ FCB
->Recv
.Content
,
48 FCB
->Recv
.Size
- FCB
->Recv
.Content
,
53 static VOID
HandleReceiveComplete( PAFD_FCB FCB
, NTSTATUS Status
, ULONG_PTR Information
)
55 FCB
->LastReceiveStatus
= Status
;
57 /* We got closed while the receive was in progress */
58 if (FCB
->TdiReceiveClosed
)
60 /* The received data is discarded */
62 /* Receive successful */
63 else if (Status
== STATUS_SUCCESS
)
65 FCB
->Recv
.Content
+= Information
;
66 ASSERT(FCB
->Recv
.Content
<= FCB
->Recv
.Size
);
68 /* Check for graceful closure */
71 /* Receive is closed */
72 FCB
->TdiReceiveClosed
= TRUE
;
76 /* Issue another receive IRP to keep the buffer well stocked */
77 RefillSocketBuffer(FCB
);
80 /* Receive failed with no data (unexpected closure) */
83 /* Previously received data remains intact */
84 FCB
->TdiReceiveClosed
= TRUE
;
88 static BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
89 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
91 return !BytesAvailable
&& FCB
->TdiReceiveClosed
;
94 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
95 PAFD_RECV_INFO RecvReq
,
96 PUINT TotalBytesCopied
) {
97 UINT i
, BytesToCopy
= 0, FcbBytesCopied
= FCB
->Recv
.BytesUsed
,
99 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
101 *TotalBytesCopied
= 0;
104 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %u\n", BytesAvailable
));
106 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
107 if( !BytesAvailable
) return STATUS_PENDING
;
109 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
111 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %u @ %p\n",
112 RecvReq
->BufferCount
,
113 RecvReq
->BufferArray
));
115 RecvReq
->BufferArray
&&
117 i
< RecvReq
->BufferCount
;
120 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
123 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
125 AFD_DbgPrint(MID_TRACE
,("Buffer %u: %p:%u\n",
127 Map
[i
].BufferAddress
,
130 RtlCopyMemory( Map
[i
].BufferAddress
,
131 FCB
->Recv
.Window
+ FcbBytesCopied
,
134 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
136 *TotalBytesCopied
+= BytesToCopy
;
137 FcbBytesCopied
+= BytesToCopy
;
138 BytesAvailable
-= BytesToCopy
;
140 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
141 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
145 /* Issue another receive IRP to keep the buffer well stocked */
146 RefillSocketBuffer(FCB
);
148 return STATUS_SUCCESS
;
151 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
152 PLIST_ENTRY NextIrpEntry
;
154 PIO_STACK_LOCATION NextIrpSp
;
155 PAFD_RECV_INFO RecvReq
;
156 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
157 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
159 AFD_DbgPrint(MID_TRACE
,("%p %p\n", FCB
, Irp
));
161 AFD_DbgPrint(MID_TRACE
,("FCB %p Receive data waiting %u\n",
162 FCB
, FCB
->Recv
.Content
));
164 if( CantReadMore( FCB
) ) {
165 /* Success here means that we got an EOF. Complete a pending read
166 * with zero bytes if we haven't yet overread, then kill the others.
168 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
169 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
170 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
171 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
172 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
174 AFD_DbgPrint(MID_TRACE
,("Completing recv %p (%u)\n", NextIrp
,
176 UnlockBuffers( RecvReq
->BufferArray
,
177 RecvReq
->BufferCount
, FALSE
);
178 if (FCB
->Overread
&& FCB
->LastReceiveStatus
== STATUS_SUCCESS
)
180 /* Overread after a graceful disconnect so complete with an error */
181 Status
= STATUS_FILE_CLOSED
;
185 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */
186 Status
= FCB
->LastReceiveStatus
;
188 NextIrp
->IoStatus
.Status
= Status
;
189 NextIrp
->IoStatus
.Information
= 0;
190 if( NextIrp
== Irp
) RetStatus
= Status
;
191 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
192 (void)IoSetCancelRoutine(NextIrp
, NULL
);
193 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
194 FCB
->Overread
= TRUE
;
197 /* Kick the user that receive would be possible now */
198 /* XXX Not implemented yet */
200 AFD_DbgPrint(MID_TRACE
,("FCB %p Receive data waiting %u\n",
201 FCB
, FCB
->Recv
.Content
));
202 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
204 /* Try to clear some requests */
205 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
206 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
207 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
208 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
209 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
211 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %p\n", RecvReq
));
213 Status
= TryToSatisfyRecvRequestFromBuffer
214 ( FCB
, RecvReq
, &TotalBytesCopied
);
216 if( Status
== STATUS_PENDING
) {
217 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %p\n", NextIrp
));
218 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
219 &NextIrp
->Tail
.Overlay
.ListEntry
);
222 AFD_DbgPrint(MID_TRACE
,("Completing recv %p (%u)\n", NextIrp
,
224 UnlockBuffers( RecvReq
->BufferArray
,
225 RecvReq
->BufferCount
, FALSE
);
226 NextIrp
->IoStatus
.Status
= Status
;
227 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
228 if( NextIrp
== Irp
) {
230 RetBytesCopied
= TotalBytesCopied
;
232 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
233 (void)IoSetCancelRoutine(NextIrp
, NULL
);
234 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
239 if( FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
&&
240 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
241 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
242 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
243 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
247 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
250 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
251 if (CantReadMore(FCB
))
253 if (FCB
->LastReceiveStatus
== STATUS_SUCCESS
)
255 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
259 FCB
->PollState
|= AFD_EVENT_CLOSE
;
261 FCB
->PollStatus
[FD_CLOSE_BIT
] = FCB
->LastReceiveStatus
;
262 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
265 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %p is %x\n", Irp
, RetStatus
));
267 /* Sometimes we're called with a NULL Irp */
269 Irp
->IoStatus
.Status
= RetStatus
;
270 Irp
->IoStatus
.Information
= RetBytesCopied
;
276 NTSTATUS NTAPI ReceiveComplete
277 ( PDEVICE_OBJECT DeviceObject
,
280 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
281 PLIST_ENTRY NextIrpEntry
;
283 PAFD_RECV_INFO RecvReq
;
284 PIO_STACK_LOCATION NextIrpSp
;
286 UNREFERENCED_PARAMETER(DeviceObject
);
288 AFD_DbgPrint(MID_TRACE
,("Called\n"));
290 if( !SocketAcquireStateLock( FCB
) )
291 return STATUS_FILE_CLOSED
;
293 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
294 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
296 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
297 /* Cleanup our IRP queue because the FCB is being destroyed */
298 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
299 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
300 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
301 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
302 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
303 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
304 NextIrp
->IoStatus
.Information
= 0;
305 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
306 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
307 (void)IoSetCancelRoutine(NextIrp
, NULL
);
308 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
310 SocketStateUnlock( FCB
);
311 return STATUS_FILE_CLOSED
;
312 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
313 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
314 SocketStateUnlock( FCB
);
315 return STATUS_INVALID_PARAMETER
;
318 HandleReceiveComplete( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
320 ReceiveActivity( FCB
, NULL
);
322 SocketStateUnlock( FCB
);
324 return STATUS_SUCCESS
;
327 static NTSTATUS NTAPI
328 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
329 PAFD_STORED_DATAGRAM DatagramRecv
,
330 PUINT TotalBytesCopied
) {
331 NTSTATUS Status
= STATUS_SUCCESS
;
332 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
333 PAFD_RECV_INFO RecvReq
=
334 GetLockedData(Irp
, IrpSp
);
335 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
337 BOOLEAN ExtraBuffers
= CheckUnlockExtraBuffers(FCB
, IrpSp
);
339 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
340 RecvReq
->BufferCount
+
341 (ExtraBuffers
? EXTRA_LOCK_BUFFERS
: 0));
343 BytesToCopy
= MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
345 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %u len %u\n", BytesToCopy
,
346 RecvReq
->BufferArray
[0].len
));
349 /* Copy the address */
350 if( ExtraBuffers
&& Map
[1].Mdl
&& Map
[2].Mdl
) {
351 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
353 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
356 ("Wierd address count %d\n",
357 DatagramRecv
->Address
->TAAddressCount
));
360 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
362 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
364 RecvReq
->BufferArray
[1].len
);
366 AFD_DbgPrint(MID_TRACE
,("Copying %u bytes of address\n", AddrLen
));
368 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
370 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
372 RtlCopyMemory( Map
[1].BufferAddress
,
373 &DatagramRecv
->Address
->Address
->AddressType
,
376 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
378 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
380 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
381 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
382 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
385 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
387 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
389 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %p:%u\n",
391 Map
[0].BufferAddress
,
394 RtlCopyMemory( Map
[0].BufferAddress
,
395 DatagramRecv
->Buffer
,
398 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
400 *TotalBytesCopied
= BytesToCopy
;
403 if (*TotalBytesCopied
== DatagramRecv
->Len
)
405 /* We copied the whole datagram */
406 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
410 /* We only copied part of the datagram */
411 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
414 Irp
->IoStatus
.Information
= *TotalBytesCopied
;
416 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
418 FCB
->Recv
.Content
-= DatagramRecv
->Len
;
419 ExFreePool( DatagramRecv
->Address
);
420 ExFreePool( DatagramRecv
);
423 AFD_DbgPrint(MID_TRACE
,("Done\n"));
429 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
430 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
431 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
432 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
433 PAFD_FCB FCB
= FileObject
->FsContext
;
434 PAFD_RECV_INFO RecvReq
;
435 UINT TotalBytesCopied
= 0;
436 PAFD_STORED_DATAGRAM DatagramRecv
;
437 PLIST_ENTRY ListEntry
;
438 KPROCESSOR_MODE LockMode
;
440 UNREFERENCED_PARAMETER(DeviceObject
);
441 UNREFERENCED_PARAMETER(Short
);
443 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
445 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
447 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
449 if( !(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) &&
450 FCB
->State
!= SOCKET_STATE_CONNECTED
&&
451 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
452 AFD_DbgPrint(MIN_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
454 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
458 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
459 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
462 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
464 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
465 RecvReq
->BufferCount
,
467 TRUE
, FALSE
, LockMode
);
469 if( !RecvReq
->BufferArray
) {
470 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
474 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
476 if (!IsListEmpty(&FCB
->DatagramList
))
478 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
479 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
480 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
481 (PUINT
)&Irp
->IoStatus
.Information
);
483 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
485 InsertHeadList(&FCB
->DatagramList
,
486 &DatagramRecv
->ListEntry
);
489 if (!IsListEmpty(&FCB
->DatagramList
))
491 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
492 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
493 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
496 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
498 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
500 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
502 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
503 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
505 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
506 Status
= STATUS_CANT_WAIT
;
507 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
508 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
509 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
513 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
514 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);
518 Irp
->IoStatus
.Status
= STATUS_PENDING
;
519 Irp
->IoStatus
.Information
= 0;
521 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
522 &Irp
->Tail
.Overlay
.ListEntry
);
524 /************ From this point, the IRP is not ours ************/
526 Status
= ReceiveActivity( FCB
, Irp
);
528 if( Status
== STATUS_PENDING
&&
529 !(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
530 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
531 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
532 Status
= STATUS_CANT_WAIT
;
533 TotalBytesCopied
= 0;
534 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
535 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
536 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
538 } else if( Status
== STATUS_PENDING
) {
539 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
540 IoMarkIrpPending( Irp
);
541 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
543 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
546 SocketStateUnlock( FCB
);
551 PacketSocketRecvComplete(
552 PDEVICE_OBJECT DeviceObject
,
555 NTSTATUS Status
= STATUS_SUCCESS
;
556 PAFD_FCB FCB
= Context
;
558 PIO_STACK_LOCATION NextIrpSp
;
559 PLIST_ENTRY ListEntry
;
560 PAFD_RECV_INFO RecvReq
;
561 PAFD_STORED_DATAGRAM DatagramRecv
;
562 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
563 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
565 UNREFERENCED_PARAMETER(DeviceObject
);
567 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
569 if( !SocketAcquireStateLock( FCB
) )
570 return STATUS_FILE_CLOSED
;
572 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
573 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
575 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
576 /* Cleanup our IRP queue because the FCB is being destroyed */
577 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
578 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
579 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
580 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
581 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
582 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
583 NextIrp
->IoStatus
.Information
= 0;
584 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
));
585 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
586 (void)IoSetCancelRoutine(NextIrp
, NULL
);
587 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
590 /* Free all items on the datagram list */
591 while( !IsListEmpty( &FCB
->DatagramList
) ) {
592 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
593 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
594 ExFreePool( DatagramRecv
->Address
);
595 ExFreePool( DatagramRecv
);
598 SocketStateUnlock( FCB
);
599 return STATUS_FILE_CLOSED
;
602 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
604 SocketStateUnlock(FCB
);
605 return Irp
->IoStatus
.Status
;
608 if (FCB
->TdiReceiveClosed
)
610 SocketStateUnlock(FCB
);
611 return STATUS_FILE_CLOSED
;
614 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
617 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
618 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
620 AFD_DbgPrint(MID_TRACE
,("Received (A %p)\n",
621 FCB
->AddressFrom
->RemoteAddress
));
622 DatagramRecv
->Address
=
623 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
625 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
627 } else Status
= STATUS_NO_MEMORY
;
629 if( !NT_SUCCESS( Status
) ) {
630 if( DatagramRecv
) ExFreePool( DatagramRecv
);
631 SocketStateUnlock( FCB
);
634 FCB
->Recv
.Content
+= DatagramRecv
->Len
;
635 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
638 /* Satisfy as many requests as we can */
640 while( !IsListEmpty( &FCB
->DatagramList
) &&
641 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
642 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
643 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
644 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
646 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
647 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
648 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
649 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
651 AFD_DbgPrint(MID_TRACE
,("RecvReq: %p, DatagramRecv: %p\n",
652 RecvReq
, DatagramRecv
));
654 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
655 Status
= SatisfyPacketRecvRequest
656 ( FCB
, NextIrp
, DatagramRecv
,
657 (PUINT
)&NextIrp
->IoStatus
.Information
);
659 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
661 InsertHeadList(&FCB
->DatagramList
,
662 &DatagramRecv
->ListEntry
);
665 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
666 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
) );
667 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
669 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
670 (void)IoSetCancelRoutine(NextIrp
, NULL
);
671 NextIrp
->IoStatus
.Status
= Status
;
673 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
676 if( !IsListEmpty( &FCB
->DatagramList
) && IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
677 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
678 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
679 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
680 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
682 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
684 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
685 /* Now relaunch the datagram request */
686 Status
= TdiReceiveDatagram
687 ( &FCB
->ReceiveIrp
.InFlightRequest
,
688 FCB
->AddressFile
.Object
,
693 PacketSocketRecvComplete
,
697 SocketStateUnlock( FCB
);
699 return STATUS_SUCCESS
;
703 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
704 PIO_STACK_LOCATION IrpSp
) {
705 NTSTATUS Status
= STATUS_SUCCESS
;
706 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
707 PAFD_FCB FCB
= FileObject
->FsContext
;
708 PAFD_RECV_INFO_UDP RecvReq
;
709 PLIST_ENTRY ListEntry
;
710 PAFD_STORED_DATAGRAM DatagramRecv
;
711 KPROCESSOR_MODE LockMode
;
713 UNREFERENCED_PARAMETER(DeviceObject
);
715 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
717 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
719 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
721 /* Check that the socket is bound */
722 if( FCB
->State
!= SOCKET_STATE_BOUND
)
724 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
725 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
728 if (FCB
->TdiReceiveClosed
)
730 AFD_DbgPrint(MIN_TRACE
,("Receive closed\n"));
731 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
734 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
735 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
737 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
739 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
740 RecvReq
->BufferCount
,
742 RecvReq
->AddressLength
,
743 TRUE
, TRUE
, LockMode
);
745 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
746 return UnlockAndMaybeComplete(FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0);
749 if (!IsListEmpty(&FCB
->DatagramList
))
751 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
752 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
753 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
754 (PUINT
)&Irp
->IoStatus
.Information
);
756 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
758 InsertHeadList(&FCB
->DatagramList
,
759 &DatagramRecv
->ListEntry
);
762 if (!IsListEmpty(&FCB
->DatagramList
))
764 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
765 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
766 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
769 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
771 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
773 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
775 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
776 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
778 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
779 Status
= STATUS_CANT_WAIT
;
780 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
781 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
782 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
786 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
787 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);