Synchronize with trunk.
[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 = %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, RetBytesCopied = 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 disconnnect */
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 RetBytesCopied = TotalBytesCopied;
231 }
232 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
233 (void)IoSetCancelRoutine(NextIrp, NULL);
234 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
235 }
236 }
237 }
238
239 if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
240 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
241 FCB->PollState |= AFD_EVENT_RECEIVE;
242 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
243 PollReeval( FCB->DeviceExt, FCB->FileObject );
244 }
245 else
246 {
247 FCB->PollState &= ~AFD_EVENT_RECEIVE;
248 }
249
250 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
251 if (CantReadMore(FCB))
252 {
253 if (FCB->LastReceiveStatus == STATUS_SUCCESS)
254 {
255 FCB->PollState |= AFD_EVENT_DISCONNECT;
256 }
257 else
258 {
259 FCB->PollState |= AFD_EVENT_CLOSE;
260 }
261 FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
262 PollReeval(FCB->DeviceExt, FCB->FileObject);
263 }
264
265 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus));
266
267 /* Sometimes we're called with a NULL Irp */
268 if( Irp ) {
269 Irp->IoStatus.Status = RetStatus;
270 Irp->IoStatus.Information = RetBytesCopied;
271 }
272
273 return RetStatus;
274 }
275
276 NTSTATUS NTAPI ReceiveComplete
277 ( PDEVICE_OBJECT DeviceObject,
278 PIRP Irp,
279 PVOID Context ) {
280 PAFD_FCB FCB = (PAFD_FCB)Context;
281 PLIST_ENTRY NextIrpEntry;
282 PIRP NextIrp;
283 PAFD_RECV_INFO RecvReq;
284 PIO_STACK_LOCATION NextIrpSp;
285
286 UNREFERENCED_PARAMETER(DeviceObject);
287
288 AFD_DbgPrint(MID_TRACE,("Called\n"));
289
290 if( !SocketAcquireStateLock( FCB ) )
291 return STATUS_FILE_CLOSED;
292
293 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
294 FCB->ReceiveIrp.InFlightRequest = NULL;
295
296 if( FCB->State == SOCKET_STATE_CLOSED ) {
297 /* Cleanup our IRP queue because the FCB is being destroyed */
298 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
299 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
300 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
301 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
302 RecvReq = GetLockedData(NextIrp, NextIrpSp);
303 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
304 NextIrp->IoStatus.Information = 0;
305 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
306 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
307 (void)IoSetCancelRoutine(NextIrp, NULL);
308 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
309 }
310 SocketStateUnlock( FCB );
311 return STATUS_FILE_CLOSED;
312 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
313 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
314 SocketStateUnlock( FCB );
315 return STATUS_INVALID_PARAMETER;
316 }
317
318 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
319
320 ReceiveActivity( FCB, NULL );
321
322 SocketStateUnlock( FCB );
323
324 return STATUS_SUCCESS;
325 }
326
327 static NTSTATUS NTAPI
328 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
329 PAFD_STORED_DATAGRAM DatagramRecv,
330 PUINT TotalBytesCopied ) {
331 NTSTATUS Status = STATUS_SUCCESS;
332 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
333 PAFD_RECV_INFO RecvReq =
334 GetLockedData(Irp, IrpSp);
335 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
336 PAFD_MAPBUF Map;
337 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
338
339 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
340 RecvReq->BufferCount +
341 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
342
343 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
344
345 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
346 RecvReq->BufferArray[0].len));
347
348 if( Map[0].Mdl ) {
349 /* Copy the address */
350 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
351 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
352
353 if( DatagramRecv->Address->TAAddressCount != 1 ) {
354 AFD_DbgPrint
355 (MIN_TRACE,
356 ("Wierd address count %d\n",
357 DatagramRecv->Address->TAAddressCount));
358 }
359
360 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
361
362 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
363 sizeof(USHORT),
364 RecvReq->BufferArray[1].len);
365
366 AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
367
368 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
369
370 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
371
372 RtlCopyMemory( Map[1].BufferAddress,
373 &DatagramRecv->Address->Address->AddressType,
374 AddrLen );
375
376 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
377
378 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
379
380 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
381 *((PINT)Map[2].BufferAddress) = AddrLen;
382 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
383 }
384
385 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
386
387 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
388
389 AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
390 0,
391 Map[0].BufferAddress,
392 BytesToCopy));
393
394 RtlCopyMemory( Map[0].BufferAddress,
395 DatagramRecv->Buffer,
396 BytesToCopy );
397
398 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
399
400 *TotalBytesCopied = BytesToCopy;
401 }
402
403 if (*TotalBytesCopied == DatagramRecv->Len)
404 {
405 /* We copied the whole datagram */
406 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
407 }
408 else
409 {
410 /* We only copied part of the datagram */
411 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
412 }
413
414 Irp->IoStatus.Information = *TotalBytesCopied;
415
416 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
417 {
418 FCB->Recv.Content -= DatagramRecv->Len;
419 ExFreePool( DatagramRecv->Address );
420 ExFreePool( DatagramRecv );
421 }
422
423 AFD_DbgPrint(MID_TRACE,("Done\n"));
424
425 return Status;
426 }
427
428 NTSTATUS NTAPI
429 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
430 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
431 NTSTATUS Status = STATUS_INVALID_PARAMETER;
432 PFILE_OBJECT FileObject = IrpSp->FileObject;
433 PAFD_FCB FCB = FileObject->FsContext;
434 PAFD_RECV_INFO RecvReq;
435 UINT TotalBytesCopied = 0;
436 PAFD_STORED_DATAGRAM DatagramRecv;
437 PLIST_ENTRY ListEntry;
438 KPROCESSOR_MODE LockMode;
439
440 UNREFERENCED_PARAMETER(DeviceObject);
441 UNREFERENCED_PARAMETER(Short);
442
443 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
444
445 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
446
447 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
448
449 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
450 FCB->State != SOCKET_STATE_CONNECTED &&
451 FCB->State != SOCKET_STATE_CONNECTING ) {
452 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
453 FCB->State));
454 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
455 Irp, 0 );
456 }
457
458 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
459 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
460 Irp, 0 );
461
462 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
463
464 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
465 RecvReq->BufferCount,
466 NULL, NULL,
467 TRUE, FALSE, LockMode );
468
469 if( !RecvReq->BufferArray ) {
470 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
471 Irp, 0 );
472 }
473
474 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
475 {
476 if (!IsListEmpty(&FCB->DatagramList))
477 {
478 ListEntry = RemoveHeadList(&FCB->DatagramList);
479 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
480 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
481 (PUINT)&Irp->IoStatus.Information);
482
483 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
484 {
485 InsertHeadList(&FCB->DatagramList,
486 &DatagramRecv->ListEntry);
487 }
488
489 if (!IsListEmpty(&FCB->DatagramList))
490 {
491 FCB->PollState |= AFD_EVENT_RECEIVE;
492 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
493 PollReeval( FCB->DeviceExt, FCB->FileObject );
494 }
495 else
496 FCB->PollState &= ~AFD_EVENT_RECEIVE;
497
498 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
499
500 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
501 }
502 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
503 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
504 {
505 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
506 Status = STATUS_CANT_WAIT;
507 FCB->PollState &= ~AFD_EVENT_RECEIVE;
508 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
509 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
510 }
511 else
512 {
513 FCB->PollState &= ~AFD_EVENT_RECEIVE;
514 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
515 }
516 }
517
518 Irp->IoStatus.Status = STATUS_PENDING;
519 Irp->IoStatus.Information = 0;
520
521 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
522 &Irp->Tail.Overlay.ListEntry );
523
524 /************ From this point, the IRP is not ours ************/
525
526 Status = ReceiveActivity( FCB, Irp );
527
528 if( Status == STATUS_PENDING &&
529 !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
530 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
531 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
532 Status = STATUS_CANT_WAIT;
533 TotalBytesCopied = 0;
534 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
535 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
536 return UnlockAndMaybeComplete( FCB, Status, Irp,
537 TotalBytesCopied );
538 } else if( Status == STATUS_PENDING ) {
539 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
540 IoMarkIrpPending( Irp );
541 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
542 } else {
543 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
544 }
545
546 SocketStateUnlock( FCB );
547 return Status;
548 }
549
550 NTSTATUS NTAPI
551 PacketSocketRecvComplete(
552 PDEVICE_OBJECT DeviceObject,
553 PIRP Irp,
554 PVOID Context ) {
555 NTSTATUS Status = STATUS_SUCCESS;
556 PAFD_FCB FCB = Context;
557 PIRP NextIrp;
558 PIO_STACK_LOCATION NextIrpSp;
559 PLIST_ENTRY ListEntry;
560 PAFD_RECV_INFO RecvReq;
561 PAFD_STORED_DATAGRAM DatagramRecv;
562 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
563 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
564
565 UNREFERENCED_PARAMETER(DeviceObject);
566
567 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
568
569 if( !SocketAcquireStateLock( FCB ) )
570 return STATUS_FILE_CLOSED;
571
572 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
573 FCB->ReceiveIrp.InFlightRequest = NULL;
574
575 if( FCB->State == SOCKET_STATE_CLOSED ) {
576 /* Cleanup our IRP queue because the FCB is being destroyed */
577 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
578 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
579 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
580 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
581 RecvReq = GetLockedData(NextIrp, NextIrpSp);
582 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
583 NextIrp->IoStatus.Information = 0;
584 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
585 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
586 (void)IoSetCancelRoutine(NextIrp, NULL);
587 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
588 }
589
590 /* Free all items on the datagram list */
591 while( !IsListEmpty( &FCB->DatagramList ) ) {
592 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
593 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
594 ExFreePool( DatagramRecv->Address );
595 ExFreePool( DatagramRecv );
596 }
597
598 SocketStateUnlock( FCB );
599 return STATUS_FILE_CLOSED;
600 }
601
602 if (Irp->IoStatus.Status != STATUS_SUCCESS)
603 {
604 SocketStateUnlock(FCB);
605 return Irp->IoStatus.Status;
606 }
607
608 if (FCB->TdiReceiveClosed)
609 {
610 SocketStateUnlock(FCB);
611 return STATUS_FILE_CLOSED;
612 }
613
614 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
615
616 if( DatagramRecv ) {
617 DatagramRecv->Len = Irp->IoStatus.Information;
618 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
619 DatagramRecv->Len );
620 AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
621 FCB->AddressFrom->RemoteAddress));
622 DatagramRecv->Address =
623 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
624
625 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
626
627 } else Status = STATUS_NO_MEMORY;
628
629 if( !NT_SUCCESS( Status ) ) {
630 if( DatagramRecv ) ExFreePool( DatagramRecv );
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 &FCB->ReceiveIrp.Iosb,
694 PacketSocketRecvComplete,
695 FCB );
696 }
697
698 SocketStateUnlock( FCB );
699
700 return STATUS_SUCCESS;
701 }
702
703 NTSTATUS NTAPI
704 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
705 PIO_STACK_LOCATION IrpSp ) {
706 NTSTATUS Status = STATUS_SUCCESS;
707 PFILE_OBJECT FileObject = IrpSp->FileObject;
708 PAFD_FCB FCB = FileObject->FsContext;
709 PAFD_RECV_INFO_UDP RecvReq;
710 PLIST_ENTRY ListEntry;
711 PAFD_STORED_DATAGRAM DatagramRecv;
712 KPROCESSOR_MODE LockMode;
713
714 UNREFERENCED_PARAMETER(DeviceObject);
715
716 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
717
718 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
719
720 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
721
722 /* Check that the socket is bound */
723 if( FCB->State != SOCKET_STATE_BOUND )
724 {
725 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
726 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
727 }
728
729 if (FCB->TdiReceiveClosed)
730 {
731 AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
732 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
733 }
734
735 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
736 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
737
738 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
739
740 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
741 RecvReq->BufferCount,
742 RecvReq->Address,
743 RecvReq->AddressLength,
744 TRUE, TRUE, LockMode );
745
746 if( !RecvReq->BufferArray ) { /* access violation in userspace */
747 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
748 }
749
750 if (!IsListEmpty(&FCB->DatagramList))
751 {
752 ListEntry = RemoveHeadList(&FCB->DatagramList);
753 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
754 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
755 (PUINT)&Irp->IoStatus.Information);
756
757 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
758 {
759 InsertHeadList(&FCB->DatagramList,
760 &DatagramRecv->ListEntry);
761 }
762
763 if (!IsListEmpty(&FCB->DatagramList))
764 {
765 FCB->PollState |= AFD_EVENT_RECEIVE;
766 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
767 PollReeval( FCB->DeviceExt, FCB->FileObject );
768 }
769 else
770 FCB->PollState &= ~AFD_EVENT_RECEIVE;
771
772 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
773
774 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
775 }
776 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
777 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
778 {
779 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
780 Status = STATUS_CANT_WAIT;
781 FCB->PollState &= ~AFD_EVENT_RECEIVE;
782 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
783 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
784 }
785 else
786 {
787 FCB->PollState &= ~AFD_EVENT_RECEIVE;
788 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
789 }
790 }