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.

754 lines
24 KiB

  1. // Settings.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "utils.h"
  5. #include "Settings.h"
  6. #include "Hosting.h"
  7. #include "uihelp.h"
  8. #include <mstask.h>
  9. #include <vsmgmt.h>
  10. #include <clusapi.h>
  11. #include <msclus.h>
  12. #include <vs_clus.hxx> // vss\server\inc
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CSettings dialog
  20. CSettings::CSettings(CWnd* pParent /*=NULL*/)
  21. : CDialog(CSettings::IDD, pParent)
  22. {
  23. //{{AFX_DATA_INIT(CSettings)
  24. m_strVolume = _T("");
  25. m_llDiffLimitsInMB = 0;
  26. //}}AFX_DATA_INIT
  27. m_strComputer = _T("");
  28. m_pszTaskName = NULL;
  29. }
  30. CSettings::CSettings(LPCTSTR pszComputer, LPCTSTR pszVolume, CWnd* pParent /*=NULL*/)
  31. : CDialog(CSettings::IDD, pParent)
  32. {
  33. m_llDiffLimitsInMB = 0;
  34. m_strComputer = pszComputer + (TWO_WHACKS(pszComputer) ? 2 : 0);
  35. m_strVolume = pszVolume;
  36. m_pszTaskName = NULL;
  37. }
  38. CSettings::~CSettings()
  39. {
  40. if (m_pszTaskName)
  41. free(m_pszTaskName);
  42. }
  43. void CSettings::DoDataExchange(CDataExchange* pDX)
  44. {
  45. CDialog::DoDataExchange(pDX);
  46. //{{AFX_DATA_MAP(CSettings)
  47. DDX_Control(pDX, IDC_SETTINGS_STORAGE_VOLUME_STATIC, m_ctrlStorageVolumeStatic);
  48. DDX_Control(pDX, IDC_SETTINGS_DIFFLIMITS_EDIT, m_ctrlDiffLimits);
  49. DDX_Control(pDX, IDC_SETTINGS_DIFFLIMITS_SPIN, m_ctrlSpin);
  50. DDX_Control(pDX, IDC_SETTINGS_STORAGE_VOLUME, m_ctrlStorageVolume);
  51. DDX_Text(pDX, IDC_SETTINGS_VOLUME, m_strVolume);
  52. //}}AFX_DATA_MAP
  53. }
  54. BEGIN_MESSAGE_MAP(CSettings, CDialog)
  55. //{{AFX_MSG_MAP(CSettings)
  56. ON_BN_CLICKED(IDC_SETTINGS_HOSTING, OnViewFiles)
  57. ON_BN_CLICKED(IDC_SCHEDULE, OnSchedule)
  58. ON_CBN_SELCHANGE(IDC_SETTINGS_STORAGE_VOLUME, OnSelchangeDiffVolume)
  59. ON_WM_CONTEXTMENU()
  60. ON_WM_HELPINFO()
  61. ON_BN_CLICKED(IDC_SETTINGS_HAVELIMITS, OnLimits)
  62. ON_BN_CLICKED(IDC_SETTINGS_NOLIMITS, OnLimits)
  63. ON_NOTIFY(UDN_DELTAPOS, IDC_SETTINGS_DIFFLIMITS_SPIN, OnDeltaposSettingsSpin)
  64. //}}AFX_MSG_MAP
  65. END_MESSAGE_MAP()
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CSettings message handlers
  68. void CSettings::OnOK()
  69. {
  70. CWaitCursor wait;
  71. UpdateData(TRUE);
  72. PTSTR pszVolumeName = GetVolumeName(m_pVolumeList, m_strVolume);
  73. ASSERT(pszVolumeName);
  74. PTSTR pszDiffAreaVolumeName = GetVolumeName(m_pVolumeList, m_strDiffVolumeDisplayName);
  75. ASSERT(pszDiffAreaVolumeName);
  76. CString strDiffVolumeDisplayName;
  77. m_ctrlStorageVolume.GetWindowText(strDiffVolumeDisplayName);
  78. PTSTR pszNewDiffAreaVolumeName = GetVolumeName(m_pVolumeList, strDiffVolumeDisplayName);
  79. ASSERT(pszNewDiffAreaVolumeName);
  80. ULONGLONG llDiffLimitsInMB = 0;
  81. ULONGLONG llMaximumDiffSpace = 0;
  82. if (BST_CHECKED == IsDlgButtonChecked(IDC_SETTINGS_NOLIMITS))
  83. {
  84. llDiffLimitsInMB = VSS_ASSOC_NO_MAX_SPACE / g_llMB;
  85. llMaximumDiffSpace = VSS_ASSOC_NO_MAX_SPACE;
  86. } else
  87. {
  88. CString strDiffLimits;
  89. m_ctrlDiffLimits.GetWindowText(strDiffLimits);
  90. if (strDiffLimits.IsEmpty())
  91. {
  92. DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_LIMITS_NEEDED);
  93. return;
  94. }
  95. llDiffLimitsInMB = (ULONGLONG)_ttoi64(strDiffLimits);
  96. if (llDiffLimitsInMB < MINIMUM_DIFF_LIMIT_MB)
  97. {
  98. DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_LIMITS_NEEDED);
  99. return;
  100. }
  101. llMaximumDiffSpace = llDiffLimitsInMB * g_llMB;
  102. }
  103. HRESULT hr = S_OK;
  104. if (m_bReadOnlyDiffVolume ||
  105. m_bHasDiffAreaAssociation && !strDiffVolumeDisplayName.CompareNoCase(m_strDiffVolumeDisplayName))
  106. {
  107. if (llDiffLimitsInMB != m_llDiffLimitsInMB)
  108. {
  109. hr = m_spiDiffSnapMgmt->ChangeDiffAreaMaximumSize(
  110. pszVolumeName,
  111. pszDiffAreaVolumeName,
  112. llMaximumDiffSpace);
  113. if (SUCCEEDED(hr))
  114. {
  115. m_llDiffLimitsInMB = llDiffLimitsInMB;
  116. m_llMaximumDiffSpace = llMaximumDiffSpace;
  117. } else
  118. {
  119. switch (hr)
  120. {
  121. case VSS_E_OBJECT_NOT_FOUND:
  122. {
  123. // diff association not found, dialog closing
  124. DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_NOT_FOUND);
  125. break;
  126. }
  127. default:
  128. {
  129. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_CHANGEDIFFAREAMAX_ERROR);
  130. return;
  131. }
  132. }
  133. }
  134. }
  135. } else
  136. {
  137. if (m_bHasDiffAreaAssociation)
  138. {
  139. //
  140. // Diff Volume has been changed to a different value, we need to
  141. // remove the old association and create a new one
  142. //
  143. hr = m_spiDiffSnapMgmt->ChangeDiffAreaMaximumSize(
  144. pszVolumeName,
  145. pszDiffAreaVolumeName,
  146. VSS_ASSOC_REMOVE);
  147. }
  148. if (llMaximumDiffSpace > 0 && SUCCEEDED(hr))
  149. {
  150. hr = m_spiDiffSnapMgmt->AddDiffArea(
  151. pszVolumeName,
  152. pszNewDiffAreaVolumeName,
  153. llMaximumDiffSpace);
  154. if (SUCCEEDED(hr))
  155. {
  156. m_llDiffLimitsInMB = llDiffLimitsInMB;
  157. m_llMaximumDiffSpace = llMaximumDiffSpace;
  158. m_strDiffVolumeDisplayName = strDiffVolumeDisplayName;
  159. }
  160. }
  161. if (FAILED(hr))
  162. {
  163. switch (hr)
  164. {
  165. case VSS_E_OBJECT_ALREADY_EXISTS:
  166. {
  167. // diff association already exists, dialog closing
  168. DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_ALREADY_EXISTS);
  169. break;
  170. }
  171. case VSS_E_OBJECT_NOT_FOUND:
  172. {
  173. // diff association not found, dialog closing
  174. DoErrMsgBox(m_hWnd, MB_OK, 0, IDS_DIFFASSOC_NOT_FOUND);
  175. break;
  176. }
  177. default:
  178. {
  179. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_ADDDIFFAREA_ERROR);
  180. return;
  181. }
  182. }
  183. }
  184. }
  185. // if m_spiTask association exists, persist the changes
  186. if ((ITask *)m_spiTask)
  187. {
  188. ///////////////////////////////////////////////////////////////////
  189. // Call IPersistFile::Save to save trigger to disk.
  190. ///////////////////////////////////////////////////////////////////
  191. CComPtr<IPersistFile> spiPersistFile;
  192. hr = m_spiTask->QueryInterface(IID_IPersistFile, (void **)&spiPersistFile);
  193. if (SUCCEEDED(hr))
  194. hr = spiPersistFile->Save(NULL, TRUE);
  195. ///////////////////////////////////////////////////////////////////
  196. // Notify Cluster Task Scheduler resource of the latest triggers
  197. ///////////////////////////////////////////////////////////////////
  198. if (SUCCEEDED(hr))
  199. {
  200. hr = NotifyClusterTaskSchedulerResource(m_spiTS, pszVolumeName);
  201. }
  202. // reset m_spiTask
  203. m_spiTask.Release();
  204. if (FAILED(hr))
  205. {
  206. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_PERSISTSCHEDULE_ERROR);
  207. if (m_pszTaskName)
  208. {
  209. DeleteOneScheduledTimewarpTasks(
  210. m_spiTS,
  211. m_strComputer,
  212. m_pszTaskName
  213. );
  214. //m_spiTS->Delete(m_pszTaskName);
  215. free(m_pszTaskName);
  216. m_pszTaskName = NULL;
  217. }
  218. return;
  219. }
  220. }
  221. CDialog::OnOK();
  222. }
  223. HRESULT CSettings::NotifyClusterTaskSchedulerResource(
  224. IN ITaskScheduler* i_piTS,
  225. IN LPCTSTR i_pszVolumeName
  226. )
  227. {
  228. if (!i_piTS || !i_pszVolumeName || !*i_pszVolumeName)
  229. return E_INVALIDARG;
  230. HRESULT hr = S_OK;
  231. try
  232. {
  233. CVssClusterAPI cluster;
  234. bool bRet = cluster.Initialize(m_strComputer);
  235. CComPtr<ISClusResource> ptrResource;
  236. if (bRet)
  237. ptrResource = cluster.GetPhysicalDiskResourceForVolumeName(i_pszVolumeName);
  238. if (ptrResource)
  239. {
  240. PTSTR pszTaskName = NULL;
  241. CComPtr<ITask> spiTask;
  242. hr = FindScheduledTimewarpTask(i_piTS, i_pszVolumeName, &spiTask, &pszTaskName);
  243. if (FAILED(hr))
  244. throw hr;
  245. if (S_FALSE == hr)
  246. {
  247. (void)DeleteAllScheduledTimewarpTasks(i_piTS,
  248. m_strComputer,
  249. i_pszVolumeName,
  250. TRUE // i_bDeleteDisabledOnesOnly
  251. );
  252. throw hr;
  253. }
  254. WORD cTriggers = 0;
  255. hr = spiTask->GetTriggerCount(&cTriggers);
  256. if (FAILED(hr))
  257. throw hr;
  258. TASK_TRIGGER *pTriggers = NULL;
  259. if (cTriggers > 0)
  260. {
  261. pTriggers = (TASK_TRIGGER *)calloc(cTriggers, sizeof(TASK_TRIGGER));
  262. if (!pTriggers)
  263. throw E_OUTOFMEMORY;
  264. }
  265. for (WORD i = 0; i < cTriggers; i++)
  266. {
  267. CComPtr<ITaskTrigger> spiTaskTrigger;
  268. hr = spiTask->GetTrigger(i, &spiTaskTrigger);
  269. if (FAILED(hr))
  270. break;
  271. pTriggers[i].cbTriggerSize = sizeof(TASK_TRIGGER);
  272. hr = spiTaskTrigger->GetTrigger(pTriggers + i);
  273. if (FAILED(hr))
  274. break;
  275. }
  276. if (SUCCEEDED(hr))
  277. {
  278. bRet = cluster.UpdateTaskSchedulerResource(pszTaskName, cTriggers, pTriggers);
  279. if (!bRet)
  280. hr = E_FAIL;
  281. }
  282. if (pTriggers)
  283. free(pTriggers);
  284. throw hr;
  285. }
  286. } catch (HRESULT hrClus)
  287. {
  288. hr = hrClus;
  289. }
  290. return hr;
  291. }
  292. void CSettings::OnCancel()
  293. {
  294. CWaitCursor wait;
  295. //
  296. // before exit, we want to delete the schedule we have created
  297. //
  298. if (m_pszTaskName)
  299. {
  300. DeleteOneScheduledTimewarpTasks(
  301. m_spiTS,
  302. m_strComputer,
  303. m_pszTaskName
  304. );
  305. //m_spiTS->Delete(m_pszTaskName);
  306. }
  307. CDialog::OnCancel();
  308. }
  309. void CSettings::_ResetInterfacePointers()
  310. {
  311. if ((IVssDifferentialSoftwareSnapshotMgmt *)m_spiDiffSnapMgmt)
  312. m_spiDiffSnapMgmt.Release();
  313. if ((ITaskScheduler *)m_spiTS)
  314. m_spiTS.Release();
  315. m_bCluster = FALSE;
  316. }
  317. HRESULT CSettings::Init(
  318. IVssDifferentialSoftwareSnapshotMgmt *piDiffSnapMgmt,
  319. ITaskScheduler* piTS,
  320. BOOL bCluster,
  321. IN VSSUI_VOLUME_LIST* pVolumeList,
  322. IN BOOL bReadOnlyDiffVolume
  323. )
  324. {
  325. if (!piDiffSnapMgmt || !piTS ||
  326. !pVolumeList || pVolumeList->empty())
  327. return E_INVALIDARG;
  328. _ResetInterfacePointers();
  329. m_pVolumeList = pVolumeList;
  330. m_bReadOnlyDiffVolume = bReadOnlyDiffVolume;
  331. m_spiDiffSnapMgmt = piDiffSnapMgmt;
  332. m_spiTS = piTS;
  333. m_bCluster = bCluster;
  334. HRESULT hr = S_OK;
  335. do
  336. {
  337. VSSUI_DIFFAREA diffArea;
  338. hr = GetDiffAreaInfo(m_spiDiffSnapMgmt, m_pVolumeList, m_strVolume, &diffArea);
  339. if (FAILED(hr))
  340. break;
  341. m_bHasDiffAreaAssociation = (S_OK == hr);
  342. if (S_FALSE == hr)
  343. {
  344. hr = GetVolumeSpace(
  345. m_spiDiffSnapMgmt,
  346. m_strVolume,
  347. &m_llDiffVolumeTotalSpace,
  348. &m_llDiffVolumeFreeSpace);
  349. if (FAILED(hr))
  350. break;
  351. m_strDiffVolumeDisplayName = m_strVolume;
  352. m_llMaximumDiffSpace = max(m_llDiffVolumeTotalSpace * 0.1, MINIMUM_DIFF_LIMIT); // 10%
  353. } else
  354. {
  355. m_strDiffVolumeDisplayName = diffArea.pszDiffVolumeDisplayName;
  356. m_llMaximumDiffSpace = diffArea.llMaximumDiffSpace;
  357. hr = GetVolumeSpace(
  358. m_spiDiffSnapMgmt,
  359. m_strDiffVolumeDisplayName,
  360. &m_llDiffVolumeTotalSpace,
  361. &m_llDiffVolumeFreeSpace);
  362. if (FAILED(hr))
  363. break;
  364. }
  365. m_llDiffLimitsInMB = m_llMaximumDiffSpace / g_llMB;
  366. } while(0);
  367. if (FAILED(hr))
  368. _ResetInterfacePointers();
  369. return hr;
  370. }
  371. #define ULONGLONG_TEXTLIMIT 20 // 20 decimal digits for the biggest LONGLONG
  372. BOOL CSettings::OnInitDialog()
  373. {
  374. CDialog::OnInitDialog();
  375. // Get list of volumes supported for diff areas
  376. // (Note: The volume list passed in Init() is a list of volumes supported for
  377. // snapshot, not for diff area... If this list is not required here then vssprop
  378. // may be changed to pass a different list...)
  379. VSSUI_VOLUME_LIST diffVolumeList;
  380. VSSUI_VOLUME_LIST *pDiffVolumeList = &diffVolumeList;
  381. HRESULT hrDiff = GetVolumesSupportedForDiffArea(m_spiDiffSnapMgmt, m_strVolume, pDiffVolumeList);
  382. if (FAILED(hrDiff))
  383. // Default to input list
  384. pDiffVolumeList = m_pVolumeList;
  385. // init diff volume combo box
  386. int nIndex = CB_ERR;
  387. BOOL bAdded = FALSE;
  388. BOOL bSelected = FALSE;
  389. for (VSSUI_VOLUME_LIST::iterator i = pDiffVolumeList->begin(); i != pDiffVolumeList->end(); i++)
  390. {
  391. nIndex = m_ctrlStorageVolume.AddString((*i)->pszDisplayName);
  392. if (CB_ERR != nIndex)
  393. {
  394. bAdded = TRUE;
  395. if(! m_strDiffVolumeDisplayName.CompareNoCase((*i)->pszDisplayName))
  396. {
  397. m_ctrlStorageVolume.SetCurSel(nIndex);
  398. bSelected = TRUE;
  399. }
  400. }
  401. }
  402. if (bAdded && !bSelected)
  403. // At least one volume added but none is selected - select first one
  404. // (this can happen when the volume is not supported as diff area)
  405. m_ctrlStorageVolume.SetCurSel(0);
  406. if (! FAILED(hrDiff))
  407. FreeVolumeList(&diffVolumeList);
  408. m_ctrlStorageVolume.EnableWindow(!m_bReadOnlyDiffVolume);
  409. m_ctrlStorageVolumeStatic.EnableWindow(!m_bReadOnlyDiffVolume);
  410. if (m_llMaximumDiffSpace == VSS_ASSOC_NO_MAX_SPACE)
  411. CheckDlgButton(IDC_SETTINGS_NOLIMITS, BST_CHECKED);
  412. else
  413. CheckDlgButton(IDC_SETTINGS_HAVELIMITS, BST_CHECKED);
  414. OnLimits();
  415. m_ctrlDiffLimits.SetLimitText(ULONGLONG_TEXTLIMIT);
  416. if (m_llDiffVolumeTotalSpace >= MINIMUM_DIFF_LIMIT)
  417. {
  418. LONG maxSpinRange = min(0x7FFFFFFF, m_llDiffVolumeTotalSpace / g_llMB);
  419. maxSpinRange = (maxSpinRange / MINIMUM_DIFF_LIMIT_DELTA_MB) * MINIMUM_DIFF_LIMIT_DELTA_MB;
  420. m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, maxSpinRange);
  421. }
  422. else
  423. m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, 0x7FFFFFFF);
  424. if (m_llMaximumDiffSpace != VSS_ASSOC_NO_MAX_SPACE)
  425. {
  426. CString strDiffLimitsInMB;
  427. strDiffLimitsInMB.Format(_T("%I64d"), m_llDiffLimitsInMB);
  428. m_ctrlDiffLimits.SetWindowText(strDiffLimitsInMB);
  429. } else
  430. m_ctrlDiffLimits.SetWindowText(_T("")); // default to be 100MB, no need to localize
  431. return TRUE; // return TRUE unless you set the focus to a control
  432. // EXCEPTION: OCX Property Pages should return FALSE
  433. }
  434. void CSettings::OnViewFiles()
  435. {
  436. CWaitCursor wait;
  437. CString strStorageVolume;
  438. m_ctrlStorageVolume.GetWindowText(strStorageVolume);
  439. ULONGLONG llDiffVolumeTotalSpace = 0;
  440. ULONGLONG llDiffVolumeFreeSpace = 0;
  441. HRESULT hr = GetVolumeSpace(
  442. m_spiDiffSnapMgmt,
  443. strStorageVolume,
  444. &llDiffVolumeTotalSpace,
  445. &llDiffVolumeFreeSpace);
  446. if (SUCCEEDED(hr))
  447. {
  448. CHosting dlg(m_strComputer, strStorageVolume);
  449. hr = dlg.Init(m_spiDiffSnapMgmt,
  450. m_pVolumeList,
  451. strStorageVolume,
  452. llDiffVolumeTotalSpace,
  453. llDiffVolumeFreeSpace);
  454. if (SUCCEEDED(hr))
  455. dlg.DoModal();
  456. }
  457. if (FAILED(hr))
  458. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_VIEWFILES_ERROR, strStorageVolume);
  459. }
  460. void CSettings::OnSchedule()
  461. {
  462. CWaitCursor wait;
  463. HRESULT hr = S_OK;
  464. BOOL bNewSchedule = FALSE;
  465. //
  466. // In case we have never associated m_spiTask with a schedule task, try to
  467. // associate it with an existing task, otherwise, with a new schedule task.
  468. //
  469. if (!m_spiTask)
  470. {
  471. PTSTR pszVolumeName = GetVolumeName(m_pVolumeList, m_strVolume);
  472. ASSERT(pszVolumeName);
  473. if (! pszVolumeName)
  474. {
  475. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_FINDSCHEDULE_ERROR, m_strVolume);
  476. return;
  477. }
  478. hr = FindScheduledTimewarpTask((ITaskScheduler *)m_spiTS, pszVolumeName, &m_spiTask, NULL);
  479. if (FAILED(hr))
  480. {
  481. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_FINDSCHEDULE_ERROR, m_strVolume);
  482. return;
  483. }
  484. if (S_OK != hr)
  485. {
  486. //
  487. // schedule not found, we need to create a new task with the default schedule
  488. //
  489. if (m_pszTaskName)
  490. {
  491. free(m_pszTaskName);
  492. m_pszTaskName = NULL;
  493. }
  494. hr = CreateDefaultEnableSchedule(
  495. (ITaskScheduler *)m_spiTS,
  496. m_strComputer,
  497. m_strVolume,
  498. pszVolumeName,
  499. &m_spiTask,
  500. &m_pszTaskName); // remember the taskname, we need to delete it if dlg is cancelled.
  501. if (FAILED(hr))
  502. {
  503. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_CREATESCHEDULE_ERROR, m_strVolume);
  504. return;
  505. }
  506. bNewSchedule = TRUE;
  507. }
  508. }
  509. ASSERT((ITask *)m_spiTask);
  510. //
  511. // bring up the property sheet as modal with only the schedule tab
  512. //
  513. CComPtr<IProvideTaskPage> spiProvTaskPage;
  514. hr = m_spiTask->QueryInterface(IID_IProvideTaskPage, (void **)&spiProvTaskPage);
  515. if (SUCCEEDED(hr))
  516. {
  517. //
  518. // call GetPage with FALSE, we'll persist the schedule changes in OnOK
  519. //
  520. HPROPSHEETPAGE phPage = NULL;
  521. hr = spiProvTaskPage->GetPage(TASKPAGE_SCHEDULE, FALSE, &phPage);
  522. if (SUCCEEDED(hr))
  523. {
  524. PROPSHEETHEADER psh;
  525. ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
  526. psh.dwSize = sizeof(PROPSHEETHEADER);
  527. psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
  528. psh.hwndParent = m_hWnd;
  529. psh.hInstance = _Module.GetResourceInstance();
  530. psh.pszCaption = m_strVolume;
  531. psh.phpage = &phPage;
  532. psh.nPages = 1;
  533. int id = PropertySheet(&psh);
  534. //
  535. // BUG#428943 LinanT
  536. // In case this is a new schedule task created at this entry of button click,
  537. // we need to discard it if user cancels the schedule page.
  538. //
  539. if (IDOK != id && bNewSchedule)
  540. {
  541. if (m_pszTaskName)
  542. {
  543. DeleteOneScheduledTimewarpTasks(
  544. m_spiTS,
  545. m_strComputer,
  546. m_pszTaskName
  547. );
  548. //m_spiTS->Delete(m_pszTaskName);
  549. free(m_pszTaskName);
  550. m_pszTaskName = NULL;
  551. }
  552. // reset m_spiTask
  553. m_spiTask.Release();
  554. }
  555. }
  556. }
  557. if (FAILED(hr))
  558. {
  559. DoErrMsgBox(m_hWnd, MB_OK, hr, IDS_SCHEDULEPAGE_ERROR);
  560. if (m_pszTaskName)
  561. {
  562. DeleteOneScheduledTimewarpTasks(
  563. m_spiTS,
  564. m_strComputer,
  565. m_pszTaskName
  566. );
  567. //m_spiTS->Delete(m_pszTaskName);
  568. free(m_pszTaskName);
  569. m_pszTaskName = NULL;
  570. }
  571. // reset m_spiTask
  572. m_spiTask.Release();
  573. }
  574. return;
  575. }
  576. void CSettings::OnSelchangeDiffVolume()
  577. {
  578. CWaitCursor wait;
  579. int nIndex = m_ctrlStorageVolume.GetCurSel();
  580. ASSERT(CB_ERR != nIndex);
  581. CString strDiffVolumeDisplayName;
  582. m_ctrlStorageVolume.GetLBText(nIndex, strDiffVolumeDisplayName);
  583. ULONGLONG llDiffVolumeTotalSpace = 0;
  584. ULONGLONG llDiffVolumeFreeSpace = 0;
  585. HRESULT hr = GetVolumeSpace(
  586. m_spiDiffSnapMgmt,
  587. strDiffVolumeDisplayName,
  588. &llDiffVolumeTotalSpace,
  589. &llDiffVolumeFreeSpace);
  590. if (SUCCEEDED(hr))
  591. {
  592. if (llDiffVolumeTotalSpace >= MINIMUM_DIFF_LIMIT)
  593. {
  594. LONG maxSpinRange = min(0x7FFFFFFF, llDiffVolumeTotalSpace / g_llMB);
  595. maxSpinRange = (maxSpinRange / MINIMUM_DIFF_LIMIT_DELTA_MB) * MINIMUM_DIFF_LIMIT_DELTA_MB;
  596. m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, maxSpinRange);
  597. }
  598. else
  599. m_ctrlSpin.SendMessage(UDM_SETRANGE32, MINIMUM_DIFF_LIMIT_MB, 0x7FFFFFFF);
  600. }
  601. }
  602. void CSettings::OnContextMenu(CWnd* pWnd, CPoint point)
  603. {
  604. if (!pWnd)
  605. return;
  606. ::WinHelp(pWnd->GetSafeHwnd(),
  607. VSSUI_CTX_HELP_FILE,
  608. HELP_CONTEXTMENU,
  609. (DWORD_PTR)(PVOID)aMenuHelpIDsForSettings);
  610. }
  611. BOOL CSettings::OnHelpInfo(HELPINFO* pHelpInfo)
  612. {
  613. if (!pHelpInfo ||
  614. pHelpInfo->iContextType != HELPINFO_WINDOW ||
  615. pHelpInfo->iCtrlId < 0)
  616. return FALSE;
  617. ::WinHelp((HWND)pHelpInfo->hItemHandle,
  618. VSSUI_CTX_HELP_FILE,
  619. HELP_WM_HELP,
  620. (DWORD_PTR)(PVOID)aMenuHelpIDsForSettings);
  621. return TRUE;
  622. }
  623. void CSettings::OnLimits()
  624. {
  625. // TODO: Add your control notification handler code here
  626. BOOL bNoLimits = (BST_CHECKED == IsDlgButtonChecked(IDC_SETTINGS_NOLIMITS));
  627. m_ctrlDiffLimits.EnableWindow(!bNoLimits);
  628. m_ctrlSpin.EnableWindow(!bNoLimits);
  629. }
  630. void CSettings::OnDeltaposSettingsSpin(NMHDR* pNMHDR, LRESULT* pResult)
  631. {
  632. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  633. // Change delta to min-diff-area-size-delta instead of the spin control default which is 1
  634. ASSERT(pNMUpDown);
  635. int pos = pNMUpDown->iPos;
  636. if (pNMUpDown->iDelta == 1)
  637. pNMUpDown->iDelta =
  638. (pos / MINIMUM_DIFF_LIMIT_DELTA_MB + 1) * MINIMUM_DIFF_LIMIT_DELTA_MB - pos;
  639. else if (pNMUpDown->iDelta == -1)
  640. pNMUpDown->iDelta =
  641. (pos - 1) / MINIMUM_DIFF_LIMIT_DELTA_MB * MINIMUM_DIFF_LIMIT_DELTA_MB - pos;
  642. *pResult = 0;
  643. }