ReactOS  0.4.14-dev-556-g4c5b21f
read.c
Go to the documentation of this file.
1 /*
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 
11 #include "afd.h"
12 
14 {
15  /* Make sure nothing's in flight first */
16  if (FCB->ReceiveIrp.InFlightRequest) return;
17 
18  /* Now ensure that receive is still allowed */
19  if (FCB->TdiReceiveClosed) return;
20 
21  /* Check if the buffer is full */
22  if (FCB->Recv.Content == FCB->Recv.Size)
23  {
24  /* If there are bytes used, we can solve this problem */
25  if (FCB->Recv.BytesUsed != 0)
26  {
27  /* Reposition the unused portion to the beginning of the receive window */
28  RtlMoveMemory(FCB->Recv.Window,
29  FCB->Recv.Window + FCB->Recv.BytesUsed,
30  FCB->Recv.Content - FCB->Recv.BytesUsed);
31 
32  FCB->Recv.Content -= FCB->Recv.BytesUsed;
33  FCB->Recv.BytesUsed = 0;
34  }
35  else
36  {
37  /* No space in the buffer to receive */
38  return;
39  }
40  }
41 
42  AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
43 
44  TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
45  FCB->Connection.Object,
47  FCB->Recv.Window + FCB->Recv.Content,
48  FCB->Recv.Size - FCB->Recv.Content,
50  FCB );
51 }
52 
54 {
55  FCB->LastReceiveStatus = Status;
56 
57  /* We got closed while the receive was in progress */
58  if (FCB->TdiReceiveClosed)
59  {
60  /* The received data is discarded */
61  }
62  /* Receive successful */
63  else if (Status == STATUS_SUCCESS)
64  {
65  FCB->Recv.Content += Information;
66  ASSERT(FCB->Recv.Content <= FCB->Recv.Size);
67 
68  /* Check for graceful closure */
69  if (Information == 0)
70  {
71  /* Receive is closed */
72  FCB->TdiReceiveClosed = TRUE;
73  }
74  else
75  {
76  /* Issue another receive IRP to keep the buffer well stocked */
78  }
79  }
80  /* Receive failed with no data (unexpected closure) */
81  else
82  {
83  /* Previously received data remains intact */
84  FCB->TdiReceiveClosed = TRUE;
85  }
86 }
87 
89  UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
90 
91  return !BytesAvailable && FCB->TdiReceiveClosed;
92 }
93 
95  PAFD_RECV_INFO RecvReq,
96  PUINT TotalBytesCopied ) {
97  UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed,
98  BytesAvailable =
99  FCB->Recv.Content - FCB->Recv.BytesUsed;
100  PAFD_MAPBUF Map;
101  *TotalBytesCopied = 0;
102 
103 
104  AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %u\n", BytesAvailable));
105 
106  if( CantReadMore(FCB) ) return STATUS_SUCCESS;
107  if( !BytesAvailable ) return STATUS_PENDING;
108 
109  Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
110 
111  AFD_DbgPrint(MID_TRACE,("Buffer Count: %u @ %p\n",
112  RecvReq->BufferCount,
113  RecvReq->BufferArray));
114  for( i = 0;
115  RecvReq->BufferArray &&
116  BytesAvailable &&
117  i < RecvReq->BufferCount;
118  i++ ) {
119  BytesToCopy =
120  MIN( RecvReq->BufferArray[i].len, BytesAvailable );
121 
122  if( Map[i].Mdl ) {
123  Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
124 
125  AFD_DbgPrint(MID_TRACE,("Buffer %u: %p:%u\n",
126  i,
127  Map[i].BufferAddress,
128  BytesToCopy));
129 
130  RtlCopyMemory( Map[i].BufferAddress,
131  FCB->Recv.Window + FcbBytesCopied,
132  BytesToCopy );
133 
134  MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
135 
136  *TotalBytesCopied += BytesToCopy;
137  FcbBytesCopied += BytesToCopy;
138  BytesAvailable -= BytesToCopy;
139 
140  if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
141  FCB->Recv.BytesUsed += BytesToCopy;
142  }
143  }
144 
145  /* Issue another receive IRP to keep the buffer well stocked */
147 
148  return STATUS_SUCCESS;
149 }
150 
152  PLIST_ENTRY NextIrpEntry;
153  PIRP NextIrp;
154  PIO_STACK_LOCATION NextIrpSp;
155  PAFD_RECV_INFO RecvReq;
156  UINT TotalBytesCopied = 0;
158 
159  AFD_DbgPrint(MID_TRACE,("%p %p\n", FCB, Irp));
160 
161  AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
162  FCB, FCB->Recv.Content));
163 
164  if( CantReadMore( FCB ) ) {
165  /* Success here means that we got an EOF. Complete a pending read
166  * with zero bytes if we haven't yet overread, then kill the others.
167  */
168  while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
169  NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
170  NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
171  NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
172  RecvReq = GetLockedData(NextIrp, NextIrpSp);
173 
174  AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
175  TotalBytesCopied));
176  UnlockBuffers( RecvReq->BufferArray,
177  RecvReq->BufferCount, FALSE );
178  if (FCB->Overread && FCB->LastReceiveStatus == STATUS_SUCCESS)
179  {
180  /* Overread after a graceful disconnect so complete with an error */
182  }
183  else
184  {
185  /* Unexpected disconnect by the remote host or initial read after a graceful disconnect */
186  Status = FCB->LastReceiveStatus;
187  }
188  NextIrp->IoStatus.Status = Status;
189  NextIrp->IoStatus.Information = 0;
190  if( NextIrp == Irp ) RetStatus = Status;
191  if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
192  (void)IoSetCancelRoutine(NextIrp, NULL);
194  FCB->Overread = TRUE;
195  }
196  } else {
197  /* Kick the user that receive would be possible now */
198  /* XXX Not implemented yet */
199 
200  AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
201  FCB, FCB->Recv.Content));
202  /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
203 
204  /* Try to clear some requests */
205  while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
206  NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
207  NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
208  NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
209  RecvReq = GetLockedData(NextIrp, NextIrpSp);
210 
211  AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq));
212 
214  ( FCB, RecvReq, &TotalBytesCopied );
215 
216  if( Status == STATUS_PENDING ) {
217  AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp));
218  InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
219  &NextIrp->Tail.Overlay.ListEntry);
220  break;
221  } else {
222  AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
223  TotalBytesCopied));
224  UnlockBuffers( RecvReq->BufferArray,
225  RecvReq->BufferCount, FALSE );
226  NextIrp->IoStatus.Status = Status;
227  NextIrp->IoStatus.Information = TotalBytesCopied;
228  if( NextIrp == Irp ) {
229  RetStatus = Status;
230  }
231  if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
232  (void)IoSetCancelRoutine(NextIrp, NULL);
234  }
235  }
236  }
237 
238  if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
239  IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
240  FCB->PollState |= AFD_EVENT_RECEIVE;
241  FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
242  PollReeval( FCB->DeviceExt, FCB->FileObject );
243  }
244  else
245  {
246  FCB->PollState &= ~AFD_EVENT_RECEIVE;
247  }
248 
249  /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
250  if (CantReadMore(FCB))
251  {
252  if (FCB->LastReceiveStatus == STATUS_SUCCESS)
253  {
254  FCB->PollState |= AFD_EVENT_DISCONNECT;
255  }
256  else
257  {
258  FCB->PollState |= AFD_EVENT_CLOSE;
259  }
260  FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
261  PollReeval(FCB->DeviceExt, FCB->FileObject);
262  }
263 
264  AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus));
265 
266  return RetStatus;
267 }
268 
271  PIRP Irp,
272  PVOID Context ) {
274  PLIST_ENTRY NextIrpEntry;
275  PIRP NextIrp;
276  PAFD_RECV_INFO RecvReq;
277  PIO_STACK_LOCATION NextIrpSp;
278 
280 
281  AFD_DbgPrint(MID_TRACE,("Called\n"));
282 
283  if( !SocketAcquireStateLock( FCB ) )
284  return STATUS_FILE_CLOSED;
285 
286  ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
287  FCB->ReceiveIrp.InFlightRequest = NULL;
288 
289  if( FCB->State == SOCKET_STATE_CLOSED ) {
290  /* Cleanup our IRP queue because the FCB is being destroyed */
291  while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
292  NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
293  NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
294  NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
295  RecvReq = GetLockedData(NextIrp, NextIrpSp);
296  NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
297  NextIrp->IoStatus.Information = 0;
298  UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
299  if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
300  (void)IoSetCancelRoutine(NextIrp, NULL);
302  }
304  return STATUS_FILE_CLOSED;
305  } else if( FCB->State == SOCKET_STATE_LISTENING ) {
306  AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
309  }
310 
311  HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
312 
314 
316 
317  return STATUS_SUCCESS;
318 }
319 
320 static NTSTATUS NTAPI
322  PAFD_STORED_DATAGRAM DatagramRecv,
323  PUINT TotalBytesCopied ) {
326  PAFD_RECV_INFO RecvReq =
328  UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
329  PAFD_MAPBUF Map;
330  BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
331 
332  Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
333  RecvReq->BufferCount +
334  (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
335 
336  BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
337 
338  AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
339  RecvReq->BufferArray[0].len));
340 
341  if( Map[0].Mdl ) {
342  /* Copy the address */
343  if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
344  AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
345 
346  if( DatagramRecv->Address->TAAddressCount != 1 ) {
348  (MIN_TRACE,
349  ("Wierd address count %d\n",
350  DatagramRecv->Address->TAAddressCount));
351  }
352 
353  AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
354 
355  AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
356  sizeof(USHORT),
357  RecvReq->BufferArray[1].len);
358 
359  AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
360 
361  Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
362 
363  AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
364 
365  RtlCopyMemory( Map[1].BufferAddress,
366  &DatagramRecv->Address->Address->AddressType,
367  AddrLen );
368 
369  MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
370 
371  AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
372 
373  Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
374  *((PINT)Map[2].BufferAddress) = AddrLen;
375  MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
376  }
377 
378  AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
379 
380  Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
381 
382  AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
383  0,
384  Map[0].BufferAddress,
385  BytesToCopy));
386 
387  RtlCopyMemory( Map[0].BufferAddress,
388  DatagramRecv->Buffer,
389  BytesToCopy );
390 
391  MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
392 
393  *TotalBytesCopied = BytesToCopy;
394  }
395 
396  if (*TotalBytesCopied == DatagramRecv->Len)
397  {
398  /* We copied the whole datagram */
399  Status = Irp->IoStatus.Status = STATUS_SUCCESS;
400  }
401  else
402  {
403  /* We only copied part of the datagram */
404  Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
405  }
406 
407  Irp->IoStatus.Information = *TotalBytesCopied;
408 
409  if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
410  {
411  FCB->Recv.Content -= DatagramRecv->Len;
414  }
415 
416  AFD_DbgPrint(MID_TRACE,("Done\n"));
417 
418  return Status;
419 }
420 
426  PAFD_FCB FCB = FileObject->FsContext;
427  PAFD_RECV_INFO RecvReq;
428  UINT TotalBytesCopied = 0;
429  PAFD_STORED_DATAGRAM DatagramRecv;
430  PLIST_ENTRY ListEntry;
432 
435 
436  AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
437 
438  if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
439 
440  FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
441 
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",
446  FCB->State));
448  Irp, 0 );
449  }
450 
451  if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
453  Irp, 0 );
454 
455  AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
456 
457  RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
458  RecvReq->BufferCount,
459  NULL, NULL,
460  TRUE, FALSE, LockMode );
461 
462  if( !RecvReq->BufferArray ) {
464  Irp, 0 );
465  }
466 
468  {
469  if (!IsListEmpty(&FCB->DatagramList))
470  {
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);
475 
476  if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
477  {
478  InsertHeadList(&FCB->DatagramList,
479  &DatagramRecv->ListEntry);
480  }
481 
482  if (!IsListEmpty(&FCB->DatagramList))
483  {
484  FCB->PollState |= AFD_EVENT_RECEIVE;
485  FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
486  PollReeval( FCB->DeviceExt, FCB->FileObject );
487  }
488  else
489  FCB->PollState &= ~AFD_EVENT_RECEIVE;
490 
491  UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
492 
493  return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
494  }
495  else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
496  ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
497  {
498  AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
500  FCB->PollState &= ~AFD_EVENT_RECEIVE;
501  UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
502  return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
503  }
504  else
505  {
506  FCB->PollState &= ~AFD_EVENT_RECEIVE;
508  }
509  }
510 
511  Irp->IoStatus.Status = STATUS_PENDING;
512  Irp->IoStatus.Information = 0;
513 
514  InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
515  &Irp->Tail.Overlay.ListEntry );
516 
517  /************ From this point, the IRP is not ours ************/
518 
520 
521  if( Status == STATUS_PENDING &&
522  !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
523  ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
524  AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
526  TotalBytesCopied = 0;
527  RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
528  UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
530  TotalBytesCopied );
531  } else if( Status == STATUS_PENDING ) {
532  AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
535  } else {
536  AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
537  }
538 
540  return Status;
541 }
542 
546  PIRP Irp,
547  PVOID Context ) {
549  PAFD_FCB FCB = Context;
550  PIRP NextIrp;
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;
557 
559 
560  AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
561 
562  if( !SocketAcquireStateLock( FCB ) )
563  return STATUS_FILE_CLOSED;
564 
565  ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
566  FCB->ReceiveIrp.InFlightRequest = NULL;
567 
568  if( FCB->State == SOCKET_STATE_CLOSED ) {
569  /* Cleanup our IRP queue because the FCB is being destroyed */
570  while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
571  NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
572  NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
573  NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
574  RecvReq = GetLockedData(NextIrp, NextIrpSp);
575  NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
576  NextIrp->IoStatus.Information = 0;
577  UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
578  if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
579  (void)IoSetCancelRoutine(NextIrp, NULL);
581  }
582 
583  /* Free all items on the datagram list */
584  while( !IsListEmpty( &FCB->DatagramList ) ) {
585  DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
586  DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
589  }
590 
592  return STATUS_FILE_CLOSED;
593  }
594 
595  if (Irp->IoStatus.Status != STATUS_SUCCESS)
596  {
598  return Irp->IoStatus.Status;
599  }
600 
601  if (FCB->TdiReceiveClosed)
602  {
604  return STATUS_FILE_CLOSED;
605  }
606 
607  DatagramRecv = ExAllocatePoolWithTag(NonPagedPool,
608  DGSize,
610 
611  if( DatagramRecv ) {
612  DatagramRecv->Len = Irp->IoStatus.Information;
613  RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
614  DatagramRecv->Len );
615  AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
616  FCB->AddressFrom->RemoteAddress));
617  DatagramRecv->Address =
618  TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
619 
620  if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
621 
622  } else Status = STATUS_NO_MEMORY;
623 
624  if( !NT_SUCCESS( Status ) ) {
625 
626  if (DatagramRecv)
627  {
629  }
630 
632  return Status;
633  } else {
634  FCB->Recv.Content += DatagramRecv->Len;
635  InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
636  }
637 
638  /* Satisfy as many requests as we can */
639 
640  while( !IsListEmpty( &FCB->DatagramList ) &&
641  !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
642  AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
643  ListEntry = RemoveHeadList( &FCB->DatagramList );
644  DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
645  ListEntry );
646  ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
647  NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
648  NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
649  RecvReq = GetLockedData(NextIrp, NextIrpSp);
650 
651  AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n",
652  RecvReq, DatagramRecv));
653 
654  AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
656  ( FCB, NextIrp, DatagramRecv,
657  (PUINT)&NextIrp->IoStatus.Information );
658 
659  if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
660  {
661  InsertHeadList(&FCB->DatagramList,
662  &DatagramRecv->ListEntry);
663  }
664 
665  AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
666  UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
667  if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
668 
669  AFD_DbgPrint(MID_TRACE,("Completing\n"));
670  (void)IoSetCancelRoutine(NextIrp, NULL);
671  NextIrp->IoStatus.Status = Status;
672 
674  }
675 
676  if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
677  AFD_DbgPrint(MID_TRACE,("Signalling\n"));
678  FCB->PollState |= AFD_EVENT_RECEIVE;
679  FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
680  PollReeval( FCB->DeviceExt, FCB->FileObject );
681  } else
682  FCB->PollState &= ~AFD_EVENT_RECEIVE;
683 
684  if( NT_SUCCESS(Irp->IoStatus.Status) && FCB->Recv.Content < FCB->Recv.Size ) {
685  /* Now relaunch the datagram request */
687  ( &FCB->ReceiveIrp.InFlightRequest,
688  FCB->AddressFile.Object,
689  0,
690  FCB->Recv.Window,
691  FCB->Recv.Size,
692  FCB->AddressFrom,
694  FCB );
695  }
696 
698 
699  return STATUS_SUCCESS;
700 }
701 
707  PAFD_FCB FCB = FileObject->FsContext;
708  PAFD_RECV_INFO_UDP RecvReq;
709  PLIST_ENTRY ListEntry;
710  PAFD_STORED_DATAGRAM DatagramRecv;
712 
714 
715  AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
716 
717  if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
718 
719  FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
720 
721  /* Check that the socket is bound */
722  if( FCB->State != SOCKET_STATE_BOUND )
723  {
724  AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
726  }
727 
728  if (FCB->TdiReceiveClosed)
729  {
730  AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
732  }
733 
734  if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
736 
737  AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
738 
739  RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
740  RecvReq->BufferCount,
741  RecvReq->Address,
742  RecvReq->AddressLength,
743  TRUE, TRUE, LockMode );
744 
745  if( !RecvReq->BufferArray ) { /* access violation in userspace */
747  }
748 
749  if (!IsListEmpty(&FCB->DatagramList))
750  {
751  ListEntry = RemoveHeadList(&FCB->DatagramList);
752  DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
753  Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
754  (PUINT)&Irp->IoStatus.Information);
755 
756  if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
757  {
758  InsertHeadList(&FCB->DatagramList,
759  &DatagramRecv->ListEntry);
760  }
761 
762  if (!IsListEmpty(&FCB->DatagramList))
763  {
764  FCB->PollState |= AFD_EVENT_RECEIVE;
765  FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
766  PollReeval( FCB->DeviceExt, FCB->FileObject );
767  }
768  else
769  FCB->PollState &= ~AFD_EVENT_RECEIVE;
770 
771  UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
772 
773  return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
774  }
775  else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
776  ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
777  {
778  AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
780  FCB->PollState &= ~AFD_EVENT_RECEIVE;
781  UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
782  return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
783  }
784  else
785  {
786  FCB->PollState &= ~AFD_EVENT_RECEIVE;
788  }
789 }
VOID SocketStateUnlock(PAFD_FCB FCB)
Definition: lock.c:370
UINT len
Definition: shared.h:17
ULONG AfdFlags
Definition: shared.h:94
PINT AddressLength
Definition: shared.h:97
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MID_TRACE
Definition: debug.h:15
VOID PollReeval(PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: select.c:407
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define AFD_IMMEDIATE
Definition: shared.h:220
PFILE_OBJECT FileObject
Definition: ntfs.h:516
#define FUNCTION_RECV
Definition: afd.h:85
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS NTAPI AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
Definition: read.c:703
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define AFD_EVENT_DISCONNECT
Definition: shared.h:206
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
PAFD_WSABUF LockBuffers(PAFD_WSABUF Buf, UINT Count, PVOID AddressBuf, PINT AddressLen, BOOLEAN Write, BOOLEAN LockAddress, KPROCESSOR_MODE LockMode)
Definition: lock.c:205
PVOID LockRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Output, KPROCESSOR_MODE *LockMode)
Definition: lock.c:24
LONG NTSTATUS
Definition: precomp.h:26
#define TAG_AFD_TRANSPORT_ADDRESS
Definition: afd.h:39
ULONG AfdFlags
Definition: shared.h:87
BOOLEAN SocketAcquireStateLock(PAFD_FCB FCB)
Definition: lock.c:360
PAFD_WSABUF BufferArray
Definition: shared.h:92
static NTSTATUS TryToSatisfyRecvRequestFromBuffer(PAFD_FCB FCB, PAFD_RECV_INFO RecvReq, PUINT TotalBytesCopied)
Definition: read.c:94
IRP
Definition: iotypes.h:2463
NTSTATUS NTAPI UnlockAndMaybeComplete(PAFD_FCB FCB, NTSTATUS Status, PIRP Irp, UINT Information)
Definition: lock.c:375
#define InsertTailList(ListHead, Entry)
IoSetCancelRoutine(Irp, CancelRoutine)
#define EXTRA_LOCK_BUFFERS
Definition: afd.h:95
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PVOID NTAPI MmMapLockedPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode)
Definition: mdlsup.c:822
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3167
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
static BOOLEAN CantReadMore(PAFD_FCB FCB)
Definition: read.c:88
ULONG LockMode
Definition: env_spec_w32.cpp:8
uint32_t ULONG_PTR
Definition: typedefs.h:63
T MIN(T a, T b)
Definition: polytest.cpp:79
#define AFD_EVENT_CLOSE
Definition: shared.h:208
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define TDI_RECEIVE_NORMAL
Definition: tdi.h:122
#define AFD_ENDPOINT_CONNECTIONLESS
Definition: shared.h:153
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static NTSTATUS ReceiveActivity(PAFD_FCB FCB, PIRP Irp)
Definition: read.c:151
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
NTSTATUS TdiReceive(PIRP *Irp, PFILE_OBJECT TransportObject, USHORT Flags, PCHAR Buffer, UINT BufferLength, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Definition: tdi.c:976
VOID NTAPI MmUnmapLockedPages(IN PVOID BaseAddress, IN PMDL Mdl)
Definition: mdlsup.c:841
#define AFD_DbgPrint(_t_, _x_)
Definition: debug.h:60
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define AFD_EVENT_RECEIVE
Definition: shared.h:203
#define IoCompleteRequest
Definition: irp.c:1240
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
ULONG TdiFlags
Definition: shared.h:95
static VOID RefillSocketBuffer(PAFD_FCB FCB)
Definition: read.c:13
#define FD_READ_BIT
Definition: winsock2.h:293
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define IO_NETWORK_INCREMENT
Definition: tcpip.h:43
Definition: afd.h:161
short Short
Definition: ftraster.c:311
NTSTATUS NTAPI ReceiveComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: read.c:270
struct _AFD_FCB * PAFD_FCB
#define AFD_OVERLAPPED
Definition: shared.h:219
#define FD_CLOSE_BIT
Definition: winsock2.h:303
int * PINT
Definition: windef.h:177
NTSTATUS LeaveIrpUntilLater(PAFD_FCB FCB, PIRP Irp, UINT Function)
Definition: lock.c:433
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
VOID UnlockRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp)
Definition: lock.c:180
#define SOCKET_STATE_CONNECTED
Definition: afd.h:76
VOID UnlockBuffers(PAFD_WSABUF Buf, UINT Count, BOOL Address)
Definition: lock.c:289
struct _AFD_MAPBUF * PAFD_MAPBUF
LONG TAAddressCount
Definition: tdi.h:376
PAFD_WSABUF BufferArray
Definition: shared.h:85
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
* PFILE_OBJECT
Definition: iotypes.h:1955
PVOID GetLockedData(PIRP Irp, PIO_STACK_LOCATION IrpSp)
Definition: lock.c:13
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG Flags
Definition: ntfs.h:532
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG TdiFlags
Definition: shared.h:88
ULONG BufferCount
Definition: shared.h:86
USHORT AddressType
Definition: tdi.h:339
Definition: typedefs.h:117
NTSTATUS TdiReceiveDatagram(PIRP *Irp, PFILE_OBJECT TransportObject, USHORT Flags, PCHAR Buffer, UINT BufferLength, PTDI_CONNECTION_INFORMATION Addr, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Definition: tdi.c:1058
static VOID HandleReceiveComplete(PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information)
Definition: read.c:53
Status
Definition: gdiplustypes.h:24
TA_ADDRESS Address[1]
Definition: tdi.h:377
NTSTATUS NTAPI PacketSocketRecvComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: read.c:544
LIST_ENTRY ListEntry
Definition: afd.h:155
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PTRANSPORT_ADDRESS Address
Definition: afd.h:157
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS LostSocket(PIRP Irp)
Definition: lock.c:387
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
static NTSTATUS NTAPI SatisfyPacketRecvRequest(PAFD_FCB FCB, PIRP Irp, PAFD_STORED_DATAGRAM DatagramRecv, PUINT TotalBytesCopied)
Definition: read.c:321
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
unsigned int UINT
Definition: ndis.h:50
#define TDI_RECEIVE_PEEK
Definition: tdi.h:124
PVOID BufferAddress
Definition: afd.h:106
#define SOCKET_STATE_LISTENING
Definition: afd.h:77
ULONG BufferCount
Definition: shared.h:93
USHORT AddressLength
Definition: tdi.h:338
#define SOCKET_STATE_BOUND
Definition: afd.h:74
CHAR Buffer[1]
Definition: afd.h:158
struct tagContext Context
Definition: acpixf.h:1030
#define SOCKET_STATE_CONNECTING
Definition: afd.h:75
#define SOCKET_STATE_CLOSED
Definition: afd.h:82
PTRANSPORT_ADDRESS TaCopyTransportAddress(PTRANSPORT_ADDRESS OtherAddress)
Definition: tdiconn.c:80
#define TAG_AFD_STORED_DATAGRAM
Definition: afd.h:51
#define MIN_TRACE
Definition: debug.h:14
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
return STATUS_SUCCESS
Definition: btrfs.c:2938
BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp)
Definition: main.c:1092
IoMarkIrpPending(Irp)
struct _AFD_STORED_DATAGRAM AFD_STORED_DATAGRAM
unsigned int * PUINT
Definition: ndis.h:50
Iosb Information
Definition: create.c:4377
NTSTATUS NTAPI AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Short)
Definition: read.c:422
DRIVER_CANCEL AfdCancelHandler
Definition: afd.h:304
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:518