|
|
// 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; }
|