498 lines
12 KiB
C++
498 lines
12 KiB
C++
// Copyright (c) 1997-2001 Microsoft Corporation
|
|
//
|
|
// File: DNSInstallationUnit.cpp
|
|
//
|
|
// Synopsis: Defines a DNSInstallationUnit
|
|
// This object has the knowledge for installing the
|
|
// DNS service
|
|
//
|
|
// History: 02/05/2001 JeffJon Created
|
|
|
|
#include "pch.h"
|
|
#include "resource.h"
|
|
|
|
#include "DNSInstallationUnit.h"
|
|
|
|
|
|
|
|
|
|
DNSInstallationUnit::DNSInstallationUnit() :
|
|
isExpressPathInstall(false),
|
|
staticIPAddress(0),
|
|
subnetMask(0),
|
|
NetworkServiceInstallationBase(
|
|
IDS_DNS_SERVER_TYPE,
|
|
IDS_DNS_SERVER_DESCRIPTION,
|
|
IDS_DNS_SERVER_DESCRIPTION_INSTALLED,
|
|
DNS_INSTALL)
|
|
{
|
|
LOG_CTOR(DNSInstallationUnit);
|
|
}
|
|
|
|
|
|
DNSInstallationUnit::~DNSInstallationUnit()
|
|
{
|
|
LOG_DTOR(DNSInstallationUnit);
|
|
}
|
|
|
|
|
|
InstallationReturnType
|
|
DNSInstallationUnit::InstallService(HANDLE logfileHandle, HWND hwnd)
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::InstallService);
|
|
|
|
InstallationReturnType result = INSTALL_SUCCESS;
|
|
|
|
if (IsExpressPathInstall())
|
|
{
|
|
result = ExpressPathInstall(logfileHandle, hwnd);
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
return result;
|
|
}
|
|
|
|
|
|
// Create the inf and unattend files that are used by the
|
|
// Optional Component Manager
|
|
|
|
String infFileText;
|
|
String unattendFileText;
|
|
|
|
CreateInfFileText(infFileText, IDS_DNS_INF_WINDOW_TITLE);
|
|
CreateUnattendFileText(unattendFileText, CYS_DNS_SERVICE_NAME);
|
|
|
|
// Install the service through the Optional Component Manager
|
|
|
|
bool ocmResult = InstallServiceWithOcManager(infFileText, unattendFileText);
|
|
if (ocmResult &&
|
|
IsServiceInstalled())
|
|
{
|
|
// Log the successful installation
|
|
|
|
LOG(L"DNS was installed successfully");
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_INSTALL_START_DNS));
|
|
|
|
|
|
// Run the DNS Wizard
|
|
|
|
String resultText;
|
|
|
|
if (ExecuteWizard(CYS_DNS_SERVICE_NAME, resultText))
|
|
{
|
|
// Check to be sure the wizard finished completely
|
|
|
|
String configWizardResults;
|
|
|
|
if (ReadConfigWizardRegkeys(configWizardResults))
|
|
{
|
|
// The Configure DNS Server Wizard completed successfully
|
|
|
|
LOG(L"The Configure DNS Server Wizard completed successfully");
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DNS_COMPLETED_SUCCESSFULLY));
|
|
}
|
|
else
|
|
{
|
|
// The Configure DNS Server Wizard did not finish successfully
|
|
|
|
if (!configWizardResults.empty())
|
|
{
|
|
// An error was returned via the regkey
|
|
|
|
LOG(String::format(
|
|
L"The Configure DNS Server Wizard returned the error: %1",
|
|
configWizardResults.c_str()));
|
|
|
|
String formatString = String::load(IDS_LOG_DNS_WIZARD_ERROR);
|
|
CYS_APPEND_LOG(String::format(formatString, configWizardResults.c_str()));
|
|
|
|
}
|
|
else
|
|
{
|
|
// The Configure DNS Server Wizard was cancelled by the user
|
|
|
|
LOG(L"The Configure DNS Server Wizard was cancelled by the user");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DNS_WIZARD_CANCELLED));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Show an error
|
|
|
|
LOG(L"DNS could not be installed.");
|
|
|
|
if (!resultText.empty())
|
|
{
|
|
CYS_APPEND_LOG(resultText);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Log the failure
|
|
|
|
LOG(L"DNS failed to install");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DNS_INSTALL_FAILED));
|
|
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
InstallationReturnType
|
|
DNSInstallationUnit::ExpressPathInstall(HANDLE /*logfileHandle*/, HWND /*hwnd*/)
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::ExpressPathInstall);
|
|
|
|
InstallationReturnType result = INSTALL_SUCCESS;
|
|
|
|
// Set the static IP address and the subnet mask
|
|
|
|
// invoke netsh and wait for it to terminate
|
|
|
|
String friendlyName = GetTcpIpInterfaceFriendlyName();
|
|
|
|
do
|
|
{
|
|
// set static IP address and subnet mask
|
|
|
|
String commandLine =
|
|
String::format(
|
|
L"netsh interface ip set address "
|
|
L"name=\"%1\" source=static addr=%2 mask=%3 gateway=none",
|
|
friendlyName.c_str(),
|
|
GetStaticIPAddressString().c_str(),
|
|
GetSubnetMaskString().c_str());
|
|
|
|
DWORD exitCode1 = 0;
|
|
HRESULT hr = ::CreateAndWaitForProcess(commandLine, exitCode1);
|
|
if (FAILED(hr) || exitCode1)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set the static IP address and subnet mask: exitCode = %1!x!",
|
|
exitCode1));
|
|
result = INSTALL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// set DNS server address to same address as local machine. netsh
|
|
// does not allow the dns server address to be the loopback address.
|
|
|
|
commandLine =
|
|
String::format(
|
|
L"netsh interface ip set dns name=\"%1\" source=static addr=%2",
|
|
friendlyName.c_str(),
|
|
GetStaticIPAddressString().c_str());
|
|
|
|
DWORD exitCode2 = 0;
|
|
hr = ::CreateAndWaitForProcess(commandLine, exitCode2);
|
|
if (FAILED(hr) || exitCode2)
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to set the preferred DNS server IP address: exitCode = %1!x!",
|
|
exitCode2));
|
|
result = INSTALL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// get guid name of the first tcp/ip interface we enum
|
|
|
|
HRESULT
|
|
DNSInstallationUnit::GetTcpIpInterfaceGuidName(String& result)
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::GetTcpIpInterfaceGuidName);
|
|
|
|
result.erase();
|
|
|
|
DWORD dwError = 0;
|
|
ULONG ulSize = 0;
|
|
PIP_INTERFACE_INFO pInfo = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
while ( 1 )
|
|
{
|
|
dwError = ::GetInterfaceInfo( pInfo, &ulSize );
|
|
if ( ERROR_INSUFFICIENT_BUFFER != dwError )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( NULL != pInfo )
|
|
{
|
|
Win::LocalFree(pInfo);
|
|
}
|
|
if ( 0 == ulSize )
|
|
{
|
|
hr = E_FAIL;
|
|
LOG_HRESULT(hr);
|
|
return hr;
|
|
}
|
|
|
|
pInfo = (PIP_INTERFACE_INFO) ::LocalAlloc(LPTR, ulSize);
|
|
if ( NULL == pInfo )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
LOG_HRESULT(hr);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS != dwError || 0 == pInfo->NumAdapters )
|
|
{
|
|
if ( NULL != pInfo )
|
|
{
|
|
Win::LocalFree(pInfo);
|
|
}
|
|
hr = E_FAIL;
|
|
LOG_HRESULT(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Skip the adapter prefix
|
|
|
|
result = pInfo->Adapter[0].Name + strlen("\\Device\\Tcpip_"),
|
|
|
|
// CODEWORK could do this with IIDFromString
|
|
// // // // check whether this is a valid GUID
|
|
// // //
|
|
// // // SHUnicodeToTChar(wszGuidName, szGuid, ARRAYSIZE(szGuid));
|
|
// // // if (!GUIDFromString(szGuid, &guid))
|
|
// // // {
|
|
// // // // we failed to get a valid tcp/ip interface
|
|
// // // *wszGuidName = 0;
|
|
// // // Win::LocalFree(pInfo);
|
|
// // // return E_FAIL;
|
|
// // // }
|
|
|
|
LocalFree(pInfo);
|
|
|
|
LOG(result);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// get friendly name of the first tcp/ip interface we enum
|
|
|
|
String
|
|
DNSInstallationUnit::GetTcpIpInterfaceFriendlyName()
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::GetTcpIpInterfaceFriendlyName);
|
|
|
|
DWORD dwRet = 0;
|
|
HANDLE hMprConfig = 0;
|
|
|
|
static const unsigned friendlyNameLength = 128;
|
|
wchar_t wszFriendlyName[friendlyNameLength];
|
|
ZeroMemory(wszFriendlyName, sizeof(wchar_t) * friendlyNameLength);
|
|
|
|
String result;
|
|
|
|
String guidName;
|
|
HRESULT hr = GetTcpIpInterfaceGuidName(guidName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dwRet = MprConfigServerConnect(0, &hMprConfig);
|
|
if (NO_ERROR == dwRet)
|
|
{
|
|
dwRet =
|
|
MprConfigGetFriendlyName(
|
|
hMprConfig,
|
|
const_cast<wchar_t*>(guidName.c_str()),
|
|
wszFriendlyName,
|
|
sizeof(wchar_t) * friendlyNameLength);
|
|
if (NO_ERROR != dwRet)
|
|
{
|
|
LOG(String::format(
|
|
L"MprConfigGetFriendlyName() failed: error = %1!x!",
|
|
dwRet));
|
|
*wszFriendlyName = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG(String::format(
|
|
L"MprConfigServerConnect() failed: error = %1!x!",
|
|
dwRet));
|
|
}
|
|
|
|
MprConfigServerDisconnect(hMprConfig);
|
|
}
|
|
|
|
if (!*wszFriendlyName)
|
|
{
|
|
// we failed to get a friendly name, so use the default one
|
|
// BUGBUG does this need to be localized?
|
|
|
|
result = L"Local Area Connection";
|
|
}
|
|
else
|
|
{
|
|
result = wszFriendlyName;
|
|
}
|
|
|
|
LOG(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
DNSInstallationUnit::ReadConfigWizardRegkeys(String& configWizardResults) const
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::ReadConfigWizardRegkeys);
|
|
|
|
bool result = true;
|
|
|
|
do
|
|
{
|
|
DWORD value = 0;
|
|
result = GetRegKeyValue(
|
|
DNS_WIZARD_CONFIG_REGKEY,
|
|
DNS_WIZARD_CONFIG_VALUE,
|
|
value);
|
|
|
|
if (result &&
|
|
value != 0)
|
|
{
|
|
// The Configure DNS Server Wizard succeeded
|
|
|
|
result = true;
|
|
break;
|
|
}
|
|
|
|
// Since there was a failure (or the wizard was cancelled)
|
|
// get the display string to log
|
|
|
|
result = GetRegKeyValue(
|
|
DNS_WIZARD_RESULT_REGKEY,
|
|
DNS_WIZARD_RESULT_VALUE,
|
|
configWizardResults);
|
|
|
|
} while (false);
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool
|
|
DNSInstallationUnit::IsServiceInstalled()
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::IsServiceInstalled);
|
|
|
|
bool result = IsServiceInstalledHelper(CYS_DNS_SERVICE_NAME);
|
|
|
|
LOG_BOOL(result);
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
DNSInstallationUnit::GetFinishText(String& message)
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::GetFinishText);
|
|
|
|
message = String::load(IDS_DNS_FINISH_TEXT);
|
|
|
|
LOG_BOOL(true);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
DNSInstallationUnit::SetExpressPathInstall(bool isExpressPath)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DNSInstallationUnit::SetExpressPathInstall,
|
|
(isExpressPath) ? L"true" : L"false");
|
|
|
|
isExpressPathInstall = isExpressPath;
|
|
}
|
|
|
|
|
|
bool
|
|
DNSInstallationUnit::IsExpressPathInstall() const
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::IsExpressPathInstall);
|
|
|
|
return isExpressPathInstall;
|
|
}
|
|
|
|
|
|
void
|
|
DNSInstallationUnit::SetStaticIPAddress(DWORD ipaddress)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DNSInstallationUnit::SetStaticIPAddress,
|
|
String::format(
|
|
L"%1!d!.%2!d!.%3!d!.%4!d!",
|
|
FIRST_IPADDRESS(ipaddress),
|
|
SECOND_IPADDRESS(ipaddress),
|
|
THIRD_IPADDRESS(ipaddress),
|
|
FOURTH_IPADDRESS(ipaddress)));
|
|
|
|
staticIPAddress = ipaddress;
|
|
}
|
|
|
|
void
|
|
DNSInstallationUnit::SetSubnetMask(DWORD mask)
|
|
{
|
|
LOG_FUNCTION2(
|
|
DNSInstallationUnit::SetSubnetMask,
|
|
String::format(
|
|
L"%1!d!.%2!d!.%3!d!.%4!d!",
|
|
FIRST_IPADDRESS(mask),
|
|
SECOND_IPADDRESS(mask),
|
|
THIRD_IPADDRESS(mask),
|
|
FOURTH_IPADDRESS(mask)));
|
|
|
|
subnetMask = mask;
|
|
}
|
|
|
|
String
|
|
DNSInstallationUnit::GetStaticIPAddressString() const
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::GetStaticIPAddressString);
|
|
|
|
String result = String::format(
|
|
L"%1!d!.%2!d!.%3!d!.%4!d!",
|
|
FIRST_IPADDRESS(staticIPAddress),
|
|
SECOND_IPADDRESS(staticIPAddress),
|
|
THIRD_IPADDRESS(staticIPAddress),
|
|
FOURTH_IPADDRESS(staticIPAddress));
|
|
|
|
LOG(result);
|
|
return result;
|
|
}
|
|
|
|
|
|
String
|
|
DNSInstallationUnit::GetSubnetMaskString() const
|
|
{
|
|
LOG_FUNCTION(DNSInstallationUnit::GetSubnetMaskString);
|
|
|
|
String result = String::format(
|
|
L"%1!d!.%2!d!.%3!d!.%4!d!",
|
|
FIRST_IPADDRESS(subnetMask),
|
|
SECOND_IPADDRESS(subnetMask),
|
|
THIRD_IPADDRESS(subnetMask),
|
|
FOURTH_IPADDRESS(subnetMask));
|
|
|
|
LOG(result);
|
|
return result;
|
|
}
|