Annotation of ntddk/src/network/tdi/address.c, revision 1.1.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.