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.

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