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
;
101 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
103 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
104 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
106 SocketCalloutEnter( FCB
);
108 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
109 FCB
->Connection
.Object
,
113 &FCB
->ReceiveIrp
.Iosb
,
117 SocketCalloutLeave( FCB
);
119 if( Status
== STATUS_SUCCESS
)
120 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
121 HandleEOFOnIrp( FCB
, Status
, FCB
->ReceiveIrp
.Iosb
.Information
);
125 return STATUS_SUCCESS
;
128 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
129 PLIST_ENTRY NextIrpEntry
;
131 PIO_STACK_LOCATION NextIrpSp
;
132 PAFD_RECV_INFO RecvReq
;
133 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
134 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
136 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
138 if( CantReadMore( FCB
) ) {
139 /* Success here means that we got an EOF. Complete a pending read
140 * with zero bytes if we haven't yet overread, then kill the others.
142 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
144 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
146 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
147 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
148 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
150 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
152 UnlockBuffers( RecvReq
->BufferArray
,
153 RecvReq
->BufferCount
, FALSE
);
154 Status
= NextIrp
->IoStatus
.Status
=
155 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
156 NextIrp
->IoStatus
.Information
= 0;
157 if( NextIrp
== Irp
) RetStatus
= Status
;
158 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
159 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
160 FCB
->Overread
= TRUE
;
161 //FCB->PollState |= AFD_EVENT_DISCONNECT;
162 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
165 /* Kick the user that receive would be possible now */
166 /* XXX Not implemented yet */
168 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
169 FCB
, FCB
->Recv
.Content
));
170 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
172 /* Try to clear some requests */
173 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
175 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
177 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
178 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
179 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
181 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
183 Status
= TryToSatisfyRecvRequestFromBuffer
184 ( FCB
, RecvReq
, &TotalBytesCopied
);
186 if( Status
== STATUS_PENDING
) {
187 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
188 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
189 &NextIrp
->Tail
.Overlay
.ListEntry
);
192 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
194 UnlockBuffers( RecvReq
->BufferArray
,
195 RecvReq
->BufferCount
, FALSE
);
196 NextIrp
->IoStatus
.Status
= Status
;
197 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
198 if( NextIrp
== Irp
) {
200 RetBytesCopied
= TotalBytesCopied
;
202 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
203 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
208 if( FCB
->Recv
.Content
) {
209 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
211 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
213 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
215 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
217 /* Sometimes we're called with a NULL Irp */
219 Irp
->IoStatus
.Status
= RetStatus
;
220 Irp
->IoStatus
.Information
= RetBytesCopied
;
226 NTSTATUS NTAPI ReceiveComplete
227 ( PDEVICE_OBJECT DeviceObject
,
230 NTSTATUS Status
= Irp
->IoStatus
.Status
;
231 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
233 AFD_DbgPrint(MID_TRACE
,("Called\n"));
235 ASSERT_IRQL(APC_LEVEL
);
238 if( FCB
) FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
239 return STATUS_CANCELLED
;
242 if( !SocketAcquireStateLock( FCB
) ) return Status
;
244 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
245 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
246 FCB
->Recv
.BytesUsed
= 0;
248 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
249 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
250 SocketStateUnlock( FCB
);
251 DestroySocket( FCB
);
252 return STATUS_SUCCESS
;
253 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
254 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
255 SocketStateUnlock( FCB
);
256 return STATUS_INVALID_PARAMETER
;
259 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
261 ReceiveActivity( FCB
, NULL
);
263 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
265 SocketStateUnlock( FCB
);
267 AFD_DbgPrint(MID_TRACE
,("Returned %x\n", Status
));
269 return STATUS_SUCCESS
;
273 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
274 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
275 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
276 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
277 PAFD_FCB FCB
= FileObject
->FsContext
;
278 PAFD_RECV_INFO RecvReq
;
279 UINT TotalBytesCopied
= 0;
281 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
283 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
285 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
286 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
287 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
289 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
293 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
295 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
296 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
300 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
301 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
303 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
304 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
307 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
309 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
310 RecvReq
->BufferCount
,
314 if( !RecvReq
->BufferArray
) {
315 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
319 Irp
->IoStatus
.Status
= STATUS_PENDING
;
320 Irp
->IoStatus
.Information
= 0;
322 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
323 &Irp
->Tail
.Overlay
.ListEntry
);
325 /************ From this point, the IRP is not ours ************/
327 Status
= ReceiveActivity( FCB
, Irp
);
329 if( Status
== STATUS_PENDING
&& RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
330 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
331 Status
= STATUS_CANT_WAIT
;
332 TotalBytesCopied
= 0;
333 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
334 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
335 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
336 TotalBytesCopied
, NULL
);
337 } else if( Status
== STATUS_PENDING
) {
338 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
339 IoMarkIrpPending( Irp
);
341 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
344 SocketStateUnlock( FCB
);
349 static NTSTATUS STDCALL
350 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
351 PAFD_STORED_DATAGRAM DatagramRecv
,
352 PUINT TotalBytesCopied
) {
353 NTSTATUS Status
= STATUS_SUCCESS
;
354 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
355 PAFD_RECV_INFO RecvReq
=
356 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
357 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
360 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
361 RecvReq
->BufferCount
+
365 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
367 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
368 RecvReq
->BufferArray
[0].len
));
371 /* Copy the address */
372 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
373 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
375 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
378 ("Wierd address count %d\n",
379 DatagramRecv
->Address
->TAAddressCount
));
382 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
384 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
386 RecvReq
->BufferArray
[1].len
);
388 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
390 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
392 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
394 RtlCopyMemory( Map
[1].BufferAddress
,
395 &DatagramRecv
->Address
->Address
->AddressType
,
398 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
400 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
402 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
403 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
404 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
407 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
409 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
411 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
413 Map
[0].BufferAddress
,
417 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
419 RtlCopyMemory( Map
[0].BufferAddress
,
420 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
423 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
425 *TotalBytesCopied
= BytesToCopy
;
427 if (!RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
) {
428 FCB
->Recv
.BytesUsed
= 0;
432 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
433 Irp
->IoStatus
.Information
= BytesToCopy
;
434 ExFreePool( DatagramRecv
->Address
);
435 ExFreePool( DatagramRecv
);
437 AFD_DbgPrint(MID_TRACE
,("Done\n"));
443 PacketSocketRecvComplete(
444 PDEVICE_OBJECT DeviceObject
,
447 NTSTATUS Status
= STATUS_SUCCESS
;
448 PAFD_FCB FCB
= Context
;
450 PIO_STACK_LOCATION NextIrpSp
;
451 PLIST_ENTRY ListEntry
;
452 PAFD_RECV_INFO RecvReq
;
453 PAFD_STORED_DATAGRAM DatagramRecv
;
454 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
456 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
459 if( FCB
) FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
460 return STATUS_CANCELLED
;
463 if( !SocketAcquireStateLock( FCB
) ) return STATUS_FILE_CLOSED
;
465 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
467 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
468 SocketStateUnlock( FCB
);
469 DestroySocket( FCB
);
470 return STATUS_SUCCESS
;
473 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
476 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
477 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
479 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
480 FCB
->AddressFrom
->RemoteAddress
));
481 DatagramRecv
->Address
=
482 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
484 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
486 } else Status
= STATUS_NO_MEMORY
;
488 if( !NT_SUCCESS( Status
) ) {
489 if( DatagramRecv
) ExFreePool( DatagramRecv
);
490 SocketStateUnlock( FCB
);
493 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
496 /* Satisfy as many requests as we can */
498 while( !IsListEmpty( &FCB
->DatagramList
) &&
499 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
500 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
501 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
502 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
504 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
505 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
506 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
507 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
509 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
510 RecvReq
, DatagramRecv
));
512 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
513 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
514 InsertHeadList( &FCB
->DatagramList
,
515 &DatagramRecv
->ListEntry
);
516 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
517 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
518 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
519 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
520 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
522 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
523 Status
= SatisfyPacketRecvRequest
524 ( FCB
, NextIrp
, DatagramRecv
,
525 (PUINT
)&NextIrp
->IoStatus
.Information
);
526 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
527 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
528 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
529 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
530 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
534 if( !IsListEmpty( &FCB
->DatagramList
) ) {
535 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
536 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
538 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
540 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
542 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
543 /* Now relaunch the datagram request */
544 SocketCalloutEnter( FCB
);
546 Status
= TdiReceiveDatagram
547 ( &FCB
->ReceiveIrp
.InFlightRequest
,
548 FCB
->AddressFile
.Object
,
553 &FCB
->ReceiveIrp
.Iosb
,
554 PacketSocketRecvComplete
,
557 SocketCalloutLeave( FCB
);
560 SocketStateUnlock( FCB
);
562 return STATUS_SUCCESS
;
566 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
567 PIO_STACK_LOCATION IrpSp
) {
568 NTSTATUS Status
= STATUS_SUCCESS
;
569 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
570 PAFD_FCB FCB
= FileObject
->FsContext
;
571 PAFD_RECV_INFO_UDP RecvReq
;
572 PLIST_ENTRY ListEntry
;
573 PAFD_STORED_DATAGRAM DatagramRecv
;
575 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
577 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
579 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
581 /* Check that the socket is bound */
582 if( FCB
->State
!= SOCKET_STATE_BOUND
)
583 return UnlockAndMaybeComplete
584 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0, NULL
);
585 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
586 return UnlockAndMaybeComplete
587 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
);
589 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
591 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
592 RecvReq
->BufferCount
,
594 RecvReq
->AddressLength
,
597 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
598 return UnlockAndMaybeComplete
599 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0, NULL
);
602 if( !IsListEmpty( &FCB
->DatagramList
) ) {
603 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
604 DatagramRecv
= CONTAINING_RECORD
605 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
606 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
607 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
608 InsertHeadList( &FCB
->DatagramList
,
609 &DatagramRecv
->ListEntry
);
610 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
611 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
613 if( IsListEmpty( &FCB
->DatagramList
) )
614 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
616 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
618 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
620 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
622 return UnlockAndMaybeComplete
623 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
);
625 Status
= SatisfyPacketRecvRequest
626 ( FCB
, Irp
, DatagramRecv
,
627 (PUINT
)&Irp
->IoStatus
.Information
);
629 if( IsListEmpty( &FCB
->DatagramList
) )
630 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
632 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
634 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
636 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
638 return UnlockAndMaybeComplete
639 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
);
641 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
642 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
643 Status
= STATUS_CANT_WAIT
;
644 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
645 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
646 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
);
648 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
649 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);