windows-nt/Source/XPSP1/NT/admin/dcpromo/exe/dnssetup.cpp

356 lines
7.7 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (C) 1998 Microsoft Corporation
//
// DNS installation and configuration code
//
// 6-16-98 sburns
#include "headers.hxx"
#include "resource.h"
#include "ProgressDialog.hpp"
static const DWORD HELP_MAP[] =
{
0, 0
};
static const int NAP_TIME = 3000; // in ms
int
millisecondsToSeconds(int millis)
{
static const int MILLIS_PER_SECOND = 1000;
return millis / MILLIS_PER_SECOND;
}
bool
pollForDNSServiceStart(ProgressDialog& progressDialog)
{
LOG_FUNCTION(PollForDNSServiceStart);
for (int waitCount = 0; /* empty */ ; waitCount++)
{
progressDialog.UpdateText(
String::format(
IDS_WAITING_FOR_SERVICE_START,
millisecondsToSeconds(NAP_TIME * waitCount)));
if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
{
progressDialog.UpdateButton(String());
popup.Info(
progressDialog.GetHWND(),
String::load(IDS_SKIP_DNS_MESSAGE));
break;
}
if (Dns::IsServiceRunning())
{
// success!
return true;
}
}
return false;
}
bool
pollForDNSServiceInstallAndStart(ProgressDialog& progressDialog)
{
LOG_FUNCTION(pollForDNSServiceInstallAndStart);
for (int waitCount = 0; /* empty */ ; waitCount++)
{
progressDialog.UpdateText(
String::format(
IDS_WAITING_FOR_SERVICE_INSTALL,
millisecondsToSeconds(NAP_TIME * waitCount)));
if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
{
progressDialog.UpdateButton(String());
popup.Info(
progressDialog.GetHWND(),
String::load(IDS_SKIP_DNS_MESSAGE));
break;
}
if (Dns::IsServiceInstalled())
{
// Service is installed. Now check to see if it is running.
return pollForDNSServiceStart(progressDialog);
}
}
return false;
}
HRESULT
createTempFile(const String& name, int textResID)
{
LOG_FUNCTION2(createTempFile, name);
ASSERT(!name.empty());
ASSERT(textResID);
HRESULT hr = S_OK;
HANDLE h = INVALID_HANDLE_VALUE;
do
{
hr =
FS::CreateFile(
name,
h,
GENERIC_WRITE,
0,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL);
BREAK_ON_FAILED_HRESULT(hr);
AnsiString ansi;
String::load(textResID).convert(ansi);
ASSERT(!ansi.empty());
// write to file with end of file character.
hr = FS::Write(h, ansi + "\032");
BREAK_ON_FAILED_HRESULT(hr);
}
while (0);
Win::CloseHandle(h);
return hr;
}
HRESULT
spawnDNSInstaller(PROCESS_INFORMATION& info)
{
LOG_FUNCTION(spawnDNSInstaller);
HRESULT hr = S_OK;
// CODEWORK: use GetTempPath?
String sysFolder = Win::GetSystemDirectory();
String infPath = sysFolder + L"\\dcpinf.000";
String unattendPath = sysFolder + L"\\dcpunat.001";
// create the inf and unattend files for the oc manager
do
{
hr = createTempFile(infPath, IDS_INSTALL_DNS_INF_TEXT);
BREAK_ON_FAILED_HRESULT(hr);
hr = createTempFile(unattendPath, IDS_INSTALL_DNS_UNATTEND_TEXT);
BREAK_ON_FAILED_HRESULT(hr);
String commandLine =
String::format(
IDS_INSTALL_DNS_COMMAND_LINE,
sysFolder.c_str(),
infPath.c_str(),
unattendPath.c_str());
STARTUPINFO startup;
memset(&startup, 0, sizeof(startup));
LOG(L"Calling CreateProcess");
LOG(commandLine);
hr =
Win::CreateProcess(
commandLine,
0,
0,
false,
0,
0,
String(),
startup,
info);
BREAK_ON_FAILED_HRESULT(hr);
}
while (0);
return hr;
}
bool
installDNS(ProgressDialog& progressDialog)
{
LOG_FUNCTION(installDNS);
if (Dns::IsServiceInstalled())
{
LOG(L"DNS service is already installed");
if (Dns::IsServiceRunning())
{
LOG(L"DNS service is already running");
return true;
}
// @@ start the DNS service Dns::StartService?
}
progressDialog.UpdateText(String::load(IDS_INSTALLING_DNS));
PROCESS_INFORMATION info;
HRESULT hr = spawnDNSInstaller(info);
if (FAILED(hr))
{
progressDialog.UpdateText(
String::load(IDS_PROGRESS_ERROR_INSTALLING_DNS));
popup.Error(
progressDialog.GetHWND(),
hr,
IDS_ERROR_LAUNCHING_INSTALLER);
return false;
}
progressDialog.UpdateButton(IDS_PROGRESS_BUTTON_SKIP_DNS);
// monitor the state of the installer process.
for (int waitCount = 0; /* empty */ ; waitCount++)
{
progressDialog.UpdateText(
String::format(
IDS_WAITING_FOR_INSTALLER,
millisecondsToSeconds(NAP_TIME * waitCount)));
if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
{
progressDialog.UpdateButton(String());
popup.Info(
progressDialog.GetHWND(),
String::load(IDS_SKIP_DNS_MESSAGE));
break;
}
DWORD exitCode = 0;
hr = Win::GetExitCodeProcess(info.hProcess, exitCode);
if (FAILED(hr))
{
LOG(L"GetExitCodeProcess failed");
LOG_HRESULT(hr);
progressDialog.UpdateText(
String::load(IDS_PROGRESS_ERROR_INSTALLING_DNS));
popup.Error(
progressDialog.GetHWND(),
hr,
IDS_ERROR_QUERYING_INSTALLER);
return false;
}
if (exitCode != STILL_ACTIVE)
{
// installer has terminated. Now check the status of the DNS
// service
return pollForDNSServiceInstallAndStart(progressDialog);
}
}
// user bailed out
return false;
}
bool
InstallAndConfigureDns(
ProgressDialog& progressDialog,
const String& domainDNSName)
{
LOG_FUNCTION2(DNSSetup, domainDNSName);
ASSERT(!domainDNSName.empty());
if (!installDNS(progressDialog))
{
return false;
}
progressDialog.UpdateText(String::load(IDS_CONFIGURING_DNS));
HINSTANCE dnsmgr = 0;
HRESULT hr = Win::LoadLibrary(String::load(IDS_DNSMGR_DLL_NAME), dnsmgr);
if (SUCCEEDED(hr))
{
FARPROC proc = 0;
hr = Win::GetProcAddress(dnsmgr, L"DnsSetup", proc);
if (SUCCEEDED(hr))
{
String p1 = domainDNSName;
if (*(p1.rbegin()) != L'.')
{
// add trailing dot
p1 += L'.';
}
String p2 = p1 + L"dns";
LOG(L"Calling DnsSetup");
LOG(String::format(L"lpszFwdZoneName : %1", p1.c_str()));
LOG(String::format(L"lpszFwdZoneFileName : %1", p2.c_str()));
LOG( L"lpszRevZoneName : (null)");
LOG( L"lpszRevZoneFileName : (null)");
LOG( L"dwFlags : 0");
typedef HRESULT (*DNSSetup)(PCWSTR, PCWSTR, PCWSTR, PCWSTR, DWORD);
DNSSetup dnsproc = reinterpret_cast<DNSSetup>(proc);
hr = dnsproc(p1.c_str(), p2.c_str(), 0, 0, 0);
}
else
{
LOG(L"unable to locate DnsSetup proc address");
}
HRESULT unused = Win::FreeLibrary(dnsmgr);
ASSERT(SUCCEEDED(unused));
}
else
{
LOG(L"unable to load DNSMGR");
}
LOG_HRESULT(hr);
if (FAILED(hr))
{
// unable to configure DNS, but it was installed.
progressDialog.UpdateText(
String::load(IDS_PROGRESS_ERROR_CONFIGURING_DNS));
popup.Error(
progressDialog.GetHWND(),
hr,
String::format(IDS_ERROR_CONFIGURING_DNS, domainDNSName.c_str()));
return false;
}
return true;
}