Synchronize with trunk r58528.
[reactos.git] / drivers / network / afd / afd / read.c
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 #include "afd.h"
11
12 static VOID RefillSocketBuffer( PAFD_FCB FCB )
13 {
14 /* Make sure nothing's in flight first */
15 if (FCB->ReceiveIrp.InFlightRequest) return;
16
17 /* Now ensure that receive is still allowed */
18 if (FCB->TdiReceiveClosed) return;
19
20 /* Check if the buffer is full */
21 if (FCB->Recv.Content == FCB->Recv.Size)
22 {
23 /* If there are bytes used, we can solve this problem */
24 if (FCB->Recv.BytesUsed != 0)
25 {
26 /* Reposition the unused portion to the beginning of the receive window */
27 RtlMoveMemory(FCB->Recv.Window,
28 FCB->Recv.Window + FCB->Recv.BytesUsed,
29 FCB->Recv.Content - FCB->Recv.BytesUsed);
30
31 FCB->Recv.Content -= FCB->Recv.BytesUsed;
32 FCB->Recv.BytesUsed = 0;
33 }
34 else
35 {
36 /* No space in the buffer to receive */
37 return;
38 }
39 }
40
41 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
42
43 TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
44 FCB->Connection.Object,
45 TDI_RECEIVE_NORMAL,
46 FCB->Recv.Window + FCB->Recv.Content,
47 FCB->Recv.Size - FCB->Recv.Content,
48 &FCB->ReceiveIrp.Iosb,
49 ReceiveComplete,
50 FCB );
51 }
52
53 static VOID HandleReceiveComplete( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
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 */
77 RefillSocketBuffer(FCB);
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
88 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
89 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
90
91 return !BytesAvailable && FCB->TdiReceiveClosed;
92 }
93
94 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
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 = %d\n",
105 BytesAvailable));
106
107 if( CantReadMore(FCB) ) return STATUS_SUCCESS;
108 if( !BytesAvailable ) return STATUS_PENDING;
109
110 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
111
112 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n",
113 RecvReq->BufferCount,
114 RecvReq->BufferArray));
115 for( i = 0;
116 RecvReq->BufferArray &&
117 BytesAvailable &&
118 i < RecvReq->BufferCount;
119 i++ ) {
120 BytesToCopy =
121 MIN( RecvReq->BufferArray[i].len, BytesAvailable );
122
123 if( Map[i].Mdl ) {
124 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
125
126 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
127 i,
128 Map[i].BufferAddress,
129 BytesToCopy));
130
131 RtlCopyMemory( Map[i].BufferAddress,
132 FCB->Recv.Window + FcbBytesCopied,
133 BytesToCopy );
134
135 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
136
137 *TotalBytesCopied += BytesToCopy;
138 FcbBytesCopied += BytesToCopy;
139 BytesAvailable -= BytesToCopy;
140
141 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
142 FCB->Recv.BytesUsed += BytesToCopy;
143 }
144 }
145
146 /* Issue another receive IRP to keep the buffer well stocked */
147 RefillSocketBuffer(FCB);
148
149 return STATUS_SUCCESS;
150 }
151
152 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
153 PLIST_ENTRY NextIrpEntry;
154 PIRP NextIrp;
155 PIO_STACK_LOCATION NextIrpSp;
156 PAFD_RECV_INFO RecvReq;
157 UINT TotalBytesCopied = 0, RetBytesCopied = 0;
158 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
159
160 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
161
162 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
163 FCB, FCB->Recv.Content));
164
165 if( CantReadMore( FCB ) ) {
166 /* Success here means that we got an EOF. Complete a pending read
167 * with zero bytes if we haven't yet overread, then kill the others.
168 */
169 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
170 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
171 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
172 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
173 RecvReq = GetLockedData(NextIrp, NextIrpSp);
174
175 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
176 TotalBytesCopied));
177 UnlockBuffers( RecvReq->BufferArray,
178 RecvReq->BufferCount, FALSE );
179 if (FCB->Overread && FCB->LastReceiveStatus == STATUS_SUCCESS)
180 {
181 /* Overread after a graceful disconnect so complete with an error */
182 Status = STATUS_FILE_CLOSED;
183 }
184 else
185 {
186 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */
187 Status = FCB->LastReceiveStatus;
188 }
189 NextIrp->IoStatus.Status = Status;
190 NextIrp->IoStatus.Information = 0;
191 if( NextIrp == Irp ) RetStatus = Status;
192 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
193 (void)IoSetCancelRoutine(NextIrp, NULL);
194 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
195 FCB->Overread = TRUE;
196 }
197 } else {
198 /* Kick the user that receive would be possible now */
199 /* XXX Not implemented yet */
200
201 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
202 FCB, FCB->Recv.Content));
203 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
204
205 /* Try to clear some requests */
206 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
207 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
208 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
209 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
210 RecvReq = GetLockedData(NextIrp, NextIrpSp);
211
212 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
213
214 Status = TryToSatisfyRecvRequestFromBuffer
215 ( FCB, RecvReq, &TotalBytesCopied );
216
217 if( Status == STATUS_PENDING ) {
218 AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
219 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
220 &NextIrp->Tail.Overlay.ListEntry);
221 break;
222 } else {
223 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
224 TotalBytesCopied));
225 UnlockBuffers( RecvReq->BufferArray,
226 RecvReq->BufferCount, FALSE );
227 NextIrp->IoStatus.Status = Status;
228 NextIrp->IoStatus.Information = TotalBytesCopied;
229 if( NextIrp == Irp ) {
230 RetStatus = Status;
231 RetBytesCopied = TotalBytesCopied;
232 }
233 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
234 (void)IoSetCancelRoutine(NextIrp, NULL);
235 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
236 }
237 }
238 }
239
240 if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
241 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
242 FCB->PollState |= AFD_EVENT_RECEIVE;
243 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
244 PollReeval( FCB->DeviceExt, FCB->FileObject );
245 }
246 else
247 {
248 FCB->PollState &= ~AFD_EVENT_RECEIVE;
249 }
250
251 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
252 if (CantReadMore(FCB))
253 {
254 if (FCB->LastReceiveStatus == STATUS_SUCCESS)
255 {
256 FCB->PollState |= AFD_EVENT_DISCONNECT;
257 }
258 else
259 {
260 FCB->PollState |= AFD_EVENT_CLOSE;
261 }
262 FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
263 PollReeval(FCB->DeviceExt, FCB->FileObject);
264 }
265
266 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
267
268 /* Sometimes we're called with a NULL Irp */
269 if( Irp ) {
270 Irp->IoStatus.Status = RetStatus;
271 Irp->IoStatus.Information = RetBytesCopied;
272 }
273
274 return RetStatus;
275 }
276
277 NTSTATUS NTAPI ReceiveComplete
278 ( PDEVICE_OBJECT DeviceObject,
279 PIRP Irp,
280 PVOID Context ) {
281 PAFD_FCB FCB = (PAFD_FCB)Context;
282 PLIST_ENTRY NextIrpEntry;
283 PIRP NextIrp;
284 PAFD_RECV_INFO RecvReq;
285 PIO_STACK_LOCATION NextIrpSp;
286
287 AFD_DbgPrint(MID_TRACE,("Called\n"));
288
289 if( !SocketAcquireStateLock( FCB ) )
290 return STATUS_FILE_CLOSED;
291
292 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
293 FCB->ReceiveIrp.InFlightRequest = NULL;
294
295 if( FCB->State == SOCKET_STATE_CLOSED ) {
296 /* Cleanup our IRP queue because the FCB is being destroyed */
297 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
298 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
299 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
300 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
301 RecvReq = GetLockedData(NextIrp, NextIrpSp);
302 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
303 NextIrp->IoStatus.Information = 0;
304 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
305 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
306 (void)IoSetCancelRoutine(NextIrp, NULL);
307 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
308 }
309 SocketStateUnlock( FCB );
310 return STATUS_FILE_CLOSED;
311 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
312 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
313 SocketStateUnlock( FCB );
314 return STATUS_INVALID_PARAMETER;
315 }
316
317 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
318
319 ReceiveActivity( FCB, NULL );
320
321 SocketStateUnlock( FCB );
322
323 return STATUS_SUCCESS;
324 }
325
326 static NTSTATUS NTAPI
327 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
328 PAFD_STORED_DATAGRAM DatagramRecv,
329 PUINT TotalBytesCopied ) {
330 NTSTATUS Status = STATUS_SUCCESS;
331 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
332 PAFD_RECV_INFO RecvReq =
333 GetLockedData(Irp, IrpSp);
334 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
335 PAFD_MAPBUF Map;
336 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
337
338 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
339 RecvReq->BufferCount +
340 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
341
342 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
343
344 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
345 RecvReq->BufferArray[0].len));
346
347 if( Map[0].Mdl ) {
348 /* Copy the address */
349 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
350 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
351
352 if( DatagramRecv->Address->TAAddressCount != 1 ) {
353 AFD_DbgPrint
354 (MIN_TRACE,
355 ("Wierd address count %d\n",
356 DatagramRecv->Address->TAAddressCount));
357 }
358
359 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
360
361 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
362 sizeof(USHORT),
363 RecvReq->BufferArray[1].len);
364
365 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
366
367 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
368
369 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
370
371 RtlCopyMemory( Map[1].BufferAddress,
372 &DatagramRecv->Address->Address->AddressType,
373 AddrLen );
374
375 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
376
377 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
378
379 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
380 *((PINT)Map[2].BufferAddress) = AddrLen;
381 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
382 }
383
384 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
385
386 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
387
388 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
389 0,
390 Map[0].BufferAddress,
391 BytesToCopy));
392
393 RtlCopyMemory( Map[0].BufferAddress,
394 DatagramRecv->Buffer,
395 BytesToCopy );
396
397 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
398
399 *TotalBytesCopied = BytesToCopy;
400 }
401
402 if (*TotalBytesCopied == DatagramRecv->Len)
403 {
404 /* We copied the whole datagram */
405 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
406 }
407 else
408 {
409 /* We only copied part of the datagram */
410 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
411 }
412
413 Irp->IoStatus.Information = *TotalBytesCopied;
414
415 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
416 {
417 FCB->Recv.Content -= DatagramRecv->Len;
418 ExFreePool( DatagramRecv->Address );
419 ExFreePool( DatagramRecv );
420 }
421
422 AFD_DbgPrint(MID_TRACE,("Done\n"));
423
424 return Status;
425 }
426
427 NTSTATUS NTAPI
428 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
429 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
430 NTSTATUS Status = STATUS_INVALID_PARAMETER;
431 PFILE_OBJECT FileObject = IrpSp->FileObject;
432 PAFD_FCB FCB = FileObject->FsContext;
433 PAFD_RECV_INFO RecvReq;
434 UINT TotalBytesCopied = 0;
435 PAFD_STORED_DATAGRAM DatagramRecv;
436 PLIST_ENTRY ListEntry;
437 KPROCESSOR_MODE LockMode;
438
439 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
440
441 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
442
443 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
444
445 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
446 FCB->State != SOCKET_STATE_CONNECTED &&
447 FCB->State != SOCKET_STATE_CONNECTING ) {
448 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
449 FCB->State));
450 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
451 Irp, 0 );
452 }
453
454 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
455 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
456 Irp, 0 );
457
458 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
459
460 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
461 RecvReq->BufferCount,
462 NULL, NULL,
463 TRUE, FALSE, LockMode );
464
465 if( !RecvReq->BufferArray ) {
466 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
467 Irp, 0 );
468 }
469
470 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
471 {
472 if (!IsListEmpty(&FCB->DatagramList))
473 {
474 ListEntry = RemoveHeadList(&FCB->DatagramList);
475 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
476 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
477 (PUINT)&Irp->IoStatus.Information);
478
479 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
480 {
481 InsertHeadList(&FCB->DatagramList,
482 &DatagramRecv->ListEntry);
483 }
484
485 if (!IsListEmpty(&FCB->DatagramList))
486 {
487 FCB->PollState |= AFD_EVENT_RECEIVE;
488 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
489 PollReeval( FCB->DeviceExt, FCB->FileObject );
490 }
491 else
492 FCB->PollState &= ~AFD_EVENT_RECEIVE;
493
494 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
495
496 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
497 }
498 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
499 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
500 {
501 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
502 Status = STATUS_CANT_WAIT;
503 FCB->PollState &= ~AFD_EVENT_RECEIVE;
504 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
505 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
506 }
507 else
508 {
509 FCB->PollState &= ~AFD_EVENT_RECEIVE;
510 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
511 }
512 }
513
514 Irp->IoStatus.Status = STATUS_PENDING;
515 Irp->IoStatus.Information = 0;
516
517 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
518 &Irp->Tail.Overlay.ListEntry );
519
520 /************ From this point, the IRP is not ours ************/
521
522 Status = ReceiveActivity( FCB, Irp );
523
524 if( Status == STATUS_PENDING &&
525 !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
526 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
527 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
528 Status = STATUS_CANT_WAIT;
529 TotalBytesCopied = 0;
530 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
531 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
532 return UnlockAndMaybeComplete( FCB, Status, Irp,
533 TotalBytesCopied );
534 } else if( Status == STATUS_PENDING ) {
535 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
536 IoMarkIrpPending( Irp );
537 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
538 } else {
539 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
540 }
541
542 SocketStateUnlock( FCB );
543 return Status;
544 }
545
546 NTSTATUS NTAPI
547 PacketSocketRecvComplete(
548 PDEVICE_OBJECT DeviceObject,
549 PIRP Irp,
550 PVOID Context ) {
551 NTSTATUS Status = STATUS_SUCCESS;
552 PAFD_FCB FCB = Context;
553 PIRP NextIrp;
554 PIO_STACK_LOCATION NextIrpSp;
555 PLIST_ENTRY ListEntry;
556 PAFD_RECV_INFO RecvReq;
557 PAFD_STORED_DATAGRAM DatagramRecv;
558 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
559 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
560
561 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
562
563 if( !SocketAcquireStateLock( FCB ) )
564 return STATUS_FILE_CLOSED;
565
566 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
567 FCB->ReceiveIrp.InFlightRequest = NULL;
568
569 if( FCB->State == SOCKET_STATE_CLOSED ) {
570 /* Cleanup our IRP queue because the FCB is being destroyed */
571 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
572 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
573 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
574 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
575 RecvReq = GetLockedData(NextIrp, NextIrpSp);
576 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
577 NextIrp->IoStatus.Information = 0;
578 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
579 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
580 (void)IoSetCancelRoutine(NextIrp, NULL);
581 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
582 }
583
584 /* Free all items on the datagram list */
585 while( !IsListEmpty( &FCB->DatagramList ) ) {
586 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
587 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
588 ExFreePool( DatagramRecv->Address );
589 ExFreePool( DatagramRecv );
590 }
591
592 SocketStateUnlock( FCB );
593 return STATUS_FILE_CLOSED;
594 }
595
596 if (Irp->IoStatus.Status != STATUS_SUCCESS)
597 {
598 SocketStateUnlock(FCB);
599 return Irp->IoStatus.Status;
600 }
601
602 if (FCB->TdiReceiveClosed)
603 {
604 SocketStateUnlock(FCB);
605 return STATUS_FILE_CLOSED;
606 }
607
608 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
609
610 if( DatagramRecv ) {
611 DatagramRecv->Len = Irp->IoStatus.Information;
612 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
613 DatagramRecv->Len );
614 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
615 FCB->AddressFrom->RemoteAddress));
616 DatagramRecv->Address =
617 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
618
619 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
620
621 } else Status = STATUS_NO_MEMORY;
622
623 if( !NT_SUCCESS( Status ) ) {
624 if( DatagramRecv ) ExFreePool( DatagramRecv );
625 SocketStateUnlock( FCB );
626 return Status;
627 } else {
628 FCB->Recv.Content += DatagramRecv->Len;
629 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
630 }
631
632 /* Satisfy as many requests as we can */
633
634 while( !IsListEmpty( &FCB->DatagramList ) &&
635 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
636 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
637 ListEntry = RemoveHeadList( &FCB->DatagramList );
638 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
639 ListEntry );
640 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
641 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
642 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
643 RecvReq = GetLockedData(NextIrp, NextIrpSp);
644
645 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
646 RecvReq, DatagramRecv));
647
648 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
649 Status = SatisfyPacketRecvRequest
650 ( FCB, NextIrp, DatagramRecv,
651 (PUINT)&NextIrp->IoStatus.Information );
652
653 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
654 {
655 InsertHeadList(&FCB->DatagramList,
656 &DatagramRecv->ListEntry);
657 }
658
659 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
660 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
661 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
662
663 AFD_DbgPrint(MID_TRACE,("Completing\n"));
664 (void)IoSetCancelRoutine(NextIrp, NULL);
665 NextIrp->IoStatus.Status = Status;
666
667 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
668 }
669
670 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
671 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
672 FCB->PollState |= AFD_EVENT_RECEIVE;
673 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
674 PollReeval( FCB->DeviceExt, FCB->FileObject );
675 } else
676 FCB->PollState &= ~AFD_EVENT_RECEIVE;
677
678 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
679 /* Now relaunch the datagram request */
680 Status = TdiReceiveDatagram
681 ( &FCB->ReceiveIrp.InFlightRequest,
682 FCB->AddressFile.Object,
683 0,
684 FCB->Recv.Window,
685 FCB->Recv.Size,
686 FCB->AddressFrom,
687 &FCB->ReceiveIrp.Iosb,
688 PacketSocketRecvComplete,
689 FCB );
690 }
691
692 SocketStateUnlock( FCB );
693
694 return STATUS_SUCCESS;
695 }
696
697 NTSTATUS NTAPI
698 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
699 PIO_STACK_LOCATION IrpSp ) {
700 NTSTATUS Status = STATUS_SUCCESS;
701 PFILE_OBJECT FileObject = IrpSp->FileObject;
702 PAFD_FCB FCB = FileObject->FsContext;
703 PAFD_RECV_INFO_UDP RecvReq;
704 PLIST_ENTRY ListEntry;
705 PAFD_STORED_DATAGRAM DatagramRecv;
706 KPROCESSOR_MODE LockMode;
707
708 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
709
710 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
711
712 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
713
714 /* Check that the socket is bound */
715 if( FCB->State != SOCKET_STATE_BOUND )
716 {
717 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
718 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
719 }
720
721 if (FCB->TdiReceiveClosed)
722 {
723 AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
724 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
725 }
726
727 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
728 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
729
730 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
731
732 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
733 RecvReq->BufferCount,
734 RecvReq->Address,
735 RecvReq->AddressLength,
736 TRUE, TRUE, LockMode );
737
738 if( !RecvReq->BufferArray ) { /* access violation in userspace */
739 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
740 }
741
742 if (!IsListEmpty(&FCB->DatagramList))
743 {
744 ListEntry = RemoveHeadList(&FCB->DatagramList);
745 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
746 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
747 (PUINT)&Irp->IoStatus.Information);
748
749 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
750 {
751 InsertHeadList(&FCB->DatagramList,
752 &DatagramRecv->ListEntry);
753 }
754
755 if (!IsListEmpty(&FCB->DatagramList))
756 {
757 FCB->PollState |= AFD_EVENT_RECEIVE;
758 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
759 PollReeval( FCB->DeviceExt, FCB->FileObject );
760 }
761 else
762 FCB->PollState &= ~AFD_EVENT_RECEIVE;
763
764 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
765
766 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
767 }
768 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
769 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
770 {
771 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
772 Status = STATUS_CANT_WAIT;
773 FCB->PollState &= ~AFD_EVENT_RECEIVE;
774 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
775 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
776 }
777 else
778 {
779 FCB->PollState &= ~AFD_EVENT_RECEIVE;
780 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
781 }
782 }