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)
13 static VOID
RefillSocketBuffer( PAFD_FCB FCB
)
15 /* Make sure nothing's in flight first */
16 if (FCB
->ReceiveIrp
.InFlightRequest
) return;
18 /* Now ensure that receive is still allowed */
19 if (FCB
->TdiReceiveClosed
) return;
21 /* Check if the buffer is full */
22 if (FCB
->Recv
.Content
== FCB
->Recv
.Size
)
24 /* If there are bytes used, we can solve this problem */
25 if (FCB
->Recv
.BytesUsed
!= 0)
27 /* Reposition the unused portion to the beginning of the receive window */
28 RtlMoveMemory(FCB
->Recv
.Window
,
29 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
30 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
);
32 FCB
->Recv
.Content
-= FCB
->Recv
.BytesUsed
;
33 FCB
->Recv
.BytesUsed
= 0;
37 /* No space in the buffer to receive */
42 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
44 TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
45 FCB
->Connection
.Object
,
47 FCB
->Recv
.Window
+ FCB
->Recv
.Content
,
48 FCB
->Recv
.Size
- FCB
->Recv
.Content
,
49 &FCB
->ReceiveIrp
.Iosb
,
54 static VOID
HandleReceiveComplete( PAFD_FCB FCB
, NTSTATUS Status
, ULONG_PTR Information
)
56 FCB
->LastReceiveStatus
= Status
;
58 /* We got closed while the receive was in progress */
59 if (FCB
->TdiReceiveClosed
)
61 /* The received data is discarded */
63 /* Receive successful */
64 else if (Status
== STATUS_SUCCESS
)
66 FCB
->Recv
.Content
+= Information
;
67 ASSERT(FCB
->Recv
.Content
<= FCB
->Recv
.Size
);
69 /* Check for graceful closure */
72 /* Receive is closed */
73 FCB
->TdiReceiveClosed
= TRUE
;
77 /* Issue another receive IRP to keep the buffer well stocked */
78 RefillSocketBuffer(FCB
);
81 /* Receive failed with no data (unexpected closure) */
84 /* Previously received data remains intact */
85 FCB
->TdiReceiveClosed
= TRUE
;
89 static BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
90 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
92 return !BytesAvailable
&& FCB
->TdiReceiveClosed
;
95 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
96 PAFD_RECV_INFO RecvReq
,
97 PUINT TotalBytesCopied
) {
98 UINT i
, BytesToCopy
= 0, FcbBytesCopied
= FCB
->Recv
.BytesUsed
,
100 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
102 *TotalBytesCopied
= 0;
105 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %u\n", BytesAvailable
));
107 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
108 if( !BytesAvailable
) return STATUS_PENDING
;
110 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
112 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %u @ %p\n",
113 RecvReq
->BufferCount
,
114 RecvReq
->BufferArray
));
116 RecvReq
->BufferArray
&&
118 i
< RecvReq
->BufferCount
;
121 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
124 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
126 AFD_DbgPrint(MID_TRACE
,("Buffer %u: %p:%u\n",
128 Map
[i
].BufferAddress
,
131 RtlCopyMemory( Map
[i
].BufferAddress
,
132 FCB
->Recv
.Window
+ FcbBytesCopied
,
135 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
137 *TotalBytesCopied
+= BytesToCopy
;
138 FcbBytesCopied
+= BytesToCopy
;
139 BytesAvailable
-= BytesToCopy
;
141 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
142 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
146 /* Issue another receive IRP to keep the buffer well stocked */
147 RefillSocketBuffer(FCB
);
149 return STATUS_SUCCESS
;
152 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
153 PLIST_ENTRY NextIrpEntry
;
155 PIO_STACK_LOCATION NextIrpSp
;
156 PAFD_RECV_INFO RecvReq
;
157 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
158 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
160 AFD_DbgPrint(MID_TRACE
,("%p %p\n", FCB
, Irp
));
162 AFD_DbgPrint(MID_TRACE
,("FCB %p Receive data waiting %u\n",
163 FCB
, FCB
->Recv
.Content
));
165 if( CantReadMore( FCB
) ) {
166 /* Success here means that we got an EOF. Complete a pending read
167 * with zero bytes if we haven't yet overread, then kill the others.
169 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
170 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
171 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
172 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
173 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
175 AFD_DbgPrint(MID_TRACE
,("Completing recv %p (%u)\n", NextIrp
,
177 UnlockBuffers( RecvReq
->BufferArray
,
178 RecvReq
->BufferCount
, FALSE
);
179 if (FCB
->Overread
&& FCB
->LastReceiveStatus
== STATUS_SUCCESS
)
181 /* Overread after a graceful disconnect so complete with an error */
182 Status
= STATUS_FILE_CLOSED
;
186 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */
187 Status
= FCB
->LastReceiveStatus
;
189 NextIrp
->IoStatus
.Status
= Status
;
190 NextIrp
->IoStatus
.Information
= 0;
191 if( NextIrp
== Irp
) RetStatus
= Status
;
192 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
193 (void)IoSetCancelRoutine(NextIrp
, NULL
);
194 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
195 FCB
->Overread
= TRUE
;
198 /* Kick the user that receive would be possible now */
199 /* XXX Not implemented yet */
201 AFD_DbgPrint(MID_TRACE
,("FCB %p Receive data waiting %u\n",
202 FCB
, FCB
->Recv
.Content
));
203 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
205 /* Try to clear some requests */
206 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
207 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
208 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
209 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
210 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
212 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %p\n", RecvReq
));
214 Status
= TryToSatisfyRecvRequestFromBuffer
215 ( FCB
, RecvReq
, &TotalBytesCopied
);
217 if( Status
== STATUS_PENDING
) {
218 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %p\n", NextIrp
));
219 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
220 &NextIrp
->Tail
.Overlay
.ListEntry
);
223 AFD_DbgPrint(MID_TRACE
,("Completing recv %p (%u)\n", NextIrp
,
225 UnlockBuffers( RecvReq
->BufferArray
,
226 RecvReq
->BufferCount
, FALSE
);
227 NextIrp
->IoStatus
.Status
= Status
;
228 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
229 if( NextIrp
== Irp
) {
231 RetBytesCopied
= TotalBytesCopied
;
233 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
234 (void)IoSetCancelRoutine(NextIrp
, NULL
);
235 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
240 if( FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
&&
241 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
242 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
243 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
244 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
248 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
251 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
252 if (CantReadMore(FCB
))
254 if (FCB
->LastReceiveStatus
== STATUS_SUCCESS
)
256 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
260 FCB
->PollState
|= AFD_EVENT_CLOSE
;
262 FCB
->PollStatus
[FD_CLOSE_BIT
] = FCB
->LastReceiveStatus
;
263 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
266 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %p is %x\n", Irp
, RetStatus
));
268 /* Sometimes we're called with a NULL Irp */
270 Irp
->IoStatus
.Status
= RetStatus
;
271 Irp
->IoStatus
.Information
= RetBytesCopied
;
277 NTSTATUS NTAPI ReceiveComplete
278 ( PDEVICE_OBJECT DeviceObject
,
281 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
282 PLIST_ENTRY NextIrpEntry
;
284 PAFD_RECV_INFO RecvReq
;
285 PIO_STACK_LOCATION NextIrpSp
;
287 UNREFERENCED_PARAMETER(DeviceObject
);
289 AFD_DbgPrint(MID_TRACE
,("Called\n"));
291 if( !SocketAcquireStateLock( FCB
) )
292 return STATUS_FILE_CLOSED
;
294 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
295 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
297 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
298 /* Cleanup our IRP queue because the FCB is being destroyed */
299 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
300 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
301 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
302 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
303 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
304 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
305 NextIrp
->IoStatus
.Information
= 0;
306 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
307 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
308 (void)IoSetCancelRoutine(NextIrp
, NULL
);
309 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
311 SocketStateUnlock( FCB
);
312 return STATUS_FILE_CLOSED
;
313 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
314 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
315 SocketStateUnlock( FCB
);
316 return STATUS_INVALID_PARAMETER
;
319 HandleReceiveComplete( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
321 ReceiveActivity( FCB
, NULL
);
323 SocketStateUnlock( FCB
);
325 return STATUS_SUCCESS
;
328 static NTSTATUS NTAPI
329 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
330 PAFD_STORED_DATAGRAM DatagramRecv
,
331 PUINT TotalBytesCopied
) {
332 NTSTATUS Status
= STATUS_SUCCESS
;
333 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
334 PAFD_RECV_INFO RecvReq
=
335 GetLockedData(Irp
, IrpSp
);
336 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
338 BOOLEAN ExtraBuffers
= CheckUnlockExtraBuffers(FCB
, IrpSp
);
340 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
341 RecvReq
->BufferCount
+
342 (ExtraBuffers
? EXTRA_LOCK_BUFFERS
: 0));
344 BytesToCopy
= MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
346 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %u len %u\n", BytesToCopy
,
347 RecvReq
->BufferArray
[0].len
));
350 /* Copy the address */
351 if( ExtraBuffers
&& Map
[1].Mdl
&& Map
[2].Mdl
) {
352 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
354 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
357 ("Wierd address count %d\n",
358 DatagramRecv
->Address
->TAAddressCount
));
361 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
363 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
365 RecvReq
->BufferArray
[1].len
);
367 AFD_DbgPrint(MID_TRACE
,("Copying %u bytes of address\n", AddrLen
));
369 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
371 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
373 RtlCopyMemory( Map
[1].BufferAddress
,
374 &DatagramRecv
->Address
->Address
->AddressType
,
377 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
379 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
381 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
382 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
383 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
386 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
388 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
390 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %p:%u\n",
392 Map
[0].BufferAddress
,
395 RtlCopyMemory( Map
[0].BufferAddress
,
396 DatagramRecv
->Buffer
,
399 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
401 *TotalBytesCopied
= BytesToCopy
;
404 if (*TotalBytesCopied
== DatagramRecv
->Len
)
406 /* We copied the whole datagram */
407 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
411 /* We only copied part of the datagram */
412 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
415 Irp
->IoStatus
.Information
= *TotalBytesCopied
;
417 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
419 FCB
->Recv
.Content
-= DatagramRecv
->Len
;
420 ExFreePool( DatagramRecv
->Address
);
421 ExFreePool( DatagramRecv
);
424 AFD_DbgPrint(MID_TRACE
,("Done\n"));
430 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
431 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
432 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
433 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
434 PAFD_FCB FCB
= FileObject
->FsContext
;
435 PAFD_RECV_INFO RecvReq
;
436 UINT TotalBytesCopied
= 0;
437 PAFD_STORED_DATAGRAM DatagramRecv
;
438 PLIST_ENTRY ListEntry
;
439 KPROCESSOR_MODE LockMode
;
441 UNREFERENCED_PARAMETER(DeviceObject
);
442 UNREFERENCED_PARAMETER(Short
);
444 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
446 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
448 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
450 if( !(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) &&
451 FCB
->State
!= SOCKET_STATE_CONNECTED
&&
452 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
453 AFD_DbgPrint(MIN_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
455 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
459 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
460 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
463 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
465 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
466 RecvReq
->BufferCount
,
468 TRUE
, FALSE
, LockMode
);
470 if( !RecvReq
->BufferArray
) {
471 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
475 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
477 if (!IsListEmpty(&FCB
->DatagramList
))
479 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
480 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
481 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
482 (PUINT
)&Irp
->IoStatus
.Information
);
484 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
486 InsertHeadList(&FCB
->DatagramList
,
487 &DatagramRecv
->ListEntry
);
490 if (!IsListEmpty(&FCB
->DatagramList
))
492 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
493 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
494 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
497 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
499 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
501 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
503 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
504 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
506 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
507 Status
= STATUS_CANT_WAIT
;
508 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
509 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
510 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
514 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
515 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);
519 Irp
->IoStatus
.Status
= STATUS_PENDING
;
520 Irp
->IoStatus
.Information
= 0;
522 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
523 &Irp
->Tail
.Overlay
.ListEntry
);
525 /************ From this point, the IRP is not ours ************/
527 Status
= ReceiveActivity( FCB
, Irp
);
529 if( Status
== STATUS_PENDING
&&
530 !(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
531 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
532 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
533 Status
= STATUS_CANT_WAIT
;
534 TotalBytesCopied
= 0;
535 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
536 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
537 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
539 } else if( Status
== STATUS_PENDING
) {
540 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
541 IoMarkIrpPending( Irp
);
542 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
544 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
547 SocketStateUnlock( FCB
);
552 PacketSocketRecvComplete(
553 PDEVICE_OBJECT DeviceObject
,
556 NTSTATUS Status
= STATUS_SUCCESS
;
557 PAFD_FCB FCB
= Context
;
559 PIO_STACK_LOCATION NextIrpSp
;
560 PLIST_ENTRY ListEntry
;
561 PAFD_RECV_INFO RecvReq
;
562 PAFD_STORED_DATAGRAM DatagramRecv
;
563 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
564 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
566 UNREFERENCED_PARAMETER(DeviceObject
);
568 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
570 if( !SocketAcquireStateLock( FCB
) )
571 return STATUS_FILE_CLOSED
;
573 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
574 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
576 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
577 /* Cleanup our IRP queue because the FCB is being destroyed */
578 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
579 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
580 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
581 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
582 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
583 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
584 NextIrp
->IoStatus
.Information
= 0;
585 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
));
586 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
587 (void)IoSetCancelRoutine(NextIrp
, NULL
);
588 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
591 /* Free all items on the datagram list */
592 while( !IsListEmpty( &FCB
->DatagramList
) ) {
593 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
594 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
595 ExFreePool( DatagramRecv
->Address
);
596 ExFreePool( DatagramRecv
);
599 SocketStateUnlock( FCB
);
600 return STATUS_FILE_CLOSED
;
603 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
605 SocketStateUnlock(FCB
);
606 return Irp
->IoStatus
.Status
;
609 if (FCB
->TdiReceiveClosed
)
611 SocketStateUnlock(FCB
);
612 return STATUS_FILE_CLOSED
;
615 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
618 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
619 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
621 AFD_DbgPrint(MID_TRACE
,("Received (A %p)\n",
622 FCB
->AddressFrom
->RemoteAddress
));
623 DatagramRecv
->Address
=
624 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
626 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
628 } else Status
= STATUS_NO_MEMORY
;
630 if( !NT_SUCCESS( Status
) ) {
631 if( DatagramRecv
) ExFreePool( DatagramRecv
);
632 SocketStateUnlock( FCB
);
635 FCB
->Recv
.Content
+= DatagramRecv
->Len
;
636 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
639 /* Satisfy as many requests as we can */
641 while( !IsListEmpty( &FCB
->DatagramList
) &&
642 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
643 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
644 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
645 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
647 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
648 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
649 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
650 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
652 AFD_DbgPrint(MID_TRACE
,("RecvReq: %p, DatagramRecv: %p\n",
653 RecvReq
, DatagramRecv
));
655 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
656 Status
= SatisfyPacketRecvRequest
657 ( FCB
, NextIrp
, DatagramRecv
,
658 (PUINT
)&NextIrp
->IoStatus
.Information
);
660 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
662 InsertHeadList(&FCB
->DatagramList
,
663 &DatagramRecv
->ListEntry
);
666 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
667 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
) );
668 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
670 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
671 (void)IoSetCancelRoutine(NextIrp
, NULL
);
672 NextIrp
->IoStatus
.Status
= Status
;
674 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
677 if( !IsListEmpty( &FCB
->DatagramList
) && IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
678 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
679 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
680 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
681 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
683 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
685 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
686 /* Now relaunch the datagram request */
687 Status
= TdiReceiveDatagram
688 ( &FCB
->ReceiveIrp
.InFlightRequest
,
689 FCB
->AddressFile
.Object
,
694 &FCB
->ReceiveIrp
.Iosb
,
695 PacketSocketRecvComplete
,
699 SocketStateUnlock( FCB
);
701 return STATUS_SUCCESS
;
705 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
706 PIO_STACK_LOCATION IrpSp
) {
707 NTSTATUS Status
= STATUS_SUCCESS
;
708 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
709 PAFD_FCB FCB
= FileObject
->FsContext
;
710 PAFD_RECV_INFO_UDP RecvReq
;
711 PLIST_ENTRY ListEntry
;
712 PAFD_STORED_DATAGRAM DatagramRecv
;
713 KPROCESSOR_MODE LockMode
;
715 UNREFERENCED_PARAMETER(DeviceObject
);
717 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
719 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
721 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
723 /* Check that the socket is bound */
724 if( FCB
->State
!= SOCKET_STATE_BOUND
)
726 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
727 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
730 if (FCB
->TdiReceiveClosed
)
732 AFD_DbgPrint(MIN_TRACE
,("Receive closed\n"));
733 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
736 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
737 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
739 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
741 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
742 RecvReq
->BufferCount
,
744 RecvReq
->AddressLength
,
745 TRUE
, TRUE
, LockMode
);
747 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
748 return UnlockAndMaybeComplete(FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0);
751 if (!IsListEmpty(&FCB
->DatagramList
))
753 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
754 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
755 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
756 (PUINT
)&Irp
->IoStatus
.Information
);
758 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
760 InsertHeadList(&FCB
->DatagramList
,
761 &DatagramRecv
->ListEntry
);
764 if (!IsListEmpty(&FCB
->DatagramList
))
766 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
767 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
768 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
771 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
773 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
775 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
777 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
778 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
780 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
781 Status
= STATUS_CANT_WAIT
;
782 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
783 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
784 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
788 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
789 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);