Synchronize up to trunk's revision r57784.
[reactos.git] / drivers / network / afd / afd / read.c
1 /* $Id$
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 /* We got closed while the receive was in progress */
56 if (FCB->TdiReceiveClosed)
57 {
58 FCB->Recv.Content = 0;
59 FCB->Recv.BytesUsed = 0;
60 }
61 /* Receive successful */
62 else if (Status == STATUS_SUCCESS)
63 {
64 FCB->Recv.Content += Information;
65 ASSERT(FCB->Recv.Content <= FCB->Recv.Size);
66
67 /* Check for graceful closure */
68 if (Information == 0)
69 {
70 FCB->TdiReceiveClosed = TRUE;
71
72 /* Signal graceful receive shutdown */
73 FCB->PollState |= AFD_EVENT_DISCONNECT;
74 FCB->PollStatus[FD_CLOSE_BIT] = Status;
75
76 PollReeval( FCB->DeviceExt, FCB->FileObject );
77 }
78
79 /* Issue another receive IRP to keep the buffer well stocked */
80 RefillSocketBuffer(FCB);
81 }
82 /* Receive failed with no data (unexpected closure) */
83 else
84 {
85 FCB->Recv.BytesUsed = 0;
86 FCB->Recv.Content = 0;
87 FCB->TdiReceiveClosed = TRUE;
88
89 /* Signal complete connection failure immediately */
90 FCB->PollState |= AFD_EVENT_CLOSE;
91 FCB->PollStatus[FD_CLOSE_BIT] = Status;
92
93 PollReeval( FCB->DeviceExt, FCB->FileObject );
94 }
95 }
96
97 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
98 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
99
100 return !BytesAvailable && FCB->TdiReceiveClosed;
101 }
102
103 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
104 PAFD_RECV_INFO RecvReq,
105 PUINT TotalBytesCopied ) {
106 UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed,
107 BytesAvailable =
108 FCB->Recv.Content - FCB->Recv.BytesUsed;
109 PAFD_MAPBUF Map;
110 *TotalBytesCopied = 0;
111
112
113 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
114 BytesAvailable));
115
116 if( CantReadMore(FCB) ) return STATUS_SUCCESS;
117 if( !BytesAvailable ) return STATUS_PENDING;
118
119 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
120
121 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n",
122 RecvReq->BufferCount,
123 RecvReq->BufferArray));
124 for( i = 0;
125 RecvReq->BufferArray &&
126 BytesAvailable &&
127 i < RecvReq->BufferCount;
128 i++ ) {
129 BytesToCopy =
130 MIN( RecvReq->BufferArray[i].len, BytesAvailable );
131
132 if( Map[i].Mdl ) {
133 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
134
135 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
136 i,
137 Map[i].BufferAddress,
138 BytesToCopy));
139
140 RtlCopyMemory( Map[i].BufferAddress,
141 FCB->Recv.Window + FcbBytesCopied,
142 BytesToCopy );
143
144 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
145
146 *TotalBytesCopied += BytesToCopy;
147 FcbBytesCopied += BytesToCopy;
148 BytesAvailable -= BytesToCopy;
149
150 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
151 FCB->Recv.BytesUsed += BytesToCopy;
152 }
153 }
154
155 /* Issue another receive IRP to keep the buffer well stocked */
156 RefillSocketBuffer(FCB);
157
158 return STATUS_SUCCESS;
159 }
160
161 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
162 PLIST_ENTRY NextIrpEntry;
163 PIRP NextIrp;
164 PIO_STACK_LOCATION NextIrpSp;
165 PAFD_RECV_INFO RecvReq;
166 UINT TotalBytesCopied = 0, RetBytesCopied = 0;
167 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
168
169 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
170
171 /* Kick the user that receive would be possible now */
172 /* XXX Not implemented yet */
173
174 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
175 FCB, FCB->Recv.Content));
176
177 if( CantReadMore( FCB ) ) {
178 /* Success here means that we got an EOF. Complete a pending read
179 * with zero bytes if we haven't yet overread, then kill the others.
180 */
181 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
182 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
183 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
184 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
185 RecvReq = GetLockedData(NextIrp, NextIrpSp);
186
187 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
188 TotalBytesCopied));
189 UnlockBuffers( RecvReq->BufferArray,
190 RecvReq->BufferCount, FALSE );
191 if (FCB->Overread && FCB->PollStatus[FD_CLOSE_BIT] == STATUS_SUCCESS)
192 {
193 /* Overread after a graceful disconnect so complete with an error */
194 Status = STATUS_FILE_CLOSED;
195 }
196 else
197 {
198 /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */
199 Status = FCB->PollStatus[FD_CLOSE_BIT];
200 }
201 NextIrp->IoStatus.Status = Status;
202 NextIrp->IoStatus.Information = 0;
203 if( NextIrp == Irp ) RetStatus = Status;
204 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
205 (void)IoSetCancelRoutine(NextIrp, NULL);
206 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
207 FCB->Overread = TRUE;
208 }
209 } else {
210 /* Kick the user that receive would be possible now */
211 /* XXX Not implemented yet */
212
213 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
214 FCB, FCB->Recv.Content));
215 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
216
217 /* Try to clear some requests */
218 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
219 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
220 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
221 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
222 RecvReq = GetLockedData(NextIrp, NextIrpSp);
223
224 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
225
226 Status = TryToSatisfyRecvRequestFromBuffer
227 ( FCB, RecvReq, &TotalBytesCopied );
228
229 if( Status == STATUS_PENDING ) {
230 AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
231 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
232 &NextIrp->Tail.Overlay.ListEntry);
233 break;
234 } else {
235 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
236 TotalBytesCopied));
237 UnlockBuffers( RecvReq->BufferArray,
238 RecvReq->BufferCount, FALSE );
239 NextIrp->IoStatus.Status = Status;
240 NextIrp->IoStatus.Information = TotalBytesCopied;
241 if( NextIrp == Irp ) {
242 RetStatus = Status;
243 RetBytesCopied = TotalBytesCopied;
244 }
245 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
246 (void)IoSetCancelRoutine(NextIrp, NULL);
247 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
248 }
249 }
250 }
251
252 if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
253 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
254 FCB->PollState |= AFD_EVENT_RECEIVE;
255 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
256 PollReeval( FCB->DeviceExt, FCB->FileObject );
257 }
258 else
259 {
260 FCB->PollState &= ~AFD_EVENT_RECEIVE;
261 }
262
263 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
264
265 /* Sometimes we're called with a NULL Irp */
266 if( Irp ) {
267 Irp->IoStatus.Status = RetStatus;
268 Irp->IoStatus.Information = RetBytesCopied;
269 }
270
271 return RetStatus;
272 }
273
274 NTSTATUS NTAPI ReceiveComplete
275 ( PDEVICE_OBJECT DeviceObject,
276 PIRP Irp,
277 PVOID Context ) {
278 PAFD_FCB FCB = (PAFD_FCB)Context;
279 PLIST_ENTRY NextIrpEntry;
280 PIRP NextIrp;
281 PAFD_RECV_INFO RecvReq;
282 PIO_STACK_LOCATION NextIrpSp;
283
284 AFD_DbgPrint(MID_TRACE,("Called\n"));
285
286 if( !SocketAcquireStateLock( FCB ) )
287 return STATUS_FILE_CLOSED;
288
289 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
290 FCB->ReceiveIrp.InFlightRequest = NULL;
291
292 if( FCB->State == SOCKET_STATE_CLOSED ) {
293 /* Cleanup our IRP queue because the FCB is being destroyed */
294 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
295 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
296 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
297 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
298 RecvReq = GetLockedData(NextIrp, NextIrpSp);
299 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
300 NextIrp->IoStatus.Information = 0;
301 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
302 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
303 (void)IoSetCancelRoutine(NextIrp, NULL);
304 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
305 }
306 SocketStateUnlock( FCB );
307 return STATUS_FILE_CLOSED;
308 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
309 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
310 SocketStateUnlock( FCB );
311 return STATUS_INVALID_PARAMETER;
312 }
313
314 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
315
316 ReceiveActivity( FCB, NULL );
317
318 SocketStateUnlock( FCB );
319
320 return STATUS_SUCCESS;
321 }
322
323 static NTSTATUS NTAPI
324 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
325 PAFD_STORED_DATAGRAM DatagramRecv,
326 PUINT TotalBytesCopied ) {
327 NTSTATUS Status = STATUS_SUCCESS;
328 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
329 PAFD_RECV_INFO RecvReq =
330 GetLockedData(Irp, IrpSp);
331 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
332 PAFD_MAPBUF Map;
333 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
334
335 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
336 RecvReq->BufferCount +
337 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
338
339 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
340
341 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
342 RecvReq->BufferArray[0].len));
343
344 if( Map[0].Mdl ) {
345 /* Copy the address */
346 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
347 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
348
349 if( DatagramRecv->Address->TAAddressCount != 1 ) {
350 AFD_DbgPrint
351 (MIN_TRACE,
352 ("Wierd address count %d\n",
353 DatagramRecv->Address->TAAddressCount));
354 }
355
356 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
357
358 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
359 sizeof(USHORT),
360 RecvReq->BufferArray[1].len);
361
362 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
363
364 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
365
366 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
367
368 RtlCopyMemory( Map[1].BufferAddress,
369 &DatagramRecv->Address->Address->AddressType,
370 AddrLen );
371
372 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
373
374 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
375
376 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
377 *((PINT)Map[2].BufferAddress) = AddrLen;
378 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
379 }
380
381 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
382
383 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
384
385 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
386 0,
387 Map[0].BufferAddress,
388 BytesToCopy));
389
390 RtlCopyMemory( Map[0].BufferAddress,
391 DatagramRecv->Buffer,
392 BytesToCopy );
393
394 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
395
396 *TotalBytesCopied = BytesToCopy;
397 }
398
399 if (*TotalBytesCopied == DatagramRecv->Len)
400 {
401 /* We copied the whole datagram */
402 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
403 }
404 else
405 {
406 /* We only copied part of the datagram */
407 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
408 }
409
410 Irp->IoStatus.Information = *TotalBytesCopied;
411
412 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
413 {
414 FCB->Recv.Content -= DatagramRecv->Len;
415 ExFreePool( DatagramRecv->Address );
416 ExFreePool( DatagramRecv );
417 }
418
419 AFD_DbgPrint(MID_TRACE,("Done\n"));
420
421 return Status;
422 }
423
424 NTSTATUS NTAPI
425 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
426 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
427 NTSTATUS Status = STATUS_INVALID_PARAMETER;
428 PFILE_OBJECT FileObject = IrpSp->FileObject;
429 PAFD_FCB FCB = FileObject->FsContext;
430 PAFD_RECV_INFO RecvReq;
431 UINT TotalBytesCopied = 0;
432 PAFD_STORED_DATAGRAM DatagramRecv;
433 PLIST_ENTRY ListEntry;
434 KPROCESSOR_MODE LockMode;
435
436 AFD_DbgPrint(MID_TRACE,("Called on %x\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 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
559
560 if( !SocketAcquireStateLock( FCB ) )
561 return STATUS_FILE_CLOSED;
562
563 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
564 FCB->ReceiveIrp.InFlightRequest = NULL;
565
566 if( FCB->State == SOCKET_STATE_CLOSED ) {
567 /* Cleanup our IRP queue because the FCB is being destroyed */
568 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
569 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
570 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
571 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
572 RecvReq = GetLockedData(NextIrp, NextIrpSp);
573 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
574 NextIrp->IoStatus.Information = 0;
575 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
576 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
577 (void)IoSetCancelRoutine(NextIrp, NULL);
578 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
579 }
580
581 /* Free all items on the datagram list */
582 while( !IsListEmpty( &FCB->DatagramList ) ) {
583 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
584 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
585 ExFreePool( DatagramRecv->Address );
586 ExFreePool( DatagramRecv );
587 }
588
589 SocketStateUnlock( FCB );
590 return STATUS_FILE_CLOSED;
591 }
592
593 if (Irp->IoStatus.Status != STATUS_SUCCESS)
594 {
595 SocketStateUnlock(FCB);
596 return Irp->IoStatus.Status;
597 }
598
599 if (FCB->TdiReceiveClosed)
600 {
601 SocketStateUnlock(FCB);
602 return STATUS_FILE_CLOSED;
603 }
604
605 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
606
607 if( DatagramRecv ) {
608 DatagramRecv->Len = Irp->IoStatus.Information;
609 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
610 DatagramRecv->Len );
611 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
612 FCB->AddressFrom->RemoteAddress));
613 DatagramRecv->Address =
614 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
615
616 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
617
618 } else Status = STATUS_NO_MEMORY;
619
620 if( !NT_SUCCESS( Status ) ) {
621 if( DatagramRecv ) ExFreePool( DatagramRecv );
622 SocketStateUnlock( FCB );
623 return Status;
624 } else {
625 FCB->Recv.Content += DatagramRecv->Len;
626 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
627 }
628
629 /* Satisfy as many requests as we can */
630
631 while( !IsListEmpty( &FCB->DatagramList ) &&
632 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
633 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
634 ListEntry = RemoveHeadList( &FCB->DatagramList );
635 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
636 ListEntry );
637 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
638 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
639 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
640 RecvReq = GetLockedData(NextIrp, NextIrpSp);
641
642 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
643 RecvReq, DatagramRecv));
644
645 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
646 Status = SatisfyPacketRecvRequest
647 ( FCB, NextIrp, DatagramRecv,
648 (PUINT)&NextIrp->IoStatus.Information );
649
650 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
651 {
652 InsertHeadList(&FCB->DatagramList,
653 &DatagramRecv->ListEntry);
654 }
655
656 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
657 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
658 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
659
660 AFD_DbgPrint(MID_TRACE,("Completing\n"));
661 (void)IoSetCancelRoutine(NextIrp, NULL);
662 NextIrp->IoStatus.Status = Status;
663
664 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
665 }
666
667 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
668 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
669 FCB->PollState |= AFD_EVENT_RECEIVE;
670 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
671 PollReeval( FCB->DeviceExt, FCB->FileObject );
672 } else
673 FCB->PollState &= ~AFD_EVENT_RECEIVE;
674
675 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
676 /* Now relaunch the datagram request */
677 Status = TdiReceiveDatagram
678 ( &FCB->ReceiveIrp.InFlightRequest,
679 FCB->AddressFile.Object,
680 0,
681 FCB->Recv.Window,
682 FCB->Recv.Size,
683 FCB->AddressFrom,
684 &FCB->ReceiveIrp.Iosb,
685 PacketSocketRecvComplete,
686 FCB );
687 }
688
689 SocketStateUnlock( FCB );
690
691 return STATUS_SUCCESS;
692 }
693
694 NTSTATUS NTAPI
695 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
696 PIO_STACK_LOCATION IrpSp ) {
697 NTSTATUS Status = STATUS_SUCCESS;
698 PFILE_OBJECT FileObject = IrpSp->FileObject;
699 PAFD_FCB FCB = FileObject->FsContext;
700 PAFD_RECV_INFO_UDP RecvReq;
701 PLIST_ENTRY ListEntry;
702 PAFD_STORED_DATAGRAM DatagramRecv;
703 KPROCESSOR_MODE LockMode;
704
705 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
706
707 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
708
709 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
710
711 /* Check that the socket is bound */
712 if( FCB->State != SOCKET_STATE_BOUND )
713 {
714 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
715 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
716 }
717
718 if (FCB->TdiReceiveClosed)
719 {
720 AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
721 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
722 }
723
724 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
725 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
726
727 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
728
729 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
730 RecvReq->BufferCount,
731 RecvReq->Address,
732 RecvReq->AddressLength,
733 TRUE, TRUE, LockMode );
734
735 if( !RecvReq->BufferArray ) { /* access violation in userspace */
736 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
737 }
738
739 if (!IsListEmpty(&FCB->DatagramList))
740 {
741 ListEntry = RemoveHeadList(&FCB->DatagramList);
742 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
743 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
744 (PUINT)&Irp->IoStatus.Information);
745
746 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
747 {
748 InsertHeadList(&FCB->DatagramList,
749 &DatagramRecv->ListEntry);
750 }
751
752 if (!IsListEmpty(&FCB->DatagramList))
753 {
754 FCB->PollState |= AFD_EVENT_RECEIVE;
755 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
756 PollReeval( FCB->DeviceExt, FCB->FileObject );
757 }
758 else
759 FCB->PollState &= ~AFD_EVENT_RECEIVE;
760
761 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
762
763 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
764 }
765 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
766 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
767 {
768 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
769 Status = STATUS_CANT_WAIT;
770 FCB->PollState &= ~AFD_EVENT_RECEIVE;
771 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
772 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
773 }
774 else
775 {
776 FCB->PollState &= ~AFD_EVENT_RECEIVE;
777 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
778 }
779 }