Annotation of ntddk/src/network/tdi/address.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.