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