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