[AFD]: Revert r42674 and part of r47156
[reactos.git] / reactos / 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 * Improve buffering code
11 *
12 * We're keeping data receiving in one of two states:
13 * A) Some data available in the FCB
14 * FCB->Recv.BytesUsed != FCB->Recv.Content
15 * FCB->ReceiveIrp.InFlightRequest == NULL
16 * AFD_EVENT_RECEIVE set in FCB->PollState
17 * B) No data available in the FCB
18 * FCB->Recv.BytesUsed == FCB->Recv.Content (== 0)
19 * FCB->RecieveIrp.InFlightRequest != NULL
20 * AFD_EVENT_RECEIVED not set in FCB->PollState
21 * So basically we either have data available or a TDI receive
22 * in flight.
23 */
24 #include "afd.h"
25 #include "tdi_proto.h"
26 #include "tdiconn.h"
27 #include "debug.h"
28
29 static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
30 {
31 if( ( Status == STATUS_SUCCESS && !FCB->ReceiveIrp.Iosb.Information ) ||
32 ( !NT_SUCCESS( Status ) ) )
33 {
34 /* The socket has been closed */
35 FCB->PollState |= AFD_EVENT_DISCONNECT;
36 FCB->PollStatus[FD_CLOSE_BIT] = Status;
37
38 PollReeval( FCB->DeviceExt, FCB->FileObject );
39 }
40 }
41
42 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
43 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
44
45 return !BytesAvailable &&
46 (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
47 }
48
49 static VOID RefillSocketBuffer( PAFD_FCB FCB ) {
50 NTSTATUS Status;
51
52 if( !FCB->ReceiveIrp.InFlightRequest ) {
53 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
54
55 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
56 FCB->Connection.Object,
57 TDI_RECEIVE_NORMAL,
58 FCB->Recv.Window,
59 FCB->Recv.Size,
60 &FCB->ReceiveIrp.Iosb,
61 ReceiveComplete,
62 FCB );
63
64 if( Status == STATUS_SUCCESS && FCB->ReceiveIrp.Iosb.Information )
65 {
66 FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
67 FCB->PollState |= AFD_EVENT_RECEIVE;
68 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
69
70 PollReeval( FCB->DeviceExt, FCB->FileObject );
71 }
72 else
73 {
74 /* Check for EOF */
75 HandleEOFOnIrp(FCB, Status, FCB->ReceiveIrp.Iosb.Information);
76 }
77 }
78 }
79
80 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
81 PAFD_RECV_INFO RecvReq,
82 PUINT TotalBytesCopied ) {
83 UINT i, BytesToCopy = 0,
84 BytesAvailable =
85 FCB->Recv.Content - FCB->Recv.BytesUsed;
86 PAFD_MAPBUF Map;
87 NTSTATUS Status;
88 *TotalBytesCopied = 0;
89
90
91 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
92 BytesAvailable));
93
94 if( CantReadMore(FCB) ) return STATUS_SUCCESS;
95 if( !BytesAvailable ) return STATUS_PENDING;
96
97 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
98
99 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n",
100 RecvReq->BufferCount,
101 RecvReq->BufferArray));
102 for( i = 0;
103 RecvReq->BufferArray &&
104 BytesAvailable &&
105 i < RecvReq->BufferCount;
106 i++ ) {
107 BytesToCopy =
108 MIN( RecvReq->BufferArray[i].len, BytesAvailable );
109
110 if( Map[i].Mdl ) {
111 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
112
113 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
114 i,
115 Map[i].BufferAddress,
116 BytesToCopy));
117
118 RtlCopyMemory( Map[i].BufferAddress,
119 FCB->Recv.Window + FCB->Recv.BytesUsed,
120 BytesToCopy );
121
122 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
123
124 *TotalBytesCopied += BytesToCopy;
125
126 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
127 FCB->Recv.BytesUsed += BytesToCopy;
128 BytesAvailable -= BytesToCopy;
129 }
130 }
131 }
132
133 /* If there's nothing left in our buffer start a new request */
134 if( FCB->Recv.BytesUsed == FCB->Recv.Content ) {
135 FCB->Recv.BytesUsed = FCB->Recv.Content = 0;
136 FCB->PollState &= ~AFD_EVENT_RECEIVE;
137
138 RefillSocketBuffer( FCB );
139 }
140
141 return STATUS_SUCCESS;
142 }
143
144 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
145 PLIST_ENTRY NextIrpEntry;
146 PIRP NextIrp;
147 PIO_STACK_LOCATION NextIrpSp;
148 PAFD_RECV_INFO RecvReq;
149 UINT TotalBytesCopied = 0, RetBytesCopied = 0;
150 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
151
152 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
153
154 /* Kick the user that receive would be possible now */
155 /* XXX Not implemented yet */
156
157 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
158 FCB, FCB->Recv.Content));
159
160 if( CantReadMore( FCB ) ) {
161 /* Success here means that we got an EOF. Complete a pending read
162 * with zero bytes if we haven't yet overread, then kill the others.
163 */
164 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
165 NextIrpEntry =
166 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
167 NextIrp =
168 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
169 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
170 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
171
172 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
173 TotalBytesCopied));
174 UnlockBuffers( RecvReq->BufferArray,
175 RecvReq->BufferCount, FALSE );
176 Status = NextIrp->IoStatus.Status =
177 FCB->Overread ? STATUS_END_OF_FILE : STATUS_SUCCESS;
178 NextIrp->IoStatus.Information = 0;
179 if( NextIrp == Irp ) RetStatus = Status;
180 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
181 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
182 FCB->Overread = TRUE;
183 }
184 } else {
185 /* Kick the user that receive would be possible now */
186 /* XXX Not implemented yet */
187
188 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
189 FCB, FCB->Recv.Content));
190 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
191
192 /* Try to clear some requests */
193 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
194 NextIrpEntry =
195 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
196 NextIrp =
197 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
198 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
199 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
200
201 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
202
203 Status = TryToSatisfyRecvRequestFromBuffer
204 ( FCB, RecvReq, &TotalBytesCopied );
205
206 if( Status == STATUS_PENDING ) {
207 AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
208 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
209 &NextIrp->Tail.Overlay.ListEntry);
210 break;
211 } else {
212 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
213 TotalBytesCopied));
214 UnlockBuffers( RecvReq->BufferArray,
215 RecvReq->BufferCount, FALSE );
216 NextIrp->IoStatus.Status = Status;
217 NextIrp->IoStatus.Information = TotalBytesCopied;
218 if( NextIrp == Irp ) {
219 RetStatus = Status;
220 RetBytesCopied = TotalBytesCopied;
221 }
222 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
223 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
224 }
225 }
226 }
227
228 if( FCB->Recv.Content ) {
229 FCB->PollState |= AFD_EVENT_RECEIVE;
230 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
231 PollReeval( FCB->DeviceExt, FCB->FileObject );
232 } else
233 FCB->PollState &= ~AFD_EVENT_RECEIVE;
234
235 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
236
237 /* Sometimes we're called with a NULL Irp */
238 if( Irp ) {
239 Irp->IoStatus.Status = RetStatus;
240 Irp->IoStatus.Information = RetBytesCopied;
241 }
242
243 return RetStatus;
244 }
245
246 NTSTATUS NTAPI ReceiveComplete
247 ( PDEVICE_OBJECT DeviceObject,
248 PIRP Irp,
249 PVOID Context ) {
250 PAFD_FCB FCB = (PAFD_FCB)Context;
251 PLIST_ENTRY NextIrpEntry;
252 PIRP NextIrp;
253 PAFD_RECV_INFO RecvReq;
254 PIO_STACK_LOCATION NextIrpSp;
255
256 AFD_DbgPrint(MID_TRACE,("Called\n"));
257
258 if( !SocketAcquireStateLock( FCB ) )
259 return STATUS_FILE_CLOSED;
260
261 FCB->ReceiveIrp.InFlightRequest = NULL;
262
263 FCB->Recv.Content = Irp->IoStatus.Information;
264 FCB->Recv.BytesUsed = 0;
265
266 if( FCB->State == SOCKET_STATE_CLOSED ) {
267 AFD_DbgPrint(MIN_TRACE,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
268 /* Cleanup our IRP queue because the FCB is being destroyed */
269 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
270 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
271 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
272 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
273 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
274 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
275 NextIrp->IoStatus.Information = 0;
276 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
277 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
278 (void)IoSetCancelRoutine(NextIrp, NULL);
279 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
280 }
281 SocketStateUnlock( FCB );
282 return STATUS_FILE_CLOSED;
283 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
284 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
285 SocketStateUnlock( FCB );
286 return STATUS_INVALID_PARAMETER;
287 }
288
289 HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
290
291 ReceiveActivity( FCB, NULL );
292
293 SocketStateUnlock( FCB );
294
295 return STATUS_SUCCESS;
296 }
297
298 NTSTATUS NTAPI
299 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
300 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
301 NTSTATUS Status = STATUS_INVALID_PARAMETER;
302 PFILE_OBJECT FileObject = IrpSp->FileObject;
303 PAFD_FCB FCB = FileObject->FsContext;
304 PAFD_RECV_INFO RecvReq;
305 UINT TotalBytesCopied = 0;
306
307 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
308
309 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
310
311 if( FCB->State != SOCKET_STATE_CONNECTED &&
312 FCB->State != SOCKET_STATE_CONNECTING ) {
313 AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n",
314 FCB->State));
315 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
316 Irp, 0 );
317 }
318
319 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
320 {
321 AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n"));
322 return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED,
323 Irp, 0 );
324 }
325
326 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
327 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
328 Irp, 0 );
329
330 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
331
332 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
333 RecvReq->BufferCount,
334 NULL, NULL,
335 TRUE, FALSE );
336
337 if( !RecvReq->BufferArray ) {
338 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
339 Irp, 0 );
340 }
341
342 Irp->IoStatus.Status = STATUS_PENDING;
343 Irp->IoStatus.Information = 0;
344
345 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
346 &Irp->Tail.Overlay.ListEntry );
347
348 /************ From this point, the IRP is not ours ************/
349
350 Status = ReceiveActivity( FCB, Irp );
351
352 if( Status == STATUS_PENDING && (RecvReq->AfdFlags & AFD_IMMEDIATE) ) {
353 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
354 Status = STATUS_CANT_WAIT;
355 TotalBytesCopied = 0;
356 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
357 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
358 return UnlockAndMaybeComplete( FCB, Status, Irp,
359 TotalBytesCopied );
360 } else if( Status == STATUS_PENDING ) {
361 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
362 IoMarkIrpPending( Irp );
363 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
364 } else {
365 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
366 }
367
368 SocketStateUnlock( FCB );
369 return Status;
370 }
371
372
373 static NTSTATUS NTAPI
374 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
375 PAFD_STORED_DATAGRAM DatagramRecv,
376 PUINT TotalBytesCopied ) {
377 NTSTATUS Status = STATUS_SUCCESS;
378 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
379 PAFD_RECV_INFO RecvReq =
380 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
381 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
382 PAFD_MAPBUF Map;
383
384 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
385 RecvReq->BufferCount +
386 EXTRA_LOCK_BUFFERS);
387
388 BytesToCopy =
389 MIN( RecvReq->BufferArray[0].len, BytesAvailable );
390
391 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
392 RecvReq->BufferArray[0].len));
393
394 if( Map[0].Mdl ) {
395 /* Copy the address */
396 if( Map[1].Mdl && Map[2].Mdl ) {
397 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
398
399 if( DatagramRecv->Address->TAAddressCount != 1 ) {
400 AFD_DbgPrint
401 (MID_TRACE,
402 ("Wierd address count %d\n",
403 DatagramRecv->Address->TAAddressCount));
404 }
405
406 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
407
408 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
409 sizeof(USHORT),
410 RecvReq->BufferArray[1].len);
411
412 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
413
414 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
415
416 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
417
418 RtlCopyMemory( Map[1].BufferAddress,
419 &DatagramRecv->Address->Address->AddressType,
420 AddrLen );
421
422 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
423
424 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
425
426 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
427 *((PINT)Map[2].BufferAddress) = AddrLen;
428 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
429 }
430
431 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
432
433 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
434
435 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
436 0,
437 Map[0].BufferAddress,
438 BytesToCopy));
439
440 /* OskitDumpBuffer
441 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
442
443 RtlCopyMemory( Map[0].BufferAddress,
444 FCB->Recv.Window + FCB->Recv.BytesUsed,
445 BytesToCopy );
446
447 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
448
449 *TotalBytesCopied = BytesToCopy;
450
451 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
452 FCB->Recv.BytesUsed = 0;
453 }
454 }
455
456 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
457 Irp->IoStatus.Information = BytesToCopy;
458 ExFreePool( DatagramRecv->Address );
459 ExFreePool( DatagramRecv );
460
461 AFD_DbgPrint(MID_TRACE,("Done\n"));
462
463 return Status;
464 }
465
466 NTSTATUS NTAPI
467 PacketSocketRecvComplete(
468 PDEVICE_OBJECT DeviceObject,
469 PIRP Irp,
470 PVOID Context ) {
471 NTSTATUS Status = STATUS_SUCCESS;
472 PAFD_FCB FCB = Context;
473 PIRP NextIrp;
474 PIO_STACK_LOCATION NextIrpSp;
475 PLIST_ENTRY ListEntry;
476 PAFD_RECV_INFO RecvReq;
477 PAFD_STORED_DATAGRAM DatagramRecv;
478 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
479 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
480
481 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
482
483 if( !SocketAcquireStateLock( FCB ) )
484 return STATUS_FILE_CLOSED;
485
486 FCB->ReceiveIrp.InFlightRequest = NULL;
487
488 if( FCB->State == SOCKET_STATE_CLOSED ) {
489 /* Cleanup our IRP queue because the FCB is being destroyed */
490 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
491 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
492 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
493 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
494 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
495 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
496 NextIrp->IoStatus.Information = 0;
497 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
498 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
499 (void)IoSetCancelRoutine(NextIrp, NULL);
500 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
501 }
502
503 /* Free all items on the datagram list */
504 while( !IsListEmpty( &FCB->DatagramList ) ) {
505 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
506 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
507 ExFreePool( DatagramRecv->Address );
508 ExFreePool( DatagramRecv );
509 }
510
511 SocketStateUnlock( FCB );
512 return STATUS_FILE_CLOSED;
513 }
514
515 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
516
517 if( DatagramRecv ) {
518 DatagramRecv->Len = Irp->IoStatus.Information;
519 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
520 DatagramRecv->Len );
521 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
522 FCB->AddressFrom->RemoteAddress));
523 DatagramRecv->Address =
524 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
525
526 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
527
528 } else Status = STATUS_NO_MEMORY;
529
530 if( !NT_SUCCESS( Status ) ) {
531 if( DatagramRecv ) ExFreePool( DatagramRecv );
532 SocketStateUnlock( FCB );
533 return Status;
534 } else {
535 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
536 }
537
538 /* Satisfy as many requests as we can */
539
540 while( !IsListEmpty( &FCB->DatagramList ) &&
541 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
542 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
543 ListEntry = RemoveHeadList( &FCB->DatagramList );
544 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
545 ListEntry );
546 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
547 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
548 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
549 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
550
551 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
552 RecvReq, DatagramRecv));
553
554 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
555 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
556 InsertHeadList( &FCB->DatagramList,
557 &DatagramRecv->ListEntry );
558 Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
559 NextIrp->IoStatus.Information = DatagramRecv->Len;
560 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
561 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
562 (void)IoSetCancelRoutine(NextIrp, NULL);
563 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
564 } else {
565 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
566 Status = SatisfyPacketRecvRequest
567 ( FCB, NextIrp, DatagramRecv,
568 (PUINT)&NextIrp->IoStatus.Information );
569 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
570 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
571 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
572 AFD_DbgPrint(MID_TRACE,("Completing\n"));
573 (void)IoSetCancelRoutine(NextIrp, NULL);
574 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
575 }
576 }
577
578 if( !IsListEmpty( &FCB->DatagramList ) ) {
579 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
580 FCB->PollState |= AFD_EVENT_RECEIVE;
581 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
582 PollReeval( FCB->DeviceExt, FCB->FileObject );
583 } else
584 FCB->PollState &= ~AFD_EVENT_RECEIVE;
585
586 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
587 /* Now relaunch the datagram request */
588 Status = TdiReceiveDatagram
589 ( &FCB->ReceiveIrp.InFlightRequest,
590 FCB->AddressFile.Object,
591 0,
592 FCB->Recv.Window,
593 FCB->Recv.Size,
594 FCB->AddressFrom,
595 &FCB->ReceiveIrp.Iosb,
596 PacketSocketRecvComplete,
597 FCB );
598 }
599
600 SocketStateUnlock( FCB );
601
602 return STATUS_SUCCESS;
603 }
604
605 NTSTATUS NTAPI
606 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
607 PIO_STACK_LOCATION IrpSp ) {
608 NTSTATUS Status = STATUS_SUCCESS;
609 PFILE_OBJECT FileObject = IrpSp->FileObject;
610 PAFD_FCB FCB = FileObject->FsContext;
611 PAFD_RECV_INFO_UDP RecvReq;
612 PLIST_ENTRY ListEntry;
613 PAFD_STORED_DATAGRAM DatagramRecv;
614
615 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
616
617 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
618
619 /* Check that the socket is bound */
620 if( FCB->State != SOCKET_STATE_BOUND )
621 return UnlockAndMaybeComplete
622 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
623 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
624 return UnlockAndMaybeComplete
625 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
626
627 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
628
629 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
630 RecvReq->BufferCount,
631 RecvReq->Address,
632 RecvReq->AddressLength,
633 TRUE, TRUE );
634
635 if( !RecvReq->BufferArray ) { /* access violation in userspace */
636 return UnlockAndMaybeComplete
637 ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 );
638 }
639
640 if( !IsListEmpty( &FCB->DatagramList ) ) {
641 ListEntry = RemoveHeadList( &FCB->DatagramList );
642 DatagramRecv = CONTAINING_RECORD
643 ( ListEntry, AFD_STORED_DATAGRAM, ListEntry );
644 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
645 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
646 InsertHeadList( &FCB->DatagramList,
647 &DatagramRecv->ListEntry );
648 Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
649 Irp->IoStatus.Information = DatagramRecv->Len;
650
651 if( !IsListEmpty( &FCB->DatagramList ) ) {
652 FCB->PollState |= AFD_EVENT_RECEIVE;
653 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
654 PollReeval( FCB->DeviceExt, FCB->FileObject );
655 } else
656 FCB->PollState &= ~AFD_EVENT_RECEIVE;
657
658 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
659
660 return UnlockAndMaybeComplete
661 ( FCB, Status, Irp, Irp->IoStatus.Information );
662 } else {
663 Status = SatisfyPacketRecvRequest
664 ( FCB, Irp, DatagramRecv,
665 (PUINT)&Irp->IoStatus.Information );
666
667 if( !IsListEmpty( &FCB->DatagramList ) ) {
668 FCB->PollState |= AFD_EVENT_RECEIVE;
669 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
670 PollReeval( FCB->DeviceExt, FCB->FileObject );
671 } else
672 FCB->PollState &= ~AFD_EVENT_RECEIVE;
673
674 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
675
676 return UnlockAndMaybeComplete
677 ( FCB, Status, Irp, Irp->IoStatus.Information );
678 }
679 } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
680 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
681 Status = STATUS_CANT_WAIT;
682 FCB->PollState &= ~AFD_EVENT_RECEIVE;
683 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
684 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
685 } else {
686 FCB->PollState &= ~AFD_EVENT_RECEIVE;
687 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
688 }
689 }