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
RefillSocketBuffer(PAFD_FCB FCB)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
HandleReceiveComplete(PAFD_FCB FCB,NTSTATUS Status,ULONG_PTR Information)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
CantReadMore(PAFD_FCB FCB)88 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
89 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
90
91 return !BytesAvailable && FCB->TdiReceiveClosed;
92 }
93
TryToSatisfyRecvRequestFromBuffer(PAFD_FCB FCB,PAFD_RECV_INFO RecvReq,PUINT TotalBytesCopied)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
ReceiveActivity(PAFD_FCB FCB,PIRP Irp)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
179 /* Unexpected disconnect by the remote host or graceful disconnect */
180 Status = FCB->LastReceiveStatus;
181
182 NextIrp->IoStatus.Status = Status;
183 NextIrp->IoStatus.Information = 0;
184 if( NextIrp == Irp ) RetStatus = Status;
185 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
186 (void)IoSetCancelRoutine(NextIrp, NULL);
187 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
188 }
189 } else {
190 /* Kick the user that receive would be possible now */
191 /* XXX Not implemented yet */
192
193 AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
194 FCB, FCB->Recv.Content));
195 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
196
197 /* Try to clear some requests */
198 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
199 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
200 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
201 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
202 RecvReq = GetLockedData(NextIrp, NextIrpSp);
203
204 AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq));
205
206 Status = TryToSatisfyRecvRequestFromBuffer
207 ( FCB, RecvReq, &TotalBytesCopied );
208
209 if( Status == STATUS_PENDING ) {
210 AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp));
211 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
212 &NextIrp->Tail.Overlay.ListEntry);
213 break;
214 } else {
215 AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
216 TotalBytesCopied));
217 UnlockBuffers( RecvReq->BufferArray,
218 RecvReq->BufferCount, FALSE );
219 NextIrp->IoStatus.Status = Status;
220 NextIrp->IoStatus.Information = TotalBytesCopied;
221 if( NextIrp == Irp ) {
222 RetStatus = Status;
223 }
224 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
225 (void)IoSetCancelRoutine(NextIrp, NULL);
226 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
227 }
228 }
229 }
230
231 if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
232 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
233 FCB->PollState |= AFD_EVENT_RECEIVE;
234 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
235 PollReeval( FCB->DeviceExt, FCB->FileObject );
236 }
237 else
238 {
239 FCB->PollState &= ~AFD_EVENT_RECEIVE;
240 }
241
242 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
243 if (CantReadMore(FCB))
244 {
245 if (FCB->LastReceiveStatus == STATUS_SUCCESS)
246 {
247 FCB->PollState |= AFD_EVENT_DISCONNECT;
248 }
249 else
250 {
251 FCB->PollState |= AFD_EVENT_CLOSE;
252 }
253 FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
254 PollReeval(FCB->DeviceExt, FCB->FileObject);
255 }
256
257 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus));
258
259 return RetStatus;
260 }
261
ReceiveComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)262 NTSTATUS NTAPI ReceiveComplete
263 ( PDEVICE_OBJECT DeviceObject,
264 PIRP Irp,
265 PVOID Context ) {
266 PAFD_FCB FCB = (PAFD_FCB)Context;
267 PLIST_ENTRY NextIrpEntry;
268 PIRP NextIrp;
269 PAFD_RECV_INFO RecvReq;
270 PIO_STACK_LOCATION NextIrpSp;
271
272 UNREFERENCED_PARAMETER(DeviceObject);
273
274 AFD_DbgPrint(MID_TRACE,("Called\n"));
275
276 if( !SocketAcquireStateLock( FCB ) )
277 return STATUS_FILE_CLOSED;
278
279 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
280 FCB->ReceiveIrp.InFlightRequest = NULL;
281
282 if( FCB->State == SOCKET_STATE_CLOSED ) {
283 /* Cleanup our IRP queue because the FCB is being destroyed */
284 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
285 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
286 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
287 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
288 RecvReq = GetLockedData(NextIrp, NextIrpSp);
289 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
290 NextIrp->IoStatus.Information = 0;
291 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
292 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
293 (void)IoSetCancelRoutine(NextIrp, NULL);
294 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
295 }
296 SocketStateUnlock( FCB );
297 return STATUS_FILE_CLOSED;
298 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
299 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
300 SocketStateUnlock( FCB );
301 return STATUS_INVALID_PARAMETER;
302 }
303
304 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
305
306 ReceiveActivity( FCB, NULL );
307
308 SocketStateUnlock( FCB );
309
310 return STATUS_SUCCESS;
311 }
312
313 static NTSTATUS NTAPI
SatisfyPacketRecvRequest(PAFD_FCB FCB,PIRP Irp,PAFD_STORED_DATAGRAM DatagramRecv,PUINT TotalBytesCopied)314 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
315 PAFD_STORED_DATAGRAM DatagramRecv,
316 PUINT TotalBytesCopied ) {
317 NTSTATUS Status = STATUS_SUCCESS;
318 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
319 PAFD_RECV_INFO RecvReq =
320 GetLockedData(Irp, IrpSp);
321 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
322 PAFD_MAPBUF Map;
323 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
324
325 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
326 RecvReq->BufferCount +
327 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
328
329 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
330
331 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
332 RecvReq->BufferArray[0].len));
333
334 if( Map[0].Mdl ) {
335 /* Copy the address */
336 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
337 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
338
339 if( DatagramRecv->Address->TAAddressCount != 1 ) {
340 AFD_DbgPrint
341 (MIN_TRACE,
342 ("Wierd address count %d\n",
343 DatagramRecv->Address->TAAddressCount));
344 }
345
346 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
347
348 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
349 sizeof(USHORT),
350 RecvReq->BufferArray[1].len);
351
352 AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
353
354 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
355
356 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
357
358 RtlCopyMemory( Map[1].BufferAddress,
359 &DatagramRecv->Address->Address->AddressType,
360 AddrLen );
361
362 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
363
364 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
365
366 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
367 *((PINT)Map[2].BufferAddress) = AddrLen;
368 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
369 }
370
371 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
372
373 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
374
375 AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
376 0,
377 Map[0].BufferAddress,
378 BytesToCopy));
379
380 RtlCopyMemory( Map[0].BufferAddress,
381 DatagramRecv->Buffer,
382 BytesToCopy );
383
384 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
385
386 *TotalBytesCopied = BytesToCopy;
387 }
388
389 if (*TotalBytesCopied == DatagramRecv->Len)
390 {
391 /* We copied the whole datagram */
392 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
393 }
394 else
395 {
396 /* We only copied part of the datagram */
397 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
398 }
399
400 Irp->IoStatus.Information = *TotalBytesCopied;
401
402 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
403 {
404 FCB->Recv.Content -= DatagramRecv->Len;
405 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
406 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
407 }
408
409 AFD_DbgPrint(MID_TRACE,("Done\n"));
410
411 return Status;
412 }
413
414 NTSTATUS NTAPI
AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp,BOOLEAN Short)415 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
416 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
417 NTSTATUS Status = STATUS_INVALID_PARAMETER;
418 PFILE_OBJECT FileObject = IrpSp->FileObject;
419 PAFD_FCB FCB = FileObject->FsContext;
420 PAFD_RECV_INFO RecvReq;
421 UINT TotalBytesCopied = 0;
422 PAFD_STORED_DATAGRAM DatagramRecv;
423 PLIST_ENTRY ListEntry;
424 KPROCESSOR_MODE LockMode;
425
426 UNREFERENCED_PARAMETER(DeviceObject);
427 UNREFERENCED_PARAMETER(Short);
428
429 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
430
431 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
432
433 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
434
435 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
436 FCB->State != SOCKET_STATE_CONNECTED &&
437 FCB->State != SOCKET_STATE_CONNECTING ) {
438 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
439 FCB->State));
440 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
441 Irp, 0 );
442 }
443
444 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
445 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
446 Irp, 0 );
447
448 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
449
450 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
451 RecvReq->BufferCount,
452 NULL, NULL,
453 TRUE, FALSE, LockMode );
454
455 if( !RecvReq->BufferArray ) {
456 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
457 Irp, 0 );
458 }
459
460 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
461 {
462 if (!IsListEmpty(&FCB->DatagramList))
463 {
464 ListEntry = RemoveHeadList(&FCB->DatagramList);
465 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
466 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
467 (PUINT)&Irp->IoStatus.Information);
468
469 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
470 {
471 InsertHeadList(&FCB->DatagramList,
472 &DatagramRecv->ListEntry);
473 }
474
475 if (!IsListEmpty(&FCB->DatagramList))
476 {
477 FCB->PollState |= AFD_EVENT_RECEIVE;
478 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
479 PollReeval( FCB->DeviceExt, FCB->FileObject );
480 }
481 else
482 FCB->PollState &= ~AFD_EVENT_RECEIVE;
483
484 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
485
486 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
487 }
488 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
489 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
490 {
491 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
492 Status = STATUS_CANT_WAIT;
493 FCB->PollState &= ~AFD_EVENT_RECEIVE;
494 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
495 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
496 }
497 else
498 {
499 FCB->PollState &= ~AFD_EVENT_RECEIVE;
500 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
501 }
502 }
503
504 Irp->IoStatus.Status = STATUS_PENDING;
505 Irp->IoStatus.Information = 0;
506
507 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
508 &Irp->Tail.Overlay.ListEntry );
509
510 /************ From this point, the IRP is not ours ************/
511
512 Status = ReceiveActivity( FCB, Irp );
513
514 if( Status == STATUS_PENDING &&
515 !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
516 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
517 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
518 Status = STATUS_CANT_WAIT;
519 TotalBytesCopied = 0;
520 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
521 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
522 return UnlockAndMaybeComplete( FCB, Status, Irp,
523 TotalBytesCopied );
524 } else if( Status == STATUS_PENDING ) {
525 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
526 IoMarkIrpPending( Irp );
527 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
528 } else {
529 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
530 }
531
532 SocketStateUnlock( FCB );
533 return Status;
534 }
535
536 NTSTATUS NTAPI
PacketSocketRecvComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)537 PacketSocketRecvComplete(
538 PDEVICE_OBJECT DeviceObject,
539 PIRP Irp,
540 PVOID Context ) {
541 NTSTATUS Status = STATUS_SUCCESS;
542 PAFD_FCB FCB = Context;
543 PIRP NextIrp;
544 PIO_STACK_LOCATION NextIrpSp;
545 PLIST_ENTRY ListEntry;
546 PAFD_RECV_INFO RecvReq;
547 PAFD_STORED_DATAGRAM DatagramRecv;
548 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
549 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
550
551 UNREFERENCED_PARAMETER(DeviceObject);
552
553 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
554
555 if( !SocketAcquireStateLock( FCB ) )
556 return STATUS_FILE_CLOSED;
557
558 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
559 FCB->ReceiveIrp.InFlightRequest = NULL;
560
561 if( FCB->State == SOCKET_STATE_CLOSED ) {
562 /* Cleanup our IRP queue because the FCB is being destroyed */
563 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
564 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
565 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
566 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
567 RecvReq = GetLockedData(NextIrp, NextIrpSp);
568 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
569 NextIrp->IoStatus.Information = 0;
570 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
571 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
572 (void)IoSetCancelRoutine(NextIrp, NULL);
573 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
574 }
575
576 /* Free all items on the datagram list */
577 while( !IsListEmpty( &FCB->DatagramList ) ) {
578 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
579 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
580 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
581 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
582 }
583
584 SocketStateUnlock( FCB );
585 return STATUS_FILE_CLOSED;
586 }
587
588 if (Irp->IoStatus.Status != STATUS_SUCCESS)
589 {
590 SocketStateUnlock(FCB);
591 return Irp->IoStatus.Status;
592 }
593
594 if (FCB->TdiReceiveClosed)
595 {
596 SocketStateUnlock(FCB);
597 return STATUS_FILE_CLOSED;
598 }
599
600 DatagramRecv = ExAllocatePoolWithTag(NonPagedPool,
601 DGSize,
602 TAG_AFD_STORED_DATAGRAM);
603
604 if( DatagramRecv ) {
605 DatagramRecv->Len = Irp->IoStatus.Information;
606 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
607 DatagramRecv->Len );
608 AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
609 FCB->AddressFrom->RemoteAddress));
610 DatagramRecv->Address =
611 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
612
613 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
614
615 } else Status = STATUS_NO_MEMORY;
616
617 if( !NT_SUCCESS( Status ) ) {
618
619 if (DatagramRecv)
620 {
621 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
622 }
623
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) && FCB->Recv.Content < FCB->Recv.Size ) {
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
AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)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 }
783