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.

725 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: cnumber.cpp
  7. //
  8. // Contents: implementation of CConfigNumber
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "CNumber.h"
  14. #include "util.h"
  15. #include "ANumber.h"
  16. #include "DDWarn.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CConfigNumber dialog
  24. CConfigNumber::CConfigNumber(UINT nTemplateID)
  25. : CAttribute(nTemplateID ? nTemplateID : IDD),
  26. m_cMinutes(0),
  27. m_nLow(0),
  28. m_nHigh(999),
  29. m_nSave(0)
  30. {
  31. //{{AFX_DATA_INIT(CConfigNumber)
  32. m_strUnits = _T("");
  33. m_strValue = _T("");
  34. m_strStatic = _T("");
  35. m_strError = _T("");
  36. //}}AFX_DATA_INIT
  37. m_pHelpIDs = (DWORD_PTR)a181HelpIDs;
  38. m_uTemplateResID = IDD;
  39. }
  40. void CConfigNumber::DoDataExchange(CDataExchange* pDX)
  41. {
  42. CAttribute::DoDataExchange(pDX);
  43. //{{AFX_DATA_MAP(CConfigNumber)
  44. DDX_Control(pDX, IDC_SPIN, m_SpinValue);
  45. DDX_Text(pDX, IDC_UNITS, m_strUnits);
  46. DDX_Text(pDX, IDC_VALUE, m_strValue);
  47. DDX_Text(pDX, IDC_HEADER,m_strStatic);
  48. DDX_Text(pDX, IDC_RANGEERROR,m_strError);
  49. //}}AFX_DATA_MAP
  50. }
  51. BEGIN_MESSAGE_MAP(CConfigNumber, CAttribute)
  52. //{{AFX_MSG_MAP(CConfigNumber)
  53. // ON_EN_KILLFOCUS(IDC_VALUE, OnKillFocus)
  54. ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN, OnDeltaposSpin)
  55. ON_EN_UPDATE(IDC_VALUE, OnUpdateValue)
  56. ON_BN_CLICKED(IDC_CONFIGURE,OnConfigure)
  57. //}}AFX_MSG_MAP
  58. END_MESSAGE_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CConfigNumber message handlers
  61. void CConfigNumber::OnDeltaposSpin( NMHDR* pNMHDR, LRESULT* pResult )
  62. {
  63. NM_UPDOWN FAR *pnmud;
  64. pnmud = (NM_UPDOWN FAR *)pNMHDR;
  65. SetModified(TRUE);
  66. if ( pnmud ) {
  67. //
  68. // get current value
  69. //
  70. long lVal = CurrentEditValue();
  71. if (SCE_FOREVER_VALUE == lVal) {
  72. if (pnmud->iDelta > 0) {
  73. if (m_cMinutes & DW_VALUE_OFF) {
  74. lVal = SCE_KERBEROS_OFF_VALUE;
  75. } else {
  76. lVal = m_nHigh;
  77. }
  78. } else {
  79. lVal = m_nLow;
  80. }
  81. } else if (SCE_KERBEROS_OFF_VALUE == lVal) {
  82. if (pnmud->iDelta < 0) {
  83. if (m_cMinutes & DW_VALUE_FOREVER) {
  84. lVal = SCE_FOREVER_VALUE;
  85. } else {
  86. lVal = m_nLow;
  87. }
  88. } else {
  89. lVal = m_nHigh;
  90. }
  91. } else {
  92. lVal -= (LONG)(m_iAccRate*pnmud->iDelta);
  93. if ( lVal > m_nHigh ) {
  94. // if it is overflow, go back to low
  95. if ( m_cMinutes & DW_VALUE_OFF ) {
  96. lVal = SCE_KERBEROS_OFF_VALUE;
  97. } else if (m_cMinutes & DW_VALUE_FOREVER) {
  98. lVal = SCE_FOREVER_VALUE;
  99. } else {
  100. lVal = m_nLow;
  101. }
  102. } else if ( (lVal < m_nLow) &&
  103. ((lVal != SCE_KERBEROS_OFF_VALUE) || !(m_cMinutes & DW_VALUE_OFF)) &&
  104. ((lVal != SCE_FOREVER_VALUE) || !(m_cMinutes & DW_VALUE_FOREVER))) {
  105. // if it is underflow, go back to high
  106. if ( (m_cMinutes & DW_VALUE_FOREVER) && (lVal != SCE_FOREVER_VALUE)) {
  107. lVal = SCE_FOREVER_VALUE;
  108. } else if ((m_cMinutes & DW_VALUE_OFF) && (lVal != SCE_KERBEROS_OFF_VALUE)) {
  109. lVal = SCE_KERBEROS_OFF_VALUE;
  110. } else {
  111. lVal = m_nHigh;
  112. }
  113. }
  114. if ( 0 == lVal && (m_cMinutes & DW_VALUE_NOZERO) ) {
  115. // zero is not allowed
  116. if ( m_nLow > 0 ) {
  117. lVal = m_nLow;
  118. } else {
  119. lVal = 1;
  120. }
  121. }
  122. }
  123. SetValueToEdit(lVal);
  124. }
  125. *pResult = 0;
  126. }
  127. void CConfigNumber::OnKillFocus()
  128. {
  129. LONG lVal = CurrentEditValue();
  130. SetValueToEdit(lVal);
  131. }
  132. void CConfigNumber::SetValueToEdit(LONG lVal)
  133. {
  134. CString strNew;
  135. SetModified(TRUE);
  136. if ( m_iStaticId )
  137. m_strStatic.LoadString(m_iStaticId);
  138. else
  139. m_strStatic = _T("");
  140. if ( 0 == lVal ) {
  141. strNew.Format(TEXT("%d"),lVal);
  142. if ( m_cMinutes & DW_VALUE_NEVER &&
  143. m_iNeverId > 0 ) {
  144. // change to never
  145. m_strStatic.LoadString(m_iNeverId);
  146. }
  147. } else if ( SCE_FOREVER_VALUE == lVal ) {
  148. strNew.LoadString(IDS_FOREVER);
  149. if ( m_iNeverId ) {
  150. m_strStatic.LoadString(m_iNeverId);
  151. }
  152. } else if (SCE_KERBEROS_OFF_VALUE == lVal) {
  153. strNew.LoadString(IDS_OFF);
  154. if ( m_iNeverId ) {
  155. m_strStatic.LoadString(m_iNeverId);
  156. }
  157. } else {
  158. strNew.Format(TEXT("%d"),lVal);
  159. }
  160. m_nSave = lVal;
  161. SetDlgItemText(IDC_VALUE,strNew);
  162. SetDlgItemText(IDC_HEADER,m_strStatic);
  163. }
  164. LONG CConfigNumber::CurrentEditValue()
  165. {
  166. UINT uiVal = 0;
  167. LONG lVal = 0;
  168. BOOL bTrans = FALSE;
  169. uiVal = GetDlgItemInt(IDC_VALUE,&bTrans,TRUE);
  170. lVal = uiVal;
  171. if ( !bTrans ) {
  172. CString str;
  173. if (m_cMinutes & DW_VALUE_FOREVER) {
  174. str.LoadString(IDS_FOREVER);
  175. if (str == m_strValue) {
  176. return SCE_FOREVER_VALUE;
  177. }
  178. }
  179. lVal = _ttol((LPCTSTR)m_strValue);
  180. if ( lVal == 0 ) {
  181. // nonnumeric
  182. lVal = (LONG) m_nSave;
  183. return lVal;
  184. }
  185. }
  186. if ( m_iAccRate > 1 && lVal > 0 ) {
  187. // for log max size, make it multiples of m_iAccRate
  188. int nCount = lVal % m_iAccRate;
  189. if ( nCount > 0 ) {
  190. lVal = ((LONG)(lVal/m_iAccRate))*m_iAccRate;
  191. }
  192. }
  193. if ( lVal > m_nHigh ) {
  194. // if it is overflow, go back to low
  195. if ( m_cMinutes & DW_VALUE_FOREVER ) {
  196. lVal = SCE_FOREVER_VALUE;
  197. } else if (m_cMinutes & DW_VALUE_OFF) {
  198. lVal = SCE_KERBEROS_OFF_VALUE;
  199. } else {
  200. // Leave alone and let the OnKillActive catch it
  201. }
  202. }
  203. if ( (lVal < m_nLow) &&
  204. (lVal != SCE_KERBEROS_OFF_VALUE) &&
  205. (lVal != SCE_FOREVER_VALUE) ) {
  206. // if it is underflow, go back to high
  207. if (m_cMinutes & DW_VALUE_OFF) {
  208. lVal = SCE_KERBEROS_OFF_VALUE;
  209. } else if ( m_cMinutes & DW_VALUE_FOREVER) {
  210. lVal = SCE_FOREVER_VALUE;
  211. } else {
  212. // Leave alone and let the OnKillActive catch it
  213. }
  214. }
  215. if ( 0 == lVal && (m_cMinutes & DW_VALUE_NOZERO) ) {
  216. // zero is not allowed
  217. if ( m_nLow > 0 ) {
  218. lVal = m_nLow;
  219. } else {
  220. lVal = 1;
  221. }
  222. }
  223. return lVal;
  224. }
  225. void CConfigNumber::OnConfigure()
  226. {
  227. UpdateData(TRUE);
  228. CAttribute::OnConfigure();
  229. CWnd* cwnd = GetDlgItem(IDOK);
  230. if(cwnd)
  231. {
  232. if(!m_bConfigure)
  233. cwnd->EnableWindow(TRUE);
  234. else
  235. OnUpdateValue();
  236. }
  237. }
  238. BOOL CConfigNumber::OnInitDialog()
  239. {
  240. CAttribute::OnInitDialog();
  241. AddUserControl(IDC_VALUE);
  242. AddUserControl(IDC_SPIN);
  243. AddUserControl(IDC_UNITS);
  244. UpdateData(TRUE);
  245. OnConfigure();
  246. return TRUE; // return TRUE unless you set the focus to a control
  247. // EXCEPTION: OCX Property Pages should return FALSE
  248. }
  249. BOOL CConfigNumber::OnApply()
  250. {
  251. if ( !m_bReadOnly )
  252. {
  253. BOOL bSet = FALSE;
  254. LONG_PTR dw = 0;
  255. CString strForever;
  256. CString strOff;
  257. UpdateData(TRUE);
  258. if (!m_bConfigure)
  259. dw = (LONG_PTR)ULongToPtr(SCE_NO_VALUE);
  260. else
  261. dw = CurrentEditValue();
  262. CEditTemplate *petSave = m_pData->GetBaseProfile();
  263. //
  264. // Check dependecies for this item.
  265. //
  266. if(DDWarn.CheckDependencies(
  267. (DWORD)dw) == ERROR_MORE_DATA )
  268. {
  269. //
  270. // If it fails and the user presses cancel then we will exit and do nothing.
  271. //
  272. CThemeContextActivator activator;
  273. if( DDWarn.DoModal() != IDOK)
  274. return FALSE;
  275. //
  276. // If the user presses autoset then we set the item and update the result panes.
  277. //
  278. for(int i = 0; i < DDWarn.GetFailedCount(); i++)
  279. {
  280. PDEPENDENCYFAILED pItem = DDWarn.GetFailedInfo(i);
  281. if(pItem && pItem->pResult )
  282. {
  283. pItem->pResult->SetBase( pItem->dwSuggested );
  284. SetProfileInfo(
  285. pItem->pResult->GetID(),
  286. pItem->dwSuggested,
  287. pItem->pResult->GetBaseProfile());
  288. pItem->pResult->Update(m_pSnapin, FALSE);
  289. }
  290. }
  291. }
  292. //
  293. // Update this items profile.
  294. //
  295. m_pData->SetBase(dw);
  296. SetProfileInfo(m_pData->GetID(),dw,m_pData->GetBaseProfile());
  297. m_pData->Update(m_pSnapin, false);
  298. LPTSTR pszAlloc = NULL; //Raid #402030
  299. m_pData->GetBaseNoUnit(pszAlloc);
  300. if(pszAlloc)
  301. {
  302. SetDlgItemText(IDC_VALUE,pszAlloc);
  303. delete [] pszAlloc;
  304. }
  305. }
  306. return CAttribute::OnApply();
  307. }
  308. void CConfigNumber::Initialize(CResult * pResult)
  309. {
  310. LONG_PTR dw=0;
  311. CAttribute::Initialize(pResult);
  312. m_strUnits = pResult->GetUnits();
  313. DDWarn.InitializeDependencies(m_pSnapin,pResult);
  314. m_cMinutes = DW_VALUE_NOZERO;
  315. m_nLow = 0;
  316. m_nHigh = 999;
  317. m_nSave = 0;
  318. m_iNeverId = 0;
  319. m_iAccRate = 1;
  320. m_iStaticId = 0;
  321. CEditTemplate *pTemplate = pResult->GetBaseProfile();
  322. switch (pResult->GetID())
  323. {
  324. // below no zero value
  325. case IDS_LOCK_DURATION:
  326. m_cMinutes = DW_VALUE_FOREVER | DW_VALUE_NOZERO;
  327. m_nHigh = 99999;
  328. m_iStaticId = IDS_DURATION;
  329. m_iNeverId = IDS_LOCKOUT_FOREVER;
  330. break;
  331. case IDS_MIN_PAS_AGE:
  332. m_cMinutes = DW_VALUE_NEVER;
  333. m_iNeverId = IDS_CHANGE_IMMEDIATELY;
  334. m_iStaticId = IDS_PASSWORD_CHANGE;
  335. m_nHigh = 998;
  336. break;
  337. case IDS_MAX_PAS_AGE:
  338. m_cMinutes = DW_VALUE_FOREVER | DW_VALUE_NOZERO;
  339. m_iStaticId = IDS_PASSWORD_EXPIRE;
  340. m_iNeverId = IDS_PASSWORD_FOREVER;
  341. break;
  342. // below zero value means differently
  343. case IDS_LOCK_COUNT:
  344. m_cMinutes = DW_VALUE_NEVER;
  345. m_iNeverId = IDS_NO_LOCKOUT;
  346. m_iStaticId = IDS_LOCKOUT_AFTER;
  347. break;
  348. case IDS_MIN_PAS_LEN:
  349. m_cMinutes = DW_VALUE_NEVER;
  350. m_nHigh = 14;
  351. m_iNeverId = IDS_PERMIT_BLANK;
  352. m_iStaticId = IDS_PASSWORD_LEN;
  353. break;
  354. case IDS_PAS_UNIQUENESS:
  355. m_cMinutes = DW_VALUE_NEVER;
  356. m_nHigh = 24;
  357. m_iNeverId = IDS_NO_HISTORY;
  358. m_iStaticId = IDS_PASSWORD_REMEMBER;
  359. break;
  360. // below there is no zero values
  361. case IDS_LOCK_RESET_COUNT:
  362. m_nLow = 1;
  363. m_nHigh = 99999;
  364. m_iStaticId = IDS_LOCK_RESET_COUNT;
  365. break;
  366. case IDS_SYS_LOG_MAX:
  367. case IDS_SEC_LOG_MAX:
  368. case IDS_APP_LOG_MAX:
  369. m_nLow = 64;
  370. m_nHigh = 4194240;
  371. m_iAccRate = 64;
  372. // no static text
  373. break;
  374. case IDS_SYS_LOG_DAYS:
  375. case IDS_SEC_LOG_DAYS:
  376. case IDS_APP_LOG_DAYS:
  377. m_nHigh = 365;
  378. m_nLow = 1;
  379. m_iStaticId = IDS_OVERWRITE_EVENT;
  380. break;
  381. case IDS_KERBEROS_MAX_AGE:
  382. m_cMinutes = DW_VALUE_FOREVER | DW_VALUE_NOZERO;
  383. m_iStaticId = IDS_TICKET_EXPIRE;
  384. m_iNeverId = IDS_TICKET_FOREVER;
  385. m_nHigh = 99999;
  386. break;
  387. case IDS_KERBEROS_RENEWAL:
  388. m_cMinutes = DW_VALUE_FOREVER | DW_VALUE_NOZERO; // | DW_VALUE_OFF;
  389. m_iStaticId = IDS_TICKET_RENEWAL_EXPIRE;
  390. m_iNeverId = IDS_TICKET_RENEWAL_FOREVER;
  391. m_nHigh = 99999;
  392. break;
  393. case IDS_KERBEROS_MAX_SERVICE:
  394. m_nLow = 10;
  395. m_cMinutes = DW_VALUE_FOREVER | DW_VALUE_NOZERO;
  396. m_iStaticId = IDS_TICKET_EXPIRE;
  397. m_iNeverId = IDS_TICKET_FOREVER;
  398. m_nHigh = 99999;
  399. break;
  400. case IDS_KERBEROS_MAX_CLOCK:
  401. m_cMinutes = DW_VALUE_FOREVER;
  402. m_iStaticId = IDS_MAX_TOLERANCE;
  403. m_iNeverId = IDS_NO_MAX_TOLERANCE;
  404. m_nHigh = 99999;
  405. break;
  406. }
  407. if ((m_cMinutes & DW_VALUE_NOZERO) && (0 == m_nLow)) {
  408. m_nLow = 1;
  409. }
  410. m_strStatic = _T("");
  411. dw = pResult->GetBase();
  412. if ((LONG_PTR)ULongToPtr(SCE_NO_VALUE) == dw)
  413. {
  414. m_bConfigure = FALSE;
  415. }
  416. else
  417. {
  418. m_bConfigure = TRUE;
  419. SetInitialValue (dw);
  420. }
  421. }
  422. void CConfigNumber::SetInitialValue(DWORD_PTR dw)
  423. {
  424. //
  425. // Don't overwrite an already set value.
  426. //
  427. if (!m_strValue.IsEmpty())
  428. {
  429. return;
  430. }
  431. if (SCE_FOREVER_VALUE == dw) {
  432. // forever value
  433. m_strValue.LoadString(IDS_FOREVER);
  434. if ( (m_cMinutes & DW_VALUE_FOREVER) &&
  435. m_iNeverId > 0 ) {
  436. m_strStatic.LoadString(m_iNeverId);
  437. }
  438. m_nSave = SCE_FOREVER_VALUE;
  439. } else if (SCE_KERBEROS_OFF_VALUE == dw) {
  440. // off value
  441. m_strValue.LoadString(IDS_OFF);
  442. if ( (m_cMinutes & DW_VALUE_OFF) &&
  443. m_iNeverId > 0 ) {
  444. m_strStatic.LoadString(m_iNeverId);
  445. }
  446. m_nSave = SCE_KERBEROS_OFF_VALUE;
  447. } else {
  448. if ( 0 == dw && (m_cMinutes & DW_VALUE_NOZERO) ) {
  449. // no zero vallue is allowed
  450. if ( m_nLow > 0 ) {
  451. dw = m_nLow;
  452. } else {
  453. dw = 1;
  454. }
  455. }
  456. m_strValue.Format(TEXT("%d"),dw);
  457. m_nSave = dw;
  458. if ( 0 == dw && (m_cMinutes & DW_VALUE_NEVER) &&
  459. m_iNeverId > 0 ) {
  460. // zero means different values
  461. m_strStatic.LoadString(m_iNeverId);
  462. } else if ( m_iStaticId > 0 ) {
  463. m_strStatic.LoadString(m_iStaticId);
  464. }
  465. }
  466. }
  467. void CConfigNumber::OnUpdateValue()
  468. {
  469. DWORD dwRes = 0;
  470. UpdateData(TRUE);
  471. SetModified(TRUE);
  472. CString sNum;
  473. CEdit *pEdit = (CEdit *)GetDlgItem(IDC_VALUE);
  474. CWnd *pOK = GetDlgItem(IDOK);
  475. DWORD dwValue = _ttoi(m_strValue);
  476. //
  477. // Don't do anything if the string is equal to predefined strings.
  478. //
  479. sNum.LoadString(IDS_FOREVER);
  480. if (m_strValue.IsEmpty()) {
  481. if (pOK) {
  482. pOK->EnableWindow(FALSE);
  483. }
  484. } else if(m_strValue == sNum){
  485. if(pOK && !QueryReadOnly()){
  486. pOK->EnableWindow(TRUE);
  487. }
  488. } else {
  489. if((LONG)dwValue < m_nLow){
  490. //
  491. // Disable the OK button.
  492. //
  493. if( pOK ){
  494. pOK->EnableWindow(FALSE);
  495. }
  496. if(pEdit){
  497. //
  498. // We will only force a select if edit text length >=
  499. // minimum text length
  500. //
  501. sNum.Format(TEXT("%d"), m_nLow);
  502. dwValue = m_nLow;
  503. if(sNum.GetLength() < m_strValue.GetLength()){
  504. pEdit->SetSel(0, -1);
  505. }
  506. }
  507. } else if( (LONG)dwValue > m_nHigh ) {
  508. if(!QueryReadOnly() && pOK){
  509. pOK->EnableWindow(TRUE);
  510. }
  511. if(pEdit){
  512. if(m_cMinutes & DW_VALUE_FOREVER){
  513. sNum.LoadString(IDS_FOREVER);
  514. dwValue = 0;
  515. } else {
  516. sNum.Format(TEXT("%d"), m_nHigh);
  517. dwValue = m_nHigh;
  518. }
  519. m_strValue = sNum;
  520. UpdateData(FALSE);
  521. pEdit->SetSel(0, -1);
  522. }
  523. } else if(!QueryReadOnly() && pOK){
  524. //
  525. // Enable the OK button.
  526. //
  527. if (pOK) {
  528. pOK->EnableWindow(TRUE);
  529. }
  530. }
  531. }
  532. //
  533. // Load the description for this string.
  534. //
  535. if ((dwValue <= 0) && (m_iNeverId != 0)) {
  536. m_strStatic.LoadString(m_iNeverId);
  537. } else {
  538. m_strStatic.LoadString(m_iStaticId);
  539. }
  540. GetDlgItem(IDC_HEADER)->SetWindowText(m_strStatic);
  541. }
  542. BOOL CConfigNumber::OnKillActive()
  543. {
  544. UINT uiVal = 0;
  545. LONG lVal = 0;
  546. BOOL bTrans = FALSE;
  547. CString strRange;
  548. int lMin = m_nLow;
  549. UpdateData(TRUE);
  550. if (!m_bConfigure)
  551. {
  552. return TRUE;
  553. }
  554. if ((m_cMinutes & DW_VALUE_NOZERO) &&
  555. !(m_cMinutes & DW_VALUE_FOREVER) &&
  556. lMin == 0)
  557. {
  558. lMin = 1;
  559. }
  560. CString strFormat;
  561. strFormat.LoadString(IDS_RANGE);
  562. strRange.Format(strFormat,lMin,m_nHigh);
  563. uiVal = GetDlgItemInt(IDC_VALUE, &bTrans, TRUE);
  564. lVal = uiVal;
  565. if (!bTrans)
  566. {
  567. CString str;
  568. if (m_cMinutes & DW_VALUE_FOREVER)
  569. {
  570. str.LoadString(IDS_FOREVER);
  571. if (str == m_strValue)
  572. {
  573. return TRUE;
  574. }
  575. }
  576. lVal = _ttol((LPCTSTR)m_strValue);
  577. if (lVal == 0)
  578. {
  579. // nonnumeric
  580. lVal = (LONG) m_nSave;
  581. m_strError = strRange;
  582. UpdateData(FALSE);
  583. return FALSE;
  584. }
  585. }
  586. if (m_iAccRate > 1 && lVal > 0)
  587. {
  588. // for log max size, make it multiples of m_iAccRate
  589. int nCount = lVal % m_iAccRate;
  590. if ( nCount > 0 )
  591. {
  592. lVal = ((LONG)(lVal/m_iAccRate))*m_iAccRate;
  593. }
  594. }
  595. if (lVal > m_nHigh)
  596. {
  597. m_strError = strRange;
  598. UpdateData(FALSE);
  599. return FALSE;
  600. }
  601. if ((lVal < m_nLow) &&
  602. (lVal != SCE_KERBEROS_OFF_VALUE) &&
  603. (lVal != SCE_FOREVER_VALUE))
  604. {
  605. // if it is underflow, go back to high
  606. if (m_cMinutes & DW_VALUE_OFF)
  607. {
  608. lVal = SCE_KERBEROS_OFF_VALUE;
  609. }
  610. else if (m_cMinutes & DW_VALUE_FOREVER)
  611. {
  612. lVal = SCE_FOREVER_VALUE;
  613. }
  614. else
  615. {
  616. // Leave alone and let the OnKillActive catch it
  617. }
  618. }
  619. if ((lVal < m_nLow) &&
  620. (lVal != SCE_KERBEROS_OFF_VALUE) &&
  621. (lVal != SCE_FOREVER_VALUE))
  622. {
  623. // if it is underflow, go back to high
  624. m_strError = strRange;
  625. UpdateData(FALSE);
  626. return FALSE;
  627. }
  628. if (0 == lVal && (m_cMinutes & DW_VALUE_NOZERO))
  629. {
  630. // zero is not allowed
  631. m_strError = strRange;
  632. UpdateData(FALSE);
  633. return FALSE;
  634. }
  635. return CAttribute::OnKillActive();
  636. }