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