|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
domain.c
Abstract:
Code to manage primary and emulated networks.
Author:
Cliff Van Dyke (CliffV) 23-Jan-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Module specific globals
//
// Serialized by BowserTransportDatabaseResource
LIST_ENTRY BowserServicedDomains = {0};
//
// Local procedure forwards.
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, BowserInitializeDomains)
#pragma alloc_text(PAGE, BowserCreateDomain)
#pragma alloc_text(PAGE, BowserSetDomainName)
#pragma alloc_text(PAGE, BowserFindDomain)
#pragma alloc_text(PAGE, BowserDereferenceDomain)
#endif
VOID BowserInitializeDomains( VOID )
/*++
Routine Description:
Initialize domain.c.
Arguments:
None
Return Value:
None.
--*/ { PAGED_CODE(); //
// Initialize globals
//
InitializeListHead(&BowserServicedDomains); }
PDOMAIN_INFO BowserCreateDomain( PUNICODE_STRING DomainName, PUNICODE_STRING ComputerName )
/*++
Routine Description:
Find the existing domain definition or create a new domain to browse on.
Arguments:
DomainName - Name of the domain to browse on
ComputerName - emulated computer name for this domain.
Return Value:
NULL - No such domain exists
A pointer to the domain found/created. The found/created domain should be dereferenced using BowserDereferenceDomain.
--*/ { NTSTATUS Status;
PDOMAIN_INFO DomainInfo = NULL; ULONG OemComputerNameLength;
PAGED_CODE(); dlog(DPRT_DOMAIN, ("%wZ: BowserCreateDomain\n", DomainName));
try { ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
//
// If the domain already exists, use it.
//
DomainInfo = BowserFindDomain( DomainName );
if ( DomainInfo == NULL) {
//
// Allocate a structure describing the new domain.
//
DomainInfo = ALLOCATE_POOL(NonPagedPool, sizeof(DOMAIN_INFO), POOL_DOMAIN_INFO);
if ( DomainInfo == NULL ) { try_return( Status = STATUS_NO_MEMORY ); } RtlZeroMemory( DomainInfo, sizeof(DOMAIN_INFO) );
//
// Create an interim reference count for this domain.
//
// One for the caller.
//
// We don't increment the reference count for being in the global list since
// the domain info structure is merely a performance enchancements that lives
// only because it is referenced by a network.
//
DomainInfo->ReferenceCount = 1;
//
// Link the domain into the list of domains
//
// The primary domain is at the front of the list.
//
InsertTailList(&BowserServicedDomains, &DomainInfo->Next); }
//
// Copy the DomainName into the structure
//
Status = BowserSetDomainName( DomainInfo, DomainName );
if (!NT_SUCCESS(Status)) { try_return( Status ); }
//
// Copy the OEM Computer name into the structure.
//
if ( ComputerName->Length > CNLEN*sizeof(WCHAR) ) { try_return( Status = STATUS_INVALID_PARAMETER ); }
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemComputerNameBuffer, sizeof(DomainInfo->DomOemComputerNameBuffer)-1, &OemComputerNameLength, ComputerName->Buffer, ComputerName->Length );
if (!NT_SUCCESS(Status)) { try_return( Status ); }
DomainInfo->DomOemComputerNameBuffer[OemComputerNameLength] = '\0'; DomainInfo->DomOemComputerName.Buffer = DomainInfo->DomOemComputerNameBuffer; DomainInfo->DomOemComputerName.Length = (USHORT)OemComputerNameLength; DomainInfo->DomOemComputerName.MaximumLength = (USHORT)(OemComputerNameLength + 1);
//
// Copy the upcased Unicode Computer name into the structure.
//
DomainInfo->DomUnicodeComputerName.Buffer = DomainInfo->DomUnicodeComputerNameBuffer; DomainInfo->DomUnicodeComputerName.MaximumLength = sizeof(DomainInfo->DomUnicodeComputerNameBuffer);
Status = RtlOemStringToUnicodeString(&DomainInfo->DomUnicodeComputerName, &DomainInfo->DomOemComputerName, FALSE);
if (!NT_SUCCESS(Status)) { try_return( Status ); }
Status = STATUS_SUCCESS;
try_exit:NOTHING; } finally { if ( !NT_SUCCESS(Status) && DomainInfo != NULL ) { BowserDereferenceDomain( DomainInfo ); DomainInfo = NULL; } ExReleaseResourceLite(&BowserTransportDatabaseResource); }
return DomainInfo; }
NTSTATUS BowserSetDomainName( PDOMAIN_INFO DomainInfo, PUNICODE_STRING DomainName ) /*++
Routine Description:
Find the existing domain definition or create a new domain to browse on.
Arguments:
DomainName - Name of the domain to browse on
ComputerName - emulated computer name for this domain.
Return Value:
Status of the operation
--*/ { NTSTATUS Status; STRING OemDomainName;
PAGED_CODE();
try { ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
// if the alignment of the name given is bad, return error
if ( !POINTER_IS_ALIGNED( DomainName->Buffer, ALIGN_WCHAR ) ) { try_return( STATUS_DATATYPE_MISALIGNMENT_ERROR ); }
//
// Copy the DomainName into the structure
//
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName, sizeof(DomainInfo->DomOemDomainName), &DomainInfo->DomOemDomainNameLength, DomainName->Buffer, DomainName->Length );
if (!NT_SUCCESS(Status)) { try_return( Status ); }
DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
//
// Build the domain name as a Netbios name
// Trailing blank filled and <00> 16th byte
//
RtlCopyMemory( DomainInfo->DomNetbiosDomainName, DomainInfo->DomOemDomainName, DomainInfo->DomOemDomainNameLength ); RtlFillMemory( DomainInfo->DomNetbiosDomainName+DomainInfo->DomOemDomainNameLength, NETBIOS_NAME_LEN-1-DomainInfo->DomOemDomainNameLength, ' '); DomainInfo->DomNetbiosDomainName[NETBIOS_NAME_LEN-1] = PRIMARY_DOMAIN_SIGNATURE;
//
// Copy the upcased Unicode domain name into the structure.
//
OemDomainName.Buffer = DomainInfo->DomOemDomainName; OemDomainName.Length = (USHORT)DomainInfo->DomOemDomainNameLength; OemDomainName.MaximumLength = OemDomainName.Length + sizeof(WCHAR);
DomainInfo->DomUnicodeDomainName.Buffer = DomainInfo->DomUnicodeDomainNameBuffer; DomainInfo->DomUnicodeDomainName.MaximumLength = sizeof(DomainInfo->DomUnicodeDomainNameBuffer);
Status = RtlOemStringToUnicodeString(&DomainInfo->DomUnicodeDomainName, &OemDomainName, FALSE);
if (!NT_SUCCESS(Status)) { try_return( Status ); }
Status = STATUS_SUCCESS;
try_exit:NOTHING; } finally { ExReleaseResourceLite(&BowserTransportDatabaseResource); }
return Status; }
PDOMAIN_INFO BowserFindDomain( PUNICODE_STRING DomainName OPTIONAL ) /*++
Routine Description:
This routine will look up a domain given a name.
Arguments:
DomainName - The name of the domain to look up.
Return Value:
NULL - No such domain exists
A pointer to the domain found. The found domain should be dereferenced using BowserDereferenceDomain.
--*/ { NTSTATUS Status; PLIST_ENTRY DomainEntry;
PDOMAIN_INFO DomainInfo = NULL;
CHAR OemDomainName[DNLEN+1]; DWORD OemDomainNameLength;
PAGED_CODE();
ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
try {
// If no domain was specified
// try to return primary domain.
//
if ( DomainName == NULL || DomainName->Length == 0 ) { if ( !IsListEmpty( &BowserServicedDomains ) ) { DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next); }
// if the alignment of the name given is bad, return null
} else if ( !POINTER_IS_ALIGNED( DomainName->Buffer, ALIGN_WCHAR ) ) { DomainInfo = NULL;
//
// If the domain name was specified,
// Find it in the list of domains.
//
} else {
//
// Convert the domain name to OEM for faster comparison
//
Status = RtlUpcaseUnicodeToOemN( OemDomainName, DNLEN, &OemDomainNameLength, DomainName->Buffer, DomainName->Length );
if ( NT_SUCCESS(Status)) {
//
// The PrimaryDomainInfo structure is allocated with no
// domain name during bowser driver initialization.
// Detect that case here and always return that domain
// entry for all lookups.
//
if ( !IsListEmpty( &BowserServicedDomains ) ) { DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next);
if ( DomainInfo->DomOemDomainNameLength == 0 ) { try_return( DomainInfo ); }
}
//
// Loop trying to find this domain name.
//
for (DomainEntry = BowserServicedDomains.Flink ; DomainEntry != &BowserServicedDomains; DomainEntry = DomainEntry->Flink ) {
DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength && RtlCompareMemory( DomainInfo->DomOemDomainName, OemDomainName, OemDomainNameLength ) == OemDomainNameLength ) { try_return( DomainInfo ); }
}
DomainInfo = NULL; }
}
try_exit:NOTHING; } finally {
//
// Reference the domain.
//
if ( DomainInfo != NULL ) { DomainInfo->ReferenceCount ++; dprintf(DPRT_REF, ("Reference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount)); }
ExReleaseResourceLite(&BowserTransportDatabaseResource);
}
return DomainInfo; }
VOID BowserDereferenceDomain( IN PDOMAIN_INFO DomainInfo ) /*++
Routine Description:
Decrement the reference count on a domain.
If the reference count goes to 0, remove the domain.
On entry, the global BowserTransportDatabaseResource may not be locked
Arguments:
DomainInfo - The domain to dereference
Return Value:
None
--*/ { NTSTATUS Status; ULONG ReferenceCount;
PAGED_CODE();
//
// Decrement the reference count
//
ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE); ReferenceCount = -- DomainInfo->ReferenceCount; if ( ReferenceCount == 0 ) { RemoveEntryList( &DomainInfo->Next ); } ExReleaseResourceLite(&BowserTransportDatabaseResource); dprintf(DPRT_REF, ("Dereference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount));
if ( ReferenceCount != 0 ) { return; }
//
// Free the Domain Info structure.
//
dlog(DPRT_DOMAIN, ("%s: BowserDereferenceDomain: domain deleted.\n", DomainInfo->DomOemDomainName )); FREE_POOL(DomainInfo );
}
|