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( !NT_SUCCESS(Status
) ||
38 (Status
== STATUS_SUCCESS
&& Information
== 0) ) {
39 AFD_DbgPrint(MID_TRACE
,("Looks like an EOF\n"));
40 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
41 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
45 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
46 PAFD_RECV_INFO RecvReq
,
47 PUINT TotalBytesCopied
) {
48 UINT i
, BytesToCopy
= 0,
50 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
53 *TotalBytesCopied
= 0;
56 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
59 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
60 if( !BytesAvailable
) return STATUS_PENDING
;
62 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
64 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
66 RecvReq
->BufferArray
));
68 RecvReq
->BufferArray
&&
70 i
< RecvReq
->BufferCount
;
73 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
76 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
78 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
83 RtlCopyMemory( Map
[i
].BufferAddress
,
84 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
87 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
89 *TotalBytesCopied
+= BytesToCopy
;
91 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
92 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
93 BytesAvailable
-= BytesToCopy
;
98 /* If there's nothing left in our buffer start a new request */
99 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
100 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
101 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
102 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
104 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
105 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
107 SocketCalloutEnter( FCB
);
109 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
110 FCB
->Connection
.Object
,
114 &FCB
->ReceiveIrp
.Iosb
,
118 SocketCalloutLeave( FCB
);
120 if( Status
== STATUS_SUCCESS
)
121 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
122 HandleEOFOnIrp( FCB
, Status
, FCB
->ReceiveIrp
.Iosb
.Information
);
126 return STATUS_SUCCESS
;
129 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
130 PLIST_ENTRY NextIrpEntry
;
132 PIO_STACK_LOCATION NextIrpSp
;
133 PAFD_RECV_INFO RecvReq
;
134 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
135 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
137 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
139 if( CantReadMore( FCB
) ) {
140 /* Success here means that we got an EOF. Complete a pending read
141 * with zero bytes if we haven't yet overread, then kill the others.
143 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
145 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
147 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
148 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
149 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
151 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
153 UnlockBuffers( RecvReq
->BufferArray
,
154 RecvReq
->BufferCount
, FALSE
);
155 Status
= NextIrp
->IoStatus
.Status
=
156 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
157 NextIrp
->IoStatus
.Information
= 0;
158 if( NextIrp
== Irp
) RetStatus
= Status
;
159 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
160 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
161 FCB
->Overread
= TRUE
;
162 //FCB->PollState |= AFD_EVENT_DISCONNECT;
163 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
166 /* Kick the user that receive would be possible now */
167 /* XXX Not implemented yet */
169 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
170 FCB
, FCB
->Recv
.Content
));
171 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
173 /* Try to clear some requests */
174 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
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
) {
201 RetBytesCopied
= TotalBytesCopied
;
203 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
204 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
209 if( FCB
->Recv
.Content
) {
210 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
212 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
214 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
216 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
218 /* Sometimes we're called with a NULL Irp */
220 Irp
->IoStatus
.Status
= RetStatus
;
221 Irp
->IoStatus
.Information
= RetBytesCopied
;
227 NTSTATUS NTAPI ReceiveComplete
228 ( PDEVICE_OBJECT DeviceObject
,
231 NTSTATUS Status
= Irp
->IoStatus
.Status
;
232 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
234 AFD_DbgPrint(MID_TRACE
,("Called\n"));
236 ASSERT_IRQL(APC_LEVEL
);
238 if( !SocketAcquireStateLock( FCB
) ) return Status
;
240 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
243 SocketStateUnlock( FCB
);
244 return STATUS_CANCELLED
;
247 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
248 FCB
->Recv
.BytesUsed
= 0;
250 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
251 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
252 SocketStateUnlock( FCB
);
253 DestroySocket( FCB
);
254 return STATUS_SUCCESS
;
255 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
256 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
257 SocketStateUnlock( FCB
);
258 return STATUS_INVALID_PARAMETER
;
261 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
263 ReceiveActivity( FCB
, NULL
);
265 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
267 SocketStateUnlock( FCB
);
269 AFD_DbgPrint(MID_TRACE
,("Returned %x\n", Status
));
271 return STATUS_SUCCESS
;
275 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
276 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
277 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
278 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
279 PAFD_FCB FCB
= FileObject
->FsContext
;
280 PAFD_RECV_INFO RecvReq
;
281 UINT TotalBytesCopied
= 0;
283 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
285 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
287 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
288 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
289 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
291 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
295 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
297 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
298 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
302 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
303 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
305 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
306 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
309 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
311 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
312 RecvReq
->BufferCount
,
316 if( !RecvReq
->BufferArray
) {
317 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
321 Irp
->IoStatus
.Status
= STATUS_PENDING
;
322 Irp
->IoStatus
.Information
= 0;
324 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
325 &Irp
->Tail
.Overlay
.ListEntry
);
327 /************ From this point, the IRP is not ours ************/
329 Status
= ReceiveActivity( FCB
, Irp
);
331 if( Status
== STATUS_PENDING
&& RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
332 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
333 Status
= STATUS_CANT_WAIT
;
334 TotalBytesCopied
= 0;
335 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
336 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
337 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
338 TotalBytesCopied
, NULL
);
339 } else if( Status
== STATUS_PENDING
) {
340 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
341 IoMarkIrpPending( Irp
);
343 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
346 SocketStateUnlock( FCB
);
351 static NTSTATUS NTAPI
352 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
353 PAFD_STORED_DATAGRAM DatagramRecv
,
354 PUINT TotalBytesCopied
) {
355 NTSTATUS Status
= STATUS_SUCCESS
;
356 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
357 PAFD_RECV_INFO RecvReq
=
358 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
359 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
362 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
363 RecvReq
->BufferCount
+
367 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
369 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
370 RecvReq
->BufferArray
[0].len
));
373 /* Copy the address */
374 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
375 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
377 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
380 ("Wierd address count %d\n",
381 DatagramRecv
->Address
->TAAddressCount
));
384 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
386 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
388 RecvReq
->BufferArray
[1].len
);
390 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
392 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
394 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
396 RtlCopyMemory( Map
[1].BufferAddress
,
397 &DatagramRecv
->Address
->Address
->AddressType
,
400 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
402 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
404 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
405 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
406 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
409 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
411 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
413 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
415 Map
[0].BufferAddress
,
419 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
421 RtlCopyMemory( Map
[0].BufferAddress
,
422 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
425 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
427 *TotalBytesCopied
= BytesToCopy
;
429 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
430 FCB
->Recv
.BytesUsed
= 0;
434 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
435 Irp
->IoStatus
.Information
= BytesToCopy
;
436 ExFreePool( DatagramRecv
->Address
);
437 ExFreePool( DatagramRecv
);
439 AFD_DbgPrint(MID_TRACE
,("Done\n"));
445 PacketSocketRecvComplete(
446 PDEVICE_OBJECT DeviceObject
,
449 NTSTATUS Status
= STATUS_SUCCESS
;
450 PAFD_FCB FCB
= Context
;
452 PIO_STACK_LOCATION NextIrpSp
;
453 PLIST_ENTRY ListEntry
;
454 PAFD_RECV_INFO RecvReq
;
455 PAFD_STORED_DATAGRAM DatagramRecv
;
456 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
458 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
460 if( !SocketAcquireStateLock( FCB
) ) return STATUS_FILE_CLOSED
;
462 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
465 SocketStateUnlock( FCB
);
466 return STATUS_CANCELLED
;
469 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
470 SocketStateUnlock( FCB
);
471 DestroySocket( FCB
);
472 return STATUS_SUCCESS
;
475 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
478 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
479 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
481 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
482 FCB
->AddressFrom
->RemoteAddress
));
483 DatagramRecv
->Address
=
484 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
486 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
488 } else Status
= STATUS_NO_MEMORY
;
490 if( !NT_SUCCESS( Status
) ) {
491 if( DatagramRecv
) ExFreePool( DatagramRecv
);
492 SocketStateUnlock( FCB
);
495 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
498 /* Satisfy as many requests as we can */
500 while( !IsListEmpty( &FCB
->DatagramList
) &&
501 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
502 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
503 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
504 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
506 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
507 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
508 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
509 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
511 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
512 RecvReq
, DatagramRecv
));
514 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
515 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
516 InsertHeadList( &FCB
->DatagramList
,
517 &DatagramRecv
->ListEntry
);
518 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
519 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
520 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
521 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
522 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
524 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
525 Status
= SatisfyPacketRecvRequest
526 ( FCB
, NextIrp
, DatagramRecv
,
527 (PUINT
)&NextIrp
->IoStatus
.Information
);
528 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
529 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
530 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
531 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
532 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
536 if( !IsListEmpty( &FCB
->DatagramList
) ) {
537 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
538 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
540 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
542 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
544 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
545 /* Now relaunch the datagram request */
546 SocketCalloutEnter( FCB
);
548 Status
= TdiReceiveDatagram
549 ( &FCB
->ReceiveIrp
.InFlightRequest
,
550 FCB
->AddressFile
.Object
,
555 &FCB
->ReceiveIrp
.Iosb
,
556 PacketSocketRecvComplete
,
559 SocketCalloutLeave( FCB
);
562 SocketStateUnlock( FCB
);
564 return STATUS_SUCCESS
;
568 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
569 PIO_STACK_LOCATION IrpSp
) {
570 NTSTATUS Status
= STATUS_SUCCESS
;
571 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
572 PAFD_FCB FCB
= FileObject
->FsContext
;
573 PAFD_RECV_INFO_UDP RecvReq
;
574 PLIST_ENTRY ListEntry
;
575 PAFD_STORED_DATAGRAM DatagramRecv
;
577 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
579 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
581 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
583 /* Check that the socket is bound */
584 if( FCB
->State
!= SOCKET_STATE_BOUND
)
585 return UnlockAndMaybeComplete
586 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0, NULL
);
587 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
588 return UnlockAndMaybeComplete
589 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
);
591 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
593 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
594 RecvReq
->BufferCount
,
596 RecvReq
->AddressLength
,
599 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
600 return UnlockAndMaybeComplete
601 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0, NULL
);
604 if( !IsListEmpty( &FCB
->DatagramList
) ) {
605 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
606 DatagramRecv
= CONTAINING_RECORD
607 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
608 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
609 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
610 InsertHeadList( &FCB
->DatagramList
,
611 &DatagramRecv
->ListEntry
);
612 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
613 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
615 if( IsListEmpty( &FCB
->DatagramList
) )
616 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
618 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
620 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
622 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
624 return UnlockAndMaybeComplete
625 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
);
627 Status
= SatisfyPacketRecvRequest
628 ( FCB
, Irp
, DatagramRecv
,
629 (PUINT
)&Irp
->IoStatus
.Information
);
631 if( IsListEmpty( &FCB
->DatagramList
) )
632 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
634 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
636 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
638 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
640 return UnlockAndMaybeComplete
641 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
, NULL
);
643 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
644 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
645 Status
= STATUS_CANT_WAIT
;
646 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
647 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
648 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
);
650 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
651 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);