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