windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/snapin/metaback.cpp
2020-09-26 16:20:57 +08:00

1064 lines
19 KiB
C++

/*++
Copyright (c) 1994-2000 Microsoft Corporation
Module Name :
metaback.cpp
Abstract:
Metabase backup and restore dialog
Author:
Ronald Meijer (ronaldm)
Sergei Antonov (sergeia)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#include "stdafx.h"
#include "common.h"
#include "InetMgrApp.h"
#include "iisobj.h"
#include "mddefw.h"
#include "metaback.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// CBackupsListBox : a listbox of CBackup objects
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//
// Column width relative weights
//
#define WT_LOCATION 8
#define WT_VERSION 2
#define WT_DATE 6
//
// Registry key name for this dialog
//
const TCHAR g_szRegKey[] = _T("MetaBack");
IMPLEMENT_DYNAMIC(CBackupsListBox, CHeaderListBox);
const int CBackupsListBox::nBitmaps = 1;
#define HAS_BACKUP_PASSWORD(x) \
((x)->QueryMajorVersion() == 5 && (x)->QueryMinorVersion() == 1) || ((x)->QueryMajorVersion() >= 6)
CBackupsListBox::CBackupsListBox()
/*++
Routine Description:
Backups listbox constructor
Arguments:
None
Return Value:
N/A
--*/
: CHeaderListBox(HLS_STRETCH, g_szRegKey)
{
}
void
CBackupsListBox::DrawItemEx(
IN CRMCListBoxDrawStruct & ds
)
/*++
Routine Description:
Draw item in the listbox
Arguments:
CRMCListBoxDrawStruct & ds : Input data structure
Return Value:
N/A
--*/
{
CBackupFile * p = (CBackupFile *)ds.m_ItemData;
ASSERT_READ_PTR(p);
DrawBitmap(ds, 0, 0);
CString strVersion;
strVersion.Format(_T("%ld"), p->QueryVersion());
#define MAXLEN (128)
//
// Convert date and time to local format
//
CTime tm;
p->GetTime(tm);
SYSTEMTIME stm =
{
(WORD)tm.GetYear(),
(WORD)tm.GetMonth(),
(WORD)tm.GetDayOfWeek(),
(WORD)tm.GetDay(),
(WORD)tm.GetHour(),
(WORD)tm.GetMinute(),
(WORD)tm.GetSecond(),
0 // Milliseconds
};
CString strDate, strTime;
LPTSTR lp = strDate.GetBuffer(MAXLEN);
::GetDateFormat(
LOCALE_USER_DEFAULT,
DATE_SHORTDATE,
&stm,
NULL,
lp,
MAXLEN
);
strDate.ReleaseBuffer();
lp = strTime.GetBuffer(MAXLEN);
GetTimeFormat(LOCALE_USER_DEFAULT, 0L, &stm, NULL, lp, MAXLEN);
strTime.ReleaseBuffer();
strDate += _T(" ");
strDate += strTime;
ColumnText(ds, 0, TRUE, (LPCTSTR)p->QueryLocation());
ColumnText(ds, 1, FALSE, strVersion);
ColumnText(ds, 2, FALSE, strDate);
}
/* virtual */
BOOL
CBackupsListBox::Initialize()
/*++
Routine Description:
initialize the listbox. Insert the columns
as requested, and lay them out appropriately
Arguments:
None
Return Value:
TRUE if initialized successfully, FALSE otherwise
--*/
{
if (!CHeaderListBox::Initialize())
{
return FALSE;
}
HINSTANCE hInst = AfxGetResourceHandle();
InsertColumn(0, WT_LOCATION, IDS_BACKUP_LOCATION, hInst);
InsertColumn(1, WT_VERSION, IDS_BACKUP_VERSION, hInst);
InsertColumn(2, WT_DATE, IDS_BACKUP_DATE, hInst);
//
// Try to set the widths from the stored registry value,
// otherwise distribute according to column weights specified
//
// if (!SetWidthsFromReg())
// {
DistributeColumns();
// }
return TRUE;
}
//
// Backup file object properties dialog
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CBkupPropDlg::CBkupPropDlg(
IN CIISMachine * pMachine,
IN CWnd * pParent OPTIONAL
)
/*++
Routine Description:
Constructor
Arguments:
CIISMachine * pMachine : Machine object
CWnd * pParent : Optional parent window
Return Value:
N/A
--*/
: CDialog(CBkupPropDlg::IDD, pParent),
m_pMachine(pMachine),
m_strName(),
m_strPassword()
{
ASSERT_PTR(m_pMachine);
}
void
CBkupPropDlg::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBkupPropDlg)
DDX_Control(pDX, IDC_EDIT_BACKUP_NAME, m_edit_Name);
DDX_Control(pDX, IDC_BACKUP_PASSWORD, m_edit_Password);
DDX_Control(pDX, IDC_BACKUP_PASSWORD_CONFIRM, m_edit_PasswordConfirm);
DDX_Control(pDX, IDC_USE_PASSWORD, m_button_Password);
DDX_Control(pDX, IDOK, m_button_OK);
DDX_Text(pDX, IDC_EDIT_BACKUP_NAME, m_strName);
DDV_MaxChars(pDX, m_strName, MD_BACKUP_MAX_LEN - 1);
//}}AFX_DATA_MAP
if (m_button_Password.GetCheck())
{
DDX_Text(pDX, IDC_BACKUP_PASSWORD, m_strPassword);
DDV_MinChars(pDX, m_strPassword, MIN_PASSWORD_LENGTH);
DDX_Text(pDX, IDC_BACKUP_PASSWORD_CONFIRM, m_strPasswordConfirm);
DDV_MinChars(pDX, m_strPasswordConfirm, MIN_PASSWORD_LENGTH);
}
}
//
// Message Map
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BEGIN_MESSAGE_MAP(CBkupPropDlg, CDialog)
//{{AFX_MSG_MAP(CBkupPropDlg)
ON_EN_CHANGE(IDC_EDIT_BACKUP_NAME, OnChangeEditBackupName)
ON_EN_CHANGE(IDC_BACKUP_PASSWORD, OnChangeEditPassword)
ON_EN_CHANGE(IDC_BACKUP_PASSWORD_CONFIRM, OnChangeEditPassword)
ON_BN_CLICKED(IDC_USE_PASSWORD, OnUsePassword)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void
CBkupPropDlg::OnChangeEditBackupName()
/*++
Routine Description:
Backup name edit change notification handler.
Arguments:
None.
Return Value:
None.
--*/
{
BOOL bEnableOK = m_edit_Name.GetWindowTextLength() > 0;
m_button_OK.EnableWindow(bEnableOK);
if (bEnableOK && m_button_Password.GetCheck())
{
m_button_OK.EnableWindow(
m_edit_Password.GetWindowTextLength() >= MIN_PASSWORD_LENGTH
&& m_edit_PasswordConfirm.GetWindowTextLength() >= MIN_PASSWORD_LENGTH);
}
}
BOOL
CBkupPropDlg::OnInitDialog()
/*++
Routine Description:
WM_INITDIALOG handler. Initialize the dialog.
Arguments:
None.
Return Value:
TRUE if no focus is to be set automatically, FALSE if the focus
is already set.
--*/
{
CDialog::OnInitDialog();
m_button_OK.EnableWindow(FALSE);
m_button_Password.EnableWindow(HAS_BACKUP_PASSWORD(m_pMachine));
m_button_Password.SetCheck(FALSE);
m_edit_Password.EnableWindow(FALSE);
m_edit_PasswordConfirm.EnableWindow(FALSE);
return TRUE;
}
void
CBkupPropDlg::OnChangeEditPassword()
{
m_button_OK.EnableWindow(
m_edit_Password.GetWindowTextLength() >= MIN_PASSWORD_LENGTH
&& m_edit_PasswordConfirm.GetWindowTextLength() >= MIN_PASSWORD_LENGTH
&& m_edit_Name.GetWindowTextLength() > 0);
}
void
CBkupPropDlg::OnUsePassword()
{
BOOL bUseIt = m_button_Password.GetCheck();
m_edit_Password.EnableWindow(bUseIt);
m_edit_PasswordConfirm.EnableWindow(bUseIt);
if (bUseIt)
{
OnChangeEditPassword();
}
else
{
OnChangeEditBackupName();
}
}
void
CBkupPropDlg::OnOK()
/*++
Routine Description:
'OK' button handler -- create the backup.
Arguments:
None
Return Value:
None
--*/
{
if (UpdateData(TRUE))
{
if (m_button_Password.GetCheck() && m_strPassword.Compare(m_strPasswordConfirm) != 0)
{
AfxMessageBox(IDS_PASSWORDS_DOESNT_MATCH);
return;
}
BeginWaitCursor();
ASSERT_PTR(m_pMachine);
//
// CODEWORK: Verify impersonation settings
//
CMetaBack mb(m_pMachine->QueryAuthInfo());
CError err(mb.QueryResult());
if (err.Succeeded())
{
if (HAS_BACKUP_PASSWORD(m_pMachine))
{
if (m_button_Password.GetCheck())
{
err = mb.BackupWithPassword(m_strName, m_strPassword);
}
else
{
err = mb.BackupWithPassword(m_strName, _T(""));
}
}
else
{
err = mb.Backup(m_strName);
}
}
EndWaitCursor();
if (err.Failed())
{
m_edit_Name.SetSel(0, -1);
//
// Special error message if IISADMIN just didn't
// like the name.
//
if (err.Win32Error() == ERROR_INVALID_PARAMETER)
{
::AfxMessageBox(IDS_BACKUP_BAD_NAME);
((CEdit *)GetDlgItem(IDC_EDIT_BACKUP_NAME))->SetSel(0, -1);
}
else
{
err.MessageBox();
}
//
// Don't dismiss the dialog
//
return;
}
EndDialog(IDOK);
}
}
//
// Metabase/Restore dialog
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CBackupDlg::CBackupDlg(
IN CIISMachine * pMachine,
IN CWnd * pParent OPTIONAL
)
/*++
Routine Description:
Constructor
Arguments:
CIISMachine * pMachine : Machine object
CWnd * pParent : Optional parent window
Return Value:
N/A
--*/
: m_pMachine(pMachine),
m_list_Backups(),
m_ListBoxRes(IDB_BACKUPS, m_list_Backups.nBitmaps),
m_oblBackups(),
m_fChangedMetabase(FALSE),
CDialog(CBackupDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CBackupDlg)
//}}AFX_DATA_INIT
ASSERT_PTR(m_pMachine);
m_list_Backups.AttachResources(&m_ListBoxRes);
}
void
CBackupDlg::DoDataExchange(
IN CDataExchange * pDX
)
/*++
Routine Description:
Initialise/Store control data
Arguments:
CDataExchange * pDX - DDX/DDV control structure
Return Value:
None
--*/
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBackupDlg)
DDX_Control(pDX, IDC_BUTTON_RESTORE, m_button_Restore);
DDX_Control(pDX, IDC_BUTTON_DELETE, m_button_Delete);
DDX_Control(pDX, IDOK, m_button_Close);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_LIST_BACKUPS, m_list_Backups);
}
void
CBackupDlg::SetControlStates()
/*++
Routine Description:
Setting control states depending on the state of the dialog
Arguments:
None
Return Value:
None
--*/
{
m_button_Restore.EnableWindow(m_list_Backups.GetSelCount() == 1);
m_button_Delete.EnableWindow(m_list_Backups.GetSelCount() > 0);
}
HRESULT
CBackupDlg::EnumerateBackups(
LPCTSTR lpszSelect OPTIONAL
)
/*++
Routine Description:
Enumerate all existing backups, and add them to the listbox
Arguments:
LPCTSTR lpszSelect : Optional item to select
Return Value:
HRESULT
Notes:
The highest version number of the given name (if any) will
be selected.
--*/
{
CWaitCursor wait;
m_list_Backups.SetRedraw(FALSE);
m_list_Backups.ResetContent();
m_oblBackups.RemoveAll();
int nSel = LB_ERR;
ASSERT_PTR(m_pMachine);
//
// CODEWORK: Verify impersonation settings
//
CMetaBack mb(m_pMachine->QueryAuthInfo());
CError err(mb.QueryResult());
if (err.Succeeded())
{
DWORD dwVersion;
FILETIME ft;
TCHAR szPath[MAX_PATH + 1] = _T("");
int nItem = 0;
FOREVER
{
*szPath = _T('\0');
err = mb.Next(&dwVersion, szPath, &ft);
if (err.Failed())
{
break;
}
TRACEEOLID(szPath << " v" << dwVersion);
CBackupFile * pItem = new CBackupFile(szPath, dwVersion, &ft);
if (!pItem)
{
TRACEEOLID("EnumerateBackups: OOM");
err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
m_oblBackups.AddTail(pItem);
VERIFY(LB_ERR != m_list_Backups.AddItem(pItem));
if (lpszSelect != NULL && lstrcmpi(lpszSelect, szPath) == 0)
{
//
// Remember selection for later
//
nSel = nItem;
}
++nItem;
}
if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
{
//
// Finished enumeration successfully
//
err.Reset();
}
}
//
// Select item requested if any
//
m_list_Backups.SetCurSel(nSel);
m_list_Backups.SetRedraw(TRUE);
SetControlStates();
return err;
}
//
// Message Map
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BEGIN_MESSAGE_MAP(CBackupDlg, CDialog)
//{{AFX_MSG_MAP(CBackupDlg)
ON_BN_CLICKED(IDC_BUTTON_CREATE, OnButtonCreate)
ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
ON_BN_CLICKED(IDC_BUTTON_RESTORE, OnButtonRestore)
ON_LBN_DBLCLK(IDC_LIST_BACKUPS, OnDblclkListBackups)
ON_LBN_SELCHANGE(IDC_LIST_BACKUPS, OnSelchangeListBackups)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//
// Message Handlers
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
BOOL
CBackupDlg::OnInitDialog()
/*++
Routine Description:
WM_INITDIALOG handler
Arguments:
None
Return Value:
TRUE if successfully initialized, FALSE otherwise.
--*/
{
CDialog::OnInitDialog();
m_list_Backups.Initialize();
CError err(EnumerateBackups());
if (err.Failed())
{
err.AddOverride(REGDB_E_CLASSNOTREG, IDS_ERR_NO_BACKUP_RESTORE);
m_pMachine->DisplayError(err);
EndDialog(IDCANCEL);
}
return TRUE;
}
void
CBackupDlg::OnButtonCreate()
/*++
Routine Description:
"Create" button handler
Arguments:
None
Return Value:
None
--*/
{
CBkupPropDlg dlg(m_pMachine, this);
if (dlg.DoModal() == IDOK)
{
//
// We can only return OK if the creation worked
// which is done in the properties dialog.
//
EnumerateBackups(dlg.QueryName());
}
}
void
CBackupDlg::OnButtonDelete()
/*++
Routine Description:
"Delete" button handler
Arguments:
None
Return Value:
None
--*/
{
if (!NoYesMessageBox(IDS_CONFIRM_DELETE_ITEMS))
{
//
// Changed his mind
//
return;
}
m_list_Backups.SetRedraw(FALSE);
CWaitCursor wait;
ASSERT_PTR(m_pMachine);
//
// CODEWORK: Verify metabase settings
//
CMetaBack mb(m_pMachine->QueryAuthInfo());
CError err(mb.QueryResult());
if (err.Failed())
{
m_pMachine->DisplayError(err);
return;
}
int nSel = 0;
CBackupFile * pItem;
while ((pItem = m_list_Backups.GetNextSelectedItem(&nSel)) != NULL)
{
TRACEEOLID("Deleting backup "
<< pItem->QueryLocation()
<< " v"
<< pItem->QueryVersion()
);
err = mb.Delete(
pItem->QueryLocation(),
pItem->QueryVersion()
);
if (err.Failed())
{
m_pMachine->DisplayError(err);
break;
}
m_list_Backups.DeleteString(nSel);
//
// Don't advance counter to account for shift
//
}
m_list_Backups.SetRedraw(TRUE);
SetControlStates();
//
// Ensure focus is not on a disabled button.
//
m_button_Close.SetFocus();
}
void
CBackupDlg::OnButtonRestore()
/*++
Routine Description:
'Restore' button handler
Arguments:
None
Return Value:
None
--*/
{
CBackupFile * pItem = GetSelectedListItem();
ASSERT_READ_PTR(pItem);
if (pItem != NULL)
{
if (NoYesMessageBox(IDS_RESTORE_CONFIRM))
{
ASSERT_PTR(m_pMachine);
//
// CODEWORK: Verify impersonation settings
//
CMetaBack mb(m_pMachine->QueryAuthInfo());
CError err(mb.QueryResult());
if (err.Succeeded())
{
//
// the WAM stuff takes a while
//
CWaitCursor wait;
//
// Restore method will take care of WAM save/recover
//
if (HAS_BACKUP_PASSWORD(m_pMachine))
{
err = mb.RestoreWithPassword(pItem->QueryLocation(), pItem->QueryVersion(), _T(""));
}
else
{
err = mb.Restore(pItem->QueryLocation(), pItem->QueryVersion());
}
}
if (err.Win32Error() == ERROR_WRONG_PASSWORD)
{
CBackupPassword dlg(this);
if (dlg.DoModal() == IDOK)
{
CWaitCursor wait;
err = mb.RestoreWithPassword(pItem->QueryLocation(), pItem->QueryVersion(), dlg.m_password);
if (err.Win32Error() == ERROR_WRONG_PASSWORD)
{
::AfxMessageBox(
IDS_WRONG_PASSWORD,
MB_OK | MB_ICONEXCLAMATION
);
return;
}
else if (err.Failed())
{
::AfxMessageBox(
IDS_ERR_CANNOT_RESTORE,
MB_OK | MB_ICONEXCLAMATION
);
return;
}
else
{
::AfxMessageBox(IDS_SUCCESS, MB_OK | MB_ICONINFORMATION);
m_button_Close.SetFocus();
m_fChangedMetabase = TRUE;
}
}
else
{
return;
}
}
else if (err.Succeeded())
{
::AfxMessageBox(IDS_SUCCESS, MB_OK | MB_ICONINFORMATION);
m_button_Close.SetFocus();
m_fChangedMetabase = TRUE;
}
else
{
err.MessageBox();
}
}
}
}
void
CBackupDlg::OnDblclkListBackups()
/*++
Routine Description:
Backup list "double click" notification handler
Arguments:
None
Return Value:
None
--*/
{
//
// Nothing presents itself as an obvious action here
//
}
void
CBackupDlg::OnSelchangeListBackups()
/*++
Routine Description:
Backup list "selection change" notification handler
Arguments:
None
Return Value:
None
--*/
{
SetControlStates();
}
CBackupPassword::CBackupPassword(CWnd * pParent) :
CDialog(CBackupPassword::IDD, pParent)
{
}
BEGIN_MESSAGE_MAP(CBackupPassword, CDialog)
//{{AFX_MSG_MAP(CBackupPassword)
ON_EN_CHANGE(IDC_BACKUP_PASSWORD, OnChangedPassword)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void
CBackupPassword::DoDataExchange(
IN CDataExchange * pDX
)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBackupPassword)
DDX_Control(pDX, IDC_BACKUP_PASSWORD, m_edit);
DDX_Control(pDX, IDOK, m_button_OK);
DDX_Text(pDX, IDC_BACKUP_PASSWORD, m_password);
//}}AFX_DATA_MAP
}
BOOL
CBackupPassword::OnInitDialog()
{
CDialog::OnInitDialog();
m_button_OK.EnableWindow(FALSE);
// ::SetFocus(GetDlgItem(IDC_BACKUP_PASSWORD)->m_hWnd);
return FALSE;
}
void
CBackupPassword::OnChangedPassword()
{
m_button_OK.EnableWindow(
m_edit.GetWindowTextLength() > 0);
}