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