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 if (AddrFile == NULL) 715 { 716 TI_DbgPrint(MIN_TRACE, ("FIXME: No address file object.\n")); 717 ASSERT(AddrFile != NULL); 718 return STATUS_INVALID_PARAMETER; 719 } 720 721 Address->TAAddressCount = 1; 722 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 723 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 724 Address->Address[0].Address[0].sin_port = AddrFile->Port; 725 Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address; 726 RtlZeroMemory( 727 &Address->Address[0].Address[0].sin_zero, 728 sizeof(Address->Address[0].Address[0].sin_zero)); 729 return STATUS_SUCCESS; 730 731 case TDI_CONNECTION_FILE: 732 Endpoint = 733 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 734 if (Endpoint == NULL || Endpoint->AddressFile == NULL) 735 { 736 TI_DbgPrint(MIN_TRACE, ("FIXME: No connection endpoint file object.\n")); 737 ASSERT(Endpoint != NULL && Endpoint->AddressFile != NULL); 738 return STATUS_INVALID_PARAMETER; 739 } 740 741 Address->TAAddressCount = 1; 742 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 743 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 744 Address->Address[0].Address[0].sin_port = Endpoint->AddressFile->Port; 745 Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address; 746 RtlZeroMemory( 747 &Address->Address[0].Address[0].sin_zero, 748 sizeof(Address->Address[0].Address[0].sin_zero)); 749 return STATUS_SUCCESS; 750 751 default: 752 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 753 return STATUS_INVALID_PARAMETER; 754 } 755 } 756 757 case TDI_QUERY_CONNECTION_INFO: 758 { 759 PTDI_CONNECTION_INFO ConnectionInfo; 760 //PCONNECTION_ENDPOINT Endpoint; 761 762 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*ConnectionInfo)) { 763 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); 764 return STATUS_BUFFER_TOO_SMALL; 765 } 766 767 ConnectionInfo = (PTDI_CONNECTION_INFO) 768 MmGetSystemAddressForMdl(Irp->MdlAddress); 769 770 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 771 case TDI_CONNECTION_FILE: 772 //Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; 773 RtlZeroMemory(ConnectionInfo, sizeof(*ConnectionInfo)); 774 return STATUS_SUCCESS; 775 776 default: 777 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 778 return STATUS_INVALID_PARAMETER; 779 } 780 } 781 782 case TDI_QUERY_MAX_DATAGRAM_INFO: 783 { 784 PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo; 785 786 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) { 787 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); 788 return STATUS_BUFFER_TOO_SMALL; 789 } 790 791 MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO) 792 MmGetSystemAddressForMdl(Irp->MdlAddress); 793 794 MaxDatagramInfo->MaxDatagramSize = 0xFFFF; 795 796 return STATUS_SUCCESS; 797 } 798 } 799 800 return STATUS_NOT_IMPLEMENTED; 801 } 802 803 804 NTSTATUS DispTdiReceive( 805 PIRP Irp) 806 /* 807 * FUNCTION: TDI_RECEIVE handler 808 * ARGUMENTS: 809 * Irp = Pointer to an I/O request packet 810 * RETURNS: 811 * Status of operation 812 */ 813 { 814 PIO_STACK_LOCATION IrpSp; 815 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo; 816 PTRANSPORT_CONTEXT TranContext; 817 NTSTATUS Status; 818 ULONG BytesReceived = 0; 819 820 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 821 822 IrpSp = IoGetCurrentIrpStackLocation(Irp); 823 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters); 824 825 IoMarkIrpPending(Irp); 826 827 TranContext = IrpSp->FileObject->FsContext; 828 if (TranContext == NULL) 829 { 830 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 831 Status = STATUS_INVALID_PARAMETER; 832 goto done; 833 } 834 835 if (TranContext->Handle.ConnectionContext == NULL) 836 { 837 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 838 Status = STATUS_INVALID_PARAMETER; 839 goto done; 840 } 841 842 /* Initialize a receive request */ 843 Status = DispPrepareIrpForCancel 844 (TranContext->Handle.ConnectionContext, 845 Irp, 846 (PDRIVER_CANCEL)DispCancelRequest); 847 848 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress)); 849 if (NT_SUCCESS(Status)) 850 { 851 Status = TCPReceiveData( 852 TranContext->Handle.ConnectionContext, 853 (PNDIS_BUFFER)Irp->MdlAddress, 854 ReceiveInfo->ReceiveLength, 855 &BytesReceived, 856 ReceiveInfo->ReceiveFlags, 857 DispDataRequestComplete, 858 Irp); 859 } 860 861 done: 862 if (Status != STATUS_PENDING) { 863 DispDataRequestComplete(Irp, Status, BytesReceived); 864 } 865 866 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 867 868 return STATUS_PENDING; 869 } 870 871 872 NTSTATUS DispTdiReceiveDatagram( 873 PIRP Irp) 874 /* 875 * FUNCTION: TDI_RECEIVE_DATAGRAM handler 876 * ARGUMENTS: 877 * Irp = Pointer to an I/O request packet 878 * RETURNS: 879 * Status of operation 880 */ 881 { 882 PIO_STACK_LOCATION IrpSp; 883 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo; 884 PTRANSPORT_CONTEXT TranContext; 885 TDI_REQUEST Request; 886 NTSTATUS Status; 887 ULONG BytesReceived = 0; 888 889 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 890 891 IrpSp = IoGetCurrentIrpStackLocation(Irp); 892 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters); 893 894 IoMarkIrpPending(Irp); 895 896 TranContext = IrpSp->FileObject->FsContext; 897 if (TranContext == NULL) 898 { 899 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 900 Status = STATUS_INVALID_PARAMETER; 901 goto done; 902 } 903 904 /* Initialize a receive request */ 905 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 906 Request.RequestNotifyObject = DispDataRequestComplete; 907 Request.RequestContext = Irp; 908 909 Status = DispPrepareIrpForCancel( 910 IrpSp->FileObject->FsContext, 911 Irp, 912 (PDRIVER_CANCEL)DispCancelRequest); 913 914 if (NT_SUCCESS(Status)) 915 { 916 PVOID DataBuffer; 917 UINT BufferSize; 918 919 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, 920 &DataBuffer, 921 &BufferSize ); 922 923 Status = DGReceiveDatagram( 924 Request.Handle.AddressHandle, 925 DgramInfo->ReceiveDatagramInformation, 926 DataBuffer, 927 DgramInfo->ReceiveLength, 928 DgramInfo->ReceiveFlags, 929 DgramInfo->ReturnDatagramInformation, 930 &BytesReceived, 931 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete, 932 Irp, 933 Irp); 934 } 935 936 done: 937 if (Status != STATUS_PENDING) { 938 DispDataRequestComplete(Irp, Status, BytesReceived); 939 } 940 941 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 942 943 return STATUS_PENDING; 944 } 945 946 947 NTSTATUS DispTdiSend( 948 PIRP Irp) 949 /* 950 * FUNCTION: TDI_SEND handler 951 * ARGUMENTS: 952 * Irp = Pointer to an I/O request packet 953 * RETURNS: 954 * Status of operation 955 */ 956 { 957 PIO_STACK_LOCATION IrpSp; 958 PTDI_REQUEST_KERNEL_SEND SendInfo; 959 PTRANSPORT_CONTEXT TranContext; 960 NTSTATUS Status; 961 ULONG BytesSent = 0; 962 963 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 964 965 IrpSp = IoGetCurrentIrpStackLocation(Irp); 966 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters); 967 968 IoMarkIrpPending(Irp); 969 970 TranContext = IrpSp->FileObject->FsContext; 971 if (TranContext == NULL) 972 { 973 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 974 Status = STATUS_INVALID_PARAMETER; 975 goto done; 976 } 977 978 if (TranContext->Handle.ConnectionContext == NULL) 979 { 980 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); 981 Status = STATUS_INVALID_PARAMETER; 982 goto done; 983 } 984 985 Status = DispPrepareIrpForCancel( 986 IrpSp->FileObject->FsContext, 987 Irp, 988 (PDRIVER_CANCEL)DispCancelRequest); 989 990 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress)); 991 if (NT_SUCCESS(Status)) 992 { 993 PVOID Data; 994 UINT Len; 995 996 NdisQueryBuffer( Irp->MdlAddress, &Data, &Len ); 997 998 TI_DbgPrint(MID_TRACE,("About to TCPSendData\n")); 999 Status = TCPSendData( 1000 TranContext->Handle.ConnectionContext, 1001 Data, 1002 SendInfo->SendLength, 1003 &BytesSent, 1004 SendInfo->SendFlags, 1005 DispDataRequestComplete, 1006 Irp); 1007 } 1008 1009 done: 1010 if (Status != STATUS_PENDING) { 1011 DispDataRequestComplete(Irp, Status, BytesSent); 1012 } 1013 1014 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); 1015 1016 return STATUS_PENDING; 1017 } 1018 1019 1020 NTSTATUS DispTdiSendDatagram( 1021 PIRP Irp) 1022 /* 1023 * FUNCTION: TDI_SEND_DATAGRAM handler 1024 * ARGUMENTS: 1025 * Irp = Pointer to an I/O request packet 1026 * RETURNS: 1027 * Status of operation 1028 */ 1029 { 1030 PIO_STACK_LOCATION IrpSp; 1031 TDI_REQUEST Request; 1032 PTDI_REQUEST_KERNEL_SENDDG DgramInfo; 1033 PTRANSPORT_CONTEXT TranContext; 1034 NTSTATUS Status; 1035 1036 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1037 1038 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1039 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters); 1040 1041 IoMarkIrpPending(Irp); 1042 1043 TranContext = IrpSp->FileObject->FsContext; 1044 if (TranContext == NULL) 1045 { 1046 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); 1047 Status = STATUS_INVALID_PARAMETER; 1048 goto done; 1049 } 1050 1051 /* Initialize a send request */ 1052 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1053 Request.RequestNotifyObject = DispDataRequestComplete; 1054 Request.RequestContext = Irp; 1055 1056 Status = DispPrepareIrpForCancel( 1057 IrpSp->FileObject->FsContext, 1058 Irp, 1059 (PDRIVER_CANCEL)DispCancelRequest); 1060 1061 if (NT_SUCCESS(Status)) { 1062 PVOID DataBuffer; 1063 UINT BufferSize; 1064 1065 TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress)); 1066 1067 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, 1068 &DataBuffer, 1069 &BufferSize ); 1070 1071 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress 1072 must be of type PTDI_ADDRESS_IP */ 1073 TI_DbgPrint(MID_TRACE, 1074 ("About to call send routine %x\n", 1075 (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); 1076 1077 if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) ) 1078 { 1079 ULONG DataUsed = 0; 1080 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( 1081 Request.Handle.AddressHandle, 1082 DgramInfo->SendDatagramInformation, 1083 DataBuffer, 1084 BufferSize, 1085 &DataUsed); 1086 Irp->IoStatus.Information = DataUsed; 1087 } 1088 else { 1089 Status = STATUS_UNSUCCESSFUL; 1090 ASSERT(FALSE); 1091 } 1092 } 1093 1094 done: 1095 if (Status != STATUS_PENDING) { 1096 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); 1097 } 1098 1099 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); 1100 1101 return STATUS_PENDING; 1102 } 1103 1104 1105 NTSTATUS DispTdiSetEventHandler(PIRP Irp) 1106 /* 1107 * FUNCTION: TDI_SET_EVENT_HANDER handler 1108 * ARGUMENTS: 1109 * Irp = Pointer to a I/O request packet 1110 * RETURNS: 1111 * Status of operation 1112 */ 1113 { 1114 PTDI_REQUEST_KERNEL_SET_EVENT Parameters; 1115 PTRANSPORT_CONTEXT TranContext; 1116 PIO_STACK_LOCATION IrpSp; 1117 PADDRESS_FILE AddrFile; 1118 NTSTATUS Status; 1119 KIRQL OldIrql; 1120 1121 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1122 1123 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1124 1125 /* Get associated address file object. Quit if none exists */ 1126 1127 TranContext = IrpSp->FileObject->FsContext; 1128 if (!TranContext) { 1129 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n")); 1130 return STATUS_INVALID_PARAMETER; 1131 } 1132 1133 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; 1134 if (!AddrFile) { 1135 TI_DbgPrint(MIN_TRACE, ("No address file object.\n")); 1136 return STATUS_INVALID_PARAMETER; 1137 } 1138 1139 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters; 1140 Status = STATUS_SUCCESS; 1141 1142 LockObject(AddrFile, &OldIrql); 1143 1144 /* Set the event handler. if an event handler is associated with 1145 a specific event, it's flag (RegisteredXxxHandler) is TRUE. 1146 If an event handler is not used it's flag is FALSE */ 1147 switch (Parameters->EventType) { 1148 case TDI_EVENT_CONNECT: 1149 if (!Parameters->EventHandler) { 1150 AddrFile->ConnectHandlerContext = NULL; 1151 AddrFile->RegisteredConnectHandler = FALSE; 1152 } else { 1153 AddrFile->ConnectHandler = 1154 (PTDI_IND_CONNECT)Parameters->EventHandler; 1155 AddrFile->ConnectHandlerContext = Parameters->EventContext; 1156 AddrFile->RegisteredConnectHandler = TRUE; 1157 } 1158 break; 1159 1160 case TDI_EVENT_DISCONNECT: 1161 if (!Parameters->EventHandler) { 1162 AddrFile->DisconnectHandlerContext = NULL; 1163 AddrFile->RegisteredDisconnectHandler = FALSE; 1164 } else { 1165 AddrFile->DisconnectHandler = 1166 (PTDI_IND_DISCONNECT)Parameters->EventHandler; 1167 AddrFile->DisconnectHandlerContext = Parameters->EventContext; 1168 AddrFile->RegisteredDisconnectHandler = TRUE; 1169 } 1170 break; 1171 1172 case TDI_EVENT_ERROR: 1173 if (Parameters->EventHandler == NULL) { 1174 AddrFile->ErrorHandlerContext = NULL; 1175 AddrFile->RegisteredErrorHandler = FALSE; 1176 } else { 1177 AddrFile->ErrorHandler = 1178 (PTDI_IND_ERROR)Parameters->EventHandler; 1179 AddrFile->ErrorHandlerContext = Parameters->EventContext; 1180 AddrFile->RegisteredErrorHandler = TRUE; 1181 } 1182 break; 1183 1184 case TDI_EVENT_RECEIVE: 1185 if (Parameters->EventHandler == NULL) { 1186 AddrFile->ReceiveHandlerContext = NULL; 1187 AddrFile->RegisteredReceiveHandler = FALSE; 1188 } else { 1189 AddrFile->ReceiveHandler = 1190 (PTDI_IND_RECEIVE)Parameters->EventHandler; 1191 AddrFile->ReceiveHandlerContext = Parameters->EventContext; 1192 AddrFile->RegisteredReceiveHandler = TRUE; 1193 } 1194 break; 1195 1196 case TDI_EVENT_RECEIVE_DATAGRAM: 1197 if (Parameters->EventHandler == NULL) { 1198 AddrFile->ReceiveDatagramHandlerContext = NULL; 1199 AddrFile->RegisteredReceiveDatagramHandler = FALSE; 1200 } else { 1201 AddrFile->ReceiveDatagramHandler = 1202 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler; 1203 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext; 1204 AddrFile->RegisteredReceiveDatagramHandler = TRUE; 1205 } 1206 break; 1207 1208 case TDI_EVENT_RECEIVE_EXPEDITED: 1209 if (Parameters->EventHandler == NULL) { 1210 AddrFile->ExpeditedReceiveHandlerContext = NULL; 1211 AddrFile->RegisteredExpeditedReceiveHandler = FALSE; 1212 } else { 1213 AddrFile->ExpeditedReceiveHandler = 1214 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler; 1215 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext; 1216 AddrFile->RegisteredExpeditedReceiveHandler = TRUE; 1217 } 1218 break; 1219 1220 case TDI_EVENT_CHAINED_RECEIVE: 1221 if (Parameters->EventHandler == NULL) { 1222 AddrFile->ChainedReceiveHandlerContext = NULL; 1223 AddrFile->RegisteredChainedReceiveHandler = FALSE; 1224 } else { 1225 AddrFile->ChainedReceiveHandler = 1226 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler; 1227 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext; 1228 AddrFile->RegisteredChainedReceiveHandler = TRUE; 1229 } 1230 break; 1231 1232 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM: 1233 if (Parameters->EventHandler == NULL) { 1234 AddrFile->ChainedReceiveDatagramHandlerContext = NULL; 1235 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE; 1236 } else { 1237 AddrFile->ChainedReceiveDatagramHandler = 1238 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler; 1239 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext; 1240 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE; 1241 } 1242 break; 1243 1244 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED: 1245 if (Parameters->EventHandler == NULL) { 1246 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL; 1247 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE; 1248 } else { 1249 AddrFile->ChainedReceiveExpeditedHandler = 1250 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler; 1251 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext; 1252 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE; 1253 } 1254 break; 1255 1256 default: 1257 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n", 1258 Parameters->EventType)); 1259 1260 Status = STATUS_INVALID_PARAMETER; 1261 } 1262 1263 UnlockObject(AddrFile, OldIrql); 1264 1265 return Status; 1266 } 1267 1268 1269 NTSTATUS DispTdiSetInformation( 1270 PIRP Irp) 1271 /* 1272 * FUNCTION: TDI_SET_INFORMATION handler 1273 * ARGUMENTS: 1274 * Irp = Pointer to an I/O request packet 1275 * RETURNS: 1276 * Status of operation 1277 */ 1278 { 1279 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1280 1281 return STATUS_NOT_IMPLEMENTED; 1282 } 1283 1284 1285 VOID DispTdiQueryInformationExComplete( 1286 PVOID Context, 1287 ULONG Status, 1288 UINT ByteCount) 1289 /* 1290 * FUNCTION: Completes a TDI QueryInformationEx request 1291 * ARGUMENTS: 1292 * Context = Pointer to the IRP for the request 1293 * Status = TDI status of the request 1294 * ByteCount = Number of bytes returned in output buffer 1295 */ 1296 { 1297 PTI_QUERY_CONTEXT QueryContext; 1298 1299 QueryContext = (PTI_QUERY_CONTEXT)Context; 1300 if (NT_SUCCESS(Status)) { 1301 CopyBufferToBufferChain( 1302 QueryContext->InputMdl, 1303 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context), 1304 (PCHAR)&QueryContext->QueryInfo.Context, 1305 CONTEXT_SIZE); 1306 } 1307 1308 MmUnlockPages(QueryContext->InputMdl); 1309 IoFreeMdl(QueryContext->InputMdl); 1310 if( QueryContext->OutputMdl ) { 1311 MmUnlockPages(QueryContext->OutputMdl); 1312 IoFreeMdl(QueryContext->OutputMdl); 1313 } 1314 1315 QueryContext->Irp->IoStatus.Information = ByteCount; 1316 QueryContext->Irp->IoStatus.Status = Status; 1317 1318 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1319 } 1320 1321 1322 NTSTATUS DispTdiQueryInformationEx( 1323 PIRP Irp, 1324 PIO_STACK_LOCATION IrpSp) 1325 /* 1326 * FUNCTION: TDI QueryInformationEx handler 1327 * ARGUMENTS: 1328 * Irp = Pointer to I/O request packet 1329 * IrpSp = Pointer to current stack location of Irp 1330 * RETURNS: 1331 * Status of operation 1332 */ 1333 { 1334 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer; 1335 PTRANSPORT_CONTEXT TranContext; 1336 PTI_QUERY_CONTEXT QueryContext; 1337 PVOID OutputBuffer; 1338 TDI_REQUEST Request; 1339 UINT Size; 1340 UINT InputBufferLength; 1341 UINT OutputBufferLength; 1342 BOOLEAN InputMdlLocked = FALSE; 1343 BOOLEAN OutputMdlLocked = FALSE; 1344 PMDL InputMdl = NULL; 1345 PMDL OutputMdl = NULL; 1346 NTSTATUS Status = STATUS_SUCCESS; 1347 1348 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1349 1350 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; 1351 1352 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 1353 case TDI_TRANSPORT_ADDRESS_FILE: 1354 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1355 break; 1356 1357 case TDI_CONNECTION_FILE: 1358 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; 1359 break; 1360 1361 case TDI_CONTROL_CHANNEL_FILE: 1362 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; 1363 break; 1364 1365 default: 1366 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); 1367 return STATUS_INVALID_PARAMETER; 1368 } 1369 1370 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; 1371 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; 1372 1373 /* Validate parameters */ 1374 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) && 1375 (OutputBufferLength != 0)) { 1376 1377 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX) 1378 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; 1379 OutputBuffer = Irp->UserBuffer; 1380 1381 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG); 1382 if (QueryContext) { 1383 _SEH2_TRY { 1384 InputMdl = IoAllocateMdl(InputBuffer, 1385 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), 1386 FALSE, TRUE, NULL); 1387 1388 OutputMdl = IoAllocateMdl(OutputBuffer, 1389 OutputBufferLength, FALSE, TRUE, NULL); 1390 1391 if (InputMdl && OutputMdl) { 1392 1393 MmProbeAndLockPages(InputMdl, Irp->RequestorMode, 1394 IoModifyAccess); 1395 1396 InputMdlLocked = TRUE; 1397 1398 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode, 1399 IoWriteAccess); 1400 1401 OutputMdlLocked = TRUE; 1402 1403 RtlCopyMemory(&QueryContext->QueryInfo, 1404 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); 1405 } else 1406 Status = STATUS_INSUFFICIENT_RESOURCES; 1407 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 1408 Status = _SEH2_GetExceptionCode(); 1409 } _SEH2_END; 1410 1411 if (NT_SUCCESS(Status)) { 1412 Size = MmGetMdlByteCount(OutputMdl); 1413 1414 QueryContext->Irp = Irp; 1415 QueryContext->InputMdl = InputMdl; 1416 QueryContext->OutputMdl = OutputMdl; 1417 1418 Request.RequestNotifyObject = DispTdiQueryInformationExComplete; 1419 Request.RequestContext = QueryContext; 1420 Status = InfoTdiQueryInformationEx(&Request, 1421 &QueryContext->QueryInfo.ID, OutputMdl, 1422 &Size, &QueryContext->QueryInfo.Context); 1423 DispTdiQueryInformationExComplete(QueryContext, Status, Size); 1424 1425 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1426 1427 return Status; 1428 } 1429 1430 /* An error occurred if we get here */ 1431 1432 if (InputMdl) { 1433 if (InputMdlLocked) 1434 MmUnlockPages(InputMdl); 1435 IoFreeMdl(InputMdl); 1436 } 1437 1438 if (OutputMdl) { 1439 if (OutputMdlLocked) 1440 MmUnlockPages(OutputMdl); 1441 IoFreeMdl(OutputMdl); 1442 } 1443 1444 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1445 } else 1446 Status = STATUS_INSUFFICIENT_RESOURCES; 1447 } else if( InputBufferLength == 1448 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) { 1449 /* Handle the case where the user is probing the buffer for length */ 1450 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n", 1451 InputBufferLength, OutputBufferLength)); 1452 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX) 1453 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; 1454 1455 Size = 0; 1456 1457 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG); 1458 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES; 1459 1460 _SEH2_TRY { 1461 InputMdl = IoAllocateMdl(InputBuffer, 1462 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), 1463 FALSE, TRUE, NULL); 1464 1465 MmProbeAndLockPages(InputMdl, Irp->RequestorMode, 1466 IoModifyAccess); 1467 1468 InputMdlLocked = TRUE; 1469 Status = STATUS_SUCCESS; 1470 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 1471 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n")); 1472 Status = _SEH2_GetExceptionCode(); 1473 } _SEH2_END; 1474 1475 if( !NT_SUCCESS(Status) || !InputMdl ) { 1476 if( InputMdl ) IoFreeMdl( InputMdl ); 1477 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG); 1478 return Status; 1479 } 1480 1481 RtlCopyMemory(&QueryContext->QueryInfo, 1482 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); 1483 1484 QueryContext->Irp = Irp; 1485 QueryContext->InputMdl = InputMdl; 1486 QueryContext->OutputMdl = NULL; 1487 1488 Request.RequestNotifyObject = DispTdiQueryInformationExComplete; 1489 Request.RequestContext = QueryContext; 1490 Status = InfoTdiQueryInformationEx(&Request, 1491 &QueryContext->QueryInfo.ID, 1492 NULL, 1493 &Size, 1494 &QueryContext->QueryInfo.Context); 1495 DispTdiQueryInformationExComplete(QueryContext, Status, Size); 1496 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1497 } else Status = STATUS_INVALID_PARAMETER; 1498 1499 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status)); 1500 1501 return Status; 1502 } 1503 1504 1505 NTSTATUS DispTdiSetInformationEx( 1506 PIRP Irp, 1507 PIO_STACK_LOCATION IrpSp) 1508 /* 1509 * FUNCTION: TDI SetInformationEx handler 1510 * ARGUMENTS: 1511 * Irp = Pointer to I/O request packet 1512 * IrpSp = Pointer to current stack location of Irp 1513 * RETURNS: 1514 * Status of operation 1515 */ 1516 { 1517 PTRANSPORT_CONTEXT TranContext; 1518 PTCP_REQUEST_SET_INFORMATION_EX Info; 1519 TDI_REQUEST Request; 1520 TDI_STATUS Status; 1521 1522 TI_DbgPrint(DEBUG_IRP, ("Called.\n")); 1523 1524 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; 1525 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer; 1526 1527 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { 1528 case TDI_TRANSPORT_ADDRESS_FILE: 1529 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; 1530 break; 1531 1532 case TDI_CONNECTION_FILE: 1533 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; 1534 break; 1535 1536 case TDI_CONTROL_CHANNEL_FILE: 1537 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; 1538 break; 1539 1540 default: 1541 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1542 Irp->IoStatus.Information = 0; 1543 1544 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); 1545 1546 return Irp->IoStatus.Status; 1547 } 1548 1549 Request.RequestNotifyObject = NULL; 1550 Request.RequestContext = NULL; 1551 1552 Status = InfoTdiSetInformationEx(&Request, &Info->ID, 1553 &Info->Buffer, Info->BufferSize); 1554 1555 return Status; 1556 } 1557 1558 /* TODO: Support multiple addresses per interface. 1559 * For now just set the nte context to the interface index. 1560 * 1561 * Later on, create an NTE context and NTE instance 1562 */ 1563 1564 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1565 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST; 1566 PIP_SET_ADDRESS IpAddrChange = 1567 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer; 1568 IF_LIST_ITER(IF); 1569 1570 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n", 1571 IpAddrChange->NteIndex)); 1572 1573 ForEachInterface(IF) { 1574 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index)); 1575 1576 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) { 1577 Status = STATUS_DUPLICATE_OBJECTID; 1578 break; 1579 } 1580 if( IF->Index == IpAddrChange->NteIndex ) { 1581 IPRemoveInterfaceRoute( IF ); 1582 1583 IF->Unicast.Type = IP_ADDRESS_V4; 1584 IF->Unicast.Address.IPv4Address = IpAddrChange->Address; 1585 1586 IF->Netmask.Type = IP_ADDRESS_V4; 1587 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask; 1588 1589 IF->Broadcast.Type = IP_ADDRESS_V4; 1590 IF->Broadcast.Address.IPv4Address = 1591 IF->Unicast.Address.IPv4Address | 1592 ~IF->Netmask.Address.IPv4Address; 1593 1594 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n", 1595 IF->Unicast.Address.IPv4Address)); 1596 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n", 1597 IF->Netmask.Address.IPv4Address)); 1598 1599 IPAddInterfaceRoute( IF ); 1600 1601 IpAddrChange->Address = IF->Index; 1602 Status = STATUS_SUCCESS; 1603 Irp->IoStatus.Information = IF->Index; 1604 break; 1605 } 1606 } EndFor(IF); 1607 1608 Irp->IoStatus.Status = Status; 1609 return Status; 1610 } 1611 1612 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1613 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1614 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer; 1615 IF_LIST_ITER(IF); 1616 1617 ForEachInterface(IF) { 1618 if( IF->Index == *NteIndex ) { 1619 IPRemoveInterfaceRoute( IF ); 1620 IF->Unicast.Type = IP_ADDRESS_V4; 1621 IF->Unicast.Address.IPv4Address = 0; 1622 1623 IF->Netmask.Type = IP_ADDRESS_V4; 1624 IF->Netmask.Address.IPv4Address = 0; 1625 1626 IF->Broadcast.Type = IP_ADDRESS_V4; 1627 IF->Broadcast.Address.IPv4Address = 0; 1628 1629 Status = STATUS_SUCCESS; 1630 } 1631 } EndFor(IF); 1632 1633 Irp->IoStatus.Status = Status; 1634 return Status; 1635 } 1636 1637 VOID NTAPI 1638 WaitForHwAddress ( PDEVICE_OBJECT DeviceObject, PVOID Context) { 1639 PQUERY_HW_WORK_ITEM WorkItem = (PQUERY_HW_WORK_ITEM)Context; 1640 LARGE_INTEGER Now; 1641 LARGE_INTEGER Wait; 1642 IP_ADDRESS Remote; 1643 PIRP Irp; 1644 PNEIGHBOR_CACHE_ENTRY NCE = NULL; 1645 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1646 1647 IoFreeWorkItem(WorkItem->WorkItem); 1648 Irp = WorkItem->Irp; 1649 AddrInitIPv4(&Remote, WorkItem->RemoteIP); 1650 KeQuerySystemTime(&Now); 1651 while (Now.QuadPart - WorkItem->StartTime.QuadPart < 10000 * 1000 && !Irp->Cancel) { 1652 NCE = NBLocateNeighbor(&Remote, WorkItem->Interface); 1653 if (NCE && !(NCE->State & NUD_INCOMPLETE)) { 1654 break; 1655 } 1656 1657 NCE = NULL; 1658 Wait.QuadPart = -10000; 1659 KeDelayExecutionThread(KernelMode, FALSE, &Wait); 1660 KeQuerySystemTime(&Now); 1661 } 1662 1663 if (NCE) { 1664 PVOID OutputBuffer; 1665 1666 if (NCE->LinkAddressLength > WorkItem->IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1667 Status = STATUS_INSUFFICIENT_RESOURCES; 1668 } else { 1669 OutputBuffer = Irp->AssociatedIrp.SystemBuffer; 1670 RtlCopyMemory(OutputBuffer, NCE->LinkAddress, NCE->LinkAddressLength); 1671 Irp->IoStatus.Information = NCE->LinkAddressLength; 1672 Status = STATUS_SUCCESS; 1673 } 1674 } 1675 1676 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1677 if (Irp->Flags & IRP_SYNCHRONOUS_API) { 1678 Irp->IoStatus.Status = Status; 1679 } else { 1680 IRPFinish(Irp, Status); 1681 } 1682 } 1683 1684 NTSTATUS DispTdiQueryIpHwAddress( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { 1685 NTSTATUS Status; 1686 PULONG IPs; 1687 IP_ADDRESS Remote, Local; 1688 PNEIGHBOR_CACHE_ENTRY NCE; 1689 PIP_INTERFACE Interface; 1690 PQUERY_HW_WORK_ITEM WorkItem; 1691 1692 Irp->IoStatus.Information = 0; 1693 1694 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2 * sizeof(ULONG) || 1695 IrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) { 1696 Status = STATUS_INVALID_BUFFER_SIZE; 1697 goto Exit; 1698 } 1699 1700 IPs = (PULONG)Irp->AssociatedIrp.SystemBuffer; 1701 AddrInitIPv4(&Remote, IPs[0]); 1702 AddrInitIPv4(&Local, IPs[1]); 1703 1704 if (AddrIsUnspecified(&Remote)) { 1705 Status = STATUS_UNSUCCESSFUL; 1706 goto Exit; 1707 } 1708 1709 Interface = AddrLocateInterface(&Remote); 1710 if (Interface) { 1711 PVOID OutputBuffer; 1712 1713 if (Interface->AddressLength > IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1714 Status = STATUS_INSUFFICIENT_RESOURCES; 1715 goto Exit; 1716 } 1717 1718 OutputBuffer = Irp->AssociatedIrp.SystemBuffer; 1719 RtlCopyMemory(OutputBuffer, Interface->Address, Interface->AddressLength); 1720 Irp->IoStatus.Information = Interface->AddressLength; 1721 Status = STATUS_SUCCESS; 1722 goto Exit; 1723 } 1724 1725 if (AddrIsUnspecified(&Local)) { 1726 NCE = RouteGetRouteToDestination(&Remote); 1727 if (NCE == NULL) { 1728 Status = STATUS_NETWORK_UNREACHABLE; 1729 goto Exit; 1730 } 1731 1732 Interface = NCE->Interface; 1733 } 1734 else { 1735 Interface = AddrLocateInterface(&Local); 1736 if (Interface == NULL) { 1737 Interface = GetDefaultInterface(); 1738 if (Interface == NULL) { 1739 Status = STATUS_NETWORK_UNREACHABLE; 1740 goto Exit; 1741 } 1742 } 1743 } 1744 1745 WorkItem = ExAllocatePoolWithTag(PagedPool, sizeof(QUERY_HW_WORK_ITEM), QUERY_CONTEXT_TAG); 1746 if (WorkItem == NULL) { 1747 Status = STATUS_INSUFFICIENT_RESOURCES; 1748 goto Exit; 1749 } 1750 1751 WorkItem->WorkItem = IoAllocateWorkItem(DeviceObject); 1752 if (WorkItem->WorkItem == NULL) { 1753 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1754 Status = STATUS_INSUFFICIENT_RESOURCES; 1755 goto Exit; 1756 } 1757 1758 WorkItem->Irp = Irp; 1759 WorkItem->IrpSp = IrpSp; 1760 WorkItem->Interface = Interface; 1761 WorkItem->RemoteIP = IPs[0]; 1762 KeQuerySystemTime(&WorkItem->StartTime); 1763 1764 NCE = NBLocateNeighbor(&Remote, Interface); 1765 if (NCE != NULL) { 1766 if (NCE->LinkAddressLength > IrpSp->Parameters.DeviceIoControl.OutputBufferLength) { 1767 IoFreeWorkItem(WorkItem->WorkItem); 1768 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1769 Status = STATUS_INVALID_BUFFER_SIZE; 1770 goto Exit; 1771 } 1772 1773 if (!(NCE->State & NUD_INCOMPLETE)) { 1774 PVOID LinkAddress = ExAllocatePoolWithTag(PagedPool, NCE->LinkAddressLength, QUERY_CONTEXT_TAG); 1775 if (LinkAddress == NULL) { 1776 IoFreeWorkItem(WorkItem->WorkItem); 1777 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1778 Status = STATUS_INSUFFICIENT_RESOURCES; 1779 goto Exit; 1780 } 1781 memset(LinkAddress, 0xff, NCE->LinkAddressLength); 1782 NBUpdateNeighbor(NCE, LinkAddress, NUD_INCOMPLETE); 1783 ExFreePoolWithTag(LinkAddress, QUERY_CONTEXT_TAG); 1784 } 1785 } 1786 1787 if (!ARPTransmit(&Remote, NULL, Interface)) { 1788 IoFreeWorkItem(WorkItem->WorkItem); 1789 ExFreePoolWithTag(WorkItem, QUERY_CONTEXT_TAG); 1790 Status = STATUS_UNSUCCESSFUL; 1791 goto Exit; 1792 } 1793 1794 if (Irp->Flags & IRP_SYNCHRONOUS_API) { 1795 WaitForHwAddress(DeviceObject, WorkItem); 1796 Status = Irp->IoStatus.Status; 1797 } else { 1798 IoMarkIrpPending(Irp); 1799 IoQueueWorkItem(WorkItem->WorkItem, WaitForHwAddress, DelayedWorkQueue, WorkItem); 1800 Status = STATUS_PENDING; 1801 } 1802 1803 Exit: 1804 return Status; 1805 } 1806 1807 /* EOF */ 1808