|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1989-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: address.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains code which implements the TP_ADDRESS object. ! 12: Routines are provided to create, destroy, reference, and dereference, ! 13: transport address objects. ! 14: ! 15: Environment: ! 16: ! 17: Kernel mode ! 18: ! 19: Revision History: ! 20: ! 21: --*/ ! 22: ! 23: #include "st.h" ! 24: ! 25: ! 26: // ! 27: // Map all generic accesses to the same one. ! 28: // ! 29: ! 30: STATIC GENERIC_MAPPING AddressGenericMapping = ! 31: { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL }; ! 32: ! 33: ! 34: NTSTATUS ! 35: StOpenAddress( ! 36: IN PDEVICE_OBJECT DeviceObject, ! 37: IN PIRP Irp, ! 38: IN PIO_STACK_LOCATION IrpSp ! 39: ) ! 40: ! 41: /*++ ! 42: ! 43: Routine Description: ! 44: ! 45: This routine opens a file that points to an existing address object, or, if ! 46: the object doesn't exist, creates it (note that creation of the address ! 47: object includes registering the address, and may take many seconds to ! 48: complete, depending upon system configuration). ! 49: ! 50: If the address already exists, and it has an ACL associated with it, the ! 51: ACL is checked for access rights before allowing creation of the address. ! 52: ! 53: Arguments: ! 54: ! 55: DeviceObject - pointer to the device object describing the ST transport. ! 56: ! 57: Irp - a pointer to the Irp used for the creation of the address. ! 58: ! 59: IrpSp - a pointer to the Irp stack location. ! 60: ! 61: Return Value: ! 62: ! 63: NTSTATUS - status of operation. ! 64: ! 65: --*/ ! 66: ! 67: { ! 68: PDEVICE_CONTEXT DeviceContext; ! 69: NTSTATUS status; ! 70: PTP_ADDRESS address; ! 71: PTP_ADDRESS_FILE addressFile; ! 72: PST_NETBIOS_ADDRESS networkName; // Network name string. ! 73: PFILE_FULL_EA_INFORMATION ea; ! 74: TRANSPORT_ADDRESS UNALIGNED *name; ! 75: TA_ADDRESS UNALIGNED *addressName; ! 76: TDI_ADDRESS_NETBIOS UNALIGNED *netbiosName; ! 77: ULONG DesiredShareAccess; ! 78: KIRQL oldirql; ! 79: PACCESS_STATE AccessState; ! 80: ACCESS_MASK GrantedAccess; ! 81: BOOLEAN AccessAllowed; ! 82: int i; ! 83: BOOLEAN found = FALSE; ! 84: ! 85: DeviceContext = (PDEVICE_CONTEXT)DeviceObject; ! 86: ! 87: // ! 88: // The network name is in the EA, passed in AssociatedIrp.SystemBuffer ! 89: // ! 90: ! 91: ea = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ! 92: if (ea == NULL) { ! 93: StPrint1("OpenAddress: IRP %lx has no EA\n", Irp); ! 94: return STATUS_NONEXISTENT_EA_ENTRY; ! 95: } ! 96: ! 97: // ! 98: // this may be a valid name; parse the name from the EA and use it if OK. ! 99: // ! 100: ! 101: name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1]; ! 102: addressName = (PTA_ADDRESS)&name->Address[0]; ! 103: ! 104: // ! 105: // The name can be passed with multiple entries; we'll take and use only ! 106: // the first one. ! 107: // ! 108: ! 109: for (i=0;i<name->TAAddressCount;i++) { ! 110: if (addressName->AddressType == TDI_ADDRESS_TYPE_NETBIOS) { ! 111: if (addressName->AddressLength != 0) { ! 112: netbiosName = (PTDI_ADDRESS_NETBIOS)&addressName->Address[0]; ! 113: networkName = (PST_NETBIOS_ADDRESS)ExAllocatePool ( ! 114: NonPagedPool, ! 115: sizeof (ST_NETBIOS_ADDRESS)); ! 116: if (networkName == NULL) { ! 117: PANIC ("StOpenAddress: PANIC! could not allocate networkName!\n"); ! 118: StWriteResourceErrorLog (DeviceContext, sizeof(TA_NETBIOS_ADDRESS), 1); ! 119: return STATUS_INSUFFICIENT_RESOURCES; ! 120: } ! 121: ! 122: // ! 123: // get the name to local storage ! 124: // ! 125: ! 126: if ((netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP) || ! 127: (netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP)) { ! 128: networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_GROUP; ! 129: } else { ! 130: networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; ! 131: } ! 132: RtlCopyMemory (networkName->NetbiosName, netbiosName->NetbiosName, 16); ! 133: ! 134: found = TRUE; ! 135: } else { ! 136: networkName = NULL; ! 137: found = TRUE; ! 138: } ! 139: ! 140: break; ! 141: ! 142: } else { ! 143: ! 144: addressName = (PTA_ADDRESS)(addressName->Address + ! 145: addressName->AddressLength); ! 146: ! 147: } ! 148: ! 149: } ! 150: ! 151: if (!found) { ! 152: StPrint1("OpenAddress: IRP %lx has no NETBIOS address\n", Irp); ! 153: return STATUS_NONEXISTENT_EA_ENTRY; ! 154: } ! 155: ! 156: // ! 157: // get an address file structure to represent this address. ! 158: // ! 159: ! 160: status = StCreateAddressFile (DeviceContext, &addressFile); ! 161: ! 162: if (!NT_SUCCESS (status)) { ! 163: return status; ! 164: } ! 165: ! 166: // ! 167: // See if this address is already established. This call automatically ! 168: // increments the reference count on the address so that it won't disappear ! 169: // from underneath us after this call but before we have a chance to use it. ! 170: // ! 171: // To ensure that we don't create two address objects for the ! 172: // same address, we hold the device context AddressResource until ! 173: // we have found the address or created a new one. ! 174: // ! 175: ! 176: ExAcquireResourceExclusive (&DeviceContext->AddressResource, TRUE); ! 177: ! 178: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 179: ! 180: address = StLookupAddress (DeviceContext, networkName); ! 181: ! 182: if (address == NULL) { ! 183: ! 184: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 185: ! 186: // ! 187: // This address doesn't exist. Create it, and start the process of ! 188: // registering it. ! 189: // ! 190: ! 191: status = StCreateAddress ( ! 192: DeviceContext, ! 193: networkName, ! 194: &address); ! 195: ! 196: if (NT_SUCCESS (status)) { ! 197: ! 198: // ! 199: // Initialize the shared access now. We use read access ! 200: // to control all access. ! 201: // ! 202: ! 203: DesiredShareAccess = (ULONG) ! 204: (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) || ! 205: (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ? ! 206: FILE_SHARE_READ : 0); ! 207: ! 208: IoSetShareAccess( ! 209: FILE_READ_DATA, ! 210: DesiredShareAccess, ! 211: IrpSp->FileObject, ! 212: &address->ShareAccess); ! 213: ! 214: ! 215: // ! 216: // Assign the security descriptor (need to do this with ! 217: // the spinlock released because the descriptor is not ! 218: // mapped. BUGBUG: Need to synchronize Assign and Access). ! 219: // ! 220: ! 221: AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; ! 222: ! 223: status = SeAssignSecurity( ! 224: NULL, // parent descriptor ! 225: AccessState->SecurityDescriptor, ! 226: &address->SecurityDescriptor, ! 227: FALSE, // is directory ! 228: &AccessState->SubjectSecurityContext, ! 229: &AddressGenericMapping, ! 230: NonPagedPool); ! 231: ! 232: if (!NT_SUCCESS(status)) { ! 233: ! 234: // ! 235: // Error, return status. ! 236: // ! 237: ! 238: IoRemoveShareAccess (IrpSp->FileObject, &address->ShareAccess); ! 239: ExReleaseResource (&DeviceContext->AddressResource); ! 240: StDereferenceAddress ("Device context stopping", address); ! 241: StDereferenceAddressFile (addressFile); ! 242: return status; ! 243: ! 244: } ! 245: ! 246: ExReleaseResource (&DeviceContext->AddressResource); ! 247: ! 248: // ! 249: // if the adapter isn't ready, we can't do any of this; get out ! 250: // ! 251: ! 252: if (DeviceContext->State == DEVICECONTEXT_STATE_STOPPING) { ! 253: StDereferenceAddress ("Device context stopping", address); ! 254: StDereferenceAddressFile (addressFile); ! 255: status = STATUS_DEVICE_NOT_READY; ! 256: ! 257: } else { ! 258: ! 259: IrpSp->FileObject->FsContext = (PVOID)addressFile; ! 260: IrpSp->FileObject->FsContext2 = ! 261: (PVOID)TDI_TRANSPORT_ADDRESS_FILE; ! 262: addressFile->FileObject = IrpSp->FileObject; ! 263: addressFile->Irp = Irp; ! 264: addressFile->Address = address; ! 265: ! 266: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql); ! 267: InsertTailList (&address->AddressFileDatabase, &addressFile->Linkage); ! 268: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 269: ! 270: ! 271: // ! 272: // Begin address registration unless this is the broadcast ! 273: // address (which is a "fake" address with no corresponding ! 274: // Netbios address) or the reserved address, which we know ! 275: // is unique since it is based on the adapter address. ! 276: // ! 277: ! 278: if ((networkName != NULL) && ! 279: (RtlCompareMemory (networkName->NetbiosName, ! 280: DeviceContext->ReservedNetBIOSAddress, ! 281: NETBIOS_NAME_LENGTH) < NETBIOS_NAME_LENGTH)) { ! 282: ! 283: StRegisterAddress (address); // begin address registration. ! 284: status = STATUS_PENDING; ! 285: ! 286: } else { ! 287: ! 288: address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG; ! 289: addressFile->Irp = NULL; ! 290: addressFile->State = ADDRESSFILE_STATE_OPEN; ! 291: status = STATUS_SUCCESS; ! 292: ! 293: } ! 294: ! 295: } ! 296: ! 297: } else { ! 298: ! 299: ExReleaseResource (&DeviceContext->AddressResource); ! 300: ! 301: // ! 302: // If the address could not be created, and is not in the process of ! 303: // being created, then we can't open up an address. ! 304: // ! 305: ! 306: if (networkName != NULL) { ! 307: ExFreePool (networkName); ! 308: } ! 309: ! 310: StDereferenceAddressFile (addressFile); ! 311: ! 312: } ! 313: ! 314: } else { ! 315: ! 316: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 317: ! 318: // ! 319: // The address already exists. Check the ACL and see if we ! 320: // can access it. If so, simply use this address as our address. ! 321: // ! 322: ! 323: AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState; ! 324: ! 325: AccessAllowed = SeAccessCheck( ! 326: address->SecurityDescriptor, ! 327: &AccessState->SubjectSecurityContext, ! 328: FALSE, // tokens locked ! 329: IrpSp->Parameters.Create.SecurityContext->DesiredAccess, ! 330: (ACCESS_MASK)0, // previously granted ! 331: NULL, // privileges ! 332: &AddressGenericMapping, ! 333: Irp->RequestorMode, ! 334: &GrantedAccess, ! 335: &status); ! 336: ! 337: if (AccessAllowed) { ! 338: ! 339: // ! 340: // Access was successful, make sure Status is right. ! 341: // ! 342: ! 343: status = STATUS_SUCCESS; ! 344: ! 345: // ! 346: // Check that the name is of the correct type (unique vs. group) ! 347: // We don't need to check this for the broadcast address. ! 348: // ! 349: ! 350: if (networkName != NULL) { ! 351: if (address->NetworkName->NetbiosNameType != ! 352: networkName->NetbiosNameType) { ! 353: ! 354: status = STATUS_DUPLICATE_NAME; ! 355: ! 356: } ! 357: } ! 358: ! 359: } ! 360: ! 361: ! 362: if (!NT_SUCCESS (status)) { ! 363: ! 364: ExReleaseResource (&DeviceContext->AddressResource); ! 365: ! 366: StDereferenceAddressFile (addressFile); ! 367: ! 368: } else { ! 369: ! 370: // ! 371: // Now check that we can obtain the desired share ! 372: // access. We use read access to control all access. ! 373: // ! 374: ! 375: DesiredShareAccess = (ULONG) ! 376: (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) || ! 377: (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ? ! 378: FILE_SHARE_READ : 0); ! 379: ! 380: status = IoCheckShareAccess( ! 381: FILE_READ_DATA, ! 382: DesiredShareAccess, ! 383: IrpSp->FileObject, ! 384: &address->ShareAccess, ! 385: TRUE); ! 386: ! 387: if (!NT_SUCCESS (status)) { ! 388: ! 389: ExReleaseResource (&DeviceContext->AddressResource); ! 390: ! 391: StDereferenceAddressFile (addressFile); ! 392: ! 393: } else { ! 394: ! 395: ExReleaseResource (&DeviceContext->AddressResource); ! 396: ! 397: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql); ! 398: ! 399: // ! 400: // now, if the address registered, we simply return success after ! 401: // pointing the file object at the address file (which points to ! 402: // the address). If the address registration is pending, we mark ! 403: // the registration pending and let the registration completion ! 404: // routine complete the open. If the address is bad, we simply ! 405: // fail the open. ! 406: // ! 407: ! 408: if ((address->Flags & ! 409: (ADDRESS_FLAGS_CONFLICT | ! 410: ADDRESS_FLAGS_REGISTERING | ! 411: ADDRESS_FLAGS_DEREGISTERING | ! 412: ADDRESS_FLAGS_DUPLICATE_NAME | ! 413: ADDRESS_FLAGS_NEEDS_REG | ! 414: ADDRESS_FLAGS_STOPPING | ! 415: ADDRESS_FLAGS_BAD_ADDRESS | ! 416: ADDRESS_FLAGS_CLOSED)) == 0) { ! 417: ! 418: InsertTailList ( ! 419: &address->AddressFileDatabase, ! 420: &addressFile->Linkage); ! 421: ! 422: addressFile->Irp = NULL; ! 423: addressFile->Address = address; ! 424: addressFile->FileObject = IrpSp->FileObject; ! 425: addressFile->State = ADDRESSFILE_STATE_OPEN; ! 426: ! 427: StReferenceAddress("open ready", address); ! 428: ! 429: IrpSp->FileObject->FsContext = (PVOID)addressFile; ! 430: IrpSp->FileObject->FsContext2 = ! 431: (PVOID)TDI_TRANSPORT_ADDRESS_FILE; ! 432: ! 433: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 434: ! 435: status = STATUS_SUCCESS; ! 436: ! 437: } else { ! 438: ! 439: // ! 440: // if the address is still registering, make the open pending. ! 441: // ! 442: ! 443: if ((address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_NEEDS_REG)) != 0) { ! 444: ! 445: InsertTailList ( ! 446: &address->AddressFileDatabase, ! 447: &addressFile->Linkage); ! 448: ! 449: addressFile->Irp = Irp; ! 450: addressFile->Address = address; ! 451: addressFile->FileObject = IrpSp->FileObject; ! 452: ! 453: StReferenceAddress("open registering", address); ! 454: ! 455: IrpSp->FileObject->FsContext = (PVOID)addressFile; ! 456: IrpSp->FileObject->FsContext2 = ! 457: (PVOID)TDI_TRANSPORT_ADDRESS_FILE; ! 458: ! 459: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 460: ! 461: status = STATUS_PENDING; ! 462: ! 463: } else { ! 464: ! 465: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 466: ! 467: StDereferenceAddressFile (addressFile); ! 468: ! 469: status = STATUS_DRIVER_INTERNAL_ERROR; ! 470: ! 471: } ! 472: } ! 473: } ! 474: } ! 475: ! 476: // ! 477: // Remove the reference from StLookupAddress. ! 478: // ! 479: ! 480: StDereferenceAddress ("Done opening", address); ! 481: } ! 482: ! 483: return status; ! 484: } /* StOpenAddress */ ! 485: ! 486: ! 487: VOID ! 488: StAllocateAddress( ! 489: IN PDEVICE_CONTEXT DeviceContext, ! 490: OUT PTP_ADDRESS *TransportAddress ! 491: ) ! 492: ! 493: /*++ ! 494: ! 495: Routine Description: ! 496: ! 497: This routine allocates storage for a transport address. Some minimal ! 498: initialization is done on the address. ! 499: ! 500: NOTE: This routine is called with the device context spinlock ! 501: held, or at such a time as synchronization is unnecessary. ! 502: ! 503: Arguments: ! 504: ! 505: DeviceContext - Pointer to the device context (which is really just ! 506: the device object with its extension) to be associated with the ! 507: address. ! 508: ! 509: Address - Pointer to a place where this routine will return a pointer ! 510: to a transport address structure. Returns NULL if no storage ! 511: can be allocated. ! 512: ! 513: Return Value: ! 514: ! 515: None. ! 516: ! 517: --*/ ! 518: ! 519: { ! 520: PTP_ADDRESS Address; ! 521: PSEND_PACKET_TAG SendTag; ! 522: ! 523: if ((DeviceContext->MemoryLimit != 0) && ! 524: ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS)) > ! 525: DeviceContext->MemoryLimit)) { ! 526: PANIC("ST: Could not allocate address: limit\n"); ! 527: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 101); ! 528: *TransportAddress = NULL; ! 529: return; ! 530: } ! 531: ! 532: Address = (PTP_ADDRESS)ExAllocatePool (NonPagedPool, sizeof (TP_ADDRESS)); ! 533: if (Address == NULL) { ! 534: PANIC("ST: Could not allocate address: no pool\n"); ! 535: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 201); ! 536: *TransportAddress = NULL; ! 537: return; ! 538: } ! 539: RtlZeroMemory (Address, sizeof(TP_ADDRESS)); ! 540: ! 541: DeviceContext->MemoryUsage += sizeof(TP_ADDRESS); ! 542: ++DeviceContext->AddressAllocated; ! 543: ! 544: StAllocateSendPacket (DeviceContext, &(Address->Packet)); ! 545: if (Address->Packet == NULL) { ! 546: ExFreePool (Address); ! 547: *TransportAddress = NULL; ! 548: return; ! 549: } ! 550: --DeviceContext->PacketAllocated; // AllocatePacket added one ! 551: ! 552: // ! 553: // Need to modify the address packets to belong to ! 554: // the address, not the device context. ! 555: // ! 556: ! 557: SendTag = (PSEND_PACKET_TAG)(Address->Packet->NdisPacket->ProtocolReserved); ! 558: SendTag->Type = TYPE_G_FRAME; ! 559: SendTag->Packet = Address->Packet; ! 560: SendTag->Owner = (PVOID)Address; ! 561: ! 562: ! 563: Address->Type = ST_ADDRESS_SIGNATURE; ! 564: Address->Size = sizeof (TP_ADDRESS); ! 565: ! 566: Address->Provider = DeviceContext; ! 567: KeInitializeSpinLock (&Address->SpinLock); ! 568: ! 569: InitializeListHead (&Address->ConnectionDatabase); ! 570: InitializeListHead (&Address->AddressFileDatabase); ! 571: InitializeListHead (&Address->SendDatagramQueue); ! 572: ! 573: // ! 574: // For each address, allocate a receive packet, a receive buffer, ! 575: // and a UI frame. ! 576: // ! 577: ! 578: StAddReceivePacket (DeviceContext); ! 579: StAddReceiveBuffer (DeviceContext); ! 580: ! 581: *TransportAddress = Address; ! 582: ! 583: } /* StAllocateAddress */ ! 584: ! 585: ! 586: VOID ! 587: StDeallocateAddress( ! 588: IN PDEVICE_CONTEXT DeviceContext, ! 589: IN PTP_ADDRESS TransportAddress ! 590: ) ! 591: ! 592: /*++ ! 593: ! 594: Routine Description: ! 595: ! 596: This routine frees storage for a transport address. ! 597: ! 598: NOTE: This routine is called with the device context spinlock ! 599: held, or at such a time as synchronization is unnecessary. ! 600: ! 601: Arguments: ! 602: ! 603: DeviceContext - Pointer to the device context (which is really just ! 604: the device object with its extension) to be associated with the ! 605: address. ! 606: ! 607: Address - Pointer to a transport address structure. ! 608: ! 609: Return Value: ! 610: ! 611: None. ! 612: ! 613: --*/ ! 614: ! 615: { ! 616: ! 617: if (TransportAddress->NetworkName != NULL) { ! 618: ExFreePool (TransportAddress->NetworkName); ! 619: } ! 620: StDeallocateSendPacket (DeviceContext, TransportAddress->Packet); ! 621: ++DeviceContext->PacketAllocated; ! 622: ! 623: ExFreePool (TransportAddress); ! 624: --DeviceContext->AddressAllocated; ! 625: DeviceContext->MemoryUsage -= sizeof(TP_ADDRESS); ! 626: ! 627: // ! 628: // Remove the resources which allocating this caused. ! 629: // ! 630: ! 631: StRemoveReceivePacket (DeviceContext); ! 632: StRemoveReceiveBuffer (DeviceContext); ! 633: ! 634: } /* StDeallocateAddress */ ! 635: ! 636: ! 637: NTSTATUS ! 638: StCreateAddress( ! 639: IN PDEVICE_CONTEXT DeviceContext, ! 640: IN PST_NETBIOS_ADDRESS NetworkName, ! 641: OUT PTP_ADDRESS *Address ! 642: ) ! 643: ! 644: /*++ ! 645: ! 646: Routine Description: ! 647: ! 648: This routine creates a transport address and associates it with ! 649: the specified transport device context. The reference count in the ! 650: address is automatically set to 1, and the reference count of the ! 651: device context is incremented. ! 652: ! 653: NOTE: This routine must be called with the DeviceContext ! 654: spinlock held. ! 655: ! 656: Arguments: ! 657: ! 658: DeviceContext - Pointer to the device context (which is really just ! 659: the device object with its extension) to be associated with the ! 660: address. ! 661: ! 662: NetworkName - Pointer to an ST_NETBIOS_ADDRESS type containing the network ! 663: name to be associated with this address, if any. ! 664: ! 665: Address - Pointer to a place where this routine will return a pointer ! 666: to a transport address structure. ! 667: ! 668: Return Value: ! 669: ! 670: NTSTATUS - status of operation. ! 671: ! 672: --*/ ! 673: ! 674: { ! 675: PTP_ADDRESS pAddress; ! 676: PLIST_ENTRY p; ! 677: ! 678: ! 679: p = RemoveHeadList (&DeviceContext->AddressPool); ! 680: if (p == &DeviceContext->AddressPool) { ! 681: ! 682: if ((DeviceContext->AddressMaxAllocated == 0) || ! 683: (DeviceContext->AddressAllocated < DeviceContext->AddressMaxAllocated)) { ! 684: ! 685: StAllocateAddress (DeviceContext, &pAddress); ! 686: ! 687: } else { ! 688: ! 689: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 401); ! 690: pAddress = NULL; ! 691: ! 692: } ! 693: ! 694: if (pAddress == NULL) { ! 695: ++DeviceContext->AddressExhausted; ! 696: PANIC ("StCreateConnection: Could not allocate address object!\n"); ! 697: return STATUS_INSUFFICIENT_RESOURCES; ! 698: } ! 699: ! 700: } else { ! 701: ! 702: pAddress = CONTAINING_RECORD (p, TP_ADDRESS, Linkage); ! 703: ! 704: } ! 705: ! 706: ++DeviceContext->AddressInUse; ! 707: if (DeviceContext->AddressInUse > DeviceContext->AddressMaxInUse) { ! 708: ++DeviceContext->AddressMaxInUse; ! 709: } ! 710: ! 711: DeviceContext->AddressTotal += DeviceContext->AddressInUse; ! 712: ++DeviceContext->AddressSamples; ! 713: ! 714: ! 715: // ! 716: // Initialize all of the static data for this address. ! 717: // ! 718: ! 719: pAddress->ReferenceCount = 1; ! 720: ! 721: pAddress->Flags = ADDRESS_FLAGS_NEEDS_REG; ! 722: InitializeListHead (&pAddress->AddressFileDatabase); ! 723: ! 724: pAddress->NetworkName = NetworkName; ! 725: if ((NetworkName != (PST_NETBIOS_ADDRESS)NULL) && ! 726: (NetworkName->NetbiosNameType == ! 727: TDI_ADDRESS_NETBIOS_TYPE_GROUP)) { ! 728: ! 729: pAddress->Flags |= ADDRESS_FLAGS_GROUP; ! 730: ! 731: } ! 732: ! 733: // ! 734: // Now link this address into the specified device context's ! 735: // address database. To do this, we need to acquire the spin lock ! 736: // on the device context. ! 737: // ! 738: ! 739: InsertTailList (&DeviceContext->AddressDatabase, &pAddress->Linkage); ! 740: pAddress->Provider = DeviceContext; ! 741: StReferenceDeviceContext ("Create Address", DeviceContext); // count refs to the device context. ! 742: ! 743: *Address = pAddress; // return the address. ! 744: return STATUS_SUCCESS; // not finished yet. ! 745: } /* StCreateAddress */ ! 746: ! 747: ! 748: VOID ! 749: StRegisterAddress( ! 750: PTP_ADDRESS Address ! 751: ) ! 752: ! 753: /*++ ! 754: ! 755: Routine Description: ! 756: ! 757: This routine starts the registration process of the transport address ! 758: specified, if it has not already been started. ! 759: ! 760: Arguments: ! 761: ! 762: Address - Pointer to a transport address object to begin registering ! 763: on the network. ! 764: ! 765: Return Value: ! 766: ! 767: NTSTATUS - status of operation. ! 768: ! 769: --*/ ! 770: ! 771: { ! 772: KIRQL oldirql; ! 773: PLIST_ENTRY p; ! 774: PIRP irp; ! 775: PTP_ADDRESS_FILE addressFile; ! 776: ! 777: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 778: if (!(Address->Flags & ADDRESS_FLAGS_NEEDS_REG)) { ! 779: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 780: ! 781: return; ! 782: } ! 783: ! 784: Address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG; ! 785: Address->Flags |= ADDRESS_FLAGS_REGISTERING; ! 786: ! 787: // ! 788: // Keep a reference on this address until the registration process ! 789: // completes or is aborted. It will be aborted in UFRAMES.C, in ! 790: // either the NAME_IN_CONFLICT or ADD_NAME_RESPONSE frame handlers. ! 791: // ! 792: ! 793: StReferenceAddress ("start registration", Address); ! 794: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 795: ! 796: // ! 797: // Normally we would add the name on the network, then ! 798: // do the following in our timeout logic, but for ST ! 799: // we assume that all names are OK. ! 800: // ! 801: ! 802: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 803: Address->Flags &= ~ADDRESS_FLAGS_REGISTERING; ! 804: ! 805: p = Address->AddressFileDatabase.Flink; ! 806: ! 807: while (p != &Address->AddressFileDatabase) { ! 808: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 809: p = p->Flink; ! 810: ! 811: if (addressFile->Irp != NULL) { ! 812: irp = addressFile->Irp; ! 813: addressFile->Irp = NULL; ! 814: addressFile->State = ADDRESSFILE_STATE_OPEN; ! 815: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 816: irp->IoStatus.Information = 0; ! 817: irp->IoStatus.Status = STATUS_SUCCESS; ! 818: ! 819: IoCompleteRequest (irp, IO_NETWORK_INCREMENT); ! 820: ! 821: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 822: } ! 823: ! 824: } ! 825: ! 826: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 827: ! 828: // ! 829: // Dereference the address if we're all done. ! 830: // ! 831: ! 832: StDereferenceAddress ("Timer, registered", Address); ! 833: ! 834: } /* StRegisterAddress */ ! 835: ! 836: ! 837: NTSTATUS ! 838: StVerifyAddressObject ( ! 839: IN PTP_ADDRESS_FILE AddressFile ! 840: ) ! 841: ! 842: /*++ ! 843: ! 844: Routine Description: ! 845: ! 846: This routine is called to verify that the pointer given us in a file ! 847: object is in fact a valid address file object. We also verify that the ! 848: address object pointed to by it is a valid address object, and reference ! 849: it to keep it from disappearing while we use it. ! 850: ! 851: Arguments: ! 852: ! 853: AddressFile - potential pointer to a TP_ADDRESS_FILE object ! 854: ! 855: Return Value: ! 856: ! 857: STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise ! 858: ! 859: --*/ ! 860: ! 861: { ! 862: KIRQL oldirql; ! 863: NTSTATUS status = STATUS_SUCCESS; ! 864: PTP_ADDRESS address; ! 865: ! 866: // ! 867: // try to verify the address file signature. If the signature is valid, ! 868: // verify the address pointed to by it and get the address spinlock. ! 869: // check the address's state, and increment the reference count if it's ! 870: // ok to use it. Note that the only time we return an error for state is ! 871: // if the address is closing. ! 872: // ! 873: ! 874: try { ! 875: ! 876: if ((AddressFile->Size == sizeof (TP_ADDRESS_FILE)) && ! 877: (AddressFile->Type == ST_ADDRESSFILE_SIGNATURE) ) { ! 878: // (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) { ! 879: ! 880: address = AddressFile->Address; ! 881: ! 882: if ((address->Size == sizeof (TP_ADDRESS)) && ! 883: (address->Type == ST_ADDRESS_SIGNATURE) ) { ! 884: ! 885: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql); ! 886: ! 887: if ((address->Flags & ADDRESS_FLAGS_STOPPING) == 0) { ! 888: ! 889: StReferenceAddress ("verify", address); ! 890: ! 891: } else { ! 892: ! 893: StPrint1("StVerifyAddress: A %lx closing\n", address); ! 894: status = STATUS_INVALID_ADDRESS; ! 895: } ! 896: ! 897: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 898: ! 899: } else { ! 900: ! 901: StPrint1("StVerifyAddress: A %lx bad signature\n", address); ! 902: status = STATUS_INVALID_ADDRESS; ! 903: } ! 904: ! 905: } else { ! 906: ! 907: StPrint1("StVerifyAddress: AF %lx bad signature\n", AddressFile); ! 908: status = STATUS_INVALID_ADDRESS; ! 909: } ! 910: ! 911: } except(EXCEPTION_EXECUTE_HANDLER) { ! 912: ! 913: StPrint1("StVerifyAddress: AF %lx exception\n", address); ! 914: return GetExceptionCode(); ! 915: } ! 916: ! 917: return status; ! 918: ! 919: } ! 920: ! 921: NTSTATUS ! 922: StDestroyAddress( ! 923: IN PTP_ADDRESS Address ! 924: ) ! 925: ! 926: /*++ ! 927: ! 928: Routine Description: ! 929: ! 930: This routine destroys a transport address and removes all references ! 931: made by it to other objects in the transport. The address structure ! 932: is returned to nonpaged system pool or our lookaside list. It is assumed ! 933: that the caller has already removed all addressfile structures associated ! 934: with this address. ! 935: ! 936: This routine is only called by StDerefAddress. The reason for ! 937: this is that there may be multiple streams of execution which are ! 938: simultaneously referencing the same address object, and it should ! 939: not be deleted out from under an interested stream of execution. ! 940: ! 941: Arguments: ! 942: ! 943: Address - Pointer to a transport address structure to be destroyed. ! 944: ! 945: Return Value: ! 946: ! 947: NTSTATUS - status of operation. ! 948: ! 949: --*/ ! 950: ! 951: { ! 952: KIRQL oldirql; ! 953: PDEVICE_CONTEXT DeviceContext; ! 954: ! 955: DeviceContext = Address->Provider; ! 956: ! 957: SeDeassignSecurity (&Address->SecurityDescriptor); ! 958: ! 959: // ! 960: // Delink this address from its associated device context's address ! 961: // database. To do this we must spin lock on the device context object, ! 962: // not on the address. ! 963: // ! 964: ! 965: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 966: ! 967: RemoveEntryList (&Address->Linkage); ! 968: ! 969: // ! 970: // Now we can deallocate the transport address object. ! 971: // ! 972: ! 973: DeviceContext->AddressTotal += DeviceContext->AddressInUse; ! 974: ++DeviceContext->AddressSamples; ! 975: --DeviceContext->AddressInUse; ! 976: ! 977: if ((DeviceContext->AddressAllocated - DeviceContext->AddressInUse) > ! 978: DeviceContext->AddressInitAllocated) { ! 979: StDeallocateAddress (DeviceContext, Address); ! 980: } else { ! 981: InsertTailList (&DeviceContext->AddressPool, &Address->Linkage); ! 982: } ! 983: ! 984: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 985: StDereferenceDeviceContext ("Destroy Address", DeviceContext); // just housekeeping. ! 986: ! 987: return STATUS_SUCCESS; ! 988: } /* StDestroyAddress */ ! 989: ! 990: ! 991: VOID ! 992: StRefAddress( ! 993: IN PTP_ADDRESS Address ! 994: ) ! 995: ! 996: /*++ ! 997: ! 998: Routine Description: ! 999: ! 1000: This routine increments the reference count on a transport address. ! 1001: ! 1002: Arguments: ! 1003: ! 1004: Address - Pointer to a transport address object. ! 1005: ! 1006: Return Value: ! 1007: ! 1008: none. ! 1009: ! 1010: --*/ ! 1011: ! 1012: { ! 1013: ! 1014: ASSERT (Address->ReferenceCount > 0); // not perfect, but... ! 1015: ! 1016: (VOID)ExInterlockedIncrementLong ( ! 1017: &Address->ReferenceCount, ! 1018: &Address->Provider->Interlock); ! 1019: ! 1020: } /* StRefAddress */ ! 1021: ! 1022: ! 1023: VOID ! 1024: StDerefAddress( ! 1025: IN PTP_ADDRESS Address ! 1026: ) ! 1027: ! 1028: /*++ ! 1029: ! 1030: Routine Description: ! 1031: ! 1032: This routine dereferences a transport address by decrementing the ! 1033: reference count contained in the structure. If, after being ! 1034: decremented, the reference count is zero, then this routine calls ! 1035: StDestroyAddress to remove it from the system. ! 1036: ! 1037: Arguments: ! 1038: ! 1039: Address - Pointer to a transport address object. ! 1040: ! 1041: Return Value: ! 1042: ! 1043: none. ! 1044: ! 1045: --*/ ! 1046: ! 1047: { ! 1048: INTERLOCKED_RESULT result; ! 1049: ! 1050: result = ExInterlockedDecrementLong ( ! 1051: &Address->ReferenceCount, ! 1052: &Address->Provider->Interlock); ! 1053: ! 1054: // ! 1055: // If we have deleted all references to this address, then we can ! 1056: // destroy the object. It is okay to have already released the spin ! 1057: // lock at this point because there is no possible way that another ! 1058: // stream of execution has access to the address any longer. ! 1059: // ! 1060: ! 1061: ASSERT (result != ResultNegative); ! 1062: ! 1063: if (result == ResultZero) { ! 1064: StDestroyAddress (Address); ! 1065: } ! 1066: } /* StDerefAddress */ ! 1067: ! 1068: ! 1069: ! 1070: VOID ! 1071: StAllocateAddressFile( ! 1072: IN PDEVICE_CONTEXT DeviceContext, ! 1073: OUT PTP_ADDRESS_FILE *TransportAddressFile ! 1074: ) ! 1075: ! 1076: /*++ ! 1077: ! 1078: Routine Description: ! 1079: ! 1080: This routine allocates storage for an address file. Some ! 1081: minimal initialization is done on the object. ! 1082: ! 1083: NOTE: This routine is called with the device context spinlock ! 1084: held, or at such a time as synchronization is unnecessary. ! 1085: ! 1086: Arguments: ! 1087: ! 1088: DeviceContext - Pointer to the device context (which is really just ! 1089: the device object with its extension) to be associated with the ! 1090: address. ! 1091: ! 1092: TransportAddressFile - Pointer to a place where this routine will return ! 1093: a pointer to a transport address file structure. It returns NULL if no ! 1094: storage can be allocated. ! 1095: ! 1096: Return Value: ! 1097: ! 1098: None. ! 1099: ! 1100: --*/ ! 1101: ! 1102: { ! 1103: ! 1104: PTP_ADDRESS_FILE AddressFile; ! 1105: ! 1106: if ((DeviceContext->MemoryLimit != 0) && ! 1107: ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS_FILE)) > ! 1108: DeviceContext->MemoryLimit)) { ! 1109: PANIC("ST: Could not allocate address file: limit\n"); ! 1110: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 102); ! 1111: *TransportAddressFile = NULL; ! 1112: return; ! 1113: } ! 1114: ! 1115: AddressFile = (PTP_ADDRESS_FILE)ExAllocatePool (NonPagedPool, sizeof (TP_ADDRESS_FILE)); ! 1116: if (AddressFile == NULL) { ! 1117: PANIC("ST: Could not allocate address file: no pool\n"); ! 1118: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 202); ! 1119: *TransportAddressFile = NULL; ! 1120: return; ! 1121: } ! 1122: RtlZeroMemory (AddressFile, sizeof(TP_ADDRESS_FILE)); ! 1123: ! 1124: DeviceContext->MemoryUsage += sizeof(TP_ADDRESS_FILE); ! 1125: ++DeviceContext->AddressFileAllocated; ! 1126: ! 1127: AddressFile->Type = ST_ADDRESSFILE_SIGNATURE; ! 1128: AddressFile->Size = sizeof (TP_ADDRESS_FILE); ! 1129: ! 1130: InitializeListHead (&AddressFile->ReceiveDatagramQueue); ! 1131: InitializeListHead (&AddressFile->ConnectionDatabase); ! 1132: ! 1133: *TransportAddressFile = AddressFile; ! 1134: ! 1135: } /* StAllocateAddressFile */ ! 1136: ! 1137: ! 1138: VOID ! 1139: StDeallocateAddressFile( ! 1140: IN PDEVICE_CONTEXT DeviceContext, ! 1141: IN PTP_ADDRESS_FILE TransportAddressFile ! 1142: ) ! 1143: ! 1144: /*++ ! 1145: ! 1146: Routine Description: ! 1147: ! 1148: This routine frees storage for an address file. ! 1149: ! 1150: NOTE: This routine is called with the device context spinlock ! 1151: held, or at such a time as synchronization is unnecessary. ! 1152: ! 1153: Arguments: ! 1154: ! 1155: DeviceContext - Pointer to the device context (which is really just ! 1156: the device object with its extension) to be associated with the ! 1157: address. ! 1158: ! 1159: TransportAddressFile - Pointer to a transport address file structure. ! 1160: ! 1161: Return Value: ! 1162: ! 1163: None. ! 1164: ! 1165: --*/ ! 1166: ! 1167: { ! 1168: ! 1169: ExFreePool (TransportAddressFile); ! 1170: --DeviceContext->AddressFileAllocated; ! 1171: DeviceContext->MemoryUsage -= sizeof(TP_ADDRESS_FILE); ! 1172: ! 1173: } /* StDeallocateAddressFile */ ! 1174: ! 1175: ! 1176: NTSTATUS ! 1177: StCreateAddressFile( ! 1178: IN PDEVICE_CONTEXT DeviceContext, ! 1179: OUT PTP_ADDRESS_FILE * AddressFile ! 1180: ) ! 1181: ! 1182: /*++ ! 1183: ! 1184: Routine Description: ! 1185: ! 1186: This routine creates an address file from the pool of ther ! 1187: specified device context. The reference count in the ! 1188: address is automatically set to 1. ! 1189: ! 1190: Arguments: ! 1191: ! 1192: DeviceContext - Pointer to the device context (which is really just ! 1193: the device object with its extension) to be associated with the ! 1194: address. ! 1195: ! 1196: AddressFile - Pointer to a place where this routine will return a pointer ! 1197: to a transport address file structure. ! 1198: ! 1199: Return Value: ! 1200: ! 1201: NTSTATUS - status of operation. ! 1202: ! 1203: --*/ ! 1204: ! 1205: { ! 1206: KIRQL oldirql; ! 1207: PLIST_ENTRY p; ! 1208: PTP_ADDRESS_FILE addressFile; ! 1209: ! 1210: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 1211: ! 1212: p = RemoveHeadList (&DeviceContext->AddressFilePool); ! 1213: if (p == &DeviceContext->AddressFilePool) { ! 1214: ! 1215: if ((DeviceContext->AddressFileMaxAllocated == 0) || ! 1216: (DeviceContext->AddressFileAllocated < DeviceContext->AddressFileMaxAllocated)) { ! 1217: ! 1218: StAllocateAddressFile (DeviceContext, &addressFile); ! 1219: } else { ! 1220: ! 1221: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 402); ! 1222: addressFile = NULL; ! 1223: ! 1224: } ! 1225: ! 1226: if (addressFile == NULL) { ! 1227: ++DeviceContext->AddressFileExhausted; ! 1228: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 1229: PANIC ("StCreateConnection: Could not allocate address file object!\n"); ! 1230: return STATUS_INSUFFICIENT_RESOURCES; ! 1231: } ! 1232: ! 1233: } else { ! 1234: ! 1235: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 1236: ! 1237: } ! 1238: ! 1239: ++DeviceContext->AddressFileInUse; ! 1240: if (DeviceContext->AddressFileInUse > DeviceContext->AddressFileMaxInUse) { ! 1241: ++DeviceContext->AddressFileMaxInUse; ! 1242: } ! 1243: ! 1244: DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse; ! 1245: ++DeviceContext->AddressFileSamples; ! 1246: ! 1247: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 1248: ! 1249: ! 1250: InitializeListHead (&addressFile->ConnectionDatabase); ! 1251: addressFile->Address = NULL; ! 1252: addressFile->FileObject = NULL; ! 1253: addressFile->Provider = DeviceContext; ! 1254: addressFile->State = ADDRESSFILE_STATE_OPENING; ! 1255: addressFile->ConnectIndicationInProgress = FALSE; ! 1256: addressFile->ReferenceCount = 1; ! 1257: addressFile->CloseIrp = (PIRP)NULL; ! 1258: ! 1259: // ! 1260: // Initialize the request handlers. ! 1261: // ! 1262: ! 1263: addressFile->RegisteredConnectionHandler = FALSE; ! 1264: addressFile->ConnectionHandler = TdiDefaultConnectHandler; ! 1265: addressFile->ConnectionHandlerContext = NULL; ! 1266: addressFile->RegisteredDisconnectHandler = FALSE; ! 1267: addressFile->DisconnectHandler = TdiDefaultDisconnectHandler; ! 1268: addressFile->DisconnectHandlerContext = NULL; ! 1269: addressFile->RegisteredReceiveHandler = FALSE; ! 1270: addressFile->ReceiveHandler = TdiDefaultReceiveHandler; ! 1271: addressFile->ReceiveHandlerContext = NULL; ! 1272: addressFile->RegisteredReceiveDatagramHandler = FALSE; ! 1273: addressFile->ReceiveDatagramHandler = TdiDefaultRcvDatagramHandler; ! 1274: addressFile->ReceiveDatagramHandlerContext = NULL; ! 1275: addressFile->RegisteredExpeditedDataHandler = FALSE; ! 1276: addressFile->ExpeditedDataHandler = TdiDefaultRcvExpeditedHandler; ! 1277: addressFile->ExpeditedDataHandlerContext = NULL; ! 1278: addressFile->RegisteredErrorHandler = FALSE; ! 1279: addressFile->ErrorHandler = TdiDefaultErrorHandler; ! 1280: addressFile->ErrorHandlerContext = NULL; ! 1281: ! 1282: ! 1283: *AddressFile = addressFile; ! 1284: return STATUS_SUCCESS; ! 1285: ! 1286: } /* StCreateAddress */ ! 1287: ! 1288: ! 1289: NTSTATUS ! 1290: StDestroyAddressFile( ! 1291: IN PTP_ADDRESS_FILE AddressFile ! 1292: ) ! 1293: ! 1294: /*++ ! 1295: ! 1296: Routine Description: ! 1297: ! 1298: This routine destroys an address file and removes all references ! 1299: made by it to other objects in the transport. ! 1300: ! 1301: This routine is only called by StDereferenceAddressFile. The reason ! 1302: for this is that there may be multiple streams of execution which are ! 1303: simultaneously referencing the same address file object, and it should ! 1304: not be deleted out from under an interested stream of execution. ! 1305: ! 1306: Arguments: ! 1307: ! 1308: AddressFile Pointer to a transport address file structure to be destroyed. ! 1309: ! 1310: Return Value: ! 1311: ! 1312: NTSTATUS - status of operation. ! 1313: ! 1314: --*/ ! 1315: ! 1316: { ! 1317: KIRQL oldirql, oldirql1; ! 1318: PTP_ADDRESS address; ! 1319: PDEVICE_CONTEXT DeviceContext; ! 1320: PIRP CloseIrp; ! 1321: ! 1322: ! 1323: address = AddressFile->Address; ! 1324: DeviceContext = AddressFile->Provider; ! 1325: ! 1326: if (address) { ! 1327: ! 1328: // ! 1329: // This addressfile was associated with an address. ! 1330: // ! 1331: ! 1332: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql); ! 1333: ! 1334: // ! 1335: // remove this addressfile from the address list and disassociate it from ! 1336: // the file handle. ! 1337: // ! 1338: ! 1339: RemoveEntryList (&AddressFile->Linkage); ! 1340: InitializeListHead (&AddressFile->Linkage); ! 1341: ! 1342: if (address->AddressFileDatabase.Flink == &address->AddressFileDatabase) { ! 1343: ! 1344: // ! 1345: // This is the last open of this address, it will close ! 1346: // due to normal dereferencing but we have to set the ! 1347: // CLOSING flag too to stop further references. ! 1348: // ! 1349: ! 1350: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1); ! 1351: address->Flags |= ADDRESS_FLAGS_STOPPING; ! 1352: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1); ! 1353: ! 1354: } ! 1355: ! 1356: AddressFile->Address = NULL; ! 1357: ! 1358: AddressFile->FileObject->FsContext = NULL; ! 1359: AddressFile->FileObject->FsContext2 = NULL; ! 1360: ! 1361: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql); ! 1362: ! 1363: // ! 1364: // We will already have been removed from the ShareAccess ! 1365: // of the owning address. ! 1366: // ! 1367: ! 1368: // ! 1369: // Now dereference the owning address. ! 1370: // ! 1371: ! 1372: StDereferenceAddress ("Close", address); // remove the creation hold ! 1373: ! 1374: } ! 1375: ! 1376: // ! 1377: // Save this for later completion. ! 1378: // ! 1379: ! 1380: CloseIrp = AddressFile->CloseIrp; ! 1381: ! 1382: // ! 1383: // return the addressFile to the pool of address files ! 1384: // ! 1385: ! 1386: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 1387: ! 1388: DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse; ! 1389: ++DeviceContext->AddressFileSamples; ! 1390: --DeviceContext->AddressFileInUse; ! 1391: ! 1392: if ((DeviceContext->AddressFileAllocated - DeviceContext->AddressFileInUse) > ! 1393: DeviceContext->AddressFileInitAllocated) { ! 1394: StDeallocateAddressFile (DeviceContext, AddressFile); ! 1395: } else { ! 1396: InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage); ! 1397: } ! 1398: ! 1399: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 1400: ! 1401: ! 1402: if (CloseIrp != (PIRP)NULL) { ! 1403: CloseIrp->IoStatus.Information = 0; ! 1404: CloseIrp->IoStatus.Status = STATUS_SUCCESS; ! 1405: IoCompleteRequest (CloseIrp, IO_NETWORK_INCREMENT); ! 1406: } ! 1407: ! 1408: return STATUS_SUCCESS; ! 1409: ! 1410: } /* StDestroyAddress */ ! 1411: ! 1412: ! 1413: VOID ! 1414: StReferenceAddressFile( ! 1415: IN PTP_ADDRESS_FILE AddressFile ! 1416: ) ! 1417: ! 1418: /*++ ! 1419: ! 1420: Routine Description: ! 1421: ! 1422: This routine increments the reference count on an address file. ! 1423: ! 1424: Arguments: ! 1425: ! 1426: AddressFile - Pointer to a transport address file object. ! 1427: ! 1428: Return Value: ! 1429: ! 1430: none. ! 1431: ! 1432: --*/ ! 1433: ! 1434: { ! 1435: ! 1436: ASSERT (AddressFile->ReferenceCount > 0); // not perfect, but... ! 1437: ! 1438: (VOID)ExInterlockedIncrementLong ( ! 1439: &AddressFile->ReferenceCount, ! 1440: &AddressFile->Provider->Interlock); ! 1441: ! 1442: } /* StReferenceAddressFile */ ! 1443: ! 1444: ! 1445: VOID ! 1446: StDereferenceAddressFile( ! 1447: IN PTP_ADDRESS_FILE AddressFile ! 1448: ) ! 1449: ! 1450: /*++ ! 1451: ! 1452: Routine Description: ! 1453: ! 1454: This routine dereferences an address file by decrementing the ! 1455: reference count contained in the structure. If, after being ! 1456: decremented, the reference count is zero, then this routine calls ! 1457: StDestroyAddressFile to remove it from the system. ! 1458: ! 1459: Arguments: ! 1460: ! 1461: AddressFile - Pointer to a transport address file object. ! 1462: ! 1463: Return Value: ! 1464: ! 1465: none. ! 1466: ! 1467: --*/ ! 1468: ! 1469: { ! 1470: INTERLOCKED_RESULT result; ! 1471: ! 1472: result = ExInterlockedDecrementLong ( ! 1473: &AddressFile->ReferenceCount, ! 1474: &AddressFile->Provider->Interlock); ! 1475: ! 1476: // ! 1477: // If we have deleted all references to this address file, then we can ! 1478: // destroy the object. It is okay to have already released the spin ! 1479: // lock at this point because there is no possible way that another ! 1480: // stream of execution has access to the address any longer. ! 1481: // ! 1482: ! 1483: ASSERT (result != ResultNegative); ! 1484: ! 1485: if (result == ResultZero) { ! 1486: StDestroyAddressFile (AddressFile); ! 1487: } ! 1488: } /* StDerefAddressFile */ ! 1489: ! 1490: ! 1491: PTP_ADDRESS ! 1492: StLookupAddress( ! 1493: IN PDEVICE_CONTEXT DeviceContext, ! 1494: IN PST_NETBIOS_ADDRESS NetworkName ! 1495: ) ! 1496: ! 1497: /*++ ! 1498: ! 1499: Routine Description: ! 1500: ! 1501: This routine scans the transport addresses defined for the given ! 1502: device context and compares them with the specified NETWORK ! 1503: NAME values. If an exact match is found, then a pointer to the ! 1504: TP_ADDRESS object is returned, and as a side effect, the reference ! 1505: count to the address object is incremented. If the address is not ! 1506: found, then NULL is returned. ! 1507: ! 1508: NOTE: This routine must be called with the DeviceContext ! 1509: spinlock held. ! 1510: ! 1511: Arguments: ! 1512: ! 1513: DeviceContext - Pointer to the device object and its extension. ! 1514: NetworkName - Pointer to an ST_NETBIOS_ADDRESS structure containing the ! 1515: network name. ! 1516: ! 1517: Return Value: ! 1518: ! 1519: Pointer to the TP_ADDRESS object found, or NULL if not found. ! 1520: ! 1521: --*/ ! 1522: ! 1523: { ! 1524: PTP_ADDRESS address; ! 1525: PLIST_ENTRY p; ! 1526: ULONG i; ! 1527: ! 1528: ! 1529: p = DeviceContext->AddressDatabase.Flink; ! 1530: ! 1531: for (p = DeviceContext->AddressDatabase.Flink; ! 1532: p != &DeviceContext->AddressDatabase; ! 1533: p = p->Flink) { ! 1534: ! 1535: address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage); ! 1536: ! 1537: if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) { ! 1538: continue; ! 1539: } ! 1540: ! 1541: // ! 1542: // If the network name is specified and the network names don't match, ! 1543: // then the addresses don't match. ! 1544: // ! 1545: ! 1546: i = NETBIOS_NAME_LENGTH; // length of a Netbios name ! 1547: ! 1548: if (address->NetworkName != NULL) { ! 1549: if (NetworkName != NULL) { ! 1550: if (RtlCompareMemory ( ! 1551: address->NetworkName->NetbiosName, ! 1552: NetworkName->NetbiosName, ! 1553: i) < i) { ! 1554: continue; ! 1555: } ! 1556: } else { ! 1557: continue; ! 1558: } ! 1559: ! 1560: } else { ! 1561: if (NetworkName != NULL) { ! 1562: continue; ! 1563: } ! 1564: } ! 1565: ! 1566: // ! 1567: // We found the match. Bump the reference count on the address, and ! 1568: // return a pointer to the address object for the caller to use. ! 1569: // ! 1570: ! 1571: StReferenceAddress ("lookup", address); ! 1572: return address; ! 1573: ! 1574: } /* for */ ! 1575: ! 1576: // ! 1577: // The specified address was not found. ! 1578: // ! 1579: ! 1580: return NULL; ! 1581: ! 1582: } /* StLookupAddress */ ! 1583: ! 1584: ! 1585: PTP_CONNECTION ! 1586: StLookupRemoteName( ! 1587: IN PTP_ADDRESS Address, ! 1588: IN PUCHAR RemoteName ! 1589: ) ! 1590: ! 1591: /*++ ! 1592: ! 1593: Routine Description: ! 1594: ! 1595: This routine scans the connections associated with an ! 1596: address, and determines if there is an connection ! 1597: associated with the specific remote address. ! 1598: ! 1599: Arguments: ! 1600: ! 1601: Address - Pointer to the address. ! 1602: ! 1603: RemoteName - The 16-character Netbios name of the remote. ! 1604: ! 1605: Return Value: ! 1606: ! 1607: The connection if one is found, NULL otherwise. ! 1608: ! 1609: --*/ ! 1610: ! 1611: { ! 1612: KIRQL oldirql, oldirql1; ! 1613: PLIST_ENTRY p; ! 1614: PTP_CONNECTION connection; ! 1615: ! 1616: ! 1617: // ! 1618: // Hold the spinlock so the connection database doesn't ! 1619: // change. ! 1620: // ! 1621: ! 1622: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 1623: ! 1624: for (p=Address->ConnectionDatabase.Flink; ! 1625: p != &Address->ConnectionDatabase; ! 1626: p=p->Flink) { ! 1627: ! 1628: connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressList); ! 1629: ! 1630: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql1); ! 1631: ! 1632: if (((connection->Flags2 & CONNECTION_FLAGS2_REMOTE_VALID) != 0) && ! 1633: ((connection->Flags & CONNECTION_FLAGS_READY) != 0)) { ! 1634: ! 1635: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1); ! 1636: ! 1637: // ! 1638: // If the remote names match, then return the ! 1639: // connection. ! 1640: // ! 1641: ! 1642: if (RtlCompareMemory(RemoteName, connection->RemoteName, NETBIOS_NAME_LENGTH) == ! 1643: NETBIOS_NAME_LENGTH) { ! 1644: ! 1645: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1646: StReferenceConnection ("Lookup found", connection); ! 1647: return connection; ! 1648: ! 1649: } ! 1650: ! 1651: } else { ! 1652: ! 1653: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1); ! 1654: ! 1655: } ! 1656: ! 1657: } ! 1658: ! 1659: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1660: ! 1661: return (PTP_CONNECTION)NULL; ! 1662: ! 1663: } ! 1664: ! 1665: ! 1666: BOOLEAN ! 1667: StMatchNetbiosAddress( ! 1668: IN PTP_ADDRESS Address, ! 1669: IN PUCHAR NetBIOSName ! 1670: ) ! 1671: ! 1672: /*++ ! 1673: ! 1674: Routine Description: ! 1675: ! 1676: This routine is called to compare the addressing information in a ! 1677: TP_ADDRESS object with the 16-byte NetBIOS name in a frame header. ! 1678: If they match, then this routine returns TRUE, else it returns FALSE. ! 1679: ! 1680: Arguments: ! 1681: ! 1682: Address - Pointer to a TP_ADDRESS object. ! 1683: ! 1684: NetBIOSName - Pointer to a 16-byte character string (non-terminated), ! 1685: or NULL if this is a received broadcast address. ! 1686: ! 1687: Return Value: ! 1688: ! 1689: BOOLEAN, TRUE if match, FALSE if not. ! 1690: ! 1691: --*/ ! 1692: ! 1693: { ! 1694: ! 1695: PULONG AddressNamePointer; ! 1696: ULONG UNALIGNED * NetbiosNamePointer; ! 1697: ! 1698: // ! 1699: // If this is address is the Netbios broadcast address, the comparison ! 1700: // succeeds only if the passed in address is also NULL. ! 1701: // ! 1702: ! 1703: if (Address->NetworkName == NULL) { ! 1704: ! 1705: if (NetBIOSName == NULL) { ! 1706: return TRUE; ! 1707: } else { ! 1708: return FALSE; ! 1709: } ! 1710: ! 1711: } else if (NetBIOSName == NULL) { ! 1712: ! 1713: return FALSE; ! 1714: ! 1715: } ! 1716: ! 1717: // ! 1718: // Do a quick check of the first character in the names. ! 1719: // ! 1720: ! 1721: if (Address->NetworkName->NetbiosName[0] != NetBIOSName[0]) { ! 1722: return FALSE; ! 1723: } ! 1724: ! 1725: // ! 1726: // Now compare the 16-character Netbios names as ULONGs ! 1727: // for speed. We know the one stored in the address ! 1728: // structure is aligned. ! 1729: // ! 1730: ! 1731: AddressNamePointer = (PULONG)(Address->NetworkName->NetbiosName); ! 1732: NetbiosNamePointer = (ULONG UNALIGNED *)NetBIOSName; ! 1733: ! 1734: if ((AddressNamePointer[0] == NetbiosNamePointer[0]) && ! 1735: (AddressNamePointer[1] == NetbiosNamePointer[1]) && ! 1736: (AddressNamePointer[2] == NetbiosNamePointer[2]) && ! 1737: (AddressNamePointer[3] == NetbiosNamePointer[3])) { ! 1738: return TRUE; ! 1739: } else { ! 1740: return FALSE; ! 1741: } ! 1742: ! 1743: } /* StMatchNetbiosAddress */ ! 1744: ! 1745: ! 1746: VOID ! 1747: StStopAddress( ! 1748: IN PTP_ADDRESS Address ! 1749: ) ! 1750: ! 1751: /*++ ! 1752: ! 1753: Routine Description: ! 1754: ! 1755: This routine is called to terminate all activity on an address and ! 1756: destroy the object. This is done in a graceful manner; i.e., all ! 1757: outstanding addressfiles are removed from the addressfile database, and ! 1758: all their activities are shut down. ! 1759: ! 1760: Arguments: ! 1761: ! 1762: Address - Pointer to a TP_ADDRESS object. ! 1763: ! 1764: Return Value: ! 1765: ! 1766: none. ! 1767: ! 1768: --*/ ! 1769: ! 1770: { ! 1771: KIRQL oldirql, oldirql1; ! 1772: PTP_ADDRESS_FILE addressFile; ! 1773: PLIST_ENTRY p; ! 1774: PDEVICE_CONTEXT DeviceContext; ! 1775: ! 1776: DeviceContext = Address->Provider; ! 1777: ! 1778: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 1779: ! 1780: // ! 1781: // If we're already stopping this address, then don't try to do it again. ! 1782: // ! 1783: ! 1784: if (!(Address->Flags & ADDRESS_FLAGS_STOPPING)) { ! 1785: ! 1786: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1); ! 1787: Address->Flags |= ADDRESS_FLAGS_STOPPING; ! 1788: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1); ! 1789: ! 1790: // ! 1791: // Run down all addressfiles on this address. This ! 1792: // will leave the address with no references ! 1793: // potentially, but we don't need a temp one ! 1794: // because every place that calls StStopAddress ! 1795: // already has a temp reference. ! 1796: // ! 1797: ! 1798: while (!IsListEmpty (&Address->AddressFileDatabase)) { ! 1799: p = RemoveHeadList (&Address->AddressFileDatabase); ! 1800: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); ! 1801: ! 1802: addressFile->Address = NULL; ! 1803: addressFile->FileObject->FsContext = NULL; ! 1804: addressFile->FileObject->FsContext2 = NULL; ! 1805: ! 1806: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1807: ! 1808: // ! 1809: // Run-down this addressFile without the lock on. ! 1810: // We don't care about removing ourselves from ! 1811: // the address' ShareAccess because we are ! 1812: // tearing it down. ! 1813: // ! 1814: ! 1815: StStopAddressFile (addressFile, Address); ! 1816: ! 1817: // ! 1818: // return the addressFile to the pool of address files ! 1819: // ! 1820: ! 1821: StDereferenceAddressFile (addressFile); ! 1822: ! 1823: StDereferenceAddress ("stop address", Address); ! 1824: ! 1825: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 1826: } ! 1827: ! 1828: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1829: return; ! 1830: ! 1831: } ! 1832: ! 1833: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1834: } /* StStopAddress */ ! 1835: ! 1836: ! 1837: NTSTATUS ! 1838: StStopAddressFile( ! 1839: IN PTP_ADDRESS_FILE AddressFile, ! 1840: IN PTP_ADDRESS Address ! 1841: ) ! 1842: ! 1843: /*++ ! 1844: ! 1845: Routine Description: ! 1846: ! 1847: This routine is called to terminate all activity on an AddressFile and ! 1848: destroy the object. We remove every connection and datagram associated ! 1849: with this addressfile from the address database and terminate their ! 1850: activity. Then, if there are no other outstanding addressfiles open on ! 1851: this address, the address will go away. ! 1852: ! 1853: Arguments: ! 1854: ! 1855: AddressFile - pointer to the addressFile to be stopped ! 1856: ! 1857: Address - the owning address for this addressFile (we do not depend upon ! 1858: the pointer in the addressFile because we want this routine to be safe) ! 1859: ! 1860: Return Value: ! 1861: ! 1862: STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not ! 1863: point to a real address. ! 1864: ! 1865: --*/ ! 1866: ! 1867: { ! 1868: KIRQL oldirql, oldirql1; ! 1869: LIST_ENTRY localList; ! 1870: PLIST_ENTRY p, pFlink; ! 1871: PTP_REQUEST request; ! 1872: PTP_CONNECTION connection; ! 1873: ! 1874: ! 1875: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 1876: ! 1877: if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) { ! 1878: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1879: return STATUS_SUCCESS; ! 1880: } ! 1881: ! 1882: ! 1883: AddressFile->State = ADDRESSFILE_STATE_CLOSING; ! 1884: InitializeListHead (&localList); ! 1885: ! 1886: // ! 1887: // Run down all connections on this addressfile, and ! 1888: // preform the equivalent of StDestroyAssociation ! 1889: // on them. ! 1890: // ! 1891: ! 1892: while (!IsListEmpty (&AddressFile->ConnectionDatabase)) { ! 1893: p = RemoveHeadList (&AddressFile->ConnectionDatabase); ! 1894: connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressFileList); ! 1895: ! 1896: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql1); ! 1897: ! 1898: if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) == 0) { ! 1899: ! 1900: // ! 1901: // It is in the process of being disassociated already. ! 1902: // ! 1903: ! 1904: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1); ! 1905: continue; ! 1906: } ! 1907: ! 1908: connection->Flags2 &= ~CONNECTION_FLAGS2_ASSOCIATED; ! 1909: connection->Flags |= CONNECTION_FLAGS_DESTROY; // BUGBUG: Is this needed? ! 1910: RemoveEntryList (&connection->AddressList); ! 1911: InitializeListHead (&connection->AddressList); ! 1912: InitializeListHead (&connection->AddressFileList); ! 1913: connection->AddressFile = NULL; ! 1914: ! 1915: StReferenceConnection ("Close AddressFile", connection); ! 1916: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1); ! 1917: ! 1918: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1919: ! 1920: StStopConnection (connection, STATUS_LOCAL_DISCONNECT); ! 1921: StDereferenceConnection ("Close AddressFile", connection); ! 1922: ! 1923: StDereferenceAddress ("Destroy association", Address); ! 1924: ! 1925: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 1926: } ! 1927: ! 1928: // ! 1929: // now remove all of the datagrams owned by this addressfile ! 1930: // ! 1931: ! 1932: for (p = Address->SendDatagramQueue.Flink; ! 1933: p != &Address->SendDatagramQueue; ! 1934: p = pFlink ) { ! 1935: ! 1936: pFlink = p->Flink; ! 1937: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 1938: if ((PTP_ADDRESS_FILE)(request->Owner) == AddressFile) { ! 1939: RemoveEntryList (p); ! 1940: InitializeListHead (p); ! 1941: InsertTailList (&localList, p); ! 1942: } ! 1943: ! 1944: } ! 1945: ! 1946: for (p = AddressFile->ReceiveDatagramQueue.Flink; ! 1947: p != &AddressFile->ReceiveDatagramQueue; ! 1948: p = pFlink ) { ! 1949: ! 1950: pFlink = p->Flink; ! 1951: RemoveEntryList (p); ! 1952: InitializeListHead (p); ! 1953: InsertTailList (&localList, p); ! 1954: } ! 1955: ! 1956: // ! 1957: // and finally, signal failure if the address file was waiting for a ! 1958: // registration to complete (Irp is set to NULL when this succeeds). ! 1959: // ! 1960: ! 1961: if (AddressFile->Irp != NULL) { ! 1962: PIRP irp=AddressFile->Irp; ! 1963: AddressFile->Irp = NULL; ! 1964: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1965: irp->IoStatus.Information = 0; ! 1966: irp->IoStatus.Status = STATUS_DUPLICATE_NAME; ! 1967: ! 1968: IoCompleteRequest (irp, IO_NETWORK_INCREMENT); ! 1969: ! 1970: } else { ! 1971: ! 1972: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 1973: } ! 1974: ! 1975: // ! 1976: // cancel all the datagrams on this address file ! 1977: // ! 1978: ! 1979: while (!IsListEmpty (&localList)) { ! 1980: ! 1981: p = RemoveHeadList (&localList); ! 1982: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 1983: ! 1984: StCompleteRequest (request, STATUS_NETWORK_NAME_DELETED, 0); ! 1985: ! 1986: } ! 1987: ! 1988: ! 1989: } /* StStopAddressFile */ ! 1990: ! 1991: ! 1992: NTSTATUS ! 1993: StCloseAddress( ! 1994: IN PDEVICE_OBJECT DeviceObject, ! 1995: IN PIRP Irp, ! 1996: IN PIO_STACK_LOCATION IrpSp ! 1997: ) ! 1998: ! 1999: /*++ ! 2000: ! 2001: Routine Description: ! 2002: ! 2003: This routine is called to close the addressfile pointed to by a file ! 2004: object. If there is any activity to be run down, we will run it down ! 2005: before we terminate the addressfile. We remove every connection and ! 2006: datagram associated with this addressfile from the address database ! 2007: and terminate their activity. Then, if there are no other outstanding ! 2008: addressfiles open on this address, the address will go away. ! 2009: ! 2010: Arguments: ! 2011: ! 2012: Irp - the Irp Address - Pointer to a TP_ADDRESS object. ! 2013: ! 2014: Return Value: ! 2015: ! 2016: STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not ! 2017: point to a real address. ! 2018: ! 2019: --*/ ! 2020: ! 2021: { ! 2022: PTP_ADDRESS address; ! 2023: PTP_ADDRESS_FILE addressFile; ! 2024: ! 2025: addressFile = IrpSp->FileObject->FsContext; ! 2026: addressFile->CloseIrp = Irp; ! 2027: ! 2028: // ! 2029: // We assume that addressFile has already been verified ! 2030: // at this point. ! 2031: // ! 2032: ! 2033: address = addressFile->Address; ! 2034: ASSERT (address); ! 2035: ! 2036: // ! 2037: // Remove us from the access info for this address. ! 2038: // ! 2039: ! 2040: ExAcquireResourceExclusive (&addressFile->Provider->AddressResource, TRUE); ! 2041: IoRemoveShareAccess (addressFile->FileObject, &address->ShareAccess); ! 2042: ExReleaseResource (&addressFile->Provider->AddressResource); ! 2043: ! 2044: ! 2045: StStopAddressFile (addressFile, address); ! 2046: StDereferenceAddressFile (addressFile); ! 2047: ! 2048: // ! 2049: // This removes a reference added by our caller. ! 2050: // ! 2051: ! 2052: StDereferenceAddress ("IRP_MJ_CLOSE", address); ! 2053: ! 2054: return STATUS_PENDING; ! 2055: ! 2056: } /* StCloseAddress */ ! 2057: ! 2058: ! 2059: NTSTATUS ! 2060: StSendDatagramsOnAddress( ! 2061: PTP_ADDRESS Address ! 2062: ) ! 2063: ! 2064: /*++ ! 2065: ! 2066: Routine Description: ! 2067: ! 2068: This routine attempts to acquire a hold on the SendDatagramQueue of ! 2069: the specified address, prepare the next datagram for shipment, and ! 2070: call StSendUIMdlFrame to actually do the work. When StSendUIMdlFrame ! 2071: is finished, it will cause an I/O completion routine in UFRAMES.C to ! 2072: be called, at which time this routine is called again to handle the ! 2073: next datagram in the pipeline. ! 2074: ! 2075: Arguments: ! 2076: ! 2077: Address - a pointer to the address object to send the datagram on. ! 2078: ! 2079: Return Value: ! 2080: ! 2081: NTSTATUS - status of operation. ! 2082: ! 2083: --*/ ! 2084: ! 2085: { ! 2086: KIRQL oldirql; ! 2087: PLIST_ENTRY p; ! 2088: PTP_REQUEST request; ! 2089: PTA_NETBIOS_ADDRESS remoteTA; ! 2090: PIO_STACK_LOCATION irpSp; ! 2091: PDEVICE_CONTEXT DeviceContext; ! 2092: PUCHAR SourceRouting; ! 2093: UINT SourceRoutingLength; ! 2094: UINT HeaderLength; ! 2095: PST_HEADER StHeader; ! 2096: PSEND_PACKET_TAG SendTag; ! 2097: ! 2098: DeviceContext = Address->Provider; ! 2099: ! 2100: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql); ! 2101: StReferenceAddress ("Send datagram", Address); // keep it around ! 2102: ! 2103: if (!(Address->Flags & ADDRESS_FLAGS_SEND_IN_PROGRESS)) { ! 2104: ! 2105: // ! 2106: // If the queue is empty, don't do anything. ! 2107: // ! 2108: ! 2109: if (IsListEmpty (&Address->SendDatagramQueue)) { ! 2110: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 2111: StDereferenceAddress ("Queue empty", Address); ! 2112: return STATUS_SUCCESS; ! 2113: } ! 2114: ! 2115: // ! 2116: // Mark the address's send datagram queue as held so that the ! 2117: // MDL and ST header will not be used for two requests at the ! 2118: // same time. ! 2119: // ! 2120: ! 2121: Address->Flags |= ADDRESS_FLAGS_SEND_IN_PROGRESS; ! 2122: ! 2123: // ! 2124: // We own the hold, and we've released the spinlock. So pick off the ! 2125: // next datagram to be sent, and ship it. ! 2126: // ! 2127: ! 2128: p = Address->SendDatagramQueue.Flink; ! 2129: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 2130: ! 2131: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage); ! 2132: ! 2133: // ! 2134: // If there is no remote Address specified (the Address specified has ! 2135: // length 0), this is a broadcast datagram. If anything is specified, it ! 2136: // will be used as a netbios address. ! 2137: // ! 2138: ! 2139: irpSp = IoGetCurrentIrpStackLocation (request->IoRequestPacket); ! 2140: ! 2141: remoteTA = ((PTDI_REQUEST_KERNEL_SENDDG)(&irpSp->Parameters))-> ! 2142: SendDatagramInformation->RemoteAddress; ! 2143: ! 2144: // ! 2145: // Build the MAC header. DATAGRAM frames go out as ! 2146: // single-route source routing. ! 2147: // ! 2148: ! 2149: MacReturnSingleRouteSR( ! 2150: &DeviceContext->MacInfo, ! 2151: &SourceRouting, ! 2152: &SourceRoutingLength); ! 2153: ! 2154: MacConstructHeader ( ! 2155: &DeviceContext->MacInfo, ! 2156: Address->Packet->Header, ! 2157: DeviceContext->MulticastAddress.Address, ! 2158: DeviceContext->LocalAddress.Address, ! 2159: sizeof(ST_HEADER) + request->Buffer2Length, ! 2160: SourceRouting, ! 2161: SourceRoutingLength, ! 2162: &HeaderLength); ! 2163: ! 2164: // ! 2165: // Build the header: 'G', dest, source ! 2166: // ! 2167: ! 2168: StHeader = (PST_HEADER)(&Address->Packet->Header[HeaderLength]); ! 2169: ! 2170: StHeader->Signature = ST_SIGNATURE; ! 2171: StHeader->Command = ST_CMD_DATAGRAM; ! 2172: StHeader->Flags = 0; ! 2173: ! 2174: RtlCopyMemory (StHeader->Source, Address->NetworkName->NetbiosName, 16); ! 2175: ! 2176: if (remoteTA->Address[0].AddressLength == 0) { ! 2177: ! 2178: // ! 2179: // A broadcast datagram ! 2180: // ! 2181: ! 2182: RtlZeroMemory (StHeader->Destination, 16); ! 2183: StHeader->Flags |= ST_FLAGS_BROADCAST; ! 2184: ! 2185: } else { ! 2186: ! 2187: RtlCopyMemory (StHeader->Destination, remoteTA->Address[0].Address[0].NetbiosName, 16); ! 2188: ! 2189: } ! 2190: ! 2191: HeaderLength += sizeof(ST_HEADER); ! 2192: ! 2193: SendTag = (PSEND_PACKET_TAG)(Address->Packet->NdisPacket->ProtocolReserved); ! 2194: SendTag->Type = TYPE_G_FRAME; ! 2195: SendTag->Packet = Address->Packet; ! 2196: SendTag->Owner = (PVOID)Address; ! 2197: ! 2198: // ! 2199: // Update our statistics for this datagram. ! 2200: // ! 2201: ! 2202: ++DeviceContext->DatagramsSent; ! 2203: ADD_TO_LARGE_INTEGER( ! 2204: &DeviceContext->DatagramBytesSent, ! 2205: request->Buffer2Length, ! 2206: &DeviceContext->StatisticsSpinLock); ! 2207: ! 2208: ! 2209: // ! 2210: // Munge the packet length, append the data, and send it. ! 2211: // ! 2212: ! 2213: StSetNdisPacketLength(Address->Packet->NdisPacket, HeaderLength); ! 2214: ! 2215: if (request->Buffer2) { ! 2216: NdisChainBufferAtBack (Address->Packet->NdisPacket, (PNDIS_BUFFER)request->Buffer2); ! 2217: } ! 2218: ! 2219: (VOID)StSendAddressFrame ( ! 2220: Address); ! 2221: ! 2222: ! 2223: // ! 2224: // The hold will be released in the I/O completion handler. ! 2225: // At that time, if there is another outstanding datagram ! 2226: // to send, it will reset the hold and call this routine again. ! 2227: // ! 2228: ! 2229: ! 2230: } else { ! 2231: ! 2232: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql); ! 2233: } ! 2234: ! 2235: StDereferenceAddress ("Sent datagram", Address); // all done ! 2236: ! 2237: return STATUS_SUCCESS; ! 2238: ! 2239: } /* StSendDatagramsOnAddress */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.