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 static 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 static 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_DISCONNECT
;
40 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
44 static 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
;
52 *TotalBytesCopied
= 0;
55 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
58 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
59 if( !BytesAvailable
) return STATUS_PENDING
;
61 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
63 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
65 RecvReq
->BufferArray
));
67 RecvReq
->BufferArray
&&
69 i
< RecvReq
->BufferCount
;
72 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
75 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
77 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
82 RtlCopyMemory( Map
[i
].BufferAddress
,
83 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
86 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
88 *TotalBytesCopied
+= BytesToCopy
;
90 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
91 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
92 BytesAvailable
-= BytesToCopy
;
97 /* If there's nothing left in our buffer start a new request */
98 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
99 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
100 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
102 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
103 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
105 SocketCalloutEnter( FCB
);
107 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
108 FCB
->Connection
.Object
,
112 &FCB
->ReceiveIrp
.Iosb
,
116 SocketCalloutLeave( FCB
);
118 if( Status
== STATUS_SUCCESS
)
119 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
120 HandleEOFOnIrp( FCB
, Status
, FCB
->ReceiveIrp
.Iosb
.Information
);
124 return STATUS_SUCCESS
;
127 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
128 PLIST_ENTRY NextIrpEntry
;
130 PIO_STACK_LOCATION NextIrpSp
;
131 PAFD_RECV_INFO RecvReq
;
132 UINT TotalBytesCopied
= 0;
133 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
135 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
137 if( CantReadMore( FCB
) ) {
138 /* Success here means that we got an EOF. Complete a pending read
139 * with zero bytes if we haven't yet overread, then kill the others.
141 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
143 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
145 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
146 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
147 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
149 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
151 UnlockBuffers( RecvReq
->BufferArray
,
152 RecvReq
->BufferCount
, FALSE
);
153 Status
= NextIrp
->IoStatus
.Status
=
154 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
155 NextIrp
->IoStatus
.Information
= 0;
156 if( NextIrp
== Irp
) RetStatus
= Status
;
157 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
158 FCB
->Overread
= TRUE
;
159 //FCB->PollState |= AFD_EVENT_DISCONNECT;
160 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
163 /* Kick the user that receive would be possible now */
164 /* XXX Not implemented yet */
166 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
167 FCB
, FCB
->Recv
.Content
));
168 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
170 Status
= STATUS_SUCCESS
;
172 /* Try to clear some requests */
173 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) &&
174 NT_SUCCESS(Status
) ) {
176 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
178 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
179 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
180 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
182 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
184 Status
= TryToSatisfyRecvRequestFromBuffer
185 ( FCB
, RecvReq
, &TotalBytesCopied
);
187 if( Status
== STATUS_PENDING
) {
188 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
189 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
190 &NextIrp
->Tail
.Overlay
.ListEntry
);
193 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
195 UnlockBuffers( RecvReq
->BufferArray
,
196 RecvReq
->BufferCount
, FALSE
);
197 NextIrp
->IoStatus
.Status
= Status
;
198 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
199 if( NextIrp
== Irp
) RetStatus
= Status
;
200 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
205 if( FCB
->Recv
.Content
) {
206 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
208 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
210 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
212 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
217 NTSTATUS NTAPI ReceiveComplete
218 ( PDEVICE_OBJECT DeviceObject
,
221 NTSTATUS Status
= Irp
->IoStatus
.Status
;
222 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
224 AFD_DbgPrint(MID_TRACE
,("Called\n"));
226 ASSERT_IRQL(APC_LEVEL
);
228 if( !SocketAcquireStateLock( FCB
) ) return Status
;
230 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
231 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
232 FCB
->Recv
.BytesUsed
= 0;
234 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
235 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
236 SocketStateUnlock( FCB
);
237 DestroySocket( FCB
);
238 return STATUS_SUCCESS
;
239 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
240 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
241 SocketStateUnlock( FCB
);
242 return STATUS_UNSUCCESSFUL
;
245 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
247 ReceiveActivity( FCB
, NULL
);
249 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
251 SocketStateUnlock( FCB
);
253 AFD_DbgPrint(MID_TRACE
,("Returned %x\n", Status
));
255 return STATUS_SUCCESS
;
259 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
260 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
261 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
262 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
263 PAFD_FCB FCB
= FileObject
->FsContext
;
264 PAFD_RECV_INFO RecvReq
;
265 UINT TotalBytesCopied
= 0;
267 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
269 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
271 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
272 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
273 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
275 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
,
276 Irp
, 0, NULL
, FALSE
);
279 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
281 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
282 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
283 Irp
, 0, NULL
, FALSE
);
286 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
287 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
289 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
290 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
291 Irp
, 0, NULL
, FALSE
);
293 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
295 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
296 RecvReq
->BufferCount
,
300 if( !RecvReq
->BufferArray
) {
301 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
302 Irp
, 0, NULL
, FALSE
);
305 Irp
->IoStatus
.Status
= STATUS_PENDING
;
306 Irp
->IoStatus
.Information
= 0;
308 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
309 &Irp
->Tail
.Overlay
.ListEntry
);
311 /************ From this point, the IRP is not ours ************/
313 Status
= ReceiveActivity( FCB
, Irp
);
315 if( Status
== STATUS_PENDING
&& RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
316 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
317 Status
= STATUS_CANT_WAIT
;
318 TotalBytesCopied
= 0;
319 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
320 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
321 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
322 TotalBytesCopied
, NULL
, TRUE
);
323 } else if( Status
== STATUS_PENDING
) {
324 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
325 IoMarkIrpPending( Irp
);
327 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
330 SocketStateUnlock( FCB
);
335 static NTSTATUS STDCALL
336 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
337 PAFD_STORED_DATAGRAM DatagramRecv
,
338 PUINT TotalBytesCopied
) {
339 NTSTATUS Status
= STATUS_SUCCESS
;
340 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
341 PAFD_RECV_INFO RecvReq
=
342 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
343 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
346 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
347 RecvReq
->BufferCount
+
351 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
353 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
354 RecvReq
->BufferArray
[0].len
));
357 /* Copy the address */
358 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
359 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
361 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
364 ("Wierd address count %d\n",
365 DatagramRecv
->Address
->TAAddressCount
));
368 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
370 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
372 RecvReq
->BufferArray
[1].len
);
374 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
376 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
378 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
380 RtlCopyMemory( Map
[1].BufferAddress
,
381 &DatagramRecv
->Address
->Address
->AddressType
,
384 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
386 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
388 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
389 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
390 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
393 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
395 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
397 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
399 Map
[0].BufferAddress
,
403 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
405 RtlCopyMemory( Map
[0].BufferAddress
,
406 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
409 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
411 *TotalBytesCopied
= BytesToCopy
;
413 if (!RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
) {
414 FCB
->Recv
.BytesUsed
= 0;
418 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
419 Irp
->IoStatus
.Information
= BytesToCopy
;
420 ExFreePool( DatagramRecv
->Address
);
421 ExFreePool( DatagramRecv
);
423 AFD_DbgPrint(MID_TRACE
,("Done\n"));
429 PacketSocketRecvComplete(
430 PDEVICE_OBJECT DeviceObject
,
433 NTSTATUS Status
= STATUS_SUCCESS
;
434 PAFD_FCB FCB
= Context
;
436 PIO_STACK_LOCATION NextIrpSp
;
437 PLIST_ENTRY ListEntry
;
438 PAFD_RECV_INFO RecvReq
;
439 PAFD_STORED_DATAGRAM DatagramRecv
;
440 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
442 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
444 if( !SocketAcquireStateLock( FCB
) ) return STATUS_UNSUCCESSFUL
;
446 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
448 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
449 SocketStateUnlock( FCB
);
450 DestroySocket( FCB
);
451 return STATUS_SUCCESS
;
454 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
457 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
458 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
460 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
461 FCB
->AddressFrom
->RemoteAddress
));
462 DatagramRecv
->Address
=
463 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
465 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
466 } else Status
= STATUS_NO_MEMORY
;
468 /* Satisfy as many requests as we can */
470 while( NT_SUCCESS(Status
) &&
471 !IsListEmpty( &FCB
->DatagramList
) &&
472 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
473 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
474 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
475 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
477 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
478 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
479 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
480 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
482 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
483 RecvReq
, DatagramRecv
));
485 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
486 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
487 InsertHeadList( &FCB
->DatagramList
,
488 &DatagramRecv
->ListEntry
);
489 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
490 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
491 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
492 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
494 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
495 Status
= SatisfyPacketRecvRequest
496 ( FCB
, NextIrp
, DatagramRecv
,
497 (PUINT
)&NextIrp
->IoStatus
.Information
);
498 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
499 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
500 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
501 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
505 if( !IsListEmpty( &FCB
->DatagramList
) ) {
506 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
507 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
509 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
511 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
513 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
514 /* Now relaunch the datagram request */
515 SocketCalloutEnter( FCB
);
517 Status
= TdiReceiveDatagram
518 ( &FCB
->ReceiveIrp
.InFlightRequest
,
519 FCB
->AddressFile
.Object
,
524 &FCB
->ReceiveIrp
.Iosb
,
525 PacketSocketRecvComplete
,
528 SocketCalloutLeave( FCB
);
531 SocketStateUnlock( FCB
);
533 return STATUS_SUCCESS
;
537 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
538 PIO_STACK_LOCATION IrpSp
) {
539 NTSTATUS Status
= STATUS_SUCCESS
;
540 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
541 PAFD_FCB FCB
= FileObject
->FsContext
;
542 PAFD_RECV_INFO_UDP RecvReq
;
543 PLIST_ENTRY ListEntry
;
544 PAFD_STORED_DATAGRAM DatagramRecv
;
546 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
548 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
550 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
552 /* Check that the socket is bound */
553 if( FCB
->State
!= SOCKET_STATE_BOUND
)
554 return UnlockAndMaybeComplete
555 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
, FALSE
);
556 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
557 return UnlockAndMaybeComplete
558 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, FALSE
);
560 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
562 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
563 RecvReq
->BufferCount
,
565 RecvReq
->AddressLength
,
568 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
569 return UnlockAndMaybeComplete
570 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0, NULL
, FALSE
);
573 if( !IsListEmpty( &FCB
->DatagramList
) ) {
574 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
575 DatagramRecv
= CONTAINING_RECORD
576 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
577 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
578 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
579 InsertHeadList( &FCB
->DatagramList
,
580 &DatagramRecv
->ListEntry
);
581 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
582 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
584 if( IsListEmpty( &FCB
->DatagramList
) )
585 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
587 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
589 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
591 return UnlockAndMaybeComplete
592 ( FCB
, Status
, Irp
, RecvReq
->BufferArray
[0].len
, NULL
, TRUE
);
594 Status
= SatisfyPacketRecvRequest
595 ( FCB
, Irp
, DatagramRecv
,
596 (PUINT
)&Irp
->IoStatus
.Information
);
598 if( IsListEmpty( &FCB
->DatagramList
) )
599 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
601 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
603 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
605 return UnlockAndMaybeComplete
606 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
, TRUE
);
608 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
609 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
610 Status
= STATUS_CANT_WAIT
;
611 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
612 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);
614 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
615 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);