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.
1132 lines
31 KiB
1132 lines
31 KiB
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// File: DHCPInstallationUnit.cpp
|
|
//
|
|
// Synopsis: Defines a DHCPInstallationUnit
|
|
// This object has the knowledge for installing the
|
|
// DHCP service
|
|
//
|
|
// History: 02/05/2001 JeffJon Created
|
|
|
|
#include "pch.h"
|
|
#include "resource.h"
|
|
|
|
#include "DHCPInstallationUnit.h"
|
|
#include "InstallationUnitProvider.h"
|
|
|
|
// Finish page help
|
|
extern PCWSTR CYS_DHCP_FINISH_PAGE_HELP = L"cys.chm::/dhcp_server_role.htm";
|
|
static PCWSTR CYS_DHCP_MILESTONE_HELP = L"cys.chm::/dhcp_server_role.htm#dhcpsrvsummary";
|
|
static PCWSTR CYS_DHCP_AFTER_FINISH_HELP = L"cys.chm::/dhcp_server_role.htm#dhcpsrvcompletion";
|
|
|
|
DHCPInstallationUnit::DHCPInstallationUnit() :
|
|
startIPAddress(0),
|
|
endIPAddress(0),
|
|
scopeCalculated(false),
|
|
dhcpRoleResult(DHCP_SUCCESS),
|
|
installedDescriptionID(IDS_DHCP_SERVER_DESCRIPTION_INSTALLED),
|
|
ExpressPathInstallationUnitBase(
|
|
IDS_DHCP_SERVER_TYPE,
|
|
IDS_DHCP_SERVER_DESCRIPTION,
|
|
IDS_DHCP_FINISH_TITLE,
|
|
IDS_DHCP_FINISH_UNINSTALL_TITLE,
|
|
IDS_DHCP_FINISH_MESSAGE,
|
|
IDS_DHCP_INSTALL_FAILED,
|
|
IDS_DHCP_UNINSTALL_MESSAGE,
|
|
IDS_DHCP_UNINSTALL_FAILED,
|
|
IDS_DHCP_UNINSTALL_WARNING,
|
|
IDS_DHCP_UNINSTALL_CHECKBOX,
|
|
CYS_DHCP_FINISH_PAGE_HELP,
|
|
CYS_DHCP_MILESTONE_HELP,
|
|
CYS_DHCP_AFTER_FINISH_HELP,
|
|
DHCP_SERVER)
|
|
{
|
|
LOG_CTOR(DHCPInstallationUnit);
|
|
}
|
|
|
|
|
|
DHCPInstallationUnit::~DHCPInstallationUnit()
|
|
{
|
|
LOG_DTOR(DHCPInstallationUnit);
|
|
}
|
|
|
|
|
|
InstallationReturnType
|
|
DHCPInstallationUnit::InstallService(HANDLE logfileHandle, HWND hwnd)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::InstallService);
|
|
|
|
InstallationReturnType result = INSTALL_SUCCESS;
|
|
|
|
if (IsExpressPathInstall())
|
|
{
|
|
// This is an express path install. It must be done special
|
|
|
|
result = ExpressPathInstall(logfileHandle, hwnd);
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
return result;
|
|
}
|
|
|
|
dhcpRoleResult = DHCP_SUCCESS;
|
|
|
|
// Log the DHCP header
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_HEADER));
|
|
|
|
UpdateInstallationProgressText(hwnd, IDS_DHCP_INSTALL_PROGRESS);
|
|
|
|
String infFileText;
|
|
String unattendFileText;
|
|
|
|
CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
|
|
CreateUnattendFileText(unattendFileText, CYS_DHCP_SERVICE_NAME);
|
|
|
|
// We are ignoring the ocmresult because it doesn't matter
|
|
// with respect to whether the role is installed or not
|
|
|
|
InstallServiceWithOcManager(infFileText, unattendFileText);
|
|
|
|
if (IsServiceInstalled())
|
|
{
|
|
// Log the successful installation
|
|
|
|
LOG(L"DHCP was installed successfully");
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_SERVER_START_DHCP));
|
|
|
|
// Wait for the service to enter the running state
|
|
|
|
NTService serviceObject(CYS_DHCP_SERVICE_NAME);
|
|
|
|
HRESULT hr = serviceObject.WaitForServiceState(SERVICE_RUNNING);
|
|
if (FAILED(hr))
|
|
{
|
|
// Remember where the failure happened
|
|
|
|
dhcpRoleResult = DHCP_INSTALL_FAILURE;
|
|
|
|
LOG(String::format(
|
|
L"The DHCP service failed to start in a timely fashion: %1!x!",
|
|
hr));
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
// Run the DHCP Wizard
|
|
|
|
String resultText;
|
|
HRESULT unused = S_OK;
|
|
|
|
UpdateInstallationProgressText(hwnd, IDS_DHCP_CONFIG_PROGRESS);
|
|
|
|
if (ExecuteWizard(hwnd, CYS_DHCP_SERVICE_NAME, resultText, unused))
|
|
{
|
|
// Check to be sure the wizard finished completely
|
|
|
|
String configWizardResults;
|
|
bool regkeyResult = GetRegKeyValue(
|
|
CYS_DHCP_DOMAIN_IP_REGKEY,
|
|
CYS_DHCP_WIZARD_RESULT,
|
|
configWizardResults,
|
|
HKEY_CURRENT_USER);
|
|
|
|
if (IsDhcpConfigured() &&
|
|
(!regkeyResult ||
|
|
configWizardResults.empty()))
|
|
{
|
|
// The New Scope Wizard completed successfully
|
|
|
|
LOG(L"DHCP installed and the New Scope Wizard completed successfully");
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_COMPLETED_SUCCESSFULLY));
|
|
}
|
|
else if(regkeyResult &&
|
|
!configWizardResults.empty())
|
|
{
|
|
// Remember where the failure happened
|
|
|
|
dhcpRoleResult = DHCP_CONFIG_FAILURE;
|
|
|
|
LOG(L"DHCP was installed but the New Scope Wizard failed or was cancelled");
|
|
|
|
// NTRAID#NTBUG9-704311-2002/09/16-artm
|
|
// Don't include failure string in free builds b/c it is not localized.
|
|
#if DBG == 1
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
IDS_LOG_DHCP_WIZARD_ERROR_FORMAT,
|
|
configWizardResults.c_str()));
|
|
#else
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
|
|
#endif
|
|
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
// The New Scope Wizard did not finish successfully
|
|
|
|
// Remember where the failure happened
|
|
|
|
dhcpRoleResult = DHCP_CONFIG_FAILURE;
|
|
|
|
LOG(L"DHCP installed successfully, but a problem occurred during the New Scope Wizard");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
|
|
// reset the regkey to make sure that if someone runs this path
|
|
// again we don't still think the wizard was cancelled.
|
|
|
|
SetRegKeyValue(
|
|
CYS_DHCP_DOMAIN_IP_REGKEY,
|
|
CYS_DHCP_WIZARD_RESULT,
|
|
L"",
|
|
HKEY_CURRENT_USER);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Remember where the failure happened
|
|
|
|
dhcpRoleResult = DHCP_CONFIG_FAILURE;
|
|
|
|
// Log an error
|
|
|
|
LOG(L"DHCP could not be installed.");
|
|
|
|
if (!resultText.empty())
|
|
{
|
|
CYS_APPEND_LOG(resultText);
|
|
}
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remember where the failure happened
|
|
|
|
dhcpRoleResult = DHCP_INSTALL_FAILURE;
|
|
|
|
// Log the failure
|
|
|
|
LOG(L"DHCP failed to install");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_SERVER_FAILED));
|
|
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
UnInstallReturnType
|
|
DHCPInstallationUnit::UnInstallService(HANDLE logfileHandle, HWND hwnd)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::UnInstallService);
|
|
|
|
UnInstallReturnType result = UNINSTALL_SUCCESS;
|
|
|
|
// Log the DHCP header
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_HEADER));
|
|
|
|
UpdateInstallationProgressText(hwnd, IDS_UNINSTALL_DHCP_PROGRESS);
|
|
|
|
String infFileText;
|
|
String unattendFileText;
|
|
|
|
CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
|
|
CreateUnattendFileText(unattendFileText, CYS_DHCP_SERVICE_NAME, false);
|
|
|
|
// NTRAID#NTBUG9-736557-2002/11/13-JeffJon
|
|
// Pass the /w switch to sysocmgr when uninstalling
|
|
// so that if a situation occurs in which a reboot
|
|
// is required, the user will be prompted.
|
|
|
|
String additionalArgs = L"/w";
|
|
|
|
// We are ignoring the ocmresult because it doesn't matter
|
|
// with respect to whether the role is installed or not
|
|
|
|
InstallServiceWithOcManager(
|
|
infFileText,
|
|
unattendFileText,
|
|
additionalArgs);
|
|
|
|
// Wait for the service to enter the stopped state
|
|
|
|
NTService serviceObject(CYS_DHCP_SERVICE_NAME);
|
|
|
|
// ignore the returned value. This is just to wait on the
|
|
// service. Use the normal mechanism for determining success
|
|
// or failure of the uninstall
|
|
|
|
serviceObject.WaitForServiceState(SERVICE_STOPPED);
|
|
|
|
if (IsServiceInstalled())
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_FAILED));
|
|
|
|
result = UNINSTALL_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_SUCCESS));
|
|
}
|
|
LOG_UNINSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
InstallationReturnType
|
|
DHCPInstallationUnit::ExpressPathInstall(HANDLE logfileHandle, HWND hwnd)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::ExpressPathInstall);
|
|
|
|
InstallationReturnType result = INSTALL_SUCCESS;
|
|
|
|
String infFileText;
|
|
String unattendFileText;
|
|
String commandline;
|
|
|
|
String netshPath = GetNetshPath();
|
|
|
|
do
|
|
{
|
|
// We ignore if the NIC is found or not because the function will return
|
|
// the first NIC if the correct NIC is not found. We can then use this
|
|
// to setup the network
|
|
|
|
NetworkInterface* localNIC =
|
|
State::GetInstance().GetLocalNIC();
|
|
|
|
if (!localNIC)
|
|
{
|
|
result = INSTALL_FAILURE;
|
|
|
|
LOG(L"Failed to get local NIC");
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetExpressInstallationUnit().SetExpressRoleResult(
|
|
ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
|
|
|
|
break;
|
|
}
|
|
|
|
// In the case where the public interface has a static IP address
|
|
// and the private interface has a DHCP server (whether the NIC
|
|
// has a static or dynamic address doesn't matter), we don't want
|
|
// to install another DHCP server. So we will just skip it.
|
|
|
|
if (localNIC->IsDHCPAvailable())
|
|
{
|
|
LOG(L"DHCP is already on this NIC so don't install");
|
|
|
|
if (!SetRegKeyValue(
|
|
CYS_FIRST_DC_REGKEY,
|
|
CYS_FIRST_DC_DHCP_SERVERED,
|
|
CYS_DHCP_NOT_SERVERED_VALUE,
|
|
HKEY_LOCAL_MACHINE,
|
|
true))
|
|
{
|
|
LOG(L"Failed to set the DHCP installed regkey");
|
|
}
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_NOT_REQUIRED));
|
|
break;
|
|
}
|
|
|
|
UpdateInstallationProgressText(hwnd, IDS_DHCP_INSTALL_PROGRESS);
|
|
|
|
CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
|
|
CreateUnattendFileTextForExpressPath(*localNIC, unattendFileText);
|
|
|
|
bool ocmResult = InstallServiceWithOcManager(infFileText, unattendFileText);
|
|
if (ocmResult &&
|
|
!IsServiceInstalled())
|
|
{
|
|
result = INSTALL_FAILURE;
|
|
|
|
LOG(L"DHCP installation failed");
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetExpressInstallationUnit().SetExpressRoleResult(
|
|
ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (!SetRegKeyValue(
|
|
CYS_FIRST_DC_REGKEY,
|
|
CYS_FIRST_DC_DHCP_SERVERED,
|
|
CYS_DHCP_SERVERED_VALUE,
|
|
HKEY_LOCAL_MACHINE,
|
|
true))
|
|
{
|
|
LOG(L"Failed to set the DHCP installed regkey");
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Wait for the service to enter the running state
|
|
|
|
NTService serviceObject(CYS_DHCP_SERVICE_NAME);
|
|
|
|
hr = serviceObject.WaitForServiceState(SERVICE_RUNNING);
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"The DHCP service failed to start in a timely fashion: %1!x!",
|
|
hr));
|
|
|
|
result = INSTALL_FAILURE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetExpressInstallationUnit().SetExpressRoleResult(
|
|
ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
|
|
|
|
break;
|
|
}
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_SUCCESS));
|
|
|
|
UpdateInstallationProgressText(hwnd, IDS_DHCP_CONFIG_PROGRESS);
|
|
|
|
DWORD exitCode = 0;
|
|
|
|
String ipaddressString =
|
|
localNIC->GetStringIPAddress(0);
|
|
|
|
String subnetMaskString =
|
|
localNIC->GetStringSubnetMask(0);
|
|
|
|
do
|
|
{
|
|
commandline = L"dhcp server add optiondef 6 \"DNS Servers\" IPADDRESS 1";
|
|
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to run DHCP options: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to run DHCP options: exitCode = %1!x!",
|
|
exitCode));
|
|
|
|
// Don't break here. The most likely error is that the option already
|
|
// exists. In which case continue to set the value
|
|
}
|
|
|
|
commandline = String::format(
|
|
L"dhcp server set optionvalue 6 IPADDRESS %1",
|
|
ipaddressString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to run DHCP server IP address: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to run DHCP server IP address: exitCode = %1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
|
|
// Set the subnet mask
|
|
|
|
DWORD staticipaddress =
|
|
localNIC->GetIPAddress(0);
|
|
|
|
DWORD subnetMask =
|
|
localNIC->GetSubnetMask(0);
|
|
|
|
DWORD subnet = staticipaddress & subnetMask;
|
|
|
|
String subnetString = IPAddressToString(subnet);
|
|
|
|
commandline = String::format(
|
|
L"dhcp server 127.0.0.1 add scope %1 %2 Scope1",
|
|
subnetString.c_str(),
|
|
subnetMaskString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP address and subnet: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to create DHCP scope: exitCode = %1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
|
|
// Set the DHCP scopes
|
|
|
|
String start = GetStartIPAddressString(*localNIC);
|
|
String end = GetEndIPAddressString(*localNIC);
|
|
|
|
commandline = String::format(
|
|
L"dhcp server 127.0.0.1 scope %1 add iprange %2 %3 both",
|
|
subnetString.c_str(),
|
|
start.c_str(),
|
|
end.c_str());
|
|
|
|
// Set the start and end of the scope in regkeys so that they can
|
|
// be read after reboot
|
|
|
|
if (!SetRegKeyValue(
|
|
CYS_FIRST_DC_REGKEY,
|
|
CYS_FIRST_DC_SCOPE_START,
|
|
start.c_str(),
|
|
HKEY_LOCAL_MACHINE,
|
|
true))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope start regkey: hr = %1!x!",
|
|
hr));
|
|
}
|
|
|
|
if (!SetRegKeyValue(
|
|
CYS_FIRST_DC_REGKEY,
|
|
CYS_FIRST_DC_SCOPE_END,
|
|
end.c_str(),
|
|
HKEY_LOCAL_MACHINE,
|
|
true))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope end regkey: hr = %1!x!",
|
|
hr));
|
|
}
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope iprange: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope iprange: exitCode = %1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
|
|
// Set an exception for the servers IP address if it falls within
|
|
// the scope
|
|
|
|
if (staticipaddress >= GetStartIPAddress(*localNIC) &&
|
|
staticipaddress <= GetEndIPAddress(*localNIC))
|
|
{
|
|
commandline = String::format(
|
|
L"dhcp server 127.0.0.1 scope %1 add excluderange %2 %2",
|
|
subnetString.c_str(),
|
|
ipaddressString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set server exclusion for DHCP scopes: hr = 0x%1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set server exclusion for DHCP scopes: exitCode = 0x%1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
}
|
|
|
|
// Activate the scope
|
|
|
|
commandline = String::format(
|
|
L"dhcp server 127.0.0.1 scope %1 set state 1",
|
|
subnetString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to activate scope: hr = 0x%1!x!",
|
|
hr));
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to activate scope: exitCode = 0x%1!x!",
|
|
exitCode));
|
|
}
|
|
|
|
// Set the DHCP scope lease time
|
|
|
|
commandline = L"dhcp server 127.0.0.1 add optiondef 51 \"Lease\" DWORD 0 comment=\"Client IP address lease time in seconds\" 0";
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope lease time: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope lease time: exitCode = %1!x!",
|
|
exitCode));
|
|
}
|
|
|
|
// Set the DHCP scope lease time value
|
|
|
|
commandline = String::format(
|
|
L"dhcp server 127.0.0.1 scope %1 set optionvalue 51 dword 874800",
|
|
subnetString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope lease time value: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP scope lease time value: exitCode = %1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
|
|
// Set the default gateway to be handed out to clients. This will allow
|
|
// for proper routing
|
|
|
|
if (InstallationUnitProvider::GetInstance().GetRRASInstallationUnit().IsRoutingOn())
|
|
{
|
|
commandline =
|
|
L"dhcp server 127.0.0.1 add optiondef 3 \"Router\" IPADDRESS "
|
|
L"1 comment=\"Array of router addresses ordered by preference\" 0.0.0.0";
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
// From CEdson - Ignore any failures because it probably just means that
|
|
// the option already exists in which case we can continue on
|
|
|
|
commandline =
|
|
String::format(
|
|
L"dhcp server 127.0.0.1 set optionvalue 3 IPADDRESS \"%1\"",
|
|
ipaddressString.c_str());
|
|
|
|
exitCode = 0;
|
|
hr = CreateAndWaitForProcess(
|
|
netshPath,
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP default gateway: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
if (exitCode != 1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set DHCP default gateway: exitCode = %1!x!",
|
|
exitCode));
|
|
//break;
|
|
}
|
|
}
|
|
}
|
|
} while (false);
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void
|
|
DHCPInstallationUnit::CreateUnattendFileTextForExpressPath(
|
|
const NetworkInterface& nic,
|
|
String& unattendFileText)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::CreateUnattendFileTextForExpressPath);
|
|
|
|
// The DNS server IP
|
|
|
|
DWORD staticipaddress = nic.GetIPAddress(0);
|
|
|
|
DWORD subnetMask = nic.GetSubnetMask(0);
|
|
|
|
DWORD subnet = staticipaddress & subnetMask;
|
|
|
|
String subnetString = IPAddressToString(subnet);
|
|
|
|
unattendFileText = L"[NetOptionalComponents]\r\n";
|
|
unattendFileText += L"DHCPServer=1\r\n";
|
|
unattendFileText += L"[dhcpserver]\r\n";
|
|
unattendFileText += L"Subnets=";
|
|
unattendFileText += subnetString;
|
|
unattendFileText += L"\r\n";
|
|
|
|
// Add the DHCP scope
|
|
|
|
unattendFileText += L"StartIP=";
|
|
unattendFileText += GetStartIPAddressString(nic);
|
|
unattendFileText += L"\r\n";
|
|
unattendFileText += L"EndIp=";
|
|
unattendFileText += GetEndIPAddressString(nic);
|
|
unattendFileText += L"\r\n";
|
|
|
|
// Add subnet mask
|
|
|
|
String subnetMaskString = nic.GetStringSubnetMask(0);
|
|
|
|
unattendFileText += L"SubnetMask=";
|
|
unattendFileText += subnetMaskString;
|
|
unattendFileText += L"\r\n";
|
|
unattendFileText += L"LeaseDuration=874800\r\n";
|
|
|
|
unattendFileText += String::format(
|
|
L"DnsServer=%1\r\n",
|
|
IPAddressToString(staticipaddress).c_str());
|
|
|
|
// The domain name
|
|
|
|
unattendFileText += String::format(
|
|
L"DomainName=%1\r\n",
|
|
InstallationUnitProvider::GetInstance().GetADInstallationUnit().GetNewDomainDNSName().c_str());
|
|
|
|
}
|
|
|
|
bool
|
|
DHCPInstallationUnit::GetMilestoneText(String& message)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetMilestoneText);
|
|
|
|
if (IsExpressPathInstall())
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
message = String::load(IDS_DHCP_FINISH_TEXT);
|
|
}
|
|
|
|
LOG_BOOL(true);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
DHCPInstallationUnit::GetUninstallMilestoneText(String& message)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetUninstallMilestoneText);
|
|
|
|
message = String::load(IDS_DHCP_UNINSTALL_TEXT);
|
|
|
|
LOG_BOOL(true);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
DHCPInstallationUnit::AuthorizeDHCPServer(const String& dnsName) const
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::AuthorizeDHCPServer);
|
|
|
|
bool result = true;
|
|
|
|
do
|
|
{
|
|
// Read the local NIC GUID from the registry
|
|
|
|
NetworkInterface* localNIC =
|
|
State::GetInstance().GetLocalNICFromRegistry();
|
|
|
|
if (!localNIC)
|
|
{
|
|
LOG(L"Failed to get the local NIC from registry");
|
|
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
// Authorize the DHCP scope
|
|
|
|
String commandline;
|
|
commandline = L"dhcp add server ";
|
|
commandline += dnsName;
|
|
commandline += L" ";
|
|
commandline += localNIC->GetStringIPAddress(0);
|
|
|
|
DWORD exitCode = 0;
|
|
HRESULT hr =
|
|
CreateAndWaitForProcess(
|
|
GetNetshPath(),
|
|
commandline,
|
|
exitCode,
|
|
true);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to run DHCP authorization: hr = %1!x!",
|
|
hr));
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
// Success code appears to be 0 for this one
|
|
|
|
if (exitCode != 0)
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
} while (false);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
DHCPInstallationUnit::SetStartIPAddress(DWORD ipaddress)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DHCPInstallationUnit::SetStartIPAddress,
|
|
String::format(L"0x%1!x!", ipaddress));
|
|
|
|
startIPAddress = ipaddress;
|
|
|
|
// Scope is being set manually so lets not try to calculate it
|
|
|
|
scopeCalculated = true;
|
|
}
|
|
|
|
void
|
|
DHCPInstallationUnit::SetEndIPAddress(DWORD ipaddress)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DHCPInstallationUnit::SetEndIPAddress,
|
|
String::format(L"0x%1!x!", ipaddress));
|
|
|
|
endIPAddress = ipaddress;
|
|
|
|
// Scope is being set manually so lets not try to calculate it
|
|
|
|
scopeCalculated = true;
|
|
}
|
|
|
|
String
|
|
DHCPInstallationUnit::GetStartIPAddressString(const NetworkInterface& nic)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetStartIPAddressString);
|
|
|
|
CalculateScope(nic);
|
|
|
|
String result = IPAddressToString(startIPAddress);
|
|
|
|
LOG(result);
|
|
return result;
|
|
}
|
|
|
|
String
|
|
DHCPInstallationUnit::GetEndIPAddressString(const NetworkInterface& nic)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetEndIPAddressString);
|
|
|
|
CalculateScope(nic);
|
|
|
|
String result = IPAddressToString(endIPAddress);
|
|
|
|
LOG(result);
|
|
return result;
|
|
}
|
|
|
|
DWORD
|
|
DHCPInstallationUnit::GetStartIPAddress(const NetworkInterface& nic)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetStartIPAddress);
|
|
|
|
CalculateScope(nic);
|
|
|
|
return startIPAddress;
|
|
}
|
|
|
|
DWORD
|
|
DHCPInstallationUnit::GetEndIPAddress(const NetworkInterface& nic)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetEndIPAddress);
|
|
|
|
CalculateScope(nic);
|
|
|
|
return endIPAddress;
|
|
}
|
|
|
|
void
|
|
DHCPInstallationUnit::CalculateScope(const NetworkInterface& nic)
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::CalculateScope);
|
|
|
|
if (!scopeCalculated)
|
|
{
|
|
DWORD staticIPAddress = nic.GetIPAddress(0);
|
|
|
|
DWORD subnetMask = nic.GetSubnetMask(0);
|
|
|
|
// We are allowing a buffer of 10 addresses that are not part of the scope
|
|
// in case the user wants to add other machines (computers, routers, etc)
|
|
// with static IP addresses
|
|
|
|
startIPAddress = (subnetMask & staticIPAddress);
|
|
endIPAddress = (subnetMask & staticIPAddress) | (~(subnetMask) - 1);
|
|
|
|
if (startIPAddress + 10 < endIPAddress)
|
|
{
|
|
startIPAddress = startIPAddress + 10;
|
|
}
|
|
scopeCalculated = true;
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"Start: %1",
|
|
IPAddressToString(startIPAddress).c_str()));
|
|
|
|
LOG(String::format(
|
|
L"End: %1",
|
|
IPAddressToString(endIPAddress).c_str()));
|
|
}
|
|
|
|
String
|
|
DHCPInstallationUnit::GetServiceDescription()
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetServiceDescription);
|
|
|
|
String result;
|
|
|
|
unsigned int resultID = descriptionID;
|
|
|
|
if (GetStatus() == STATUS_COMPLETED)
|
|
{
|
|
resultID = installedDescriptionID;
|
|
}
|
|
|
|
result = String::load(resultID);
|
|
|
|
ASSERT(!result.empty());
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
DHCPInstallationUnit::ServerRoleLinkSelected(int linkIndex, HWND /*hwnd*/)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DHCPInstallationUnit::ServerRoleLinkSelected,
|
|
String::format(
|
|
L"linkIndex = %1!d!",
|
|
linkIndex));
|
|
|
|
if (IsServiceInstalled())
|
|
{
|
|
ASSERT(linkIndex == 0);
|
|
|
|
LaunchMYS();
|
|
}
|
|
else
|
|
{
|
|
ASSERT(linkIndex == 0);
|
|
|
|
LOG(L"Showing configuration help");
|
|
|
|
ShowHelp(CYS_DHCP_FINISH_PAGE_HELP);
|
|
}
|
|
}
|
|
|
|
void
|
|
DHCPInstallationUnit::FinishLinkSelected(int linkIndex, HWND /*hwnd*/)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DHCPInstallationUnit::FinishLinkSelected,
|
|
String::format(
|
|
L"linkIndex = %1!d!",
|
|
linkIndex));
|
|
|
|
if (installing)
|
|
{
|
|
if (linkIndex == 0 &&
|
|
IsServiceInstalled())
|
|
{
|
|
// Installation was successful. Check to see
|
|
// if there was a failure in configuration
|
|
|
|
if (dhcpRoleResult == DHCP_CONFIG_FAILURE)
|
|
{
|
|
// Since there was a config failure just
|
|
// point them to the snapin
|
|
|
|
LOG(L"Launching DHCP snapin");
|
|
|
|
LaunchMMCConsole(L"dhcpmgmt.msc");
|
|
}
|
|
else
|
|
{
|
|
// Offer the next steps document
|
|
|
|
LOG("Showing after checklist");
|
|
|
|
ShowHelp(CYS_DHCP_AFTER_FINISH_HELP);
|
|
}
|
|
}
|
|
else if (linkIndex == 0)
|
|
{
|
|
// There was a failure
|
|
|
|
LOG(L"Showing configuration help");
|
|
|
|
ShowHelp(CYS_DHCP_FINISH_PAGE_HELP);
|
|
}
|
|
}
|
|
}
|
|
|
|
String
|
|
DHCPInstallationUnit::GetFinishText()
|
|
{
|
|
LOG_FUNCTION(DHCPInstallationUnit::GetFinishText);
|
|
|
|
unsigned int messageID = finishMessageID;
|
|
|
|
if (installing)
|
|
{
|
|
InstallationReturnType result = GetInstallResult();
|
|
if (result != INSTALL_SUCCESS &&
|
|
result != INSTALL_SUCCESS_REBOOT &&
|
|
result != INSTALL_SUCCESS_PROMPT_REBOOT)
|
|
{
|
|
if (dhcpRoleResult == DHCP_INSTALL_FAILURE)
|
|
{
|
|
messageID = finishInstallFailedMessageID;
|
|
}
|
|
else
|
|
{
|
|
messageID = IDS_DHCP_CONFIG_FAILED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
messageID = finishUninstallMessageID;
|
|
|
|
UnInstallReturnType result = GetUnInstallResult();
|
|
if (result != UNINSTALL_SUCCESS &&
|
|
result != UNINSTALL_SUCCESS_REBOOT &&
|
|
result != UNINSTALL_SUCCESS_PROMPT_REBOOT)
|
|
{
|
|
messageID = finishUninstallFailedMessageID;
|
|
}
|
|
}
|
|
|
|
return String::load(messageID);
|
|
}
|