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 NTSTATUS
RefillSocketBuffer( PAFD_FCB FCB
) {
30 NTSTATUS Status
= STATUS_PENDING
;
32 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
33 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
35 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
36 FCB
->Connection
.Object
,
40 &FCB
->ReceiveIrp
.Iosb
,
44 if( ( Status
== STATUS_SUCCESS
&& !FCB
->ReceiveIrp
.Iosb
.Information
) ||
45 ( !NT_SUCCESS( Status
) ) )
47 /* The socket has been closed */
48 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
50 Status
= STATUS_FILE_CLOSED
;
52 else if( Status
== STATUS_SUCCESS
)
54 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
55 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
57 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
63 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
64 PAFD_RECV_INFO RecvReq
,
65 PUINT TotalBytesCopied
) {
66 UINT i
, BytesToCopy
= 0,
68 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
71 *TotalBytesCopied
= 0;
74 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
77 if( FCB
->Overread
) return STATUS_FILE_CLOSED
;
78 if( !BytesAvailable
) {
79 FCB
->Recv
.Content
= FCB
->Recv
.BytesUsed
= 0;
80 Status
= RefillSocketBuffer( FCB
);
81 if ( Status
!= STATUS_SUCCESS
)
84 /* If RefillSocketBuffer returns STATUS_SUCCESS, we're good to go
85 * If RefillSocketBuffer returns STATUS_PENDING, then it's waiting on the transport for data
86 * If RefillSocketBuffer returns STATUS_FILE_CLOSED, then the connection was terminated
89 /* Recalculate BytesAvailable based on new data */
90 BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
91 ASSERT(BytesAvailable
);
94 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
96 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
98 RecvReq
->BufferArray
));
100 RecvReq
->BufferArray
&&
102 i
< RecvReq
->BufferCount
;
105 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
108 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
110 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
112 Map
[i
].BufferAddress
,
115 RtlCopyMemory( Map
[i
].BufferAddress
,
116 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
119 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
121 *TotalBytesCopied
+= BytesToCopy
;
123 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
124 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
125 BytesAvailable
-= BytesToCopy
;
130 /* If there's nothing left in our buffer start a new request */
131 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
132 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
133 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
135 RefillSocketBuffer( FCB
);
138 return STATUS_SUCCESS
;
141 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
142 PLIST_ENTRY NextIrpEntry
;
144 PIO_STACK_LOCATION NextIrpSp
;
145 PAFD_RECV_INFO RecvReq
;
146 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
147 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
149 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
151 /* Kick the user that receive would be possible now */
152 /* XXX Not implemented yet */
154 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
155 FCB
, FCB
->Recv
.Content
));
157 /* Try to clear some requests */
158 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
159 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
160 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
161 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
162 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
164 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
166 Status
= TryToSatisfyRecvRequestFromBuffer( FCB
, RecvReq
, &TotalBytesCopied
);
168 if( Status
== STATUS_PENDING
) {
169 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
170 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
171 &NextIrp
->Tail
.Overlay
.ListEntry
);
174 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
176 UnlockBuffers( RecvReq
->BufferArray
,
177 RecvReq
->BufferCount
, FALSE
);
178 NextIrp
->IoStatus
.Status
= Status
;
179 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
180 if( NextIrp
== Irp
) {
182 RetBytesCopied
= TotalBytesCopied
;
184 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
185 (void)IoSetCancelRoutine(NextIrp
, NULL
);
186 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
190 if( !FCB
->Recv
.Content
) {
191 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
193 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
195 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
197 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
199 /* Sometimes we're called with a NULL Irp */
201 Irp
->IoStatus
.Status
= RetStatus
;
202 Irp
->IoStatus
.Information
= RetBytesCopied
;
208 NTSTATUS NTAPI ReceiveComplete
209 ( PDEVICE_OBJECT DeviceObject
,
212 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
213 PLIST_ENTRY NextIrpEntry
;
215 PAFD_RECV_INFO RecvReq
;
216 PIO_STACK_LOCATION NextIrpSp
;
218 AFD_DbgPrint(MID_TRACE
,("Called\n"));
220 if( !SocketAcquireStateLock( FCB
) )
221 return STATUS_FILE_CLOSED
;
223 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
225 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
226 FCB
->Recv
.BytesUsed
= 0;
228 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
229 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
230 /* Cleanup our IRP queue because the FCB is being destroyed */
231 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
232 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
233 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
234 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
235 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
236 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
237 NextIrp
->IoStatus
.Information
= 0;
238 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
239 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
240 (void)IoSetCancelRoutine(NextIrp
, NULL
);
241 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
243 SocketStateUnlock( FCB
);
244 return STATUS_FILE_CLOSED
;
245 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
246 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
247 SocketStateUnlock( FCB
);
248 return STATUS_INVALID_PARAMETER
;
251 ReceiveActivity( FCB
, NULL
);
253 SocketStateUnlock( FCB
);
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
);
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_INVALID_PARAMETER
,
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
,
286 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
287 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
290 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
292 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
293 RecvReq
->BufferCount
,
297 if( !RecvReq
->BufferArray
) {
298 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
302 Irp
->IoStatus
.Status
= STATUS_PENDING
;
303 Irp
->IoStatus
.Information
= 0;
305 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
306 &Irp
->Tail
.Overlay
.ListEntry
);
308 /************ From this point, the IRP is not ours ************/
310 Status
= ReceiveActivity( FCB
, Irp
);
312 if( Status
== STATUS_PENDING
&& (RecvReq
->AfdFlags
& AFD_IMMEDIATE
) ) {
313 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
314 Status
= STATUS_CANT_WAIT
;
315 TotalBytesCopied
= 0;
316 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
317 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
318 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
320 } else if( Status
== STATUS_PENDING
) {
321 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
322 IoMarkIrpPending( Irp
);
323 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
325 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
328 SocketStateUnlock( FCB
);
333 static NTSTATUS NTAPI
334 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
335 PAFD_STORED_DATAGRAM DatagramRecv
,
336 PUINT TotalBytesCopied
) {
337 NTSTATUS Status
= STATUS_SUCCESS
;
338 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
339 PAFD_RECV_INFO RecvReq
=
340 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
341 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
344 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
345 RecvReq
->BufferCount
+
349 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
351 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
352 RecvReq
->BufferArray
[0].len
));
355 /* Copy the address */
356 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
357 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
359 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
362 ("Wierd address count %d\n",
363 DatagramRecv
->Address
->TAAddressCount
));
366 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
368 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
370 RecvReq
->BufferArray
[1].len
);
372 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
374 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
376 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
378 RtlCopyMemory( Map
[1].BufferAddress
,
379 &DatagramRecv
->Address
->Address
->AddressType
,
382 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
384 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
386 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
387 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
388 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
391 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
393 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
395 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
397 Map
[0].BufferAddress
,
401 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
403 RtlCopyMemory( Map
[0].BufferAddress
,
404 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
407 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
409 *TotalBytesCopied
= BytesToCopy
;
411 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
412 FCB
->Recv
.BytesUsed
= 0;
416 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
417 Irp
->IoStatus
.Information
= BytesToCopy
;
418 ExFreePool( DatagramRecv
->Address
);
419 ExFreePool( DatagramRecv
);
421 AFD_DbgPrint(MID_TRACE
,("Done\n"));
427 PacketSocketRecvComplete(
428 PDEVICE_OBJECT DeviceObject
,
431 NTSTATUS Status
= STATUS_SUCCESS
;
432 PAFD_FCB FCB
= Context
;
434 PIO_STACK_LOCATION NextIrpSp
;
435 PLIST_ENTRY ListEntry
;
436 PAFD_RECV_INFO RecvReq
;
437 PAFD_STORED_DATAGRAM DatagramRecv
;
438 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
439 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
441 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
443 if( !SocketAcquireStateLock( FCB
) )
444 return STATUS_FILE_CLOSED
;
446 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
448 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
449 /* Cleanup our IRP queue because the FCB is being destroyed */
450 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
451 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
452 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
453 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
454 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
455 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
456 NextIrp
->IoStatus
.Information
= 0;
457 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
458 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
459 (void)IoSetCancelRoutine(NextIrp
, NULL
);
460 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
463 /* Free all items on the datagram list */
464 while( !IsListEmpty( &FCB
->DatagramList
) ) {
465 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
466 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
467 ExFreePool( DatagramRecv
->Address
);
468 ExFreePool( DatagramRecv
);
471 SocketStateUnlock( FCB
);
472 return STATUS_FILE_CLOSED
;
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 (void)IoSetCancelRoutine(NextIrp
, NULL
);
523 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
525 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
526 Status
= SatisfyPacketRecvRequest
527 ( FCB
, NextIrp
, DatagramRecv
,
528 (PUINT
)&NextIrp
->IoStatus
.Information
);
529 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
530 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
531 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
532 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
533 (void)IoSetCancelRoutine(NextIrp
, NULL
);
534 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
538 if( !IsListEmpty( &FCB
->DatagramList
) ) {
539 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
540 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
542 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
544 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
546 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
547 /* Now relaunch the datagram request */
548 Status
= TdiReceiveDatagram
549 ( &FCB
->ReceiveIrp
.InFlightRequest
,
550 FCB
->AddressFile
.Object
,
555 &FCB
->ReceiveIrp
.Iosb
,
556 PacketSocketRecvComplete
,
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 /* Check that the socket is bound */
580 if( FCB
->State
!= SOCKET_STATE_BOUND
)
581 return UnlockAndMaybeComplete
582 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
583 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
584 return UnlockAndMaybeComplete
585 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
587 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
589 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
590 RecvReq
->BufferCount
,
592 RecvReq
->AddressLength
,
595 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
596 return UnlockAndMaybeComplete
597 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0 );
600 if( !IsListEmpty( &FCB
->DatagramList
) ) {
601 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
602 DatagramRecv
= CONTAINING_RECORD
603 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
604 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
605 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
606 InsertHeadList( &FCB
->DatagramList
,
607 &DatagramRecv
->ListEntry
);
608 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
609 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
611 if( IsListEmpty( &FCB
->DatagramList
) )
612 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
614 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
616 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
618 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
620 return UnlockAndMaybeComplete
621 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
623 Status
= SatisfyPacketRecvRequest
624 ( FCB
, Irp
, DatagramRecv
,
625 (PUINT
)&Irp
->IoStatus
.Information
);
627 if( IsListEmpty( &FCB
->DatagramList
) )
628 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
630 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
632 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
634 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
636 return UnlockAndMaybeComplete
637 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
639 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
640 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
641 Status
= STATUS_CANT_WAIT
;
642 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
643 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
644 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
645 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
647 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
648 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
649 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);