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.
935 lines
19 KiB
935 lines
19 KiB
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// File: state.cpp
|
|
//
|
|
// Synopsis: Defines the state object that is global
|
|
// to CYS. It holds the network and OS/SKU info
|
|
//
|
|
// History: 02/02/2001 JeffJon Created
|
|
|
|
#include "pch.h"
|
|
|
|
#include "state.h"
|
|
#include "cys.h"
|
|
|
|
static State* stateInstance = 0;
|
|
|
|
|
|
State::State() :
|
|
dhcpServerAvailableOnAllNics(true),
|
|
dhcpAvailabilityRetrieved(false),
|
|
hasStateBeenRetrieved(false),
|
|
rerunWizard(true),
|
|
isRebootScenario(false),
|
|
productSKU(CYS_SERVER),
|
|
hasNTFSDrive(false),
|
|
localComputer(),
|
|
computerName(),
|
|
domainDNSName(),
|
|
domainNetbiosName(),
|
|
wizardStartPage(0)
|
|
{
|
|
LOG_CTOR(State);
|
|
|
|
HRESULT unused = localComputer.Refresh();
|
|
ASSERT(SUCCEEDED(unused));
|
|
|
|
RetrievePlatform();
|
|
}
|
|
|
|
|
|
void
|
|
State::Destroy()
|
|
{
|
|
LOG_FUNCTION(State::Destroy);
|
|
|
|
if (stateInstance)
|
|
{
|
|
delete stateInstance;
|
|
stateInstance = 0;
|
|
}
|
|
}
|
|
|
|
|
|
State&
|
|
State::GetInstance()
|
|
{
|
|
if (!stateInstance)
|
|
{
|
|
stateInstance = new State();
|
|
}
|
|
|
|
ASSERT(stateInstance);
|
|
|
|
return *stateInstance;
|
|
}
|
|
|
|
bool
|
|
State::IsRemoteSession() const
|
|
{
|
|
LOG_FUNCTION(State::IsRemoteSession);
|
|
|
|
bool result =
|
|
Win::GetSystemMetrics(SM_REMOTESESSION) ?
|
|
true : false;
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsWindowsSetupRunning() const
|
|
{
|
|
LOG_FUNCTION(State::IsWindowsSetupRunning);
|
|
|
|
bool result = false;
|
|
|
|
// Try to create a mutex for the default
|
|
// sysoc inf file. If it already exists
|
|
// then we know SYSOCMGR is running
|
|
|
|
static const String mutexName = L"Global\\sysoc";
|
|
|
|
HANDLE mutexHandle = INVALID_HANDLE_VALUE;
|
|
|
|
HRESULT hr =
|
|
Win::CreateMutex(
|
|
0,
|
|
true,
|
|
mutexName,
|
|
mutexHandle);
|
|
|
|
if (hr == Win32ToHresult(ERROR_ALREADY_EXISTS))
|
|
{
|
|
// SysOCMGR is running
|
|
|
|
result = true;
|
|
}
|
|
|
|
|
|
if (mutexHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
// Close the handle
|
|
|
|
Win::CloseHandle(mutexHandle);
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsDC() const
|
|
{
|
|
LOG_FUNCTION(State::IsDC);
|
|
|
|
bool result = localComputer.IsDomainController();
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsDCPromoRunning() const
|
|
{
|
|
LOG_FUNCTION(State::IsDCPromoRunning);
|
|
|
|
// Uses the IsDcpromoRunning from Burnslib
|
|
|
|
bool result = IsDcpromoRunning();
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsDCPromoPendingReboot() const
|
|
{
|
|
LOG_FUNCTION(State::IsDCPromoPendingReboot);
|
|
|
|
bool result = false;
|
|
|
|
do
|
|
{
|
|
// Uses the IsDcpromoRunning from Burnslib
|
|
|
|
if (!IsDcpromoRunning())
|
|
{
|
|
// this test is redundant if dcpromo is running, so only
|
|
// perform it when dcpromo is not running.
|
|
|
|
DSROLE_OPERATION_STATE_INFO* info = 0;
|
|
HRESULT hr = MyDsRoleGetPrimaryDomainInformation(0, info);
|
|
if (SUCCEEDED(hr) && info)
|
|
{
|
|
if (info->OperationState == DsRoleOperationNeedReboot)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
::DsRoleFreeMemory(info);
|
|
}
|
|
}
|
|
|
|
} while (false);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsJoinedToDomain() const
|
|
{
|
|
LOG_FUNCTION(State::IsJoinedToDomain);
|
|
|
|
bool result = localComputer.IsJoinedToDomain();
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsUpgradeState() const
|
|
{
|
|
LOG_FUNCTION(State::IsUpgradeState);
|
|
|
|
bool result = false;
|
|
|
|
do
|
|
{
|
|
DSROLE_UPGRADE_STATUS_INFO* info = 0;
|
|
HRESULT hr = MyDsRoleGetPrimaryDomainInformation(0, info);
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"MyDsRoleGetPrimaryDomainInformation(0): hr = 0x%1!x!",
|
|
hr));
|
|
|
|
break;
|
|
}
|
|
|
|
if (info && info->OperationState == DSROLE_UPGRADE_IN_PROGRESS)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
::DsRoleFreeMemory(info);
|
|
} while (false);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::IsFirstDC() const
|
|
{
|
|
LOG_FUNCTION(State::IsFirstDC);
|
|
|
|
DWORD value = 0;
|
|
bool result = GetRegKeyValue(CYS_FIRST_DC_REGKEY, CYS_FIRST_DC_VALUE, value);
|
|
|
|
if (value != 1)
|
|
{
|
|
result = false;
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
unsigned int
|
|
State::GetNICCount() const
|
|
{
|
|
return adapterConfiguration.GetNICCount();
|
|
}
|
|
|
|
unsigned int
|
|
State::GetNonModemNICCount()
|
|
{
|
|
unsigned int result = 0;
|
|
|
|
for (
|
|
unsigned int index = 0;
|
|
index < GetNICCount();
|
|
++index)
|
|
{
|
|
NetworkInterface* nic = GetNIC(index);
|
|
|
|
if (nic &&
|
|
!nic->IsModem())
|
|
{
|
|
++result;
|
|
}
|
|
}
|
|
|
|
LOG(
|
|
String::format(
|
|
L"Non-modem NIC count: %1!d!",
|
|
result));
|
|
|
|
return result;
|
|
}
|
|
|
|
NetworkInterface*
|
|
State::GetNIC(unsigned int nicIndex)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::GetNIC,
|
|
String::format(
|
|
L"%1!d!",
|
|
nicIndex));
|
|
|
|
return adapterConfiguration.GetNIC(nicIndex);
|
|
}
|
|
|
|
NetworkInterface*
|
|
State::GetNICFromName(const String& name, bool& found)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::GetNICFromName,
|
|
name.c_str());
|
|
|
|
return adapterConfiguration.GetNICFromName(name, found);
|
|
}
|
|
|
|
NetworkInterface*
|
|
State::GetLocalNICFromRegistry()
|
|
{
|
|
LOG_FUNCTION(State::GetLocalNICFromRegistry);
|
|
|
|
// Read the local NIC GUID from the registry
|
|
|
|
String nicName;
|
|
NetworkInterface* nic = 0;
|
|
|
|
if (!GetRegKeyValue(
|
|
CYS_FIRST_DC_REGKEY,
|
|
CYS_FIRST_DC_LOCAL_NIC,
|
|
nicName))
|
|
{
|
|
LOG(L"Failed to read LocalNIC regkey, using default local NIC");
|
|
|
|
nic = State::GetInstance().GetLocalNIC();
|
|
|
|
if (nic)
|
|
{
|
|
nicName = nic->GetName();
|
|
}
|
|
}
|
|
|
|
SetLocalNIC(nicName, false);
|
|
|
|
if (!nic)
|
|
{
|
|
nic = GetLocalNIC();
|
|
}
|
|
return nic;
|
|
}
|
|
|
|
bool
|
|
State::RetrieveMachineConfigurationInformation(
|
|
HWND progressStatic,
|
|
bool doDHCPCheck,
|
|
int nicInfoResID,
|
|
int osInfoResID,
|
|
int defaultConnectionResID,
|
|
int detectSettingsResID)
|
|
{
|
|
LOG_FUNCTION(State::RetrieveMachineConfigurationInformation);
|
|
|
|
ASSERT(!hasStateBeenRetrieved);
|
|
|
|
// This is used to get the minimal information needed to
|
|
// determine if we should enable the express path
|
|
// This should probably just be changed to gather the
|
|
// information and let the page decide what to do
|
|
|
|
if (progressStatic)
|
|
{
|
|
Win::SetWindowText(
|
|
progressStatic,
|
|
String::load(nicInfoResID));
|
|
}
|
|
|
|
HRESULT hr = RetrieveNICInformation();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
// Only bother to check for a DHCP server on the network if we are not
|
|
// a DC, not a DNS server, not a DHCP server and have at least one NIC.
|
|
// Right now we only use this info for determining whether or not to
|
|
// show the Express path option
|
|
|
|
if (!(IsDC() || IsUpgradeState()) &&
|
|
(GetNICCount() > 0) &&
|
|
doDHCPCheck)
|
|
{
|
|
CheckDhcpServer(
|
|
progressStatic,
|
|
defaultConnectionResID,
|
|
detectSettingsResID);
|
|
}
|
|
}
|
|
|
|
if (progressStatic)
|
|
{
|
|
Win::SetWindowText(
|
|
progressStatic,
|
|
String::load(osInfoResID));
|
|
}
|
|
|
|
RetrieveProductSKU();
|
|
RetrievePlatform();
|
|
|
|
// Retrieve the drive information (quotas enabled, partition types, etc.)
|
|
|
|
RetrieveDriveInformation();
|
|
|
|
hasStateBeenRetrieved = true;
|
|
return true;
|
|
}
|
|
|
|
DWORD
|
|
State::RetrieveProductSKU()
|
|
{
|
|
LOG_FUNCTION(State::RetrieveProductSKU);
|
|
|
|
// I am making the assumption that we are on a
|
|
// Server SKU if GetVersionEx fails
|
|
|
|
productSKU = CYS_UNSUPPORTED_SKU;
|
|
|
|
OSVERSIONINFOEX info;
|
|
HRESULT hr = Win::GetVersionEx(info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"wSuiteMask = 0x%1!x!",
|
|
info.wSuiteMask));
|
|
LOG(String::format(
|
|
L"wProductType = 0x%1!x!",
|
|
info.wProductType));
|
|
|
|
do
|
|
{
|
|
if (info.wProductType == VER_NT_SERVER ||
|
|
info.wProductType == VER_NT_DOMAIN_CONTROLLER)
|
|
{
|
|
|
|
if (info.wSuiteMask & VER_SUITE_DATACENTER)
|
|
{
|
|
// datacenter
|
|
|
|
productSKU = CYS_DATACENTER_SERVER;
|
|
break;
|
|
}
|
|
else if (info.wSuiteMask & VER_SUITE_ENTERPRISE)
|
|
{
|
|
// advanced server
|
|
|
|
productSKU = CYS_ADVANCED_SERVER;
|
|
break;
|
|
}
|
|
else if (info.wSuiteMask & VER_SUITE_SMALLBUSINESS ||
|
|
info.wSuiteMask & VER_SUITE_BACKOFFICE ||
|
|
info.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED ||
|
|
info.wSuiteMask & VER_SUITE_EMBEDDEDNT ||
|
|
info.wSuiteMask & VER_SUITE_BLADE)
|
|
{
|
|
// Unsupported server
|
|
|
|
productSKU = CYS_UNSUPPORTED_SKU;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// default to standard server
|
|
|
|
productSKU = CYS_SERVER;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// All other SKUs are unsupported
|
|
|
|
productSKU = CYS_UNSUPPORTED_SKU;
|
|
|
|
} while (false);
|
|
}
|
|
LOG(String::format(L"Product SKU = 0x%1!x!", productSKU ));
|
|
|
|
return productSKU;
|
|
}
|
|
|
|
void
|
|
State::RetrievePlatform()
|
|
{
|
|
LOG_FUNCTION(State::RetrievePlatform);
|
|
|
|
// I am making the assumption that we are not on a
|
|
// 64bit machine if GetSystemInfo fails
|
|
|
|
SYSTEM_INFO info;
|
|
Win::GetSystemInfo(info);
|
|
|
|
switch (info.wProcessorArchitecture)
|
|
{
|
|
case PROCESSOR_ARCHITECTURE_IA64:
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|
platform = CYS_64BIT;
|
|
break;
|
|
|
|
default:
|
|
platform = CYS_32BIT;
|
|
break;
|
|
}
|
|
|
|
LOG(String::format(L"Platform = 0x%1!x!", platform));
|
|
|
|
return;
|
|
}
|
|
|
|
HRESULT
|
|
State::RetrieveNICInformation()
|
|
{
|
|
ASSERT(!hasStateBeenRetrieved);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!adapterConfiguration.IsInitialized())
|
|
{
|
|
hr = adapterConfiguration.Initialize();
|
|
}
|
|
|
|
LOG_HRESULT(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
void
|
|
State::CheckDhcpServer(
|
|
HWND progressStatic,
|
|
int defaultConnectionNameResID,
|
|
int detectSettingsResID)
|
|
{
|
|
LOG_FUNCTION(State::CheckDhcpServer);
|
|
|
|
// This should loop through all network interfaces
|
|
// seeing if we can obtain a lease on any of them
|
|
|
|
for (unsigned int idx = 0; idx < GetNICCount(); ++idx)
|
|
{
|
|
NetworkInterface* nic = GetNIC(idx);
|
|
|
|
if (!nic)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Update the text on the NetDetectProgressDialog
|
|
|
|
String progress =
|
|
String::format(
|
|
detectSettingsResID,
|
|
nic->GetFriendlyName(
|
|
String::load(defaultConnectionNameResID)).c_str());
|
|
|
|
if (progressStatic)
|
|
{
|
|
Win::SetWindowText(progressStatic, progress);
|
|
}
|
|
|
|
// Now try to renew the lease
|
|
|
|
if (!nic->CanDetectDHCPServer())
|
|
{
|
|
dhcpServerAvailableOnAllNics = false;
|
|
|
|
// Don't break because we need to retrieve the
|
|
// avialability of a DHCP server on all NICs
|
|
}
|
|
}
|
|
dhcpAvailabilityRetrieved = true;
|
|
|
|
LOG_BOOL(dhcpServerAvailableOnAllNics);
|
|
}
|
|
|
|
|
|
bool
|
|
State::HasNTFSDrive() const
|
|
{
|
|
LOG_FUNCTION(State::HasNTFSDrive);
|
|
|
|
return hasNTFSDrive;
|
|
}
|
|
|
|
void
|
|
State::RetrieveDriveInformation()
|
|
{
|
|
LOG_FUNCTION(State::RetrieveDriveInformation);
|
|
|
|
do
|
|
{
|
|
// Get a list of the valid drives
|
|
|
|
StringVector dl;
|
|
HRESULT hr = FS::GetValidDrives(std::back_inserter(dl));
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(L"Failed to GetValidDrives: hr = %1!x!", hr));
|
|
break;
|
|
}
|
|
|
|
// Loop through the list
|
|
|
|
ASSERT(dl.size());
|
|
for (
|
|
StringVector::iterator i = dl.begin();
|
|
i != dl.end();
|
|
++i)
|
|
{
|
|
// look for the NTFS partition
|
|
|
|
FS::FSType fsType = FS::GetFileSystemType(*i);
|
|
if (fsType == FS::NTFS5 ||
|
|
fsType == FS::NTFS4)
|
|
{
|
|
// found one. good to go
|
|
|
|
LOG(String::format(L"%1 is NTFS", i->c_str()));
|
|
|
|
hasNTFSDrive = true;
|
|
break;
|
|
}
|
|
}
|
|
} while (false);
|
|
|
|
LOG_BOOL(hasNTFSDrive);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
void
|
|
State::SetRerunWizard(bool rerun)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::SetRerunWizard,
|
|
rerun ? L"true" : L"false");
|
|
|
|
rerunWizard = rerun;
|
|
}
|
|
*/
|
|
|
|
bool
|
|
State::SetHomeRegkey(const String& newKeyValue)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::SetHomeRegkey,
|
|
newKeyValue);
|
|
|
|
bool result = SetRegKeyValue(
|
|
CYS_HOME_REGKEY,
|
|
CYS_HOME_VALUE,
|
|
newKeyValue,
|
|
HKEY_LOCAL_MACHINE,
|
|
true);
|
|
ASSERT(result);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
State::GetHomeRegkey(String& keyValue) const
|
|
{
|
|
LOG_FUNCTION(State::GetHomeRegkey);
|
|
|
|
bool result = GetRegKeyValue(
|
|
CYS_HOME_REGKEY,
|
|
CYS_HOME_VALUE,
|
|
keyValue);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
String
|
|
State::GetComputerName()
|
|
{
|
|
LOG_FUNCTION(State::GetComputerName);
|
|
|
|
if (computerName.empty())
|
|
{
|
|
computerName = Win::GetComputerNameEx(ComputerNameDnsHostname);
|
|
}
|
|
|
|
LOG(computerName);
|
|
return computerName;
|
|
}
|
|
|
|
String
|
|
State::GetDomainDNSName()
|
|
{
|
|
LOG_FUNCTION(State::GetDomainDNSName);
|
|
|
|
if (domainDNSName.empty())
|
|
{
|
|
domainDNSName = localComputer.GetDomainDnsName();
|
|
}
|
|
|
|
LOG(domainDNSName);
|
|
return domainDNSName;
|
|
}
|
|
|
|
String
|
|
State::GetDomainNetbiosName()
|
|
{
|
|
LOG_FUNCTION(State::GetDomainNetbiosName);
|
|
|
|
if (domainNetbiosName.empty())
|
|
{
|
|
domainNetbiosName = localComputer.GetDomainNetbiosName();
|
|
}
|
|
|
|
LOG(domainNetbiosName);
|
|
return domainNetbiosName;
|
|
}
|
|
|
|
bool
|
|
State::HasDNSServerOnAnyNicToForwardTo()
|
|
{
|
|
LOG_FUNCTION(State::HasDNSServerOnAnyNicToForwardTo);
|
|
|
|
// A valid DNS server is considered to be any DNS
|
|
// server defined on any NIC that does not point
|
|
// to itself for resolution. The reason I consider
|
|
// a DNS server that points to itself as invalid is
|
|
// because this routine is used to determine if the
|
|
// DNS server can be used as a forwarder. Since DNS
|
|
// servers cannot forward to themselves I consider
|
|
// this an invalid DNS server.
|
|
// Also consider the "next available" IP address to
|
|
// be invalid because chances are the "next available"
|
|
// IP address will be used as the static IP address
|
|
// of this server in the express path.
|
|
|
|
bool result = false;
|
|
|
|
DWORD nextAvailableAddress =
|
|
GetNextAvailableIPAddress(
|
|
CYS_DEFAULT_IPADDRESS,
|
|
CYS_DEFAULT_SUBNETMASK);
|
|
|
|
for (unsigned int idx = 0; idx < GetNICCount(); ++idx)
|
|
{
|
|
IPAddressList dnsServers;
|
|
|
|
NetworkInterface* nic = GetNIC(idx);
|
|
|
|
if (!nic)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
nic->GetDNSServers(dnsServers);
|
|
|
|
if (dnsServers.empty())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Only return true if there is a DNS server in the list
|
|
// and the IP address is not the local machine
|
|
|
|
DWORD ipaddress = nic->GetIPAddress(0);
|
|
|
|
for (IPAddressList::iterator itr = dnsServers.begin();
|
|
itr != dnsServers.end();
|
|
++itr)
|
|
{
|
|
DWORD currentServer = *itr;
|
|
|
|
if (ipaddress != currentServer &&
|
|
ipaddress != nextAvailableAddress)
|
|
{
|
|
LOG(String::format(
|
|
L"Found valid server: %1",
|
|
IPAddressToString(currentServer).c_str()));
|
|
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
return result;
|
|
}
|
|
|
|
void
|
|
State::SetLocalNIC(
|
|
String guid,
|
|
bool setInRegistry)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::SetLocalNIC,
|
|
guid.c_str());
|
|
|
|
LOG_BOOL(setInRegistry);
|
|
adapterConfiguration.SetLocalNIC(guid, setInRegistry);
|
|
}
|
|
|
|
NetworkInterface*
|
|
State::GetLocalNIC()
|
|
{
|
|
LOG_FUNCTION(State::GetLocalNIC);
|
|
|
|
return adapterConfiguration.GetLocalNIC();
|
|
}
|
|
|
|
bool
|
|
State::IsRebootScenario() const
|
|
{
|
|
LOG_FUNCTION(State::IsRebootScenario);
|
|
|
|
LOG_BOOL(isRebootScenario);
|
|
return isRebootScenario;
|
|
}
|
|
|
|
void
|
|
State::SetRebootScenario(bool reboot)
|
|
{
|
|
LOG_FUNCTION(State::SetRebootScenario);
|
|
LOG_BOOL(reboot);
|
|
|
|
isRebootScenario = reboot;
|
|
}
|
|
|
|
bool
|
|
State::ShouldRunMYS() const
|
|
{
|
|
LOG_FUNCTION(State::ShouldRunMYS);
|
|
|
|
bool result = false;
|
|
|
|
do
|
|
{
|
|
// First check to be sure this is a supported SKU
|
|
|
|
if (!::IsSupportedSku())
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Now check the startup flags
|
|
|
|
if (!::IsStartupFlagSet())
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Check the policy setting
|
|
|
|
if (!::ShouldShowMYSAccordingToPolicy())
|
|
{
|
|
// The policy is enabled so that means don't show MYS
|
|
|
|
break;
|
|
}
|
|
|
|
// everything passed so we should run MYS
|
|
|
|
result = true;
|
|
} while (false);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
DWORD
|
|
State::GetNextAvailableIPAddress(
|
|
DWORD startAddress,
|
|
DWORD subnetMask)
|
|
{
|
|
LOG_FUNCTION2(
|
|
State::GetNextAvailableIPAddress,
|
|
IPAddressToString(startAddress));
|
|
|
|
DWORD result = startAddress;
|
|
DWORD currentAddress = startAddress;
|
|
|
|
bool isIPInUse = false;
|
|
|
|
do
|
|
{
|
|
isIPInUse = false;
|
|
|
|
// Check to see if the IP address
|
|
// is in use on any NIC. If it is
|
|
// then increment and try all the NICs
|
|
// again.
|
|
|
|
for (
|
|
unsigned int index = 0;
|
|
index < GetNICCount();
|
|
++index)
|
|
{
|
|
NetworkInterface* nic = GetNIC(index);
|
|
|
|
if (nic)
|
|
{
|
|
bool isInUseOnThisNIC =
|
|
nic->IsIPAddressInUse(
|
|
currentAddress,
|
|
subnetMask);
|
|
|
|
isIPInUse = isIPInUse || isInUseOnThisNIC;
|
|
}
|
|
|
|
if (isIPInUse)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isIPInUse)
|
|
{
|
|
++currentAddress;
|
|
|
|
if ((currentAddress & subnetMask) != (startAddress & subnetMask))
|
|
{
|
|
// REVIEW_JEFFJON : what should the behavior be if there are
|
|
// no available addresses? Is this likely to happen?
|
|
|
|
// Since we couldn't find an available address in this subnet
|
|
// use the start address
|
|
|
|
currentAddress = startAddress;
|
|
break;
|
|
}
|
|
}
|
|
} while (isIPInUse);
|
|
|
|
result = currentAddress;
|
|
|
|
LOG(IPAddressToString(result));
|
|
|
|
return result;
|
|
}
|