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.
754 lines
24 KiB
754 lines
24 KiB
// Settings.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "utils.h"
|
|
#include "Settings.h"
|
|
#include "Hosting.h"
|
|
#include "uihelp.h"
|
|
#include <mstask.h>
|
|
#include <vsmgmt.h>
|
|
|
|
#include <clusapi.h>
|
|
#include <msclus.h>
|
|
#include <vs_clus.hxx> // vss\server\inc
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSettings dialog
|
|
|
|
|
|
CSettings::CSettings(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CSettings::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CSettings)
|
|
m_strVolume = _T("");
|
|
m_llDiffLimitsInMB = 0;
|
|
//}}AFX_DATA_INIT
|
|
m_strComputer = _T("");
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
CSettings::CSettings(LPCTSTR pszComputer, LPCTSTR pszVolume, CWnd* pParent /*=NULL*/)
|
|
: CDialog(CSettings::IDD, pParent)
|
|
{
|
|
m_llDiffLimitsInMB = 0;
|
|
m_strComputer = pszComputer + (TWO_WHACKS(pszComputer) ? 2 : 0);
|
|
m_strVolume = pszVolume;
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
CSettings::~CSettings()
|
|
{
|
|
if (m_pszTaskName)
|
|
free(m_pszTaskName);
|
|
}
|
|
|
|
void CSettings::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CSettings)
|
|
DDX_Control(pDX, IDC_SETTINGS_STORAGE_VOLUME_STATIC, m_ctrlStorageVolumeStatic);
|
|
DDX_Control(pDX, IDC_SETTINGS_DIFFLIMITS_EDIT, m_ctrlDiffLimits);
|
|
DDX_Control(pDX, IDC_SETTINGS_DIFFLIMITS_SPIN, m_ctrlSpin);
|
|
DDX_Control(pDX, IDC_SETTINGS_STORAGE_VOLUME, m_ctrlStorageVolume);
|
|
DDX_Text(pDX, IDC_SETTINGS_VOLUME, m_strVolume);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CSettings, CDialog)
|
|
//{{AFX_MSG_MAP(CSettings)
|
|
ON_BN_CLICKED(IDC_SETTINGS_HOSTING, OnViewFiles)
|
|
ON_BN_CLICKED(IDC_SCHEDULE, OnSchedule)
|
|
ON_CBN_SELCHANGE(IDC_SETTINGS_STORAGE_VOLUME, OnSelchangeDiffVolume)
|
|
ON_WM_CONTEXTMENU()
|
|
ON_WM_HELPINFO()
|
|
ON_BN_CLICKED(IDC_SETTINGS_HAVELIMITS, OnLimits)
|
|
ON_BN_CLICKED(IDC_SETTINGS_NOLIMITS, OnLimits)
|
|
ON_NOTIFY(UDN_DELTAPOS, IDC_SETTINGS_DIFFLIMITS_SPIN, OnDeltaposSettingsSpin)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSettings message handlers
|
|
|
|
void CSettings::OnOK()
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
UpdateData(TRUE);
|
|
|
|
PTSTR pszVolumeName = GetVolumeName(m_pVolumeList, m_strVolume);
|
|
ASSERT(pszVolumeName);
|
|
PTSTR pszDiffAreaVolumeName = GetVolumeName(m_pVolumeList, m_strDiffVolumeDisplayName);
|
|
ASSERT(pszDiffAreaVolumeName);
|
|
|
|
CString strDiffVolumeDisplayName;
|
|
m_ctrlStorageVolume.GetWindowText(strDiffVolumeDisplayName);
|
|
|
|
PTSTR pszNewDiffAreaVolumeName = GetVolumeName(m_pVolumeList, strDiffVolumeDisplayName);
|
|
ASSERT(pszNewDiffAreaVolumeName);
|
|
|
|
ULONGLONG llDiffLimitsInMB = 0;
|
|
ULONGLONG llMaximumDiffSpace = 0;
|
|
if (BST_CHECKED == IsDlgButtonChecked(IDC_SETTINGS_NOLIMITS))
|
|
{
|
|
llDiffLimitsInMB = VSS_ASSOC_NO_MAX_SPACE / g_llMB;
|
|
llMaximumDiffSpace = VSS_ASSOC_NO_MAX_SPACE;
|
|
} else
|
|
{
|
|
CString strDiffLimits;
|
|
m_ctrlDiffLimits.GetWindowText(strDiffLimits);
|
|
if (strDiffLimits.IsEmpty())
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_LIMITS_NEEDED);
|
|
return;
|
|
}
|
|
|
|
llDiffLimitsInMB = (ULONGLONG)_ttoi64(strDiffLimits);
|
|
if (llDiffLimitsInMB < MINIMUM_DIFF_LIMIT_MB)
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_LIMITS_NEEDED);
|
|
return;
|
|
}
|
|
|
|
llMaximumDiffSpace = llDiffLimitsInMB * g_llMB;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
if (m_bReadOnlyDiffVolume ||
|
|
m_bHasDiffAreaAssociation && !strDiffVolumeDisplayName.CompareNoCase(m_strDiffVolumeDisplayName))
|
|
{
|
|
if (llDiffLimitsInMB != m_llDiffLimitsInMB)
|
|
{
|
|
hr = m_spiDiffSnapMgmt->ChangeDiffAreaMaximumSize(
|
|
pszVolumeName,
|
|
pszDiffAreaVolumeName,
|
|
llMaximumDiffSpace);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_llDiffLimitsInMB = llDiffLimitsInMB;
|
|
m_llMaximumDiffSpace = llMaximumDiffSpace;
|
|
} else
|
|
{
|
|
switch (hr)
|
|
{
|
|
case VSS_E_OBJECT_NOT_FOUND:
|
|
{
|
|
// diff association not found, dialog closing
|
|
DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_NOT_FOUND);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_CHANGEDIFFAREAMAX_ERROR);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
{
|
|
if (m_bHasDiffAreaAssociation)
|
|
{
|
|
//
|
|
// Diff Volume has been changed to a different value, we need to
|
|
// remove the old association and create a new one
|
|
//
|
|
hr = m_spiDiffSnapMgmt->ChangeDiffAreaMaximumSize(
|
|
pszVolumeName,
|
|
pszDiffAreaVolumeName,
|
|
VSS_ASSOC_REMOVE);
|
|
}
|
|
|
|
if (llMaximumDiffSpace > 0 && SUCCEEDED(hr))
|
|
{
|
|
hr = m_spiDiffSnapMgmt->AddDiffArea(
|
|
pszVolumeName,
|
|
pszNewDiffAreaVolumeName,
|
|
llMaximumDiffSpace);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_llDiffLimitsInMB = llDiffLimitsInMB;
|
|
m_llMaximumDiffSpace = llMaximumDiffSpace;
|
|
m_strDiffVolumeDisplayName = strDiffVolumeDisplayName;
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
switch (hr)
|
|
{
|
|
case VSS_E_OBJECT_ALREADY_EXISTS:
|
|
{
|
|
// diff association already exists, dialog closing
|
|
DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_ALREADY_EXISTS);
|
|
break;
|
|
}
|
|
case VSS_E_OBJECT_NOT_FOUND:
|
|
{
|
|
// diff association not found, dialog closing
|
|
DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_NOT_FOUND);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_ADDDIFFAREA_ERROR);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if m_spiTask association exists, persist the changes
|
|
if ((ITask *)m_spiTask)
|
|
{
|
|
///////////////////////////////////////////////////////////////////
|
|
// Call IPersistFile::Save to save trigger to disk.
|
|
///////////////////////////////////////////////////////////////////
|
|
CComPtr<IPersistFile> spiPersistFile;
|
|
hr = m_spiTask->QueryInterface(IID_IPersistFile, (void **)&spiPersistFile);
|
|
if (SUCCEEDED(hr))
|
|
hr = spiPersistFile->Save(NULL, TRUE);
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Notify Cluster Task Scheduler resource of the latest triggers
|
|
///////////////////////////////////////////////////////////////////
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = NotifyClusterTaskSchedulerResource(m_spiTS, pszVolumeName);
|
|
}
|
|
|
|
// reset m_spiTask
|
|
m_spiTask.Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_PERSISTSCHEDULE_ERROR);
|
|
|
|
if (m_pszTaskName)
|
|
{
|
|
DeleteOneScheduledTimewarpTasks(
|
|
m_spiTS,
|
|
m_strComputer,
|
|
m_pszTaskName
|
|
);
|
|
//m_spiTS->Delete(m_pszTaskName);
|
|
free(m_pszTaskName);
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
CDialog::OnOK();
|
|
}
|
|
|
|
HRESULT CSettings::NotifyClusterTaskSchedulerResource(
|
|
IN ITaskScheduler* i_piTS,
|
|
IN LPCTSTR i_pszVolumeName
|
|
)
|
|
{
|
|
if (!i_piTS || !i_pszVolumeName || !*i_pszVolumeName)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
try
|
|
{
|
|
CVssClusterAPI cluster;
|
|
bool bRet = cluster.Initialize(m_strComputer);
|
|
CComPtr<ISClusResource> ptrResource;
|
|
if (bRet)
|
|
ptrResource = cluster.GetPhysicalDiskResourceForVolumeName(i_pszVolumeName);
|
|
if (ptrResource)
|
|
{
|
|
PTSTR pszTaskName = NULL;
|
|
CComPtr<ITask> spiTask;
|
|
hr = FindScheduledTimewarpTask(i_piTS, i_pszVolumeName, &spiTask, &pszTaskName);
|
|
if (FAILED(hr))
|
|
throw hr;
|
|
|
|
if (S_FALSE == hr)
|
|
{
|
|
(void)DeleteAllScheduledTimewarpTasks(i_piTS,
|
|
m_strComputer,
|
|
i_pszVolumeName,
|
|
TRUE // i_bDeleteDisabledOnesOnly
|
|
);
|
|
throw hr;
|
|
}
|
|
|
|
WORD cTriggers = 0;
|
|
hr = spiTask->GetTriggerCount(&cTriggers);
|
|
if (FAILED(hr))
|
|
throw hr;
|
|
|
|
TASK_TRIGGER *pTriggers = NULL;
|
|
if (cTriggers > 0)
|
|
{
|
|
pTriggers = (TASK_TRIGGER *)calloc(cTriggers, sizeof(TASK_TRIGGER));
|
|
if (!pTriggers)
|
|
throw E_OUTOFMEMORY;
|
|
}
|
|
|
|
for (WORD i = 0; i < cTriggers; i++)
|
|
{
|
|
CComPtr<ITaskTrigger> spiTaskTrigger;
|
|
hr = spiTask->GetTrigger(i, &spiTaskTrigger);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
pTriggers[i].cbTriggerSize = sizeof(TASK_TRIGGER);
|
|
hr = spiTaskTrigger->GetTrigger(pTriggers + i);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bRet = cluster.UpdateTaskSchedulerResource(pszTaskName, cTriggers, pTriggers);
|
|
if (!bRet)
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (pTriggers)
|
|
free(pTriggers);
|
|
|
|
throw hr;
|
|
}
|
|
} catch (HRESULT hrClus)
|
|
{
|
|
hr = hrClus;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CSettings::OnCancel()
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
//
|
|
// before exit, we want to delete the schedule we have created
|
|
//
|
|
if (m_pszTaskName)
|
|
{
|
|
DeleteOneScheduledTimewarpTasks(
|
|
m_spiTS,
|
|
m_strComputer,
|
|
m_pszTaskName
|
|
);
|
|
//m_spiTS->Delete(m_pszTaskName);
|
|
}
|
|
|
|
CDialog::OnCancel();
|
|
}
|
|
|
|
void CSettings::_ResetInterfacePointers()
|
|
{
|
|
if ((IVssDifferentialSoftwareSnapshotMgmt *)m_spiDiffSnapMgmt)
|
|
m_spiDiffSnapMgmt.Release();
|
|
|
|
if ((ITaskScheduler *)m_spiTS)
|
|
m_spiTS.Release();
|
|
|
|
m_bCluster = FALSE;
|
|
}
|
|
|
|
HRESULT CSettings::Init(
|
|
IVssDifferentialSoftwareSnapshotMgmt *piDiffSnapMgmt,
|
|
ITaskScheduler* piTS,
|
|
BOOL bCluster,
|
|
IN VSSUI_VOLUME_LIST* pVolumeList,
|
|
IN BOOL bReadOnlyDiffVolume
|
|
)
|
|
{
|
|
if (!piDiffSnapMgmt || !piTS ||
|
|
!pVolumeList || pVolumeList->empty())
|
|
return E_INVALIDARG;
|
|
|
|
_ResetInterfacePointers();
|
|
|
|
m_pVolumeList = pVolumeList;
|
|
m_bReadOnlyDiffVolume = bReadOnlyDiffVolume;
|
|
m_spiDiffSnapMgmt = piDiffSnapMgmt;
|
|
m_spiTS = piTS;
|
|
m_bCluster = bCluster;
|
|
|
|
HRESULT hr = S_OK;
|
|
do
|
|
{
|
|
VSSUI_DIFFAREA diffArea;
|
|
hr = GetDiffAreaInfo(m_spiDiffSnapMgmt, m_pVolumeList, m_strVolume, &diffArea);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
m_bHasDiffAreaAssociation = (S_OK == hr);
|
|
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = GetVolumeSpace(
|
|
m_spiDiffSnapMgmt,
|
|
m_strVolume,
|
|
&m_llDiffVolumeTotalSpace,
|
|
&m_llDiffVolumeFreeSpace);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
m_strDiffVolumeDisplayName = m_strVolume;
|
|
m_llMaximumDiffSpace = max(m_llDiffVolumeTotalSpace * 0.1, MINIMUM_DIFF_LIMIT); // 10%
|
|
} else
|
|
{
|
|
m_strDiffVolumeDisplayName = diffArea.pszDiffVolumeDisplayName;
|
|
m_llMaximumDiffSpace = diffArea.llMaximumDiffSpace;
|
|
|
|
hr = GetVolumeSpace(
|
|
m_spiDiffSnapMgmt,
|
|
m_strDiffVolumeDisplayName,
|
|
&m_llDiffVolumeTotalSpace,
|
|
&m_llDiffVolumeFreeSpace);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
|
|
m_llDiffLimitsInMB = m_llMaximumDiffSpace / g_llMB;
|
|
} while(0);
|
|
|
|
if (FAILED(hr))
|
|
_ResetInterfacePointers();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#define ULONGLONG_TEXTLIMIT 20 // 20 decimal digits for the biggest LONGLONG
|
|
|
|
BOOL CSettings::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// Get list of volumes supported for diff areas
|
|
// (Note: The volume list passed in Init() is a list of volumes supported for
|
|
// snapshot, not for diff area... If this list is not required here then vssprop
|
|
// may be changed to pass a different list...)
|
|
VSSUI_VOLUME_LIST diffVolumeList;
|
|
VSSUI_VOLUME_LIST *pDiffVolumeList = &diffVolumeList;
|
|
|
|
HRESULT hrDiff = GetVolumesSupportedForDiffArea(m_spiDiffSnapMgmt, m_strVolume, pDiffVolumeList);
|
|
if (FAILED(hrDiff))
|
|
// Default to input list
|
|
pDiffVolumeList = m_pVolumeList;
|
|
|
|
// init diff volume combo box
|
|
int nIndex = CB_ERR;
|
|
BOOL bAdded = FALSE;
|
|
BOOL bSelected = FALSE;
|
|
for (VSSUI_VOLUME_LIST::iterator i = pDiffVolumeList->begin(); i != pDiffVolumeList->end(); i++)
|
|
{
|
|
nIndex = m_ctrlStorageVolume.AddString((*i)->pszDisplayName);
|
|
if (CB_ERR != nIndex)
|
|
{
|
|
bAdded = TRUE;
|
|
if(! m_strDiffVolumeDisplayName.CompareNoCase((*i)->pszDisplayName))
|
|
{
|
|
m_ctrlStorageVolume.SetCurSel(nIndex);
|
|
bSelected = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (bAdded && !bSelected)
|
|
// At least one volume added but none is selected - select first one
|
|
// (this can happen when the volume is not supported as diff area)
|
|
m_ctrlStorageVolume.SetCurSel(0);
|
|
|
|
if (! FAILED(hrDiff))
|
|
FreeVolumeList(&diffVolumeList);
|
|
|
|
m_ctrlStorageVolume.EnableWindow(!m_bReadOnlyDiffVolume);
|
|
m_ctrlStorageVolumeStatic.EnableWindow(!m_bReadOnlyDiffVolume);
|
|
|
|
if (m_llMaximumDiffSpace == VSS_ASSOC_NO_MAX_SPACE)
|
|
CheckDlgButton(IDC_SETTINGS_NOLIMITS, BST_CHECKED);
|
|
else
|
|
CheckDlgButton(IDC_SETTINGS_HAVELIMITS, BST_CHECKED);
|
|
OnLimits();
|
|
|
|
m_ctrlDiffLimits.SetLimitText(ULONGLONG_TEXTLIMIT);
|
|
|
|
if (m_llDiffVolumeTotalSpace >= MINIMUM_DIFF_LIMIT)
|
|
{
|
|
LONG maxSpinRange = min(0x7FFFFFFF, m_llDiffVolumeTotalSpace / g_llMB);
|
|
maxSpinRange = (maxSpinRange / MINIMUM_DIFF_LIMIT_DELTA_MB) * MINIMUM_DIFF_LIMIT_DELTA_MB;
|
|
m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, maxSpinRange);
|
|
}
|
|
else
|
|
m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, 0x7FFFFFFF);
|
|
|
|
if (m_llMaximumDiffSpace != VSS_ASSOC_NO_MAX_SPACE)
|
|
{
|
|
CString strDiffLimitsInMB;
|
|
strDiffLimitsInMB.Format(_T("%I64d"), m_llDiffLimitsInMB);
|
|
m_ctrlDiffLimits.SetWindowText(strDiffLimitsInMB);
|
|
} else
|
|
m_ctrlDiffLimits.SetWindowText(_T("")); // default to be 100MB, no need to localize
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
void CSettings::OnViewFiles()
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
CString strStorageVolume;
|
|
m_ctrlStorageVolume.GetWindowText(strStorageVolume);
|
|
|
|
ULONGLONG llDiffVolumeTotalSpace = 0;
|
|
ULONGLONG llDiffVolumeFreeSpace = 0;
|
|
HRESULT hr = GetVolumeSpace(
|
|
m_spiDiffSnapMgmt,
|
|
strStorageVolume,
|
|
&llDiffVolumeTotalSpace,
|
|
&llDiffVolumeFreeSpace);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CHosting dlg(m_strComputer, strStorageVolume);
|
|
hr = dlg.Init(m_spiDiffSnapMgmt,
|
|
m_pVolumeList,
|
|
strStorageVolume,
|
|
llDiffVolumeTotalSpace,
|
|
llDiffVolumeFreeSpace);
|
|
|
|
if (SUCCEEDED(hr))
|
|
dlg.DoModal();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_VIEWFILES_ERROR, strStorageVolume);
|
|
}
|
|
|
|
void CSettings::OnSchedule()
|
|
{
|
|
CWaitCursor wait;
|
|
HRESULT hr = S_OK;
|
|
BOOL bNewSchedule = FALSE;
|
|
|
|
//
|
|
// In case we have never associated m_spiTask with a schedule task, try to
|
|
// associate it with an existing task, otherwise, with a new schedule task.
|
|
//
|
|
if (!m_spiTask)
|
|
{
|
|
PTSTR pszVolumeName = GetVolumeName(m_pVolumeList, m_strVolume);
|
|
ASSERT(pszVolumeName);
|
|
if (! pszVolumeName)
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_FINDSCHEDULE_ERROR, m_strVolume);
|
|
return;
|
|
}
|
|
|
|
hr = FindScheduledTimewarpTask((ITaskScheduler *)m_spiTS, pszVolumeName, &m_spiTask, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_FINDSCHEDULE_ERROR, m_strVolume);
|
|
return;
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
//
|
|
// schedule not found, we need to create a new task with the default schedule
|
|
//
|
|
if (m_pszTaskName)
|
|
{
|
|
free(m_pszTaskName);
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
hr = CreateDefaultEnableSchedule(
|
|
(ITaskScheduler *)m_spiTS,
|
|
m_strComputer,
|
|
m_strVolume,
|
|
pszVolumeName,
|
|
&m_spiTask,
|
|
&m_pszTaskName); // remember the taskname, we need to delete it if dlg is cancelled.
|
|
if (FAILED(hr))
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_CREATESCHEDULE_ERROR, m_strVolume);
|
|
|
|
return;
|
|
}
|
|
|
|
bNewSchedule = TRUE;
|
|
}
|
|
}
|
|
|
|
ASSERT((ITask *)m_spiTask);
|
|
|
|
//
|
|
// bring up the property sheet as modal with only the schedule tab
|
|
//
|
|
CComPtr<IProvideTaskPage> spiProvTaskPage;
|
|
hr = m_spiTask->QueryInterface(IID_IProvideTaskPage, (void **)&spiProvTaskPage);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// call GetPage with FALSE, we'll persist the schedule changes in OnOK
|
|
//
|
|
HPROPSHEETPAGE phPage = NULL;
|
|
hr = spiProvTaskPage->GetPage(TASKPAGE_SCHEDULE, FALSE, &phPage);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PROPSHEETHEADER psh;
|
|
ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
|
|
psh.hwndParent = m_hWnd;
|
|
psh.hInstance = _Module.GetResourceInstance();
|
|
psh.pszCaption = m_strVolume;
|
|
psh.phpage = &phPage;
|
|
psh.nPages = 1;
|
|
|
|
int id = PropertySheet(&psh);
|
|
|
|
//
|
|
// BUG#428943 LinanT
|
|
// In case this is a new schedule task created at this entry of button click,
|
|
// we need to discard it if user cancels the schedule page.
|
|
//
|
|
if (IDOK != id && bNewSchedule)
|
|
{
|
|
if (m_pszTaskName)
|
|
{
|
|
DeleteOneScheduledTimewarpTasks(
|
|
m_spiTS,
|
|
m_strComputer,
|
|
m_pszTaskName
|
|
);
|
|
//m_spiTS->Delete(m_pszTaskName);
|
|
free(m_pszTaskName);
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
// reset m_spiTask
|
|
m_spiTask.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_SCHEDULEPAGE_ERROR);
|
|
|
|
if (m_pszTaskName)
|
|
{
|
|
DeleteOneScheduledTimewarpTasks(
|
|
m_spiTS,
|
|
m_strComputer,
|
|
m_pszTaskName
|
|
);
|
|
//m_spiTS->Delete(m_pszTaskName);
|
|
free(m_pszTaskName);
|
|
m_pszTaskName = NULL;
|
|
}
|
|
|
|
// reset m_spiTask
|
|
m_spiTask.Release();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void CSettings::OnSelchangeDiffVolume()
|
|
{
|
|
CWaitCursor wait;
|
|
|
|
int nIndex = m_ctrlStorageVolume.GetCurSel();
|
|
ASSERT(CB_ERR != nIndex);
|
|
|
|
CString strDiffVolumeDisplayName;
|
|
m_ctrlStorageVolume.GetLBText(nIndex, strDiffVolumeDisplayName);
|
|
|
|
ULONGLONG llDiffVolumeTotalSpace = 0;
|
|
ULONGLONG llDiffVolumeFreeSpace = 0;
|
|
HRESULT hr = GetVolumeSpace(
|
|
m_spiDiffSnapMgmt,
|
|
strDiffVolumeDisplayName,
|
|
&llDiffVolumeTotalSpace,
|
|
&llDiffVolumeFreeSpace);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (llDiffVolumeTotalSpace >= MINIMUM_DIFF_LIMIT)
|
|
{
|
|
LONG maxSpinRange = min(0x7FFFFFFF, llDiffVolumeTotalSpace / g_llMB);
|
|
maxSpinRange = (maxSpinRange / MINIMUM_DIFF_LIMIT_DELTA_MB) * MINIMUM_DIFF_LIMIT_DELTA_MB;
|
|
m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, maxSpinRange);
|
|
}
|
|
else
|
|
m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, 0x7FFFFFFF);
|
|
}
|
|
}
|
|
|
|
void CSettings::OnContextMenu(CWnd* pWnd, CPoint point)
|
|
{
|
|
if (!pWnd)
|
|
return;
|
|
|
|
::WinHelp(pWnd->GetSafeHwnd(),
|
|
VSSUI_CTX_HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(PVOID)aMenuHelpIDsForSettings);
|
|
}
|
|
|
|
BOOL CSettings::OnHelpInfo(HELPINFO* pHelpInfo)
|
|
{
|
|
if (!pHelpInfo ||
|
|
pHelpInfo->iContextType != HELPINFO_WINDOW ||
|
|
pHelpInfo->iCtrlId < 0)
|
|
return FALSE;
|
|
|
|
::WinHelp((HWND)pHelpInfo->hItemHandle,
|
|
VSSUI_CTX_HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(PVOID)aMenuHelpIDsForSettings);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CSettings::OnLimits()
|
|
{
|
|
// TODO: Add your control notification handler code here
|
|
|
|
BOOL bNoLimits = (BST_CHECKED == IsDlgButtonChecked(IDC_SETTINGS_NOLIMITS));
|
|
|
|
m_ctrlDiffLimits.EnableWindow(!bNoLimits);
|
|
m_ctrlSpin.EnableWindow(!bNoLimits);
|
|
}
|
|
|
|
void CSettings::OnDeltaposSettingsSpin(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
|
|
|
|
// Change delta to min-diff-area-size-delta instead of the spin control default which is 1
|
|
ASSERT(pNMUpDown);
|
|
int pos = pNMUpDown->iPos;
|
|
if (pNMUpDown->iDelta == 1)
|
|
pNMUpDown->iDelta =
|
|
(pos / MINIMUM_DIFF_LIMIT_DELTA_MB + 1) * MINIMUM_DIFF_LIMIT_DELTA_MB - pos;
|
|
else if (pNMUpDown->iDelta == -1)
|
|
pNMUpDown->iDelta =
|
|
(pos - 1) / MINIMUM_DIFF_LIMIT_DELTA_MB * MINIMUM_DIFF_LIMIT_DELTA_MB - pos;
|
|
|
|
*pResult = 0;
|
|
}
|