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