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)
10 * Improve buffering code
12 * We're keeping data receiving in one of two states:
13 * A) Some data available in the FCB
14 * FCB->Recv.BytesUsed != FCB->Recv.Content
15 * FCB->ReceiveIrp.InFlightRequest == NULL
16 * AFD_EVENT_RECEIVE set in FCB->PollState
17 * B) No data available in the FCB
18 * FCB->Recv.BytesUsed == FCB->Recv.Content (== 0)
19 * FCB->RecieveIrp.InFlightRequest != NULL
20 * AFD_EVENT_RECEIVED not set in FCB->PollState
21 * So basically we either have data available or a TDI receive
25 #include "tdi_proto.h"
29 BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
30 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
32 return !BytesAvailable
&&
33 (FCB
->PollState
& (AFD_EVENT_CLOSE
| AFD_EVENT_DISCONNECT
));
36 VOID
HandleEOFOnIrp( PAFD_FCB FCB
, NTSTATUS Status
, UINT Information
) {
37 if( Status
== STATUS_SUCCESS
&& Information
== 0 ) {
38 AFD_DbgPrint(MID_TRACE
,("Looks like an EOF\n"));
39 FCB
->PollState
|= AFD_EVENT_CLOSE
/*| AFD_EVENT_DISCONNECT */;
40 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
44 NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
45 PAFD_RECV_INFO RecvReq
,
46 PUINT TotalBytesCopied
) {
47 UINT i
, BytesToCopy
= 0,
49 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
50 *TotalBytesCopied
= 0;
54 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
57 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
58 if( !BytesAvailable
) return STATUS_PENDING
;
60 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
62 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
64 RecvReq
->BufferArray
));
66 RecvReq
->BufferArray
&&
68 i
< RecvReq
->BufferCount
;
71 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
74 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
76 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
81 RtlCopyMemory( Map
[i
].BufferAddress
,
82 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
85 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
87 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
88 *TotalBytesCopied
+= BytesToCopy
;
89 BytesAvailable
-= BytesToCopy
;
93 /* If there's nothing left in our buffer start a new request */
94 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
95 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
96 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
98 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
99 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
101 SocketCalloutEnter( FCB
);
103 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
104 FCB
->Connection
.Object
,
108 &FCB
->ReceiveIrp
.Iosb
,
112 if( Status
== STATUS_SUCCESS
)
113 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
114 HandleEOFOnIrp( FCB
, Status
, FCB
->Recv
.Content
);
115 SocketCalloutLeave( FCB
);
119 return STATUS_SUCCESS
;
122 NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
123 PLIST_ENTRY NextIrpEntry
;
125 PIO_STACK_LOCATION NextIrpSp
;
126 PAFD_RECV_INFO RecvReq
;
127 UINT TotalBytesCopied
= 0;
128 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
130 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
132 if( CantReadMore( FCB
) ) {
133 /* Success here means that we got an EOF. Complete a pending read
134 * with zero bytes if we haven't yet overread, then kill the others.
136 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
138 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
140 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
141 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
142 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
144 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
146 UnlockBuffers( RecvReq
->BufferArray
,
147 RecvReq
->BufferCount
, FALSE
);
148 Status
= NextIrp
->IoStatus
.Status
=
149 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
150 NextIrp
->IoStatus
.Information
= 0;
151 if( NextIrp
== Irp
) RetStatus
= Status
;
152 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
153 FCB
->Overread
= TRUE
;
154 //FCB->PollState |= AFD_EVENT_DISCONNECT;
155 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
158 /* Kick the user that receive would be possible now */
159 /* XXX Not implemented yet */
161 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
162 FCB
, FCB
->Recv
.Content
));
163 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
165 Status
= STATUS_SUCCESS
;
167 /* Try to clear some requests */
168 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) &&
169 NT_SUCCESS(Status
) ) {
171 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
173 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
174 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
175 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
177 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
179 Status
= TryToSatisfyRecvRequestFromBuffer
180 ( FCB
, RecvReq
, &TotalBytesCopied
);
182 if( Status
== STATUS_PENDING
) {
183 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
184 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
185 &NextIrp
->Tail
.Overlay
.ListEntry
);
188 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
190 UnlockBuffers( RecvReq
->BufferArray
,
191 RecvReq
->BufferCount
, FALSE
);
192 NextIrp
->IoStatus
.Status
= Status
;
193 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
194 if( NextIrp
== Irp
) RetStatus
= Status
;
195 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
200 if( FCB
->Recv
.Content
) {
201 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
203 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
205 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
207 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
212 NTSTATUS DDKAPI ReceiveComplete
213 ( PDEVICE_OBJECT DeviceObject
,
216 NTSTATUS Status
= Irp
->IoStatus
.Status
;
217 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
219 AFD_DbgPrint(MID_TRACE
,("Called\n"));
221 ASSERT_IRQL(APC_LEVEL
);
223 if( !SocketAcquireStateLock( FCB
) ) return Status
;
225 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
226 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
227 FCB
->Recv
.BytesUsed
= 0;
229 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
230 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
231 SocketStateUnlock( FCB
);
232 DestroySocket( FCB
);
233 return STATUS_SUCCESS
;
234 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
235 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
236 SocketStateUnlock( FCB
);
237 return STATUS_UNSUCCESSFUL
;
240 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
242 ReceiveActivity( FCB
, NULL
);
244 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
246 SocketStateUnlock( FCB
);
248 AFD_DbgPrint(MID_TRACE
,("Returned %x\n", Status
));
250 return STATUS_SUCCESS
;
254 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
255 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
256 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
257 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
258 PAFD_FCB FCB
= FileObject
->FsContext
;
259 PAFD_RECV_INFO RecvReq
;
260 UINT TotalBytesCopied
= 0;
262 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
264 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
266 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
267 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
268 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
270 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
,
271 Irp
, 0, NULL
, FALSE
);
274 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
276 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
277 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
278 Irp
, 0, NULL
, FALSE
);
281 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
282 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
284 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
285 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
286 Irp
, 0, NULL
, FALSE
);
288 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
290 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
291 RecvReq
->BufferCount
,
295 if( !RecvReq
->BufferArray
) {
296 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
297 Irp
, 0, NULL
, FALSE
);
300 Irp
->IoStatus
.Status
= STATUS_PENDING
;
301 Irp
->IoStatus
.Information
= 0;
303 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
304 &Irp
->Tail
.Overlay
.ListEntry
);
306 /************ From this point, the IRP is not ours ************/
308 Status
= ReceiveActivity( FCB
, Irp
);
310 if( Status
== STATUS_PENDING
&& RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
311 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
312 Status
= STATUS_CANT_WAIT
;
313 TotalBytesCopied
= 0;
314 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
315 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
316 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
317 TotalBytesCopied
, NULL
, TRUE
);
318 } else if( Status
== STATUS_PENDING
) {
319 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
320 IoMarkIrpPending( Irp
);
322 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
325 SocketStateUnlock( FCB
);
331 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
332 PAFD_STORED_DATAGRAM DatagramRecv
,
333 PUINT TotalBytesCopied
) {
334 NTSTATUS Status
= STATUS_SUCCESS
;
335 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
336 PAFD_RECV_INFO RecvReq
=
337 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
338 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
341 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
342 RecvReq
->BufferCount
+
346 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
348 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
349 RecvReq
->BufferArray
[0].len
));
352 /* Copy the address */
353 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
354 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
356 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
359 ("Wierd address count %d\n",
360 DatagramRecv
->Address
->TAAddressCount
));
363 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
365 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
367 RecvReq
->BufferArray
[1].len
);
369 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
371 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
373 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
375 RtlCopyMemory( Map
[1].BufferAddress
,
376 &DatagramRecv
->Address
->Address
->AddressType
,
379 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
381 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
383 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
384 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
385 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
388 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
390 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
392 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
394 Map
[0].BufferAddress
,
398 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
400 RtlCopyMemory( Map
[0].BufferAddress
,
401 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
404 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
406 FCB
->Recv
.BytesUsed
= 0;
407 *TotalBytesCopied
= BytesToCopy
;
410 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
411 Irp
->IoStatus
.Information
= BytesToCopy
;
412 ExFreePool( DatagramRecv
->Address
);
413 ExFreePool( DatagramRecv
);
415 AFD_DbgPrint(MID_TRACE
,("Done\n"));
421 PacketSocketRecvComplete(
422 PDEVICE_OBJECT DeviceObject
,
425 NTSTATUS Status
= STATUS_SUCCESS
;
426 PAFD_FCB FCB
= Context
;
428 PIO_STACK_LOCATION NextIrpSp
;
429 PLIST_ENTRY ListEntry
;
430 PAFD_RECV_INFO RecvReq
;
431 PAFD_STORED_DATAGRAM DatagramRecv
;
432 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
434 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
436 if( !SocketAcquireStateLock( FCB
) ) return STATUS_UNSUCCESSFUL
;
438 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
440 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
441 SocketStateUnlock( FCB
);
442 DestroySocket( FCB
);
443 return STATUS_SUCCESS
;
446 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
449 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
450 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
452 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
453 FCB
->AddressFrom
->RemoteAddress
));
454 DatagramRecv
->Address
=
455 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
457 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
458 } else Status
= STATUS_NO_MEMORY
;
460 /* Satisfy as many requests as we can */
462 while( NT_SUCCESS(Status
) &&
463 !IsListEmpty( &FCB
->DatagramList
) &&
464 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
465 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
466 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
467 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
469 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
470 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
471 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
472 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
474 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
475 RecvReq
, DatagramRecv
));
477 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
478 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
479 InsertHeadList( &FCB
->DatagramList
,
480 &DatagramRecv
->ListEntry
);
481 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
482 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
483 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
484 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
486 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
487 Status
= SatisfyPacketRecvRequest
488 ( FCB
, NextIrp
, DatagramRecv
,
489 (PUINT
)&NextIrp
->IoStatus
.Information
);
490 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
491 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
492 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
493 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
497 if( !IsListEmpty( &FCB
->DatagramList
) ) {
498 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
499 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
501 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
503 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
505 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
506 /* Now relaunch the datagram request */
507 SocketCalloutEnter( FCB
);
509 Status
= TdiReceiveDatagram
510 ( &FCB
->ReceiveIrp
.InFlightRequest
,
511 FCB
->AddressFile
.Object
,
516 &FCB
->ReceiveIrp
.Iosb
,
517 PacketSocketRecvComplete
,
520 SocketCalloutLeave( FCB
);
523 SocketStateUnlock( FCB
);
525 return STATUS_SUCCESS
;
529 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
530 PIO_STACK_LOCATION IrpSp
) {
531 NTSTATUS Status
= STATUS_SUCCESS
;
532 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
533 PAFD_FCB FCB
= FileObject
->FsContext
;
534 PAFD_RECV_INFO_UDP RecvReq
;
535 PLIST_ENTRY ListEntry
;
536 PAFD_STORED_DATAGRAM DatagramRecv
;
538 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
540 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
542 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
544 /* Check that the socket is bound */
545 if( FCB
->State
!= SOCKET_STATE_BOUND
)
546 return UnlockAndMaybeComplete
547 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
, FALSE
);
548 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
549 return UnlockAndMaybeComplete
550 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, FALSE
);
552 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
554 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
555 RecvReq
->BufferCount
,
557 RecvReq
->AddressLength
,
560 if( !IsListEmpty( &FCB
->DatagramList
) ) {
561 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
562 DatagramRecv
= CONTAINING_RECORD
563 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
564 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
565 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
566 InsertHeadList( &FCB
->DatagramList
,
567 &DatagramRecv
->ListEntry
);
568 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
569 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
571 if( IsListEmpty( &FCB
->DatagramList
) )
572 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
574 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
576 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
578 return UnlockAndMaybeComplete
579 ( FCB
, Status
, Irp
, RecvReq
->BufferArray
[0].len
, NULL
, TRUE
);
581 Status
= SatisfyPacketRecvRequest
582 ( FCB
, Irp
, DatagramRecv
,
583 (PUINT
)&Irp
->IoStatus
.Information
);
585 if( IsListEmpty( &FCB
->DatagramList
) )
586 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
588 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
590 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
592 return UnlockAndMaybeComplete
593 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
, TRUE
);
595 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
596 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
597 Status
= STATUS_CANT_WAIT
;
598 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
599 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);
601 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
602 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);