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