356 lines
7.7 KiB
C++
356 lines
7.7 KiB
C++
|
// 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|