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