Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1918 lines
35 KiB

// Copyright (C) 1997 Microsoft Corporation
//
// wizard state object
//
// 12-15-97 sburns
#include "headers.hxx"
#include "state.hpp"
#include "resource.h"
#include "ds.hpp"
#include "common.hpp"
#include "NonDomainNc.hpp"
static State* stateInstance;
void
State::Init()
{
ASSERT(!stateInstance);
stateInstance = new State;
}
void
State::Destroy()
{
delete stateInstance;
};
State&
State::GetInstance()
{
ASSERT(stateInstance);
return *stateInstance;
}
// Determines the full file path of the folder where administration (incl. DS)
// tools shortcuts are placed. On success, returns S_OK and sets result to
// the path. On failure, returns a COM error and sets results to empty.
//
// result - receives the folder path on success.
HRESULT
GetAdminToolsPath(String& result)
{
LOG_FUNCTION(GetAdminToolsPath);
result.erase();
// +1 for null-termination paranoia
WCHAR buf[MAX_PATH + 1];
// REVIEWED-2002/02/28-sburns correct byte count passed.
::ZeroMemory(buf, (MAX_PATH + 1) * sizeof WCHAR);
HRESULT hr =
::SHGetFolderPath(
0,
CSIDL_COMMON_ADMINTOOLS,
0,
SHGFP_TYPE_CURRENT,
buf);
if (SUCCEEDED(hr))
{
result = buf;
}
return hr;
}
// Sets result = true if the registry option to not configure the dns client
// to point to itself is absent or non-zero, false otherwise.
// NTRAID#NTBUG9-446484-2001/10/11-sburns
void
InitDnsClientConfigFlag(bool& result)
{
LOG_FUNCTION(InitDnsClientConfigFlag);
result = true;
do
{
static String keyname =
String(REG_ADMIN_RUNTIME_OPTIONS) + RUNTIME_NAME;
RegistryKey key;
HRESULT hr = key.Open(HKEY_LOCAL_MACHINE, keyname);
BREAK_ON_FAILED_HRESULT(hr);
DWORD mode = 0;
hr = key.GetValue(L"ConfigureDnsClient", mode);
BREAK_ON_FAILED_HRESULT(hr);
result = mode ? true : false;
}
while (0);
LOG_BOOL(result);
}
State::State()
:
adminPassword(),
allowAnonAccess(false),
answerFile(0),
autoConfigDns(false),
computer(),
context(),
dbPath(),
domainsInForest(),
failureMessage(),
finishMessages(),
installedSite(),
isAdvancedMode(false),
isBackupGc(false),
isDnsOnNet(true),
#ifdef DBG
isExitOnFailureMode(false),
#endif
isForcedDemotion(false),
isLastDc(false),
isUpgrade(false),
logPath(),
needsCommandLineHelp(false),
needsReboot(false),
newDomainDnsName(),
newDomainFlatName(),
operation(NONE),
operationResultsMessage(),
operationResultsStatus(FAILURE),
operationResultsFlags(0),
parentDomainDnsName(),
password(),
reinstallDomain(false),
reinstallDomainController(false),
replicaDnsDomainName(),
replicateFromMedia(false),
replicationPartnerDc(),
restoreGc(false),
runHiddenWhileUnattended(true),
safeModeAdminPassword(),
setForestVersion(false),
shortcutPath(),
shouldConfigDnsClient(true),
siteName(),
splash(0),
sourcePath(),
sysvolPath(),
syskey(),
syskeyLocation(STORED),
useCurrentCredentials(false),
userDomain(),
userForest(),
username()
{
LOG_CTOR(State);
HRESULT hr = computer.Refresh();
// we're confident this will work, as the computer refers to the
// local machine.
ASSERT(SUCCEEDED(hr));
LOG_HRESULT(hr);
DetermineRunContext();
ArgMap args;
MapCommandLineArgs(args);
if (args.size() < 2)
{
LOG(L"no options specified");
}
else
{
// check for answerfile specification
static const wchar_t* ANSWER1 = L"answer";
static const wchar_t* ANSWER2 = L"u";
static const wchar_t* ANSWER3 = L"upgrade";
if (
args.find(ANSWER1) != args.end()
|| args.find(ANSWER2) != args.end()
|| args.find(ANSWER3) != args.end() )
{
bool isDefaultAnswerfile = false;
String filename = args[ANSWER1];
if (filename.empty())
{
filename = args[ANSWER2];
}
if (filename.empty())
{
filename = args[ANSWER3];
}
if (filename.empty())
{
// default value if none specified
filename = L"%systemdrive%\\dcpromo-ntupg.inf";
// if this file does not exist, don't pop up an error message.
isDefaultAnswerfile = true;
}
SetupAnswerFile(filename, isDefaultAnswerfile);
args.erase(ANSWER1);
args.erase(ANSWER2);
args.erase(ANSWER3);
}
// check for /adv
static const wchar_t* ADV = L"adv";
if (args.find(ADV) != args.end())
{
LOG(L"Enabling advanced mode");
isAdvancedMode = true;
args.erase(ADV);
}
#ifdef DBG
// check for /ExitOnFailure
// NTRAID#NTBUG9-416968-2001/06/14-sburns
static const wchar_t* EXIT_ON_FAIL = L"ExitOnFailure";
if (args.find(EXIT_ON_FAIL) != args.end())
{
LOG(L"Enabling exit-on-failure mode");
isExitOnFailureMode = true;
args.erase(EXIT_ON_FAIL);
}
#endif
// check for /forceremoval
// NTRAID#NTBUG9-496409-2001/11/29-sburns
static const wchar_t* FORCE = L"forceremoval";
if (args.find(FORCE) != args.end())
{
LOG(L"Enabling forced demotion mode");
isForcedDemotion = true;
args.erase(FORCE);
}
// anything left over gets you command line help, (one arg will always
// remain: the name of the exe)
if (args.size() > 1)
{
LOG(L"Unrecognized command line options specified");
needsCommandLineHelp = true;
}
}
// Disable locking of the console as early as possible to narrow the
// window of opportunity for the user (or the system) to lock the
// console before a valid machine security state is reached. We do this
// early only for upgrades, because upgrades autologon and autostart
// dcpromo, and the console may sit idle for some time. 311161
if (context == PDC_UPGRADE || context == BDC_UPGRADE)
{
DisableConsoleLocking();
}
// We must call this at startup, because once a demote operation is
// complete, it may not be possible for the shell to determine this
// path. 366738
hr = GetAdminToolsPath(shortcutPath);
ASSERT(SUCCEEDED(hr));
LOG_HRESULT(hr);
// Set the current directory to the root directory. This is to make the
// pathname normalization on the paths pages seem less astonishing. It
// will cause normalization to be relative to the root directory,
// rather than the user's home directory (which is typically the current
// directory when the app is launched from Start->Run)
// NTRAID#NTBUG9-470687-2001/09/21-sburns
String curdir;
hr = Win::GetCurrentDirectory(curdir);
if (SUCCEEDED(hr))
{
// NTRAID#NTBUG9-547394-2002/03/26-sburns
switch (FS::GetPathSyntax(curdir))
{
case FS::SYNTAX_ABSOLUTE_DRIVE:
{
// this is the typical case.
break;
}
default:
{
curdir = Win::GetSystemWindowsDirectory();
break;
}
}
hr = Win::SetCurrentDirectory(curdir.substr(0, 3));
ASSERT(SUCCEEDED(hr));
LOG_HRESULT(hr);
}
InitDnsClientConfigFlag(shouldConfigDnsClient);
IfmHandle = NULL;
}
void
State::SetupAnswerFile(
const String& filename,
bool isDefaultAnswerfile)
{
LOG_FUNCTION2(State::SetupAnswerFile, filename);
String f = Win::ExpandEnvironmentStrings(filename);
f = FS::NormalizePath(f);
LOG(L"answerfile resolved to: " + f);
if (FS::PathExists(f))
{
// file found.
LOG(L"answerfile found");
answerFile = new AnswerFile(f);
splash =
new UnattendSplashDialog(
context == State::NT5_DC
? IDS_DEMOTE_SPLASH_MESSAGE
: IDS_PROMOTE_SPLASH_MESSAGE);
splash->ModelessExecute(Win::GetDesktopWindow());
}
else
{
LOG(L"answerfile NOT found");
if (!isDefaultAnswerfile)
{
popup.Error(
Win::GetDesktopWindow(),
String::format(IDS_ANSWERFILE_NOT_FOUND, f.c_str()));
}
}
}
#ifdef LOGGING_BUILD
static const String CONTEXTS[] =
{
L"NT5_DC",
L"NT5_STANDALONE_SERVER",
L"NT5_MEMBER_SERVER",
L"BDC_UPGRADE",
L"PDC_UPGRADE"
};
#endif
void
State::DetermineRunContext()
{
LOG_FUNCTION(State::DetermineRunContext);
DS::PriorServerRole priorRole = DS::GetPriorServerRole(isUpgrade);
if (isUpgrade && priorRole != DS::UNKNOWN)
{
switch (priorRole)
{
case DS::PDC:
{
context = PDC_UPGRADE;
break;
}
case DS::BDC:
{
context = BDC_UPGRADE;
break;
}
default:
{
ASSERT(false);
break;
}
}
}
else
{
switch (computer.GetRole())
{
case Computer::STANDALONE_SERVER:
{
context = NT5_STANDALONE_SERVER;
break;
}
case Computer::MEMBER_SERVER:
{
context = NT5_MEMBER_SERVER;
break;
}
case Computer::PRIMARY_CONTROLLER:
case Computer::BACKUP_CONTROLLER:
{
// we're already an NT5 DC
context = NT5_DC;
break;
}
case Computer::STANDALONE_WORKSTATION:
case Computer::MEMBER_WORKSTATION:
default:
{
// we checked for this at startup
ASSERT(false);
break;
}
}
}
LOG(CONTEXTS[context]);
}
State::~State()
{
LOG_DTOR(State);
FreeIfmHandle();
delete answerFile;
// closes the splash dialog, if visible.
delete splash;
}
State::RunContext
State::GetRunContext() const
{
LOG_FUNCTION2(State::GetRunContext, CONTEXTS[context]);
return context;
}
bool
State::UsingAnswerFile() const
{
return answerFile != 0;
}
String
State::GetAnswerFileOption(const String& option) const
{
LOG_FUNCTION2(GetAnswerFileOption, option);
ASSERT(UsingAnswerFile());
String result;
if (answerFile)
{
result = answerFile->GetOption(option);
}
return result;
}
EncryptedString
State::GetEncryptedAnswerFileOption(const String& option) const
{
LOG_FUNCTION2(GetEncryptedAnswerFileOption, option);
ASSERT(UsingAnswerFile());
EncryptedString result;
if (answerFile)
{
result = answerFile->GetEncryptedOption(option);
}
return result;
}
#ifdef LOGGING_BUILD
static const String OPERATIONS[] =
{
L"NONE",
L"REPLICA",
L"FOREST",
L"TREE",
L"CHILD",
L"DEMOTE",
L"ABORT_BDC_UPGRADE"
};
#endif
void
State::SetOperation(Operation oper)
{
LOG_FUNCTION2(State::SetOperation, OPERATIONS[oper]);
operation = oper;
}
State::Operation
State::GetOperation() const
{
LOG_FUNCTION2(State::GetOperation, OPERATIONS[operation]);
// if aborting BDC upgrade, context must be BDC upgrade
ASSERT(operation == ABORT_BDC_UPGRADE ? context == BDC_UPGRADE : true);
return operation;
}
void
State::SetIfmHandle(DSROLE_IFM_OPERATION_HANDLE IfmHandleIn)
{
ASSERT(IfmHandle == NULL || IfmHandleIn == 0);
if (IfmHandle) {
// need to free any existing handle
::DsRoleIfmHandleFree(0, // this server
&IfmHandle);
IfmHandle = NULL;
}
IfmHandle = IfmHandleIn;
}
void
State::SetReplicaDomainDNSName(const String& dnsName)
{
LOG_FUNCTION2(State:::SetReplicaDomainDNSName, dnsName);
ASSERT(!dnsName.empty());
replicaDnsDomainName = dnsName;
// if the user is changing the domain to be replicated, then any
// previous replication partner DC may no longer apply.
// see ntbug9 #158726
SetReplicationPartnerDC(L"");
}
String
State::GetDatabasePath() const
{
LOG_FUNCTION2(State::GetDatabasePath, dbPath);
return dbPath;
}
String
State::GetLogPath() const
{
LOG_FUNCTION2(State::GetLogPath, logPath);
return logPath;
}
String
State::GetSYSVOLPath() const
{
LOG_FUNCTION2(State::GetSYSVOLPath, sysvolPath);
return sysvolPath;
}
void
State::SetDatabasePath(const String& path)
{
LOG_FUNCTION2(State::SetDatabasePath, path);
ASSERT(!path.empty());
dbPath = path;
}
void
State::SetLogPath(const String& path)
{
LOG_FUNCTION2(State::SetLogPath, path);
ASSERT(!path.empty());
logPath = path;
}
void
State::SetSYSVOLPath(const String& path)
{
LOG_FUNCTION2(State::SetSYSVOLPath, path);
ASSERT(!path.empty());
sysvolPath = path;
}
String
State::GetUsername() const
{
LOG_FUNCTION2(State::GetUsername, username);
// don't assert that this is !empty -- we may use existing credentials
return username;
}
EncryptedString
State::GetPassword() const
{
// don't log the password...
LOG_FUNCTION(State::GetPassword);
// don't assert that this is !empty -- we may use existing credentials
return password;
}
void
State::SetUsername(const String& name)
{
LOG_FUNCTION2(State::SetUsername, name);
ASSERT(!name.empty());
username = name;
}
void
State::SetPassword(const EncryptedString& password_)
{
LOG_FUNCTION(State::SetPassword);
// password_ may be empty
// ASSERT(!password_.empty());
password = password_;
}
String
State::GetReplicaDomainDNSName() const
{
LOG_FUNCTION2(
State::GetReplicaDomainDNSName,
replicaDnsDomainName);
return replicaDnsDomainName;
}
String
State::GetSiteName() const
{
LOG_FUNCTION2(State::GetSiteName, siteName);
return siteName;
}
void
State::SetSiteName(const String& site)
{
LOG_FUNCTION2(State::SetSiteName, site);
siteName = site;
}
void
State::SetOperationResults(OperationResult result)
{
LOG_FUNCTION2(
State::SetOperationResults,
String::format(L"result %1",
result == SUCCESS ? L"SUCCESS" : L"FAILURE"));
operationResultsStatus = result;
}
void
State::SetOperationResultsMessage(const String& message)
{
LOG_FUNCTION2(State::SetOperationResultsMessage, message);
operationResultsMessage = message;
}
String
State::GetParentDomainDnsName() const
{
LOG_FUNCTION2(
State::GetParentDomainDnsName,
parentDomainDnsName);
return parentDomainDnsName;
}
String
State::GetNewDomainDNSName() const
{
LOG_FUNCTION2(State::GetNewDomainDNSName, newDomainDnsName);
return newDomainDnsName;
}
String
State::GetNewDomainNetbiosName() const
{
LOG_FUNCTION2(
State::GetNewDomainNetbiosName,
newDomainFlatName);
return newDomainFlatName;
}
void
State::SetParentDomainDNSName(const String& name)
{
LOG_FUNCTION2(State::SetParentDomainDNSName, name);
ASSERT(!name.empty());
parentDomainDnsName = name;
}
void
State::SetNewDomainDNSName(const String& name)
{
LOG_FUNCTION2(State::SetNewDomainDNSName, name);
ASSERT(!name.empty());
newDomainDnsName = name;
// This will cause the flat name to be re-generated
newDomainFlatName.erase();
}
void
State::SetNewDomainNetbiosName(const String& name)
{
LOG_FUNCTION2(State::SetNewDomainNetbiosName, name);
ASSERT(!name.empty());
newDomainFlatName = name;
}
void
State::SetUserDomainName(const String& name)
{
LOG_FUNCTION2(State::SetUserDomainName, name);
// name may be empty;
userDomain = name;
}
String
State::GetUserDomainName() const
{
LOG_FUNCTION2(State::GetUserDomainName, userDomain);
return userDomain;
}
void
State::ClearHiddenWhileUnattended()
{
LOG_FUNCTION(State::ClearHiddenWhileUnattended);
runHiddenWhileUnattended = false;
// closes the splash dialog, if visible.
if (splash)
{
// this will delete splash, too
splash->SelfDestruct();
splash = 0;
}
}
bool
State::RunHiddenUnattended() const
{
// LOG_FUNCTION(State::RunHiddenUnattended);
return UsingAnswerFile() && runHiddenWhileUnattended;
}
bool
State::IsLastDCInDomain() const
{
LOG_FUNCTION2(State::IsLastDCInDomain, isLastDc ? L"true" : L"false");
return isLastDc;
}
void
State::SetIsLastDCInDomain(bool yesNo)
{
LOG_FUNCTION2(
State::SetIsLastDCInDomain,
yesNo ? L"is last dc" : L"is NOT last dc");
isLastDc = yesNo;
}
void
State::SetAdminPassword(const EncryptedString& password)
{
LOG_FUNCTION(State::SetAdminPassword);
adminPassword = password;
}
EncryptedString
State::GetAdminPassword() const
{
LOG_FUNCTION(State::GetAdminPassword);
return adminPassword;
}
String
State::GetOperationResultsMessage() const
{
LOG_FUNCTION2(
State::GetOperationResultsMessage,
operationResultsMessage);
return operationResultsMessage;
}
State::OperationResult
State::GetOperationResultsCode() const
{
LOG_FUNCTION2(
State::GetOperationResultsCode,
operationResultsStatus == SUCCESS ? L"SUCCESS" : L"FAILURE");
return operationResultsStatus;
}
bool
State::AutoConfigureDNS() const
{
LOG_FUNCTION2(
State::AutoConfigureDNS,
autoConfigDns ? L"true" : L"false");
return autoConfigDns;
}
void
State::SetAutoConfigureDNS(bool yesNo)
{
LOG_FUNCTION2(
State::SetAutoConfigureDNS,
yesNo ? L"true" : L"false");
autoConfigDns = yesNo;
}
bool
State::IsDNSOnNetwork() const
{
LOG_FUNCTION2(
State::IsDNSOnNetwork,
isDnsOnNet ? L"true" : L"false");
return isDnsOnNet;
}
void
State::SetDNSOnNetwork(bool yesNo)
{
LOG_FUNCTION2(
State::SetDNSOnNetwork,
yesNo ? L"true" : L"false");
isDnsOnNet = yesNo;
}
String
State::GetInstalledSite() const
{
LOG_FUNCTION2(State::GetInstalledSite, installedSite);
// should be set before we ask for it...
ASSERT(!installedSite.empty());
return installedSite;
}
void
State::SetInstalledSite(const String& site)
{
LOG_FUNCTION2(State::SetInstalledSite, site);
ASSERT(!site.empty());
installedSite = site;
}
void
State::AddFinishMessage(const String& message)
{
LOG_FUNCTION2(State::AddFinishMessage, message);
ASSERT(!message.empty());
if (finishMessages.empty())
{
finishMessages += message;
}
else
{
// add a blank line between each message
finishMessages += L"\r\n\r\n" + message;
}
}
String
State::GetFinishMessages() const
{
LOG_FUNCTION2(State::GetFinishMessages, finishMessages);
return finishMessages;
}
Computer&
State::GetComputer()
{
return computer;
}
void
State::SetFailureMessage(const String& message)
{
LOG_FUNCTION2(State::SetFailureMessage, message);
ASSERT(!message.empty());
failureMessage = message;
}
String
State::GetFailureMessage() const
{
LOG_FUNCTION2(State::GetFailureMessage, failureMessage);
return failureMessage;
}
bool
State::ShouldInstallAndConfigureDns() const
{
if (AutoConfigureDNS() || !IsDNSOnNetwork())
{
return true;
}
return false;
}
String
State::GetUserForestName() const
{
LOG_FUNCTION2(State::GetUserForestName, userForest);
ASSERT(!userForest.empty());
return userForest;
}
void
State::SetUserForestName(const String& forest)
{
LOG_FUNCTION2(State::SetUserForestName, forest);
ASSERT(!forest.empty());
userForest = forest;
}
bool
State::IsDomainInForest(const String& domain) const
{
LOG_FUNCTION2(State::IsDomainInForest, domain);
ASSERT(!domain.empty());
for (
DomainList::iterator i = domainsInForest.begin();
i != domainsInForest.end();
i++)
{
DNS_NAME_COMPARE_STATUS compare = Dns::CompareNames(*i, domain);
if (compare == DnsNameCompareEqual)
{
LOG(L"domain is in forest");
return true;
}
}
return false;
}
HRESULT
State::ReadDomains()
{
LOG_FUNCTION(State::ReadDomains);
domainsInForest.clear();
return ::ReadDomains(domainsInForest);
}
DNS_NAME_COMPARE_STATUS
State::DomainFitsInForest(const String& domain, String& conflictingDomain)
{
LOG_FUNCTION(domainFitsInForest);
ASSERT(!domain.empty());
conflictingDomain.erase();
DNS_NAME_COMPARE_STATUS relation = DnsNameCompareNotEqual;
for (
DomainList::iterator i = domainsInForest.begin();
i != domainsInForest.end();
i++)
{
relation = Dns::CompareNames(domain, *i);
switch (relation)
{
case DnsNameCompareNotEqual:
{
continue;
}
case DnsNameCompareEqual:
{
ASSERT(domain == *i);
// fall thru
}
case DnsNameCompareLeftParent:
case DnsNameCompareRightParent:
case DnsNameCompareInvalid:
default:
{
conflictingDomain = *i;
break;
}
}
break;
}
return relation;
}
bool
State::GetDomainReinstallFlag() const
{
LOG_FUNCTION2(
State::GetDomainReinstallFlag,
reinstallDomain ? L"true" : L"false");
return reinstallDomain;
}
void
State::SetDomainReinstallFlag(bool newValue)
{
LOG_FUNCTION2(
State::SetDomainReinstallFlag,
newValue ? L"true" : L"false");
reinstallDomain = newValue;
}
bool
State::ShouldAllowAnonymousAccess() const
{
LOG_FUNCTION2(
State::ShouldAllowAnonymousAccess,
allowAnonAccess ? L"true" : L"false");
return allowAnonAccess;
}
void
State::SetShouldAllowAnonymousAccess(bool yesNo)
{
LOG_FUNCTION2(
State::ShouldAllowAnonymousAccess,
yesNo ? L"true" : L"false");
allowAnonAccess = yesNo;
}
String
State::GetReplicationPartnerDC() const
{
LOG_FUNCTION2(State::GetReplicationPartnerDC, replicationPartnerDc);
return replicationPartnerDc;
}
void
State::SetReplicationPartnerDC(const String dcName)
{
LOG_FUNCTION2(State::SetReplicationPartnerDC, dcName);
replicationPartnerDc = dcName;
}
// Retrieve domain controller info for all DCs in the domain that this dc
// is a controller. (The result set should include this dc)
// Caller should free the result with DsFreeDomainControllerInfo
HRESULT
State::GetDomainControllerInfoForMyDomain(
DS_DOMAIN_CONTROLLER_INFO_2W*& info,
DWORD& dcCount)
{
LOG_FUNCTION(State::GetDomainControllerInfoForMyDomain);
// if this assertion does not hold, then the DsBind call below should
// fail.
ASSERT(GetComputer().IsDomainController());
dcCount = 0;
info = 0;
HRESULT hr = S_OK;
HANDLE hds = 0;
do
{
String domainDnsName = GetComputer().GetDomainDnsName();
String dcName = Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
ASSERT(!domainDnsName.empty());
ASSERT(!dcName.empty());
// Bind to self
hr =
MyDsBind(
dcName,
domainDnsName,
hds);
BREAK_ON_FAILED_HRESULT(hr);
// find all the dc's for my domain. the list should contain dcName.
// level 2 contains the "is gc" flag
hr =
MyDsGetDomainControllerInfo(
hds,
domainDnsName,
dcCount,
info);
BREAK_ON_FAILED_HRESULT(hr);
}
while (0);
if (hds)
{
::DsUnBind(&hds);
hds = 0;
}
return hr;
}
// returns true if no other domain controller for this DCs domain can be
// found in the DS. False otherwise
bool
State::IsReallyLastDcInDomain()
{
LOG_FUNCTION(State::IsReallyLastDcInDomain);
// Assume we are alone in the universe.
bool result = true;
do
{
// find all the dc's for my domain. the list should contain dcName.
DS_DOMAIN_CONTROLLER_INFO_2W* info = 0;
DWORD count = 0;
HRESULT hr = GetDomainControllerInfoForMyDomain(info, count);
BREAK_ON_FAILED_HRESULT(hr);
ASSERT(count);
ASSERT(info);
// if there are more than 1 entry (more than the one for this dc),
// then the DS believes that there are other DCs for this domain.
if (count > 1)
{
result = false;
}
#ifdef DBG
// double check that we found ourselves.
if (result && info[0].DnsHostName)
{
LOG(info[0].DnsHostName);
String dcName =
Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
ASSERT(
Dns::CompareNames(info[0].DnsHostName, dcName)
== DnsNameCompareEqual);
}
#endif
MyDsFreeDomainControllerInfo(count, info);
}
while (0);
LOG(
String::format(
L"This box %1 the sole DC for the domain",
result ? L"is" : L"is NOT"));
return result;
}
// Returns true if this computer is a global catalog
bool
State::IsGlobalCatalog()
{
LOG_FUNCTION(State::IsGlobalCatalog);
if (!GetComputer().IsDomainController())
{
// can't possibly be a GC if not a DC
return false;
}
bool result = false;
do
{
String dcName = Win::GetComputerNameEx(ComputerNameDnsFullyQualified);
// find all the dc's for my domain. the list should contain dcName.
// level 2 contains the "is gc" flag
DS_DOMAIN_CONTROLLER_INFO_2W* info = 0;
DWORD count = 0;
HRESULT hr = GetDomainControllerInfoForMyDomain(info, count);
BREAK_ON_FAILED_HRESULT(hr);
// there should be at least 1 entry (ourself)
ASSERT(count);
ASSERT(info);
for (size_t i = 0; i < count; i++)
{
if (info[i].DnsHostName) // 340723
{
LOG(info[i].DnsHostName);
if (
Dns::CompareNames(info[i].DnsHostName, dcName)
== DnsNameCompareEqual)
{
// we found ourselves in the list
LOG(L"found!");
result = info[i].fIsGc ? true : false;
break;
}
}
}
MyDsFreeDomainControllerInfo(count, info);
}
while (0);
LOG(
String::format(
L"This box %1 a global catalog",
result ? L"is" : L"is NOT"));
return result;
}
EncryptedString
State::GetSafeModeAdminPassword() const
{
LOG_FUNCTION(State::GetSafeModeAdminPassword);
// don't trace the password!
return safeModeAdminPassword;
}
void
State::SetSafeModeAdminPassword(const EncryptedString& pwd)
{
LOG_FUNCTION(State::SetSafeModeAdminPassword);
// don't trace the password!
// pwd may be empty.
safeModeAdminPassword = pwd;
}
String
State::GetAdminToolsShortcutPath() const
{
LOG_FUNCTION2(State::GetAdminToolsShortcutPath, shortcutPath);
return shortcutPath;
}
bool
State::NeedsCommandLineHelp() const
{
return needsCommandLineHelp;
}
bool
State::IsAdvancedMode() const
{
return isAdvancedMode;
}
void
State::SetReplicateFromMedia(bool yesNo)
{
LOG_FUNCTION2(
State::SetReplicateFromMedia,
yesNo ? L"true" : L"false");
replicateFromMedia = yesNo;
}
void
State::SetReplicationSourcePath(const String& path)
{
LOG_FUNCTION2(State::SetReplicationSourcePath, path);
sourcePath = path;
}
bool
State::ReplicateFromMedia() const
{
LOG_FUNCTION2(
State::ReplicateFromMedia,
replicateFromMedia ? L"true" : L"false");
return replicateFromMedia;
}
String
State::GetReplicationSourcePath() const
{
LOG_FUNCTION2(State::GetReplicationSourcePath, sourcePath);
return sourcePath;
}
void
State::SetSyskeyLocation(SyskeyLocation loc)
{
LOG_FUNCTION2(State::SetSyskeyLocation,
loc == DISK
? L"disk"
: ((loc == PROMPT) ? L"prompt" : L"stored"));
syskeyLocation = loc;
}
State::SyskeyLocation
State::GetSyskeyLocation() const
{
LOG_FUNCTION2(
State::IsSyskeyPresent,
syskeyLocation == DISK
? L"disk"
: ((syskeyLocation == PROMPT) ? L"prompt" : L"stored"));
return syskeyLocation;
}
void
State::SetIsBackupGc(bool yesNo)
{
LOG_FUNCTION2(State::SetIsBackupGc, yesNo ? L"true" : L"false");
isBackupGc = yesNo;
}
bool
State::IsBackupGc() const
{
LOG_FUNCTION2(State::IsBackupGc, isBackupGc ? L"true" : L"false");
return isBackupGc;
}
void
State::SetSyskey(const EncryptedString& syskey_)
{
// don't log the syskey!
LOG_FUNCTION(State::SetSyskey);
ASSERT(!syskey_.IsEmpty());
syskey = syskey_;
}
EncryptedString
State::GetSyskey() const
{
// don't log the syskey!
LOG_FUNCTION(State::GetSyskey);
return syskey;
}
void
State::SetRestoreGc(bool yesNo)
{
LOG_FUNCTION2(State::SetRestoreGc, yesNo ? L"true" : L"false");
restoreGc = yesNo;
}
bool
State::GetRestoreGc() const
{
LOG_FUNCTION2(State::GetRestoreGc, restoreGc ? L"true" : L"false");
return restoreGc;
}
bool
State::IsSafeModeAdminPwdOptionPresent() const
{
LOG_FUNCTION(State::IsSafeModeAdminPwdOptionPresent);
ASSERT(UsingAnswerFile());
bool result = false;
if (answerFile)
{
result = answerFile->IsSafeModeAdminPwdOptionPresent();
}
LOG(result ? L"true" : L"false");
return result;
}
void
State::SetDomainControllerReinstallFlag(bool newValue)
{
LOG_FUNCTION2(
State::SetDomainControllerReinstallFlag,
newValue ? L"true" : L"false");
reinstallDomainController = newValue;
}
bool
State::GetDomainControllerReinstallFlag() const
{
LOG_FUNCTION2(
State::GetDomainControllerReinstallFlag,
reinstallDomain ? L"true" : L"false");
return reinstallDomainController;
}
void
State::SetOperationResultsFlags(ULONG flags)
{
LOG_FUNCTION2(
State::SetOperationResultsFlags,
String::format(L"0x%1!X!", flags));
operationResultsFlags = flags;
}
ULONG
State::GetOperationResultsFlags() const
{
LOG_FUNCTION2(
State::GetOperationResultsFlags,
String::format(L"0x%1!X!", operationResultsFlags));
return operationResultsFlags;
}
bool
State::IsOperationRetryAllowed() const
{
LOG_FUNCTION(State::IsOperationRetryAllowed);
bool result = true;
if (operationResultsFlags & DSROLE_IFM_RESTORED_DATABASE_FILES_MOVED)
{
// don't allow the user to retry the operation again, as one consequence
// of the failure is that the moved files are now trashed. The user
// must re-restore the files in order to attempt the operation again.
// NTRAID#NTBUG9-296872-2001/01/29-sburns
LOG(L"ifm files moved, retry not allowed");
result = false;
}
// NTRAID#NTBUG9-416968-2001/06/14-sburns
#ifdef DBG
if (IsExitOnFailureMode())
{
// don't allow retry on failure in this mode. This will cause the
// retry logic in the promote thread to be skipped.
//
LOG(L"exit-on-failure mode trumps retry");
result = false;
}
#endif
LOG(result ? L"true" : L"false");
return result;
}
// needing a reboot is a "sticky" setting: there's no way to turn it off.
// if you once needed to reboot the machine, you will always need to reboot
// the machine. (at least, for now).
void
State::SetNeedsReboot()
{
LOG_FUNCTION(State::SetNeedsReboot);
needsReboot = true;
}
bool
State::GetNeedsReboot() const
{
LOG_FUNCTION2(State::GetNeedsReboot, needsReboot ? L"true" : L"false");
return needsReboot;
}
void
State::SetSetForestVersionFlag(bool setVersion)
{
LOG_FUNCTION2(
State::SetSetForestVersionFlag,
setVersion ? L"true" : L"false");
setForestVersion = setVersion;
}
bool
State::GetSetForestVersionFlag() const
{
LOG_FUNCTION2(
State::GetSetForestVersionFlag,
setForestVersion ? L"true" : L"false");
return setForestVersion;
}
// NTRAID#NTBUG9-416968-2001/06/14-sburns
#ifdef DBG
bool
State::IsExitOnFailureMode() const
{
LOG_FUNCTION2(
State::IsExitOnFailureMode,
isExitOnFailureMode ? L"true" : L"false");
return isExitOnFailureMode;
}
#endif
bool
State::IsLastAppPartitionReplica()
{
LOG_FUNCTION(State::IsLastAppPartitionReplica);
bool result = false;
partitionList.clear();
do
{
RunContext context = GetInstance().GetRunContext();
if (context != State::NT5_DC)
{
// not a DC, so can't be replica of any NCs
LOG(L"not a DC");
break;
}
// Find any non-domain NCs for which this DC is the last replica
HRESULT hr = IsLastNonDomainNamingContextReplica(partitionList);
if (FAILED(hr))
{
LOG(L"Failed to determine if the machine is last replica of NDNCs");
ASSERT(result == false);
// This is not an error condition that we'll deal with here. We
// will end up passing an empty list to the demote API, which will
// then fail, and we will catch the failure.
break;
}
if (hr == S_FALSE)
{
LOG(L"Not last replica of non-domain NCs");
ASSERT(result == false);
break;
}
result = true;
// there should be at least one DN in the list.
ASSERT(partitionList.size());
}
while (0);
LOG(result ? L"true" : L"false");
return result;
}
const StringList&
State::GetAppPartitionList() const
{
LOG_FUNCTION(State::GetAppPartitionList);
return partitionList;
}
// Returns true if the registry option to not configure the dns client to
// point to itself is absent or non-zero, false otherwise.
// NTRAID#NTBUG9-446484-2001/10/11-sburns
bool
State::ShouldConfigDnsClient() const
{
LOG_FUNCTION(State::ShouldConfigDnsClient);
LOG_BOOL(shouldConfigDnsClient);
return shouldConfigDnsClient;
}
// NTRAID#NTBUG9-496409-2001/11/29-sburns
bool
State::IsForcedDemotion() const
{
LOG_FUNCTION2(
State::IsForcedDemotion,
isForcedDemotion ? L"true" : L"false");
return isForcedDemotion;
}