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
;
35 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
36 PAFD_RECV_INFO RecvReq
,
37 PUINT TotalBytesCopied
) {
38 UINT i
, BytesToCopy
= 0,
40 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
43 *TotalBytesCopied
= 0;
46 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
49 if( CantReadMore(FCB
) ) return STATUS_PENDING
;
51 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
53 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
55 RecvReq
->BufferArray
));
57 RecvReq
->BufferArray
&&
59 i
< RecvReq
->BufferCount
;
62 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
65 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
67 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
72 RtlCopyMemory( Map
[i
].BufferAddress
,
73 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
76 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
78 *TotalBytesCopied
+= BytesToCopy
;
80 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
81 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
82 BytesAvailable
-= BytesToCopy
;
87 /* If there's nothing left in our buffer start a new request */
88 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
89 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
90 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
91 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
93 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
94 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
96 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
97 FCB
->Connection
.Object
,
101 &FCB
->ReceiveIrp
.Iosb
,
105 if( Status
== STATUS_SUCCESS
)
106 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
110 return STATUS_SUCCESS
;
113 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
114 PLIST_ENTRY NextIrpEntry
;
116 PIO_STACK_LOCATION NextIrpSp
;
117 PAFD_RECV_INFO RecvReq
;
118 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
119 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
121 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
123 /* Kick the user that receive would be possible now */
124 /* XXX Not implemented yet */
126 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
127 FCB
, FCB
->Recv
.Content
));
129 /* Try to clear some requests */
130 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
131 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
132 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
133 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
134 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
136 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
138 Status
= TryToSatisfyRecvRequestFromBuffer( FCB
, RecvReq
, &TotalBytesCopied
);
140 if( Status
== STATUS_PENDING
) {
141 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
142 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
143 &NextIrp
->Tail
.Overlay
.ListEntry
);
146 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
148 UnlockBuffers( RecvReq
->BufferArray
,
149 RecvReq
->BufferCount
, FALSE
);
150 NextIrp
->IoStatus
.Status
= Status
;
151 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
152 if( NextIrp
== Irp
) {
154 RetBytesCopied
= TotalBytesCopied
;
156 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
157 (void)IoSetCancelRoutine(NextIrp
, NULL
);
158 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
162 if( !CantReadMore(FCB
) ) {
163 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
165 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
167 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
169 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
171 /* Sometimes we're called with a NULL Irp */
173 Irp
->IoStatus
.Status
= RetStatus
;
174 Irp
->IoStatus
.Information
= RetBytesCopied
;
180 NTSTATUS NTAPI ReceiveComplete
181 ( PDEVICE_OBJECT DeviceObject
,
184 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
185 PLIST_ENTRY NextIrpEntry
;
187 PAFD_RECV_INFO RecvReq
;
188 PIO_STACK_LOCATION NextIrpSp
;
190 AFD_DbgPrint(MID_TRACE
,("Called\n"));
192 if( !SocketAcquireStateLock( FCB
) )
193 return STATUS_FILE_CLOSED
;
195 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
197 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
198 FCB
->Recv
.BytesUsed
= 0;
200 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
201 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
202 /* Cleanup our IRP queue because the FCB is being destroyed */
203 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
204 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
205 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
206 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
207 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
208 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
209 NextIrp
->IoStatus
.Information
= 0;
210 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
211 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
212 (void)IoSetCancelRoutine(NextIrp
, NULL
);
213 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
215 SocketStateUnlock( FCB
);
216 return STATUS_FILE_CLOSED
;
217 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
218 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
219 SocketStateUnlock( FCB
);
220 return STATUS_INVALID_PARAMETER
;
223 ReceiveActivity( FCB
, NULL
);
225 SocketStateUnlock( FCB
);
227 return STATUS_SUCCESS
;
231 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
232 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
233 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
234 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
235 PAFD_FCB FCB
= FileObject
->FsContext
;
236 PAFD_RECV_INFO RecvReq
;
237 UINT TotalBytesCopied
= 0;
239 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
241 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
243 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
244 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
245 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
247 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
251 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
253 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
254 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
258 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
259 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
262 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
264 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
265 RecvReq
->BufferCount
,
269 if( !RecvReq
->BufferArray
) {
270 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
274 Irp
->IoStatus
.Status
= STATUS_PENDING
;
275 Irp
->IoStatus
.Information
= 0;
277 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
278 &Irp
->Tail
.Overlay
.ListEntry
);
280 /************ From this point, the IRP is not ours ************/
282 Status
= ReceiveActivity( FCB
, Irp
);
284 if( Status
== STATUS_PENDING
&& (RecvReq
->AfdFlags
& AFD_IMMEDIATE
) ) {
285 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
286 Status
= STATUS_CANT_WAIT
;
287 TotalBytesCopied
= 0;
288 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
289 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
290 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
292 } else if( Status
== STATUS_PENDING
) {
293 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
294 IoMarkIrpPending( Irp
);
295 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
297 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
300 SocketStateUnlock( FCB
);
305 static NTSTATUS NTAPI
306 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
307 PAFD_STORED_DATAGRAM DatagramRecv
,
308 PUINT TotalBytesCopied
) {
309 NTSTATUS Status
= STATUS_SUCCESS
;
310 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
311 PAFD_RECV_INFO RecvReq
=
312 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
313 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
316 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
317 RecvReq
->BufferCount
+
321 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
323 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
324 RecvReq
->BufferArray
[0].len
));
327 /* Copy the address */
328 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
329 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
331 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
334 ("Wierd address count %d\n",
335 DatagramRecv
->Address
->TAAddressCount
));
338 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
340 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
342 RecvReq
->BufferArray
[1].len
);
344 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
346 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
348 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
350 RtlCopyMemory( Map
[1].BufferAddress
,
351 &DatagramRecv
->Address
->Address
->AddressType
,
354 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
356 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
358 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
359 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
360 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
363 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
365 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
367 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
369 Map
[0].BufferAddress
,
373 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
375 RtlCopyMemory( Map
[0].BufferAddress
,
376 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
379 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
381 *TotalBytesCopied
= BytesToCopy
;
383 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
384 FCB
->Recv
.BytesUsed
= 0;
388 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
389 Irp
->IoStatus
.Information
= BytesToCopy
;
390 ExFreePool( DatagramRecv
->Address
);
391 ExFreePool( DatagramRecv
);
393 AFD_DbgPrint(MID_TRACE
,("Done\n"));
399 PacketSocketRecvComplete(
400 PDEVICE_OBJECT DeviceObject
,
403 NTSTATUS Status
= STATUS_SUCCESS
;
404 PAFD_FCB FCB
= Context
;
406 PIO_STACK_LOCATION NextIrpSp
;
407 PLIST_ENTRY ListEntry
;
408 PAFD_RECV_INFO RecvReq
;
409 PAFD_STORED_DATAGRAM DatagramRecv
;
410 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
411 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
413 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
415 if( !SocketAcquireStateLock( FCB
) )
416 return STATUS_FILE_CLOSED
;
418 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
420 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
421 /* Cleanup our IRP queue because the FCB is being destroyed */
422 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
423 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
424 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
425 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
426 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
427 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
428 NextIrp
->IoStatus
.Information
= 0;
429 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
430 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
431 (void)IoSetCancelRoutine(NextIrp
, NULL
);
432 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
435 /* Free all items on the datagram list */
436 while( !IsListEmpty( &FCB
->DatagramList
) ) {
437 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
438 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
439 ExFreePool( DatagramRecv
->Address
);
440 ExFreePool( DatagramRecv
);
443 SocketStateUnlock( FCB
);
444 return STATUS_FILE_CLOSED
;
447 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
450 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
451 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
453 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
454 FCB
->AddressFrom
->RemoteAddress
));
455 DatagramRecv
->Address
=
456 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
458 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
460 } else Status
= STATUS_NO_MEMORY
;
462 if( !NT_SUCCESS( Status
) ) {
463 if( DatagramRecv
) ExFreePool( DatagramRecv
);
464 SocketStateUnlock( FCB
);
467 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
470 /* Satisfy as many requests as we can */
472 while( !IsListEmpty( &FCB
->DatagramList
) &&
473 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
474 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
475 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
476 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
478 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
479 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
480 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
481 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
483 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
484 RecvReq
, DatagramRecv
));
486 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
487 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
488 InsertHeadList( &FCB
->DatagramList
,
489 &DatagramRecv
->ListEntry
);
490 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
491 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
492 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
493 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
494 (void)IoSetCancelRoutine(NextIrp
, NULL
);
495 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
497 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
498 Status
= SatisfyPacketRecvRequest
499 ( FCB
, NextIrp
, DatagramRecv
,
500 (PUINT
)&NextIrp
->IoStatus
.Information
);
501 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
502 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
503 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
504 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
505 (void)IoSetCancelRoutine(NextIrp
, NULL
);
506 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
510 if( !IsListEmpty( &FCB
->DatagramList
) ) {
511 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
512 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
514 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
516 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
518 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
519 /* Now relaunch the datagram request */
520 Status
= TdiReceiveDatagram
521 ( &FCB
->ReceiveIrp
.InFlightRequest
,
522 FCB
->AddressFile
.Object
,
527 &FCB
->ReceiveIrp
.Iosb
,
528 PacketSocketRecvComplete
,
532 SocketStateUnlock( FCB
);
534 return STATUS_SUCCESS
;
538 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
539 PIO_STACK_LOCATION IrpSp
) {
540 NTSTATUS Status
= STATUS_SUCCESS
;
541 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
542 PAFD_FCB FCB
= FileObject
->FsContext
;
543 PAFD_RECV_INFO_UDP RecvReq
;
544 PLIST_ENTRY ListEntry
;
545 PAFD_STORED_DATAGRAM DatagramRecv
;
547 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
549 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
551 /* Check that the socket is bound */
552 if( FCB
->State
!= SOCKET_STATE_BOUND
)
553 return UnlockAndMaybeComplete
554 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
555 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
556 return UnlockAndMaybeComplete
557 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
559 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
561 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
562 RecvReq
->BufferCount
,
564 RecvReq
->AddressLength
,
567 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
568 return UnlockAndMaybeComplete
569 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0 );
572 if( !IsListEmpty( &FCB
->DatagramList
) ) {
573 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
574 DatagramRecv
= CONTAINING_RECORD
575 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
576 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
577 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
578 InsertHeadList( &FCB
->DatagramList
,
579 &DatagramRecv
->ListEntry
);
580 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
581 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
583 if( IsListEmpty( &FCB
->DatagramList
) )
584 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
586 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
588 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
590 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
592 return UnlockAndMaybeComplete
593 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
595 Status
= SatisfyPacketRecvRequest
596 ( FCB
, Irp
, DatagramRecv
,
597 (PUINT
)&Irp
->IoStatus
.Information
);
599 if( IsListEmpty( &FCB
->DatagramList
) )
600 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
602 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
604 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
606 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
608 return UnlockAndMaybeComplete
609 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
611 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
612 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
613 Status
= STATUS_CANT_WAIT
;
614 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
615 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
616 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
617 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
619 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
620 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
621 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);