20ef8228780a4974cf5136d48702ccbff8431562
[reactos.git] / reactos / drivers / network / afd / afd / read.c
1 /* $Id$
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)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 *
10 * Improve buffering code
11 *
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
22 * in flight.
23 */
24 #include "afd.h"
25 #include "tdi_proto.h"
26 #include "tdiconn.h"
27 #include "debug.h"
28
29 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
30 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
31
32 return !BytesAvailable &&
33 (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
34 }
35
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 );
42 }
43 }
44
45 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
46 PAFD_RECV_INFO RecvReq,
47 PUINT TotalBytesCopied ) {
48 UINT i, BytesToCopy = 0,
49 BytesAvailable =
50 FCB->Recv.Content - FCB->Recv.BytesUsed;
51 PAFD_MAPBUF Map;
52 NTSTATUS Status;
53 *TotalBytesCopied = 0;
54
55
56 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
57 BytesAvailable));
58
59 if( CantReadMore(FCB) ) return STATUS_SUCCESS;
60 if( !BytesAvailable ) return STATUS_PENDING;
61
62 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
63
64 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n",
65 RecvReq->BufferCount,
66 RecvReq->BufferArray));
67 for( i = 0;
68 RecvReq->BufferArray &&
69 BytesAvailable &&
70 i < RecvReq->BufferCount;
71 i++ ) {
72 BytesToCopy =
73 MIN( RecvReq->BufferArray[i].len, BytesAvailable );
74
75 if( Map[i].Mdl ) {
76 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
77
78 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
79 i,
80 Map[i].BufferAddress,
81 BytesToCopy));
82
83 RtlCopyMemory( Map[i].BufferAddress,
84 FCB->Recv.Window + FCB->Recv.BytesUsed,
85 BytesToCopy );
86
87 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
88
89 *TotalBytesCopied += BytesToCopy;
90
91 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
92 FCB->Recv.BytesUsed += BytesToCopy;
93 BytesAvailable -= BytesToCopy;
94 }
95 }
96 }
97
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 );
103
104 if( !FCB->ReceiveIrp.InFlightRequest ) {
105 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
106
107 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
108 FCB->Connection.Object,
109 TDI_RECEIVE_NORMAL,
110 FCB->Recv.Window,
111 FCB->Recv.Size,
112 &FCB->ReceiveIrp.Iosb,
113 ReceiveComplete,
114 FCB );
115
116 if( Status == STATUS_SUCCESS )
117 FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
118 HandleEOFOnIrp( FCB, Status, FCB->ReceiveIrp.Iosb.Information );
119 }
120 }
121
122 return STATUS_SUCCESS;
123 }
124
125 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
126 PLIST_ENTRY NextIrpEntry;
127 PIRP NextIrp;
128 PIO_STACK_LOCATION NextIrpSp;
129 PAFD_RECV_INFO RecvReq;
130 UINT TotalBytesCopied = 0, RetBytesCopied = 0;
131 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
132
133 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
134
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.
138 */
139 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
140 NextIrpEntry =
141 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
142 NextIrp =
143 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
144 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
145 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
146
147 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
148 TotalBytesCopied));
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 );
160 }
161 } else {
162 /* Kick the user that receive would be possible now */
163 /* XXX Not implemented yet */
164
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 );*/
168
169 /* Try to clear some requests */
170 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
171 NextIrpEntry =
172 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
173 NextIrp =
174 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
175 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
176 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
177
178 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
179
180 Status = TryToSatisfyRecvRequestFromBuffer
181 ( FCB, RecvReq, &TotalBytesCopied );
182
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);
187 break;
188 } else {
189 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
190 TotalBytesCopied));
191 UnlockBuffers( RecvReq->BufferArray,
192 RecvReq->BufferCount, FALSE );
193 NextIrp->IoStatus.Status = Status;
194 NextIrp->IoStatus.Information = TotalBytesCopied;
195 if( NextIrp == Irp ) {
196 RetStatus = Status;
197 RetBytesCopied = TotalBytesCopied;
198 }
199 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
200 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
201 }
202 }
203 }
204
205 if( FCB->Recv.Content ) {
206 FCB->PollState |= AFD_EVENT_RECEIVE;
207 } else
208 FCB->PollState &= ~AFD_EVENT_RECEIVE;
209
210 PollReeval( FCB->DeviceExt, FCB->FileObject );
211
212 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
213
214 /* Sometimes we're called with a NULL Irp */
215 if( Irp ) {
216 Irp->IoStatus.Status = RetStatus;
217 Irp->IoStatus.Information = RetBytesCopied;
218 }
219
220 return RetStatus;
221 }
222
223 NTSTATUS NTAPI ReceiveComplete
224 ( PDEVICE_OBJECT DeviceObject,
225 PIRP Irp,
226 PVOID Context ) {
227 PAFD_FCB FCB = (PAFD_FCB)Context;
228 PLIST_ENTRY NextIrpEntry;
229 PIRP NextIrp;
230 PAFD_RECV_INFO RecvReq;
231 PIO_STACK_LOCATION NextIrpSp;
232
233 AFD_DbgPrint(MID_TRACE,("Called\n"));
234
235 ASSERT_IRQL(APC_LEVEL);
236
237 if( !SocketAcquireStateLock( FCB ) )
238 return STATUS_FILE_CLOSED;
239
240 FCB->ReceiveIrp.InFlightRequest = NULL;
241
242 FCB->Recv.Content = Irp->IoStatus.Information;
243 FCB->Recv.BytesUsed = 0;
244
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 );
258 }
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;
265 }
266
267 HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
268
269 ReceiveActivity( FCB, NULL );
270
271 PollReeval( FCB->DeviceExt, FCB->FileObject );
272
273 SocketStateUnlock( FCB );
274
275 return STATUS_SUCCESS;
276 }
277
278 NTSTATUS NTAPI
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;
286
287 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
288
289 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
290
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",
294 FCB->State));
295 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
296 Irp, 0 );
297 }
298
299 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
300 {
301 AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n"));
302 return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED,
303 Irp, 0 );
304 }
305
306 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
307 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
308 Irp, 0 );
309
310 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
311
312 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
313 RecvReq->BufferCount,
314 NULL, NULL,
315 TRUE, FALSE );
316
317 if( !RecvReq->BufferArray ) {
318 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
319 Irp, 0 );
320 }
321
322 Irp->IoStatus.Status = STATUS_PENDING;
323 Irp->IoStatus.Information = 0;
324
325 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
326 &Irp->Tail.Overlay.ListEntry );
327
328 /************ From this point, the IRP is not ours ************/
329
330 Status = ReceiveActivity( FCB, Irp );
331
332 if( Status == STATUS_PENDING && (RecvReq->AfdFlags & AFD_IMMEDIATE) ) {
333 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
334 Status = STATUS_CANT_WAIT;
335 TotalBytesCopied = 0;
336 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
337 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
338 return UnlockAndMaybeComplete( FCB, Status, Irp,
339 TotalBytesCopied );
340 } else if( Status == STATUS_PENDING ) {
341 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
342 IoMarkIrpPending( Irp );
343 } else {
344 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
345 }
346
347 SocketStateUnlock( FCB );
348 return Status;
349 }
350
351
352 static NTSTATUS NTAPI
353 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
354 PAFD_STORED_DATAGRAM DatagramRecv,
355 PUINT TotalBytesCopied ) {
356 NTSTATUS Status = STATUS_SUCCESS;
357 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
358 PAFD_RECV_INFO RecvReq =
359 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
360 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
361 PAFD_MAPBUF Map;
362
363 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
364 RecvReq->BufferCount +
365 EXTRA_LOCK_BUFFERS);
366
367 BytesToCopy =
368 MIN( RecvReq->BufferArray[0].len, BytesAvailable );
369
370 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
371 RecvReq->BufferArray[0].len));
372
373 if( Map[0].Mdl ) {
374 /* Copy the address */
375 if( Map[1].Mdl && Map[2].Mdl ) {
376 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
377
378 if( DatagramRecv->Address->TAAddressCount != 1 ) {
379 AFD_DbgPrint
380 (MID_TRACE,
381 ("Wierd address count %d\n",
382 DatagramRecv->Address->TAAddressCount));
383 }
384
385 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
386
387 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
388 sizeof(USHORT),
389 RecvReq->BufferArray[1].len);
390
391 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
392
393 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
394
395 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
396
397 RtlCopyMemory( Map[1].BufferAddress,
398 &DatagramRecv->Address->Address->AddressType,
399 AddrLen );
400
401 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
402
403 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
404
405 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
406 *((PINT)Map[2].BufferAddress) = AddrLen;
407 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
408 }
409
410 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
411
412 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
413
414 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
415 0,
416 Map[0].BufferAddress,
417 BytesToCopy));
418
419 /* OskitDumpBuffer
420 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
421
422 RtlCopyMemory( Map[0].BufferAddress,
423 FCB->Recv.Window + FCB->Recv.BytesUsed,
424 BytesToCopy );
425
426 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
427
428 *TotalBytesCopied = BytesToCopy;
429
430 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
431 FCB->Recv.BytesUsed = 0;
432 }
433 }
434
435 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
436 Irp->IoStatus.Information = BytesToCopy;
437 ExFreePool( DatagramRecv->Address );
438 ExFreePool( DatagramRecv );
439
440 AFD_DbgPrint(MID_TRACE,("Done\n"));
441
442 return Status;
443 }
444
445 NTSTATUS NTAPI
446 PacketSocketRecvComplete(
447 PDEVICE_OBJECT DeviceObject,
448 PIRP Irp,
449 PVOID Context ) {
450 NTSTATUS Status = STATUS_SUCCESS;
451 PAFD_FCB FCB = Context;
452 PIRP NextIrp;
453 PIO_STACK_LOCATION NextIrpSp;
454 PLIST_ENTRY ListEntry;
455 PAFD_RECV_INFO RecvReq;
456 PAFD_STORED_DATAGRAM DatagramRecv;
457 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
458 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
459
460 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
461
462 if( !SocketAcquireStateLock( FCB ) )
463 return STATUS_FILE_CLOSED;
464
465 FCB->ReceiveIrp.InFlightRequest = NULL;
466
467 if( FCB->State == SOCKET_STATE_CLOSED ) {
468 /* Cleanup our IRP queue because the FCB is being destroyed */
469 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
470 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
471 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
472 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
473 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
474 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
475 NextIrp->IoStatus.Information = 0;
476 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
477 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
478 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
479 }
480
481 /* Free all items on the datagram list */
482 while( !IsListEmpty( &FCB->DatagramList ) ) {
483 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
484 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
485 ExFreePool( DatagramRecv->Address );
486 ExFreePool( DatagramRecv );
487 }
488
489 SocketStateUnlock( FCB );
490 return STATUS_FILE_CLOSED;
491 }
492
493 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
494
495 if( DatagramRecv ) {
496 DatagramRecv->Len = Irp->IoStatus.Information;
497 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
498 DatagramRecv->Len );
499 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
500 FCB->AddressFrom->RemoteAddress));
501 DatagramRecv->Address =
502 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
503
504 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
505
506 } else Status = STATUS_NO_MEMORY;
507
508 if( !NT_SUCCESS( Status ) ) {
509 if( DatagramRecv ) ExFreePool( DatagramRecv );
510 SocketStateUnlock( FCB );
511 return Status;
512 } else {
513 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
514 }
515
516 /* Satisfy as many requests as we can */
517
518 while( !IsListEmpty( &FCB->DatagramList ) &&
519 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
520 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
521 ListEntry = RemoveHeadList( &FCB->DatagramList );
522 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
523 ListEntry );
524 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
525 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
526 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
527 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
528
529 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
530 RecvReq, DatagramRecv));
531
532 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
533 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
534 InsertHeadList( &FCB->DatagramList,
535 &DatagramRecv->ListEntry );
536 Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
537 NextIrp->IoStatus.Information = DatagramRecv->Len;
538 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
539 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
540 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
541 } else {
542 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
543 Status = SatisfyPacketRecvRequest
544 ( FCB, NextIrp, DatagramRecv,
545 (PUINT)&NextIrp->IoStatus.Information );
546 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
547 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
548 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
549 AFD_DbgPrint(MID_TRACE,("Completing\n"));
550 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
551 }
552 }
553
554 if( !IsListEmpty( &FCB->DatagramList ) ) {
555 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
556 FCB->PollState |= AFD_EVENT_RECEIVE;
557 } else
558 FCB->PollState &= ~AFD_EVENT_RECEIVE;
559
560 PollReeval( FCB->DeviceExt, FCB->FileObject );
561
562 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
563 /* Now relaunch the datagram request */
564 Status = TdiReceiveDatagram
565 ( &FCB->ReceiveIrp.InFlightRequest,
566 FCB->AddressFile.Object,
567 0,
568 FCB->Recv.Window,
569 FCB->Recv.Size,
570 FCB->AddressFrom,
571 &FCB->ReceiveIrp.Iosb,
572 PacketSocketRecvComplete,
573 FCB );
574 }
575
576 SocketStateUnlock( FCB );
577
578 return STATUS_SUCCESS;
579 }
580
581 NTSTATUS NTAPI
582 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
583 PIO_STACK_LOCATION IrpSp ) {
584 NTSTATUS Status = STATUS_SUCCESS;
585 PFILE_OBJECT FileObject = IrpSp->FileObject;
586 PAFD_FCB FCB = FileObject->FsContext;
587 PAFD_RECV_INFO_UDP RecvReq;
588 PLIST_ENTRY ListEntry;
589 PAFD_STORED_DATAGRAM DatagramRecv;
590
591 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
592
593 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
594
595 /* Check that the socket is bound */
596 if( FCB->State != SOCKET_STATE_BOUND )
597 return UnlockAndMaybeComplete
598 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
599 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
600 return UnlockAndMaybeComplete
601 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
602
603 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
604
605 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
606 RecvReq->BufferCount,
607 RecvReq->Address,
608 RecvReq->AddressLength,
609 TRUE, TRUE );
610
611 if( !RecvReq->BufferArray ) { /* access violation in userspace */
612 return UnlockAndMaybeComplete
613 ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 );
614 }
615
616 if( !IsListEmpty( &FCB->DatagramList ) ) {
617 ListEntry = RemoveHeadList( &FCB->DatagramList );
618 DatagramRecv = CONTAINING_RECORD
619 ( ListEntry, AFD_STORED_DATAGRAM, ListEntry );
620 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
621 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
622 InsertHeadList( &FCB->DatagramList,
623 &DatagramRecv->ListEntry );
624 Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
625 Irp->IoStatus.Information = DatagramRecv->Len;
626
627 if( IsListEmpty( &FCB->DatagramList ) )
628 FCB->PollState &= ~AFD_EVENT_RECEIVE;
629 else
630 FCB->PollState |= AFD_EVENT_RECEIVE;
631
632 PollReeval( FCB->DeviceExt, FCB->FileObject );
633
634 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
635
636 return UnlockAndMaybeComplete
637 ( FCB, Status, Irp, Irp->IoStatus.Information );
638 } else {
639 Status = SatisfyPacketRecvRequest
640 ( FCB, Irp, DatagramRecv,
641 (PUINT)&Irp->IoStatus.Information );
642
643 if( IsListEmpty( &FCB->DatagramList ) )
644 FCB->PollState &= ~AFD_EVENT_RECEIVE;
645 else
646 FCB->PollState |= AFD_EVENT_RECEIVE;
647
648 PollReeval( FCB->DeviceExt, FCB->FileObject );
649
650 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
651
652 return UnlockAndMaybeComplete
653 ( FCB, Status, Irp, Irp->IoStatus.Information );
654 }
655 } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
656 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
657 Status = STATUS_CANT_WAIT;
658 FCB->PollState &= ~AFD_EVENT_RECEIVE;
659 PollReeval( FCB->DeviceExt, FCB->FileObject );
660 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
661 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
662 } else {
663 FCB->PollState &= ~AFD_EVENT_RECEIVE;
664 PollReeval( FCB->DeviceExt, FCB->FileObject );
665 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
666 }
667 }