e7e9a6e67db5fc005cfe487841096182a8a14f4c
[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 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 (void)IoSetCancelRoutine(NextIrp, NULL);
158 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
159 }
160 }
161
162 if( !CantReadMore(FCB) ) {
163 FCB->PollState |= AFD_EVENT_RECEIVE;
164 } else
165 FCB->PollState &= ~AFD_EVENT_RECEIVE;
166
167 PollReeval( FCB->DeviceExt, FCB->FileObject );
168
169 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
170
171 /* Sometimes we're called with a NULL Irp */
172 if( Irp ) {
173 Irp->IoStatus.Status = RetStatus;
174 Irp->IoStatus.Information = RetBytesCopied;
175 }
176
177 return RetStatus;
178 }
179
180 NTSTATUS NTAPI ReceiveComplete
181 ( PDEVICE_OBJECT DeviceObject,
182 PIRP Irp,
183 PVOID Context ) {
184 PAFD_FCB FCB = (PAFD_FCB)Context;
185 PLIST_ENTRY NextIrpEntry;
186 PIRP NextIrp;
187 PAFD_RECV_INFO RecvReq;
188 PIO_STACK_LOCATION NextIrpSp;
189
190 AFD_DbgPrint(MID_TRACE,("Called\n"));
191
192 if( !SocketAcquireStateLock( FCB ) )
193 return STATUS_FILE_CLOSED;
194
195 FCB->ReceiveIrp.InFlightRequest = NULL;
196
197 FCB->Recv.Content = Irp->IoStatus.Information;
198 FCB->Recv.BytesUsed = 0;
199
200 if( FCB->State == SOCKET_STATE_CLOSED ) {
201 AFD_DbgPrint(MIN_TRACE,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
202 /* Cleanup our IRP queue because the FCB is being destroyed */
203 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
204 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
205 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
206 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
207 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
208 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
209 NextIrp->IoStatus.Information = 0;
210 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
211 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
212 (void)IoSetCancelRoutine(NextIrp, NULL);
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 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
296 } else {
297 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
298 }
299
300 SocketStateUnlock( FCB );
301 return Status;
302 }
303
304
305 static NTSTATUS NTAPI
306 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
307 PAFD_STORED_DATAGRAM DatagramRecv,
308 PUINT TotalBytesCopied ) {
309 NTSTATUS Status = STATUS_SUCCESS;
310 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
311 PAFD_RECV_INFO RecvReq =
312 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
313 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
314 PAFD_MAPBUF Map;
315
316 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
317 RecvReq->BufferCount +
318 EXTRA_LOCK_BUFFERS);
319
320 BytesToCopy =
321 MIN( RecvReq->BufferArray[0].len, BytesAvailable );
322
323 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
324 RecvReq->BufferArray[0].len));
325
326 if( Map[0].Mdl ) {
327 /* Copy the address */
328 if( Map[1].Mdl && Map[2].Mdl ) {
329 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
330
331 if( DatagramRecv->Address->TAAddressCount != 1 ) {
332 AFD_DbgPrint
333 (MID_TRACE,
334 ("Wierd address count %d\n",
335 DatagramRecv->Address->TAAddressCount));
336 }
337
338 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
339
340 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
341 sizeof(USHORT),
342 RecvReq->BufferArray[1].len);
343
344 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
345
346 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
347
348 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
349
350 RtlCopyMemory( Map[1].BufferAddress,
351 &DatagramRecv->Address->Address->AddressType,
352 AddrLen );
353
354 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
355
356 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
357
358 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
359 *((PINT)Map[2].BufferAddress) = AddrLen;
360 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
361 }
362
363 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
364
365 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
366
367 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
368 0,
369 Map[0].BufferAddress,
370 BytesToCopy));
371
372 /* OskitDumpBuffer
373 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
374
375 RtlCopyMemory( Map[0].BufferAddress,
376 FCB->Recv.Window + FCB->Recv.BytesUsed,
377 BytesToCopy );
378
379 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
380
381 *TotalBytesCopied = BytesToCopy;
382
383 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
384 FCB->Recv.BytesUsed = 0;
385 }
386 }
387
388 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
389 Irp->IoStatus.Information = BytesToCopy;
390 ExFreePool( DatagramRecv->Address );
391 ExFreePool( DatagramRecv );
392
393 AFD_DbgPrint(MID_TRACE,("Done\n"));
394
395 return Status;
396 }
397
398 NTSTATUS NTAPI
399 PacketSocketRecvComplete(
400 PDEVICE_OBJECT DeviceObject,
401 PIRP Irp,
402 PVOID Context ) {
403 NTSTATUS Status = STATUS_SUCCESS;
404 PAFD_FCB FCB = Context;
405 PIRP NextIrp;
406 PIO_STACK_LOCATION NextIrpSp;
407 PLIST_ENTRY ListEntry;
408 PAFD_RECV_INFO RecvReq;
409 PAFD_STORED_DATAGRAM DatagramRecv;
410 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
411 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
412
413 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
414
415 if( !SocketAcquireStateLock( FCB ) )
416 return STATUS_FILE_CLOSED;
417
418 FCB->ReceiveIrp.InFlightRequest = NULL;
419
420 if( FCB->State == SOCKET_STATE_CLOSED ) {
421 /* Cleanup our IRP queue because the FCB is being destroyed */
422 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
423 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
424 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
425 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
426 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
427 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
428 NextIrp->IoStatus.Information = 0;
429 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
430 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
431 (void)IoSetCancelRoutine(NextIrp, NULL);
432 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
433 }
434
435 /* Free all items on the datagram list */
436 while( !IsListEmpty( &FCB->DatagramList ) ) {
437 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
438 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
439 ExFreePool( DatagramRecv->Address );
440 ExFreePool( DatagramRecv );
441 }
442
443 SocketStateUnlock( FCB );
444 return STATUS_FILE_CLOSED;
445 }
446
447 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
448
449 if( DatagramRecv ) {
450 DatagramRecv->Len = Irp->IoStatus.Information;
451 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
452 DatagramRecv->Len );
453 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
454 FCB->AddressFrom->RemoteAddress));
455 DatagramRecv->Address =
456 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
457
458 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
459
460 } else Status = STATUS_NO_MEMORY;
461
462 if( !NT_SUCCESS( Status ) ) {
463 if( DatagramRecv ) ExFreePool( DatagramRecv );
464 SocketStateUnlock( FCB );
465 return Status;
466 } else {
467 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
468 }
469
470 /* Satisfy as many requests as we can */
471
472 while( !IsListEmpty( &FCB->DatagramList ) &&
473 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
474 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
475 ListEntry = RemoveHeadList( &FCB->DatagramList );
476 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
477 ListEntry );
478 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
479 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
480 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
481 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
482
483 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
484 RecvReq, DatagramRecv));
485
486 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
487 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
488 InsertHeadList( &FCB->DatagramList,
489 &DatagramRecv->ListEntry );
490 Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
491 NextIrp->IoStatus.Information = DatagramRecv->Len;
492 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
493 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
494 (void)IoSetCancelRoutine(NextIrp, NULL);
495 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
496 } else {
497 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
498 Status = SatisfyPacketRecvRequest
499 ( FCB, NextIrp, DatagramRecv,
500 (PUINT)&NextIrp->IoStatus.Information );
501 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
502 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
503 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
504 AFD_DbgPrint(MID_TRACE,("Completing\n"));
505 (void)IoSetCancelRoutine(NextIrp, NULL);
506 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
507 }
508 }
509
510 if( !IsListEmpty( &FCB->DatagramList ) ) {
511 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
512 FCB->PollState |= AFD_EVENT_RECEIVE;
513 } else
514 FCB->PollState &= ~AFD_EVENT_RECEIVE;
515
516 PollReeval( FCB->DeviceExt, FCB->FileObject );
517
518 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
519 /* Now relaunch the datagram request */
520 Status = TdiReceiveDatagram
521 ( &FCB->ReceiveIrp.InFlightRequest,
522 FCB->AddressFile.Object,
523 0,
524 FCB->Recv.Window,
525 FCB->Recv.Size,
526 FCB->AddressFrom,
527 &FCB->ReceiveIrp.Iosb,
528 PacketSocketRecvComplete,
529 FCB );
530 }
531
532 SocketStateUnlock( FCB );
533
534 return STATUS_SUCCESS;
535 }
536
537 NTSTATUS NTAPI
538 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
539 PIO_STACK_LOCATION IrpSp ) {
540 NTSTATUS Status = STATUS_SUCCESS;
541 PFILE_OBJECT FileObject = IrpSp->FileObject;
542 PAFD_FCB FCB = FileObject->FsContext;
543 PAFD_RECV_INFO_UDP RecvReq;
544 PLIST_ENTRY ListEntry;
545 PAFD_STORED_DATAGRAM DatagramRecv;
546
547 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
548
549 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
550
551 /* Check that the socket is bound */
552 if( FCB->State != SOCKET_STATE_BOUND )
553 return UnlockAndMaybeComplete
554 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
555 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
556 return UnlockAndMaybeComplete
557 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
558
559 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
560
561 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
562 RecvReq->BufferCount,
563 RecvReq->Address,
564 RecvReq->AddressLength,
565 TRUE, TRUE );
566
567 if( !RecvReq->BufferArray ) { /* access violation in userspace */
568 return UnlockAndMaybeComplete
569 ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 );
570 }
571
572 if( !IsListEmpty( &FCB->DatagramList ) ) {
573 ListEntry = RemoveHeadList( &FCB->DatagramList );
574 DatagramRecv = CONTAINING_RECORD
575 ( ListEntry, AFD_STORED_DATAGRAM, ListEntry );
576 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
577 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
578 InsertHeadList( &FCB->DatagramList,
579 &DatagramRecv->ListEntry );
580 Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
581 Irp->IoStatus.Information = DatagramRecv->Len;
582
583 if( IsListEmpty( &FCB->DatagramList ) )
584 FCB->PollState &= ~AFD_EVENT_RECEIVE;
585 else
586 FCB->PollState |= AFD_EVENT_RECEIVE;
587
588 PollReeval( FCB->DeviceExt, FCB->FileObject );
589
590 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
591
592 return UnlockAndMaybeComplete
593 ( FCB, Status, Irp, Irp->IoStatus.Information );
594 } else {
595 Status = SatisfyPacketRecvRequest
596 ( FCB, Irp, DatagramRecv,
597 (PUINT)&Irp->IoStatus.Information );
598
599 if( IsListEmpty( &FCB->DatagramList ) )
600 FCB->PollState &= ~AFD_EVENT_RECEIVE;
601 else
602 FCB->PollState |= AFD_EVENT_RECEIVE;
603
604 PollReeval( FCB->DeviceExt, FCB->FileObject );
605
606 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
607
608 return UnlockAndMaybeComplete
609 ( FCB, Status, Irp, Irp->IoStatus.Information );
610 }
611 } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
612 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
613 Status = STATUS_CANT_WAIT;
614 FCB->PollState &= ~AFD_EVENT_RECEIVE;
615 PollReeval( FCB->DeviceExt, FCB->FileObject );
616 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
617 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
618 } else {
619 FCB->PollState &= ~AFD_EVENT_RECEIVE;
620 PollReeval( FCB->DeviceExt, FCB->FileObject );
621 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
622 }
623 }