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 if (FCB->Overread && FCB->LastReceiveStatus == STATUS_SUCCESS) 179 { 180 /* Overread after a graceful disconnect so complete with an error */ 181 Status = STATUS_FILE_CLOSED; 182 } 183 else 184 { 185 /* Unexpected disconnect by the remote host or initial read after a graceful disconnect */ 186 Status = FCB->LastReceiveStatus; 187 } 188 NextIrp->IoStatus.Status = Status; 189 NextIrp->IoStatus.Information = 0; 190 if( NextIrp == Irp ) RetStatus = Status; 191 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 192 (void)IoSetCancelRoutine(NextIrp, NULL); 193 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 194 FCB->Overread = TRUE; 195 } 196 } else { 197 /* Kick the user that receive would be possible now */ 198 /* XXX Not implemented yet */ 199 200 AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n", 201 FCB, FCB->Recv.Content)); 202 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/ 203 204 /* Try to clear some requests */ 205 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 206 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 207 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 208 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 209 RecvReq = GetLockedData(NextIrp, NextIrpSp); 210 211 AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq)); 212 213 Status = TryToSatisfyRecvRequestFromBuffer 214 ( FCB, RecvReq, &TotalBytesCopied ); 215 216 if( Status == STATUS_PENDING ) { 217 AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp)); 218 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV], 219 &NextIrp->Tail.Overlay.ListEntry); 220 break; 221 } else { 222 AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp, 223 TotalBytesCopied)); 224 UnlockBuffers( RecvReq->BufferArray, 225 RecvReq->BufferCount, FALSE ); 226 NextIrp->IoStatus.Status = Status; 227 NextIrp->IoStatus.Information = TotalBytesCopied; 228 if( NextIrp == Irp ) { 229 RetStatus = Status; 230 } 231 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 232 (void)IoSetCancelRoutine(NextIrp, NULL); 233 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 234 } 235 } 236 } 237 238 if( FCB->Recv.Content - FCB->Recv.BytesUsed && 239 IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { 240 FCB->PollState |= AFD_EVENT_RECEIVE; 241 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 242 PollReeval( FCB->DeviceExt, FCB->FileObject ); 243 } 244 else 245 { 246 FCB->PollState &= ~AFD_EVENT_RECEIVE; 247 } 248 249 /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */ 250 if (CantReadMore(FCB)) 251 { 252 if (FCB->LastReceiveStatus == STATUS_SUCCESS) 253 { 254 FCB->PollState |= AFD_EVENT_DISCONNECT; 255 } 256 else 257 { 258 FCB->PollState |= AFD_EVENT_CLOSE; 259 } 260 FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus; 261 PollReeval(FCB->DeviceExt, FCB->FileObject); 262 } 263 264 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus)); 265 266 return RetStatus; 267 } 268 269 NTSTATUS NTAPI ReceiveComplete 270 ( PDEVICE_OBJECT DeviceObject, 271 PIRP Irp, 272 PVOID Context ) { 273 PAFD_FCB FCB = (PAFD_FCB)Context; 274 PLIST_ENTRY NextIrpEntry; 275 PIRP NextIrp; 276 PAFD_RECV_INFO RecvReq; 277 PIO_STACK_LOCATION NextIrpSp; 278 279 UNREFERENCED_PARAMETER(DeviceObject); 280 281 AFD_DbgPrint(MID_TRACE,("Called\n")); 282 283 if( !SocketAcquireStateLock( FCB ) ) 284 return STATUS_FILE_CLOSED; 285 286 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); 287 FCB->ReceiveIrp.InFlightRequest = NULL; 288 289 if( FCB->State == SOCKET_STATE_CLOSED ) { 290 /* Cleanup our IRP queue because the FCB is being destroyed */ 291 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 292 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 293 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 294 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp); 295 RecvReq = GetLockedData(NextIrp, NextIrpSp); 296 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 297 NextIrp->IoStatus.Information = 0; 298 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); 299 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 300 (void)IoSetCancelRoutine(NextIrp, NULL); 301 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 302 } 303 SocketStateUnlock( FCB ); 304 return STATUS_FILE_CLOSED; 305 } else if( FCB->State == SOCKET_STATE_LISTENING ) { 306 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n")); 307 SocketStateUnlock( FCB ); 308 return STATUS_INVALID_PARAMETER; 309 } 310 311 HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); 312 313 ReceiveActivity( FCB, NULL ); 314 315 SocketStateUnlock( FCB ); 316 317 return STATUS_SUCCESS; 318 } 319 320 static NTSTATUS NTAPI 321 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, 322 PAFD_STORED_DATAGRAM DatagramRecv, 323 PUINT TotalBytesCopied ) { 324 NTSTATUS Status = STATUS_SUCCESS; 325 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 326 PAFD_RECV_INFO RecvReq = 327 GetLockedData(Irp, IrpSp); 328 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0; 329 PAFD_MAPBUF Map; 330 BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp); 331 332 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + 333 RecvReq->BufferCount + 334 (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0)); 335 336 BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable ); 337 338 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy, 339 RecvReq->BufferArray[0].len)); 340 341 if( Map[0].Mdl ) { 342 /* Copy the address */ 343 if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) { 344 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n")); 345 346 if( DatagramRecv->Address->TAAddressCount != 1 ) { 347 AFD_DbgPrint 348 (MIN_TRACE, 349 ("Wierd address count %d\n", 350 DatagramRecv->Address->TAAddressCount)); 351 } 352 353 AFD_DbgPrint(MID_TRACE,("Computing addr len\n")); 354 355 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength + 356 sizeof(USHORT), 357 RecvReq->BufferArray[1].len); 358 359 AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen)); 360 361 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode ); 362 363 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n")); 364 365 RtlCopyMemory( Map[1].BufferAddress, 366 &DatagramRecv->Address->Address->AddressType, 367 AddrLen ); 368 369 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl ); 370 371 AFD_DbgPrint(MID_TRACE,("Copying address len\n")); 372 373 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode ); 374 *((PINT)Map[2].BufferAddress) = AddrLen; 375 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl ); 376 } 377 378 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n")); 379 380 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode ); 381 382 AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n", 383 0, 384 Map[0].BufferAddress, 385 BytesToCopy)); 386 387 RtlCopyMemory( Map[0].BufferAddress, 388 DatagramRecv->Buffer, 389 BytesToCopy ); 390 391 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl ); 392 393 *TotalBytesCopied = BytesToCopy; 394 } 395 396 if (*TotalBytesCopied == DatagramRecv->Len) 397 { 398 /* We copied the whole datagram */ 399 Status = Irp->IoStatus.Status = STATUS_SUCCESS; 400 } 401 else 402 { 403 /* We only copied part of the datagram */ 404 Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; 405 } 406 407 Irp->IoStatus.Information = *TotalBytesCopied; 408 409 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) 410 { 411 FCB->Recv.Content -= DatagramRecv->Len; 412 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS); 413 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM); 414 } 415 416 AFD_DbgPrint(MID_TRACE,("Done\n")); 417 418 return Status; 419 } 420 421 NTSTATUS NTAPI 422 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 423 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { 424 NTSTATUS Status = STATUS_INVALID_PARAMETER; 425 PFILE_OBJECT FileObject = IrpSp->FileObject; 426 PAFD_FCB FCB = FileObject->FsContext; 427 PAFD_RECV_INFO RecvReq; 428 UINT TotalBytesCopied = 0; 429 PAFD_STORED_DATAGRAM DatagramRecv; 430 PLIST_ENTRY ListEntry; 431 KPROCESSOR_MODE LockMode; 432 433 UNREFERENCED_PARAMETER(DeviceObject); 434 UNREFERENCED_PARAMETER(Short); 435 436 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); 437 438 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 439 440 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; 441 442 if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) && 443 FCB->State != SOCKET_STATE_CONNECTED && 444 FCB->State != SOCKET_STATE_CONNECTING ) { 445 AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n", 446 FCB->State)); 447 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, 448 Irp, 0 ); 449 } 450 451 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) 452 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, 453 Irp, 0 ); 454 455 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); 456 457 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, 458 RecvReq->BufferCount, 459 NULL, NULL, 460 TRUE, FALSE, LockMode ); 461 462 if( !RecvReq->BufferArray ) { 463 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, 464 Irp, 0 ); 465 } 466 467 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) 468 { 469 if (!IsListEmpty(&FCB->DatagramList)) 470 { 471 ListEntry = RemoveHeadList(&FCB->DatagramList); 472 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); 473 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, 474 (PUINT)&Irp->IoStatus.Information); 475 476 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 477 { 478 InsertHeadList(&FCB->DatagramList, 479 &DatagramRecv->ListEntry); 480 } 481 482 if (!IsListEmpty(&FCB->DatagramList)) 483 { 484 FCB->PollState |= AFD_EVENT_RECEIVE; 485 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 486 PollReeval( FCB->DeviceExt, FCB->FileObject ); 487 } 488 else 489 FCB->PollState &= ~AFD_EVENT_RECEIVE; 490 491 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); 492 493 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); 494 } 495 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) && 496 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) 497 { 498 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 499 Status = STATUS_CANT_WAIT; 500 FCB->PollState &= ~AFD_EVENT_RECEIVE; 501 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); 502 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 503 } 504 else 505 { 506 FCB->PollState &= ~AFD_EVENT_RECEIVE; 507 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); 508 } 509 } 510 511 Irp->IoStatus.Status = STATUS_PENDING; 512 Irp->IoStatus.Information = 0; 513 514 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV], 515 &Irp->Tail.Overlay.ListEntry ); 516 517 /************ From this point, the IRP is not ours ************/ 518 519 Status = ReceiveActivity( FCB, Irp ); 520 521 if( Status == STATUS_PENDING && 522 !(RecvReq->AfdFlags & AFD_OVERLAPPED) && 523 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { 524 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 525 Status = STATUS_CANT_WAIT; 526 TotalBytesCopied = 0; 527 RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); 528 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); 529 return UnlockAndMaybeComplete( FCB, Status, Irp, 530 TotalBytesCopied ); 531 } else if( Status == STATUS_PENDING ) { 532 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n")); 533 IoMarkIrpPending( Irp ); 534 (void)IoSetCancelRoutine(Irp, AfdCancelHandler); 535 } else { 536 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status)); 537 } 538 539 SocketStateUnlock( FCB ); 540 return Status; 541 } 542 543 NTSTATUS NTAPI 544 PacketSocketRecvComplete( 545 PDEVICE_OBJECT DeviceObject, 546 PIRP Irp, 547 PVOID Context ) { 548 NTSTATUS Status = STATUS_SUCCESS; 549 PAFD_FCB FCB = Context; 550 PIRP NextIrp; 551 PIO_STACK_LOCATION NextIrpSp; 552 PLIST_ENTRY ListEntry; 553 PAFD_RECV_INFO RecvReq; 554 PAFD_STORED_DATAGRAM DatagramRecv; 555 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM ); 556 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry; 557 558 UNREFERENCED_PARAMETER(DeviceObject); 559 560 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); 561 562 if( !SocketAcquireStateLock( FCB ) ) 563 return STATUS_FILE_CLOSED; 564 565 ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); 566 FCB->ReceiveIrp.InFlightRequest = NULL; 567 568 if( FCB->State == SOCKET_STATE_CLOSED ) { 569 /* Cleanup our IRP queue because the FCB is being destroyed */ 570 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 571 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); 572 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 573 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 574 RecvReq = GetLockedData(NextIrp, NextIrpSp); 575 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 576 NextIrp->IoStatus.Information = 0; 577 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp)); 578 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 579 (void)IoSetCancelRoutine(NextIrp, NULL); 580 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 581 } 582 583 /* Free all items on the datagram list */ 584 while( !IsListEmpty( &FCB->DatagramList ) ) { 585 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList); 586 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry); 587 ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS); 588 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM); 589 } 590 591 SocketStateUnlock( FCB ); 592 return STATUS_FILE_CLOSED; 593 } 594 595 if (Irp->IoStatus.Status != STATUS_SUCCESS) 596 { 597 SocketStateUnlock(FCB); 598 return Irp->IoStatus.Status; 599 } 600 601 if (FCB->TdiReceiveClosed) 602 { 603 SocketStateUnlock(FCB); 604 return STATUS_FILE_CLOSED; 605 } 606 607 DatagramRecv = ExAllocatePoolWithTag(NonPagedPool, 608 DGSize, 609 TAG_AFD_STORED_DATAGRAM); 610 611 if( DatagramRecv ) { 612 DatagramRecv->Len = Irp->IoStatus.Information; 613 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window, 614 DatagramRecv->Len ); 615 AFD_DbgPrint(MID_TRACE,("Received (A %p)\n", 616 FCB->AddressFrom->RemoteAddress)); 617 DatagramRecv->Address = 618 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress ); 619 620 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY; 621 622 } else Status = STATUS_NO_MEMORY; 623 624 if( !NT_SUCCESS( Status ) ) { 625 626 if (DatagramRecv) 627 { 628 ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM); 629 } 630 631 SocketStateUnlock( FCB ); 632 return Status; 633 } else { 634 FCB->Recv.Content += DatagramRecv->Len; 635 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry ); 636 } 637 638 /* Satisfy as many requests as we can */ 639 640 while( !IsListEmpty( &FCB->DatagramList ) && 641 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { 642 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n")); 643 ListEntry = RemoveHeadList( &FCB->DatagramList ); 644 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM, 645 ListEntry ); 646 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] ); 647 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry ); 648 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 649 RecvReq = GetLockedData(NextIrp, NextIrpSp); 650 651 AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n", 652 RecvReq, DatagramRecv)); 653 654 AFD_DbgPrint(MID_TRACE,("Satisfying\n")); 655 Status = SatisfyPacketRecvRequest 656 ( FCB, NextIrp, DatagramRecv, 657 (PUINT)&NextIrp->IoStatus.Information ); 658 659 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 660 { 661 InsertHeadList(&FCB->DatagramList, 662 &DatagramRecv->ListEntry); 663 } 664 665 AFD_DbgPrint(MID_TRACE,("Unlocking\n")); 666 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); 667 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 668 669 AFD_DbgPrint(MID_TRACE,("Completing\n")); 670 (void)IoSetCancelRoutine(NextIrp, NULL); 671 NextIrp->IoStatus.Status = Status; 672 673 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 674 } 675 676 if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { 677 AFD_DbgPrint(MID_TRACE,("Signalling\n")); 678 FCB->PollState |= AFD_EVENT_RECEIVE; 679 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 680 PollReeval( FCB->DeviceExt, FCB->FileObject ); 681 } else 682 FCB->PollState &= ~AFD_EVENT_RECEIVE; 683 684 if( NT_SUCCESS(Irp->IoStatus.Status) && FCB->Recv.Content < FCB->Recv.Size ) { 685 /* Now relaunch the datagram request */ 686 Status = TdiReceiveDatagram 687 ( &FCB->ReceiveIrp.InFlightRequest, 688 FCB->AddressFile.Object, 689 0, 690 FCB->Recv.Window, 691 FCB->Recv.Size, 692 FCB->AddressFrom, 693 PacketSocketRecvComplete, 694 FCB ); 695 } 696 697 SocketStateUnlock( FCB ); 698 699 return STATUS_SUCCESS; 700 } 701 702 NTSTATUS NTAPI 703 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 704 PIO_STACK_LOCATION IrpSp ) { 705 NTSTATUS Status = STATUS_SUCCESS; 706 PFILE_OBJECT FileObject = IrpSp->FileObject; 707 PAFD_FCB FCB = FileObject->FsContext; 708 PAFD_RECV_INFO_UDP RecvReq; 709 PLIST_ENTRY ListEntry; 710 PAFD_STORED_DATAGRAM DatagramRecv; 711 KPROCESSOR_MODE LockMode; 712 713 UNREFERENCED_PARAMETER(DeviceObject); 714 715 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); 716 717 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 718 719 FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; 720 721 /* Check that the socket is bound */ 722 if( FCB->State != SOCKET_STATE_BOUND ) 723 { 724 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); 725 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); 726 } 727 728 if (FCB->TdiReceiveClosed) 729 { 730 AFD_DbgPrint(MIN_TRACE,("Receive closed\n")); 731 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); 732 } 733 734 if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) 735 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 736 737 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); 738 739 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, 740 RecvReq->BufferCount, 741 RecvReq->Address, 742 RecvReq->AddressLength, 743 TRUE, TRUE, LockMode ); 744 745 if( !RecvReq->BufferArray ) { /* access violation in userspace */ 746 return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0); 747 } 748 749 if (!IsListEmpty(&FCB->DatagramList)) 750 { 751 ListEntry = RemoveHeadList(&FCB->DatagramList); 752 DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); 753 Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, 754 (PUINT)&Irp->IoStatus.Information); 755 756 if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) 757 { 758 InsertHeadList(&FCB->DatagramList, 759 &DatagramRecv->ListEntry); 760 } 761 762 if (!IsListEmpty(&FCB->DatagramList)) 763 { 764 FCB->PollState |= AFD_EVENT_RECEIVE; 765 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; 766 PollReeval( FCB->DeviceExt, FCB->FileObject ); 767 } 768 else 769 FCB->PollState &= ~AFD_EVENT_RECEIVE; 770 771 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE); 772 773 return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); 774 } 775 else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) && 776 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) 777 { 778 AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); 779 Status = STATUS_CANT_WAIT; 780 FCB->PollState &= ~AFD_EVENT_RECEIVE; 781 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); 782 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 783 } 784 else 785 { 786 FCB->PollState &= ~AFD_EVENT_RECEIVE; 787 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); 788 } 789 } 790