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