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