351 lines
9.6 KiB
C
351 lines
9.6 KiB
C
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
brwan.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains WAN support routines used by the
|
|||
|
Browser service.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Larry Osterman (LarryO) 22-Nov-1992
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Local function prototypes //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrAddDomainEntry(
|
|||
|
IN PINTERIM_SERVER_LIST InterimServerList,
|
|||
|
IN LPTSTR ConfigEntry
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Global routines //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
NET_API_STATUS NET_API_FUNCTION
|
|||
|
I_BrowserrQueryOtherDomains(
|
|||
|
IN BROWSER_IDENTIFY_HANDLE ServerName,
|
|||
|
IN OUT LPSERVER_ENUM_STRUCT InfoStruct,
|
|||
|
OUT LPDWORD TotalEntries
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns the list of "other domains" configured for this
|
|||
|
machine. It is only valid on primary domain controllers. If it is called
|
|||
|
on a machine that is not a PDC, it will return NERR_NotPrimary.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN BROWSER_IDENTIFY_HANDLE ServerName - Ignored.
|
|||
|
IN LPSERVER_ENUM_STRUCT InfoStruct - Returns the list of other domains
|
|||
|
as a SERVER_INFO_100 structure.
|
|||
|
OUT LPDWORD TotalEntries - Returns the total number of other domains.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - The status of this request.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NET_API_STATUS Status;
|
|||
|
PSERVER_INFO_100 ServerInfo;
|
|||
|
ULONG NumberOfOtherDomains;
|
|||
|
|
|||
|
if ( InfoStruct == NULL ) {
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if (InfoStruct->Level != 100) {
|
|||
|
return(ERROR_INVALID_LEVEL);
|
|||
|
}
|
|||
|
|
|||
|
if ( InfoStruct->ServerInfo.Level100 == NULL ) {
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Use the worker routine to do the actual work.
|
|||
|
//
|
|||
|
|
|||
|
Status = BrQueryOtherDomains( &ServerInfo, &NumberOfOtherDomains );
|
|||
|
|
|||
|
if ( Status == NERR_Success ) {
|
|||
|
*TotalEntries = NumberOfOtherDomains;
|
|||
|
|
|||
|
InfoStruct->ServerInfo.Level100->Buffer = ServerInfo;
|
|||
|
InfoStruct->ServerInfo.Level100->EntriesRead = NumberOfOtherDomains;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrWanMasterInitialize(
|
|||
|
IN PNETWORK Network
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
This routine initializes the wan information for a new master.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LPBYTE Buffer = NULL;
|
|||
|
PSERVER_INFO_100 ServerInfo;
|
|||
|
NET_API_STATUS Status;
|
|||
|
ULONG i;
|
|||
|
ULONG EntriesRead;
|
|||
|
ULONG TotalEntries;
|
|||
|
PDOMAIN_CONTROLLER_INFO pDcInfo=NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If we're on the PDC, then all our initialization has been done.
|
|||
|
// Or, if we're semi-pseudo server, we don't contact the PDC/BDC
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
#ifdef ENABLE_PSEUDO_BROWSER
|
|||
|
if ( (Network->Flags & NETWORK_PDC) ||
|
|||
|
BrInfo.PseudoServerLevel == BROWSER_SEMI_PSEUDO_NO_DMB ) {
|
|||
|
#else
|
|||
|
if ( Network->Flags & NETWORK_PDC ) {
|
|||
|
#endif
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
Status = DsGetDcName( NULL, NULL, NULL, NULL,
|
|||
|
DS_PDC_REQUIRED |
|
|||
|
DS_BACKGROUND_ONLY |
|
|||
|
DS_RETURN_FLAT_NAME,
|
|||
|
&pDcInfo );
|
|||
|
|
|||
|
//
|
|||
|
// It is not an error to not be able to contact the PDC.
|
|||
|
//
|
|||
|
|
|||
|
if (Status != NERR_Success) {
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT ( pDcInfo &&
|
|||
|
pDcInfo->DomainControllerName );
|
|||
|
|
|||
|
Status = I_BrowserQueryOtherDomains(pDcInfo->DomainControllerName,
|
|||
|
&Buffer,
|
|||
|
&EntriesRead,
|
|||
|
&TotalEntries);
|
|||
|
|
|||
|
//
|
|||
|
// We don't need the PDC name any more.
|
|||
|
//
|
|||
|
NetApiBufferFree((LPVOID)pDcInfo);
|
|||
|
pDcInfo = NULL;
|
|||
|
|
|||
|
if (Status != NERR_Success) {
|
|||
|
|
|||
|
//
|
|||
|
// We failed to get the list from supposedly the PDC.
|
|||
|
// It could be that the role has changed & DsGetDcName's cache
|
|||
|
// hasn't got refreshed.
|
|||
|
//
|
|||
|
// Force PDC discovery so that next time around we're sure
|
|||
|
// to get the real PDC.
|
|||
|
//
|
|||
|
|
|||
|
Status = DsGetDcName( NULL, NULL, NULL, NULL,
|
|||
|
DS_PDC_REQUIRED |
|
|||
|
DS_FORCE_REDISCOVERY | // Note FORCE option
|
|||
|
DS_RETURN_FLAT_NAME,
|
|||
|
&pDcInfo );
|
|||
|
|
|||
|
if (Status != NERR_Success) {
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT ( pDcInfo &&
|
|||
|
pDcInfo->DomainControllerName );
|
|||
|
|
|||
|
Status = I_BrowserQueryOtherDomains(pDcInfo->DomainControllerName,
|
|||
|
&Buffer,
|
|||
|
&EntriesRead,
|
|||
|
&TotalEntries);
|
|||
|
|
|||
|
//
|
|||
|
// We don't need the PDC name any more.
|
|||
|
//
|
|||
|
NetApiBufferFree((LPVOID)pDcInfo);
|
|||
|
|
|||
|
if (Status != NERR_Success) {
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (!LOCK_NETWORK(Network)) {
|
|||
|
return NERR_InternalError;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
PLIST_ENTRY Entry;
|
|||
|
PLIST_ENTRY NextEntry;
|
|||
|
|
|||
|
//
|
|||
|
// Scan the other domains list and turn on the active bit for each
|
|||
|
// other domain.
|
|||
|
//
|
|||
|
|
|||
|
for (Entry = Network->OtherDomainsList.Flink;
|
|||
|
Entry != &Network->OtherDomainsList ;
|
|||
|
Entry = Entry->Flink) {
|
|||
|
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
|
|||
|
|
|||
|
OtherDomain->Flags |= OTHERDOMAIN_INVALID;
|
|||
|
}
|
|||
|
|
|||
|
ServerInfo = (PSERVER_INFO_100)Buffer;
|
|||
|
|
|||
|
for (i = 0; i < EntriesRead; i++ ) {
|
|||
|
|
|||
|
//
|
|||
|
// Add this as an other domain.
|
|||
|
//
|
|||
|
for (Entry = Network->OtherDomainsList.Flink;
|
|||
|
Entry != &Network->OtherDomainsList ;
|
|||
|
Entry = Entry->Flink) {
|
|||
|
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
|
|||
|
|
|||
|
//
|
|||
|
// If this name is in the other domains list, it's not invalid
|
|||
|
// and we should flag that we've seen the domain name.
|
|||
|
//
|
|||
|
// The list we're getting is over the net. Make sure serverinfo
|
|||
|
// contains a valid name for comparison (see bug 377078)
|
|||
|
// Skip processing if NULL.
|
|||
|
// If ServerInfo got NULLED out in prev run, we shouldn't
|
|||
|
// get into _wcsicmp.
|
|||
|
|
|||
|
if (ServerInfo->sv100_name &&
|
|||
|
!_wcsicmp(OtherDomain->Name, ServerInfo->sv100_name)) {
|
|||
|
OtherDomain->Flags &= ~OTHERDOMAIN_INVALID;
|
|||
|
ServerInfo->sv100_name = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ServerInfo ++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Scan the other domains list and remove any domains that are
|
|||
|
// still marked as invalid.
|
|||
|
//
|
|||
|
|
|||
|
for (Entry = Network->OtherDomainsList.Flink;
|
|||
|
Entry != &Network->OtherDomainsList ;
|
|||
|
Entry = NextEntry) {
|
|||
|
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
|
|||
|
|
|||
|
if (OtherDomain->Flags & OTHERDOMAIN_INVALID) {
|
|||
|
NextEntry = Entry->Flink;
|
|||
|
|
|||
|
//
|
|||
|
// Remove this entry from the list.
|
|||
|
//
|
|||
|
|
|||
|
RemoveEntryList(Entry);
|
|||
|
|
|||
|
BrRemoveOtherDomain(Network, OtherDomain->Name);
|
|||
|
|
|||
|
MIDL_user_free(OtherDomain);
|
|||
|
|
|||
|
} else {
|
|||
|
NextEntry = Entry->Flink;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now scan the domain list from the PDC and add any entries that
|
|||
|
// weren't there already.
|
|||
|
//
|
|||
|
|
|||
|
ServerInfo = (PSERVER_INFO_100)Buffer;
|
|||
|
|
|||
|
for (i = 0; i < EntriesRead; i++ ) {
|
|||
|
|
|||
|
if (ServerInfo->sv100_name != NULL) {
|
|||
|
PNET_OTHER_DOMAIN OtherDomain = MIDL_user_allocate(sizeof(NET_OTHER_DOMAIN));
|
|||
|
|
|||
|
if (OtherDomain != NULL) {
|
|||
|
|
|||
|
Status = BrAddOtherDomain(Network, ServerInfo->sv100_name);
|
|||
|
|
|||
|
//
|
|||
|
// If we were able to add the other domain, add it to our
|
|||
|
// internal structure.
|
|||
|
//
|
|||
|
|
|||
|
if (Status == NERR_Success) {
|
|||
|
wcscpy(OtherDomain->Name, ServerInfo->sv100_name);
|
|||
|
OtherDomain->Flags = 0;
|
|||
|
InsertHeadList(&Network->OtherDomainsList, &OtherDomain->Next);
|
|||
|
} else {
|
|||
|
LPWSTR SubString[1];
|
|||
|
|
|||
|
SubString[0] = ServerInfo->sv100_name;
|
|||
|
|
|||
|
BrLogEvent(EVENT_BROWSER_OTHERDOMAIN_ADD_FAILED, Status, 1, SubString);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ServerInfo ++;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
} finally {
|
|||
|
UNLOCK_NETWORK(Network);
|
|||
|
|
|||
|
if (Buffer != NULL) {
|
|||
|
MIDL_user_free(Buffer);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
return NERR_Success;
|
|||
|
|
|||
|
}
|