[AFD] Introduce and use pool tags. Thanks go to Arty for assisting me with this....
[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 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
413 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
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 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
588 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
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 = ExAllocatePoolWithTag(NonPagedPool,
608 DGSize,
609 TAG_AFD_STORED_DATAGRAM);
610
611 if( DatagramRecv ) {
612 DatagramRecv->Len = Irp->IoStatus.Information;
613 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
614 DatagramRecv->Len );
615 AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
616 FCB->AddressFrom->RemoteAddress));
617 DatagramRecv->Address =
618 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
619
620 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
621
622 } else Status = STATUS_NO_MEMORY;
623
624 if( !NT_SUCCESS( Status ) ) {
625
626 if (DatagramRecv)
627 {
628 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
629 }
630
631 SocketStateUnlock( FCB );
632 return Status;
633 } else {
634 FCB->Recv.Content += DatagramRecv->Len;
635 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
636 }
637
638 /* Satisfy as many requests as we can */
639
640 while( !IsListEmpty( &FCB->DatagramList ) &&
641 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
642 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
643 ListEntry = RemoveHeadList( &FCB->DatagramList );
644 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
645 ListEntry );
646 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
647 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
648 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
649 RecvReq = GetLockedData(NextIrp, NextIrpSp);
650
651 AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n",
652 RecvReq, DatagramRecv));
653
654 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
655 Status = SatisfyPacketRecvRequest
656 ( FCB, NextIrp, DatagramRecv,
657 (PUINT)&NextIrp->IoStatus.Information );
658
659 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
660 {
661 InsertHeadList(&FCB->DatagramList,
662 &DatagramRecv->ListEntry);
663 }
664
665 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
666 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
667 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
668
669 AFD_DbgPrint(MID_TRACE,("Completing\n"));
670 (void)IoSetCancelRoutine(NextIrp, NULL);
671 NextIrp->IoStatus.Status = Status;
672
673 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
674 }
675
676 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
677 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
678 FCB->PollState |= AFD_EVENT_RECEIVE;
679 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
680 PollReeval( FCB->DeviceExt, FCB->FileObject );
681 } else
682 FCB->PollState &= ~AFD_EVENT_RECEIVE;
683
684 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
685 /* Now relaunch the datagram request */
686 Status = TdiReceiveDatagram
687 ( &FCB->ReceiveIrp.InFlightRequest,
688 FCB->AddressFile.Object,
689 0,
690 FCB->Recv.Window,
691 FCB->Recv.Size,
692 FCB->AddressFrom,
693 PacketSocketRecvComplete,
694 FCB );
695 }
696
697 SocketStateUnlock( FCB );
698
699 return STATUS_SUCCESS;
700 }
701
702 NTSTATUS NTAPI
703 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
704 PIO_STACK_LOCATION IrpSp ) {
705 NTSTATUS Status = STATUS_SUCCESS;
706 PFILE_OBJECT FileObject = IrpSp->FileObject;
707 PAFD_FCB FCB = FileObject->FsContext;
708 PAFD_RECV_INFO_UDP RecvReq;
709 PLIST_ENTRY ListEntry;
710 PAFD_STORED_DATAGRAM DatagramRecv;
711 KPROCESSOR_MODE LockMode;
712
713 UNREFERENCED_PARAMETER(DeviceObject);
714
715 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
716
717 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
718
719 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
720
721 /* Check that the socket is bound */
722 if( FCB->State != SOCKET_STATE_BOUND )
723 {
724 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
725 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
726 }
727
728 if (FCB->TdiReceiveClosed)
729 {
730 AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
731 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
732 }
733
734 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
735 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
736
737 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
738
739 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
740 RecvReq->BufferCount,
741 RecvReq->Address,
742 RecvReq->AddressLength,
743 TRUE, TRUE, LockMode );
744
745 if( !RecvReq->BufferArray ) { /* access violation in userspace */
746 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
747 }
748
749 if (!IsListEmpty(&FCB->DatagramList))
750 {
751 ListEntry = RemoveHeadList(&FCB->DatagramList);
752 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
753 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
754 (PUINT)&Irp->IoStatus.Information);
755
756 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
757 {
758 InsertHeadList(&FCB->DatagramList,
759 &DatagramRecv->ListEntry);
760 }
761
762 if (!IsListEmpty(&FCB->DatagramList))
763 {
764 FCB->PollState |= AFD_EVENT_RECEIVE;
765 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
766 PollReeval( FCB->DeviceExt, FCB->FileObject );
767 }
768 else
769 FCB->PollState &= ~AFD_EVENT_RECEIVE;
770
771 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
772
773 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
774 }
775 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
776 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
777 {
778 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
779 Status = STATUS_CANT_WAIT;
780 FCB->PollState &= ~AFD_EVENT_RECEIVE;
781 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
782 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
783 }
784 else
785 {
786 FCB->PollState &= ~AFD_EVENT_RECEIVE;
787 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
788 }
789 }