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 BOOLEAN
CantReadMore( PAFD_FCB FCB
) {
30 UINT BytesAvailable
= FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
32 return !BytesAvailable
&&
33 (FCB
->PollState
& (AFD_EVENT_CLOSE
| AFD_EVENT_DISCONNECT
));
36 static VOID
HandleEOFOnIrp( PAFD_FCB FCB
, NTSTATUS Status
, UINT Information
) {
37 if( !NT_SUCCESS(Status
) ||
38 (Status
== STATUS_SUCCESS
&& Information
== 0) ) {
39 AFD_DbgPrint(MID_TRACE
,("Looks like an EOF\n"));
40 FCB
->PollState
|= AFD_EVENT_DISCONNECT
;
41 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
45 static NTSTATUS
TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB
,
46 PAFD_RECV_INFO RecvReq
,
47 PUINT TotalBytesCopied
) {
48 UINT i
, BytesToCopy
= 0,
50 FCB
->Recv
.Content
- FCB
->Recv
.BytesUsed
;
53 *TotalBytesCopied
= 0;
56 AFD_DbgPrint(MID_TRACE
,("Called, BytesAvailable = %d\n",
59 if( CantReadMore(FCB
) ) return STATUS_SUCCESS
;
60 if( !BytesAvailable
) return STATUS_PENDING
;
62 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+ RecvReq
->BufferCount
);
64 AFD_DbgPrint(MID_TRACE
,("Buffer Count: %d @ %x\n",
66 RecvReq
->BufferArray
));
68 RecvReq
->BufferArray
&&
70 i
< RecvReq
->BufferCount
;
73 MIN( RecvReq
->BufferArray
[i
].len
, BytesAvailable
);
76 Map
[i
].BufferAddress
= MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
78 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
83 RtlCopyMemory( Map
[i
].BufferAddress
,
84 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
87 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
89 *TotalBytesCopied
+= BytesToCopy
;
91 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
92 FCB
->Recv
.BytesUsed
+= BytesToCopy
;
93 BytesAvailable
-= BytesToCopy
;
98 /* If there's nothing left in our buffer start a new request */
99 if( FCB
->Recv
.BytesUsed
== FCB
->Recv
.Content
) {
100 FCB
->Recv
.BytesUsed
= FCB
->Recv
.Content
= 0;
101 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
102 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
104 if( !FCB
->ReceiveIrp
.InFlightRequest
) {
105 AFD_DbgPrint(MID_TRACE
,("Replenishing buffer\n"));
107 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
108 FCB
->Connection
.Object
,
112 &FCB
->ReceiveIrp
.Iosb
,
116 if( Status
== STATUS_SUCCESS
)
117 FCB
->Recv
.Content
= FCB
->ReceiveIrp
.Iosb
.Information
;
118 HandleEOFOnIrp( FCB
, Status
, FCB
->ReceiveIrp
.Iosb
.Information
);
122 return STATUS_SUCCESS
;
125 static NTSTATUS
ReceiveActivity( PAFD_FCB FCB
, PIRP Irp
) {
126 PLIST_ENTRY NextIrpEntry
;
128 PIO_STACK_LOCATION NextIrpSp
;
129 PAFD_RECV_INFO RecvReq
;
130 UINT TotalBytesCopied
= 0, RetBytesCopied
= 0;
131 NTSTATUS Status
= STATUS_SUCCESS
, RetStatus
= STATUS_PENDING
;
133 AFD_DbgPrint(MID_TRACE
,("%x %x\n", FCB
, Irp
));
135 if( CantReadMore( FCB
) ) {
136 /* Success here means that we got an EOF. Complete a pending read
137 * with zero bytes if we haven't yet overread, then kill the others.
139 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
141 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
143 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
144 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
145 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
147 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
149 UnlockBuffers( RecvReq
->BufferArray
,
150 RecvReq
->BufferCount
, FALSE
);
151 Status
= NextIrp
->IoStatus
.Status
=
152 FCB
->Overread
? STATUS_END_OF_FILE
: STATUS_SUCCESS
;
153 NextIrp
->IoStatus
.Information
= 0;
154 if( NextIrp
== Irp
) RetStatus
= Status
;
155 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
156 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
157 FCB
->Overread
= TRUE
;
158 //FCB->PollState |= AFD_EVENT_DISCONNECT;
159 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
162 /* Kick the user that receive would be possible now */
163 /* XXX Not implemented yet */
165 AFD_DbgPrint(MID_TRACE
,("FCB %x Receive data waiting %d\n",
166 FCB
, FCB
->Recv
.Content
));
167 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
169 /* Try to clear some requests */
170 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
172 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
174 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
175 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
176 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
178 AFD_DbgPrint(MID_TRACE
,("RecvReq @ %x\n", RecvReq
));
180 Status
= TryToSatisfyRecvRequestFromBuffer
181 ( FCB
, RecvReq
, &TotalBytesCopied
);
183 if( Status
== STATUS_PENDING
) {
184 AFD_DbgPrint(MID_TRACE
,("Ran out of data for %x\n", NextIrp
));
185 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
],
186 &NextIrp
->Tail
.Overlay
.ListEntry
);
189 AFD_DbgPrint(MID_TRACE
,("Completing recv %x (%d)\n", NextIrp
,
191 UnlockBuffers( RecvReq
->BufferArray
,
192 RecvReq
->BufferCount
, FALSE
);
193 NextIrp
->IoStatus
.Status
= Status
;
194 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
195 if( NextIrp
== Irp
) {
197 RetBytesCopied
= TotalBytesCopied
;
199 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
200 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
205 if( FCB
->Recv
.Content
) {
206 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
208 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
210 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
212 AFD_DbgPrint(MID_TRACE
,("RetStatus for irp %x is %x\n", Irp
, RetStatus
));
214 /* Sometimes we're called with a NULL Irp */
216 Irp
->IoStatus
.Status
= RetStatus
;
217 Irp
->IoStatus
.Information
= RetBytesCopied
;
223 NTSTATUS NTAPI ReceiveComplete
224 ( PDEVICE_OBJECT DeviceObject
,
227 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
228 PLIST_ENTRY NextIrpEntry
;
230 PAFD_RECV_INFO RecvReq
;
231 PIO_STACK_LOCATION NextIrpSp
;
233 AFD_DbgPrint(MID_TRACE
,("Called\n"));
235 ASSERT_IRQL(APC_LEVEL
);
237 if( !SocketAcquireStateLock( FCB
) )
238 return STATUS_FILE_CLOSED
;
240 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
242 FCB
->Recv
.Content
= Irp
->IoStatus
.Information
;
243 FCB
->Recv
.BytesUsed
= 0;
245 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
246 AFD_DbgPrint(MIN_TRACE
,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
247 /* Cleanup our IRP queue because the FCB is being destroyed */
248 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
249 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
250 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
251 NextIrpSp
= IoGetCurrentIrpStackLocation(NextIrp
);
252 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
253 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
254 NextIrp
->IoStatus
.Information
= 0;
255 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
256 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
257 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
259 SocketStateUnlock( FCB
);
260 return STATUS_FILE_CLOSED
;
261 } else if( FCB
->State
== SOCKET_STATE_LISTENING
) {
262 AFD_DbgPrint(MIN_TRACE
,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
263 SocketStateUnlock( FCB
);
264 return STATUS_INVALID_PARAMETER
;
267 HandleEOFOnIrp( FCB
, Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
269 ReceiveActivity( FCB
, NULL
);
271 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
273 SocketStateUnlock( FCB
);
275 return STATUS_SUCCESS
;
279 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
280 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
281 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
282 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
283 PAFD_FCB FCB
= FileObject
->FsContext
;
284 PAFD_RECV_INFO RecvReq
;
285 UINT TotalBytesCopied
= 0;
287 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
289 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
291 if( FCB
->State
!= SOCKET_STATE_CONNECTED
&&
292 FCB
->State
!= SOCKET_STATE_CONNECTING
) {
293 AFD_DbgPrint(MID_TRACE
,("Called recv on wrong kind of socket (s%x)\n",
295 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
,
299 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
301 AFD_DbgPrint(MID_TRACE
,("Receive on connection-less sockets not implemented\n"));
302 return UnlockAndMaybeComplete( FCB
, STATUS_NOT_IMPLEMENTED
,
306 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
307 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
309 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
310 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
,
313 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
315 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
316 RecvReq
->BufferCount
,
320 if( !RecvReq
->BufferArray
) {
321 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
325 Irp
->IoStatus
.Status
= STATUS_PENDING
;
326 Irp
->IoStatus
.Information
= 0;
328 InsertTailList( &FCB
->PendingIrpList
[FUNCTION_RECV
],
329 &Irp
->Tail
.Overlay
.ListEntry
);
331 /************ From this point, the IRP is not ours ************/
333 Status
= ReceiveActivity( FCB
, Irp
);
335 if( Status
== STATUS_PENDING
&& RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
336 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
337 Status
= STATUS_CANT_WAIT
;
338 TotalBytesCopied
= 0;
339 RemoveEntryList( &Irp
->Tail
.Overlay
.ListEntry
);
340 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
341 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
343 } else if( Status
== STATUS_PENDING
) {
344 AFD_DbgPrint(MID_TRACE
,("Leaving read irp\n"));
345 IoMarkIrpPending( Irp
);
347 AFD_DbgPrint(MID_TRACE
,("Completed with status %x\n", Status
));
350 SocketStateUnlock( FCB
);
355 static NTSTATUS NTAPI
356 SatisfyPacketRecvRequest( PAFD_FCB FCB
, PIRP Irp
,
357 PAFD_STORED_DATAGRAM DatagramRecv
,
358 PUINT TotalBytesCopied
) {
359 NTSTATUS Status
= STATUS_SUCCESS
;
360 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
361 PAFD_RECV_INFO RecvReq
=
362 IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
363 UINT BytesToCopy
= 0, BytesAvailable
= DatagramRecv
->Len
, AddrLen
= 0;
366 Map
= (PAFD_MAPBUF
)(RecvReq
->BufferArray
+
367 RecvReq
->BufferCount
+
371 MIN( RecvReq
->BufferArray
[0].len
, BytesAvailable
);
373 AFD_DbgPrint(MID_TRACE
,("BytesToCopy: %d len %d\n", BytesToCopy
,
374 RecvReq
->BufferArray
[0].len
));
377 /* Copy the address */
378 if( Map
[1].Mdl
&& Map
[2].Mdl
) {
379 AFD_DbgPrint(MID_TRACE
,("Checking TAAddressCount\n"));
381 if( DatagramRecv
->Address
->TAAddressCount
!= 1 ) {
384 ("Wierd address count %d\n",
385 DatagramRecv
->Address
->TAAddressCount
));
388 AFD_DbgPrint(MID_TRACE
,("Computing addr len\n"));
390 AddrLen
= MIN(DatagramRecv
->Address
->Address
->AddressLength
+
392 RecvReq
->BufferArray
[1].len
);
394 AFD_DbgPrint(MID_TRACE
,("Copying %d bytes of address\n", AddrLen
));
396 Map
[1].BufferAddress
= MmMapLockedPages( Map
[1].Mdl
, KernelMode
);
398 AFD_DbgPrint(MID_TRACE
,("Done mapping, copying address\n"));
400 RtlCopyMemory( Map
[1].BufferAddress
,
401 &DatagramRecv
->Address
->Address
->AddressType
,
404 MmUnmapLockedPages( Map
[1].BufferAddress
, Map
[1].Mdl
);
406 AFD_DbgPrint(MID_TRACE
,("Copying address len\n"));
408 Map
[2].BufferAddress
= MmMapLockedPages( Map
[2].Mdl
, KernelMode
);
409 *((PINT
)Map
[2].BufferAddress
) = AddrLen
;
410 MmUnmapLockedPages( Map
[2].BufferAddress
, Map
[2].Mdl
);
413 AFD_DbgPrint(MID_TRACE
,("Mapping data buffer pages\n"));
415 Map
[0].BufferAddress
= MmMapLockedPages( Map
[0].Mdl
, KernelMode
);
417 AFD_DbgPrint(MID_TRACE
,("Buffer %d: %x:%d\n",
419 Map
[0].BufferAddress
,
423 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
425 RtlCopyMemory( Map
[0].BufferAddress
,
426 FCB
->Recv
.Window
+ FCB
->Recv
.BytesUsed
,
429 MmUnmapLockedPages( Map
[0].BufferAddress
, Map
[0].Mdl
);
431 *TotalBytesCopied
= BytesToCopy
;
433 if (!(RecvReq
->TdiFlags
& TDI_RECEIVE_PEEK
)) {
434 FCB
->Recv
.BytesUsed
= 0;
438 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
439 Irp
->IoStatus
.Information
= BytesToCopy
;
440 ExFreePool( DatagramRecv
->Address
);
441 ExFreePool( DatagramRecv
);
443 AFD_DbgPrint(MID_TRACE
,("Done\n"));
449 PacketSocketRecvComplete(
450 PDEVICE_OBJECT DeviceObject
,
453 NTSTATUS Status
= STATUS_SUCCESS
;
454 PAFD_FCB FCB
= Context
;
456 PIO_STACK_LOCATION NextIrpSp
;
457 PLIST_ENTRY ListEntry
;
458 PAFD_RECV_INFO RecvReq
;
459 PAFD_STORED_DATAGRAM DatagramRecv
;
460 UINT DGSize
= Irp
->IoStatus
.Information
+ sizeof( AFD_STORED_DATAGRAM
);
461 PLIST_ENTRY NextIrpEntry
, DatagramRecvEntry
;
463 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
465 if( !SocketAcquireStateLock( FCB
) )
466 return STATUS_FILE_CLOSED
;
468 FCB
->ReceiveIrp
.InFlightRequest
= NULL
;
470 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
471 /* Cleanup our IRP queue because the FCB is being destroyed */
472 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
473 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
474 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
475 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
476 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
477 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
478 NextIrp
->IoStatus
.Information
= 0;
479 UnlockBuffers(RecvReq
->BufferArray
, RecvReq
->BufferCount
, FALSE
);
480 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
481 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
484 /* Free all items on the datagram list */
485 while( !IsListEmpty( &FCB
->DatagramList
) ) {
486 DatagramRecvEntry
= RemoveHeadList(&FCB
->DatagramList
);
487 DatagramRecv
= CONTAINING_RECORD(DatagramRecvEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
488 ExFreePool( DatagramRecv
->Address
);
489 ExFreePool( DatagramRecv
);
492 SocketStateUnlock( FCB
);
493 return STATUS_FILE_CLOSED
;
496 DatagramRecv
= ExAllocatePool( NonPagedPool
, DGSize
);
499 DatagramRecv
->Len
= Irp
->IoStatus
.Information
;
500 RtlCopyMemory( DatagramRecv
->Buffer
, FCB
->Recv
.Window
,
502 AFD_DbgPrint(MID_TRACE
,("Received (A %x)\n",
503 FCB
->AddressFrom
->RemoteAddress
));
504 DatagramRecv
->Address
=
505 TaCopyTransportAddress( FCB
->AddressFrom
->RemoteAddress
);
507 if( !DatagramRecv
->Address
) Status
= STATUS_NO_MEMORY
;
509 } else Status
= STATUS_NO_MEMORY
;
511 if( !NT_SUCCESS( Status
) ) {
512 if( DatagramRecv
) ExFreePool( DatagramRecv
);
513 SocketStateUnlock( FCB
);
516 InsertTailList( &FCB
->DatagramList
, &DatagramRecv
->ListEntry
);
519 /* Satisfy as many requests as we can */
521 while( !IsListEmpty( &FCB
->DatagramList
) &&
522 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_RECV
] ) ) {
523 AFD_DbgPrint(MID_TRACE
,("Looping trying to satisfy request\n"));
524 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
525 DatagramRecv
= CONTAINING_RECORD( ListEntry
, AFD_STORED_DATAGRAM
,
527 ListEntry
= RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_RECV
] );
528 NextIrp
= CONTAINING_RECORD( ListEntry
, IRP
, Tail
.Overlay
.ListEntry
);
529 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
530 RecvReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
532 AFD_DbgPrint(MID_TRACE
,("RecvReq: %x, DatagramRecv: %x\n",
533 RecvReq
, DatagramRecv
));
535 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
536 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
537 InsertHeadList( &FCB
->DatagramList
,
538 &DatagramRecv
->ListEntry
);
539 Status
= NextIrp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
540 NextIrp
->IoStatus
.Information
= DatagramRecv
->Len
;
541 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
542 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
543 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
545 AFD_DbgPrint(MID_TRACE
,("Satisfying\n"));
546 Status
= SatisfyPacketRecvRequest
547 ( FCB
, NextIrp
, DatagramRecv
,
548 (PUINT
)&NextIrp
->IoStatus
.Information
);
549 AFD_DbgPrint(MID_TRACE
,("Unlocking\n"));
550 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
551 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
552 AFD_DbgPrint(MID_TRACE
,("Completing\n"));
553 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
557 if( !IsListEmpty( &FCB
->DatagramList
) ) {
558 AFD_DbgPrint(MID_TRACE
,("Signalling\n"));
559 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
561 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
563 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
565 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
566 /* Now relaunch the datagram request */
567 Status
= TdiReceiveDatagram
568 ( &FCB
->ReceiveIrp
.InFlightRequest
,
569 FCB
->AddressFile
.Object
,
574 &FCB
->ReceiveIrp
.Iosb
,
575 PacketSocketRecvComplete
,
579 SocketStateUnlock( FCB
);
581 return STATUS_SUCCESS
;
585 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
586 PIO_STACK_LOCATION IrpSp
) {
587 NTSTATUS Status
= STATUS_SUCCESS
;
588 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
589 PAFD_FCB FCB
= FileObject
->FsContext
;
590 PAFD_RECV_INFO_UDP RecvReq
;
591 PLIST_ENTRY ListEntry
;
592 PAFD_STORED_DATAGRAM DatagramRecv
;
594 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
596 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
598 FCB
->EventsFired
&= ~AFD_EVENT_RECEIVE
;
600 /* Check that the socket is bound */
601 if( FCB
->State
!= SOCKET_STATE_BOUND
)
602 return UnlockAndMaybeComplete
603 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0 );
604 if( !(RecvReq
= LockRequest( Irp
, IrpSp
)) )
605 return UnlockAndMaybeComplete
606 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
608 AFD_DbgPrint(MID_TRACE
,("Recv flags %x\n", RecvReq
->AfdFlags
));
610 RecvReq
->BufferArray
= LockBuffers( RecvReq
->BufferArray
,
611 RecvReq
->BufferCount
,
613 RecvReq
->AddressLength
,
616 if( !RecvReq
->BufferArray
) { /* access violation in userspace */
617 return UnlockAndMaybeComplete
618 ( FCB
, STATUS_ACCESS_VIOLATION
, Irp
, 0 );
621 if( !IsListEmpty( &FCB
->DatagramList
) ) {
622 ListEntry
= RemoveHeadList( &FCB
->DatagramList
);
623 DatagramRecv
= CONTAINING_RECORD
624 ( ListEntry
, AFD_STORED_DATAGRAM
, ListEntry
);
625 if( DatagramRecv
->Len
> RecvReq
->BufferArray
[0].len
&&
626 !(RecvReq
->TdiFlags
& TDI_RECEIVE_PARTIAL
) ) {
627 InsertHeadList( &FCB
->DatagramList
,
628 &DatagramRecv
->ListEntry
);
629 Status
= Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
630 Irp
->IoStatus
.Information
= DatagramRecv
->Len
;
632 if( IsListEmpty( &FCB
->DatagramList
) )
633 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
635 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
637 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
639 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
641 return UnlockAndMaybeComplete
642 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
644 Status
= SatisfyPacketRecvRequest
645 ( FCB
, Irp
, DatagramRecv
,
646 (PUINT
)&Irp
->IoStatus
.Information
);
648 if( IsListEmpty( &FCB
->DatagramList
) )
649 FCB
->PollState
&= ~AFD_EVENT_RECEIVE
;
651 FCB
->PollState
|= AFD_EVENT_RECEIVE
;
653 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
655 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
657 return UnlockAndMaybeComplete
658 ( FCB
, Status
, Irp
, Irp
->IoStatus
.Information
);
660 } else if( RecvReq
->AfdFlags
& AFD_IMMEDIATE
) {
661 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
662 Status
= STATUS_CANT_WAIT
;
663 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
664 UnlockBuffers( RecvReq
->BufferArray
, RecvReq
->BufferCount
, TRUE
);
665 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
667 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
668 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_RECV
);