1071 lines
25 KiB
C
1071 lines
25 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
brdomain.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Code to manage primary and emulated networks.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Cliff Van Dyke (CliffV) 11-Jan-1995
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// Module specific globals
|
|||
|
//
|
|||
|
|
|||
|
// Serialized by NetworkCritSect
|
|||
|
LIST_ENTRY ServicedDomains = {0};
|
|||
|
|
|||
|
//
|
|||
|
// Local procedure forwards.
|
|||
|
//
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrCreateDomain(
|
|||
|
LPWSTR DomainName,
|
|||
|
LPWSTR ComputerName,
|
|||
|
BOOLEAN IsEmulatedDomain
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
BrCreateDomainWorker(
|
|||
|
IN PVOID Ctx
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrInitializeDomains(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize brdomain.c and create the primary domain.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
LPWSTR ComputerName = NULL;
|
|||
|
LPWSTR DomainName = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize globals
|
|||
|
//
|
|||
|
|
|||
|
InitializeListHead(&ServicedDomains);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize actual domain of this machine.
|
|||
|
//
|
|||
|
// Get the configured computer name. NetpGetComputerName allocates
|
|||
|
// the memory to hold the computername string using LocalAlloc.
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = NetpGetComputerName( &ComputerName );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
NetStatus = NetpGetDomainName( &DomainName );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
NetStatus = BrCreateDomain( DomainName,
|
|||
|
ComputerName,
|
|||
|
FALSE );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NetStatus = NERR_Success;
|
|||
|
|
|||
|
//
|
|||
|
// Free locally used resources
|
|||
|
//
|
|||
|
Cleanup:
|
|||
|
if ( ComputerName != NULL ) {
|
|||
|
(VOID)LocalFree( ComputerName );
|
|||
|
}
|
|||
|
if ( DomainName != NULL ) {
|
|||
|
(VOID)LocalFree( DomainName );
|
|||
|
}
|
|||
|
|
|||
|
return NetStatus;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrCreateDomain(
|
|||
|
LPWSTR DomainName,
|
|||
|
LPWSTR ComputerName,
|
|||
|
BOOLEAN IsEmulatedDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Create a new domain to browse on.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainName - Name of the domain to browse on
|
|||
|
|
|||
|
ComputerName - Name of this computer in the specified domain.
|
|||
|
|
|||
|
IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
|
|||
|
BOOLEAN CanCallBrDeleteDomain = FALSE;
|
|||
|
|
|||
|
PDOMAIN_INFO DomainInfo = NULL;
|
|||
|
ULONG AComputerNameLength;
|
|||
|
|
|||
|
BrPrint(( BR_DOMAIN, "%ws: Added new domain and computer: %ws\n",
|
|||
|
DomainName,
|
|||
|
ComputerName ));
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a structure describing the new domain.
|
|||
|
//
|
|||
|
|
|||
|
DomainInfo = LocalAlloc( LMEM_ZEROINIT, sizeof(DOMAIN_INFO) );
|
|||
|
|
|||
|
if ( DomainInfo == NULL ) {
|
|||
|
NetStatus = GetLastError();
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create an interim reference count for this domain.
|
|||
|
//
|
|||
|
|
|||
|
DomainInfo->ReferenceCount = 1;
|
|||
|
|
|||
|
DomainInfo->IsEmulatedDomain = IsEmulatedDomain;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Copy the computer name into the structure.
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = I_NetNameCanonicalize(
|
|||
|
NULL,
|
|||
|
ComputerName,
|
|||
|
DomainInfo->DomUnicodeComputerName,
|
|||
|
sizeof(DomainInfo->DomUnicodeComputerName),
|
|||
|
NAMETYPE_COMPUTER,
|
|||
|
0 );
|
|||
|
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"ComputerName " FORMAT_LPWSTR " is invalid\n",
|
|||
|
ComputerName ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DomainInfo->DomUnicodeComputerNameLength = wcslen(DomainInfo->DomUnicodeComputerName);
|
|||
|
|
|||
|
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemComputerName,
|
|||
|
sizeof(DomainInfo->DomOemComputerName),
|
|||
|
&DomainInfo->DomOemComputerNameLength,
|
|||
|
DomainInfo->DomUnicodeComputerName,
|
|||
|
DomainInfo->DomUnicodeComputerNameLength*sizeof(WCHAR));
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
BrPrint(( BR_CRITICAL, "Unable to convert computer name to OEM %ws %lx\n", ComputerName, Status ));
|
|||
|
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DomainInfo->DomOemComputerName[DomainInfo->DomOemComputerNameLength] = '\0';
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Copy the domain name into the structure
|
|||
|
// Note: Use workgroup type rather then domain since
|
|||
|
// we have no notion of domain/workgroup in the browser (all are "groups")
|
|||
|
// an workgroup is less restrictive (see bug 348606)
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = I_NetNameCanonicalize(
|
|||
|
NULL,
|
|||
|
DomainName,
|
|||
|
DomainInfo->DomUnicodeDomainName,
|
|||
|
sizeof(DomainInfo->DomUnicodeDomainName),
|
|||
|
NAMETYPE_WORKGROUP,
|
|||
|
0 );
|
|||
|
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: DomainName is invalid\n", DomainName ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
RtlInitUnicodeString( &DomainInfo->DomUnicodeDomainNameString,
|
|||
|
DomainInfo->DomUnicodeDomainName );
|
|||
|
|
|||
|
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
|
|||
|
sizeof(DomainInfo->DomOemDomainName),
|
|||
|
&DomainInfo->DomOemDomainNameLength,
|
|||
|
DomainInfo->DomUnicodeDomainNameString.Buffer,
|
|||
|
DomainInfo->DomUnicodeDomainNameString.Length);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
|
|||
|
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
|
|||
|
|
|||
|
//
|
|||
|
// Create the domain rename timer
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrCreateTimer( &DomainInfo->DomainRenameTimer );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Cannot create domain rename timer %ld\n", DomainName, NetStatus ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Link the domain into the list of domains
|
|||
|
// (And mark that any future cleanup can be done by calling BrDeleteDomain)
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
InsertTailList(&ServicedDomains, &DomainInfo->Next);
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
CanCallBrDeleteDomain = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Create the various networks for this domain.
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrCreateNetworks( DomainInfo );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Free Locally used resources
|
|||
|
//
|
|||
|
Cleanup:
|
|||
|
|
|||
|
if (NetStatus != NERR_Success) {
|
|||
|
|
|||
|
if (DomainInfo != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// If we've initialized to the point where we can call
|
|||
|
// we can call BrDeleteDomain, do so.
|
|||
|
//
|
|||
|
|
|||
|
if ( CanCallBrDeleteDomain ) {
|
|||
|
(VOID) BrDeleteDomain( DomainInfo );
|
|||
|
|
|||
|
//
|
|||
|
// Otherwise, just delete what we've created.
|
|||
|
//
|
|||
|
} else {
|
|||
|
|
|||
|
(VOID) LocalFree(DomainInfo);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return NetStatus;
|
|||
|
}
|
|||
|
|
|||
|
typedef struct _BROWSER_CREATE_DOMAIN_CONTEXT {
|
|||
|
LPWSTR DomainName;
|
|||
|
LPWSTR ComputerName;
|
|||
|
BOOLEAN IsEmulatedDomain;
|
|||
|
HANDLE EventHandle;
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
} BROWSER_CREATE_DOMAIN_CONTEXT, *PBROWSER_CREATE_DOMAIN_CONTEXT;
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrCreateDomainInWorker(
|
|||
|
LPWSTR DomainName,
|
|||
|
LPWSTR ComputerName,
|
|||
|
BOOLEAN IsEmulatedDomain
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Wrapper for BrCreateDomain. Since BrCreateDomain starts several pending
|
|||
|
IO's to the browser driver, the thread that calls BrCreateDomain must
|
|||
|
remain around forever. This wrapper can be called by any transient thread
|
|||
|
(e.g., an RPC thread). It simply causes BrCreateDomain to be called in a
|
|||
|
worker thread.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainName - Name of the domain to browse on
|
|||
|
|
|||
|
ComputerName - Name of this computer in the specified domain.
|
|||
|
|
|||
|
IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status of operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
DWORD WaitStatus;
|
|||
|
|
|||
|
WORKER_ITEM WorkItem;
|
|||
|
BROWSER_CREATE_DOMAIN_CONTEXT Context;
|
|||
|
|
|||
|
//
|
|||
|
// Copy our arguments into a context block for the worker thread
|
|||
|
//
|
|||
|
|
|||
|
Context.DomainName = DomainName;
|
|||
|
Context.ComputerName = ComputerName;
|
|||
|
Context.IsEmulatedDomain = IsEmulatedDomain;
|
|||
|
|
|||
|
//
|
|||
|
// Create an event which we use to wait on the worker thread.
|
|||
|
//
|
|||
|
|
|||
|
Context.EventHandle = CreateEvent(
|
|||
|
NULL, // Event attributes
|
|||
|
TRUE, // Event must be manually reset
|
|||
|
FALSE, // Initial state not signalled
|
|||
|
NULL ); // Event name
|
|||
|
|
|||
|
if ( Context.EventHandle == NULL ) {
|
|||
|
NetStatus = GetLastError();
|
|||
|
return NetStatus;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Queue the request to the worker thread.
|
|||
|
//
|
|||
|
|
|||
|
BrInitializeWorkItem( &WorkItem,
|
|||
|
BrCreateDomainWorker,
|
|||
|
&Context );
|
|||
|
|
|||
|
BrQueueWorkItem( &WorkItem );
|
|||
|
|
|||
|
//
|
|||
|
// Wait for the worker thread to finish
|
|||
|
//
|
|||
|
|
|||
|
WaitStatus = WaitForSingleObject( Context.EventHandle, INFINITE );
|
|||
|
|
|||
|
if ( WaitStatus == WAIT_OBJECT_0 ) {
|
|||
|
NetStatus = Context.NetStatus;
|
|||
|
} else {
|
|||
|
NetStatus = GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( Context.EventHandle );
|
|||
|
|
|||
|
return NetStatus;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrCreateDomainWorker(
|
|||
|
IN PVOID Ctx
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Worker routine for BrCreateDomainInWorker.
|
|||
|
|
|||
|
This routine executes in the context of a worker thread.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context - Context containing the workitem and the description of the
|
|||
|
domain to create.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PBROWSER_CREATE_DOMAIN_CONTEXT Context = (PBROWSER_CREATE_DOMAIN_CONTEXT) Ctx;
|
|||
|
|
|||
|
//
|
|||
|
// Create the domain.
|
|||
|
//
|
|||
|
|
|||
|
Context->NetStatus = BrCreateDomain(
|
|||
|
Context->DomainName,
|
|||
|
Context->ComputerName,
|
|||
|
Context->IsEmulatedDomain );
|
|||
|
|
|||
|
//
|
|||
|
// Let the caller know we're done.
|
|||
|
//
|
|||
|
SetEvent( Context->EventHandle );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
PDOMAIN_INFO
|
|||
|
BrFindDomain(
|
|||
|
LPWSTR DomainName,
|
|||
|
BOOLEAN DefaultToPrimary
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will look up a domain given a name.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainName - The name of the domain to look up.
|
|||
|
|
|||
|
DefaultToPrimary - Return the primary domain if DomainName is NULL or
|
|||
|
can't be found.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NULL - No such domain exists
|
|||
|
|
|||
|
A pointer to the domain found. The found domain should be dereferenced
|
|||
|
using BrDereferenceDomain.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PLIST_ENTRY DomainEntry;
|
|||
|
|
|||
|
PDOMAIN_INFO DomainInfo = NULL;
|
|||
|
|
|||
|
CHAR OemDomainName[DNLEN+1];
|
|||
|
DWORD OemDomainNameLength;
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If domain was specified,
|
|||
|
// try to return primary domain.
|
|||
|
//
|
|||
|
|
|||
|
if ( DomainName != NULL ) {
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Convert the domain name to OEM for faster comparison
|
|||
|
//
|
|||
|
Status = RtlUpcaseUnicodeToOemN( OemDomainName,
|
|||
|
sizeof(OemDomainName),
|
|||
|
&OemDomainNameLength,
|
|||
|
DomainName,
|
|||
|
wcslen(DomainName)*sizeof(WCHAR));
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
|
|||
|
DomainInfo = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Loop trying to find this domain name.
|
|||
|
//
|
|||
|
|
|||
|
for (DomainEntry = ServicedDomains.Flink ;
|
|||
|
DomainEntry != &ServicedDomains;
|
|||
|
DomainEntry = DomainEntry->Flink ) {
|
|||
|
|
|||
|
DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
|
|||
|
|
|||
|
if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength &&
|
|||
|
RtlCompareMemory( DomainInfo->DomOemDomainName,
|
|||
|
OemDomainName,
|
|||
|
OemDomainNameLength ) == OemDomainNameLength ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
DomainInfo = NULL;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we're to default to the primary domain,
|
|||
|
// do so.
|
|||
|
//
|
|||
|
|
|||
|
if ( DefaultToPrimary && DomainInfo == NULL ) {
|
|||
|
if ( !IsListEmpty( &ServicedDomains ) ) {
|
|||
|
DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reference the domain.
|
|||
|
//
|
|||
|
|
|||
|
if ( DomainInfo != NULL ) {
|
|||
|
DomainInfo->ReferenceCount ++;
|
|||
|
}
|
|||
|
|
|||
|
Cleanup:
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
return DomainInfo;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PDOMAIN_INFO
|
|||
|
BrReferenceDomain(
|
|||
|
PDOMAIN_INFO PotentialDomainInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will look up a domain given a potential pointer to the domain
|
|||
|
|
|||
|
This routine is useful if a caller has a pointer to a domain but
|
|||
|
hasn't incremented the reference count. For instance,
|
|||
|
a timer completion routine has such a pointer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
PotentialDomainInfo - Pointer to the DomainInfo to be verified.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NULL - No such domain exists
|
|||
|
|
|||
|
A pointer to the domain found. The found domain should be dereferenced
|
|||
|
using BrDereferenceDomain.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PLIST_ENTRY ListEntry;
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
for (ListEntry = ServicedDomains.Flink ;
|
|||
|
ListEntry != &ServicedDomains;
|
|||
|
ListEntry = ListEntry->Flink ) {
|
|||
|
PDOMAIN_INFO DomainInfo = CONTAINING_RECORD(ListEntry, DOMAIN_INFO, Next);
|
|||
|
|
|||
|
if ( PotentialDomainInfo == DomainInfo ) {
|
|||
|
|
|||
|
DomainInfo->ReferenceCount ++;
|
|||
|
BrPrint(( BR_LOCKS,
|
|||
|
"%ws: reference domain: %ld\n",
|
|||
|
DomainInfo->DomUnicodeDomainName,
|
|||
|
DomainInfo->ReferenceCount ));
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
return DomainInfo;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
BrDereferenceDomain(
|
|||
|
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 NetworkCritSect may not be locked
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainInfo - The domain to dereference
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG ReferenceCount;
|
|||
|
|
|||
|
//
|
|||
|
// Decrement the reference count
|
|||
|
//
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
ReferenceCount = -- DomainInfo->ReferenceCount;
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
if ( ReferenceCount != 0 ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Ditch the rename timer
|
|||
|
//
|
|||
|
|
|||
|
BrDestroyTimer( &DomainInfo->DomainRenameTimer );
|
|||
|
|
|||
|
//
|
|||
|
// Free the Domain Info structure.
|
|||
|
//
|
|||
|
(VOID) LocalFree( DomainInfo );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrRenameDomainForNetwork(
|
|||
|
PNETWORK Network,
|
|||
|
PVOID Context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Handle domain rename for a particular network.
|
|||
|
|
|||
|
Reset the network indicating this machine plays no special role.
|
|||
|
Then, re-enable any role we're currently playing.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Network - Network to reset (Referenced)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status - The status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
|
|||
|
//
|
|||
|
// Lock the network
|
|||
|
//
|
|||
|
if (LOCK_NETWORK(Network)) {
|
|||
|
|
|||
|
//
|
|||
|
// Stop it from being a master.
|
|||
|
//
|
|||
|
if (Network->Role & ROLE_MASTER) {
|
|||
|
|
|||
|
NetStatus = BrStopMaster(Network);
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Cannot BrStopMaster %ld\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Stop being a backup as well.
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrStopBackup(Network);
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Cannot BrStopBackup %ld\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Stop even being a potential browser.
|
|||
|
// Close the <DomainName>[1E] name
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrUpdateNetworkAnnouncementBits(Network, (PVOID)(BR_SHUTDOWN|BR_PARANOID) );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Cannot BrUpdateNetworkAnnouncementBits %ld\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Register the new <DomainName>[1E] name
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrUpdateNetworkAnnouncementBits(Network, (PVOID)BR_PARANOID );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Cannot BrUpdateNetworkAnnouncementBits %ld\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If we are on either a domain master, or on a lanman/NT machine,
|
|||
|
// force an election on all our transports to make sure that we're
|
|||
|
// the master
|
|||
|
//
|
|||
|
|
|||
|
if ( (Network->Flags & NETWORK_PDC) != 0 || BrInfo.IsLanmanNt) {
|
|||
|
NetStatus = BrElectMasterOnNet( Network, (PVOID)EVENT_BROWSER_ELECTION_SENT_LANMAN_NT_STARTED );
|
|||
|
|
|||
|
if (NetStatus != NERR_Success) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Can't Elect Master.\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
// This isn't fatal.
|
|||
|
} else {
|
|||
|
BrPrint(( BR_NETWORK, "%ws: %ws: Election forced on domain rename.\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer ));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If forced to MaintainServerList, become a backup again
|
|||
|
//
|
|||
|
|
|||
|
EnterCriticalSection(&BrInfo.ConfigCritSect);
|
|||
|
if (BrInfo.MaintainServerList == 1){
|
|||
|
|
|||
|
//
|
|||
|
// Become a backup server now.
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrBecomeBackup( Network );
|
|||
|
|
|||
|
if (NetStatus != NERR_Success) {
|
|||
|
BrPrint(( BR_CRITICAL,
|
|||
|
"%ws: %ws: BrRenameDomainForNetwork: Can't BecomeBackup.\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer,
|
|||
|
NetStatus ));
|
|||
|
// This isn't fatal.
|
|||
|
} else {
|
|||
|
BrPrint(( BR_NETWORK, "%ws: %ws: Became Backup.\n",
|
|||
|
Network->DomainInfo->DomUnicodeDomainName,
|
|||
|
Network->NetworkName.Buffer ));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
LeaveCriticalSection(&BrInfo.ConfigCritSect);
|
|||
|
|
|||
|
UNLOCK_NETWORK(Network);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Always return success so allow the caller to continue to the next network.
|
|||
|
//
|
|||
|
return NERR_Success;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrRenameDomain(
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Rename the domain from the specified name to the currently register named
|
|||
|
for the domain.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
OldDomainName - Name that the domain is currently known by.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
NTSTATUS Status;
|
|||
|
PDOMAIN_INFO DomainInfo = NULL;
|
|||
|
LPWSTR NewDomainName = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Reference the domain.
|
|||
|
// This routine can be called as a timer routine. In that case, the
|
|||
|
// domain might not exist any more.
|
|||
|
//
|
|||
|
|
|||
|
DomainInfo = BrReferenceDomain( Context );
|
|||
|
|
|||
|
if ( DomainInfo == NULL ) {
|
|||
|
BrPrint(( BR_CRITICAL, "%lx: Renamed domain no longer exists\n", Context ));
|
|||
|
NetStatus = ERROR_INTERNAL_ERROR;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
BrPrint(( BR_DOMAIN, "%ws: BrRenameDomain called\n",
|
|||
|
DomainInfo->DomUnicodeDomainName ));
|
|||
|
|
|||
|
//
|
|||
|
// Determine the new domain name
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = NetpGetDomainName( &NewDomainName );
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Cannot determine the new domain name %ld\n",
|
|||
|
DomainInfo->DomUnicodeDomainName,
|
|||
|
NetStatus ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put the new domain name into the domain structure
|
|||
|
// Note: Use workgroup type rather then domain since
|
|||
|
// we have no notion of domain/workgroup in the browser (all are "groups")
|
|||
|
// an workgroup is less restrictive (see bug 348606)
|
|||
|
//
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
NetStatus = I_NetNameCanonicalize(
|
|||
|
NULL,
|
|||
|
NewDomainName,
|
|||
|
DomainInfo->DomUnicodeDomainName,
|
|||
|
sizeof(DomainInfo->DomUnicodeDomainName),
|
|||
|
NAMETYPE_WORKGROUP,
|
|||
|
0 );
|
|||
|
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: DomainName is invalid %ld\n",
|
|||
|
NewDomainName,
|
|||
|
NetStatus ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
RtlInitUnicodeString( &DomainInfo->DomUnicodeDomainNameString,
|
|||
|
DomainInfo->DomUnicodeDomainName );
|
|||
|
|
|||
|
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
|
|||
|
sizeof(DomainInfo->DomOemDomainName),
|
|||
|
&DomainInfo->DomOemDomainNameLength,
|
|||
|
DomainInfo->DomUnicodeDomainNameString.Buffer,
|
|||
|
DomainInfo->DomUnicodeDomainNameString.Length);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
|
|||
|
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Reset all of the networks telling them of the new domain name
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = BrEnumerateNetworksForDomain(DomainInfo, BrRenameDomainForNetwork, NULL);
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrPrint(( BR_CRITICAL, "%ws: Cannot do rename on all networks %ld\n",
|
|||
|
NewDomainName,
|
|||
|
NetStatus ));
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
NetStatus = NERR_Success;
|
|||
|
|
|||
|
//
|
|||
|
// Free locally used resources
|
|||
|
//
|
|||
|
Cleanup:
|
|||
|
|
|||
|
if ( NewDomainName != NULL ) {
|
|||
|
(VOID)LocalFree( NewDomainName );
|
|||
|
}
|
|||
|
|
|||
|
if ( DomainInfo != NULL ) {
|
|||
|
|
|||
|
//
|
|||
|
// If the domain rename failed,
|
|||
|
// try it again in 15 minutes.
|
|||
|
//
|
|||
|
|
|||
|
if ( NetStatus != NERR_Success ) {
|
|||
|
BrSetTimer(&DomainInfo->DomainRenameTimer, 15 * 1000 * 60, BrRenameDomain, DomainInfo);
|
|||
|
}
|
|||
|
|
|||
|
BrDereferenceDomain( DomainInfo );
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrDeleteDomain(
|
|||
|
IN PDOMAIN_INFO DomainInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Force a domain to be deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainInfo - The domain to delete
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Delete each of the networks for this domain.
|
|||
|
//
|
|||
|
|
|||
|
BrEnumerateNetworksForDomain(DomainInfo, BrDeleteNetwork, NULL );
|
|||
|
|
|||
|
//
|
|||
|
// Delink the domain from the global list and remove the final reference.
|
|||
|
//
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
RemoveEntryList(&DomainInfo->Next);
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
BrDereferenceDomain( DomainInfo );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrUninitializeDomains(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Delete all of the domains.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Loop through the domains deleting each of them
|
|||
|
//
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
while (!IsListEmpty(&ServicedDomains)) {
|
|||
|
|
|||
|
PDOMAIN_INFO DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
|
|||
|
|
|||
|
DomainInfo->ReferenceCount ++;
|
|||
|
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
//
|
|||
|
// Clean up the domain.
|
|||
|
//
|
|||
|
|
|||
|
BrDeleteDomain( DomainInfo );
|
|||
|
|
|||
|
//
|
|||
|
// Actually delete the delinked structure by removing the last reference
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( DomainInfo->ReferenceCount == 1 );
|
|||
|
BrDereferenceDomain( DomainInfo );
|
|||
|
|
|||
|
|
|||
|
EnterCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
}
|
|||
|
LeaveCriticalSection(&NetworkCritSect);
|
|||
|
|
|||
|
}
|