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 /* We got closed while the receive was in progress */
56 if (FCB
->TdiReceiveClosed
)
58 FCB
->Recv
.Content
= 0;
59 FCB
->Recv
.BytesUsed
= 0;
61 /* Receive successful */
62 else if (Status
== STATUS_SUCCESS
)
64 FCB
->Recv
.Content
+= Information
;
65 ASSERT(FCB
->Recv
.Content
<= FCB
->Recv
.Size
);
67 /* Check for graceful closure */
70 FCB
->TdiReceiveClosed
= TRUE
;
72 /* Signal graceful receive shutdown */
73 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
74 FCB
->PollStatus
[FD_CLOSE_BIT
] = Status
;
76 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
79 /* Issue another receive IRP to keep the buffer well stocked */
80 RefillSocketBuffer(FCB
);
82 /* Receive failed with no data (unexpected closure) */
85 FCB
->Recv
.BytesUsed
= 0;
86 FCB
->Recv
.Content
= 0;
87 FCB
->TdiReceiveClosed
= TRUE
;
89 /* Signal complete connection failure immediately */
90 FCB
->PollState
|= AFD_EVENT_CLOSE
;
91 FCB
->PollStatus
[FD_CLOSE_BIT
] = Status
;
93 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
97 static BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
98 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
100 return !BytesAvailable
&& FCB
->TdiReceiveClosed
;
103 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
104 PAFD_RECV_INFO RecvReq
,
105 PUINT TotalBytesCopied
) {
106 UINT i
, BytesToCopy
= 0, FcbBytesCopied
= FCB
->Recv
.BytesUsed
,
108 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
110 *TotalBytesCopied
= 0;
113 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
116 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
117 if( !BytesAvailable
) return STATUS_PENDING
;
119 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
121 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
122 RecvReq
->BufferCount
,
123 RecvReq
->BufferArray
));
125 RecvReq
->BufferArray
&&
127 i
< RecvReq
->BufferCount
;
130 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
133 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
135 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
137 Map
[i
].BufferAddress
,
140 RtlCopyMemory( Map
[i
].BufferAddress
,
141 FCB
->Recv
.Window
+ FcbBytesCopied
,
144 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
146 *TotalBytesCopied
+= BytesToCopy
;
147 FcbBytesCopied
+= BytesToCopy
;
148 BytesAvailable
-= BytesToCopy
;
150 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
151 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
155 /* Issue another receive IRP to keep the buffer well stocked */
156 RefillSocketBuffer(FCB
);
158 return STATUS_SUCCESS
;
161 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
162 PLIST_ENTRY NextIrpEntry
;
164 PIO_STACK_LOCATION NextIrpSp
;
165 PAFD_RECV_INFO RecvReq
;
166 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
167 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
169 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
171 /* Kick the user that receive would be possible now */
172 /* XXX Not implemented yet */
174 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
175 FCB
, FCB
->Recv
.Content
));
177 if( CantReadMore( FCB
) ) {
178 /* Success here means that we got an EOF. Complete a pending read
179 * with zero bytes if we haven't yet overread, then kill the others.
181 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
182 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
183 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
184 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
185 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
187 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
189 UnlockBuffers( RecvReq
->BufferArray
,
190 RecvReq
->BufferCount
, FALSE
);
191 if (FCB
->Overread
&& FCB
->PollStatus
[FD_CLOSE_BIT
] == STATUS_SUCCESS
)
193 /* Overread after a graceful disconnect so complete with an error */
194 Status
= STATUS_FILE_CLOSED
;
198 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */
199 Status
= FCB
->PollStatus
[FD_CLOSE_BIT
];
201 NextIrp
->IoStatus
.Status
= Status
;
202 NextIrp
->IoStatus
.Information
= 0;
203 if( NextIrp
== Irp
) RetStatus
= Status
;
204 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
205 (void)IoSetCancelRoutine(NextIrp
, NULL
);
206 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
207 FCB
->Overread
= TRUE
;
210 /* Kick the user that receive would be possible now */
211 /* XXX Not implemented yet */
213 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
214 FCB
, FCB
->Recv
.Content
));
215 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
217 /* Try to clear some requests */
218 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
219 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
220 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
221 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
222 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
224 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
226 Status
= TryToSatisfyRecvRequestFromBuffer
227 ( FCB
, RecvReq
, &TotalBytesCopied
);
229 if( Status
== STATUS_PENDING
) {
230 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
231 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
232 &NextIrp
->Tail
.Overlay
.ListEntry
);
235 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
237 UnlockBuffers( RecvReq
->BufferArray
,
238 RecvReq
->BufferCount
, FALSE
);
239 NextIrp
->IoStatus
.Status
= Status
;
240 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
241 if( NextIrp
== Irp
) {
243 RetBytesCopied
= TotalBytesCopied
;
245 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
246 (void)IoSetCancelRoutine(NextIrp
, NULL
);
247 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
252 if( FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
&&
253 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
254 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
255 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
256 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
260 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
263 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
265 /* Sometimes we're called with a NULL Irp */
267 Irp
->IoStatus
.Status
= RetStatus
;
268 Irp
->IoStatus
.Information
= RetBytesCopied
;
274 NTSTATUS NTAPI ReceiveComplete
275 ( PDEVICE_OBJECT DeviceObject
,
278 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
279 PLIST_ENTRY NextIrpEntry
;
281 PAFD_RECV_INFO RecvReq
;
282 PIO_STACK_LOCATION NextIrpSp
;
284 AFD_DbgPrint(MID_TRACE
,("Called\n"));
286 if( !SocketAcquireStateLock( FCB
) )
287 return STATUS_FILE_CLOSED
;
289 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
290 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
292 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
293 /* Cleanup our IRP queue because the FCB is being destroyed */
294 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
295 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
296 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
297 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
298 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
299 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
300 NextIrp
->IoStatus
.Information
= 0;
301 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
302 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
303 (void)IoSetCancelRoutine(NextIrp
, NULL
);
304 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
306 SocketStateUnlock( FCB
);
307 return STATUS_FILE_CLOSED
;
308 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
309 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
310 SocketStateUnlock( FCB
);
311 return STATUS_INVALID_PARAMETER
;
314 HandleReceiveComplete( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
316 ReceiveActivity( FCB
, NULL
);
318 SocketStateUnlock( FCB
);
320 return STATUS_SUCCESS
;
323 static NTSTATUS NTAPI
324 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
325 PAFD_STORED_DATAGRAM DatagramRecv
,
326 PUINT TotalBytesCopied
) {
327 NTSTATUS Status
= STATUS_SUCCESS
;
328 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
329 PAFD_RECV_INFO RecvReq
=
330 GetLockedData(Irp
, IrpSp
);
331 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
333 BOOLEAN ExtraBuffers
= CheckUnlockExtraBuffers(FCB
, IrpSp
);
335 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
336 RecvReq
->BufferCount
+
337 (ExtraBuffers
? EXTRA_LOCK_BUFFERS
: 0));
339 BytesToCopy
= MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
341 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
342 RecvReq
->BufferArray
[0].len
));
345 /* Copy the address */
346 if( ExtraBuffers
&& Map
[1].Mdl
&& Map
[2].Mdl
) {
347 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
349 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
352 ("Wierd address count %d\n",
353 DatagramRecv
->Address
->TAAddressCount
));
356 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
358 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
360 RecvReq
->BufferArray
[1].len
);
362 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
364 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
366 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
368 RtlCopyMemory( Map
[1].BufferAddress
,
369 &DatagramRecv
->Address
->Address
->AddressType
,
372 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
374 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
376 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
377 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
378 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
381 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
383 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
385 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
387 Map
[0].BufferAddress
,
390 RtlCopyMemory( Map
[0].BufferAddress
,
391 DatagramRecv
->Buffer
,
394 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
396 *TotalBytesCopied
= BytesToCopy
;
399 if (*TotalBytesCopied
== DatagramRecv
->Len
)
401 /* We copied the whole datagram */
402 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
406 /* We only copied part of the datagram */
407 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
410 Irp
->IoStatus
.Information
= *TotalBytesCopied
;
412 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
))
414 FCB
->Recv
.Content
-= DatagramRecv
->Len
;
415 ExFreePool( DatagramRecv
->Address
);
416 ExFreePool( DatagramRecv
);
419 AFD_DbgPrint(MID_TRACE
,("Done\n"));
425 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
426 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
427 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
428 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
429 PAFD_FCB FCB
= FileObject
->FsContext
;
430 PAFD_RECV_INFO RecvReq
;
431 UINT TotalBytesCopied
= 0;
432 PAFD_STORED_DATAGRAM DatagramRecv
;
433 PLIST_ENTRY ListEntry
;
434 KPROCESSOR_MODE LockMode
;
436 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
438 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
440 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
442 if( !(FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
) &&
443 FCB
->State
!= SOCKET_STATE_CONNECTED
&&
444 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
445 AFD_DbgPrint(MIN_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
447 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
451 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
452 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
455 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
457 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
458 RecvReq
->BufferCount
,
460 TRUE
, FALSE
, LockMode
);
462 if( !RecvReq
->BufferArray
) {
463 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
467 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
469 if (!IsListEmpty(&FCB
->DatagramList
))
471 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
472 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
473 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
474 (PUINT
)&Irp
->IoStatus
.Information
);
476 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
478 InsertHeadList(&FCB
->DatagramList
,
479 &DatagramRecv
->ListEntry
);
482 if (!IsListEmpty(&FCB
->DatagramList
))
484 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
485 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
486 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
489 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
491 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
493 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
495 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
496 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
498 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
499 Status
= STATUS_CANT_WAIT
;
500 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
501 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
502 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
506 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
507 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);
511 Irp
->IoStatus
.Status
= STATUS_PENDING
;
512 Irp
->IoStatus
.Information
= 0;
514 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
515 &Irp
->Tail
.Overlay
.ListEntry
);
517 /************ From this point, the IRP is not ours ************/
519 Status
= ReceiveActivity( FCB
, Irp
);
521 if( Status
== STATUS_PENDING
&&
522 !(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
523 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
524 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
525 Status
= STATUS_CANT_WAIT
;
526 TotalBytesCopied
= 0;
527 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
528 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
529 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
531 } else if( Status
== STATUS_PENDING
) {
532 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
533 IoMarkIrpPending( Irp
);
534 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
536 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
539 SocketStateUnlock( FCB
);
544 PacketSocketRecvComplete(
545 PDEVICE_OBJECT DeviceObject
,
548 NTSTATUS Status
= STATUS_SUCCESS
;
549 PAFD_FCB FCB
= Context
;
551 PIO_STACK_LOCATION NextIrpSp
;
552 PLIST_ENTRY ListEntry
;
553 PAFD_RECV_INFO RecvReq
;
554 PAFD_STORED_DATAGRAM DatagramRecv
;
555 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
556 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
558 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
560 if( !SocketAcquireStateLock( FCB
) )
561 return STATUS_FILE_CLOSED
;
563 ASSERT(FCB
->ReceiveIrp
.InFlightRequest
== Irp
);
564 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
566 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
567 /* Cleanup our IRP queue because the FCB is being destroyed */
568 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
569 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
570 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
571 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
572 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
573 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
574 NextIrp
->IoStatus
.Information
= 0;
575 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
));
576 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
577 (void)IoSetCancelRoutine(NextIrp
, NULL
);
578 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
581 /* Free all items on the datagram list */
582 while( !IsListEmpty( &FCB
->DatagramList
) ) {
583 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
584 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
585 ExFreePool( DatagramRecv
->Address
);
586 ExFreePool( DatagramRecv
);
589 SocketStateUnlock( FCB
);
590 return STATUS_FILE_CLOSED
;
593 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
595 SocketStateUnlock(FCB
);
596 return Irp
->IoStatus
.Status
;
599 if (FCB
->TdiReceiveClosed
)
601 SocketStateUnlock(FCB
);
602 return STATUS_FILE_CLOSED
;
605 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
608 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
609 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
611 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
612 FCB
->AddressFrom
->RemoteAddress
));
613 DatagramRecv
->Address
=
614 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
616 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
618 } else Status
= STATUS_NO_MEMORY
;
620 if( !NT_SUCCESS( Status
) ) {
621 if( DatagramRecv
) ExFreePool( DatagramRecv
);
622 SocketStateUnlock( FCB
);
625 FCB
->Recv
.Content
+= DatagramRecv
->Len
;
626 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
629 /* Satisfy as many requests as we can */
631 while( !IsListEmpty( &FCB
->DatagramList
) &&
632 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
633 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
634 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
635 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
637 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
638 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
639 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
640 RecvReq
= GetLockedData(NextIrp
, NextIrpSp
);
642 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
643 RecvReq
, DatagramRecv
));
645 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
646 Status
= SatisfyPacketRecvRequest
647 ( FCB
, NextIrp
, DatagramRecv
,
648 (PUINT
)&NextIrp
->IoStatus
.Information
);
650 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
652 InsertHeadList(&FCB
->DatagramList
,
653 &DatagramRecv
->ListEntry
);
656 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
657 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, CheckUnlockExtraBuffers(FCB
, NextIrpSp
) );
658 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
660 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
661 (void)IoSetCancelRoutine(NextIrp
, NULL
);
662 NextIrp
->IoStatus
.Status
= Status
;
664 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
667 if( !IsListEmpty( &FCB
->DatagramList
) && IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_RECV
]) ) {
668 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
669 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
670 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
671 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
673 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
675 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
676 /* Now relaunch the datagram request */
677 Status
= TdiReceiveDatagram
678 ( &FCB
->ReceiveIrp
.InFlightRequest
,
679 FCB
->AddressFile
.Object
,
684 &FCB
->ReceiveIrp
.Iosb
,
685 PacketSocketRecvComplete
,
689 SocketStateUnlock( FCB
);
691 return STATUS_SUCCESS
;
695 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
696 PIO_STACK_LOCATION IrpSp
) {
697 NTSTATUS Status
= STATUS_SUCCESS
;
698 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
699 PAFD_FCB FCB
= FileObject
->FsContext
;
700 PAFD_RECV_INFO_UDP RecvReq
;
701 PLIST_ENTRY ListEntry
;
702 PAFD_STORED_DATAGRAM DatagramRecv
;
703 KPROCESSOR_MODE LockMode
;
705 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
707 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
709 FCB
->EventSelectDisabled
&= ~AFD_EVENT_RECEIVE
;
711 /* Check that the socket is bound */
712 if( FCB
->State
!= SOCKET_STATE_BOUND
)
714 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
715 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
718 if (FCB
->TdiReceiveClosed
)
720 AFD_DbgPrint(MIN_TRACE
,("Receive closed\n"));
721 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
724 if( !(RecvReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
725 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
727 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
729 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
730 RecvReq
->BufferCount
,
732 RecvReq
->AddressLength
,
733 TRUE
, TRUE
, LockMode
);
735 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
736 return UnlockAndMaybeComplete(FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0);
739 if (!IsListEmpty(&FCB
->DatagramList
))
741 ListEntry
= RemoveHeadList(&FCB
->DatagramList
);
742 DatagramRecv
= CONTAINING_RECORD(ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
743 Status
= SatisfyPacketRecvRequest(FCB
, Irp
, DatagramRecv
,
744 (PUINT
)&Irp
->IoStatus
.Information
);
746 if (RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)
748 InsertHeadList(&FCB
->DatagramList
,
749 &DatagramRecv
->ListEntry
);
752 if (!IsListEmpty(&FCB
->DatagramList
))
754 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
755 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
756 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
759 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
761 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
763 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
765 else if (!(RecvReq
->AfdFlags
& AFD_OVERLAPPED
) &&
766 ((RecvReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
768 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
769 Status
= STATUS_CANT_WAIT
;
770 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
771 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
772 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
776 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
777 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);