sync to trunk revision 36500
[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( Irp->Cancel ) {
238 if( FCB ) FCB->ReceiveIrp.InFlightRequest = NULL;
239 return STATUS_CANCELLED;
240 }
241
242 if( !SocketAcquireStateLock( FCB ) ) return Status;
243
244 FCB->ReceiveIrp.InFlightRequest = NULL;
245 FCB->Recv.Content = Irp->IoStatus.Information;
246 FCB->Recv.BytesUsed = 0;
247
248 if( FCB->State == SOCKET_STATE_CLOSED ) {
249 AFD_DbgPrint(MIN_TRACE,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n"));
250 SocketStateUnlock( FCB );
251 DestroySocket( FCB );
252 return STATUS_SUCCESS;
253 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
254 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
255 SocketStateUnlock( FCB );
256 return STATUS_INVALID_PARAMETER;
257 }
258
259 HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
260
261 ReceiveActivity( FCB, NULL );
262
263 PollReeval( FCB->DeviceExt, FCB->FileObject );
264
265 SocketStateUnlock( FCB );
266
267 AFD_DbgPrint(MID_TRACE,("Returned %x\n", Status));
268
269 return STATUS_SUCCESS;
270 }
271
272 NTSTATUS STDCALL
273 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
274 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
275 NTSTATUS Status = STATUS_INVALID_PARAMETER;
276 PFILE_OBJECT FileObject = IrpSp->FileObject;
277 PAFD_FCB FCB = FileObject->FsContext;
278 PAFD_RECV_INFO RecvReq;
279 UINT TotalBytesCopied = 0;
280
281 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
282
283 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
284
285 if( FCB->State != SOCKET_STATE_CONNECTED &&
286 FCB->State != SOCKET_STATE_CONNECTING ) {
287 AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n",
288 FCB->State));
289 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
290 Irp, 0, NULL );
291 }
292
293 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
294 {
295 AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n"));
296 return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED,
297 Irp, 0, NULL );
298 }
299
300 FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
301 PollReeval( FCB->DeviceExt, FCB->FileObject );
302
303 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
304 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
305 Irp, 0, NULL );
306
307 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
308
309 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
310 RecvReq->BufferCount,
311 NULL, NULL,
312 TRUE, FALSE );
313
314 if( !RecvReq->BufferArray ) {
315 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
316 Irp, 0, NULL );
317 }
318
319 Irp->IoStatus.Status = STATUS_PENDING;
320 Irp->IoStatus.Information = 0;
321
322 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
323 &Irp->Tail.Overlay.ListEntry );
324
325 /************ From this point, the IRP is not ours ************/
326
327 Status = ReceiveActivity( FCB, Irp );
328
329 if( Status == STATUS_PENDING && RecvReq->AfdFlags & AFD_IMMEDIATE ) {
330 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
331 Status = STATUS_CANT_WAIT;
332 TotalBytesCopied = 0;
333 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
334 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
335 return UnlockAndMaybeComplete( FCB, Status, Irp,
336 TotalBytesCopied, NULL );
337 } else if( Status == STATUS_PENDING ) {
338 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
339 IoMarkIrpPending( Irp );
340 } else {
341 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
342 }
343
344 SocketStateUnlock( FCB );
345 return Status;
346 }
347
348
349 static NTSTATUS STDCALL
350 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
351 PAFD_STORED_DATAGRAM DatagramRecv,
352 PUINT TotalBytesCopied ) {
353 NTSTATUS Status = STATUS_SUCCESS;
354 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
355 PAFD_RECV_INFO RecvReq =
356 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
357 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
358 PAFD_MAPBUF Map;
359
360 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
361 RecvReq->BufferCount +
362 EXTRA_LOCK_BUFFERS);
363
364 BytesToCopy =
365 MIN( RecvReq->BufferArray[0].len, BytesAvailable );
366
367 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
368 RecvReq->BufferArray[0].len));
369
370 if( Map[0].Mdl ) {
371 /* Copy the address */
372 if( Map[1].Mdl && Map[2].Mdl ) {
373 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
374
375 if( DatagramRecv->Address->TAAddressCount != 1 ) {
376 AFD_DbgPrint
377 (MID_TRACE,
378 ("Wierd address count %d\n",
379 DatagramRecv->Address->TAAddressCount));
380 }
381
382 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
383
384 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
385 sizeof(USHORT),
386 RecvReq->BufferArray[1].len);
387
388 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
389
390 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
391
392 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
393
394 RtlCopyMemory( Map[1].BufferAddress,
395 &DatagramRecv->Address->Address->AddressType,
396 AddrLen );
397
398 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
399
400 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
401
402 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
403 *((PINT)Map[2].BufferAddress) = AddrLen;
404 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
405 }
406
407 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
408
409 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
410
411 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
412 0,
413 Map[0].BufferAddress,
414 BytesToCopy));
415
416 /* OskitDumpBuffer
417 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
418
419 RtlCopyMemory( Map[0].BufferAddress,
420 FCB->Recv.Window + FCB->Recv.BytesUsed,
421 BytesToCopy );
422
423 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
424
425 *TotalBytesCopied = BytesToCopy;
426
427 if (!RecvReq->TdiFlags & TDI_RECEIVE_PEEK) {
428 FCB->Recv.BytesUsed = 0;
429 }
430 }
431
432 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
433 Irp->IoStatus.Information = BytesToCopy;
434 ExFreePool( DatagramRecv->Address );
435 ExFreePool( DatagramRecv );
436
437 AFD_DbgPrint(MID_TRACE,("Done\n"));
438
439 return Status;
440 }
441
442 NTSTATUS NTAPI
443 PacketSocketRecvComplete(
444 PDEVICE_OBJECT DeviceObject,
445 PIRP Irp,
446 PVOID Context ) {
447 NTSTATUS Status = STATUS_SUCCESS;
448 PAFD_FCB FCB = Context;
449 PIRP NextIrp;
450 PIO_STACK_LOCATION NextIrpSp;
451 PLIST_ENTRY ListEntry;
452 PAFD_RECV_INFO RecvReq;
453 PAFD_STORED_DATAGRAM DatagramRecv;
454 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
455
456 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
457
458 if( Irp->Cancel ) {
459 if( FCB ) FCB->ReceiveIrp.InFlightRequest = NULL;
460 return STATUS_CANCELLED;
461 }
462
463 if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
464
465 FCB->ReceiveIrp.InFlightRequest = NULL;
466
467 if( FCB->State == SOCKET_STATE_CLOSED ) {
468 SocketStateUnlock( FCB );
469 DestroySocket( FCB );
470 return STATUS_SUCCESS;
471 }
472
473 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
474
475 if( DatagramRecv ) {
476 DatagramRecv->Len = Irp->IoStatus.Information;
477 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
478 DatagramRecv->Len );
479 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
480 FCB->AddressFrom->RemoteAddress));
481 DatagramRecv->Address =
482 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
483
484 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
485
486 } else Status = STATUS_NO_MEMORY;
487
488 if( !NT_SUCCESS( Status ) ) {
489 if( DatagramRecv ) ExFreePool( DatagramRecv );
490 SocketStateUnlock( FCB );
491 return Status;
492 } else {
493 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
494 }
495
496 /* Satisfy as many requests as we can */
497
498 while( !IsListEmpty( &FCB->DatagramList ) &&
499 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
500 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
501 ListEntry = RemoveHeadList( &FCB->DatagramList );
502 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
503 ListEntry );
504 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
505 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
506 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
507 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
508
509 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
510 RecvReq, DatagramRecv));
511
512 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
513 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
514 InsertHeadList( &FCB->DatagramList,
515 &DatagramRecv->ListEntry );
516 Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
517 NextIrp->IoStatus.Information = DatagramRecv->Len;
518 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
519 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
520 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
521 } else {
522 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
523 Status = SatisfyPacketRecvRequest
524 ( FCB, NextIrp, DatagramRecv,
525 (PUINT)&NextIrp->IoStatus.Information );
526 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
527 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
528 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
529 AFD_DbgPrint(MID_TRACE,("Completing\n"));
530 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
531 }
532 }
533
534 if( !IsListEmpty( &FCB->DatagramList ) ) {
535 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
536 FCB->PollState |= AFD_EVENT_RECEIVE;
537 } else
538 FCB->PollState &= ~AFD_EVENT_RECEIVE;
539
540 PollReeval( FCB->DeviceExt, FCB->FileObject );
541
542 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
543 /* Now relaunch the datagram request */
544 SocketCalloutEnter( FCB );
545
546 Status = TdiReceiveDatagram
547 ( &FCB->ReceiveIrp.InFlightRequest,
548 FCB->AddressFile.Object,
549 0,
550 FCB->Recv.Window,
551 FCB->Recv.Size,
552 FCB->AddressFrom,
553 &FCB->ReceiveIrp.Iosb,
554 PacketSocketRecvComplete,
555 FCB );
556
557 SocketCalloutLeave( FCB );
558 }
559
560 SocketStateUnlock( FCB );
561
562 return STATUS_SUCCESS;
563 }
564
565 NTSTATUS STDCALL
566 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
567 PIO_STACK_LOCATION IrpSp ) {
568 NTSTATUS Status = STATUS_SUCCESS;
569 PFILE_OBJECT FileObject = IrpSp->FileObject;
570 PAFD_FCB FCB = FileObject->FsContext;
571 PAFD_RECV_INFO_UDP RecvReq;
572 PLIST_ENTRY ListEntry;
573 PAFD_STORED_DATAGRAM DatagramRecv;
574
575 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
576
577 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
578
579 FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
580
581 /* Check that the socket is bound */
582 if( FCB->State != SOCKET_STATE_BOUND )
583 return UnlockAndMaybeComplete
584 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0, NULL );
585 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
586 return UnlockAndMaybeComplete
587 ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL );
588
589 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
590
591 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
592 RecvReq->BufferCount,
593 RecvReq->Address,
594 RecvReq->AddressLength,
595 TRUE, TRUE );
596
597 if( !RecvReq->BufferArray ) { /* access violation in userspace */
598 return UnlockAndMaybeComplete
599 ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0, NULL );
600 }
601
602 if( !IsListEmpty( &FCB->DatagramList ) ) {
603 ListEntry = RemoveHeadList( &FCB->DatagramList );
604 DatagramRecv = CONTAINING_RECORD
605 ( ListEntry, AFD_STORED_DATAGRAM, ListEntry );
606 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
607 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
608 InsertHeadList( &FCB->DatagramList,
609 &DatagramRecv->ListEntry );
610 Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
611 Irp->IoStatus.Information = DatagramRecv->Len;
612
613 if( IsListEmpty( &FCB->DatagramList ) )
614 FCB->PollState &= ~AFD_EVENT_RECEIVE;
615 else
616 FCB->PollState |= AFD_EVENT_RECEIVE;
617
618 PollReeval( FCB->DeviceExt, FCB->FileObject );
619
620 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
621
622 return UnlockAndMaybeComplete
623 ( FCB, Status, Irp, Irp->IoStatus.Information, NULL );
624 } else {
625 Status = SatisfyPacketRecvRequest
626 ( FCB, Irp, DatagramRecv,
627 (PUINT)&Irp->IoStatus.Information );
628
629 if( IsListEmpty( &FCB->DatagramList ) )
630 FCB->PollState &= ~AFD_EVENT_RECEIVE;
631 else
632 FCB->PollState |= AFD_EVENT_RECEIVE;
633
634 PollReeval( FCB->DeviceExt, FCB->FileObject );
635
636 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
637
638 return UnlockAndMaybeComplete
639 ( FCB, Status, Irp, Irp->IoStatus.Information, NULL );
640 }
641 } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
642 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
643 Status = STATUS_CANT_WAIT;
644 PollReeval( FCB->DeviceExt, FCB->FileObject );
645 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
646 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
647 } else {
648 PollReeval( FCB->DeviceExt, FCB->FileObject );
649 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
650 }
651 }