1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/net/afd/afd/write.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 IO_COMPLETION_ROUTINE SendComplete; 14 static NTSTATUS NTAPI SendComplete 15 ( PDEVICE_OBJECT DeviceObject, 16 PIRP Irp, 17 PVOID Context ) { 18 NTSTATUS Status = Irp->IoStatus.Status; 19 PAFD_FCB FCB = (PAFD_FCB)Context; 20 PLIST_ENTRY NextIrpEntry; 21 PIRP NextIrp = NULL; 22 PIO_STACK_LOCATION NextIrpSp; 23 PAFD_SEND_INFO SendReq = NULL; 24 PAFD_MAPBUF Map; 25 SIZE_T TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i; 26 UINT SendLength, BytesCopied; 27 BOOLEAN HaltSendQueue; 28 29 UNREFERENCED_PARAMETER(DeviceObject); 30 31 /* 32 * The Irp parameter passed in is the IRP of the stream between AFD and 33 * TDI driver. It's not very useful to us. We need the IRPs of the stream 34 * between usermode and AFD. Those are chained from 35 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code 36 * below as "NextIrp" ('cause they are the next usermode IRP to be 37 * processed). 38 */ 39 40 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n", 41 Irp->IoStatus.Status, 42 Irp->IoStatus.Information)); 43 44 if( !SocketAcquireStateLock( FCB ) ) 45 return STATUS_FILE_CLOSED; 46 47 ASSERT(FCB->SendIrp.InFlightRequest == Irp); 48 FCB->SendIrp.InFlightRequest = NULL; 49 /* Request is not in flight any longer */ 50 51 if( FCB->State == SOCKET_STATE_CLOSED ) { 52 /* Cleanup our IRP queue because the FCB is being destroyed */ 53 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { 54 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 55 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 56 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 57 SendReq = GetLockedData(NextIrp, NextIrpSp); 58 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 59 NextIrp->IoStatus.Information = 0; 60 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 61 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 62 (void)IoSetCancelRoutine(NextIrp, NULL); 63 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 64 } 65 66 RetryDisconnectCompletion(FCB); 67 68 SocketStateUnlock( FCB ); 69 return STATUS_FILE_CLOSED; 70 } 71 72 if( !NT_SUCCESS(Status) ) { 73 /* Complete all following send IRPs with error */ 74 75 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { 76 NextIrpEntry = 77 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 78 NextIrp = 79 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 80 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 81 SendReq = GetLockedData(NextIrp, NextIrpSp); 82 83 UnlockBuffers( SendReq->BufferArray, 84 SendReq->BufferCount, 85 FALSE ); 86 87 NextIrp->IoStatus.Status = Status; 88 NextIrp->IoStatus.Information = 0; 89 90 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 91 (void)IoSetCancelRoutine(NextIrp, NULL); 92 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 93 } 94 95 RetryDisconnectCompletion(FCB); 96 97 SocketStateUnlock( FCB ); 98 99 return STATUS_SUCCESS; 100 } 101 102 RtlMoveMemory( FCB->Send.Window, 103 FCB->Send.Window + Irp->IoStatus.Information, 104 FCB->Send.BytesUsed - Irp->IoStatus.Information ); 105 106 TotalBytesProcessed = 0; 107 SendLength = Irp->IoStatus.Information; 108 HaltSendQueue = FALSE; 109 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && SendLength > 0) { 110 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 111 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 112 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 113 SendReq = GetLockedData(NextIrp, NextIrpSp); 114 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); 115 116 TotalBytesCopied = (ULONG_PTR)NextIrp->Tail.Overlay.DriverContext[3]; 117 ASSERT(TotalBytesCopied != 0); 118 119 /* If we didn't get enough, keep waiting */ 120 if (TotalBytesCopied > SendLength) 121 { 122 /* Update the bytes left to copy */ 123 TotalBytesCopied -= SendLength; 124 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)TotalBytesCopied; 125 126 /* Update the state variables */ 127 FCB->Send.BytesUsed -= SendLength; 128 TotalBytesProcessed += SendLength; 129 SendLength = 0; 130 131 /* Pend the IRP */ 132 InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND], 133 &NextIrp->Tail.Overlay.ListEntry); 134 HaltSendQueue = TRUE; 135 break; 136 } 137 138 ASSERT(NextIrp->IoStatus.Information != 0); 139 140 NextIrp->IoStatus.Status = Irp->IoStatus.Status; 141 142 FCB->Send.BytesUsed -= TotalBytesCopied; 143 TotalBytesProcessed += TotalBytesCopied; 144 SendLength -= TotalBytesCopied; 145 146 (void)IoSetCancelRoutine(NextIrp, NULL); 147 148 UnlockBuffers( SendReq->BufferArray, 149 SendReq->BufferCount, 150 FALSE ); 151 152 if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); 153 154 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); 155 } 156 157 ASSERT(SendLength == 0); 158 159 if ( !HaltSendQueue && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { 160 NextIrpEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink; 161 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 162 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); 163 SendReq = GetLockedData(NextIrp, NextIrpSp); 164 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); 165 166 AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq)); 167 168 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; 169 TotalBytesCopied = 0; 170 171 /* Count the total transfer size */ 172 SendLength = 0; 173 for (i = 0; i < SendReq->BufferCount; i++) 174 { 175 SendLength += SendReq->BufferArray[i].len; 176 } 177 178 /* Make sure we've got the space */ 179 if (SendLength > SpaceAvail) 180 { 181 /* Blocking sockets have to wait here */ 182 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) 183 { 184 FCB->PollState &= ~AFD_EVENT_SEND; 185 186 NextIrp = NULL; 187 } 188 189 /* Check if we can send anything */ 190 if (SpaceAvail == 0) 191 { 192 FCB->PollState &= ~AFD_EVENT_SEND; 193 194 /* We should never be non-overlapped and get to this point */ 195 ASSERT(SendReq->AfdFlags & AFD_OVERLAPPED); 196 197 NextIrp = NULL; 198 } 199 } 200 201 if (NextIrp != NULL) 202 { 203 for( i = 0; i < SendReq->BufferCount; i++ ) { 204 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); 205 206 Map[i].BufferAddress = 207 MmMapLockedPages( Map[i].Mdl, KernelMode ); 208 209 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, 210 Map[i].BufferAddress, 211 BytesCopied ); 212 213 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); 214 215 TotalBytesCopied += BytesCopied; 216 SpaceAvail -= BytesCopied; 217 FCB->Send.BytesUsed += BytesCopied; 218 } 219 220 NextIrp->IoStatus.Information = TotalBytesCopied; 221 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)NextIrp->IoStatus.Information; 222 } 223 } 224 225 if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed && 226 IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])) 227 { 228 FCB->PollState |= AFD_EVENT_SEND; 229 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; 230 PollReeval( FCB->DeviceExt, FCB->FileObject ); 231 } 232 else 233 { 234 FCB->PollState &= ~AFD_EVENT_SEND; 235 } 236 237 238 /* Some data is still waiting */ 239 if( FCB->Send.BytesUsed ) 240 { 241 Status = TdiSend( &FCB->SendIrp.InFlightRequest, 242 FCB->Connection.Object, 243 0, 244 FCB->Send.Window, 245 FCB->Send.BytesUsed, 246 SendComplete, 247 FCB ); 248 } 249 else 250 { 251 /* Nothing is waiting so try to complete a pending disconnect */ 252 RetryDisconnectCompletion(FCB); 253 } 254 255 SocketStateUnlock( FCB ); 256 257 return STATUS_SUCCESS; 258 } 259 260 static IO_COMPLETION_ROUTINE PacketSocketSendComplete; 261 static NTSTATUS NTAPI PacketSocketSendComplete 262 ( PDEVICE_OBJECT DeviceObject, 263 PIRP Irp, 264 PVOID Context ) { 265 PAFD_FCB FCB = (PAFD_FCB)Context; 266 PLIST_ENTRY NextIrpEntry; 267 PIRP NextIrp; 268 PAFD_SEND_INFO SendReq; 269 270 UNREFERENCED_PARAMETER(DeviceObject); 271 272 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n", 273 Irp->IoStatus.Status, 274 Irp->IoStatus.Information)); 275 276 if( !SocketAcquireStateLock( FCB ) ) 277 return STATUS_FILE_CLOSED; 278 279 ASSERT(FCB->SendIrp.InFlightRequest == Irp); 280 FCB->SendIrp.InFlightRequest = NULL; 281 /* Request is not in flight any longer */ 282 283 if( FCB->State == SOCKET_STATE_CLOSED ) { 284 /* Cleanup our IRP queue because the FCB is being destroyed */ 285 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { 286 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 287 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 288 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); 289 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; 290 NextIrp->IoStatus.Information = 0; 291 (void)IoSetCancelRoutine(NextIrp, NULL); 292 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 293 UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); 294 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); 295 } 296 SocketStateUnlock( FCB ); 297 return STATUS_FILE_CLOSED; 298 } 299 300 ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])); 301 302 /* TDI spec guarantees FIFO ordering on IRPs */ 303 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); 304 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); 305 306 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); 307 308 NextIrp->IoStatus.Status = Irp->IoStatus.Status; 309 NextIrp->IoStatus.Information = Irp->IoStatus.Information; 310 311 (void)IoSetCancelRoutine(NextIrp, NULL); 312 313 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 314 315 UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); 316 317 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); 318 319 FCB->PollState |= AFD_EVENT_SEND; 320 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; 321 PollReeval(FCB->DeviceExt, FCB->FileObject); 322 323 SocketStateUnlock(FCB); 324 325 return STATUS_SUCCESS; 326 } 327 328 NTSTATUS NTAPI 329 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 330 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { 331 NTSTATUS Status = STATUS_SUCCESS; 332 PFILE_OBJECT FileObject = IrpSp->FileObject; 333 PAFD_FCB FCB = FileObject->FsContext; 334 PAFD_SEND_INFO SendReq; 335 UINT TotalBytesCopied = 0, i, SpaceAvail = 0, BytesCopied, SendLength; 336 KPROCESSOR_MODE LockMode; 337 338 UNREFERENCED_PARAMETER(DeviceObject); 339 UNREFERENCED_PARAMETER(Short); 340 341 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); 342 343 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 344 345 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; 346 347 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) 348 { 349 PAFD_SEND_INFO_UDP SendReq; 350 PTDI_CONNECTION_INFORMATION TargetAddress; 351 352 /* Check that the socket is bound */ 353 if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress ) 354 { 355 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); 356 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 357 0 ); 358 } 359 360 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) 361 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); 362 363 /* Must lock buffers before handing off user data */ 364 SendReq->BufferArray = LockBuffers( SendReq->BufferArray, 365 SendReq->BufferCount, 366 NULL, NULL, 367 FALSE, FALSE, LockMode ); 368 369 if( !SendReq->BufferArray ) { 370 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, 371 Irp, 0 ); 372 } 373 374 Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); 375 376 if( NT_SUCCESS(Status) ) { 377 FCB->PollState &= ~AFD_EVENT_SEND; 378 379 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); 380 if (Status == STATUS_PENDING) 381 { 382 Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, 383 FCB->AddressFile.Object, 384 SendReq->BufferArray[0].buf, 385 SendReq->BufferArray[0].len, 386 TargetAddress, 387 PacketSocketSendComplete, 388 FCB); 389 if (Status != STATUS_PENDING) 390 { 391 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); 392 Irp->IoStatus.Status = Status; 393 Irp->IoStatus.Information = 0; 394 (void)IoSetCancelRoutine(Irp, NULL); 395 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 396 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); 397 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); 398 } 399 } 400 401 ExFreePoolWithTag(TargetAddress, TAG_AFD_TDI_CONNECTION_INFORMATION); 402 403 SocketStateUnlock(FCB); 404 405 return STATUS_PENDING; 406 } 407 else 408 { 409 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 410 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 411 } 412 } 413 414 if (FCB->PollState & AFD_EVENT_CLOSE) 415 { 416 AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); 417 418 /* This is an unexpected remote disconnect */ 419 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); 420 } 421 422 if (FCB->PollState & AFD_EVENT_ABORT) 423 { 424 AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); 425 426 /* This is an abortive socket closure on our side */ 427 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); 428 } 429 430 if (FCB->SendClosed) 431 { 432 AFD_DbgPrint(MIN_TRACE,("No more sends\n")); 433 434 /* This is a graceful send closure */ 435 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); 436 } 437 438 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) 439 return UnlockAndMaybeComplete 440 ( FCB, STATUS_NO_MEMORY, Irp, 0 ); 441 442 SendReq->BufferArray = LockBuffers( SendReq->BufferArray, 443 SendReq->BufferCount, 444 NULL, NULL, 445 FALSE, FALSE, LockMode ); 446 447 if( !SendReq->BufferArray ) { 448 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, 449 Irp, 0 ); 450 } 451 452 AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State)); 453 454 if( FCB->State != SOCKET_STATE_CONNECTED ) { 455 AFD_DbgPrint(MID_TRACE,("Socket not connected\n")); 456 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); 457 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_CONNECTION, Irp, 0 ); 458 } 459 460 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n", 461 FCB->Send.BytesUsed)); 462 463 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; 464 465 AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n", 466 SpaceAvail)); 467 468 /* Count the total transfer size */ 469 SendLength = 0; 470 for (i = 0; i < SendReq->BufferCount; i++) 471 { 472 SendLength += SendReq->BufferArray[i].len; 473 } 474 475 /* Make sure we've got the space */ 476 if (SendLength > SpaceAvail) 477 { 478 /* Blocking sockets have to wait here */ 479 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) 480 { 481 FCB->PollState &= ~AFD_EVENT_SEND; 482 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); 483 } 484 485 /* Check if we can send anything */ 486 if (SpaceAvail == 0) 487 { 488 FCB->PollState &= ~AFD_EVENT_SEND; 489 490 /* Non-overlapped sockets will fail if we can send nothing */ 491 if (!(SendReq->AfdFlags & AFD_OVERLAPPED)) 492 { 493 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); 494 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 ); 495 } 496 else 497 { 498 /* Overlapped sockets just pend */ 499 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); 500 } 501 } 502 } 503 504 for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ ) 505 { 506 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); 507 508 AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n", 509 i, 510 SendReq->BufferArray[i].buf, 511 BytesCopied, 512 FCB->Send.Window + FCB->Send.BytesUsed)); 513 514 RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed, 515 SendReq->BufferArray[i].buf, 516 BytesCopied); 517 518 TotalBytesCopied += BytesCopied; 519 SpaceAvail -= BytesCopied; 520 FCB->Send.BytesUsed += BytesCopied; 521 } 522 523 Irp->IoStatus.Information = TotalBytesCopied; 524 525 if( TotalBytesCopied == 0 ) { 526 AFD_DbgPrint(MID_TRACE,("Empty send\n")); 527 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); 528 return UnlockAndMaybeComplete 529 ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); 530 } 531 532 if (SpaceAvail) 533 { 534 FCB->PollState |= AFD_EVENT_SEND; 535 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; 536 PollReeval( FCB->DeviceExt, FCB->FileObject ); 537 } 538 else 539 { 540 FCB->PollState &= ~AFD_EVENT_SEND; 541 } 542 543 /* We use the IRP tail for some temporary storage here */ 544 Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information; 545 546 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); 547 if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) 548 { 549 TdiSend(&FCB->SendIrp.InFlightRequest, 550 FCB->Connection.Object, 551 0, 552 FCB->Send.Window, 553 FCB->Send.BytesUsed, 554 SendComplete, 555 FCB); 556 } 557 558 SocketStateUnlock(FCB); 559 560 return STATUS_PENDING; 561 } 562 563 NTSTATUS NTAPI 564 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, 565 PIO_STACK_LOCATION IrpSp) { 566 NTSTATUS Status = STATUS_SUCCESS; 567 PTDI_CONNECTION_INFORMATION TargetAddress; 568 PFILE_OBJECT FileObject = IrpSp->FileObject; 569 PAFD_FCB FCB = FileObject->FsContext; 570 PAFD_SEND_INFO_UDP SendReq; 571 KPROCESSOR_MODE LockMode; 572 573 UNREFERENCED_PARAMETER(DeviceObject); 574 575 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); 576 577 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); 578 579 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; 580 581 /* Check that the socket is bound */ 582 if( FCB->State != SOCKET_STATE_BOUND && 583 FCB->State != SOCKET_STATE_CREATED) 584 { 585 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); 586 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); 587 } 588 589 if (FCB->SendClosed) 590 { 591 AFD_DbgPrint(MIN_TRACE,("No more sends\n")); 592 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); 593 } 594 595 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) 596 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); 597 598 if (FCB->State == SOCKET_STATE_CREATED) 599 { 600 if (FCB->LocalAddress) 601 { 602 ExFreePoolWithTag(FCB->LocalAddress, TAG_AFD_TRANSPORT_ADDRESS); 603 } 604 605 FCB->LocalAddress = 606 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> 607 Address[0].AddressType ); 608 609 if( FCB->LocalAddress ) { 610 Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); 611 612 if( NT_SUCCESS(Status) ) 613 FCB->State = SOCKET_STATE_BOUND; 614 else 615 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 616 } else 617 return UnlockAndMaybeComplete 618 ( FCB, STATUS_NO_MEMORY, Irp, 0 ); 619 } 620 621 SendReq->BufferArray = LockBuffers( SendReq->BufferArray, 622 SendReq->BufferCount, 623 NULL, NULL, 624 FALSE, FALSE, LockMode ); 625 626 if( !SendReq->BufferArray ) 627 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, 628 Irp, 0 ); 629 630 AFD_DbgPrint 631 (MID_TRACE,("RemoteAddress #%d Type %u\n", 632 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> 633 TAAddressCount, 634 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> 635 Address[0].AddressType)); 636 637 Status = TdiBuildConnectionInfo( &TargetAddress, 638 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); 639 640 /* Check the size of the Address given ... */ 641 642 if( NT_SUCCESS(Status) ) { 643 FCB->PollState &= ~AFD_EVENT_SEND; 644 645 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); 646 if (Status == STATUS_PENDING) 647 { 648 Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, 649 FCB->AddressFile.Object, 650 SendReq->BufferArray[0].buf, 651 SendReq->BufferArray[0].len, 652 TargetAddress, 653 PacketSocketSendComplete, 654 FCB); 655 if (Status != STATUS_PENDING) 656 { 657 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); 658 Irp->IoStatus.Status = Status; 659 Irp->IoStatus.Information = 0; 660 (void)IoSetCancelRoutine(Irp, NULL); 661 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 662 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); 663 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); 664 } 665 } 666 667 ExFreePoolWithTag(TargetAddress, TAG_AFD_TDI_CONNECTION_INFORMATION); 668 669 SocketStateUnlock(FCB); 670 671 return STATUS_PENDING; 672 } 673 else 674 { 675 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); 676 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); 677 } 678 } 679