// Copyright (c) 1997-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" static State* stateInstance = 0; State::State() : dhcpServerAvailable(false), dhcpAvailabilityRetrieved(false), hasStateBeenRetrieved(false), rerunWizard(true), productSKU(CYS_SERVER), hasNTFSDrive(false), computerName() { LOG_CTOR(State); } 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::IsDC() const { LOG_FUNCTION(State::IsDC); bool result = false; do { DSROLE_PRIMARY_DOMAIN_INFO_BASIC* info = 0; HRESULT hr = MyDsRoleGetPrimaryDomainInformation(0, info); if(FAILED(hr)) { LOG(String::format( L"Failed MyDsRoleGetPrimaryDomainInformation(0): hr = 0x%1!x!", hr)); break; } if (info && (info->MachineRole == DsRole_RolePrimaryDomainController || info->MachineRole == DsRole_RoleBackupDomainController) ) { result = true; } ::DsRoleFreeMemory(info); } while (false); 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::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; } int State::GetNICCount() const { return adapterConfiguration.GetNICCount(); } NetworkInterface State::GetNIC(unsigned int nicIndex) { LOG_FUNCTION2( State::GetNIC, String::format( L"%1!d!", nicIndex)); return adapterConfiguration.GetNIC(nicIndex); } bool State::RetrieveMachineConfigurationInformation(HWND /*hwndParent*/) { LOG_FUNCTION(State::RetrieveMachineConfigurationInformation); ASSERT(!hasStateBeenRetrieved); // For now I will make this a synchronous action. // We should have some sort of fancy UI that lets // the user know we are progressing Win::WaitCursor cursor; // 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 HRESULT hr = RetrieveNICInformation(); if (SUCCEEDED(hr)) { // Only bother to check for a DHCP server on the network if we are not // a DC and only have one NIC. Right now we only use this info // for determining whether or not to show the Express path option if (!(IsDC() || IsUpgradeState()) && (GetNICCount() == 1)) { CheckDhcpServer(); } } RetrieveProductSKU(); RetrievePlatform(); // Retrieve the drive information (quotas enabled, partition types, etc.) RetrieveDriveInformation(); hasStateBeenRetrieved = true; return true; } void State::RetrieveProductSKU() { LOG_FUNCTION(State::RetrieveProductSKU); // I am making the assumption that we are on a // Server SKU if GetVersionEx fails productSKU = CYS_SERVER; OSVERSIONINFOEX info; HRESULT hr = Win::GetVersionEx(info); if (SUCCEEDED(hr)) { do { if (info.wSuiteMask & VER_SUITE_DATACENTER) { // datacenter productSKU = CYS_DATACENTER_SERVER; break; } if (info.wSuiteMask & VER_SUITE_ENTERPRISE) { // advanced server productSKU = CYS_ADVANCED_SERVER; break; } if (info.wSuiteMask & VER_SUITE_PERSONAL) { // personal productSKU = CYS_PERSONAL; break; } if (info.wProductType == VER_NT_WORKSTATION) { // profesional productSKU = CYS_PROFESSIONAL; } else { // server productSKU = CYS_SERVER; } } while (false); } LOG(String::format(L"Product SKU = 0x%1!x!", productSKU )); return; } 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_ALPHA64: 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() { LOG_FUNCTION(State::CheckDhcpServer); // This should loop through all network interfaces // seeing if we can obtain a lease on any of them if (GetNICCount() > 0) { DWORD nicIPAddress = GetNIC(0).GetIPAddress(0); // force to bool dhcpServerAvailable = (IsDHCPAvailableOnInterface(nicIPAddress) != 0); } dhcpAvailabilityRetrieved = true; LOG_BOOL(dhcpServerAvailable); } 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; }