Sync with trunk r63270.
[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
11 #include "afd.h"
12
13 static VOID RefillSocketBuffer( PAFD_FCB FCB )
14 {
15 /* Make sure nothing's in flight first */
16 if (FCB->ReceiveIrp.InFlightRequest) return;
17
18 /* Now ensure that receive is still allowed */
19 if (FCB->TdiReceiveClosed) return;
20
21 /* Check if the buffer is full */
22 if (FCB->Recv.Content == FCB->Recv.Size)
23 {
24 /* If there are bytes used, we can solve this problem */
25 if (FCB->Recv.BytesUsed != 0)
26 {
27 /* Reposition the unused portion to the beginning of the receive window */
28 RtlMoveMemory(FCB->Recv.Window,
29 FCB->Recv.Window + FCB->Recv.BytesUsed,
30 FCB->Recv.Content - FCB->Recv.BytesUsed);
31
32 FCB->Recv.Content -= FCB->Recv.BytesUsed;
33 FCB->Recv.BytesUsed = 0;
34 }
35 else
36 {
37 /* No space in the buffer to receive */
38 return;
39 }
40 }
41
42 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
43
44 TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
45 FCB->Connection.Object,
46 TDI_RECEIVE_NORMAL,
47 FCB->Recv.Window + FCB->Recv.Content,
48 FCB->Recv.Size - FCB->Recv.Content,
49 &FCB->ReceiveIrp.Iosb,
50 ReceiveComplete,
51 FCB );
52 }
53
54 static VOID HandleReceiveComplete( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
55 {
56 FCB->LastReceiveStatus = Status;
57
58 /* We got closed while the receive was in progress */
59 if (FCB->TdiReceiveClosed)
60 {
61 /* The received data is discarded */
62 }
63 /* Receive successful */
64 else if (Status == STATUS_SUCCESS)
65 {
66 FCB->Recv.Content += Information;
67 ASSERT(FCB->Recv.Content <= FCB->Recv.Size);
68
69 /* Check for graceful closure */
70 if (Information == 0)
71 {
72 /* Receive is closed */
73 FCB->TdiReceiveClosed = TRUE;
74 }
75 else
76 {
77 /* Issue another receive IRP to keep the buffer well stocked */
78 RefillSocketBuffer(FCB);
79 }
80 }
81 /* Receive failed with no data (unexpected closure) */
82 else
83 {
84 /* Previously received data remains intact */
85 FCB->TdiReceiveClosed = TRUE;
86 }
87 }
88
89 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
90 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
91
92 return !BytesAvailable && FCB->TdiReceiveClosed;
93 }
94
95 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
96 PAFD_RECV_INFO RecvReq,
97 PUINT TotalBytesCopied ) {
98 UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed,
99 BytesAvailable =
100 FCB->Recv.Content - FCB->Recv.BytesUsed;
101 PAFD_MAPBUF Map;
102 *TotalBytesCopied = 0;
103
104
105 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %u\n", 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: %u @ %p\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 %u: %p:%u\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,("%p %p\n", FCB, Irp));
161
162 AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\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 %p (%u)\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 %p Receive data waiting %u\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 @ %p\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 %p\n", NextIrp));
219 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
220 &NextIrp->Tail.Overlay.ListEntry);
221 break;
222 } else {
223 AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\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 %p 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 UNREFERENCED_PARAMETER(DeviceObject);
288
289 AFD_DbgPrint(MID_TRACE,("Called\n"));
290
291 if( !SocketAcquireStateLock( FCB ) )
292 return STATUS_FILE_CLOSED;
293
294 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
295 FCB->ReceiveIrp.InFlightRequest = NULL;
296
297 if( FCB->State == SOCKET_STATE_CLOSED ) {
298 /* Cleanup our IRP queue because the FCB is being destroyed */
299 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
300 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
301 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
302 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
303 RecvReq = GetLockedData(NextIrp, NextIrpSp);
304 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
305 NextIrp->IoStatus.Information = 0;
306 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
307 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
308 (void)IoSetCancelRoutine(NextIrp, NULL);
309 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
310 }
311 SocketStateUnlock( FCB );
312 return STATUS_FILE_CLOSED;
313 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
314 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
315 SocketStateUnlock( FCB );
316 return STATUS_INVALID_PARAMETER;
317 }
318
319 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
320
321 ReceiveActivity( FCB, NULL );
322
323 SocketStateUnlock( FCB );
324
325 return STATUS_SUCCESS;
326 }
327
328 static NTSTATUS NTAPI
329 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
330 PAFD_STORED_DATAGRAM DatagramRecv,
331 PUINT TotalBytesCopied ) {
332 NTSTATUS Status = STATUS_SUCCESS;
333 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
334 PAFD_RECV_INFO RecvReq =
335 GetLockedData(Irp, IrpSp);
336 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
337 PAFD_MAPBUF Map;
338 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
339
340 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
341 RecvReq->BufferCount +
342 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
343
344 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
345
346 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
347 RecvReq->BufferArray[0].len));
348
349 if( Map[0].Mdl ) {
350 /* Copy the address */
351 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
352 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
353
354 if( DatagramRecv->Address->TAAddressCount != 1 ) {
355 AFD_DbgPrint
356 (MIN_TRACE,
357 ("Wierd address count %d\n",
358 DatagramRecv->Address->TAAddressCount));
359 }
360
361 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
362
363 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
364 sizeof(USHORT),
365 RecvReq->BufferArray[1].len);
366
367 AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
368
369 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
370
371 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
372
373 RtlCopyMemory( Map[1].BufferAddress,
374 &DatagramRecv->Address->Address->AddressType,
375 AddrLen );
376
377 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
378
379 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
380
381 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
382 *((PINT)Map[2].BufferAddress) = AddrLen;
383 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
384 }
385
386 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
387
388 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
389
390 AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
391 0,
392 Map[0].BufferAddress,
393 BytesToCopy));
394
395 RtlCopyMemory( Map[0].BufferAddress,
396 DatagramRecv->Buffer,
397 BytesToCopy );
398
399 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
400
401 *TotalBytesCopied = BytesToCopy;
402 }
403
404 if (*TotalBytesCopied == DatagramRecv->Len)
405 {
406 /* We copied the whole datagram */
407 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
408 }
409 else
410 {
411 /* We only copied part of the datagram */
412 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
413 }
414
415 Irp->IoStatus.Information = *TotalBytesCopied;
416
417 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
418 {
419 FCB->Recv.Content -= DatagramRecv->Len;
420 ExFreePool( DatagramRecv->Address );
421 ExFreePool( DatagramRecv );
422 }
423
424 AFD_DbgPrint(MID_TRACE,("Done\n"));
425
426 return Status;
427 }
428
429 NTSTATUS NTAPI
430 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
431 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
432 NTSTATUS Status = STATUS_INVALID_PARAMETER;
433 PFILE_OBJECT FileObject = IrpSp->FileObject;
434 PAFD_FCB FCB = FileObject->FsContext;
435 PAFD_RECV_INFO RecvReq;
436 UINT TotalBytesCopied = 0;
437 PAFD_STORED_DATAGRAM DatagramRecv;
438 PLIST_ENTRY ListEntry;
439 KPROCESSOR_MODE LockMode;
440
441 UNREFERENCED_PARAMETER(DeviceObject);
442 UNREFERENCED_PARAMETER(Short);
443
444 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
445
446 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
447
448 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
449
450 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
451 FCB->State != SOCKET_STATE_CONNECTED &&
452 FCB->State != SOCKET_STATE_CONNECTING ) {
453 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
454 FCB->State));
455 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
456 Irp, 0 );
457 }
458
459 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
460 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
461 Irp, 0 );
462
463 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
464
465 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
466 RecvReq->BufferCount,
467 NULL, NULL,
468 TRUE, FALSE, LockMode );
469
470 if( !RecvReq->BufferArray ) {
471 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
472 Irp, 0 );
473 }
474
475 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
476 {
477 if (!IsListEmpty(&FCB->DatagramList))
478 {
479 ListEntry = RemoveHeadList(&FCB->DatagramList);
480 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
481 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
482 (PUINT)&Irp->IoStatus.Information);
483
484 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
485 {
486 InsertHeadList(&FCB->DatagramList,
487 &DatagramRecv->ListEntry);
488 }
489
490 if (!IsListEmpty(&FCB->DatagramList))
491 {
492 FCB->PollState |= AFD_EVENT_RECEIVE;
493 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
494 PollReeval( FCB->DeviceExt, FCB->FileObject );
495 }
496 else
497 FCB->PollState &= ~AFD_EVENT_RECEIVE;
498
499 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
500
501 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
502 }
503 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
504 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
505 {
506 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
507 Status = STATUS_CANT_WAIT;
508 FCB->PollState &= ~AFD_EVENT_RECEIVE;
509 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
510 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
511 }
512 else
513 {
514 FCB->PollState &= ~AFD_EVENT_RECEIVE;
515 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
516 }
517 }
518
519 Irp->IoStatus.Status = STATUS_PENDING;
520 Irp->IoStatus.Information = 0;
521
522 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
523 &Irp->Tail.Overlay.ListEntry );
524
525 /************ From this point, the IRP is not ours ************/
526
527 Status = ReceiveActivity( FCB, Irp );
528
529 if( Status == STATUS_PENDING &&
530 !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
531 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
532 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
533 Status = STATUS_CANT_WAIT;
534 TotalBytesCopied = 0;
535 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
536 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
537 return UnlockAndMaybeComplete( FCB, Status, Irp,
538 TotalBytesCopied );
539 } else if( Status == STATUS_PENDING ) {
540 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
541 IoMarkIrpPending( Irp );
542 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
543 } else {
544 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
545 }
546
547 SocketStateUnlock( FCB );
548 return Status;
549 }
550
551 NTSTATUS NTAPI
552 PacketSocketRecvComplete(
553 PDEVICE_OBJECT DeviceObject,
554 PIRP Irp,
555 PVOID Context ) {
556 NTSTATUS Status = STATUS_SUCCESS;
557 PAFD_FCB FCB = Context;
558 PIRP NextIrp;
559 PIO_STACK_LOCATION NextIrpSp;
560 PLIST_ENTRY ListEntry;
561 PAFD_RECV_INFO RecvReq;
562 PAFD_STORED_DATAGRAM DatagramRecv;
563 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
564 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
565
566 UNREFERENCED_PARAMETER(DeviceObject);
567
568 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
569
570 if( !SocketAcquireStateLock( FCB ) )
571 return STATUS_FILE_CLOSED;
572
573 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
574 FCB->ReceiveIrp.InFlightRequest = NULL;
575
576 if( FCB->State == SOCKET_STATE_CLOSED ) {
577 /* Cleanup our IRP queue because the FCB is being destroyed */
578 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
579 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
580 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
581 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
582 RecvReq = GetLockedData(NextIrp, NextIrpSp);
583 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
584 NextIrp->IoStatus.Information = 0;
585 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
586 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
587 (void)IoSetCancelRoutine(NextIrp, NULL);
588 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
589 }
590
591 /* Free all items on the datagram list */
592 while( !IsListEmpty( &FCB->DatagramList ) ) {
593 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
594 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
595 ExFreePool( DatagramRecv->Address );
596 ExFreePool( DatagramRecv );
597 }
598
599 SocketStateUnlock( FCB );
600 return STATUS_FILE_CLOSED;
601 }
602
603 if (Irp->IoStatus.Status != STATUS_SUCCESS)
604 {
605 SocketStateUnlock(FCB);
606 return Irp->IoStatus.Status;
607 }
608
609 if (FCB->TdiReceiveClosed)
610 {
611 SocketStateUnlock(FCB);
612 return STATUS_FILE_CLOSED;
613 }
614
615 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
616
617 if( DatagramRecv ) {
618 DatagramRecv->Len = Irp->IoStatus.Information;
619 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
620 DatagramRecv->Len );
621 AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
622 FCB->AddressFrom->RemoteAddress));
623 DatagramRecv->Address =
624 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
625
626 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
627
628 } else Status = STATUS_NO_MEMORY;
629
630 if( !NT_SUCCESS( Status ) ) {
631 if( DatagramRecv ) ExFreePool( DatagramRecv );
632 SocketStateUnlock( FCB );
633 return Status;
634 } else {
635 FCB->Recv.Content += DatagramRecv->Len;
636 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
637 }
638
639 /* Satisfy as many requests as we can */
640
641 while( !IsListEmpty( &FCB->DatagramList ) &&
642 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
643 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
644 ListEntry = RemoveHeadList( &FCB->DatagramList );
645 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
646 ListEntry );
647 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
648 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
649 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
650 RecvReq = GetLockedData(NextIrp, NextIrpSp);
651
652 AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n",
653 RecvReq, DatagramRecv));
654
655 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
656 Status = SatisfyPacketRecvRequest
657 ( FCB, NextIrp, DatagramRecv,
658 (PUINT)&NextIrp->IoStatus.Information );
659
660 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
661 {
662 InsertHeadList(&FCB->DatagramList,
663 &DatagramRecv->ListEntry);
664 }
665
666 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
667 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
668 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
669
670 AFD_DbgPrint(MID_TRACE,("Completing\n"));
671 (void)IoSetCancelRoutine(NextIrp, NULL);
672 NextIrp->IoStatus.Status = Status;
673
674 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
675 }
676
677 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
678 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
679 FCB->PollState |= AFD_EVENT_RECEIVE;
680 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
681 PollReeval( FCB->DeviceExt, FCB->FileObject );
682 } else
683 FCB->PollState &= ~AFD_EVENT_RECEIVE;
684
685 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
686 /* Now relaunch the datagram request */
687 Status = TdiReceiveDatagram
688 ( &FCB->ReceiveIrp.InFlightRequest,
689 FCB->AddressFile.Object,
690 0,
691 FCB->Recv.Window,
692 FCB->Recv.Size,
693 FCB->AddressFrom,
694 &FCB->ReceiveIrp.Iosb,
695 PacketSocketRecvComplete,
696 FCB );
697 }
698
699 SocketStateUnlock( FCB );
700
701 return STATUS_SUCCESS;
702 }
703
704 NTSTATUS NTAPI
705 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
706 PIO_STACK_LOCATION IrpSp ) {
707 NTSTATUS Status = STATUS_SUCCESS;
708 PFILE_OBJECT FileObject = IrpSp->FileObject;
709 PAFD_FCB FCB = FileObject->FsContext;
710 PAFD_RECV_INFO_UDP RecvReq;
711 PLIST_ENTRY ListEntry;
712 PAFD_STORED_DATAGRAM DatagramRecv;
713 KPROCESSOR_MODE LockMode;
714
715 UNREFERENCED_PARAMETER(DeviceObject);
716
717 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
718
719 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
720
721 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
722
723 /* Check that the socket is bound */
724 if( FCB->State != SOCKET_STATE_BOUND )
725 {
726 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
727 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
728 }
729
730 if (FCB->TdiReceiveClosed)
731 {
732 AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
733 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
734 }
735
736 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
737 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
738
739 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
740
741 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
742 RecvReq->BufferCount,
743 RecvReq->Address,
744 RecvReq->AddressLength,
745 TRUE, TRUE, LockMode );
746
747 if( !RecvReq->BufferArray ) { /* access violation in userspace */
748 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
749 }
750
751 if (!IsListEmpty(&FCB->DatagramList))
752 {
753 ListEntry = RemoveHeadList(&FCB->DatagramList);
754 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
755 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
756 (PUINT)&Irp->IoStatus.Information);
757
758 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
759 {
760 InsertHeadList(&FCB->DatagramList,
761 &DatagramRecv->ListEntry);
762 }
763
764 if (!IsListEmpty(&FCB->DatagramList))
765 {
766 FCB->PollState |= AFD_EVENT_RECEIVE;
767 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
768 PollReeval( FCB->DeviceExt, FCB->FileObject );
769 }
770 else
771 FCB->PollState &= ~AFD_EVENT_RECEIVE;
772
773 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
774
775 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
776 }
777 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
778 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
779 {
780 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
781 Status = STATUS_CANT_WAIT;
782 FCB->PollState &= ~AFD_EVENT_RECEIVE;
783 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
784 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
785 }
786 else
787 {
788 FCB->PollState &= ~AFD_EVENT_RECEIVE;
789 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
790 }
791 }