484 lines
12 KiB
C
484 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
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);
|
||
|
|
||
|
//
|
||
|
// 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 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 );
|
||
|
|
||
|
}
|