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