1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS TCP/IP protocol driver 4 * FILE: tcpip/dispatch.h 5 * PURPOSE: TDI dispatch routines 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * REVISIONS: 8 * CSH 01/08-2000 Created 9 * TODO: Validate device object in all dispatch routines 10 */ 11 12 #include "precomp.h" 13 14 #include <datagram.h> 15 #include <pseh/pseh2.h> 16 17 typedef struct _QUERY_HW_WORK_ITEM { 18 PIO_WORKITEM WorkItem; 19 PIRP Irp; 20 PIO_STACK_LOCATION IrpSp; 21 PIP_INTERFACE Interface; 22 LARGE_INTEGER StartTime; 23 ULONG RemoteIP; 24 } QUERY_HW_WORK_ITEM, *PQUERY_HW_WORK_ITEM; 25 26 NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) { 27 KIRQL OldIrql; 28 29 if (Status != STATUS_PENDING) { 30 Irp->IoStatus.Status = Status; 31 IoAcquireCancelSpinLock(&OldIrql); 32 (void)IoSetCancelRoutine( Irp, NULL ); 33 IoReleaseCancelSpinLock(OldIrql); 34 35 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); 36 } 37 38 return Status; 39 } 40 41 NTSTATUS DispPrepareIrpForCancel( 42 PTRANSPORT_CONTEXT Context, 43 PIRP Irp, 44 PDRIVER_CANCEL CancelRoutine) 45 /* 46 * FUNCTION: Prepare an IRP for cancellation 47 * ARGUMENTS: 48 * Context = Pointer to context information 49 * Irp = Pointer to an I/O request packet 50 * CancelRoutine = Routine to be called when I/O request is cancelled 51 * RETURNS: 52 * Status of operation 53 */ 54 { 55 KIRQL OldIrql; 56 PIO_STACK_LOCATION IrpSp; 57 PTRANSPORT_CONTEXT TransContext; 58 59 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 60 61 IrpSp = IoGetCurrentIrpStackLocation(Irp); 62 TransContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; 63 64 IoAcquireCancelSpinLock(&OldIrql); 65 66 if (!Irp->Cancel && !TransContext->CancelIrps) { 67 (void)IoSetCancelRoutine(Irp, CancelRoutine); 68 IoReleaseCancelSpinLock(OldIrql); 69 70 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp)); 71 72 return STATUS_SUCCESS; 73 } 74 75 /* IRP has already been cancelled */ 76 77 IoReleaseCancelSpinLock(OldIrql); 78 79 Irp->IoStatus.Status = STATUS_CANCELLED; 80 Irp->IoStatus.Information = 0; 81 82 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n")); 83 84 return Irp->IoStatus.Status; 85 } 86 87 VOID DispDataRequestComplete( 88 PVOID Context, 89 NTSTATUS Status, 90 ULONG Count) 91 /* 92 * FUNCTION: Completes a send/receive IRP 93 * ARGUMENTS: 94 * Context = Pointer to context information (IRP) 95 * Status = Status of the request 96 * Count = Number of bytes sent or received 97 */ 98 { 99 PIRP Irp = Context; 100 101 TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n", 102 Irp, Status, Count)); 103 104 Irp->IoStatus.Status = Status; 105 Irp->IoStatus.Information = Count; 106 107 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n", 108 Irp->IoStatus.Status)); 109 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n", 110 Irp->IoStatus.Information)); 111 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); 112 113 IRPFinish(Irp, Status); 114 115 TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n")); 116 } 117 118 VOID NTAPI DispCancelRequest( 119 PDEVICE_OBJECT Device, 120 PIRP Irp) 121 /* 122 * FUNCTION: Cancels an IRP 123 * ARGUMENTS: 124 * Device = Pointer to device object 125 * Irp = Pointer to an I/O request packet 126 */ 127 { 128 PIO_STACK_LOCATION IrpSp; 129 PTRANSPORT_CONTEXT TranContext; 130 PFILE_OBJECT FileObject; 131 UCHAR MinorFunction; 132 PCONNECTION_ENDPOINT Connection; 133 BOOLEAN DequeuedIrp = TRUE; 134 135 IoReleaseCancelSpinLock(Irp->CancelIrql); 136 137 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 138 139 IrpSp = IoGetCurrentIrpStackLocation(Irp); 140 FileObject = IrpSp->FileObject; 141 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; 142 MinorFunction = IrpSp->MinorFunction; 143 144 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp)); 145 146 Irp->IoStatus.Status = STATUS_CANCELLED; 147 Irp->IoStatus.Information = 0; 148 149 #if DBG 150 if (!Irp->Cancel) 151 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); 152 #endif 153 154 /* Try canceling the request */ 155 switch(MinorFunction) { 156 case TDI_SEND: 157 case TDI_RECEIVE: 158 DequeuedIrp = TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp ); 159 break; 160 161 case TDI_SEND_DATAGRAM: 162 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { 163 TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n")); 164 break; 165 } 166 167 DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp); 168 break; 169 170 case TDI_RECEIVE_DATAGRAM: 171 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { 172 TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n")); 173 break; 174 } 175 176 DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp); 177 break; 178 179 case TDI_CONNECT: 180 DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp); 181 break; 182 183 case TDI_DISCONNECT: 184 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 185 186 DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp); 187 if (DequeuedIrp) 188 { 189 if (KeCancelTimer(&Connection->DisconnectTimer)) 190 { 191 DereferenceObject(Connection); 192 } 193 } 194 break; 195 196 default: 197 TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction)); 198 ASSERT(FALSE); 199 break; 200 } 201 202 if (DequeuedIrp) 203 IRPFinish(Irp, STATUS_CANCELLED); 204 205 TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); 206 } 207 208 209 VOID NTAPI DispCancelListenRequest( 210 PDEVICE_OBJECT Device, 211 PIRP Irp) 212 /* 213 * FUNCTION: Cancels a listen IRP 214 * ARGUMENTS: 215 * Device = Pointer to device object 216 * Irp = Pointer to an I/O request packet 217 */ 218 { 219 PIO_STACK_LOCATION IrpSp; 220 PTRANSPORT_CONTEXT TranContext; 221 PFILE_OBJECT FileObject; 222 PCONNECTION_ENDPOINT Connection; 223 224 IoReleaseCancelSpinLock(Irp->CancelIrql); 225 226 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 227 228 IrpSp = IoGetCurrentIrpStackLocation(Irp); 229 FileObject = IrpSp->FileObject; 230 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; 231 ASSERT( TDI_LISTEN == IrpSp->MinorFunction); 232 233 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp)); 234 235 #if DBG 236 if (!Irp->Cancel) 237 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); 238 #endif 239 240 /* Try canceling the request */ 241 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 242 243 if (TCPAbortListenForSocket(Connection->AddressFile->Listener, 244 Connection)) 245 { 246 Irp->IoStatus.Information = 0; 247 IRPFinish(Irp, STATUS_CANCELLED); 248 } 249 250 TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); 251 } 252 253 254 NTSTATUS DispTdiAccept( 255 PIRP Irp) 256 /* 257 * FUNCTION: TDI_ACCEPT handler 258 * ARGUMENTS: 259 * Irp = Pointer to an I/O request packet 260 * RETURNS: 261 * Status of operation 262 */ 263 { 264 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 265 266 return STATUS_NOT_IMPLEMENTED; 267 } 268 269 270 NTSTATUS DispTdiAssociateAddress( 271 PIRP Irp) 272 /* 273 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler 274 * ARGUMENTS: 275 * Irp = Pointer to an I/O request packet 276 * RETURNS: 277 * Status of operation 278 */ 279 { 280 PTDI_REQUEST_KERNEL_ASSOCIATE Parameters; 281 PTRANSPORT_CONTEXT TranContext; 282 PIO_STACK_LOCATION IrpSp; 283 PCONNECTION_ENDPOINT Connection, LastConnection; 284 PFILE_OBJECT FileObject; 285 PADDRESS_FILE AddrFile = NULL; 286 NTSTATUS Status; 287 KIRQL OldIrql; 288 289 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 290 291 IrpSp = IoGetCurrentIrpStackLocation(Irp); 292 293 /* Get associated connection endpoint file object. Quit if none exists */ 294 295 TranContext = IrpSp->FileObject->FsContext; 296 if (!TranContext) { 297 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 298 return STATUS_INVALID_PARAMETER; 299 } 300 301 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 302 if (!Connection) { 303 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 304 return STATUS_INVALID_PARAMETER; 305 } 306 307 Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters; 308 309 Status = ObReferenceObjectByHandle( 310 Parameters->AddressHandle, 311 0, 312 *IoFileObjectType, 313 KernelMode, 314 (PVOID*)&FileObject, 315 NULL); 316 if (!NT_SUCCESS(Status)) { 317 TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n", 318 Parameters->AddressHandle, Status)); 319 return STATUS_INVALID_PARAMETER; 320 } 321 322 LockObject(Connection, &OldIrql); 323 324 if (Connection->AddressFile) { 325 ObDereferenceObject(FileObject); 326 UnlockObject(Connection, OldIrql); 327 TI_DbgPrint(MID_TRACE, ("An address file is already associated.\n")); 328 return STATUS_INVALID_PARAMETER; 329 } 330 331 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { 332 ObDereferenceObject(FileObject); 333 UnlockObject(Connection, OldIrql); 334 TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n", 335 FileObject->FsContext2)); 336 return STATUS_INVALID_PARAMETER; 337 } 338 339 /* Get associated address file object. Quit if none exists */ 340 341 TranContext = FileObject->FsContext; 342 if (!TranContext) { 343 ObDereferenceObject(FileObject); 344 UnlockObject(Connection, OldIrql); 345 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 346 return STATUS_INVALID_PARAMETER; 347 } 348 349 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; 350 if (!AddrFile) { 351 UnlockObject(Connection, OldIrql); 352 ObDereferenceObject(FileObject); 353 TI_DbgPrint(MID_TRACE, ("No address file object.\n")); 354 return STATUS_INVALID_PARAMETER; 355 } 356 357 LockObjectAtDpcLevel(AddrFile); 358 359 ReferenceObject(AddrFile); 360 Connection->AddressFile = AddrFile; 361 362 /* Add connection endpoint to the address file */ 363 ReferenceObject(Connection); 364 if (AddrFile->Connection == NULL) 365 AddrFile->Connection = Connection; 366 else 367 { 368 LastConnection = AddrFile->Connection; 369 while (LastConnection->Next != NULL) 370 LastConnection = LastConnection->Next; 371 LastConnection->Next = Connection; 372 } 373 374 ObDereferenceObject(FileObject); 375 376 UnlockObjectFromDpcLevel(AddrFile); 377 UnlockObject(Connection, OldIrql); 378 379 return STATUS_SUCCESS; 380 } 381 382 383 NTSTATUS DispTdiConnect( 384 PIRP Irp) 385 /* 386 * FUNCTION: TDI_CONNECT handler 387 * ARGUMENTS: 388 * Irp = Pointer to an I/O request packet 389 * RETURNS: 390 * Status of operation 391 */ 392 { 393 PCONNECTION_ENDPOINT Connection; 394 PTDI_REQUEST_KERNEL Parameters; 395 PTRANSPORT_CONTEXT TranContext; 396 PIO_STACK_LOCATION IrpSp; 397 NTSTATUS Status; 398 399 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 400 401 IrpSp = IoGetCurrentIrpStackLocation(Irp); 402 403 IoMarkIrpPending(Irp); 404 405 /* Get associated connection endpoint file object. Quit if none exists */ 406 407 TranContext = IrpSp->FileObject->FsContext; 408 if (!TranContext) { 409 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 410 Status = STATUS_INVALID_PARAMETER; 411 goto done; 412 } 413 414 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 415 if (!Connection) { 416 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 417 Status = STATUS_INVALID_PARAMETER; 418 goto done; 419 } 420 421 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters; 422 423 Status = DispPrepareIrpForCancel(TranContext->Handle.ConnectionContext, 424 Irp, 425 DispCancelRequest); 426 427 if (NT_SUCCESS(Status)) { 428 Status = TCPConnect( 429 TranContext->Handle.ConnectionContext, 430 Parameters->RequestConnectionInformation, 431 Parameters->ReturnConnectionInformation, 432 DispDataRequestComplete, 433 Irp ); 434 } 435 436 done: 437 if (Status != STATUS_PENDING) { 438 DispDataRequestComplete(Irp, Status, 0); 439 } 440 441 TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status)); 442 443 return STATUS_PENDING; 444 } 445 446 447 NTSTATUS DispTdiDisassociateAddress( 448 PIRP Irp) 449 /* 450 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler 451 * ARGUMENTS: 452 * Irp = Pointer to an I/O request packet 453 * RETURNS: 454 * Status of operation 455 */ 456 { 457 PCONNECTION_ENDPOINT Connection; 458 PTRANSPORT_CONTEXT TranContext; 459 PIO_STACK_LOCATION IrpSp; 460 461 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 462 463 IrpSp = IoGetCurrentIrpStackLocation(Irp); 464 465 /* Get associated connection endpoint file object. Quit if none exists */ 466 467 TranContext = IrpSp->FileObject->FsContext; 468 if (!TranContext) { 469 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 470 return STATUS_INVALID_PARAMETER; 471 } 472 473 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 474 if (!Connection) { 475 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 476 return STATUS_INVALID_PARAMETER; 477 } 478 479 /* NO-OP because we need the address to deallocate the port when the connection closes */ 480 481 return STATUS_SUCCESS; 482 } 483 484 485 NTSTATUS DispTdiDisconnect( 486 PIRP Irp) 487 /* 488 * FUNCTION: TDI_DISCONNECT handler 489 * ARGUMENTS: 490 * Irp = Pointer to an I/O request packet 491 * RETURNS: 492 * Status of operation 493 */ 494 { 495 NTSTATUS Status; 496 PTDI_REQUEST_KERNEL_DISCONNECT DisReq; 497 PCONNECTION_ENDPOINT Connection; 498 PTRANSPORT_CONTEXT TranContext; 499 PIO_STACK_LOCATION IrpSp; 500 501 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 502 503 IrpSp = IoGetCurrentIrpStackLocation(Irp); 504 DisReq = (PTDI_REQUEST_KERNEL_DISCONNECT)&IrpSp->Parameters; 505 506 IoMarkIrpPending(Irp); 507 508 /* Get associated connection endpoint file object. Quit if none exists */ 509 510 TranContext = IrpSp->FileObject->FsContext; 511 if (!TranContext) { 512 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 513 Status = STATUS_INVALID_PARAMETER; 514 goto done; 515 } 516 517 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 518 if (!Connection) { 519 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 520 Status = STATUS_INVALID_PARAMETER; 521 goto done; 522 } 523 524 Status = DispPrepareIrpForCancel 525 (TranContext->Handle.ConnectionContext, 526 Irp, 527 (PDRIVER_CANCEL)DispCancelRequest); 528 529 if (NT_SUCCESS(Status)) 530 { 531 Status = TCPDisconnect(TranContext->Handle.ConnectionContext, 532 DisReq->RequestFlags, 533 DisReq->RequestSpecific, 534 DisReq->RequestConnectionInformation, 535 DisReq->ReturnConnectionInformation, 536 DispDataRequestComplete, 537 Irp); 538 } 539 540 done: 541 if (Status != STATUS_PENDING) { 542 DispDataRequestComplete(Irp, Status, 0); 543 } 544 545 TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status)); 546 547 return STATUS_PENDING; 548 } 549 550 551 NTSTATUS DispTdiListen( 552 PIRP Irp) 553 /* 554 * FUNCTION: TDI_LISTEN handler 555 * ARGUMENTS: 556 * Irp = Pointer to an I/O request packet 557 * RETURNS: 558 * Status of operation 559 */ 560 { 561 PCONNECTION_ENDPOINT Connection; 562 PTDI_REQUEST_KERNEL Parameters; 563 PTRANSPORT_CONTEXT TranContext; 564 PIO_STACK_LOCATION IrpSp; 565 NTSTATUS Status = STATUS_SUCCESS; 566 KIRQL OldIrql; 567 568 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 569 570 IrpSp = IoGetCurrentIrpStackLocation(Irp); 571 572 IoMarkIrpPending(Irp); 573 574 /* Get associated connection endpoint file object. Quit if none exists */ 575 576 TranContext = IrpSp->FileObject->FsContext; 577 if (TranContext == NULL) 578 { 579 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 580 Status = STATUS_INVALID_PARAMETER; 581 goto done; 582 } 583 584 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 585 if (Connection == NULL) 586 { 587 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 588 Status = STATUS_INVALID_PARAMETER; 589 goto done; 590 } 591 592 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters; 593 594 Status = DispPrepareIrpForCancel 595 (TranContext->Handle.ConnectionContext, 596 Irp, 597 (PDRIVER_CANCEL)DispCancelListenRequest); 598 599 LockObject(Connection, &OldIrql); 600 601 if (Connection->AddressFile == NULL) 602 { 603 TI_DbgPrint(MID_TRACE, ("No associated address file\n")); 604 UnlockObject(Connection, OldIrql); 605 Status = STATUS_INVALID_PARAMETER; 606 goto done; 607 } 608 609 LockObjectAtDpcLevel(Connection->AddressFile); 610 611 /* Listening will require us to create a listening socket and store it in 612 * the address file. It will be signalled, and attempt to complete an irp 613 * when a new connection arrives. */ 614 /* The important thing to note here is that the irp we'll complete belongs 615 * to the socket to be accepted onto, not the listener */ 616 if( NT_SUCCESS(Status) && !Connection->AddressFile->Listener ) { 617 Connection->AddressFile->Listener = 618 TCPAllocateConnectionEndpoint( NULL ); 619 620 if( !Connection->AddressFile->Listener ) 621 Status = STATUS_NO_MEMORY; 622 623 if( NT_SUCCESS(Status) ) { 624 ReferenceObject(Connection->AddressFile); 625 Connection->AddressFile->Listener->AddressFile = 626 Connection->AddressFile; 627 628 Status = TCPSocket( Connection->AddressFile->Listener, 629 Connection->AddressFile->Family, 630 SOCK_STREAM, 631 Connection->AddressFile->Protocol ); 632 } 633 634 if( NT_SUCCESS(Status) ) { 635 ReferenceObject(Connection->AddressFile->Listener); 636 Status = TCPListen( Connection->AddressFile->Listener, 1024 ); 637 /* BACKLOG */ 638 } 639 } 640 641 if( NT_SUCCESS(Status) ) { 642 Status = TCPAccept 643 ( (PTDI_REQUEST)Parameters, 644 Connection->AddressFile->Listener, 645 Connection, 646 DispDataRequestComplete, 647 Irp ); 648 } 649 650 UnlockObjectFromDpcLevel(Connection->AddressFile); 651 UnlockObject(Connection, OldIrql); 652 653 done: 654 if (Status != STATUS_PENDING) { 655 DispDataRequestComplete(Irp, Status, 0); 656 } 657 658 TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status)); 659 660 return STATUS_PENDING; 661 } 662 663 664 NTSTATUS DispTdiQueryInformation( 665 PDEVICE_OBJECT DeviceObject, 666 PIRP Irp) 667 /* 668 * FUNCTION: TDI_QUERY_INFORMATION handler 669 * ARGUMENTS: 670 * DeviceObject = Pointer to device object structure 671 * Irp = Pointer to an I/O request packet 672 * RETURNS: 673 * Status of operation 674 */ 675 { 676 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters; 677 PTRANSPORT_CONTEXT TranContext; 678 PIO_STACK_LOCATION IrpSp; 679 680 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 681 682 IrpSp = IoGetCurrentIrpStackLocation(Irp); 683 Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters; 684 685 TranContext = IrpSp->FileObject->FsContext; 686 if (!TranContext) { 687 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 688 return STATUS_INVALID_PARAMETER; 689 } 690 691 switch (Parameters->QueryType) 692 { 693 case TDI_QUERY_ADDRESS_INFO: 694 { 695 PTDI_ADDRESS_INFO AddressInfo; 696 PADDRESS_FILE AddrFile; 697 PTA_IP_ADDRESS Address; 698 PCONNECTION_ENDPOINT Endpoint = NULL; 699 700 701 if (MmGetMdlByteCount(Irp->MdlAddress) < 702 (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) + 703 sizeof(TDI_ADDRESS_IP))) { 704 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); 705 return STATUS_BUFFER_TOO_SMALL; 706 } 707 708 AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress); 709 Address = (PTA_IP_ADDRESS)&AddressInfo->Address; 710 711 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 712 case TDI_TRANSPORT_ADDRESS_FILE: 713 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; 714 715 Address->TAAddressCount = 1; 716 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 717 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 718 Address->Address[0].Address[0].sin_port = AddrFile->Port; 719 Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address; 720 RtlZeroMemory( 721 &Address->Address[0].Address[0].sin_zero, 722 sizeof(Address->Address[0].Address[0].sin_zero)); 723 return STATUS_SUCCESS; 724 725 case TDI_CONNECTION_FILE: 726 Endpoint = 727 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 728 729 Address->TAAddressCount = 1; 730 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 731 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 732 Address->Address[0].Address[0].sin_port = Endpoint->AddressFile->Port; 733 Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address; 734 RtlZeroMemory( 735 &Address->Address[0].Address[0].sin_zero, 736 sizeof(Address->Address[0].Address[0].sin_zero)); 737 return STATUS_SUCCESS; 738 739 default: 740 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 741 return STATUS_INVALID_PARAMETER; 742 } 743 } 744 745 case TDI_QUERY_CONNECTION_INFO: 746 { 747 PTDI_CONNECTION_INFO ConnectionInfo; 748 //PCONNECTION_ENDPOINT Endpoint; 749 750 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*ConnectionInfo)) { 751 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); 752 return STATUS_BUFFER_TOO_SMALL; 753 } 754 755 ConnectionInfo = (PTDI_CONNECTION_INFO) 756 MmGetSystemAddressForMdl(Irp->MdlAddress); 757 758 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 759 case TDI_CONNECTION_FILE: 760 //Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 761 RtlZeroMemory(ConnectionInfo, sizeof(*ConnectionInfo)); 762 return STATUS_SUCCESS; 763 764 default: 765 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 766 return STATUS_INVALID_PARAMETER; 767 } 768 } 769 770 case TDI_QUERY_MAX_DATAGRAM_INFO: 771 { 772 PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo; 773 774 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) { 775 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); 776 return STATUS_BUFFER_TOO_SMALL; 777 } 778 779 MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO) 780 MmGetSystemAddressForMdl(Irp->MdlAddress); 781 782 MaxDatagramInfo->MaxDatagramSize = 0xFFFF; 783 784 return STATUS_SUCCESS; 785 } 786 } 787 788 return STATUS_NOT_IMPLEMENTED; 789 } 790 791 792 NTSTATUS DispTdiReceive( 793 PIRP Irp) 794 /* 795 * FUNCTION: TDI_RECEIVE handler 796 * ARGUMENTS: 797 * Irp = Pointer to an I/O request packet 798 * RETURNS: 799 * Status of operation 800 */ 801 { 802 PIO_STACK_LOCATION IrpSp; 803 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo; 804 PTRANSPORT_CONTEXT TranContext; 805 NTSTATUS Status; 806 ULONG BytesReceived = 0; 807 808 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 809 810 IrpSp = IoGetCurrentIrpStackLocation(Irp); 811 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters); 812 813 IoMarkIrpPending(Irp); 814 815 TranContext = IrpSp->FileObject->FsContext; 816 if (TranContext == NULL) 817 { 818 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 819 Status = STATUS_INVALID_PARAMETER; 820 goto done; 821 } 822 823 if (TranContext->Handle.ConnectionContext == NULL) 824 { 825 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 826 Status = STATUS_INVALID_PARAMETER; 827 goto done; 828 } 829 830 /* Initialize a receive request */ 831 Status = DispPrepareIrpForCancel 832 (TranContext->Handle.ConnectionContext, 833 Irp, 834 (PDRIVER_CANCEL)DispCancelRequest); 835 836 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress)); 837 if (NT_SUCCESS(Status)) 838 { 839 Status = TCPReceiveData( 840 TranContext->Handle.ConnectionContext, 841 (PNDIS_BUFFER)Irp->MdlAddress, 842 ReceiveInfo->ReceiveLength, 843 &BytesReceived, 844 ReceiveInfo->ReceiveFlags, 845 DispDataRequestComplete, 846 Irp); 847 } 848 849 done: 850 if (Status != STATUS_PENDING) { 851 DispDataRequestComplete(Irp, Status, BytesReceived); 852 } 853 854 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 855 856 return STATUS_PENDING; 857 } 858 859 860 NTSTATUS DispTdiReceiveDatagram( 861 PIRP Irp) 862 /* 863 * FUNCTION: TDI_RECEIVE_DATAGRAM handler 864 * ARGUMENTS: 865 * Irp = Pointer to an I/O request packet 866 * RETURNS: 867 * Status of operation 868 */ 869 { 870 PIO_STACK_LOCATION IrpSp; 871 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo; 872 PTRANSPORT_CONTEXT TranContext; 873 TDI_REQUEST Request; 874 NTSTATUS Status; 875 ULONG BytesReceived = 0; 876 877 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 878 879 IrpSp = IoGetCurrentIrpStackLocation(Irp); 880 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters); 881 882 IoMarkIrpPending(Irp); 883 884 TranContext = IrpSp->FileObject->FsContext; 885 if (TranContext == NULL) 886 { 887 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 888 Status = STATUS_INVALID_PARAMETER; 889 goto done; 890 } 891 892 /* Initialize a receive request */ 893 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 894 Request.RequestNotifyObject = DispDataRequestComplete; 895 Request.RequestContext = Irp; 896 897 Status = DispPrepareIrpForCancel( 898 IrpSp->FileObject->FsContext, 899 Irp, 900 (PDRIVER_CANCEL)DispCancelRequest); 901 902 if (NT_SUCCESS(Status)) 903 { 904 PVOID DataBuffer; 905 UINT BufferSize; 906 907 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, 908 &DataBuffer, 909 &BufferSize ); 910 911 Status = DGReceiveDatagram( 912 Request.Handle.AddressHandle, 913 DgramInfo->ReceiveDatagramInformation, 914 DataBuffer, 915 DgramInfo->ReceiveLength, 916 DgramInfo->ReceiveFlags, 917 DgramInfo->ReturnDatagramInformation, 918 &BytesReceived, 919 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete, 920 Irp, 921 Irp); 922 } 923 924 done: 925 if (Status != STATUS_PENDING) { 926 DispDataRequestComplete(Irp, Status, BytesReceived); 927 } 928 929 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 930 931 return STATUS_PENDING; 932 } 933 934 935 NTSTATUS DispTdiSend( 936 PIRP Irp) 937 /* 938 * FUNCTION: TDI_SEND handler 939 * ARGUMENTS: 940 * Irp = Pointer to an I/O request packet 941 * RETURNS: 942 * Status of operation 943 */ 944 { 945 PIO_STACK_LOCATION IrpSp; 946 PTDI_REQUEST_KERNEL_SEND SendInfo; 947 PTRANSPORT_CONTEXT TranContext; 948 NTSTATUS Status; 949 ULONG BytesSent = 0; 950 951 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 952 953 IrpSp = IoGetCurrentIrpStackLocation(Irp); 954 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters); 955 956 IoMarkIrpPending(Irp); 957 958 TranContext = IrpSp->FileObject->FsContext; 959 if (TranContext == NULL) 960 { 961 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 962 Status = STATUS_INVALID_PARAMETER; 963 goto done; 964 } 965 966 if (TranContext->Handle.ConnectionContext == NULL) 967 { 968 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 969 Status = STATUS_INVALID_PARAMETER; 970 goto done; 971 } 972 973 Status = DispPrepareIrpForCancel( 974 IrpSp->FileObject->FsContext, 975 Irp, 976 (PDRIVER_CANCEL)DispCancelRequest); 977 978 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress)); 979 if (NT_SUCCESS(Status)) 980 { 981 PVOID Data; 982 UINT Len; 983 984 NdisQueryBuffer( Irp->MdlAddress, &Data, &Len ); 985 986 TI_DbgPrint(MID_TRACE,("About to TCPSendData\n")); 987 Status = TCPSendData( 988 TranContext->Handle.ConnectionContext, 989 Data, 990 SendInfo->SendLength, 991 &BytesSent, 992 SendInfo->SendFlags, 993 DispDataRequestComplete, 994 Irp); 995 } 996 997 done: 998 if (Status != STATUS_PENDING) { 999 DispDataRequestComplete(Irp, Status, BytesSent); 1000 } 1001 1002 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 1003 1004 return STATUS_PENDING; 1005 } 1006 1007 1008 NTSTATUS DispTdiSendDatagram( 1009 PIRP Irp) 1010 /* 1011 * FUNCTION: TDI_SEND_DATAGRAM handler 1012 * ARGUMENTS: 1013 * Irp = Pointer to an I/O request packet 1014 * RETURNS: 1015 * Status of operation 1016 */ 1017 { 1018 PIO_STACK_LOCATION IrpSp; 1019 TDI_REQUEST Request; 1020 PTDI_REQUEST_KERNEL_SENDDG DgramInfo; 1021 PTRANSPORT_CONTEXT TranContext; 1022 NTSTATUS Status; 1023 1024 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1025 1026 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1027 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters); 1028 1029 IoMarkIrpPending(Irp); 1030 1031 TranContext = IrpSp->FileObject->FsContext; 1032 if (TranContext == NULL) 1033 { 1034 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 1035 Status = STATUS_INVALID_PARAMETER; 1036 goto done; 1037 } 1038 1039 /* Initialize a send request */ 1040 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1041 Request.RequestNotifyObject = DispDataRequestComplete; 1042 Request.RequestContext = Irp; 1043 1044 Status = DispPrepareIrpForCancel( 1045 IrpSp->FileObject->FsContext, 1046 Irp, 1047 (PDRIVER_CANCEL)DispCancelRequest); 1048 1049 if (NT_SUCCESS(Status)) { 1050 PVOID DataBuffer; 1051 UINT BufferSize; 1052 1053 TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress)); 1054 1055 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, 1056 &DataBuffer, 1057 &BufferSize ); 1058 1059 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress 1060 must be of type PTDI_ADDRESS_IP */ 1061 TI_DbgPrint(MID_TRACE, 1062 ("About to call send routine %x\n", 1063 (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); 1064 1065 if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) ) 1066 { 1067 ULONG DataUsed = 0; 1068 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( 1069 Request.Handle.AddressHandle, 1070 DgramInfo->SendDatagramInformation, 1071 DataBuffer, 1072 BufferSize, 1073 &DataUsed); 1074 Irp->IoStatus.Information = DataUsed; 1075 } 1076 else { 1077 Status = STATUS_UNSUCCESSFUL; 1078 ASSERT(FALSE); 1079 } 1080 } 1081 1082 done: 1083 if (Status != STATUS_PENDING) { 1084 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); 1085 } 1086 1087 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); 1088 1089 return STATUS_PENDING; 1090 } 1091 1092 1093 NTSTATUS DispTdiSetEventHandler(PIRP Irp) 1094 /* 1095 * FUNCTION: TDI_SET_EVENT_HANDER handler 1096 * ARGUMENTS: 1097 * Irp = Pointer to a I/O request packet 1098 * RETURNS: 1099 * Status of operation 1100 */ 1101 { 1102 PTDI_REQUEST_KERNEL_SET_EVENT Parameters; 1103 PTRANSPORT_CONTEXT TranContext; 1104 PIO_STACK_LOCATION IrpSp; 1105 PADDRESS_FILE AddrFile; 1106 NTSTATUS Status; 1107 KIRQL OldIrql; 1108 1109 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1110 1111 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1112 1113 /* Get associated address file object. Quit if none exists */ 1114 1115 TranContext = IrpSp->FileObject->FsContext; 1116 if (!TranContext) { 1117 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n")); 1118 return STATUS_INVALID_PARAMETER; 1119 } 1120 1121 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; 1122 if (!AddrFile) { 1123 TI_DbgPrint(MIN_TRACE, ("No address file object.\n")); 1124 return STATUS_INVALID_PARAMETER; 1125 } 1126 1127 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters; 1128 Status = STATUS_SUCCESS; 1129 1130 LockObject(AddrFile, &OldIrql); 1131 1132 /* Set the event handler. if an event handler is associated with 1133 a specific event, it's flag (RegisteredXxxHandler) is TRUE. 1134 If an event handler is not used it's flag is FALSE */ 1135 switch (Parameters->EventType) { 1136 case TDI_EVENT_CONNECT: 1137 if (!Parameters->EventHandler) { 1138 AddrFile->ConnectHandlerContext = NULL; 1139 AddrFile->RegisteredConnectHandler = FALSE; 1140 } else { 1141 AddrFile->ConnectHandler = 1142 (PTDI_IND_CONNECT)Parameters->EventHandler; 1143 AddrFile->ConnectHandlerContext = Parameters->EventContext; 1144 AddrFile->RegisteredConnectHandler = TRUE; 1145 } 1146 break; 1147 1148 case TDI_EVENT_DISCONNECT: 1149 if (!Parameters->EventHandler) { 1150 AddrFile->DisconnectHandlerContext = NULL; 1151 AddrFile->RegisteredDisconnectHandler = FALSE; 1152 } else { 1153 AddrFile->DisconnectHandler = 1154 (PTDI_IND_DISCONNECT)Parameters->EventHandler; 1155 AddrFile->DisconnectHandlerContext = Parameters->EventContext; 1156 AddrFile->RegisteredDisconnectHandler = TRUE; 1157 } 1158 break; 1159 1160 case TDI_EVENT_ERROR: 1161 if (Parameters->EventHandler == NULL) { 1162 AddrFile->ErrorHandlerContext = NULL; 1163 AddrFile->RegisteredErrorHandler = FALSE; 1164 } else { 1165 AddrFile->ErrorHandler = 1166 (PTDI_IND_ERROR)Parameters->EventHandler; 1167 AddrFile->ErrorHandlerContext = Parameters->EventContext; 1168 AddrFile->RegisteredErrorHandler = TRUE; 1169 } 1170 break; 1171 1172 case TDI_EVENT_RECEIVE: 1173 if (Parameters->EventHandler == NULL) { 1174 AddrFile->ReceiveHandlerContext = NULL; 1175 AddrFile->RegisteredReceiveHandler = FALSE; 1176 } else { 1177 AddrFile->ReceiveHandler = 1178 (PTDI_IND_RECEIVE)Parameters->EventHandler; 1179 AddrFile->ReceiveHandlerContext = Parameters->EventContext; 1180 AddrFile->RegisteredReceiveHandler = TRUE; 1181 } 1182 break; 1183 1184 case TDI_EVENT_RECEIVE_DATAGRAM: 1185 if (Parameters->EventHandler == NULL) { 1186 AddrFile->ReceiveDatagramHandlerContext = NULL; 1187 AddrFile->RegisteredReceiveDatagramHandler = FALSE; 1188 } else { 1189 AddrFile->ReceiveDatagramHandler = 1190 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler; 1191 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext; 1192 AddrFile->RegisteredReceiveDatagramHandler = TRUE; 1193 } 1194 break; 1195 1196 case TDI_EVENT_RECEIVE_EXPEDITED: 1197 if (Parameters->EventHandler == NULL) { 1198 AddrFile->ExpeditedReceiveHandlerContext = NULL; 1199 AddrFile->RegisteredExpeditedReceiveHandler = FALSE; 1200 } else { 1201 AddrFile->ExpeditedReceiveHandler = 1202 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler; 1203 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext; 1204 AddrFile->RegisteredExpeditedReceiveHandler = TRUE; 1205 } 1206 break; 1207 1208 case TDI_EVENT_CHAINED_RECEIVE: 1209 if (Parameters->EventHandler == NULL) { 1210 AddrFile->ChainedReceiveHandlerContext = NULL; 1211 AddrFile->RegisteredChainedReceiveHandler = FALSE; 1212 } else { 1213 AddrFile->ChainedReceiveHandler = 1214 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler; 1215 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext; 1216 AddrFile->RegisteredChainedReceiveHandler = TRUE; 1217 } 1218 break; 1219 1220 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM: 1221 if (Parameters->EventHandler == NULL) { 1222 AddrFile->ChainedReceiveDatagramHandlerContext = NULL; 1223 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE; 1224 } else { 1225 AddrFile->ChainedReceiveDatagramHandler = 1226 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler; 1227 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext; 1228 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE; 1229 } 1230 break; 1231 1232 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED: 1233 if (Parameters->EventHandler == NULL) { 1234 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL; 1235 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE; 1236 } else { 1237 AddrFile->ChainedReceiveExpeditedHandler = 1238 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler; 1239 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext; 1240 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE; 1241 } 1242 break; 1243 1244 default: 1245 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n", 1246 Parameters->EventType)); 1247 1248 Status = STATUS_INVALID_PARAMETER; 1249 } 1250 1251 UnlockObject(AddrFile, OldIrql); 1252 1253 return Status; 1254 } 1255 1256 1257 NTSTATUS DispTdiSetInformation( 1258 PIRP Irp) 1259 /* 1260 * FUNCTION: TDI_SET_INFORMATION handler 1261 * ARGUMENTS: 1262 * Irp = Pointer to an I/O request packet 1263 * RETURNS: 1264 * Status of operation 1265 */ 1266 { 1267 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1268 1269 return STATUS_NOT_IMPLEMENTED; 1270 } 1271 1272 1273 VOID DispTdiQueryInformationExComplete( 1274 PVOID Context, 1275 ULONG Status, 1276 UINT ByteCount) 1277 /* 1278 * FUNCTION: Completes a TDI QueryInformationEx request 1279 * ARGUMENTS: 1280 * Context = Pointer to the IRP for the request 1281 * Status = TDI status of the request 1282 * ByteCount = Number of bytes returned in output buffer 1283 */ 1284 { 1285 PTI_QUERY_CONTEXT QueryContext; 1286 1287 QueryContext = (PTI_QUERY_CONTEXT)Context; 1288 if (NT_SUCCESS(Status)) { 1289 CopyBufferToBufferChain( 1290 QueryContext->InputMdl, 1291 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context), 1292 (PCHAR)&QueryContext->QueryInfo.Context, 1293 CONTEXT_SIZE); 1294 } 1295 1296 MmUnlockPages(QueryContext->InputMdl); 1297 IoFreeMdl(QueryContext->InputMdl); 1298 if( QueryContext->OutputMdl ) { 1299 MmUnlockPages(QueryContext->OutputMdl); 1300 IoFreeMdl(QueryContext->OutputMdl); 1301 } 1302 1303 QueryContext->Irp->IoStatus.Information = ByteCount; 1304 QueryContext->Irp->IoStatus.Status = Status; 1305 1306 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1307 } 1308 1309 1310 NTSTATUS DispTdiQueryInformationEx( 1311 PIRP Irp, 1312 PIO_STACK_LOCATION IrpSp) 1313 /* 1314 * FUNCTION: TDI QueryInformationEx handler 1315 * ARGUMENTS: 1316 * Irp = Pointer to I/O request packet 1317 * IrpSp = Pointer to current stack location of Irp 1318 * RETURNS: 1319 * Status of operation 1320 */ 1321 { 1322 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer; 1323 PTRANSPORT_CONTEXT TranContext; 1324 PTI_QUERY_CONTEXT QueryContext; 1325 PVOID OutputBuffer; 1326 TDI_REQUEST Request; 1327 UINT Size; 1328 UINT InputBufferLength; 1329 UINT OutputBufferLength; 1330 BOOLEAN InputMdlLocked = FALSE; 1331 BOOLEAN OutputMdlLocked = FALSE; 1332 PMDL InputMdl = NULL; 1333 PMDL OutputMdl = NULL; 1334 NTSTATUS Status = STATUS_SUCCESS; 1335 1336 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1337 1338 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; 1339 1340 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 1341 case TDI_TRANSPORT_ADDRESS_FILE: 1342 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1343 break; 1344 1345 case TDI_CONNECTION_FILE: 1346 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; 1347 break; 1348 1349 case TDI_CONTROL_CHANNEL_FILE: 1350 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; 1351 break; 1352 1353 default: 1354 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 1355 return STATUS_INVALID_PARAMETER; 1356 } 1357 1358 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 1359 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; 1360 1361 /* Validate parameters */ 1362 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) && 1363 (OutputBufferLength != 0)) { 1364 1365 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX) 1366 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; 1367 OutputBuffer = Irp->UserBuffer; 1368 1369 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG); 1370 if (QueryContext) { 1371 _SEH2_TRY { 1372 InputMdl = IoAllocateMdl(InputBuffer, 1373 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), 1374 FALSE, TRUE, NULL); 1375 1376 OutputMdl = IoAllocateMdl(OutputBuffer, 1377 OutputBufferLength, FALSE, TRUE, NULL); 1378 1379 if (InputMdl && OutputMdl) { 1380 1381 MmProbeAndLockPages(InputMdl, Irp->RequestorMode, 1382 IoModifyAccess); 1383 1384 InputMdlLocked = TRUE; 1385 1386 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode, 1387 IoWriteAccess); 1388 1389 OutputMdlLocked = TRUE; 1390 1391 RtlCopyMemory(&QueryContext->QueryInfo, 1392 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); 1393 } else 1394 Status = STATUS_INSUFFICIENT_RESOURCES; 1395 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 1396 Status = _SEH2_GetExceptionCode(); 1397 } _SEH2_END; 1398 1399 if (NT_SUCCESS(Status)) { 1400 Size = MmGetMdlByteCount(OutputMdl); 1401 1402 QueryContext->Irp = Irp; 1403 QueryContext->InputMdl = InputMdl; 1404 QueryContext->OutputMdl = OutputMdl; 1405 1406 Request.RequestNotifyObject = DispTdiQueryInformationExComplete; 1407 Request.RequestContext = QueryContext; 1408 Status = InfoTdiQueryInformationEx(&Request, 1409 &QueryContext->QueryInfo.ID, OutputMdl, 1410 &Size, &QueryContext->QueryInfo.Context); 1411 DispTdiQueryInformationExComplete(QueryContext, Status, Size); 1412 1413 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1414 1415 return Status; 1416 } 1417 1418 /* An error occurred if we get here */ 1419 1420 if (InputMdl) { 1421 if (InputMdlLocked) 1422 MmUnlockPages(InputMdl); 1423 IoFreeMdl(InputMdl); 1424 } 1425 1426 if (OutputMdl) { 1427 if (OutputMdlLocked) 1428 MmUnlockPages(OutputMdl); 1429 IoFreeMdl(OutputMdl); 1430 } 1431 1432 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1433 } else 1434 Status = STATUS_INSUFFICIENT_RESOURCES; 1435 } else if( InputBufferLength == 1436 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) { 1437 /* Handle the case where the user is probing the buffer for length */ 1438 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n", 1439 InputBufferLength, OutputBufferLength)); 1440 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX) 1441 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; 1442 1443 Size = 0; 1444 1445 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG); 1446 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES; 1447 1448 _SEH2_TRY { 1449 InputMdl = IoAllocateMdl(InputBuffer, 1450 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), 1451 FALSE, TRUE, NULL); 1452 1453 MmProbeAndLockPages(InputMdl, Irp->RequestorMode, 1454 IoModifyAccess); 1455 1456 InputMdlLocked = TRUE; 1457 Status = STATUS_SUCCESS; 1458 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 1459 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n")); 1460 Status = _SEH2_GetExceptionCode(); 1461 } _SEH2_END; 1462 1463 if( !NT_SUCCESS(Status) || !InputMdl ) { 1464 if( InputMdl ) IoFreeMdl( InputMdl ); 1465 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1466 return Status; 1467 } 1468 1469 RtlCopyMemory(&QueryContext->QueryInfo, 1470 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); 1471 1472 QueryContext->Irp = Irp; 1473 QueryContext->InputMdl = InputMdl; 1474 QueryContext->OutputMdl = NULL; 1475 1476 Request.RequestNotifyObject = DispTdiQueryInformationExComplete; 1477 Request.RequestContext = QueryContext; 1478 Status = InfoTdiQueryInformationEx(&Request, 1479 &QueryContext->QueryInfo.ID, 1480 NULL, 1481 &Size, 1482 &QueryContext->QueryInfo.Context); 1483 DispTdiQueryInformationExComplete(QueryContext, Status, Size); 1484 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1485 } else Status = STATUS_INVALID_PARAMETER; 1486 1487 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1488 1489 return Status; 1490 } 1491 1492 1493 NTSTATUS DispTdiSetInformationEx( 1494 PIRP Irp, 1495 PIO_STACK_LOCATION IrpSp) 1496 /* 1497 * FUNCTION: TDI SetInformationEx handler 1498 * ARGUMENTS: 1499 * Irp = Pointer to I/O request packet 1500 * IrpSp = Pointer to current stack location of Irp 1501 * RETURNS: 1502 * Status of operation 1503 */ 1504 { 1505 PTRANSPORT_CONTEXT TranContext; 1506 PTCP_REQUEST_SET_INFORMATION_EX Info; 1507 TDI_REQUEST Request; 1508 TDI_STATUS Status; 1509 1510 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1511 1512 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; 1513 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer; 1514 1515 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 1516 case TDI_TRANSPORT_ADDRESS_FILE: 1517 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1518 break; 1519 1520 case TDI_CONNECTION_FILE: 1521 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; 1522 break; 1523 1524 case TDI_CONTROL_CHANNEL_FILE: 1525 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; 1526 break; 1527 1528 default: 1529 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1530 Irp->IoStatus.Information = 0; 1531 1532 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); 1533 1534 return Irp->IoStatus.Status; 1535 } 1536 1537 Request.RequestNotifyObject = NULL; 1538 Request.RequestContext = NULL; 1539 1540 Status = InfoTdiSetInformationEx(&Request, &Info->ID, 1541 &Info->Buffer, Info->BufferSize); 1542 1543 return Status; 1544 } 1545 1546 /* TODO: Support multiple addresses per interface. 1547 * For now just set the nte context to the interface index. 1548 * 1549 * Later on, create an NTE context and NTE instance 1550 */ 1551 1552 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1553 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST; 1554 PIP_SET_ADDRESS IpAddrChange = 1555 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer; 1556 IF_LIST_ITER(IF); 1557 1558 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n", 1559 IpAddrChange->NteIndex)); 1560 1561 ForEachInterface(IF) { 1562 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index)); 1563 1564 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) { 1565 Status = STATUS_DUPLICATE_OBJECTID; 1566 break; 1567 } 1568 if( IF->Index == IpAddrChange->NteIndex ) { 1569 IPRemoveInterfaceRoute( IF ); 1570 1571 IF->Unicast.Type = IP_ADDRESS_V4; 1572 IF->Unicast.Address.IPv4Address = IpAddrChange->Address; 1573 1574 IF->Netmask.Type = IP_ADDRESS_V4; 1575 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask; 1576 1577 IF->Broadcast.Type = IP_ADDRESS_V4; 1578 IF->Broadcast.Address.IPv4Address = 1579 IF->Unicast.Address.IPv4Address | 1580 ~IF->Netmask.Address.IPv4Address; 1581 1582 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n", 1583 IF->Unicast.Address.IPv4Address)); 1584 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n", 1585 IF->Netmask.Address.IPv4Address)); 1586 1587 IPAddInterfaceRoute( IF ); 1588 1589 IpAddrChange->Address = IF->Index; 1590 Status = STATUS_SUCCESS; 1591 Irp->IoStatus.Information = IF->Index; 1592 break; 1593 } 1594 } EndFor(IF); 1595 1596 Irp->IoStatus.Status = Status; 1597 return Status; 1598 } 1599 1600 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1601 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1602 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer; 1603 IF_LIST_ITER(IF); 1604 1605 ForEachInterface(IF) { 1606 if( IF->Index == *NteIndex ) { 1607 IPRemoveInterfaceRoute( IF ); 1608 IF->Unicast.Type = IP_ADDRESS_V4; 1609 IF->Unicast.Address.IPv4Address = 0; 1610 1611 IF->Netmask.Type = IP_ADDRESS_V4; 1612 IF->Netmask.Address.IPv4Address = 0; 1613 1614 IF->Broadcast.Type = IP_ADDRESS_V4; 1615 IF->Broadcast.Address.IPv4Address = 0; 1616 1617 Status = STATUS_SUCCESS; 1618 } 1619 } EndFor(IF); 1620 1621 Irp->IoStatus.Status = Status; 1622 return Status; 1623 } 1624 1625 VOID NTAPI 1626 WaitForHwAddress ( PDEVICE_OBJECT DeviceObject, PVOID Context) { 1627 PQUERY_HW_WORK_ITEM WorkItem = (PQUERY_HW_WORK_ITEM)Context; 1628 LARGE_INTEGER Now; 1629 LARGE_INTEGER Wait; 1630 IP_ADDRESS Remote; 1631 PIRP Irp; 1632 PNEIGHBOR_CACHE_ENTRY NCE = NULL; 1633 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1634 1635 IoFreeWorkItem(WorkItem->WorkItem); 1636 Irp = WorkItem->Irp; 1637 AddrInitIPv4(&Remote, WorkItem->RemoteIP); 1638 KeQuerySystemTime(&Now); 1639 while (Now.QuadPart - WorkItem->StartTime.QuadPart < 10000 * 1000 && !Irp->Cancel) { 1640 NCE = NBLocateNeighbor(&Remote, WorkItem->Interface); 1641 if (NCE && !(NCE->State & NUD_INCOMPLETE)) { 1642 break; 1643 } 1644 1645 NCE = NULL; 1646 Wait.QuadPart = -10000; 1647 KeDelayExecutionThread(KernelMode, FALSE, &Wait); 1648 KeQuerySystemTime(&Now); 1649 } 1650 1651 if (NCE) { 1652 PVOID OutputBuffer; 1653 1654 if (NCE->LinkAddressLength > WorkItem->IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1655 Status = STATUS_INSUFFICIENT_RESOURCES; 1656 } else { 1657 OutputBuffer = Irp->AssociatedIrp.SystemBuffer; 1658 RtlCopyMemory(OutputBuffer, NCE->LinkAddress, NCE->LinkAddressLength); 1659 Irp->IoStatus.Information = NCE->LinkAddressLength; 1660 Status = STATUS_SUCCESS; 1661 } 1662 } 1663 1664 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1665 if (Irp->Flags & IRP_SYNCHRONOUS_API) { 1666 Irp->IoStatus.Status = Status; 1667 } else { 1668 IRPFinish(Irp, Status); 1669 } 1670 } 1671 1672 NTSTATUS DispTdiQueryIpHwAddress( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1673 NTSTATUS Status; 1674 PULONG IPs; 1675 IP_ADDRESS Remote, Local; 1676 PNEIGHBOR_CACHE_ENTRY NCE; 1677 PIP_INTERFACE Interface; 1678 PQUERY_HW_WORK_ITEM WorkItem; 1679 1680 Irp->IoStatus.Information = 0; 1681 1682 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2 * sizeof(ULONG) || 1683 IrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) { 1684 Status = STATUS_INVALID_BUFFER_SIZE; 1685 goto Exit; 1686 } 1687 1688 IPs = (PULONG)Irp->AssociatedIrp.SystemBuffer; 1689 AddrInitIPv4(&Remote, IPs[0]); 1690 AddrInitIPv4(&Local, IPs[1]); 1691 1692 if (AddrIsUnspecified(&Remote)) { 1693 Status = STATUS_UNSUCCESSFUL; 1694 goto Exit; 1695 } 1696 1697 Interface = AddrLocateInterface(&Remote); 1698 if (Interface) { 1699 PVOID OutputBuffer; 1700 1701 if (Interface->AddressLength > IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1702 Status = STATUS_INSUFFICIENT_RESOURCES; 1703 goto Exit; 1704 } 1705 1706 OutputBuffer = Irp->AssociatedIrp.SystemBuffer; 1707 RtlCopyMemory(OutputBuffer, Interface->Address, Interface->AddressLength); 1708 Irp->IoStatus.Information = Interface->AddressLength; 1709 Status = STATUS_SUCCESS; 1710 goto Exit; 1711 } 1712 1713 if (AddrIsUnspecified(&Local)) { 1714 NCE = RouteGetRouteToDestination(&Remote); 1715 if (NCE == NULL) { 1716 Status = STATUS_NETWORK_UNREACHABLE; 1717 goto Exit; 1718 } 1719 1720 Interface = NCE->Interface; 1721 } 1722 else { 1723 Interface = AddrLocateInterface(&Local); 1724 if (Interface == NULL) { 1725 Interface = GetDefaultInterface(); 1726 if (Interface == NULL) { 1727 Status = STATUS_NETWORK_UNREACHABLE; 1728 goto Exit; 1729 } 1730 } 1731 } 1732 1733 WorkItem = ExAllocatePoolWithTag(PagedPool, sizeof(QUERY_HW_WORK_ITEM), QUERY_CONTEXT_TAG); 1734 if (WorkItem == NULL) { 1735 Status = STATUS_INSUFFICIENT_RESOURCES; 1736 goto Exit; 1737 } 1738 1739 WorkItem->WorkItem = IoAllocateWorkItem(DeviceObject); 1740 if (WorkItem->WorkItem == NULL) { 1741 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1742 Status = STATUS_INSUFFICIENT_RESOURCES; 1743 goto Exit; 1744 } 1745 1746 WorkItem->Irp = Irp; 1747 WorkItem->IrpSp = IrpSp; 1748 WorkItem->Interface = Interface; 1749 WorkItem->RemoteIP = IPs[0]; 1750 KeQuerySystemTime(&WorkItem->StartTime); 1751 1752 NCE = NBLocateNeighbor(&Remote, Interface); 1753 if (NCE != NULL) { 1754 if (NCE->LinkAddressLength > IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1755 IoFreeWorkItem(WorkItem->WorkItem); 1756 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1757 Status = STATUS_INVALID_BUFFER_SIZE; 1758 goto Exit; 1759 } 1760 1761 if (!(NCE->State & NUD_INCOMPLETE)) { 1762 PVOID LinkAddress = ExAllocatePoolWithTag(PagedPool, NCE->LinkAddressLength, QUERY_CONTEXT_TAG); 1763 if (LinkAddress == NULL) { 1764 IoFreeWorkItem(WorkItem->WorkItem); 1765 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1766 Status = STATUS_INSUFFICIENT_RESOURCES; 1767 goto Exit; 1768 } 1769 memset(LinkAddress, 0xff, NCE->LinkAddressLength); 1770 NBUpdateNeighbor(NCE, LinkAddress, NUD_INCOMPLETE); 1771 ExFreePoolWithTag(LinkAddress, QUERY_CONTEXT_TAG); 1772 } 1773 } 1774 1775 if (!ARPTransmit(&Remote, NULL, Interface)) { 1776 IoFreeWorkItem(WorkItem->WorkItem); 1777 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1778 Status = STATUS_UNSUCCESSFUL; 1779 goto Exit; 1780 } 1781 1782 if (Irp->Flags & IRP_SYNCHRONOUS_API) { 1783 WaitForHwAddress(DeviceObject, WorkItem); 1784 Status = Irp->IoStatus.Status; 1785 } else { 1786 IoMarkIrpPending(Irp); 1787 IoQueueWorkItem(WorkItem->WorkItem, WaitForHwAddress, DelayedWorkQueue, WorkItem); 1788 Status = STATUS_PENDING; 1789 } 1790 1791 Exit: 1792 return Status; 1793 } 1794 1795 /* EOF */ 1796