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 VOID
HandleEOFOnIrp( PAFD_FCB FCB
, NTSTATUS Status
, ULONG_PTR Information
)
31 if( ( Status
== STATUS_SUCCESS
&& !Information
) ||
32 ( !NT_SUCCESS( Status
) ) )
34 /* The socket has been closed */
35 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
36 FCB
->PollStatus
[FD_CLOSE_BIT
] = Status
;
38 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
42 static BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
43 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
45 return !BytesAvailable
&&
46 (FCB
->PollState
& (AFD_EVENT_CLOSE
| AFD_EVENT_DISCONNECT
));
49 static VOID
RefillSocketBuffer( PAFD_FCB FCB
) {
52 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
53 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
55 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
56 FCB
->Connection
.Object
,
60 &FCB
->ReceiveIrp
.Iosb
,
64 if( Status
== STATUS_SUCCESS
&& FCB
->ReceiveIrp
.Iosb
.Information
)
66 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
67 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
68 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
70 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
75 HandleEOFOnIrp(FCB
, Status
, FCB
->ReceiveIrp
.Iosb
.Information
);
80 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
81 PAFD_RECV_INFO RecvReq
,
82 PUINT TotalBytesCopied
) {
83 UINT i
, BytesToCopy
= 0, FcbBytesCopied
= FCB
->Recv
.BytesUsed
;
85 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
87 *TotalBytesCopied
= 0;
90 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
93 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
94 if( !BytesAvailable
) return STATUS_PENDING
;
96 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
98 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
100 RecvReq
->BufferArray
));
102 RecvReq
->BufferArray
&&
104 i
< RecvReq
->BufferCount
;
107 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
110 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
112 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
114 Map
[i
].BufferAddress
,
117 RtlCopyMemory( Map
[i
].BufferAddress
,
118 FCB
->Recv
.Window
+ FcbBytesCopied
,
121 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
123 *TotalBytesCopied
+= BytesToCopy
;
124 FcbBytesCopied
+= BytesToCopy
;
126 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
127 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
128 BytesAvailable
-= BytesToCopy
;
133 /* If there's nothing left in our buffer start a new request */
134 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
135 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
136 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
138 RefillSocketBuffer( FCB
);
141 return STATUS_SUCCESS
;
144 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
145 PLIST_ENTRY NextIrpEntry
;
147 PIO_STACK_LOCATION NextIrpSp
;
148 PAFD_RECV_INFO RecvReq
;
149 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
150 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
152 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
154 /* Kick the user that receive would be possible now */
155 /* XXX Not implemented yet */
157 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
158 FCB
, FCB
->Recv
.Content
));
160 if( CantReadMore( FCB
) ) {
161 /* Success here means that we got an EOF. Complete a pending read
162 * with zero bytes if we haven't yet overread, then kill the others.
164 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
166 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
168 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
169 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
170 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
172 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
174 UnlockBuffers( RecvReq
->BufferArray
,
175 RecvReq
->BufferCount
, FALSE
);
176 Status
= NextIrp
->IoStatus
.Status
=
177 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
178 NextIrp
->IoStatus
.Information
= 0;
179 if( NextIrp
== Irp
) RetStatus
= Status
;
180 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
181 (void)IoSetCancelRoutine(NextIrp
, NULL
);
182 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
183 FCB
->Overread
= TRUE
;
186 /* Kick the user that receive would be possible now */
187 /* XXX Not implemented yet */
189 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
190 FCB
, FCB
->Recv
.Content
));
191 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
193 /* Try to clear some requests */
194 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
196 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
198 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
199 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
200 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
202 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
204 Status
= TryToSatisfyRecvRequestFromBuffer
205 ( FCB
, RecvReq
, &TotalBytesCopied
);
207 if( Status
== STATUS_PENDING
) {
208 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
209 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
210 &NextIrp
->Tail
.Overlay
.ListEntry
);
213 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
215 UnlockBuffers( RecvReq
->BufferArray
,
216 RecvReq
->BufferCount
, FALSE
);
217 NextIrp
->IoStatus
.Status
= Status
;
218 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
219 if( NextIrp
== Irp
) {
221 RetBytesCopied
= TotalBytesCopied
;
223 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
224 (void)IoSetCancelRoutine(NextIrp
, NULL
);
225 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
230 if( FCB
->Recv
.Content
) {
231 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
232 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
233 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
235 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
237 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
239 /* Sometimes we're called with a NULL Irp */
241 Irp
->IoStatus
.Status
= RetStatus
;
242 Irp
->IoStatus
.Information
= RetBytesCopied
;
248 NTSTATUS NTAPI ReceiveComplete
249 ( PDEVICE_OBJECT DeviceObject
,
252 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
253 PLIST_ENTRY NextIrpEntry
;
255 PAFD_RECV_INFO RecvReq
;
256 PIO_STACK_LOCATION NextIrpSp
;
258 AFD_DbgPrint(MID_TRACE
,("Called\n"));
260 if( !SocketAcquireStateLock( FCB
) )
261 return STATUS_FILE_CLOSED
;
263 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
265 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
266 FCB
->Recv
.BytesUsed
= 0;
268 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
269 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
270 /* Cleanup our IRP queue because the FCB is being destroyed */
271 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
272 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
273 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
274 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
275 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
276 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
277 NextIrp
->IoStatus
.Information
= 0;
278 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
279 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
280 (void)IoSetCancelRoutine(NextIrp
, NULL
);
281 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
283 SocketStateUnlock( FCB
);
284 return STATUS_FILE_CLOSED
;
285 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
286 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
287 SocketStateUnlock( FCB
);
288 return STATUS_INVALID_PARAMETER
;
291 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
293 ReceiveActivity( FCB
, NULL
);
295 SocketStateUnlock( FCB
);
297 return STATUS_SUCCESS
;
301 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
302 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
303 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
304 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
305 PAFD_FCB FCB
= FileObject
->FsContext
;
306 PAFD_RECV_INFO RecvReq
;
307 UINT TotalBytesCopied
= 0;
309 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
311 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
313 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
314 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
315 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
317 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
321 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
323 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
324 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
328 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
329 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
332 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
334 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
335 RecvReq
->BufferCount
,
339 if( !RecvReq
->BufferArray
) {
340 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
344 Irp
->IoStatus
.Status
= STATUS_PENDING
;
345 Irp
->IoStatus
.Information
= 0;
347 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
348 &Irp
->Tail
.Overlay
.ListEntry
);
350 /************ From this point, the IRP is not ours ************/
352 Status
= ReceiveActivity( FCB
, Irp
);
354 if( Status
== STATUS_PENDING
&& (RecvReq
->AfdFlags
& AFD_IMMEDIATE
) ) {
355 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
356 Status
= STATUS_CANT_WAIT
;
357 TotalBytesCopied
= 0;
358 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
359 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
360 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
362 } else if( Status
== STATUS_PENDING
) {
363 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
364 IoMarkIrpPending( Irp
);
365 (void)IoSetCancelRoutine(Irp
, AfdCancelHandler
);
367 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
370 SocketStateUnlock( FCB
);
375 static NTSTATUS NTAPI
376 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
377 PAFD_STORED_DATAGRAM DatagramRecv
,
378 PUINT TotalBytesCopied
) {
379 NTSTATUS Status
= STATUS_SUCCESS
;
380 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
381 PAFD_RECV_INFO RecvReq
=
382 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
383 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
386 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
387 RecvReq
->BufferCount
+
391 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
393 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
394 RecvReq
->BufferArray
[0].len
));
397 /* Copy the address */
398 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
399 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
401 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
404 ("Wierd address count %d\n",
405 DatagramRecv
->Address
->TAAddressCount
));
408 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
410 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
412 RecvReq
->BufferArray
[1].len
);
414 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
416 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
418 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
420 RtlCopyMemory( Map
[1].BufferAddress
,
421 &DatagramRecv
->Address
->Address
->AddressType
,
424 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
426 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
428 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
429 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
430 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
433 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
435 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
437 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
439 Map
[0].BufferAddress
,
443 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
445 RtlCopyMemory( Map
[0].BufferAddress
,
446 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
449 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
451 *TotalBytesCopied
= BytesToCopy
;
453 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
454 FCB
->Recv
.BytesUsed
= 0;
458 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
459 Irp
->IoStatus
.Information
= BytesToCopy
;
460 ExFreePool( DatagramRecv
->Address
);
461 ExFreePool( DatagramRecv
);
463 AFD_DbgPrint(MID_TRACE
,("Done\n"));
469 PacketSocketRecvComplete(
470 PDEVICE_OBJECT DeviceObject
,
473 NTSTATUS Status
= STATUS_SUCCESS
;
474 PAFD_FCB FCB
= Context
;
476 PIO_STACK_LOCATION NextIrpSp
;
477 PLIST_ENTRY ListEntry
;
478 PAFD_RECV_INFO RecvReq
;
479 PAFD_STORED_DATAGRAM DatagramRecv
;
480 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
481 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
483 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
485 if( !SocketAcquireStateLock( FCB
) )
486 return STATUS_FILE_CLOSED
;
488 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
490 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
491 /* Cleanup our IRP queue because the FCB is being destroyed */
492 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
493 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
494 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
495 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
496 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
497 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
498 NextIrp
->IoStatus
.Information
= 0;
499 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
500 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
501 (void)IoSetCancelRoutine(NextIrp
, NULL
);
502 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
505 /* Free all items on the datagram list */
506 while( !IsListEmpty( &FCB
->DatagramList
) ) {
507 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
508 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
509 ExFreePool( DatagramRecv
->Address
);
510 ExFreePool( DatagramRecv
);
513 SocketStateUnlock( FCB
);
514 return STATUS_FILE_CLOSED
;
517 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
520 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
521 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
523 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
524 FCB
->AddressFrom
->RemoteAddress
));
525 DatagramRecv
->Address
=
526 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
528 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
530 } else Status
= STATUS_NO_MEMORY
;
532 if( !NT_SUCCESS( Status
) ) {
533 if( DatagramRecv
) ExFreePool( DatagramRecv
);
534 SocketStateUnlock( FCB
);
537 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
540 /* Satisfy as many requests as we can */
542 while( !IsListEmpty( &FCB
->DatagramList
) &&
543 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
544 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
545 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
546 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
548 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
549 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
550 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
551 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
553 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
554 RecvReq
, DatagramRecv
));
556 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
557 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
558 InsertHeadList( &FCB
->DatagramList
,
559 &DatagramRecv
->ListEntry
);
560 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
561 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
562 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
563 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
564 (void)IoSetCancelRoutine(NextIrp
, NULL
);
565 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
567 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
568 Status
= SatisfyPacketRecvRequest
569 ( FCB
, NextIrp
, DatagramRecv
,
570 (PUINT
)&NextIrp
->IoStatus
.Information
);
571 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
572 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
573 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
574 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
575 (void)IoSetCancelRoutine(NextIrp
, NULL
);
576 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
580 if( !IsListEmpty( &FCB
->DatagramList
) ) {
581 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
582 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
583 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
584 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
586 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
588 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
589 /* Now relaunch the datagram request */
590 Status
= TdiReceiveDatagram
591 ( &FCB
->ReceiveIrp
.InFlightRequest
,
592 FCB
->AddressFile
.Object
,
597 &FCB
->ReceiveIrp
.Iosb
,
598 PacketSocketRecvComplete
,
602 SocketStateUnlock( FCB
);
604 return STATUS_SUCCESS
;
608 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
609 PIO_STACK_LOCATION IrpSp
) {
610 NTSTATUS Status
= STATUS_SUCCESS
;
611 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
612 PAFD_FCB FCB
= FileObject
->FsContext
;
613 PAFD_RECV_INFO_UDP RecvReq
;
614 PLIST_ENTRY ListEntry
;
615 PAFD_STORED_DATAGRAM DatagramRecv
;
617 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
619 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
621 /* Check that the socket is bound */
622 if( FCB
->State
!= SOCKET_STATE_BOUND
)
623 return UnlockAndMaybeComplete
624 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
625 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
626 return UnlockAndMaybeComplete
627 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
629 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
631 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
632 RecvReq
->BufferCount
,
634 RecvReq
->AddressLength
,
637 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
638 return UnlockAndMaybeComplete
639 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0 );
642 if( !IsListEmpty( &FCB
->DatagramList
) ) {
643 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
644 DatagramRecv
= CONTAINING_RECORD
645 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
646 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
647 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
648 InsertHeadList( &FCB
->DatagramList
,
649 &DatagramRecv
->ListEntry
);
650 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
651 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
653 if( !IsListEmpty( &FCB
->DatagramList
) ) {
654 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
655 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
656 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
658 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
660 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
662 return UnlockAndMaybeComplete
663 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
665 Status
= SatisfyPacketRecvRequest
666 ( FCB
, Irp
, DatagramRecv
,
667 (PUINT
)&Irp
->IoStatus
.Information
);
669 if( !IsListEmpty( &FCB
->DatagramList
) ) {
670 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
671 FCB
->PollStatus
[FD_READ_BIT
] = STATUS_SUCCESS
;
672 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
674 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
676 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
678 return UnlockAndMaybeComplete
679 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
681 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
682 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
683 Status
= STATUS_CANT_WAIT
;
684 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
685 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
686 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
688 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
689 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);