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;
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 disconnect */
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
) {
231 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
232 (void)IoSetCancelRoutine(NextIrp
, NULL
);
233 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
238 if( FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
&&
239 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
240 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
241 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
242 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
246 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
249 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
250 if (CantReadMore(FCB
))
252 if (FCB
->LastReceiveStatus
== STATUS_SUCCESS
)
254 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
258 FCB
->PollState
|= AFD_EVENT_CLOSE
;
260 FCB
->PollStatus
[FD_CLOSE_BIT
] = FCB
->LastReceiveStatus
;
261 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
264 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %p is %x\n", Irp
, RetStatus
));
269 NTSTATUS NTAPI ReceiveComplete
270 ( PDEVICE_OBJECT DeviceObject
,
273 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
274 PLIST_ENTRY NextIrpEntry
;
276 PAFD_RECV_INFO RecvReq
;
277 PIO_STACK_LOCATION NextIrpSp
;
279 UNREFERENCED_PARAMETER(DeviceObject
);
281 AFD_DbgPrint(MID_TRACE
,("Called\n"));
283 if( !SocketAcquireStateLock( FCB
) )
284 return STATUS_FILE_CLOSED
;
286 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
287 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
289 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
290 /* Cleanup our IRP queue because the FCB is being destroyed */
291 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
292 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
293 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
294 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
295 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
296 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
297 NextIrp
->IoStatus
.Information
= 0;
298 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
299 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
300 (void)IoSetCancelRoutine(NextIrp
, NULL
);
301 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
303 SocketStateUnlock( FCB
);
304 return STATUS_FILE_CLOSED
;
305 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
306 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
307 SocketStateUnlock( FCB
);
308 return STATUS_INVALID_PARAMETER
;
311 HandleReceiveComplete( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
313 ReceiveActivity( FCB
, NULL
);
315 SocketStateUnlock( FCB
);
317 return STATUS_SUCCESS
;
320 static NTSTATUS NTAPI
321 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
322 PAFD_STORED_DATAGRAM DatagramRecv
,
323 PUINT TotalBytesCopied
) {
324 NTSTATUS Status
= STATUS_SUCCESS
;
325 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
326 PAFD_RECV_INFO RecvReq
=
327 GetLockedData(Irp
, IrpSp
);
328 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
330 BOOLEAN ExtraBuffers
= CheckUnlockExtraBuffers(FCB
, IrpSp
);
332 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
333 RecvReq
->BufferCount
+
334 (ExtraBuffers
? EXTRA_LOCK_BUFFERS
: 0));
336 BytesToCopy
= MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
338 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %u len %u\n", BytesToCopy
,
339 RecvReq
->BufferArray
[0].len
));
342 /* Copy the address */
343 if( ExtraBuffers
&& Map
[1].Mdl
&& Map
[2].Mdl
) {
344 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
346 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
349 ("Wierd address count %d\n",
350 DatagramRecv
->Address
->TAAddressCount
));
353 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
355 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
357 RecvReq
->BufferArray
[1].len
);
359 AFD_DbgPrint(MID_TRACE
,("Copying %u bytes of address\n", AddrLen
));
361 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
363 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
365 RtlCopyMemory( Map
[1].BufferAddress
,
366 &DatagramRecv
->Address
->Address
->AddressType
,
369 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
371 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
373 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
374 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
375 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
378 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
380 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
382 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %p:%u\n",
384 Map
[0].BufferAddress
,
387 RtlCopyMemory( Map
[0].BufferAddress
,
388 DatagramRecv
->Buffer
,
391 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
393 *TotalBytesCopied
= BytesToCopy
;
396 if (*TotalBytesCopied
== DatagramRecv
->Len
)
398 /* We copied the whole datagram */
399 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
403 /* We only copied part of the datagram */
404 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
407 Irp
->IoStatus
.Information
= *TotalBytesCopied
;
409 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
411 FCB
->Recv
.Content
-= DatagramRecv
->Len
;
412 ExFreePool( DatagramRecv
->Address
);
413 ExFreePool( DatagramRecv
);
416 AFD_DbgPrint(MID_TRACE
,("Done\n"));
422 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
423 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
424 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
425 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
426 PAFD_FCB FCB
= FileObject
->FsContext
;
427 PAFD_RECV_INFO RecvReq
;
428 UINT TotalBytesCopied
= 0;
429 PAFD_STORED_DATAGRAM DatagramRecv
;
430 PLIST_ENTRY ListEntry
;
431 KPROCESSOR_MODE LockMode
;
433 UNREFERENCED_PARAMETER(DeviceObject
);
434 UNREFERENCED_PARAMETER(Short
);
436 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
438 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
440 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
442 if( !(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) &&
443 FCB
->State
!= SOCKET_STATE_CONNECTED
&&
444 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
445 AFD_DbgPrint(MIN_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
447 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
451 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
452 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
455 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
457 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
458 RecvReq
->BufferCount
,
460 TRUE
, FALSE
, LockMode
);
462 if( !RecvReq
->BufferArray
) {
463 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
467 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
469 if (!IsListEmpty(&FCB
->DatagramList
))
471 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
472 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
473 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
474 (PUINT
)&Irp
->IoStatus
.Information
);
476 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
478 InsertHeadList(&FCB
->DatagramList
,
479 &DatagramRecv
->ListEntry
);
482 if (!IsListEmpty(&FCB
->DatagramList
))
484 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
485 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
486 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
489 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
491 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
493 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
495 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
496 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
498 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
499 Status
= STATUS_CANT_WAIT
;
500 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
501 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
502 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
506 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
507 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);
511 Irp
->IoStatus
.Status
= STATUS_PENDING
;
512 Irp
->IoStatus
.Information
= 0;
514 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
515 &Irp
->Tail
.Overlay
.ListEntry
);
517 /************ From this point, the IRP is not ours ************/
519 Status
= ReceiveActivity( FCB
, Irp
);
521 if( Status
== STATUS_PENDING
&&
522 !(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
523 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
524 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
525 Status
= STATUS_CANT_WAIT
;
526 TotalBytesCopied
= 0;
527 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
528 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
529 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
531 } else if( Status
== STATUS_PENDING
) {
532 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
533 IoMarkIrpPending( Irp
);
534 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
536 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
539 SocketStateUnlock( FCB
);
544 PacketSocketRecvComplete(
545 PDEVICE_OBJECT DeviceObject
,
548 NTSTATUS Status
= STATUS_SUCCESS
;
549 PAFD_FCB FCB
= Context
;
551 PIO_STACK_LOCATION NextIrpSp
;
552 PLIST_ENTRY ListEntry
;
553 PAFD_RECV_INFO RecvReq
;
554 PAFD_STORED_DATAGRAM DatagramRecv
;
555 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
556 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
558 UNREFERENCED_PARAMETER(DeviceObject
);
560 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
562 if( !SocketAcquireStateLock( FCB
) )
563 return STATUS_FILE_CLOSED
;
565 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
566 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
568 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
569 /* Cleanup our IRP queue because the FCB is being destroyed */
570 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
571 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
572 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
573 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
574 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
575 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
576 NextIrp
->IoStatus
.Information
= 0;
577 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
));
578 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
579 (void)IoSetCancelRoutine(NextIrp
, NULL
);
580 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
583 /* Free all items on the datagram list */
584 while( !IsListEmpty( &FCB
->DatagramList
) ) {
585 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
586 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
587 ExFreePool( DatagramRecv
->Address
);
588 ExFreePool( DatagramRecv
);
591 SocketStateUnlock( FCB
);
592 return STATUS_FILE_CLOSED
;
595 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
597 SocketStateUnlock(FCB
);
598 return Irp
->IoStatus
.Status
;
601 if (FCB
->TdiReceiveClosed
)
603 SocketStateUnlock(FCB
);
604 return STATUS_FILE_CLOSED
;
607 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
610 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
611 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
613 AFD_DbgPrint(MID_TRACE
,("Received (A %p)\n",
614 FCB
->AddressFrom
->RemoteAddress
));
615 DatagramRecv
->Address
=
616 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
618 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
620 } else Status
= STATUS_NO_MEMORY
;
622 if( !NT_SUCCESS( Status
) ) {
623 if( DatagramRecv
) ExFreePool( DatagramRecv
);
624 SocketStateUnlock( FCB
);
627 FCB
->Recv
.Content
+= DatagramRecv
->Len
;
628 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
631 /* Satisfy as many requests as we can */
633 while( !IsListEmpty( &FCB
->DatagramList
) &&
634 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
635 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
636 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
637 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
639 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
640 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
641 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
642 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
644 AFD_DbgPrint(MID_TRACE
,("RecvReq: %p, DatagramRecv: %p\n",
645 RecvReq
, DatagramRecv
));
647 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
648 Status
= SatisfyPacketRecvRequest
649 ( FCB
, NextIrp
, DatagramRecv
,
650 (PUINT
)&NextIrp
->IoStatus
.Information
);
652 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
654 InsertHeadList(&FCB
->DatagramList
,
655 &DatagramRecv
->ListEntry
);
658 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
659 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
) );
660 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
662 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
663 (void)IoSetCancelRoutine(NextIrp
, NULL
);
664 NextIrp
->IoStatus
.Status
= Status
;
666 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
669 if( !IsListEmpty( &FCB
->DatagramList
) && IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
670 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
671 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
672 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
673 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
675 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
677 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
678 /* Now relaunch the datagram request */
679 Status
= TdiReceiveDatagram
680 ( &FCB
->ReceiveIrp
.InFlightRequest
,
681 FCB
->AddressFile
.Object
,
686 PacketSocketRecvComplete
,
690 SocketStateUnlock( FCB
);
692 return STATUS_SUCCESS
;
696 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
697 PIO_STACK_LOCATION IrpSp
) {
698 NTSTATUS Status
= STATUS_SUCCESS
;
699 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
700 PAFD_FCB FCB
= FileObject
->FsContext
;
701 PAFD_RECV_INFO_UDP RecvReq
;
702 PLIST_ENTRY ListEntry
;
703 PAFD_STORED_DATAGRAM DatagramRecv
;
704 KPROCESSOR_MODE LockMode
;
706 UNREFERENCED_PARAMETER(DeviceObject
);
708 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
710 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
712 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
714 /* Check that the socket is bound */
715 if( FCB
->State
!= SOCKET_STATE_BOUND
)
717 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
718 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
721 if (FCB
->TdiReceiveClosed
)
723 AFD_DbgPrint(MIN_TRACE
,("Receive closed\n"));
724 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
727 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
728 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
730 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
732 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
733 RecvReq
->BufferCount
,
735 RecvReq
->AddressLength
,
736 TRUE
, TRUE
, LockMode
);
738 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
739 return UnlockAndMaybeComplete(FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0);
742 if (!IsListEmpty(&FCB
->DatagramList
))
744 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
745 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
746 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
747 (PUINT
)&Irp
->IoStatus
.Information
);
749 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
751 InsertHeadList(&FCB
->DatagramList
,
752 &DatagramRecv
->ListEntry
);
755 if (!IsListEmpty(&FCB
->DatagramList
))
757 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
758 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
759 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
762 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
764 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
766 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
768 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
769 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
771 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
772 Status
= STATUS_CANT_WAIT
;
773 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
774 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
775 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
779 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
780 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);