Source code of Windows XP (NT5)
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.

2204 lines
66 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: volprop.cpp
  3. Description: Provides implementations for quota property pages.
  4. Revision History:
  5. Date Description Programmer
  6. -------- --------------------------------------------------- ----------
  7. 08/15/96 Initial creation. BrianAu
  8. 08/01/97 Removed IDC_CBX_WARN_THRESHOLD from UI. BrianAu
  9. 11/27/98 Added logging checkboxes back in. BrianAu
  10. */
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "dskquota.h"
  15. #include "volprop.h"
  16. #include "uihelp.h"
  17. #include "registry.h"
  18. #include "guidsp.h"
  19. #include "uiutils.h"
  20. #ifdef POLICY_MMC_SNAPIN
  21. # include "snapin.h"
  22. #endif
  23. //
  24. // Context help IDs.
  25. //
  26. #pragma data_seg(".text", "CODE")
  27. const static DWORD rgVolumePropPageHelpIDs[] =
  28. {
  29. IDC_TRAFFIC_LIGHT, IDH_TRAFFIC_LIGHT,
  30. IDC_TXT_QUOTA_STATUS, IDH_TXT_QUOTA_STATUS,
  31. IDC_TXT_QUOTA_STATUS_LABEL, DWORD(-1),
  32. IDC_CBX_ENABLE_QUOTA, IDH_CBX_ENABLE_QUOTA,
  33. IDC_CBX_DENY_LIMIT, IDH_CBX_DENY_LIMIT,
  34. IDC_RBN_DEF_NOLIMIT, IDH_RBN_DEF_NO_LIMIT,
  35. IDC_RBN_DEF_LIMIT, IDH_RBN_DEF_LIMIT,
  36. IDC_EDIT_DEF_LIMIT, IDH_EDIT_DEF_LIMIT,
  37. IDC_EDIT_DEF_THRESHOLD, IDH_EDIT_DEF_THRESHOLD,
  38. IDC_CMB_DEF_LIMIT, IDH_CMB_DEF_LIMIT,
  39. IDC_CMB_DEF_THRESHOLD, IDH_CMB_DEF_THRESHOLD,
  40. IDC_BTN_DETAILS, IDH_BTN_DETAILS,
  41. IDC_BTN_EVENTLOG, IDH_BTN_EVENTLOG,
  42. IDC_CBX_LOG_OVERWARNING, IDH_CBX_LOG_OVERWARNING,
  43. IDC_CBX_LOG_OVERLIMIT, IDH_CBX_LOG_OVERLIMIT,
  44. IDC_TXT_DEFAULTS, IDH_GRP_DEFAULTS,
  45. IDC_TXT_LOGGING, DWORD(-1),
  46. IDC_TXT_WARN_LEVEL, DWORD(-1),
  47. 0,0
  48. };
  49. #pragma data_seg()
  50. #ifdef POLICY_MMC_SNAPIN
  51. const TCHAR c_szSnapInPrefs[] = TEXT("GPTEditorExtData");
  52. #endif
  53. extern TCHAR c_szWndClassDetailsView[]; // defined in details.cpp
  54. /*
  55. // NOTE: This code has been disabled.
  56. // I've left in case we decide to launch the event viewer from
  57. // the volume prop page again. [brianau - 3/23/98]
  58. //
  59. const TCHAR c_szVerbOpen[] = TEXT("Open");
  60. const TCHAR c_szManagementConsole[] = TEXT("MMC.EXE");
  61. const TCHAR c_szMMCInitFile[] = TEXT("%SystemRoot%\\System32\\EVENTVWR.MSC");
  62. */
  63. #define VPPM_FOCUS_ON_THRESHOLDEDIT (WM_USER + 1)
  64. ///////////////////////////////////////////////////////////////////////////////
  65. /* Function: VolumePropPage::VolumePropPage
  66. Description: Constructor for a volume property page object.
  67. Initializes the members that hold volume quota data.
  68. Arguments: None.
  69. Returns: Nothing.
  70. Revision History:
  71. Date Description Programmer
  72. -------- --------------------------------------------------- ----------
  73. 08/15/96 Initial creation. BrianAu
  74. */
  75. ///////////////////////////////////////////////////////////////////////////////
  76. VolumePropPage::VolumePropPage(VOID)
  77. : m_dwQuotaState(0),
  78. m_dwQuotaLogFlags(0),
  79. m_idStatusUpdateTimer(0),
  80. m_dwLastStatusMsgID(0),
  81. m_cVolumeMaxBytes(NOLIMIT),
  82. m_pxbDefaultLimit(NULL),
  83. m_pxbDefaultThreshold(NULL),
  84. m_llDefaultQuotaThreshold(0),
  85. m_llDefaultQuotaLimit(0),
  86. m_idCtlNextFocus(-1)
  87. {
  88. }
  89. ///////////////////////////////////////////////////////////////////////////////
  90. /* Function: VolumePropPage::~VolumePropPage
  91. Description: Destructor for a volume property page object.
  92. Arguments: None.
  93. Returns: Nothing.
  94. Revision History:
  95. Date Description Programmer
  96. -------- --------------------------------------------------- ----------
  97. 08/15/96 Initial creation. BrianAu
  98. */
  99. ///////////////////////////////////////////////////////////////////////////////
  100. VolumePropPage::~VolumePropPage(
  101. VOID
  102. )
  103. {
  104. delete m_pxbDefaultLimit;
  105. delete m_pxbDefaultThreshold;
  106. }
  107. ///////////////////////////////////////////////////////////////////////////////
  108. /* Function: VolumePropPage::DlgProc
  109. Description: Static method called by windows to process messages for the
  110. property page dialog. Since it's static, we have to save the "this"
  111. pointer in the window's USERDATA.
  112. Arguments: Standard WndProc-type arguments.
  113. Returns: Standard WndProc-type return values.
  114. Revision History:
  115. Date Description Programmer
  116. -------- --------------------------------------------------- ----------
  117. 08/15/96 Initial creation. BrianAu
  118. */
  119. ///////////////////////////////////////////////////////////////////////////////
  120. INT_PTR APIENTRY
  121. VolumePropPage::DlgProc(
  122. HWND hDlg,
  123. UINT message,
  124. WPARAM wParam,
  125. LPARAM lParam
  126. )
  127. {
  128. INT_PTR bResult = FALSE;
  129. //
  130. // Retrieve the "this" pointer from the dialog's userdata.
  131. // It was placed there in OnInitDialog().
  132. //
  133. VolumePropPage *pThis = (VolumePropPage *)GetWindowLongPtr(hDlg, DWLP_USER);
  134. try
  135. {
  136. switch(message)
  137. {
  138. case WM_INITDIALOG:
  139. {
  140. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_INITDIALOG")));
  141. PROPSHEETPAGE *pPage = (PROPSHEETPAGE *)lParam;
  142. pThis = (VolumePropPage *)pPage->lParam;
  143. DBGASSERT((NULL != pThis));
  144. //
  145. // pThis pointer AddRef'd in AddPages().
  146. // Save it in the window's userdata.
  147. //
  148. SetWindowLongPtr(hDlg, DWLP_USER, (INT_PTR)pThis);
  149. bResult = pThis->OnInitDialog(hDlg, wParam, lParam);
  150. break;
  151. }
  152. case WM_SYSCOLORCHANGE:
  153. bResult = pThis->m_TrafficLight.ForwardMessage(message, wParam, lParam);
  154. break;
  155. case WM_NOTIFY:
  156. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_NOTIFY")));
  157. bResult = pThis->OnNotify(hDlg, wParam, lParam);
  158. break;
  159. case WM_COMMAND:
  160. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_COMMAND")));
  161. bResult = pThis->OnCommand(hDlg, wParam, lParam);
  162. break;
  163. case WM_HELP:
  164. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_HELP")));
  165. bResult = pThis->OnHelp(hDlg, wParam, lParam);
  166. break;
  167. case WM_CONTEXTMENU:
  168. bResult = pThis->OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  169. break;
  170. case WM_DESTROY:
  171. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_DESTROY")));
  172. pThis->KillStatusUpdateTimer(hDlg);
  173. //
  174. // Nothing to do.
  175. //
  176. break;
  177. case WM_TIMER:
  178. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_TIMER")));
  179. bResult = pThis->OnTimer(hDlg, wParam, lParam);
  180. break;
  181. case VPPM_FOCUS_ON_THRESHOLDEDIT:
  182. //
  183. // This is sort of a hack because of the way the prop sheet
  184. // code in comctl32 sets focus after a page has returned
  185. // PSNRET_INVALID. It automatically activates the problem
  186. // page and sets focus to the FIRST control in the tab order.
  187. // Since the only failure we generate is from the threshold
  188. // exceeding the limit, I want to return focus to the threshold
  189. // edit control so that the user can directly change the offending
  190. // value. Posting this custom message was the only way I
  191. // could get this to work. [brianau].
  192. //
  193. SetFocus((HWND)lParam);
  194. SendMessage((HWND)lParam, EM_SETSEL, 0, -1);
  195. break;
  196. default:
  197. break;
  198. }
  199. }
  200. catch(CAllocException& me)
  201. {
  202. //
  203. // Announce any out-of-memory errors associated with running the
  204. // volume Quota property page.
  205. //
  206. DiskQuotaMsgBox(GetDesktopWindow(),
  207. IDS_OUTOFMEMORY,
  208. IDS_TITLE_DISK_QUOTA,
  209. MB_ICONERROR | MB_OK);
  210. }
  211. return bResult;
  212. }
  213. ///////////////////////////////////////////////////////////////////////////////
  214. /* Function: VolumePropPage::OnInitDialog
  215. Description: Handler for WM_INITDIALOG.
  216. Arguments:
  217. hDlg - Dialog window handle.
  218. wParam - Handle of control to receive focus if we return FALSE.
  219. lParam - Pointer to PROPSHEETPAGE structure for the property page.
  220. Returns:
  221. TRUE = Tells windows to assign focus to the control in wParam.
  222. Exceptions: OutOfMemory.
  223. Revision History:
  224. Date Description Programmer
  225. -------- --------------------------------------------------- ----------
  226. 08/15/96 Initial creation. BrianAu
  227. 02/10/98 Converted from static to a virtual function to BrianAu
  228. support addition of SnapInVolPropPage class.
  229. */
  230. ///////////////////////////////////////////////////////////////////////////////
  231. INT_PTR
  232. VolumePropPage::OnInitDialog(
  233. HWND hDlg,
  234. WPARAM wParam,
  235. LPARAM lParam
  236. )
  237. {
  238. HRESULT hResult = NO_ERROR;
  239. DWORD dwSectorsPerCluster = 0;
  240. DWORD dwBytesPerSector = 0;
  241. DWORD dwFreeClusters = 0;
  242. DWORD dwTotalClusters = 0;
  243. //
  244. // Load the volume's quota information into member variables.
  245. //
  246. hResult = RefreshCachedVolumeQuotaInfo();
  247. //
  248. // Calculate the volume's size.
  249. // We'll use this to limit user threshold and quota limit entries.
  250. //
  251. if (GetDiskFreeSpace(m_idVolume.ForParsing(),
  252. &dwSectorsPerCluster,
  253. &dwBytesPerSector,
  254. &dwFreeClusters,
  255. &dwTotalClusters))
  256. {
  257. m_cVolumeMaxBytes = (UINT64)dwSectorsPerCluster *
  258. (UINT64)dwBytesPerSector *
  259. (UINT64)dwTotalClusters;
  260. }
  261. //
  262. // Create the XBytes objects to manage the relationship between the
  263. // limit/threshold edit controls and their combo boxes.
  264. //
  265. m_pxbDefaultLimit = new XBytes(hDlg,
  266. IDC_EDIT_DEF_LIMIT,
  267. IDC_CMB_DEF_LIMIT,
  268. m_llDefaultQuotaLimit);
  269. m_pxbDefaultThreshold = new XBytes(hDlg,
  270. IDC_EDIT_DEF_THRESHOLD,
  271. IDC_CMB_DEF_THRESHOLD,
  272. m_llDefaultQuotaThreshold);
  273. m_TrafficLight.Initialize(GetDlgItem(hDlg, IDC_TRAFFIC_LIGHT), IDR_AVI_TRAFFIC);
  274. InitializeControls(hDlg);
  275. return TRUE; // Set focus to default control.
  276. }
  277. ///////////////////////////////////////////////////////////////////////////////
  278. /* Function: VolumePropPage::OnCommand
  279. Description: Handler for WM_COMMAND.
  280. Arguments:
  281. hDlg - Dialog window handle.
  282. wParam - ID of selected control and notification code.
  283. lParam - HWND of selected control.
  284. Returns:
  285. TRUE = Message wasn't handled.
  286. FALSE = Message was handled.
  287. Revision History:
  288. Date Description Programmer
  289. -------- --------------------------------------------------- ----------
  290. 08/15/96 Initial creation. BrianAu
  291. 08/01/97 Removed IDC_CBX_WARN_THRESHOLD from UI. BrianAu
  292. */
  293. ///////////////////////////////////////////////////////////////////////////////
  294. INT_PTR
  295. VolumePropPage::OnCommand(
  296. HWND hDlg,
  297. WPARAM wParam,
  298. LPARAM lParam
  299. )
  300. {
  301. INT_PTR bResult = TRUE;
  302. DWORD dwCtlId = LOWORD(wParam);
  303. HWND hWndCtl = (HWND)lParam;
  304. DWORD dwNotifyCode = HIWORD(wParam);
  305. BOOL bIsChecked = FALSE;
  306. BOOL bEnableApplyBtn = FALSE;
  307. switch(dwCtlId)
  308. {
  309. case IDC_CBX_ENABLE_QUOTA:
  310. {
  311. //
  312. // This is executed when the user checks or unchecks the
  313. // "Enable quota management checkbox.
  314. //
  315. bIsChecked = IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA);
  316. //
  317. // Remember: Limit/Threshold Edit and combo boxes are enabled/disabled
  318. // through XBytes::SetBytes().
  319. //
  320. m_pxbDefaultLimit->SetBytes(m_llDefaultQuotaLimit);
  321. m_pxbDefaultThreshold->SetBytes(m_llDefaultQuotaThreshold);
  322. CheckDlgButton(hDlg, IDC_RBN_DEF_NOLIMIT, NOLIMIT == m_pxbDefaultLimit->GetBytes());
  323. CheckDlgButton(hDlg, IDC_RBN_DEF_LIMIT, BST_CHECKED != IsDlgButtonChecked(hDlg, IDC_RBN_DEF_NOLIMIT));
  324. CheckDlgButton(hDlg, IDC_CBX_DENY_LIMIT, bIsChecked && DISKQUOTA_IS_ENFORCED(m_dwQuotaState));
  325. CheckDlgButton(hDlg,
  326. IDC_CBX_LOG_OVERWARNING,
  327. bIsChecked &&
  328. DISKQUOTA_IS_LOGGED_USER_THRESHOLD(m_dwQuotaLogFlags));
  329. CheckDlgButton(hDlg,
  330. IDC_CBX_LOG_OVERLIMIT,
  331. bIsChecked &&
  332. DISKQUOTA_IS_LOGGED_USER_LIMIT(m_dwQuotaLogFlags));
  333. EnableControls(hDlg);
  334. bEnableApplyBtn = TRUE;
  335. bResult = FALSE;
  336. break;
  337. }
  338. case IDC_CBX_DENY_LIMIT:
  339. bResult = FALSE;
  340. bEnableApplyBtn = TRUE;
  341. break;
  342. case IDC_RBN_DEF_NOLIMIT:
  343. DBGASSERT((IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA)));
  344. if (m_pxbDefaultLimit->IsEnabled())
  345. {
  346. m_pxbDefaultThreshold->SetBytes(NOLIMIT);
  347. m_pxbDefaultLimit->SetBytes(NOLIMIT);
  348. bEnableApplyBtn = TRUE;
  349. }
  350. bResult = FALSE;
  351. break;
  352. case IDC_RBN_DEF_LIMIT:
  353. //
  354. // If the original threshold was -1 (no limit), set to 0.
  355. // Otherwise, set to the original value.
  356. //
  357. DBGASSERT((IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA)));
  358. if (!m_pxbDefaultLimit->IsEnabled())
  359. {
  360. m_pxbDefaultLimit->SetBytes(NOLIMIT == m_llDefaultQuotaLimit ?
  361. 0 : m_llDefaultQuotaLimit);
  362. m_pxbDefaultThreshold->SetBytes(NOLIMIT == m_llDefaultQuotaThreshold ?
  363. 0 : m_llDefaultQuotaThreshold);
  364. EnableControls(hDlg);
  365. bEnableApplyBtn = TRUE;
  366. }
  367. bResult = FALSE;
  368. break;
  369. case IDC_EDIT_DEF_LIMIT:
  370. case IDC_EDIT_DEF_THRESHOLD:
  371. switch(dwNotifyCode)
  372. {
  373. case EN_UPDATE:
  374. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc; WM_COMMAND, EN_CHANGE")));
  375. bResult = OnEditNotifyUpdate(hDlg, wParam, lParam);
  376. bEnableApplyBtn = TRUE;
  377. break;
  378. case EN_KILLFOCUS:
  379. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc; WM_COMMAND, EN_KILLFOCUS")));
  380. bResult = OnEditNotifyKillFocus(hDlg, wParam, lParam);
  381. break;
  382. case EN_SETFOCUS:
  383. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc; WM_COMMAND, EN_SETFOCUS")));
  384. bResult = OnEditNotifySetFocus(hDlg, wParam, lParam);
  385. break;
  386. default:
  387. break;
  388. }
  389. break;
  390. case IDC_CMB_DEF_LIMIT:
  391. case IDC_CMB_DEF_THRESHOLD:
  392. switch(dwNotifyCode)
  393. {
  394. case CBN_SELCHANGE:
  395. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_COMMAND, CBN_CHANGE")));
  396. bResult = OnComboNotifySelChange(hDlg, wParam, lParam);
  397. bEnableApplyBtn = TRUE;
  398. break;
  399. default:
  400. break;
  401. }
  402. break;
  403. case IDC_BTN_DETAILS:
  404. bResult = OnButtonDetails(hDlg, wParam, lParam);
  405. break;
  406. case IDC_CBX_LOG_OVERLIMIT:
  407. case IDC_CBX_LOG_OVERWARNING:
  408. bEnableApplyBtn = TRUE;
  409. break;
  410. /*
  411. //
  412. // NOTE: This code disabled until we decide to launch the event viewer
  413. // from the volume prop page. Probably won't happen because we
  414. // can't define a quota-specific error type for NT events.
  415. // If we can't filter an event viewer list on quota-only events,
  416. // there's not much use in getting to the event viewer from here.
  417. // [brianau - 3/23/98]
  418. //
  419. case IDC_BTN_EVENTLOG:
  420. bResult = OnButtonEventLog(hDlg, wParam, lParam);
  421. break;
  422. */
  423. default:
  424. break;
  425. }
  426. if (bEnableApplyBtn)
  427. PropSheet_Changed(GetParent(hDlg), hDlg);
  428. return bResult;
  429. }
  430. ///////////////////////////////////////////////////////////////////////////////
  431. /* Function: VolumePropPage::OnNotify
  432. Description: Handler for WM_NOTIFY.
  433. Arguments:
  434. hDlg - Dialog window handle.
  435. wParam - ID of selected control and notification code.
  436. lParam - HWND of selected control.
  437. Returns:
  438. TRUE = Message wasn't handled.
  439. FALSE = Message was handled.
  440. Revision History:
  441. Date Description Programmer
  442. -------- --------------------------------------------------- ----------
  443. 08/15/96 Initial creation. BrianAu
  444. */
  445. ///////////////////////////////////////////////////////////////////////////////
  446. INT_PTR
  447. VolumePropPage::OnNotify(
  448. HWND hDlg,
  449. WPARAM wParam,
  450. LPARAM lParam
  451. )
  452. {
  453. DBGTRACE((DM_VPROP, DL_MID, TEXT("VolumePropPage::OnNotify")));
  454. INT_PTR bResult = TRUE;
  455. switch(((NMHDR *)lParam)->code)
  456. {
  457. case PSN_SETACTIVE:
  458. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_NOTIFY, PSN_SETACTIVE")));
  459. bResult = OnSheetNotifySetActive(hDlg, wParam, lParam);
  460. break;
  461. case PSN_APPLY:
  462. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_NOTIFY, PSN_APPLY")));
  463. bResult = OnSheetNotifyApply(hDlg, wParam, lParam);
  464. break;
  465. case PSN_KILLACTIVE:
  466. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_NOTIFY, PSN_KILLACTIVE")));
  467. bResult = OnSheetNotifyKillActive(hDlg, wParam, lParam);
  468. break;
  469. case PSN_RESET:
  470. DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_NOTIFY, PSN_RESET")));
  471. bResult = OnSheetNotifyReset(hDlg, wParam, lParam);
  472. break;
  473. default:
  474. break;
  475. }
  476. return bResult;
  477. }
  478. ///////////////////////////////////////////////////////////////////////////////
  479. /* Function: VolumePropPage::OnSheetNotifySetActive
  480. Description: Handler for WM_NOTIFY - PSN_SETACTIVE.
  481. Arguments:
  482. hDlg - Dialog window handle.
  483. wParam - ID of control.
  484. lParam - Address of NMHDR structure.
  485. Returns:
  486. FALSE = Accept activation.
  487. Revision History:
  488. Date Description Programmer
  489. -------- --------------------------------------------------- ----------
  490. 08/15/96 Initial creation. BrianAu
  491. */
  492. ///////////////////////////////////////////////////////////////////////////////
  493. INT_PTR
  494. VolumePropPage::OnSheetNotifySetActive(
  495. HWND hDlg,
  496. WPARAM wParam,
  497. LPARAM lParam
  498. )
  499. {
  500. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("VolumePropPage::OnSheetNotifySetActive")));
  501. //
  502. // Update the status text and set the status update timer.
  503. //
  504. UpdateStatusIndicators(hDlg);
  505. SetStatusUpdateTimer(hDlg);
  506. if (IDC_EDIT_DEF_THRESHOLD == m_idCtlNextFocus)
  507. {
  508. //
  509. // Focus is being set as a result of an invalid entry
  510. // in the warning level field. Force input focus to the
  511. // field and select the entire contents. User can then just
  512. // enter a new value.
  513. //
  514. PostMessage(hDlg,
  515. VPPM_FOCUS_ON_THRESHOLDEDIT,
  516. 0,
  517. (LPARAM)GetDlgItem(hDlg, IDC_EDIT_DEF_THRESHOLD));
  518. m_idCtlNextFocus = -1;
  519. }
  520. return 0;
  521. }
  522. ///////////////////////////////////////////////////////////////////////////////
  523. /* Function: VolumePropPage::OnSheetNotifyApply
  524. Description: Handler for WM_NOTIFY - PSN_APPLY.
  525. Arguments:
  526. hDlg - Dialog window handle.
  527. wParam - ID of control.
  528. lParam - Address of NMHDR structure.
  529. Returns:
  530. TRUE = PSN return value set using SetWindowLong.
  531. Revision History:
  532. Date Description Programmer
  533. -------- --------------------------------------------------- ----------
  534. 08/15/96 Initial creation. BrianAu
  535. */
  536. ///////////////////////////////////////////////////////////////////////////////
  537. INT_PTR
  538. VolumePropPage::OnSheetNotifyApply(
  539. HWND hDlg,
  540. WPARAM wParam,
  541. LPARAM lParam
  542. )
  543. {
  544. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("VolumePropPage::OnSheetNotifyApply")));
  545. HRESULT hResult = NO_ERROR;
  546. LONG dwPSNReturn = PSNRET_NOERROR;
  547. INT idMsg = -1;
  548. if (!IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA) &&
  549. !DISKQUOTA_IS_DISABLED(m_dwQuotaState))
  550. {
  551. idMsg = IDS_DISABLE_QUOTA_WARNING;
  552. }
  553. else if (IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA) &&
  554. DISKQUOTA_IS_DISABLED(m_dwQuotaState))
  555. {
  556. idMsg = IDS_ENABLE_QUOTA_WARNING;
  557. }
  558. if (-1 != idMsg)
  559. {
  560. //
  561. // User wants to disable or enable quotas.
  562. // Warn about what this means and let them know that
  563. // re-activation of quotas requires a quota file rebuild.
  564. //
  565. if (IDCANCEL == DiskQuotaMsgBox(hDlg,
  566. idMsg,
  567. IDS_TITLE_DISK_QUOTA,
  568. MB_ICONWARNING | MB_OKCANCEL))
  569. {
  570. //
  571. // User decided to not continue the action.
  572. // Restore the checkbox to it's previous setting and abort the
  573. // settings change.
  574. // Sending the message to our DlgProc resets the dependent controls
  575. // to their proper states.
  576. //
  577. CheckDlgButton(hDlg,
  578. IDC_CBX_ENABLE_QUOTA,
  579. !IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA));
  580. SendMessage(hDlg,
  581. WM_COMMAND,
  582. (WPARAM)MAKELONG((WORD)IDC_CBX_ENABLE_QUOTA, (WORD)0),
  583. (LPARAM)GetDlgItem(hDlg, IDC_CBX_ENABLE_QUOTA));
  584. dwPSNReturn = PSNRET_INVALID;
  585. }
  586. }
  587. if (PSNRET_NOERROR == dwPSNReturn)
  588. {
  589. //
  590. // We need to do this because if you activate the apply button
  591. // with Alt-A we receive PSN_APPLY before EN_KILLFOCUS.
  592. //
  593. m_pxbDefaultThreshold->OnEditKillFocus((LPARAM)GetDlgItem(hDlg, IDC_EDIT_DEF_THRESHOLD));
  594. m_pxbDefaultLimit->OnEditKillFocus((LPARAM)GetDlgItem(hDlg, IDC_EDIT_DEF_LIMIT));
  595. //
  596. // Ensure warning threshold is not above limit.
  597. //
  598. INT64 iThreshold = m_pxbDefaultThreshold->GetBytes();
  599. INT64 iLimit = m_pxbDefaultLimit->GetBytes();
  600. if (iThreshold > iLimit)
  601. {
  602. TCHAR szLimit[40], szThreshold[40];
  603. XBytes::FormatByteCountForDisplay(iLimit, szLimit, ARRAYSIZE(szLimit));
  604. XBytes::FormatByteCountForDisplay(iThreshold, szThreshold, ARRAYSIZE(szThreshold));
  605. CString s(g_hInstDll, IDS_FMT_ERR_WARNOVERLIMIT, szThreshold, szLimit, szLimit);
  606. switch(DiskQuotaMsgBox(hDlg, s, IDS_TITLE_DISK_QUOTA, MB_ICONWARNING | MB_YESNO))
  607. {
  608. case IDYES:
  609. m_pxbDefaultThreshold->SetBytes(iLimit);
  610. break;
  611. case IDNO:
  612. m_idCtlNextFocus = IDC_EDIT_DEF_THRESHOLD;
  613. dwPSNReturn = PSNRET_INVALID;
  614. break;
  615. }
  616. }
  617. }
  618. if (PSNRET_NOERROR == dwPSNReturn)
  619. {
  620. hResult = ApplySettings(hDlg);
  621. if (FAILED(hResult))
  622. {
  623. DiskQuotaMsgBox(hDlg,
  624. IDS_APPLY_SETTINGS_ERROR,
  625. IDS_TITLE_DISK_QUOTA,
  626. MB_ICONERROR | MB_OK);
  627. dwPSNReturn = PSNRET_INVALID;
  628. InitializeControls(hDlg);
  629. }
  630. }
  631. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, dwPSNReturn);
  632. return TRUE;
  633. }
  634. ///////////////////////////////////////////////////////////////////////////////
  635. /* Function: VolumePropPage::OnSheetNotifyKillActive
  636. Description: Handler for WM_NOTIFY - PSN_KILLACTIVE.
  637. Arguments:
  638. hDlg - Dialog window handle.
  639. wParam - ID of control.
  640. lParam - Address of NMHDR structure.
  641. Returns:
  642. TRUE = Invalid data entered. Don't kill page.
  643. FALSE = All data is valid. Ok to kill page.
  644. Revision History:
  645. Date Description Programmer
  646. -------- --------------------------------------------------- ----------
  647. 08/15/96 Initial creation. BrianAu
  648. */
  649. ///////////////////////////////////////////////////////////////////////////////
  650. INT_PTR
  651. VolumePropPage::OnSheetNotifyKillActive(
  652. HWND hDlg,
  653. WPARAM wParam,
  654. LPARAM lParam
  655. )
  656. {
  657. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("VolumePropPage::OnSheetNotifyKillActive")));
  658. BOOL bAllDataIsValid = TRUE;
  659. if (bAllDataIsValid)
  660. {
  661. KillStatusUpdateTimer(hDlg);
  662. }
  663. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, !bAllDataIsValid);
  664. //
  665. // Must release quota controller whenever the sheet is deactivated.
  666. // Without this we were holding open a handle to the volume. This prevented
  667. // the disk check utility ("Tools" page) from accessing the volume.
  668. // Whenever we need an IDiskQuotaControl ptr we call GetQuotaController which
  669. // will create a new controller if necessary.
  670. //
  671. if (NULL != m_pQuotaControl)
  672. {
  673. m_pQuotaControl->Release();
  674. m_pQuotaControl = NULL;
  675. }
  676. return TRUE;
  677. }
  678. ///////////////////////////////////////////////////////////////////////////////
  679. /* Function: VolumePropPage::OnSheetNotifyReset
  680. Description: Handler for WM_NOTIFY - PSN_RESET.
  681. Arguments:
  682. hDlg - Dialog window handle.
  683. wParam - ID of control.
  684. lParam - Address of NMHDR structure.
  685. Returns:
  686. No return value.
  687. Revision History:
  688. Date Description Programmer
  689. -------- --------------------------------------------------- ----------
  690. 08/15/96 Initial creation. BrianAu
  691. */
  692. ///////////////////////////////////////////////////////////////////////////////
  693. INT_PTR
  694. VolumePropPage::OnSheetNotifyReset(
  695. HWND hDlg,
  696. WPARAM wParam,
  697. LPARAM lParam
  698. )
  699. {
  700. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("VolumePropPage::OnSheetNotifyReset")));
  701. HRESULT hResult = NO_ERROR;
  702. //
  703. // Nothing to do right now.
  704. //
  705. return FALSE;
  706. }
  707. ///////////////////////////////////////////////////////////////////////////////
  708. /* Function: VolumePropPage::OnHelp
  709. Description: Handler for WM_HELP. Displays context sensitive help.
  710. Arguments:
  711. lParam - Pointer to a HELPINFO structure.
  712. Returns: TRUE;
  713. Revision History:
  714. Date Description Programmer
  715. -------- --------------------------------------------------- ----------
  716. 08/17/96 Initial creation. BrianAu
  717. */
  718. ///////////////////////////////////////////////////////////////////////////////
  719. INT_PTR
  720. VolumePropPage::OnHelp(
  721. HWND hDlg,
  722. WPARAM wParam,
  723. LPARAM lParam
  724. )
  725. {
  726. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, STR_DSKQUOUI_HELPFILE,
  727. HELP_WM_HELP, (DWORD_PTR)(LPTSTR) rgVolumePropPageHelpIDs);
  728. return TRUE;
  729. }
  730. INT_PTR
  731. VolumePropPage::OnContextMenu(
  732. HWND hwndItem,
  733. int xPos,
  734. int yPos
  735. )
  736. {
  737. int idCtl = GetDlgCtrlID(hwndItem);
  738. WinHelp(hwndItem,
  739. UseWindowsHelp(idCtl) ? NULL : STR_DSKQUOUI_HELPFILE,
  740. HELP_CONTEXTMENU,
  741. (DWORD_PTR)((LPTSTR)rgVolumePropPageHelpIDs));
  742. return FALSE;
  743. }
  744. ///////////////////////////////////////////////////////////////////////////////
  745. /* Function: VolumePropPage::OnTimer
  746. Description: Handler for WM_TIMER. Updates the quota status text and
  747. traffic light.
  748. Arguments:
  749. wParam - Timer ID.
  750. Returns: FALSE (0);
  751. Revision History:
  752. Date Description Programmer
  753. -------- --------------------------------------------------- ----------
  754. 08/17/96 Initial creation. BrianAu
  755. */
  756. ///////////////////////////////////////////////////////////////////////////////
  757. INT_PTR
  758. VolumePropPage::OnTimer(
  759. HWND hDlg,
  760. WPARAM wParam,
  761. LPARAM lParam
  762. )
  763. {
  764. if (wParam == m_idStatusUpdateTimer)
  765. {
  766. UpdateStatusIndicators(hDlg);
  767. }
  768. return FALSE;
  769. }
  770. ///////////////////////////////////////////////////////////////////////////////
  771. /* Function: VolumePropPage::OnEditNotifyUpdate
  772. Description: Handler for WM_COMMAND, EN_UPDATE.
  773. Called whenever a character is entered in an edit control.
  774. Arguments:
  775. Returns: FALSE;
  776. Revision History:
  777. Date Description Programmer
  778. -------- --------------------------------------------------- ----------
  779. 08/17/96 Initial creation. BrianAu
  780. */
  781. ///////////////////////////////////////////////////////////////////////////////
  782. INT_PTR
  783. VolumePropPage::OnEditNotifyUpdate(
  784. HWND hDlg,
  785. WPARAM wParam,
  786. LPARAM lParam
  787. )
  788. {
  789. XBytes *rgpxb[2] = { m_pxbDefaultLimit, m_pxbDefaultThreshold };
  790. const int iLIMIT = 0;
  791. const int iTHRESHOLD = 1;
  792. int iCurrent = iLIMIT;
  793. if (IDC_EDIT_DEF_THRESHOLD == LOWORD(wParam))
  794. iCurrent = iTHRESHOLD;
  795. if (NULL != rgpxb[iCurrent])
  796. rgpxb[iCurrent]->OnEditNotifyUpdate(lParam);
  797. return FALSE;
  798. }
  799. ///////////////////////////////////////////////////////////////////////////////
  800. /* Function: VolumePropPage::OnEditNotifyKillFocus
  801. Description: Handler for WM_COMMAND, EN_KILLFOCUS.
  802. Called whenever focus leaves an edit control.
  803. Validates the value in the edit control and adjusts it if necessary.
  804. Arguments:
  805. Returns: FALSE;
  806. Revision History:
  807. Date Description Programmer
  808. -------- --------------------------------------------------- ----------
  809. 08/17/96 Initial creation. BrianAu
  810. 11/12/98 Added code to call XBytes::OnEditKillFocus. BrianAu
  811. */
  812. ///////////////////////////////////////////////////////////////////////////////
  813. INT_PTR
  814. VolumePropPage::OnEditNotifyKillFocus(
  815. HWND hDlg,
  816. WPARAM wParam,
  817. LPARAM lParam
  818. )
  819. {
  820. XBytes *rgpxb[2] = { m_pxbDefaultLimit, m_pxbDefaultThreshold };
  821. const int iLIMIT = 0;
  822. const int iTHRESHOLD = 1;
  823. int iCurrent = iLIMIT;
  824. if (IDC_EDIT_DEF_THRESHOLD == LOWORD(wParam))
  825. iCurrent = iTHRESHOLD;
  826. if (NULL != rgpxb[iCurrent])
  827. rgpxb[iCurrent]->OnEditKillFocus(lParam);
  828. return FALSE;
  829. }
  830. INT_PTR
  831. VolumePropPage::OnEditNotifySetFocus(
  832. HWND hDlg,
  833. WPARAM wParam,
  834. LPARAM lParam
  835. )
  836. {
  837. //
  838. // Nothing to do.
  839. // FEATURE: Delete this method?
  840. //
  841. return FALSE;
  842. }
  843. ///////////////////////////////////////////////////////////////////////////////
  844. /* Function: VolumePropPage::OnComboNotifySelChange
  845. Description: Handler for WM_COMMAND, CBN_SELCHANGE.
  846. Called whenever the user selects the combo box.
  847. Arguments: Std DlgProc args.
  848. Returns: FALSE;
  849. Revision History:
  850. Date Description Programmer
  851. -------- --------------------------------------------------- ----------
  852. 08/17/96 Initial creation. BrianAu
  853. */
  854. ///////////////////////////////////////////////////////////////////////////////
  855. INT_PTR
  856. VolumePropPage::OnComboNotifySelChange(
  857. HWND hDlg,
  858. WPARAM wParam,
  859. LPARAM lParam
  860. )
  861. {
  862. XBytes *rgpxb[2] = { m_pxbDefaultLimit, m_pxbDefaultThreshold };
  863. const int iLIMIT = 0;
  864. const int iTHRESHOLD = 1;
  865. int iCurrent = iLIMIT;
  866. if (IDC_CMB_DEF_THRESHOLD == LOWORD(wParam))
  867. iCurrent = iTHRESHOLD;
  868. if (NULL != rgpxb[iCurrent])
  869. rgpxb[iCurrent]->OnComboNotifySelChange(lParam);
  870. return FALSE;
  871. }
  872. ///////////////////////////////////////////////////////////////////////////////
  873. /* Function: VolumePropPage::OnButtonDetails
  874. Description: Called when the user selects the "Details" button.
  875. If a details view is already active for this prop page, it is brought
  876. to the foreground. If no details view is already active, a new one
  877. is created.
  878. Arguments: Standard DlgProc arguments.
  879. Returns:
  880. Exceptions: OutOfMemory.
  881. Revision History:
  882. Date Description Programmer
  883. -------- --------------------------------------------------- ----------
  884. 08/15/96 Initial creation. BrianAu
  885. */
  886. ///////////////////////////////////////////////////////////////////////////////
  887. INT_PTR
  888. VolumePropPage::OnButtonDetails(
  889. HWND hDlg,
  890. WPARAM wParam,
  891. LPARAM lParam
  892. )
  893. {
  894. if (!ActivateExistingDetailsView())
  895. {
  896. //
  897. // This property page doesn't have an active details view.
  898. // Create one. Note: If something fails in the details view
  899. // creation, it isn't displayed. The DetailsView code is
  900. // responsible for reporting any errors to the user.
  901. //
  902. // NOTE: The VolumePropPage object never calls "delete"
  903. // on the pDetailsView pointer. The details view
  904. // object must live on it's own (modeless) after it is created.
  905. // If the VolumePropPage object (this object) is still alive
  906. // when the details view object is destroyed, it will receive a
  907. // WM_DETAILS_VIEW_DESTROYED message from the view object. That's
  908. // why we pass the hDlg in this constructor. When this message
  909. // is received, we set m_pDetailsView to NULL so that OnButtonDetails
  910. // will know to create a new view object.
  911. //
  912. DetailsView *pDetailsView = new DetailsView;
  913. if (!pDetailsView->Initialize(m_idVolume))
  914. {
  915. //
  916. // Something failed. Either out of memory or the view's thread
  917. // couldn't start. Either way, the view won't run.
  918. // Need to call delete to clean up any partially-completed initialization.
  919. //
  920. delete pDetailsView;
  921. }
  922. }
  923. return FALSE;
  924. }
  925. ///////////////////////////////////////////////////////////////////////////////
  926. /* Function: VolumePropPage::OnButtonEventLog
  927. Description: Called when the user selects the "Event Log" button.
  928. Invokes the NT Event Viewer application.
  929. Arguments: Standard DlgProc arguments.
  930. Returns:
  931. Exceptions: OutOfMemory.
  932. Revision History:
  933. Date Description Programmer
  934. -------- --------------------------------------------------- ----------
  935. 10/14/96 Initial creation. BrianAu
  936. */
  937. ///////////////////////////////////////////////////////////////////////////////
  938. #ifdef __NEVER__
  939. //
  940. // NOTE: This code has been disabled. I just left it in case we ever
  941. // decide to launch the event viewer from the volume prop page again.
  942. // [brianan - 3/23/98]
  943. //
  944. /*
  945. INT_PTR
  946. VolumePropPage::OnButtonEventLog(
  947. HWND hDlg,
  948. WPARAM wParam,
  949. LPARAM lParam
  950. )
  951. {
  952. //
  953. // Expand the %SystemRoot% env var in the path to the MMC
  954. // initialization file (Event viewer).
  955. //
  956. CString strMMCInitFile(c_szMMCInitFile);
  957. strMMCInitFile.ExpandEnvironmentStrings();
  958. HINSTANCE SEhInstance = ShellExecute(hDlg,
  959. c_szVerbOpen,
  960. c_szManagementConsole,
  961. strMMCInitFile,
  962. NULL,
  963. SW_SHOWNORMAL);
  964. if ((DWORD)SEhInstance <= 32)
  965. {
  966. //
  967. // Something failed.
  968. //
  969. INT iMsg = 0;
  970. switch((DWORD)SEhInstance)
  971. {
  972. case 0:
  973. throw CAllocException();
  974. break;
  975. case ERROR_FILE_NOT_FOUND:
  976. iMsg = IDS_ERROR_FILE_NOT_FOUND;
  977. break;
  978. case ERROR_BAD_FORMAT:
  979. iMsg = IDS_ERROR_FILE_CORRUPT;
  980. break;
  981. case SE_ERR_DDEBUSY:
  982. case SE_ERR_DDEFAIL:
  983. case SE_ERR_DDETIMEOUT:
  984. iMsg = IDS_ERROR_DDE_EXECUTE;
  985. break;
  986. default:
  987. //
  988. // The rest of the ShellExecute errors shouldn't happen
  989. // in this situation.
  990. //
  991. break;
  992. }
  993. if (0 != iMsg)
  994. {
  995. //
  996. // Display error message.
  997. // Note that this assumes error string resources have a %1 embedded
  998. // for displaying the filename. If they don't, the following
  999. // logic will need to be changed.
  1000. //
  1001. CString strMsg(g_hInstDll, iMsg, c_szManagementConsole);
  1002. DiskQuotaMsgBox(GetDesktopWindow(),
  1003. strMsg,
  1004. IDS_TITLE_DISK_QUOTA,
  1005. MB_ICONERROR | MB_OK);
  1006. }
  1007. }
  1008. return 0;
  1009. }
  1010. */
  1011. #endif // __NEVER__
  1012. ///////////////////////////////////////////////////////////////////////////////
  1013. /* Function: VolumePropPage::ActivateExistingDetailsView
  1014. Description: Called by OnButtonDetails to see if there's already a details
  1015. view active for this volume. If there is, open it.
  1016. Arguments: None.
  1017. Returns:
  1018. TRUE = Existing details view was found and promoted to the foreground.
  1019. FALSE = Either no existing view was found or an existing one could
  1020. not be promoted to the foreground.
  1021. Exceptions: OutOfMemory.
  1022. Revision History:
  1023. Date Description Programmer
  1024. -------- --------------------------------------------------- ----------
  1025. 02/25/97 Initial creation. BrianAu
  1026. */
  1027. ///////////////////////////////////////////////////////////////////////////////
  1028. BOOL
  1029. VolumePropPage::ActivateExistingDetailsView(
  1030. VOID
  1031. ) const
  1032. {
  1033. BOOL bResult = FALSE;
  1034. CString strVolDisplayName;
  1035. DetailsView::CreateVolumeDisplayName(m_idVolume, &strVolDisplayName);
  1036. CString strDetailsViewTitle(g_hInstDll, IDS_TITLE_MAINWINDOW, (LPCTSTR)strVolDisplayName);
  1037. HWND hwndDetailsView = FindWindow(c_szWndClassDetailsView,
  1038. strDetailsViewTitle);
  1039. if (NULL != hwndDetailsView)
  1040. {
  1041. //
  1042. // Restore the details view and bring it to the front.
  1043. //
  1044. ShowWindow(hwndDetailsView, SW_RESTORE);
  1045. bResult = SetForegroundWindow(hwndDetailsView);
  1046. }
  1047. return bResult;
  1048. }
  1049. ///////////////////////////////////////////////////////////////////////////////
  1050. /* Function: VolumePropPage::ApplySettings
  1051. Description: Applies the current settings to the volume if they have
  1052. changed from the original settings.
  1053. Arguments:
  1054. hDlg - Dialog window handle.
  1055. Returns:
  1056. NO_ERROR - Success.
  1057. E_INVALIDARG - One of the settings was invalid.
  1058. ERROR_ACCESS_DENIED (hr) - No WRITE access to quota device.
  1059. E_FAIL - Any other error.
  1060. Revision History:
  1061. Date Description Programmer
  1062. -------- --------------------------------------------------- ----------
  1063. 08/15/96 Initial creation. BrianAu
  1064. */
  1065. ///////////////////////////////////////////////////////////////////////////////
  1066. HRESULT
  1067. VolumePropPage::ApplySettings(
  1068. HWND hDlg
  1069. )
  1070. {
  1071. HRESULT hResult = NO_ERROR;
  1072. DWORD dwStateSetting = 0;
  1073. DWORD dwLogFlagSettings = m_dwQuotaLogFlags;
  1074. BOOL bTranslated = FALSE;
  1075. LONGLONG llThreshold;
  1076. LONGLONG llLimit;
  1077. IDiskQuotaControl *pqc;
  1078. hResult = GetQuotaController(&pqc);
  1079. if (SUCCEEDED(hResult))
  1080. {
  1081. //
  1082. // Set quota state if changed.
  1083. //
  1084. QuotaStateFromControls(hDlg, &dwStateSetting);
  1085. if (dwStateSetting != (m_dwQuotaState & DISKQUOTA_STATE_MASK))
  1086. {
  1087. hResult = pqc->SetQuotaState(dwStateSetting);
  1088. if (FAILED(hResult))
  1089. goto apply_failed;
  1090. m_dwQuotaState = dwStateSetting;
  1091. }
  1092. //
  1093. // Set quota log flags if changed.
  1094. //
  1095. LogFlagsFromControls(hDlg, &dwLogFlagSettings);
  1096. if (dwLogFlagSettings != m_dwQuotaLogFlags)
  1097. {
  1098. hResult = pqc->SetQuotaLogFlags(dwLogFlagSettings);
  1099. if (FAILED(hResult))
  1100. goto apply_failed;
  1101. m_dwQuotaLogFlags = dwLogFlagSettings;
  1102. }
  1103. //
  1104. // Get current default quota threshold and limit values.
  1105. //
  1106. if (IsDlgButtonChecked(hDlg, IDC_RBN_DEF_NOLIMIT))
  1107. {
  1108. llThreshold = NOLIMIT;
  1109. llLimit = NOLIMIT;
  1110. }
  1111. else
  1112. {
  1113. llThreshold = m_pxbDefaultThreshold->GetBytes();
  1114. llLimit = m_pxbDefaultLimit->GetBytes();
  1115. }
  1116. //
  1117. // Set default quota threshold if changed.
  1118. //
  1119. if (llThreshold != m_llDefaultQuotaThreshold)
  1120. {
  1121. hResult = pqc->SetDefaultQuotaThreshold(llThreshold);
  1122. if (FAILED(hResult))
  1123. goto apply_failed;
  1124. m_llDefaultQuotaThreshold = llThreshold;
  1125. }
  1126. //
  1127. // Set default quota limit if changed.
  1128. //
  1129. if (llLimit != m_llDefaultQuotaLimit)
  1130. {
  1131. hResult = pqc->SetDefaultQuotaLimit(llLimit);
  1132. if (FAILED(hResult))
  1133. goto apply_failed;
  1134. m_llDefaultQuotaLimit = llLimit;
  1135. }
  1136. apply_failed:
  1137. pqc->Release();
  1138. }
  1139. return hResult;
  1140. }
  1141. ///////////////////////////////////////////////////////////////////////////////
  1142. /* Function: VolumePropPage::RefreshCachedVolumeInfo
  1143. Description: Reads the volume's quota information and stores it in
  1144. member variables.
  1145. Arguments: None.
  1146. Returns:
  1147. NO_ERROR - Success.
  1148. ERROR_ACCESS_DENIED (hr) - No READ access to quota device.
  1149. E_FAIL - Any other error.
  1150. Revision History:
  1151. Date Description Programmer
  1152. -------- --------------------------------------------------- ----------
  1153. 08/15/96 Initial creation. BrianAu
  1154. */
  1155. ///////////////////////////////////////////////////////////////////////////////
  1156. HRESULT
  1157. VolumePropPage::RefreshCachedVolumeQuotaInfo(
  1158. VOID
  1159. )
  1160. {
  1161. HRESULT hResult = NO_ERROR;
  1162. IDiskQuotaControl *pqc;
  1163. hResult = GetQuotaController(&pqc);
  1164. if (SUCCEEDED(hResult))
  1165. {
  1166. //
  1167. // Read quota state.
  1168. //
  1169. hResult = pqc->GetQuotaState(&m_dwQuotaState);
  1170. if (FAILED(hResult))
  1171. goto refresh_vol_info_failed;
  1172. //
  1173. // Read quota log flags.
  1174. //
  1175. hResult = pqc->GetQuotaLogFlags(&m_dwQuotaLogFlags);
  1176. if (FAILED(hResult))
  1177. goto refresh_vol_info_failed;
  1178. //
  1179. // Read default quota threshold.
  1180. //
  1181. hResult = pqc->GetDefaultQuotaThreshold(&m_llDefaultQuotaThreshold);
  1182. if (FAILED(hResult))
  1183. goto refresh_vol_info_failed;
  1184. //
  1185. // Read default quota limit.
  1186. //
  1187. hResult = pqc->GetDefaultQuotaLimit(&m_llDefaultQuotaLimit);
  1188. refresh_vol_info_failed:
  1189. pqc->Release();
  1190. }
  1191. return hResult;
  1192. }
  1193. //
  1194. // Determine if a given disk quota policy value is set.
  1195. //
  1196. bool
  1197. VolumePropPage::SetByPolicy(
  1198. LPCTSTR pszPolicyValue
  1199. )
  1200. {
  1201. DWORD dwData;
  1202. DWORD dwType;
  1203. DWORD cbData = sizeof(dwData);
  1204. return (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE,
  1205. REGSTR_KEY_POLICYDATA,
  1206. pszPolicyValue,
  1207. &dwType,
  1208. &dwData,
  1209. &cbData));
  1210. }
  1211. HRESULT
  1212. VolumePropPage::EnableControls(
  1213. HWND hwndDlg
  1214. )
  1215. {
  1216. BOOL bQuotaEnabled = (BST_CHECKED == IsDlgButtonChecked(hwndDlg, IDC_CBX_ENABLE_QUOTA));
  1217. BOOL bEnable;
  1218. //
  1219. // "Enable quota management" checkbox.
  1220. //
  1221. // Policy Quota Enabled Ctl Enabled
  1222. // 0 0 1
  1223. // 0 1 1
  1224. // 1 0 0
  1225. // 1 1 0
  1226. //
  1227. EnableWindow(GetDlgItem(hwndDlg, IDC_CBX_ENABLE_QUOTA),
  1228. !SetByPolicy(REGSTR_VAL_POLICY_ENABLE));
  1229. //
  1230. // "Deny disk space..." checkbox.
  1231. //
  1232. // Policy Quota Enabled Ctl Enabled
  1233. // 0 0 0
  1234. // 0 1 1
  1235. // 1 0 0
  1236. // 1 1 0
  1237. //
  1238. EnableWindow(GetDlgItem(hwndDlg, IDC_CBX_DENY_LIMIT),
  1239. bQuotaEnabled && !SetByPolicy(REGSTR_VAL_POLICY_ENFORCE));
  1240. //
  1241. // Log event checkboxes
  1242. //
  1243. // Policy Quota Enabled Ctl Enabled
  1244. // 0 0 0
  1245. // 0 1 1
  1246. // 1 0 0
  1247. // 1 1 0
  1248. //
  1249. EnableWindow(GetDlgItem(hwndDlg, IDC_CBX_LOG_OVERLIMIT),
  1250. bQuotaEnabled && !SetByPolicy(REGSTR_VAL_POLICY_LOGLIMIT));
  1251. EnableWindow(GetDlgItem(hwndDlg, IDC_CBX_LOG_OVERWARNING),
  1252. bQuotaEnabled && !SetByPolicy(REGSTR_VAL_POLICY_LOGTHRESHOLD));
  1253. //
  1254. // "Do not limit disk usage" radio button
  1255. // "Limit disk space to" radio button
  1256. //
  1257. // Policy Quota Enabled No Limit Ctl Enabled
  1258. // 0 0 0 0
  1259. // 0 0 1 0
  1260. // 0 1 0 0
  1261. // 0 1 1 1
  1262. // 1 0 0 0
  1263. // 1 0 1 0
  1264. // 1 1 0 0
  1265. // 1 1 1 0
  1266. //
  1267. bEnable = bQuotaEnabled && !SetByPolicy(REGSTR_VAL_POLICY_LIMIT);
  1268. EnableWindow(GetDlgItem(hwndDlg, IDC_RBN_DEF_NOLIMIT), bEnable);
  1269. EnableWindow(GetDlgItem(hwndDlg, IDC_RBN_DEF_LIMIT), bEnable);
  1270. //
  1271. // "Limit disk space" edit and combo controls.
  1272. //
  1273. // Policy Quota Enabled No Limit Ctl Enabled
  1274. // 0 0 0 0
  1275. // 0 0 1 0
  1276. // 0 1 0 1
  1277. // 0 1 1 0
  1278. // 1 0 0 0
  1279. // 1 0 1 0
  1280. // 1 1 0 0
  1281. // 1 1 1 0
  1282. //
  1283. bEnable = bQuotaEnabled &&
  1284. !SetByPolicy(REGSTR_VAL_POLICY_LIMIT) &&
  1285. NOLIMIT != m_pxbDefaultLimit->GetBytes();
  1286. EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_DEF_LIMIT), bEnable);
  1287. EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_DEF_LIMIT), bEnable);
  1288. bEnable = bQuotaEnabled &&
  1289. !SetByPolicy(REGSTR_VAL_POLICY_THRESHOLD) &&
  1290. NOLIMIT != m_pxbDefaultThreshold->GetBytes();
  1291. EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_WARN_LEVEL), bEnable);
  1292. EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT_DEF_THRESHOLD), bEnable);
  1293. EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_DEF_THRESHOLD), bEnable);
  1294. //
  1295. // Miscellaneous text controls.
  1296. //
  1297. // Quota Enabled Ctl Enabled
  1298. // 0 0
  1299. // 1 1
  1300. //
  1301. EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_DEFAULTS), bQuotaEnabled);
  1302. EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_LOGGING), bQuotaEnabled);
  1303. return NOERROR;
  1304. }
  1305. ///////////////////////////////////////////////////////////////////////////////
  1306. /* Function: VolumePropPage::InitializeControls
  1307. Description: Initializes the page controls based on the volume's
  1308. quota settings.
  1309. Arguments:
  1310. hDlg - Dialog window handle.
  1311. Returns:
  1312. NO_ERROR - Always returns NO_ERROR.
  1313. Revision History:
  1314. Date Description Programmer
  1315. -------- --------------------------------------------------- ----------
  1316. 08/15/96 Initial creation. BrianAu
  1317. 08/01/97 Removed IDC_CBX_WARN_THRESHOLD from UI. BrianAu
  1318. */
  1319. ///////////////////////////////////////////////////////////////////////////////
  1320. HRESULT
  1321. VolumePropPage::InitializeControls(
  1322. HWND hDlg
  1323. )
  1324. {
  1325. BOOL bQuotaEnabled = !(DISKQUOTA_IS_DISABLED(m_dwQuotaState));
  1326. BOOL bUnlimited = (NOLIMIT == m_llDefaultQuotaLimit);
  1327. CheckDlgButton(hDlg,
  1328. IDC_CBX_ENABLE_QUOTA,
  1329. bQuotaEnabled);
  1330. CheckDlgButton(hDlg,
  1331. IDC_CBX_DENY_LIMIT,
  1332. DISKQUOTA_IS_ENFORCED(m_dwQuotaState));
  1333. CheckDlgButton(hDlg,
  1334. IDC_CBX_LOG_OVERWARNING,
  1335. !DISKQUOTA_IS_DISABLED(m_dwQuotaState) &&
  1336. DISKQUOTA_IS_LOGGED_USER_THRESHOLD(m_dwQuotaLogFlags));
  1337. CheckDlgButton(hDlg,
  1338. IDC_CBX_LOG_OVERLIMIT,
  1339. !DISKQUOTA_IS_DISABLED(m_dwQuotaState) &&
  1340. DISKQUOTA_IS_LOGGED_USER_LIMIT(m_dwQuotaLogFlags));
  1341. CheckDlgButton(hDlg, IDC_RBN_DEF_NOLIMIT, bUnlimited);
  1342. CheckDlgButton(hDlg, IDC_RBN_DEF_LIMIT, !bUnlimited);
  1343. EnableControls(hDlg);
  1344. return NO_ERROR;
  1345. }
  1346. ///////////////////////////////////////////////////////////////////////////////
  1347. /* Function: VolumePropPage::UpdateStatusIndicators
  1348. Description: Updates the "Status" text message at the top of the property
  1349. page according to the actual quota system state. Also updates the
  1350. traffic light AVI clip.
  1351. Arguments:
  1352. hDlg - Dialog handle.
  1353. Returns:
  1354. Always returns NO_ERROR.
  1355. Revision History:
  1356. Date Description Programmer
  1357. -------- --------------------------------------------------- ----------
  1358. 08/18/96 Initial creation. BrianAu
  1359. 08/28/96 Added stoplight icon. BrianAu
  1360. 09/10/96 Converted stoplight from an icon to an AVI clip. BrianAu
  1361. Call it a traffic light now.
  1362. 07/14/97 Removed distinct "enforce" and "tracking" messages BrianAu
  1363. and replaced with a single "active" message.
  1364. */
  1365. ///////////////////////////////////////////////////////////////////////////////
  1366. HRESULT
  1367. VolumePropPage::UpdateStatusIndicators(
  1368. HWND hDlg
  1369. )
  1370. {
  1371. HRESULT hResult = NO_ERROR;
  1372. DWORD dwMsgID = IDS_STATUS_UNKNOWN;
  1373. IDiskQuotaControl *pqc;
  1374. hResult = GetQuotaController(&pqc);
  1375. if (SUCCEEDED(hResult))
  1376. {
  1377. //
  1378. // Update cached state information.
  1379. //
  1380. hResult = pqc->GetQuotaState(&m_dwQuotaState);
  1381. pqc->Release();
  1382. pqc = NULL;
  1383. }
  1384. if (SUCCEEDED(hResult))
  1385. {
  1386. //
  1387. // Figure out what message to display.
  1388. // "Rebuilding" overrides any other state.
  1389. //
  1390. if (DISKQUOTA_FILE_REBUILDING(m_dwQuotaState))
  1391. {
  1392. dwMsgID = IDS_STATUS_REBUILDING;
  1393. }
  1394. else switch(m_dwQuotaState & DISKQUOTA_STATE_MASK)
  1395. {
  1396. case DISKQUOTA_STATE_DISABLED:
  1397. dwMsgID = IDS_STATUS_DISABLED;
  1398. break;
  1399. case DISKQUOTA_STATE_TRACK:
  1400. case DISKQUOTA_STATE_ENFORCE:
  1401. dwMsgID = IDS_STATUS_ACTIVE;
  1402. break;
  1403. default:
  1404. break;
  1405. }
  1406. }
  1407. if (dwMsgID != m_dwLastStatusMsgID)
  1408. {
  1409. //
  1410. // Format the status text and configure the traffic light.
  1411. //
  1412. // Traffic light states:
  1413. // RED = Quotas disabled.
  1414. // GREEN = Quotas enabled.
  1415. // Flashing YELLOW = Quota file is rebuilding.
  1416. //
  1417. INT iTrafficLightState = TrafficLight::GREEN;
  1418. if (DISKQUOTA_FILE_REBUILDING(m_dwQuotaState))
  1419. iTrafficLightState = TrafficLight::FLASHING_YELLOW;
  1420. else if (DISKQUOTA_IS_DISABLED(m_dwQuotaState))
  1421. iTrafficLightState = TrafficLight::RED;
  1422. m_TrafficLight.Show(iTrafficLightState);
  1423. CString strStatus(g_hInstDll, dwMsgID);
  1424. SetWindowText(GetDlgItem(hDlg, IDC_TXT_QUOTA_STATUS), strStatus);
  1425. m_dwLastStatusMsgID = dwMsgID;
  1426. //
  1427. // Re-initialize the controls based on the new state.
  1428. //
  1429. InitializeControls(hDlg);
  1430. }
  1431. return NO_ERROR;
  1432. }
  1433. ///////////////////////////////////////////////////////////////////////////////
  1434. /* Function: VolumePropPage::QuotaStateFromControls
  1435. Description: Determines the quota state from the states of the individual
  1436. controls on the page.
  1437. Arguments:
  1438. hDlg - Dialog's window handle.
  1439. pdwState - Address of DWORD variable to receive state bits.
  1440. Returns:
  1441. Always returns NO_ERROR.
  1442. Revision History:
  1443. Date Description Programmer
  1444. -------- --------------------------------------------------- ----------
  1445. 08/19/96 Initial creation. BrianAu
  1446. */
  1447. ///////////////////////////////////////////////////////////////////////////////
  1448. HRESULT
  1449. VolumePropPage::QuotaStateFromControls(
  1450. HWND hDlg,
  1451. LPDWORD pdwState
  1452. ) const
  1453. {
  1454. DBGASSERT((NULL != pdwState));
  1455. //
  1456. // Set quota state if changed.
  1457. //
  1458. if (IsDlgButtonChecked(hDlg, IDC_CBX_ENABLE_QUOTA))
  1459. {
  1460. if (IsDlgButtonChecked(hDlg, IDC_CBX_DENY_LIMIT))
  1461. {
  1462. *pdwState = DISKQUOTA_STATE_ENFORCE;
  1463. }
  1464. else
  1465. *pdwState = DISKQUOTA_STATE_TRACK;
  1466. }
  1467. else
  1468. *pdwState = DISKQUOTA_STATE_DISABLED;
  1469. return NO_ERROR;
  1470. }
  1471. ///////////////////////////////////////////////////////////////////////////////
  1472. /* Function: VolumePropPage::LogFlagsFromControls
  1473. Description: Determines the log flags state from the states of the
  1474. individual controls on the page.
  1475. Arguments:
  1476. hDlg - Dialog's window handle.
  1477. pdwLogFlags - Address of DWORD variable to receive flag bits.
  1478. Returns:
  1479. Always returns NO_ERROR.
  1480. Revision History:
  1481. Date Description Programmer
  1482. -------- --------------------------------------------------- ----------
  1483. 08/19/96 Initial creation. BrianAu
  1484. 08/01/97 Removed IDC_CBX_WARN_THRESHOLD from UI. BrianAu
  1485. 11/20/98 Added "log over limit" and "log over warning" BrianAu
  1486. controls.
  1487. */
  1488. ///////////////////////////////////////////////////////////////////////////////
  1489. HRESULT
  1490. VolumePropPage::LogFlagsFromControls(
  1491. HWND hDlg,
  1492. LPDWORD pdwLogFlags
  1493. ) const
  1494. {
  1495. DBGASSERT((NULL != pdwLogFlags));
  1496. DISKQUOTA_SET_LOG_USER_LIMIT(*pdwLogFlags,
  1497. IsDlgButtonChecked(hDlg, IDC_CBX_LOG_OVERLIMIT));
  1498. DISKQUOTA_SET_LOG_USER_THRESHOLD(*pdwLogFlags,
  1499. IsDlgButtonChecked(hDlg, IDC_CBX_LOG_OVERWARNING));
  1500. return NO_ERROR;
  1501. }
  1502. ///////////////////////////////////////////////////////////////////////////////
  1503. /* Function: VolumePropPage::TrafficLight::Initialize
  1504. Description: Initializes the traffic light by opening the AVI clip.
  1505. Arguments:
  1506. hwndAnimateCtl - Handle to the animation control in the dialog.
  1507. idAviClipRes - Resource ID of the AVI clip resource.
  1508. Returns: Nothing. If the thing doesn't load, it just won't play.
  1509. Revision History:
  1510. Date Description Programmer
  1511. -------- --------------------------------------------------- ----------
  1512. 09/10/96 Initial creation. BrianAu
  1513. */
  1514. ///////////////////////////////////////////////////////////////////////////////
  1515. VOID
  1516. VolumePropPage::TrafficLight::Initialize(
  1517. HWND hwndAnimateCtl,
  1518. INT idAviClipRes
  1519. )
  1520. {
  1521. DBGASSERT((NULL != hwndAnimateCtl));
  1522. m_hwndAnimateCtl = hwndAnimateCtl;
  1523. m_idAviClipRes = idAviClipRes;
  1524. Animate_Open(m_hwndAnimateCtl, MAKEINTRESOURCE(idAviClipRes));
  1525. //
  1526. // See note in TrafficLight::Show below.
  1527. //
  1528. // Animate_SetFrameTime(m_hwndAnimateCtl, GetCaretBlinkTime());
  1529. }
  1530. ///////////////////////////////////////////////////////////////////////////////
  1531. /* Function: VolumePropPage::TrafficLight::Show
  1532. Description: Shows the traffic light in one of it's states.
  1533. Arguments:
  1534. eShow - One of the following enumerated constant values:
  1535. OFF, YELLOW, RED, GREEN, FLASHING_YELLOW.
  1536. NOTE: THIS IS VERY IMPORTANT!!!
  1537. The definitions of these constants MUST match as follows
  1538. with the frame numbers in the AVI clip TRAFFIC.AVI. If
  1539. you change either, it won't work.
  1540. Frame Constant Value
  1541. ------ ---------------- ------
  1542. 0 OFF 0
  1543. 1 YELLOW 1
  1544. 2 RED 2
  1545. 3 GREEN 3
  1546. N/A FLASHING_YELLOW 4
  1547. Flashing yellow is created by playing frames 0 and 1
  1548. repeatedly.
  1549. Returns: Nothing.
  1550. Revision History:
  1551. Date Description Programmer
  1552. -------- --------------------------------------------------- ----------
  1553. 09/10/96 Initial creation. BrianAu
  1554. */
  1555. ///////////////////////////////////////////////////////////////////////////////
  1556. VOID
  1557. VolumePropPage::TrafficLight::Show(
  1558. INT eShow
  1559. )
  1560. {
  1561. switch(eShow)
  1562. {
  1563. case OFF:
  1564. case YELLOW:
  1565. case RED:
  1566. case GREEN:
  1567. Animate_Seek(m_hwndAnimateCtl, eShow);
  1568. break;
  1569. case FLASHING_YELLOW:
  1570. Animate_Seek(m_hwndAnimateCtl, YELLOW);
  1571. //
  1572. // NOTE:
  1573. //
  1574. // The common control guys didn't want me to add the ACM_SETFRAMETIME
  1575. // message so we can't vary the rate of the animation. Since we can't
  1576. // have a fixed-rate blinking control, I'm just fixing the traffic light
  1577. // at yellow rather than flashing. If we can ever add the frame time
  1578. // modification message to the animation control, we can activate
  1579. // this functionality. A flashing light isn't worth the trouble of
  1580. // a unique implementation. I really wanted this. It looks cool.
  1581. //
  1582. // FEATURE: If we have time. Make this work without the animation control.
  1583. // Note that I tried just setting the icon. But since the volume
  1584. // status checking is done on the same thread that processes the
  1585. // STM_SETICON messgae, flashing of the icon is erratic.
  1586. //
  1587. // Animate_Play(m_hwndAnimateCtl, YELLOW, OFF, (UINT)-1);
  1588. break;
  1589. default:
  1590. break;
  1591. }
  1592. }
  1593. INT_PTR
  1594. VolumePropPage::TrafficLight::ForwardMessage(
  1595. UINT uMsg,
  1596. WPARAM wParam,
  1597. LPARAM lParam
  1598. )
  1599. {
  1600. return SendMessage(m_hwndAnimateCtl, uMsg, wParam, lParam);
  1601. }
  1602. #ifdef POLICY_MMC_SNAPIN
  1603. SnapInVolPropPage::~SnapInVolPropPage(
  1604. void
  1605. )
  1606. {
  1607. if (NULL != m_pPolicy)
  1608. m_pPolicy->Release();
  1609. }
  1610. BOOL
  1611. SnapInVolPropPage::OnInitDialog(
  1612. HWND hDlg,
  1613. UINT wParam,
  1614. LONG lParam
  1615. )
  1616. {
  1617. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::OnInitDialog")));
  1618. HRESULT hr = NO_ERROR;
  1619. bool bRemovableMedia = false;
  1620. //
  1621. // Policy object should have already been created and initialized
  1622. // by the creator of the property sheet. See CSnapInCompData::PropPageThreadProc.
  1623. //
  1624. DBGASSERT((NULL != m_pPolicy));
  1625. //
  1626. // Retrieve and restore the previous dialog state from when the
  1627. // user last used the snapin. We use the GPTInfo structure for
  1628. // convenience since we're storing the same information that is
  1629. // used for setting policy.
  1630. //
  1631. DISKQUOTAPOLICYINFO dqpi;
  1632. RegKey keyPref(HKEY_CURRENT_USER, REGSTR_KEY_DISKQUOTA);
  1633. if (SUCCEEDED(keyPref.Open(KEY_READ)) &&
  1634. SUCCEEDED(keyPref.GetValue(c_szSnapInPrefs, (LPBYTE)&dqpi, sizeof(dqpi))) &&
  1635. sizeof(dqpi) == dqpi.cb)
  1636. {
  1637. m_llDefaultQuotaLimit = dqpi.llDefaultQuotaLimit;
  1638. m_llDefaultQuotaThreshold = dqpi.llDefaultQuotaThreshold;
  1639. m_dwQuotaState = dqpi.dwQuotaState;
  1640. m_dwQuotaLogFlags = dqpi.dwQuotaLogFlags;
  1641. bRemovableMedia = dqpi.bRemovableMedia;
  1642. }
  1643. else
  1644. DBGERROR((TEXT("Error loading policy dialog information")));
  1645. //
  1646. // Create the XBytes objects to manage the relationship between the
  1647. // limit/threshold edit controls and their combo boxes.
  1648. //
  1649. m_pxbDefaultLimit = new XBytes(hDlg,
  1650. IDC_EDIT_DEF_LIMIT,
  1651. IDC_CMB_DEF_LIMIT,
  1652. m_llDefaultQuotaLimit);
  1653. m_pxbDefaultThreshold = new XBytes(hDlg,
  1654. IDC_EDIT_DEF_THRESHOLD,
  1655. IDC_CMB_DEF_THRESHOLD,
  1656. m_llDefaultQuotaThreshold);
  1657. InitializeControls(hDlg);
  1658. return TRUE; // Set focus to default control.
  1659. }
  1660. BOOL
  1661. SnapInVolPropPage::OnSheetNotifySetActive(
  1662. HWND hDlg,
  1663. UINT wParam,
  1664. LONG lParam
  1665. )
  1666. {
  1667. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::OnSheetNotifySetActive")));
  1668. return FALSE;
  1669. }
  1670. BOOL
  1671. SnapInVolPropPage::OnSheetNotifyApply(
  1672. HWND hDlg,
  1673. UINT wParam,
  1674. LONG lParam
  1675. )
  1676. {
  1677. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::OnSheetNotifyApply")));
  1678. LONG dwPSNReturn = PSNRET_NOERROR;
  1679. HRESULT hr = NOERROR;
  1680. DWORD dwState, dwLogFlags;
  1681. LONGLONG llThreshold, llLimit;
  1682. //
  1683. // Policy object should have already been created and initialized
  1684. // by the creator of the property sheet. See CSnapInCompData::PropPageThreadProc.
  1685. //
  1686. DBGASSERT((NULL != m_pPolicy));
  1687. //
  1688. // Query the state of the dialog to get the quota settings.
  1689. //
  1690. QuotaStateFromControls(hDlg, &dwState);
  1691. LogFlagsFromControls(hDlg, &dwLogFlags);
  1692. if (IsDlgButtonChecked(hDlg, IDC_RBN_DEF_NOLIMIT))
  1693. {
  1694. llThreshold = NOLIMIT;
  1695. llLimit = NOLIMIT;
  1696. }
  1697. else
  1698. {
  1699. llThreshold = m_pxbDefaultThreshold->GetBytes();
  1700. llLimit = m_pxbDefaultLimit->GetBytes();
  1701. }
  1702. DISKQUOTAPOLICYINFO dqpi;
  1703. dqpi.cb = sizeof(dqpi);
  1704. dqpi.llDefaultQuotaThreshold = llThreshold;
  1705. dqpi.llDefaultQuotaLimit = llLimit;
  1706. dqpi.dwQuotaState = dwState;
  1707. dqpi.dwQuotaLogFlags = dwLogFlags;
  1708. dqpi.bRemovableMedia = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RBN_POLICY_REMOVABLE));
  1709. //
  1710. // Save the policy information to the registry.
  1711. //
  1712. hr = m_pPolicy->Save(&dqpi);
  1713. if (FAILED(hr))
  1714. {
  1715. DBGERROR((TEXT("Error 0x%08X saving policy information"), hr));
  1716. //
  1717. // Show some UI?
  1718. //
  1719. }
  1720. //
  1721. // Save current dialog state so that we can restore it next time the
  1722. // user opens the snapin. This way, if the user typically sets
  1723. // quotas to the same values, the UI will appear much more friendly.
  1724. //
  1725. RegKey keyPref(HKEY_CURRENT_USER, REGSTR_KEY_DISKQUOTA);
  1726. if (FAILED(keyPref.Open(KEY_WRITE)) ||
  1727. FAILED(keyPref.SetValue(c_szSnapInPrefs, (LPBYTE)&dqpi, sizeof(dqpi))))
  1728. {
  1729. DBGERROR((TEXT("Error saving policy dialog information")));
  1730. }
  1731. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, dwPSNReturn);
  1732. return TRUE;
  1733. }
  1734. BOOL
  1735. SnapInVolPropPage::OnSheetNotifyKillActive(
  1736. HWND hDlg,
  1737. UINT wParam,
  1738. LONG lParam
  1739. )
  1740. {
  1741. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::OnSheetNotifyKillActive")));
  1742. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
  1743. return TRUE;
  1744. }
  1745. BOOL
  1746. SnapInVolPropPage::OnSheetNotifyReset(
  1747. HWND hDlg,
  1748. UINT wParam,
  1749. LONG lParam
  1750. )
  1751. {
  1752. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::OnSheetNotifyReset")));
  1753. return FALSE;
  1754. }
  1755. HRESULT
  1756. SnapInVolPropPage::CreateDiskQuotaPolicyObject(
  1757. IDiskQuotaPolicy **ppOut
  1758. )
  1759. {
  1760. DBGTRACE((DM_VPROP, DL_HIGH, TEXT("SnapInVolPropPage::CreateDiskQuotaPolicyObject")));
  1761. HRESULT hr = NOERROR;
  1762. try
  1763. {
  1764. CDiskQuotaPolicy *pPolicy = new CDiskQuotaPolicy;
  1765. hr = pPolicy->QueryInterface(IID_IDiskQuotaPolicy,
  1766. reinterpret_cast<void **>(&m_pPolicy));
  1767. if (SUCCEEDED(hr))
  1768. {
  1769. m_pPolicy->AddRef();
  1770. *ppOut = m_pPolicy;
  1771. }
  1772. }
  1773. catch(CAllocException& e)
  1774. {
  1775. hr = E_OUTOFMEMORY;
  1776. }
  1777. return hr;
  1778. }
  1779. #endif // POLICY_MMC_SNAPIN