Leaked source code of windows server 2003
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.
 
 
 
 
 
 

531 lines
11 KiB

// Copyright (C) 1997-2000 Microsoft Corporation
//
// install replica from media page
//
// 7 Feb 2000 sburns
#include "headers.hxx"
#include "resource.h"
#include "common.hpp"
#include "page.hpp"
#include "ReplicateFromMediaPage.hpp"
#include "state.hpp"
#include "SyskeyDiskDialog.hpp"
#include "SyskeyPromptDialog.hpp"
ReplicateFromMediaPage::ReplicateFromMediaPage()
:
DCPromoWizardPage(
IDD_REPLICATE_FROM_MEDIA,
IDS_REPLICATE_FROM_MEDIA_PAGE_TITLE,
IDS_REPLICATE_FROM_MEDIA_PAGE_SUBTITLE)
{
LOG_CTOR(ReplicateFromMediaPage);
}
ReplicateFromMediaPage::~ReplicateFromMediaPage()
{
LOG_DTOR(ReplicateFromMediaPage);
}
String
FirstFixedDisk()
{
LOG_FUNCTION(FirstFixedDisk);
String result;
do
{
StringVector dl;
HRESULT hr = FS::GetValidDrives(std::back_inserter(dl));
BREAK_ON_FAILED_HRESULT(hr);
ASSERT(dl.size());
for (
StringVector::iterator i = dl.begin();
i != dl.end();
++i)
{
String rootPath = *i + L"\\";
if (Win::GetDriveType(rootPath) == DRIVE_FIXED)
{
result = *i;
break;
}
}
}
while (0);
if (result.empty())
{
// This is deadcode, really, cause we're sure to find a fixed volume
// somewhere
result = FS::GetRootFolder(Win::GetSystemDirectory()).substr(0, 3);
}
LOG(result);
return result;
}
void
ReplicateFromMediaPage::OnInit()
{
LOG_FUNCTION(ReplicateFromMediaPage::OnInit);
Win::Edit_LimitText(Win::GetDlgItem(hwnd, IDC_SOURCE), MAX_PATH);
State& state = State::GetInstance();
if (state.UsingAnswerFile())
{
String option =
state.GetAnswerFileOption(AnswerFile::OPTION_SOURCE_PATH);
if (!option.empty())
{
Win::CheckDlgButton(hwnd, IDC_USE_FILES, BST_CHECKED);
Win::SetDlgItemText(
hwnd,
IDC_SOURCE,
Win::ExpandEnvironmentStrings(option));
return;
}
}
Win::CheckDlgButton(hwnd, IDC_USE_NET, BST_CHECKED);
String root = FirstFixedDisk();
Win::SetDlgItemText(
hwnd,
IDC_SOURCE,
root + String::load(IDS_SOURCE_SUFFIX));
}
void
ReplicateFromMediaPage::Enable()
{
int next = PSWIZB_NEXT;
bool useFiles = Win::IsDlgButtonChecked(hwnd, IDC_USE_FILES);
if (useFiles)
{
// if using files, the edit box must have some text.
if (Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE).empty())
{
next = 0;
}
}
Win::PropSheet_SetWizButtons(
Win::GetParent(hwnd),
PSWIZB_BACK | next);
Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_SOURCE), useFiles);
Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_BROWSE), useFiles);
}
bool
ReplicateFromMediaPage::OnCommand(
HWND /* windowFrom */ ,
unsigned controlIDFrom,
unsigned code)
{
// LOG_FUNCTION(ReplicateFromMediaPage::OnCommand);
switch (controlIDFrom)
{
case IDC_USE_NET:
case IDC_USE_FILES:
{
if (code == BN_CLICKED)
{
SetChanged(controlIDFrom);
Enable();
return true;
}
}
case IDC_BROWSE:
{
if (code == BN_CLICKED)
{
String path = BrowseForFolder(hwnd, IDS_SOURCE_BROWSE_TITLE);
if (!path.empty())
{
Win::SetDlgItemText(hwnd, IDC_SOURCE, path);
}
return true;
}
break;
}
case IDC_SOURCE:
{
if (code == EN_CHANGE)
{
SetChanged(controlIDFrom);
Enable();
return true;
}
break;
}
default:
{
// do nothing
break;
}
}
return false;
}
bool
ReplicateFromMediaPage::OnSetActive()
{
LOG_FUNCTION(ReplicateFromMediaPage::OnSetActive);
ASSERT(State::GetInstance().GetOperation() == State::REPLICA);
Win::PropSheet_SetWizButtons(
Win::GetParent(hwnd),
PSWIZB_BACK);
State& state = State::GetInstance();
if (state.RunHiddenUnattended() || !state.IsAdvancedMode())
{
LOG(L"skipping ReplicateFromMediaPage");
Wizard& wiz = GetWizard();
if (wiz.IsBacktracking())
{
// backup once again
wiz.Backtrack(hwnd);
return true;
}
int nextPage = ReplicateFromMediaPage::Validate();
if (nextPage != -1)
{
wiz.SetNextPageID(hwnd, nextPage);
}
else
{
state.ClearHiddenWhileUnattended();
}
}
Enable();
return true;
}
bool
ValidateSourcePath(HWND parent, const String& path, int editResId)
{
LOG_FUNCTION2(ValidateSourcePath, path);
bool result = false;
do
{
if (path.empty())
{
popup.Gripe(
parent,
editResId,
IDS_MUST_ENTER_SOURCE_PATH);
break;
}
// Path must have a drive letter
FS::PathSyntax syn = FS::GetPathSyntax(path);
if (syn != FS::SYNTAX_ABSOLUTE_DRIVE)
{
popup.Gripe(
parent,
editResId,
String::format(IDS_BAD_PATH_FORMAT, path.c_str()));
break;
}
// mapped network drives are not ok. This is because the DsRole apis
// copy the restored files on the server side of the api, in the
// system context.
// NTRAID#NTBUG9-309422-2001/02/12-sburns
UINT type = Win::GetDriveType(path);
switch (type)
{
// allow CDs and removeable media, too
// NTRAID#NTBUG9-648713-2002/06/25-sburns
case DRIVE_FIXED:
case DRIVE_CDROM:
case DRIVE_RAMDISK:
case DRIVE_REMOVABLE:
{
result = true;
break;
}
case DRIVE_UNKNOWN:
case DRIVE_NO_ROOT_DIR:
case DRIVE_REMOTE:
default:
{
popup.Gripe(
parent,
editResId,
String::format(IDS_BAD_DRIVE_TYPE, path.c_str()));
break;
}
}
}
while (0);
LOG(result ? L"true" : L"false")
return result;
}
// Return true on success, false on failure
bool
GetDatabaseFacts(HWND parent, const String& sourcePath)
{
LOG_FUNCTION2(GetDatabaseFacts, sourcePath);
DSROLE_IFM_OPERATION_HANDLE IfmHandle;
ASSERT(Win::IsWindow(parent));
ASSERT(!sourcePath.empty());
bool result = false;
PWSTR dnsDomainName = 0;
State& state = State::GetInstance();
state.SetIsBackupGc(false);
state.SetSyskeyLocation(State::STORED);
// If there was an IfmHandle already, free it.
state.FreeIfmHandle();
LOG(L"Calling DsRoleGetDatabaseFacts");
LOG(String::format(L"lpRestorePath: %1", sourcePath.c_str()));
ULONG facts = 0;
HRESULT hr =
Win32ToHresult(
::DsRoleGetDatabaseFacts(
0, // this server
sourcePath.c_str(),
&dnsDomainName,
&facts,
&IfmHandle));
LOG_HRESULT(hr);
if (SUCCEEDED(hr) && IfmHandle)
{
LOG(String::format(L"lpDNSDomainName: %1", dnsDomainName ? dnsDomainName : L"(null)"));
LOG(String::format(L"State : 0x%1!X!", facts));
if (IfmHandle) {
state.SetIfmHandle(IfmHandle);
}
if (dnsDomainName)
{
// Save this domain name. This will allow us to skip the ReplicaPage
// since we now know the domain name.
state.SetReplicaDomainDNSName(dnsDomainName);
MIDL_user_free(dnsDomainName);
}
if (facts & DSROLE_DC_IS_GC)
{
LOG(L"is gc");
state.SetIsBackupGc(true);
}
if (facts & DSROLE_KEY_DISK)
{
LOG(L"syskey on disk");
state.SetSyskeyLocation(State::DISK);
}
else if (facts & DSROLE_KEY_PROMPT)
{
LOG(L"prompt for syskey");
state.SetSyskeyLocation(State::PROMPT);
}
else if (facts & DSROLE_KEY_STORED)
{
LOG(L"syskey stored");
// we set this as the default value, above.
}
else
{
// The api is insane.
ASSERT(false);
LOG(L"unexpected State value");
}
result = true;
}
else
{
if (SUCCEEDED(hr)) {
ASSERT(IfmHandle == NULL);
ASSERT(!"DsRoleGetDatabaseFacts() should never return success w/o an out param");
hr = Win32ToHresult(ERROR_INVALID_PARAMETER);
LOG_HRESULT(hr);
}
popup.Error(
parent,
hr,
String::format(IDS_GET_FACTS_FAILED, sourcePath.c_str()));
}
LOG(result ? L"true" : L"false");
return result;
}
int
ReplicateFromMediaPage::Validate()
{
LOG_FUNCTION(ReplicateFromMediaPage::Validate);
State& state = State::GetInstance();
int nextPage = -1;
bool useFiles = Win::IsDlgButtonChecked(hwnd, IDC_USE_FILES);
do
{
// Don't check WasChanged for the radio buttons because when running
// unattended, CheckDlgButton does not send a parent BN_CLICKED
// notification, so WasChanged will not be set properly.
// NTRAID#NTBUG9-602141-2002/04/15-sburns
state.SetReplicateFromMedia(useFiles);
if (!useFiles)
{
LOG(L"not using source media for replication");
nextPage = IDD_CONFIG_DNS_CLIENT;
break;
}
String sourcePath = Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE);
if (ValidateSourcePath(hwnd, sourcePath, IDC_SOURCE) )
{
String s =
FS::NormalizePath(Win::GetTrimmedDlgItemText(hwnd, IDC_SOURCE));
state.SetReplicationSourcePath(s);
}
else
{
break;
}
// check the restored backup for the syskey, the domain name, and the DC
// type.
if (!GetDatabaseFacts(hwnd, sourcePath))
{
break;
}
State::SyskeyLocation loc = state.GetSyskeyLocation();
if (loc == State::DISK)
{
// Check if the disk is already inserted
// NTRAID#NTBUG9-522250-2002/01/23-sburns
if (FAILED(SyskeyDiskDialog::LocateSyskey(0)))
{
if (SyskeyDiskDialog().ModalExecute(hwnd) != IDOK)
{
break;
}
}
}
else if (loc == State::PROMPT)
{
if (SyskeyPromptDialog().ModalExecute(hwnd) != IDOK)
{
break;
}
}
// The syskey is present, do we need to jump to the GC confirmation?
if (state.IsBackupGc())
{
nextPage = IDD_GC_CONFIRM;
break;
}
// The syskey is present, the backup is not a gc, so move along
nextPage = IDD_CONFIG_DNS_CLIENT;
}
while (0);
if (nextPage != -1)
{
// only clear changes when the user has specified valid options.
// otherwise, we want to go thru the validation until he gets it
// right.
ClearChanges();
}
LOG(String::format(L"next = %1!d!", nextPage));
return nextPage;
}