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