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)
12 static VOID
RefillSocketBuffer( PAFD_FCB FCB
)
14 /* Make sure nothing's in flight first */
15 if (FCB
->ReceiveIrp
.InFlightRequest
) return;
17 /* Now ensure that receive is still allowed */
18 if (FCB
->TdiReceiveClosed
) return;
20 /* Check if the buffer is full */
21 if (FCB
->Recv
.Content
== FCB
->Recv
.Size
)
23 /* If there are bytes used, we can solve this problem */
24 if (FCB
->Recv
.BytesUsed
!= 0)
26 /* Reposition the unused portion to the beginning of the receive window */
27 RtlMoveMemory(FCB
->Recv
.Window
,
28 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
29 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
);
31 FCB
->Recv
.Content
-= FCB
->Recv
.BytesUsed
;
32 FCB
->Recv
.BytesUsed
= 0;
36 /* No space in the buffer to receive */
41 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
43 TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
44 FCB
->Connection
.Object
,
46 FCB
->Recv
.Window
+ FCB
->Recv
.Content
,
47 FCB
->Recv
.Size
- FCB
->Recv
.Content
,
48 &FCB
->ReceiveIrp
.Iosb
,
53 static VOID
HandleReceiveComplete( PAFD_FCB FCB
, NTSTATUS Status
, ULONG_PTR Information
)
55 FCB
->LastReceiveStatus
= Status
;
57 /* We got closed while the receive was in progress */
58 if (FCB
->TdiReceiveClosed
)
60 /* The received data is discarded */
62 /* Receive successful */
63 else if (Status
== STATUS_SUCCESS
)
65 FCB
->Recv
.Content
+= Information
;
66 ASSERT(FCB
->Recv
.Content
<= FCB
->Recv
.Size
);
68 /* Check for graceful closure */
71 /* Receive is closed */
72 FCB
->TdiReceiveClosed
= TRUE
;
76 /* Issue another receive IRP to keep the buffer well stocked */
77 RefillSocketBuffer(FCB
);
80 /* Receive failed with no data (unexpected closure) */
83 /* Previously received data remains intact */
84 FCB
->TdiReceiveClosed
= TRUE
;
88 static BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
89 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
91 return !BytesAvailable
&& FCB
->TdiReceiveClosed
;
94 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
95 PAFD_RECV_INFO RecvReq
,
96 PUINT TotalBytesCopied
) {
97 UINT i
, BytesToCopy
= 0, FcbBytesCopied
= FCB
->Recv
.BytesUsed
,
99 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
101 *TotalBytesCopied
= 0;
104 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
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: %d @ %x\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 %d: %x:%d\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
,("%x %x\n", FCB
, Irp
));
162 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\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 %x (%d)\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 %x Receive data waiting %d\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 @ %x\n", RecvReq
));
214 Status
= TryToSatisfyRecvRequestFromBuffer
215 ( FCB
, RecvReq
, &TotalBytesCopied
);
217 if( Status
== STATUS_PENDING
) {
218 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
219 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
220 &NextIrp
->Tail
.Overlay
.ListEntry
);
223 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\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 %x 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 AFD_DbgPrint(MID_TRACE
,("Called\n"));
289 if( !SocketAcquireStateLock( FCB
) )
290 return STATUS_FILE_CLOSED
;
292 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
293 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
295 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
296 /* Cleanup our IRP queue because the FCB is being destroyed */
297 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
298 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
299 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
300 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
301 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
302 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
303 NextIrp
->IoStatus
.Information
= 0;
304 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
305 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
306 (void)IoSetCancelRoutine(NextIrp
, NULL
);
307 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
309 SocketStateUnlock( FCB
);
310 return STATUS_FILE_CLOSED
;
311 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
312 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
313 SocketStateUnlock( FCB
);
314 return STATUS_INVALID_PARAMETER
;
317 HandleReceiveComplete( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
319 ReceiveActivity( FCB
, NULL
);
321 SocketStateUnlock( FCB
);
323 return STATUS_SUCCESS
;
326 static NTSTATUS NTAPI
327 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
328 PAFD_STORED_DATAGRAM DatagramRecv
,
329 PUINT TotalBytesCopied
) {
330 NTSTATUS Status
= STATUS_SUCCESS
;
331 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
332 PAFD_RECV_INFO RecvReq
=
333 GetLockedData(Irp
, IrpSp
);
334 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
336 BOOLEAN ExtraBuffers
= CheckUnlockExtraBuffers(FCB
, IrpSp
);
338 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
339 RecvReq
->BufferCount
+
340 (ExtraBuffers
? EXTRA_LOCK_BUFFERS
: 0));
342 BytesToCopy
= MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
344 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
345 RecvReq
->BufferArray
[0].len
));
348 /* Copy the address */
349 if( ExtraBuffers
&& Map
[1].Mdl
&& Map
[2].Mdl
) {
350 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
352 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
355 ("Wierd address count %d\n",
356 DatagramRecv
->Address
->TAAddressCount
));
359 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
361 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
363 RecvReq
->BufferArray
[1].len
);
365 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
367 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
369 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
371 RtlCopyMemory( Map
[1].BufferAddress
,
372 &DatagramRecv
->Address
->Address
->AddressType
,
375 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
377 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
379 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
380 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
381 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
384 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
386 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
388 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
390 Map
[0].BufferAddress
,
393 RtlCopyMemory( Map
[0].BufferAddress
,
394 DatagramRecv
->Buffer
,
397 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
399 *TotalBytesCopied
= BytesToCopy
;
402 if (*TotalBytesCopied
== DatagramRecv
->Len
)
404 /* We copied the whole datagram */
405 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
409 /* We only copied part of the datagram */
410 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
413 Irp
->IoStatus
.Information
= *TotalBytesCopied
;
415 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
417 FCB
->Recv
.Content
-= DatagramRecv
->Len
;
418 ExFreePool( DatagramRecv
->Address
);
419 ExFreePool( DatagramRecv
);
422 AFD_DbgPrint(MID_TRACE
,("Done\n"));
428 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
429 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
430 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
431 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
432 PAFD_FCB FCB
= FileObject
->FsContext
;
433 PAFD_RECV_INFO RecvReq
;
434 UINT TotalBytesCopied
= 0;
435 PAFD_STORED_DATAGRAM DatagramRecv
;
436 PLIST_ENTRY ListEntry
;
437 KPROCESSOR_MODE LockMode
;
439 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
441 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
443 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
445 if( !(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) &&
446 FCB
->State
!= SOCKET_STATE_CONNECTED
&&
447 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
448 AFD_DbgPrint(MIN_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
450 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
454 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
455 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
458 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
460 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
461 RecvReq
->BufferCount
,
463 TRUE
, FALSE
, LockMode
);
465 if( !RecvReq
->BufferArray
) {
466 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
470 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
472 if (!IsListEmpty(&FCB
->DatagramList
))
474 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
475 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
476 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
477 (PUINT
)&Irp
->IoStatus
.Information
);
479 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
481 InsertHeadList(&FCB
->DatagramList
,
482 &DatagramRecv
->ListEntry
);
485 if (!IsListEmpty(&FCB
->DatagramList
))
487 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
488 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
489 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
492 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
494 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
496 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
498 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
499 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
501 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
502 Status
= STATUS_CANT_WAIT
;
503 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
504 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
505 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
509 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
510 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);
514 Irp
->IoStatus
.Status
= STATUS_PENDING
;
515 Irp
->IoStatus
.Information
= 0;
517 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
518 &Irp
->Tail
.Overlay
.ListEntry
);
520 /************ From this point, the IRP is not ours ************/
522 Status
= ReceiveActivity( FCB
, Irp
);
524 if( Status
== STATUS_PENDING
&&
525 !(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
526 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
527 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
528 Status
= STATUS_CANT_WAIT
;
529 TotalBytesCopied
= 0;
530 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
531 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
532 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
534 } else if( Status
== STATUS_PENDING
) {
535 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
536 IoMarkIrpPending( Irp
);
537 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
539 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
542 SocketStateUnlock( FCB
);
547 PacketSocketRecvComplete(
548 PDEVICE_OBJECT DeviceObject
,
551 NTSTATUS Status
= STATUS_SUCCESS
;
552 PAFD_FCB FCB
= Context
;
554 PIO_STACK_LOCATION NextIrpSp
;
555 PLIST_ENTRY ListEntry
;
556 PAFD_RECV_INFO RecvReq
;
557 PAFD_STORED_DATAGRAM DatagramRecv
;
558 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
559 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
561 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
563 if( !SocketAcquireStateLock( FCB
) )
564 return STATUS_FILE_CLOSED
;
566 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
567 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
569 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
570 /* Cleanup our IRP queue because the FCB is being destroyed */
571 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
572 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
573 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
574 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
575 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
576 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
577 NextIrp
->IoStatus
.Information
= 0;
578 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
));
579 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
580 (void)IoSetCancelRoutine(NextIrp
, NULL
);
581 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
584 /* Free all items on the datagram list */
585 while( !IsListEmpty( &FCB
->DatagramList
) ) {
586 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
587 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
588 ExFreePool( DatagramRecv
->Address
);
589 ExFreePool( DatagramRecv
);
592 SocketStateUnlock( FCB
);
593 return STATUS_FILE_CLOSED
;
596 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
598 SocketStateUnlock(FCB
);
599 return Irp
->IoStatus
.Status
;
602 if (FCB
->TdiReceiveClosed
)
604 SocketStateUnlock(FCB
);
605 return STATUS_FILE_CLOSED
;
608 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
611 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
612 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
614 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
615 FCB
->AddressFrom
->RemoteAddress
));
616 DatagramRecv
->Address
=
617 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
619 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
621 } else Status
= STATUS_NO_MEMORY
;
623 if( !NT_SUCCESS( Status
) ) {
624 if( DatagramRecv
) ExFreePool( DatagramRecv
);
625 SocketStateUnlock( FCB
);
628 FCB
->Recv
.Content
+= DatagramRecv
->Len
;
629 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
632 /* Satisfy as many requests as we can */
634 while( !IsListEmpty( &FCB
->DatagramList
) &&
635 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
636 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
637 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
638 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
640 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
641 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
642 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
643 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
645 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
646 RecvReq
, DatagramRecv
));
648 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
649 Status
= SatisfyPacketRecvRequest
650 ( FCB
, NextIrp
, DatagramRecv
,
651 (PUINT
)&NextIrp
->IoStatus
.Information
);
653 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
655 InsertHeadList(&FCB
->DatagramList
,
656 &DatagramRecv
->ListEntry
);
659 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
660 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
) );
661 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
663 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
664 (void)IoSetCancelRoutine(NextIrp
, NULL
);
665 NextIrp
->IoStatus
.Status
= Status
;
667 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
670 if( !IsListEmpty( &FCB
->DatagramList
) && IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
671 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
672 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
673 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
674 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
676 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
678 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
679 /* Now relaunch the datagram request */
680 Status
= TdiReceiveDatagram
681 ( &FCB
->ReceiveIrp
.InFlightRequest
,
682 FCB
->AddressFile
.Object
,
687 &FCB
->ReceiveIrp
.Iosb
,
688 PacketSocketRecvComplete
,
692 SocketStateUnlock( FCB
);
694 return STATUS_SUCCESS
;
698 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
699 PIO_STACK_LOCATION IrpSp
) {
700 NTSTATUS Status
= STATUS_SUCCESS
;
701 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
702 PAFD_FCB FCB
= FileObject
->FsContext
;
703 PAFD_RECV_INFO_UDP RecvReq
;
704 PLIST_ENTRY ListEntry
;
705 PAFD_STORED_DATAGRAM DatagramRecv
;
706 KPROCESSOR_MODE LockMode
;
708 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
710 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
712 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
714 /* Check that the socket is bound */
715 if( FCB
->State
!= SOCKET_STATE_BOUND
)
717 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
718 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
721 if (FCB
->TdiReceiveClosed
)
723 AFD_DbgPrint(MIN_TRACE
,("Receive closed\n"));
724 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
727 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
728 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
730 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
732 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
733 RecvReq
->BufferCount
,
735 RecvReq
->AddressLength
,
736 TRUE
, TRUE
, LockMode
);
738 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
739 return UnlockAndMaybeComplete(FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0);
742 if (!IsListEmpty(&FCB
->DatagramList
))
744 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
745 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
746 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
747 (PUINT
)&Irp
->IoStatus
.Information
);
749 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
751 InsertHeadList(&FCB
->DatagramList
,
752 &DatagramRecv
->ListEntry
);
755 if (!IsListEmpty(&FCB
->DatagramList
))
757 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
758 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
759 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
762 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
764 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
766 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
768 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
769 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
771 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
772 Status
= STATUS_CANT_WAIT
;
773 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
774 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
775 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
779 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
780 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);