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.

2783 lines
76 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // RulesUI.cpp
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6. #include <pch.hxx>
  7. #include "rulesui.h"
  8. #include "aplyrule.h"
  9. #include "editrule.h"
  10. #include "ruledesc.h"
  11. #include "ruleutil.h"
  12. #include "rulesmgr.h"
  13. #include "rule.h"
  14. #include "spamui.h"
  15. #include "reutil.h"
  16. #include <rulesdlg.h>
  17. #include <imagelst.h>
  18. #include <newfldr.h>
  19. #include <instance.h>
  20. #include "shlwapip.h"
  21. #include <demand.h>
  22. // Constants
  23. class COEMailRulesPageUI : public COERulesPageUI
  24. {
  25. private:
  26. enum MOVE_DIR {MOVE_RULE_UP = 0, MOVE_RULE_DOWN = 1};
  27. private:
  28. HWND m_hwndOwner;
  29. HWND m_hwndDlg;
  30. HWND m_hwndList;
  31. HWND m_hwndDescript;
  32. RULE_TYPE m_typeRule;
  33. CRuleDescriptUI * m_pDescriptUI;
  34. public:
  35. COEMailRulesPageUI();
  36. enum INIT_TYPE
  37. {
  38. INIT_MAIL = 0x00000000,
  39. INIT_NEWS = 0x00000001
  40. };
  41. COEMailRulesPageUI(DWORD dwFlagsInit) :
  42. COERulesPageUI(iddRulesMail,
  43. (0 != (dwFlagsInit & INIT_NEWS)) ? idsRulesNews : idsRulesMail, 0, 0),
  44. m_hwndOwner(NULL), m_hwndDlg(NULL), m_hwndList(NULL),
  45. m_hwndDescript(NULL),
  46. m_typeRule((0 != (dwFlagsInit & INIT_NEWS)) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL),
  47. m_pDescriptUI(NULL) {}
  48. virtual ~COEMailRulesPageUI();
  49. virtual HRESULT HrInit(HWND hwndOwner, DWORD dwFlags);
  50. virtual HRESULT HrCommitChanges(DWORD dwFlags, BOOL fClearDirty);
  51. static INT_PTR CALLBACK FMailRulesPageDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  52. DLGPROC DlgProcGetPageDlgProc(VOID) {return FMailRulesPageDlgProc;}
  53. BOOL FGetRules(RULE_TYPE typeRule, RULENODE ** pprnode);
  54. // Message handling methods
  55. BOOL FOnInitDialog(HWND hwndDlg);
  56. BOOL FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl);
  57. BOOL FOnNotify(INT iCtl, NMHDR * pnmhdr);
  58. BOOL FOnDestroy(VOID);
  59. private:
  60. BOOL _FInitListCtrl(VOID);
  61. BOOL _FLoadListCtrl(VOID);
  62. BOOL _FAddRuleToList(DWORD dwIndex, RULEID ridRule, IOERule * pIRule);
  63. VOID _EnableButtons(INT iSelected);
  64. VOID _EnableRule(INT iSelected);
  65. // For dealing with the description field
  66. VOID _LoadRule(INT iSelected);
  67. BOOL _FSaveRule(INT iSelected);
  68. // Functions to deal with the basic actions
  69. VOID _NewRule(VOID);
  70. VOID _EditRule(INT iSelected);
  71. VOID _MoveRule(INT iSelected, MOVE_DIR dir);
  72. VOID _RemoveRule(INT iSelected);
  73. VOID _CopyRule(INT iSelected);
  74. VOID _OnApplyTo(INT iSelected);
  75. BOOL _FOnLabelEdit(BOOL fBegin, NMLVDISPINFO * pdi);
  76. BOOL _FOnRuleDescValid(VOID);
  77. };
  78. // Global data
  79. const static HELPMAP g_rgCtxMapRulesMgr[] = {
  80. {0, 0}};
  81. const static HELPMAP g_rgCtxMapMailRules[] = {
  82. {idbNewRule, idhNewRule},
  83. {idbModifyRule, idhModifyRule},
  84. {idbCopyRule, idhCopyRule},
  85. {idbDeleteRule, idhRemoveRule},
  86. {idbRulesApplyTo, idhRuleApply},
  87. {idbMoveUpRule, idhRuleUp},
  88. {idbMoveDownRule, idhRuleDown},
  89. {idredtRuleDescription, idhRuleDescription},
  90. {0, 0}};
  91. COERulesMgrUI::COERulesMgrUI() : m_hwndOwner(NULL), m_dwFlags(0), m_dwState(0), m_hwndDlg(NULL), m_hwndTab(NULL)
  92. {
  93. ZeroMemory(m_rgRuleTab, sizeof(m_rgRuleTab));
  94. }
  95. COERulesMgrUI::~COERulesMgrUI()
  96. {
  97. ULONG ulIndex = 0;
  98. for (ulIndex = 0; ulIndex < RULE_PAGE_MAX; ulIndex++)
  99. {
  100. if (NULL != m_rgRuleTab[ulIndex])
  101. {
  102. delete m_rgRuleTab[ulIndex];
  103. }
  104. }
  105. }
  106. HRESULT COERulesMgrUI::HrInit(HWND hwndOwner, DWORD dwFlags)
  107. {
  108. HRESULT hr = S_OK;
  109. // Check incoming params
  110. if (NULL == hwndOwner)
  111. {
  112. hr = E_INVALIDARG;
  113. goto exit;
  114. }
  115. if (0 != (m_dwState & STATE_INITIALIZED))
  116. {
  117. hr = E_UNEXPECTED;
  118. goto exit;
  119. }
  120. m_hwndOwner = hwndOwner;
  121. m_dwFlags = dwFlags;
  122. // Create each of the rule pages
  123. if (!(g_dwAthenaMode & MODE_NEWSONLY))
  124. {
  125. // Create the mail page
  126. m_rgRuleTab[RULE_PAGE_MAIL] = new COEMailRulesPageUI(COEMailRulesPageUI::INIT_MAIL);
  127. if (NULL == m_rgRuleTab[RULE_PAGE_MAIL])
  128. {
  129. hr = E_OUTOFMEMORY;
  130. goto exit;
  131. }
  132. }
  133. // Create the news page
  134. m_rgRuleTab[RULE_PAGE_NEWS] = new COEMailRulesPageUI(COEMailRulesPageUI::INIT_NEWS);
  135. if (NULL == m_rgRuleTab[RULE_PAGE_NEWS])
  136. {
  137. hr = E_OUTOFMEMORY;
  138. goto exit;
  139. }
  140. // Create the junk page
  141. if ((0 == (g_dwAthenaMode & MODE_NEWSONLY)) && (0 != (g_dwAthenaMode & MODE_JUNKMAIL)))
  142. {
  143. m_rgRuleTab[RULE_PAGE_JUNK] = new COEJunkRulesPageUI();
  144. if (NULL == m_rgRuleTab[RULE_PAGE_JUNK])
  145. {
  146. hr = E_OUTOFMEMORY;
  147. goto exit;
  148. }
  149. }
  150. // Create the senders page
  151. m_rgRuleTab[RULE_PAGE_SENDERS] = new COESendersRulesPageUI();
  152. if (NULL == m_rgRuleTab[RULE_PAGE_SENDERS])
  153. {
  154. hr = E_OUTOFMEMORY;
  155. goto exit;
  156. }
  157. m_dwState |= STATE_INITIALIZED;
  158. hr = S_OK;
  159. exit:
  160. return hr;
  161. }
  162. HRESULT COERulesMgrUI::HrShow(VOID)
  163. {
  164. HRESULT hr = S_OK;
  165. int iRet = 0;
  166. if (0 == (m_dwState & STATE_INITIALIZED))
  167. {
  168. hr = E_UNEXPECTED;
  169. goto exit;
  170. }
  171. // We need to load richedit
  172. if (FALSE == FInitRichEdit(TRUE))
  173. {
  174. hr = E_FAIL;
  175. goto exit;
  176. }
  177. iRet = (INT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRulesManager),
  178. m_hwndOwner, COERulesMgrUI::FOERuleMgrDlgProc,
  179. (LPARAM) this);
  180. if (-1 == iRet)
  181. {
  182. hr = E_FAIL;
  183. goto exit;
  184. }
  185. // Set the proper return code
  186. hr = (IDOK == iRet) ? S_OK : S_FALSE;
  187. exit:
  188. return hr;
  189. }
  190. INT_PTR CALLBACK COERulesMgrUI::FOERuleMgrDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  191. {
  192. BOOL fRet = FALSE;
  193. COERulesMgrUI * pRulesUI = NULL;
  194. pRulesUI = (COERulesMgrUI *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  195. switch (uiMsg)
  196. {
  197. case WM_INITDIALOG:
  198. // Grab the UI object pointer
  199. pRulesUI = (COERulesMgrUI *) lParam;
  200. // Set it into the dialog so we can get it back
  201. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pRulesUI);
  202. if (FALSE == pRulesUI->FOnInitDialog(hwndDlg))
  203. {
  204. EndDialog(hwndDlg, -1);
  205. fRet = TRUE;
  206. goto exit;
  207. }
  208. // We set the focus
  209. fRet = FALSE;
  210. break;
  211. case WM_COMMAND:
  212. fRet = pRulesUI->FOnCommand((UINT) HIWORD(wParam), (INT) LOWORD(wParam), (HWND) lParam);
  213. break;
  214. case WM_NOTIFY:
  215. fRet = pRulesUI->FOnNotify((INT) LOWORD(wParam), (NMHDR *) lParam);
  216. break;
  217. case WM_DESTROY:
  218. fRet = pRulesUI->FOnDestroy();
  219. break;
  220. case WM_OE_GET_RULES:
  221. fRet = pRulesUI->FOnGetRules((RULE_TYPE) wParam, (RULENODE **) lParam);
  222. break;
  223. case WM_HELP:
  224. case WM_CONTEXTMENU:
  225. fRet = OnContextHelp(hwndDlg, uiMsg, wParam, lParam, g_rgCtxMapRulesMgr);
  226. break;
  227. }
  228. exit:
  229. return fRet;
  230. }
  231. BOOL COERulesMgrUI::FOnInitDialog(HWND hwndDlg)
  232. {
  233. BOOL fRet = FALSE;
  234. HRESULT hr = S_OK;
  235. // Check incoming params
  236. if (NULL == hwndDlg)
  237. {
  238. fRet = FALSE;
  239. goto exit;
  240. }
  241. // Save off the dialog window handle
  242. m_hwndDlg = hwndDlg;
  243. // Set the default font onto the dialog
  244. SetIntlFont(m_hwndDlg);
  245. // Save off some of the controls
  246. m_hwndTab = GetDlgItem(hwndDlg, idtbRulesTab);
  247. if (NULL == m_hwndTab)
  248. {
  249. fRet = FALSE;
  250. goto exit;
  251. }
  252. // Initialize tab control
  253. fRet = _FInitTabCtrl();
  254. if (FALSE == fRet)
  255. {
  256. goto exit;
  257. }
  258. // Everything's AOK
  259. fRet = TRUE;
  260. exit:
  261. return fRet;
  262. }
  263. BOOL COERulesMgrUI::FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl)
  264. {
  265. BOOL fRet = FALSE;
  266. INT iSel = 0;
  267. TCITEM tcitem = {0};
  268. switch (iCtl)
  269. {
  270. case IDOK:
  271. if (FALSE != _FOnOK())
  272. {
  273. EndDialog(m_hwndDlg, IDOK);
  274. fRet = TRUE;
  275. }
  276. break;
  277. case IDCANCEL:
  278. EndDialog(m_hwndDlg, IDCANCEL);
  279. fRet = TRUE;
  280. break;
  281. default:
  282. iSel = TabCtrl_GetCurSel(m_hwndTab);
  283. if (-1 == iSel)
  284. {
  285. fRet = FALSE;
  286. goto exit;
  287. }
  288. tcitem.mask = TCIF_PARAM;
  289. if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem))
  290. {
  291. fRet = FALSE;
  292. goto exit;
  293. }
  294. fRet = !!SendMessage((HWND) (tcitem.lParam), WM_COMMAND, MAKEWPARAM(iCtl, uiNotify), (LPARAM) hwndCtl);
  295. break;
  296. }
  297. exit:
  298. return fRet;
  299. }
  300. BOOL COERulesMgrUI::FOnNotify(INT iCtl, NMHDR * pnmhdr)
  301. {
  302. BOOL fRet = FALSE;
  303. INT iSel = 0;
  304. TCITEM tcitem = {0};
  305. HWND hwndDlg = NULL;
  306. HWND hwndFocus = NULL;
  307. switch (pnmhdr->code)
  308. {
  309. case TCN_SELCHANGING:
  310. // Get the window handle for the currently
  311. // selected tab
  312. iSel = TabCtrl_GetCurSel(m_hwndTab);
  313. if (-1 == iSel)
  314. {
  315. fRet = FALSE;
  316. goto exit;
  317. }
  318. tcitem.mask = TCIF_PARAM;
  319. if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem))
  320. {
  321. fRet = FALSE;
  322. goto exit;
  323. }
  324. hwndDlg = (HWND) tcitem.lParam;
  325. Assert(NULL != hwndDlg);
  326. // Hide and disable the current dialog
  327. ShowWindow(hwndDlg, SW_HIDE);
  328. EnableWindow(hwndDlg, FALSE);
  329. SetDlgMsgResult(hwndDlg, WM_NOTIFY, FALSE);
  330. fRet = TRUE;
  331. break;
  332. case TCN_SELCHANGE:
  333. // Get the window handle for the currently
  334. // selected tab
  335. iSel = TabCtrl_GetCurSel(m_hwndTab);
  336. if (-1 == iSel)
  337. {
  338. fRet = FALSE;
  339. goto exit;
  340. }
  341. tcitem.mask = TCIF_PARAM;
  342. if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem))
  343. {
  344. fRet = FALSE;
  345. goto exit;
  346. }
  347. hwndDlg = (HWND) tcitem.lParam;
  348. Assert(NULL != hwndDlg);
  349. // Hide and disable the current dialog
  350. ShowWindow(hwndDlg, SW_SHOW);
  351. EnableWindow(hwndDlg, TRUE);
  352. // Set the focus to the first control
  353. // if the focus isn't in the tab
  354. hwndFocus = GetFocus();
  355. if (hwndFocus != m_hwndTab)
  356. {
  357. SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetNextDlgTabItem(hwndDlg, NULL, FALSE), (LPARAM) TRUE);
  358. }
  359. fRet = TRUE;
  360. break;
  361. }
  362. exit:
  363. return fRet;
  364. }
  365. BOOL COERulesMgrUI::FOnDestroy(VOID)
  366. {
  367. BOOL fRet = FALSE;
  368. UINT cTabs = 0;
  369. UINT uiIndex = 0;
  370. TC_ITEM tcitem;
  371. // Get the number of tabs
  372. cTabs = TabCtrl_GetItemCount(m_hwndTab);
  373. // Initialize the Tab control structure...
  374. ZeroMemory(&tcitem, sizeof(tcitem));
  375. tcitem.mask = TCIF_PARAM;
  376. // Destroy the dialogs from each page
  377. for (uiIndex = 0; uiIndex < cTabs; uiIndex++)
  378. {
  379. // Get the window handle for the dialog
  380. if (FALSE != TabCtrl_GetItem(m_hwndTab, uiIndex, &tcitem))
  381. {
  382. // Destroy the dialog
  383. DestroyWindow((HWND) tcitem.lParam);
  384. }
  385. }
  386. fRet = TRUE;
  387. return fRet;
  388. }
  389. BOOL COERulesMgrUI::FOnGetRules(RULE_TYPE typeRule, RULENODE ** pprnode)
  390. {
  391. BOOL fRet = FALSE;
  392. RULENODE * prnodeList = NULL;
  393. RULENODE * prnodeSender = NULL;
  394. RULENODE * prnodeJunk = NULL;
  395. RULENODE * prnodeWalk = NULL;
  396. if (NULL == pprnode)
  397. {
  398. fRet = FALSE;
  399. goto exit;
  400. }
  401. // Initialize the outgoing param
  402. *pprnode = NULL;
  403. // Forward the message to the correct dialog
  404. switch(typeRule)
  405. {
  406. case RULE_TYPE_MAIL:
  407. // Get the rules from the senders page
  408. if (NULL != m_rgRuleTab[RULE_PAGE_SENDERS])
  409. {
  410. fRet = m_rgRuleTab[RULE_PAGE_SENDERS]->FGetRules(RULE_TYPE_MAIL, &prnodeSender);
  411. }
  412. // Get the rules from the mail rules page
  413. if (NULL != m_rgRuleTab[RULE_PAGE_MAIL])
  414. {
  415. fRet = m_rgRuleTab[RULE_PAGE_MAIL]->FGetRules(RULE_TYPE_MAIL, &prnodeList);
  416. }
  417. // Get the rules from the junk mail page
  418. if (NULL != m_rgRuleTab[RULE_PAGE_JUNK])
  419. {
  420. fRet = m_rgRuleTab[RULE_PAGE_JUNK]->FGetRules(RULE_TYPE_MAIL, &prnodeJunk);
  421. }
  422. break;
  423. case RULE_TYPE_NEWS:
  424. // Get the rules from the senders page
  425. if (NULL != m_rgRuleTab[RULE_PAGE_SENDERS])
  426. {
  427. fRet = m_rgRuleTab[RULE_PAGE_SENDERS]->FGetRules(RULE_TYPE_NEWS, &prnodeSender);
  428. }
  429. // Get the rules from the news rules page
  430. if (NULL != m_rgRuleTab[RULE_PAGE_NEWS])
  431. {
  432. fRet = m_rgRuleTab[RULE_PAGE_NEWS]->FGetRules(RULE_TYPE_NEWS, &prnodeList);
  433. }
  434. break;
  435. default:
  436. Assert(FALSE);
  437. fRet = FALSE;
  438. goto exit;
  439. break;
  440. }
  441. // Set up the list
  442. if (NULL != prnodeJunk)
  443. {
  444. Assert(NULL == prnodeJunk->pNext);
  445. if (NULL == prnodeList)
  446. {
  447. prnodeList = prnodeJunk;
  448. }
  449. else
  450. {
  451. prnodeWalk = prnodeList;
  452. while (NULL != prnodeWalk->pNext)
  453. {
  454. prnodeWalk = prnodeWalk->pNext;
  455. }
  456. prnodeWalk->pNext = prnodeJunk;
  457. }
  458. prnodeJunk = NULL;
  459. }
  460. if (NULL != prnodeSender)
  461. {
  462. Assert(NULL == prnodeSender->pNext);
  463. prnodeSender->pNext = prnodeList;
  464. prnodeList = prnodeSender;
  465. prnodeSender = NULL;
  466. }
  467. // Set the outgoing param
  468. *pprnode = prnodeList;
  469. prnodeList = NULL;
  470. // Tell the dialog it's aok to proceed
  471. SetDlgMsgResult(m_hwndDlg, WM_OE_GET_RULES, TRUE);
  472. fRet = TRUE;
  473. exit:
  474. while (NULL != prnodeList)
  475. {
  476. prnodeWalk = prnodeList;
  477. if (NULL != prnodeWalk->pIRule)
  478. {
  479. prnodeWalk->pIRule->Release();
  480. }
  481. prnodeList = prnodeList->pNext;
  482. delete prnodeWalk; //MemFree(prnodeWalk);
  483. }
  484. if (NULL != prnodeJunk)
  485. {
  486. if (NULL != prnodeJunk->pIRule)
  487. {
  488. prnodeJunk->pIRule->Release();
  489. }
  490. delete prnodeJunk; // MemFree(prnodeJunk);
  491. }
  492. if (NULL != prnodeSender)
  493. {
  494. if (NULL != prnodeSender->pIRule)
  495. {
  496. prnodeSender->pIRule->Release();
  497. }
  498. delete prnodeSender; //MemFree(prnodeSender);
  499. }
  500. return fRet;
  501. }
  502. BOOL COERulesMgrUI::_FOnOK(VOID)
  503. {
  504. BOOL fRet = FALSE;
  505. UINT uiRuleTab = 0;
  506. HRESULT hr = S_OK;
  507. // Add the tabs to the tab control
  508. for (uiRuleTab = 0; uiRuleTab < RULE_PAGE_MAX; uiRuleTab++)
  509. {
  510. if (NULL == m_rgRuleTab[uiRuleTab])
  511. {
  512. continue;
  513. }
  514. hr = m_rgRuleTab[uiRuleTab]->HrCommitChanges(0, TRUE);
  515. if ((FAILED(hr)) && (E_UNEXPECTED != hr))
  516. {
  517. fRet = FALSE;
  518. goto exit;
  519. }
  520. }
  521. fRet = TRUE;
  522. exit:
  523. return fRet;
  524. }
  525. BOOL COERulesMgrUI::_FOnCancel(VOID)
  526. {
  527. return TRUE;
  528. }
  529. BOOL COERulesMgrUI::_FInitTabCtrl(VOID)
  530. {
  531. BOOL fRet = FALSE;
  532. TCITEM tcitem;
  533. TCHAR szRes[CCHMAX_STRINGRES];
  534. UINT uiRuleTab = 0;
  535. HWND hwndDlg = NULL;
  536. UINT cRuleTab = 0;
  537. UINT uiDefaultTab = 0;
  538. NMHDR nmhdr;
  539. // Make sure we have a resource dll
  540. Assert(g_hLocRes);
  541. // Initialize the Tab control structure...
  542. ZeroMemory(&tcitem, sizeof(tcitem));
  543. tcitem.mask = TCIF_PARAM | TCIF_TEXT;
  544. tcitem.pszText = szRes;
  545. tcitem.iImage = -1;
  546. // Add the tabs to the tab control
  547. for (uiRuleTab = 0; uiRuleTab < RULE_PAGE_MAX; uiRuleTab++)
  548. {
  549. // Initialize each of the pages
  550. if ((NULL == m_rgRuleTab[uiRuleTab]) || (FAILED(m_rgRuleTab[uiRuleTab]->HrInit(m_hwndDlg, m_dwFlags))))
  551. {
  552. continue;
  553. }
  554. // Create the child dialog for the tab
  555. hwndDlg = CreateDialogParam(g_hLocRes, MAKEINTRESOURCE(m_rgRuleTab[uiRuleTab]->UiGetDlgRscId()),
  556. m_hwndDlg, m_rgRuleTab[uiRuleTab]->DlgProcGetPageDlgProc(),
  557. (LPARAM) (m_rgRuleTab[uiRuleTab]));
  558. if (NULL == hwndDlg)
  559. {
  560. continue;
  561. }
  562. tcitem.lParam = (LPARAM) hwndDlg;
  563. // Load in the display string for the tab
  564. LoadString(g_hLocRes, m_rgRuleTab[uiRuleTab]->UiGetTabLabelId(), szRes, ARRAYSIZE(szRes));
  565. // Insert the tab
  566. TabCtrl_InsertItem(m_hwndTab, cRuleTab, &tcitem);
  567. // Save off the default tab
  568. if (uiRuleTab == (m_dwFlags & RULE_PAGE_MASK))
  569. {
  570. uiDefaultTab = cRuleTab;
  571. }
  572. cRuleTab++;
  573. }
  574. if (0 == cRuleTab)
  575. {
  576. fRet = FALSE;
  577. goto exit;
  578. }
  579. // Select the proper tab
  580. if (-1 != TabCtrl_SetCurSel(m_hwndTab, uiDefaultTab))
  581. {
  582. nmhdr.hwndFrom = m_hwndTab;
  583. nmhdr.idFrom = idtbRulesTab;
  584. nmhdr.code = TCN_SELCHANGE;
  585. SideAssert(FALSE != FOnNotify(idtbRulesTab, &nmhdr));
  586. }
  587. // Need to set the tab control to the bottom of the Z-order
  588. // to prevent overlapping redraws
  589. SetWindowPos(m_hwndTab, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  590. // We worked
  591. fRet = TRUE;
  592. exit:
  593. return fRet;
  594. }
  595. // Default destructor for the Mail Rules UI
  596. COEMailRulesPageUI::~COEMailRulesPageUI()
  597. {
  598. if (NULL != m_pDescriptUI)
  599. {
  600. delete m_pDescriptUI;
  601. }
  602. }
  603. ///////////////////////////////////////////////////////////////////////////////
  604. //
  605. // HrInit
  606. //
  607. // This initializes the mail rules UI dialog
  608. //
  609. // hwndOwner - the handle to the owner window of this dialog
  610. // dwFlags - modifiers on how this dialog should act
  611. //
  612. // Returns: S_OK, if it was successfully initialized
  613. //
  614. ///////////////////////////////////////////////////////////////////////////////
  615. HRESULT COEMailRulesPageUI::HrInit(HWND hwndOwner, DWORD dwFlags)
  616. {
  617. HRESULT hr = S_OK;
  618. // Check incoming params
  619. if (NULL == hwndOwner)
  620. {
  621. hr = E_INVALIDARG;
  622. goto exit;
  623. }
  624. if (0 != (m_dwState & STATE_INITIALIZED))
  625. {
  626. hr = E_UNEXPECTED;
  627. goto exit;
  628. }
  629. m_hwndOwner = hwndOwner;
  630. m_dwFlags = dwFlags;
  631. // Setup the description field
  632. m_pDescriptUI = new CRuleDescriptUI;
  633. if (NULL == m_pDescriptUI)
  634. {
  635. hr = E_OUTOFMEMORY;
  636. goto exit;
  637. }
  638. m_dwState |= STATE_INITIALIZED;
  639. hr = S_OK;
  640. exit:
  641. return hr;
  642. }
  643. ///////////////////////////////////////////////////////////////////////////////
  644. //
  645. // HrCommitChanges
  646. //
  647. // This commits the changes to the rules
  648. //
  649. // dwFlags - modifiers on how we should commit the changes
  650. // fClearDirty - should we clear the dirty state
  651. //
  652. // Returns: S_OK, if it was successfully committed
  653. //
  654. ///////////////////////////////////////////////////////////////////////////////
  655. HRESULT COEMailRulesPageUI::HrCommitChanges(DWORD dwFlags, BOOL fClearDirty)
  656. {
  657. HRESULT hr = S_OK;
  658. LONG cRules = 0;
  659. INT iSelected = 0;
  660. RULEINFO * pinfoRule = NULL;
  661. ULONG cpinfoRule = 0;
  662. LVITEM lvitem = {0};
  663. Assert(NULL != m_hwndList);
  664. // Check incoming params
  665. if (0 != dwFlags)
  666. {
  667. hr = E_INVALIDARG;
  668. goto exit;
  669. }
  670. // Fail if we weren't initialized
  671. if (0 == (m_dwState & STATE_INITIALIZED))
  672. {
  673. hr = E_UNEXPECTED;
  674. goto exit;
  675. }
  676. // If we aren't dirty, then there's
  677. // nothing to do
  678. if ((0 == (m_dwState & STATE_DIRTY)) && (S_OK != m_pDescriptUI->HrIsDirty()))
  679. {
  680. hr = S_FALSE;
  681. goto exit;
  682. }
  683. // Get the number of rules in the list view
  684. cRules = ListView_GetItemCount(m_hwndList);
  685. if (0 != cRules)
  686. {
  687. // Let's make sure the selected rule is saved...
  688. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  689. if (-1 != iSelected)
  690. {
  691. _FSaveRule(iSelected);
  692. }
  693. // Allocate space to hold the rules
  694. hr = HrAlloc( (void **) &pinfoRule, cRules * sizeof(*pinfoRule));
  695. if (FAILED(hr))
  696. {
  697. goto exit;
  698. }
  699. ZeroMemory(pinfoRule, cRules * sizeof(*pinfoRule));
  700. lvitem.mask = LVIF_PARAM;
  701. cpinfoRule = 0;
  702. for (lvitem.iItem = 0; lvitem.iItem < cRules; lvitem.iItem++)
  703. {
  704. // Grab the rule from the list view
  705. if (FALSE != ListView_GetItem(m_hwndList, &lvitem))
  706. {
  707. if (NULL == lvitem.lParam)
  708. {
  709. continue;
  710. }
  711. pinfoRule[cpinfoRule] = *((RULEINFO *) (lvitem.lParam));
  712. cpinfoRule++;
  713. }
  714. }
  715. }
  716. // Set the rules into the rules manager
  717. hr = g_pRulesMan->SetRules(SETF_CLEAR, m_typeRule, pinfoRule, cpinfoRule);
  718. if (FAILED(hr))
  719. {
  720. goto exit;
  721. }
  722. // Should we clear the dirty state
  723. if (FALSE != fClearDirty)
  724. {
  725. m_dwState &= ~STATE_DIRTY;
  726. }
  727. hr = S_OK;
  728. exit:
  729. SafeMemFree(pinfoRule);
  730. return hr;
  731. }
  732. INT_PTR CALLBACK COEMailRulesPageUI::FMailRulesPageDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  733. {
  734. BOOL fRet = FALSE;
  735. COEMailRulesPageUI * pMailUI = NULL;
  736. HWND hwndRE = 0;
  737. pMailUI = (COEMailRulesPageUI *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  738. switch (uiMsg)
  739. {
  740. case WM_INITDIALOG:
  741. // Grab the UI object pointer
  742. pMailUI = (COEMailRulesPageUI *) lParam;
  743. // Set it into the dialog so we can get it back
  744. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pMailUI);
  745. hwndRE = CreateREInDialogA(hwndDlg, idredtRuleDescription);
  746. if (!hwndRE || (FALSE == pMailUI->FOnInitDialog(hwndDlg)))
  747. {
  748. EndDialog(hwndDlg, -1);
  749. fRet = TRUE;
  750. goto exit;
  751. }
  752. // We didn't set the focus so return TRUE
  753. fRet = TRUE;
  754. break;
  755. case WM_COMMAND:
  756. fRet = pMailUI->FOnCommand((UINT) HIWORD(wParam), (INT) LOWORD(wParam), (HWND) lParam);
  757. break;
  758. case WM_NOTIFY:
  759. fRet = pMailUI->FOnNotify((INT) LOWORD(wParam), (NMHDR *) lParam);
  760. break;
  761. case WM_DESTROY:
  762. fRet = pMailUI->FOnDestroy();
  763. break;
  764. case WM_HELP:
  765. case WM_CONTEXTMENU:
  766. fRet = OnContextHelp(hwndDlg, uiMsg, wParam, lParam, g_rgCtxMapMailRules);
  767. break;
  768. }
  769. exit:
  770. return fRet;
  771. }
  772. ///////////////////////////////////////////////////////////////////////////////
  773. //
  774. // FGetRules
  775. //
  776. // This brings up the edit UI for the selected rule from the mail rules list
  777. //
  778. // fBegin - is this for the LVN_BEGINLABELEDIT notification
  779. // pdi - the display info for the message
  780. //
  781. // Returns: TRUE, if the message was handled
  782. // FALSE, otherwise
  783. //
  784. ///////////////////////////////////////////////////////////////////////////////
  785. BOOL COEMailRulesPageUI::FGetRules(RULE_TYPE typeRule, RULENODE ** pprnode)
  786. {
  787. BOOL fRet = FALSE;
  788. INT iSelected = 0;
  789. INT cRules = 0;
  790. LVITEM lvitem;
  791. IOERule * pIRule = NULL;
  792. RULENODE * prnodeNew = NULL;
  793. RULENODE * prnodeList = NULL;
  794. RULENODE * prnodeWalk = NULL;
  795. HRESULT hr = S_OK;
  796. RULEINFO * pinfoRule = NULL;
  797. Assert(NULL != m_hwndList);
  798. if (NULL == pprnode)
  799. {
  800. fRet = FALSE;
  801. goto exit;
  802. }
  803. // Fail if we weren't initialized
  804. if ((0 == (m_dwState & STATE_INITIALIZED)) || (NULL == m_hwndList))
  805. {
  806. fRet = FALSE;
  807. goto exit;
  808. }
  809. // Initialize the outgoing param
  810. *pprnode = NULL;
  811. // Get the selected item
  812. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  813. // Make sure we don't loose any changes
  814. _FSaveRule(iSelected);
  815. // Check the count of items in the list view
  816. cRules = ListView_GetItemCount(m_hwndList);
  817. if (0 == cRules)
  818. {
  819. fRet = TRUE;
  820. goto exit;
  821. }
  822. // Initialize the list view item
  823. ZeroMemory(&lvitem, sizeof(lvitem));
  824. lvitem.mask = LVIF_PARAM | LVIF_STATE;
  825. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  826. // Create the list of rules
  827. for (lvitem.iItem = 0; lvitem.iItem < cRules; lvitem.iItem++)
  828. {
  829. // Grab the rule from the listview
  830. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  831. {
  832. fRet = FALSE;
  833. goto exit;
  834. }
  835. pinfoRule = (RULEINFO *) (lvitem.lParam);
  836. if ((NULL == pinfoRule) || (NULL == pinfoRule->pIRule))
  837. {
  838. continue;
  839. }
  840. // Skip over invalid rules
  841. hr = pinfoRule->pIRule->Validate(0);
  842. if (FAILED(hr) || (S_FALSE == hr))
  843. {
  844. continue;
  845. }
  846. // Create a new rule node
  847. prnodeNew = new RULENODE;
  848. if (NULL == prnodeNew)
  849. {
  850. fRet = FALSE;
  851. goto exit;
  852. }
  853. prnodeNew->pNext = NULL;
  854. prnodeNew->pIRule = pinfoRule->pIRule;
  855. prnodeNew->pIRule->AddRef();
  856. // Add the new node to the list
  857. if (NULL == prnodeWalk)
  858. {
  859. prnodeList = prnodeNew;
  860. }
  861. else
  862. {
  863. prnodeWalk->pNext = prnodeNew;
  864. }
  865. prnodeWalk = prnodeNew;
  866. prnodeNew = NULL;
  867. }
  868. // Set the outgoing param
  869. *pprnode = prnodeList;
  870. prnodeList = NULL;
  871. fRet = TRUE;
  872. exit:
  873. while (NULL != prnodeList)
  874. {
  875. prnodeWalk = prnodeList;
  876. if (NULL != prnodeWalk->pIRule)
  877. {
  878. prnodeWalk->pIRule->Release();
  879. }
  880. prnodeList = prnodeList->pNext;
  881. delete prnodeWalk; //MemFree(prnodeWalk);
  882. }
  883. return fRet;
  884. }
  885. ///////////////////////////////////////////////////////////////////////////////
  886. //
  887. // FOnInitDialog
  888. //
  889. // This handles the WM_INITDIALOG message for the mail rules UI dialog
  890. //
  891. // hwndDlg - the handle to the dialog window
  892. //
  893. // Returns: TRUE, if it was successfully initialized
  894. // FALSE, otherwise
  895. //
  896. ///////////////////////////////////////////////////////////////////////////////
  897. BOOL COEMailRulesPageUI::FOnInitDialog(HWND hwndDlg)
  898. {
  899. BOOL fRet = FALSE;
  900. HRESULT hr = S_OK;
  901. TCHAR szRes[CCHMAX_STRINGRES];
  902. // Check incoming params
  903. if (NULL == hwndDlg)
  904. {
  905. fRet = FALSE;
  906. goto exit;
  907. }
  908. // If we haven't been initialized yet...
  909. if (0 == (m_dwState & STATE_INITIALIZED))
  910. {
  911. fRet = FALSE;
  912. goto exit;
  913. }
  914. // Save off the dialog window handle
  915. m_hwndDlg = hwndDlg;
  916. // Set the default font onto the dialog
  917. SetIntlFont(m_hwndDlg);
  918. // Save off some of the controls
  919. m_hwndList = GetDlgItem(hwndDlg, idlvRulesList);
  920. m_hwndDescript = GetDlgItem(hwndDlg, idredtRuleDescription);
  921. if ((NULL == m_hwndList) || (NULL == m_hwndDescript))
  922. {
  923. fRet = FALSE;
  924. goto exit;
  925. }
  926. // We need to change the title if we are a news page
  927. if (RULE_TYPE_NEWS == m_typeRule)
  928. {
  929. if (0 == LoadString(g_hLocRes, idsRuleTitleNews, szRes, ARRAYSIZE(szRes)))
  930. {
  931. goto exit;
  932. }
  933. SetDlgItemText(m_hwndDlg, idcRuleTitle, szRes);
  934. }
  935. else
  936. {
  937. if (FALSE != FIsIMAPOrHTTPAvailable())
  938. {
  939. AthLoadString(idsRulesNoIMAP, szRes, sizeof(szRes));
  940. SetDlgItemText(m_hwndDlg, idcRuleTitle, szRes);
  941. }
  942. }
  943. if (FAILED(m_pDescriptUI->HrInit(m_hwndDescript, 0)))
  944. {
  945. fRet = FALSE;
  946. goto exit;
  947. }
  948. // Initialize the list view
  949. fRet = _FInitListCtrl();
  950. if (FALSE == fRet)
  951. {
  952. goto exit;
  953. }
  954. // Load the list view
  955. fRet = _FLoadListCtrl();
  956. if (FALSE == fRet)
  957. {
  958. goto exit;
  959. }
  960. // Check to see if the list is empty
  961. if (0 == ListView_GetItemCount(m_hwndList))
  962. {
  963. if (((m_typeRule == RULE_TYPE_MAIL) && (RMF_MAIL == m_dwFlags)) ||
  964. ((m_typeRule == RULE_TYPE_NEWS) && (RMF_NEWS == m_dwFlags)))
  965. {
  966. PostMessage(m_hwndDlg, WM_COMMAND, MAKEWPARAM(idbNewRule, 0), (LPARAM) (GetDlgItem(m_hwndDlg, idbNewRule)));
  967. }
  968. }
  969. // Everything's AOK
  970. fRet = TRUE;
  971. exit:
  972. return fRet;
  973. }
  974. ///////////////////////////////////////////////////////////////////////////////
  975. //
  976. // FOnCommand
  977. //
  978. // This handles the WM_COMMAND message for the mail rules UI dialog
  979. //
  980. // Returns: TRUE, if it was successfully handled
  981. // FALSE, otherwise
  982. //
  983. ///////////////////////////////////////////////////////////////////////////////
  984. BOOL COEMailRulesPageUI::FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl)
  985. {
  986. BOOL fRet = FALSE;
  987. LVITEM lvitem;
  988. INT iSelected = 0;
  989. // We only handle menu and accelerator commands
  990. if ((0 != uiNotify) && (1 != uiNotify))
  991. {
  992. fRet = FALSE;
  993. goto exit;
  994. }
  995. switch (iCtl)
  996. {
  997. case idbNewRule:
  998. _NewRule();
  999. fRet = TRUE;
  1000. break;
  1001. case idbModifyRule:
  1002. // Get the selected item from the rule list
  1003. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1004. if (-1 != iSelected)
  1005. {
  1006. // Bring up the rule editor for that item
  1007. _EditRule(iSelected);
  1008. fRet = TRUE;
  1009. }
  1010. break;
  1011. case idbMoveUpRule:
  1012. case idbMoveDownRule:
  1013. // Get the selected item from the rule list
  1014. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1015. if (-1 != iSelected)
  1016. {
  1017. // Move the rule in the desired direction
  1018. _MoveRule(iSelected, (idbMoveUpRule == iCtl) ? MOVE_RULE_UP : MOVE_RULE_DOWN);
  1019. fRet = TRUE;
  1020. }
  1021. break;
  1022. case idbDeleteRule:
  1023. // Get the selected item from the rule list
  1024. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1025. if (-1 != iSelected)
  1026. {
  1027. // Remove the rule from the list
  1028. _RemoveRule(iSelected);
  1029. fRet = TRUE;
  1030. }
  1031. break;
  1032. case idbCopyRule:
  1033. // Get the selected item from the rule list
  1034. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1035. if (-1 != iSelected)
  1036. {
  1037. // Copy the rule from the list
  1038. _CopyRule(iSelected);
  1039. fRet = TRUE;
  1040. }
  1041. break;
  1042. case idbRulesApplyTo:
  1043. // Apply the rule from the list
  1044. _OnApplyTo(ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED));
  1045. fRet = TRUE;
  1046. break;
  1047. }
  1048. exit:
  1049. return fRet;
  1050. }
  1051. ///////////////////////////////////////////////////////////////////////////////
  1052. //
  1053. // FOnNotify
  1054. //
  1055. // This handles the WM_NOTIFY message for the mail rules UI dialog
  1056. //
  1057. // Returns: TRUE, if it was successfully destroyed
  1058. // FALSE, otherwise
  1059. //
  1060. ///////////////////////////////////////////////////////////////////////////////
  1061. BOOL COEMailRulesPageUI::FOnNotify(INT iCtl, NMHDR * pnmhdr)
  1062. {
  1063. BOOL fRet = FALSE;
  1064. NMLISTVIEW * pnmlv = NULL;
  1065. NMLVKEYDOWN * pnmlvkd = NULL;
  1066. INT iSelected = 0;
  1067. LVHITTESTINFO lvh;
  1068. // We only handle notifications for the list control
  1069. // or the desscription field
  1070. if ((idlvRulesList != pnmhdr->idFrom) && (idredtRuleDescription != pnmhdr->idFrom))
  1071. {
  1072. fRet = FALSE;
  1073. goto exit;
  1074. }
  1075. pnmlv = (LPNMLISTVIEW) pnmhdr;
  1076. switch (pnmlv->hdr.code)
  1077. {
  1078. case NM_CLICK:
  1079. // Did we click on an item?
  1080. if (-1 != pnmlv->iItem)
  1081. {
  1082. ZeroMemory(&lvh, sizeof(lvh));
  1083. lvh.pt = pnmlv->ptAction;
  1084. iSelected = ListView_HitTest(m_hwndList, &lvh);
  1085. if (-1 != iSelected)
  1086. {
  1087. // Did we click on the enable field?
  1088. if ((0 != (lvh.flags & LVHT_ONITEMSTATEICON)) &&
  1089. (0 == (lvh.flags & LVHT_ONITEMLABEL)))
  1090. {
  1091. // Make sure this item is selected
  1092. ListView_SetItemState(m_hwndList, iSelected,
  1093. LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1094. // Set the proper enable state
  1095. _EnableRule(iSelected);
  1096. }
  1097. }
  1098. }
  1099. else
  1100. {
  1101. // We clicked outside the list
  1102. // Disable the buttons
  1103. _EnableButtons(pnmlv->iItem);
  1104. }
  1105. break;
  1106. case NM_DBLCLK:
  1107. // Did we click on an item?
  1108. if (-1 != pnmlv->iItem)
  1109. {
  1110. ZeroMemory(&lvh, sizeof(lvh));
  1111. lvh.pt = pnmlv->ptAction;
  1112. iSelected = ListView_HitTest(pnmlv->hdr.hwndFrom, &lvh);
  1113. if (-1 != iSelected)
  1114. {
  1115. // Did we click on the rule name?
  1116. if (0 != (lvh.flags & LVHT_ONITEMLABEL))
  1117. {
  1118. // Edit the rule
  1119. _EditRule(iSelected);
  1120. }
  1121. }
  1122. }
  1123. else
  1124. {
  1125. // We clicked outside the list
  1126. // Disable the buttons
  1127. _EnableButtons(pnmlv->iItem);
  1128. }
  1129. break;
  1130. case LVN_ITEMCHANGED:
  1131. // If an item's state changed to selected..
  1132. if ((-1 != pnmlv->iItem) &&
  1133. (0 != (pnmlv->uChanged & LVIF_STATE)) &&
  1134. (0 == (pnmlv->uOldState & LVIS_SELECTED)) &&
  1135. (0 != (pnmlv->uNewState & LVIS_SELECTED)))
  1136. {
  1137. // Enable the buttons
  1138. _EnableButtons(pnmlv->iItem);
  1139. }
  1140. break;
  1141. case LVN_ITEMCHANGING:
  1142. // If an item's state changed to unselected..
  1143. if ((-1 != pnmlv->iItem) &&
  1144. (0 != (pnmlv->uChanged & LVIF_STATE)) &&
  1145. (0 != (pnmlv->uOldState & LVIS_SELECTED)) &&
  1146. (0 == (pnmlv->uNewState & LVIS_SELECTED)))
  1147. {
  1148. // Save off the rule changes
  1149. _FSaveRule(pnmlv->iItem);
  1150. }
  1151. break;
  1152. case LVN_KEYDOWN:
  1153. pnmlvkd = (NMLVKEYDOWN *) pnmhdr;
  1154. // The space key changes the enable state of a rule
  1155. if (VK_SPACE == pnmlvkd->wVKey)
  1156. {
  1157. // Are we on a rule?
  1158. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1159. if (-1 != iSelected)
  1160. {
  1161. // Change the enable state of the rule
  1162. _EnableRule(iSelected);
  1163. }
  1164. }
  1165. // The delete key removes the rule from the list view
  1166. else if (VK_DELETE == pnmlvkd->wVKey)
  1167. {
  1168. // Are we on a rule?
  1169. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  1170. if (-1 != iSelected)
  1171. {
  1172. // Remove the rule from the list
  1173. _RemoveRule(iSelected);
  1174. }
  1175. }
  1176. break;
  1177. case LVN_BEGINLABELEDIT:
  1178. case LVN_ENDLABELEDIT:
  1179. fRet = _FOnLabelEdit((LVN_BEGINLABELEDIT == pnmlv->hdr.code), (NMLVDISPINFO *) pnmhdr);
  1180. break;
  1181. case NM_RULE_CHANGED:
  1182. fRet = _FOnRuleDescValid();
  1183. break;
  1184. }
  1185. exit:
  1186. return fRet;
  1187. }
  1188. ///////////////////////////////////////////////////////////////////////////////
  1189. //
  1190. // FOnDestroy
  1191. //
  1192. // This handles the WM_DESTROY message for the mail rules UI dialog
  1193. //
  1194. // Returns: TRUE, if it was successfully destroyed
  1195. // FALSE, otherwise
  1196. //
  1197. ///////////////////////////////////////////////////////////////////////////////
  1198. BOOL COEMailRulesPageUI::FOnDestroy(VOID)
  1199. {
  1200. BOOL fRet = FALSE;
  1201. UINT cRules = 0;
  1202. UINT uiIndex = 0;
  1203. LVITEM lvitem = {0};
  1204. UNALIGNED RULEINFO * pIRuleInfo = NULL;
  1205. Assert(m_hwndList);
  1206. // Get the number of rules in the list view
  1207. cRules = ListView_GetItemCount(m_hwndList);
  1208. // Initialize to get the rule interface from the list view
  1209. lvitem.mask = LVIF_PARAM;
  1210. // Release each of the rules from the list view
  1211. for (uiIndex = 0; uiIndex < cRules; uiIndex++)
  1212. {
  1213. lvitem.iItem = uiIndex;
  1214. // Get the rule interface
  1215. if (FALSE != ListView_GetItem(m_hwndList, &lvitem))
  1216. {
  1217. pIRuleInfo = (UNALIGNED RULEINFO *) (lvitem.lParam);
  1218. if (NULL != pIRuleInfo)
  1219. {
  1220. // Release the rule
  1221. if (NULL != pIRuleInfo->pIRule)
  1222. {
  1223. pIRuleInfo->pIRule->Release();
  1224. }
  1225. delete pIRuleInfo; // MemFree(pIRuleInfo);
  1226. }
  1227. }
  1228. }
  1229. fRet = TRUE;
  1230. return fRet;
  1231. }
  1232. ///////////////////////////////////////////////////////////////////////////////
  1233. //
  1234. // _FInitListCtrl
  1235. //
  1236. // This initializes the list view control in the mail rules dialog
  1237. //
  1238. // Returns: TRUE, on successful initialization
  1239. // FALSE, otherwise.
  1240. //
  1241. ///////////////////////////////////////////////////////////////////////////////
  1242. BOOL COEMailRulesPageUI::_FInitListCtrl(VOID)
  1243. {
  1244. BOOL fRet = FALSE;
  1245. LVCOLUMN lvc;
  1246. RECT rc;
  1247. HIMAGELIST himl = NULL;
  1248. Assert(NULL != m_hwndList);
  1249. // Initialize the list view structure
  1250. ZeroMemory(&lvc, sizeof(lvc));
  1251. lvc.mask = LVCF_WIDTH;
  1252. // Calculate the size of the list view
  1253. GetClientRect(m_hwndList, &rc);
  1254. lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  1255. ListView_InsertColumn(m_hwndList, 0, &lvc);
  1256. // Set the state image list
  1257. himl = ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idb16x16st), 16, 0, RGB(255, 0, 255));
  1258. if (NULL != himl)
  1259. {
  1260. ListView_SetImageList(m_hwndList, himl, LVSIL_STATE);
  1261. }
  1262. // Full row selection on listview
  1263. ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT);
  1264. // We worked
  1265. fRet = TRUE;
  1266. return fRet;
  1267. }
  1268. ///////////////////////////////////////////////////////////////////////////////
  1269. //
  1270. // _FLoadListCtrl
  1271. //
  1272. // This loads the list view with the current Mail rules
  1273. //
  1274. // Returns: TRUE, if it was successfully loaded
  1275. // FALSE, otherwise
  1276. //
  1277. ///////////////////////////////////////////////////////////////////////////////
  1278. BOOL COEMailRulesPageUI::_FLoadListCtrl(VOID)
  1279. {
  1280. BOOL fRet = FALSE;
  1281. HRESULT hr = S_OK;
  1282. DWORD dwListIndex = 0;
  1283. RULEINFO * pinfoRules = NULL;
  1284. ULONG cpinfoRules = 0;
  1285. ULONG ulIndex = 0;
  1286. IOERule * pIRule = NULL;
  1287. Assert(NULL != m_hwndList);
  1288. // Get the Rules enumerator
  1289. Assert(NULL != g_pRulesMan);
  1290. hr = g_pRulesMan->GetRules(GETF_EDIT, m_typeRule, &pinfoRules, &cpinfoRules);
  1291. if (FAILED(hr))
  1292. {
  1293. fRet = FALSE;
  1294. goto exit;
  1295. }
  1296. // Remove all the items from the list control
  1297. ListView_DeleteAllItems(m_hwndList);
  1298. // Add each filter to the list
  1299. dwListIndex = 0;
  1300. for (ulIndex = 0; ulIndex < cpinfoRules; ulIndex++)
  1301. {
  1302. // Make a copy of the rule
  1303. hr = pinfoRules[ulIndex].pIRule->Clone(&pIRule);
  1304. if (FAILED(hr))
  1305. {
  1306. continue;
  1307. }
  1308. // Add filter to the list
  1309. if (FALSE != _FAddRuleToList(dwListIndex, pinfoRules[ulIndex].ridRule, pIRule))
  1310. {
  1311. dwListIndex++;
  1312. }
  1313. SafeRelease(pIRule);
  1314. }
  1315. // Select the first item in the list
  1316. if (0 != dwListIndex)
  1317. {
  1318. ListView_SetItemState(m_hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1319. }
  1320. // Enable the dialog buttons.
  1321. _EnableButtons((0 != dwListIndex) ? 0 : -1);
  1322. fRet = TRUE;
  1323. exit:
  1324. SafeRelease(pIRule);
  1325. if (NULL != pinfoRules)
  1326. {
  1327. for (ulIndex = 0; ulIndex < cpinfoRules; ulIndex++)
  1328. {
  1329. pinfoRules[ulIndex].pIRule->Release();
  1330. }
  1331. MemFree(pinfoRules);
  1332. }
  1333. return fRet;
  1334. }
  1335. ///////////////////////////////////////////////////////////////////////////////
  1336. //
  1337. // _FAddRuleToList
  1338. //
  1339. // This adds the filter passed in to the list view
  1340. //
  1341. // dwIndex - the index on where to add the filter to into the list
  1342. // rhdlTag - the rule handle for the new rule
  1343. // pIRule - the actual rule
  1344. //
  1345. // Returns: TRUE, if it was successfully added
  1346. // FALSE, otherwise
  1347. //
  1348. ///////////////////////////////////////////////////////////////////////////////
  1349. BOOL COEMailRulesPageUI::_FAddRuleToList(DWORD dwIndex, RULEID ridRule, IOERule * pIRule)
  1350. {
  1351. BOOL fRet = FALSE;
  1352. HRESULT hr = S_OK;
  1353. PROPVARIANT propvar = {0};
  1354. LVITEM lvitem = {0};
  1355. BOOL fNotValid = FALSE;
  1356. BOOL fDisabled = FALSE;
  1357. RULEINFO * pinfoRule = NULL;
  1358. Assert(NULL != m_hwndList);
  1359. // If there's nothing to do...
  1360. if (NULL == pIRule)
  1361. {
  1362. fRet = FALSE;
  1363. goto exit;
  1364. }
  1365. // Is it disabled?
  1366. hr = pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar);
  1367. if (FAILED(hr))
  1368. {
  1369. fRet = FALSE;
  1370. goto exit;
  1371. }
  1372. fDisabled = !!propvar.boolVal;
  1373. // Need to check if the rule is valid
  1374. hr = pIRule->Validate(0);
  1375. if (FAILED(hr))
  1376. {
  1377. fRet = FALSE;
  1378. goto exit;
  1379. }
  1380. fNotValid = (hr == S_FALSE);
  1381. // Find out the name of the filter
  1382. hr = pIRule->GetProp(RULE_PROP_NAME , 0, &propvar);
  1383. if (FAILED(hr))
  1384. {
  1385. fRet = FALSE;
  1386. goto exit;
  1387. }
  1388. // Allocate space for the rule
  1389. pinfoRule = new RULEINFO;
  1390. if (NULL == pinfoRule)
  1391. {
  1392. fRet = FALSE;
  1393. goto exit;
  1394. }
  1395. // Set up the value
  1396. pinfoRule->ridRule = ridRule;
  1397. pinfoRule->pIRule = pIRule;
  1398. pinfoRule->pIRule->AddRef();
  1399. // Add in the image and rule interface
  1400. lvitem.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
  1401. lvitem.iItem = dwIndex;
  1402. // Need to change the state to mark the rule as invalid
  1403. if (FALSE != fNotValid)
  1404. {
  1405. lvitem.state = INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1);
  1406. }
  1407. else
  1408. {
  1409. lvitem.state = fDisabled ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) :
  1410. INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1);
  1411. }
  1412. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  1413. lvitem.pszText = propvar.pszVal;
  1414. lvitem.cchTextMax = lstrlen(propvar.pszVal) + 1;
  1415. lvitem.lParam = (LPARAM) pinfoRule;
  1416. if (-1 == ListView_InsertItem(m_hwndList, &lvitem))
  1417. {
  1418. fRet = FALSE;
  1419. goto exit;
  1420. }
  1421. fRet = TRUE;
  1422. exit:
  1423. PropVariantClear(&propvar);
  1424. return fRet;
  1425. }
  1426. ///////////////////////////////////////////////////////////////////////////////
  1427. //
  1428. // _EnableButtons
  1429. //
  1430. // This enables or disables the buttons in the Mail rules UI dialog
  1431. // depending on what is selected.
  1432. //
  1433. // iSelected - the item that was selected,
  1434. // -1 means that nothing was selected
  1435. //
  1436. // Returns: NONE
  1437. //
  1438. ///////////////////////////////////////////////////////////////////////////////
  1439. void COEMailRulesPageUI::_EnableButtons(INT iSelected)
  1440. {
  1441. int cRules = 0;
  1442. BOOL fSelected = FALSE;
  1443. BOOL fEnDisUp = FALSE;
  1444. BOOL fEnDisDown = FALSE;
  1445. LVITEM lvitem = {0};
  1446. IOERule * pIRule = NULL;
  1447. Assert(NULL != m_hwndList);
  1448. // Load the description field
  1449. _LoadRule(iSelected);
  1450. // Check the count of items in the list view
  1451. cRules = ListView_GetItemCount(m_hwndList);
  1452. fSelected = (-1 != iSelected);
  1453. // If we have rules and the top rule isn't selected
  1454. fEnDisUp = ((1 < cRules) && (0 != iSelected) && (FALSE != fSelected));
  1455. // If we have rules and the bottom rule ins't selected
  1456. fEnDisDown = ((1 < cRules) && ((cRules - 1) != iSelected) && (FALSE != fSelected));
  1457. // Enable the up/down buttons
  1458. RuleUtil_FEnDisDialogItem(m_hwndDlg, idbMoveDownRule, fEnDisDown);
  1459. RuleUtil_FEnDisDialogItem(m_hwndDlg, idbMoveUpRule, fEnDisUp);
  1460. // Enable the rule action buttons
  1461. RuleUtil_FEnDisDialogItem(m_hwndDlg, idbDeleteRule, fSelected);
  1462. RuleUtil_FEnDisDialogItem(m_hwndDlg, idbCopyRule, fSelected);
  1463. RuleUtil_FEnDisDialogItem(m_hwndDlg, idbModifyRule, fSelected);
  1464. return;
  1465. }
  1466. ///////////////////////////////////////////////////////////////////////////////
  1467. //
  1468. // _EnableRule
  1469. //
  1470. // This switches the current enabled state of the list view item
  1471. // and updates the UI
  1472. //
  1473. // iSelected - index of the item in the listview to work on
  1474. //
  1475. // Returns: NONE
  1476. //
  1477. ///////////////////////////////////////////////////////////////////////////////
  1478. VOID COEMailRulesPageUI::_EnableRule(int iSelected)
  1479. {
  1480. HRESULT hr = S_OK;
  1481. LVITEM lvi = {0};
  1482. IOERule * pIRule = NULL;
  1483. BOOL fEnabled = FALSE;
  1484. PROPVARIANT propvar;
  1485. // Grab the list view item
  1486. lvi.mask = LVIF_PARAM | LVIF_STATE;
  1487. lvi.stateMask = LVIS_STATEIMAGEMASK;
  1488. lvi.iItem = iSelected;
  1489. if (FALSE == ListView_GetItem(m_hwndList, &lvi))
  1490. {
  1491. goto exit;
  1492. }
  1493. pIRule = ((RULEINFO *) (lvi.lParam))->pIRule;
  1494. // Let's make sure we can enable this rule
  1495. hr = m_pDescriptUI->HrVerifyRule();
  1496. if (S_OK != hr)
  1497. {
  1498. // Put up a message saying something is busted
  1499. AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail),
  1500. MAKEINTRESOURCEW(idsRulesErrorEnable), NULL,
  1501. MB_OK | MB_ICONINFORMATION);
  1502. goto exit;
  1503. }
  1504. // Get the new enabled value
  1505. fEnabled = (lvi.state != INDEXTOSTATEIMAGEMASK(iiconStateChecked+1));
  1506. // Set the UI to the opposite enabled state
  1507. ZeroMemory(&lvi, sizeof(lvi));
  1508. lvi.mask = LVIF_STATE;
  1509. lvi.iItem = iSelected;
  1510. lvi.state = fEnabled ? INDEXTOSTATEIMAGEMASK(iiconStateChecked+1) :
  1511. INDEXTOSTATEIMAGEMASK(iiconStateUnchecked+1);
  1512. lvi.stateMask = LVIS_STATEIMAGEMASK;
  1513. ListView_SetItem(m_hwndList, &lvi);
  1514. // Set the enabled property
  1515. ZeroMemory(&propvar, sizeof(propvar));
  1516. propvar.vt = VT_BOOL;
  1517. propvar.boolVal = !fEnabled;
  1518. hr = pIRule->SetProp(RULE_PROP_DISABLED, 0, &propvar);
  1519. if (FAILED(hr))
  1520. {
  1521. goto exit;
  1522. }
  1523. // Tell the description field about it
  1524. m_pDescriptUI->HrSetEnabled(fEnabled);
  1525. // Redraw the string the new rule
  1526. m_pDescriptUI->ShowDescriptionString();
  1527. // Mark the rule list as dirty
  1528. m_dwState |= STATE_DIRTY;
  1529. exit:
  1530. return;
  1531. }
  1532. ///////////////////////////////////////////////////////////////////////////////
  1533. //
  1534. // _LoadRule
  1535. //
  1536. // This loads the selected rule into the description field.
  1537. // If there isn't a selected rule, then the description field is cleared.
  1538. //
  1539. // iSelected - the item that was selected,
  1540. // -1 means that nothing was selected
  1541. //
  1542. // Returns: NONE
  1543. //
  1544. ///////////////////////////////////////////////////////////////////////////////
  1545. void COEMailRulesPageUI::_LoadRule(INT iSelected)
  1546. {
  1547. LVITEM lvi = {0};
  1548. IOERule * pIRule = NULL;
  1549. Assert(NULL != m_hwndList);
  1550. Assert(NULL != m_pDescriptUI);
  1551. // Grab the rule from the list view
  1552. if (-1 != iSelected)
  1553. {
  1554. lvi.iItem = iSelected;
  1555. lvi.mask = LVIF_PARAM;
  1556. if (FALSE != ListView_GetItem(m_hwndList, &lvi))
  1557. {
  1558. pIRule = ((RULEINFO *) (lvi.lParam))->pIRule;
  1559. }
  1560. }
  1561. // Have the description field load this rule
  1562. m_pDescriptUI->HrSetRule(m_typeRule, pIRule);
  1563. // Display the new rule
  1564. m_pDescriptUI->ShowDescriptionString();
  1565. return;
  1566. }
  1567. ///////////////////////////////////////////////////////////////////////////////
  1568. //
  1569. // _FSaveRule
  1570. //
  1571. // This checks to see if the rule has been changed in the description
  1572. // area and if it has, then it warns the user and changes the text
  1573. //
  1574. // iSelected - index of the item in the listview to work on
  1575. //
  1576. // Returns: TRUE, if the rule either didn't change or did change without problems
  1577. //
  1578. ///////////////////////////////////////////////////////////////////////////////
  1579. BOOL COEMailRulesPageUI::_FSaveRule(int iSelected)
  1580. {
  1581. BOOL fRet = FALSE;
  1582. HRESULT hr = S_OK;
  1583. LVITEM lvi = {0};
  1584. IOERule * pIRule = NULL;
  1585. PROPVARIANT propvar = {0};
  1586. CRIT_ITEM * pCritItem = NULL;
  1587. ULONG cCritItem = 0;
  1588. ACT_ITEM * pActItem = NULL;
  1589. ULONG cActItem = 0;
  1590. // If the rule didn't change, then we're done
  1591. hr = m_pDescriptUI->HrIsDirty();
  1592. if (S_OK != hr)
  1593. {
  1594. fRet = (S_FALSE == hr);
  1595. goto exit;
  1596. }
  1597. // Grab the list view item
  1598. lvi.mask = LVIF_PARAM;
  1599. lvi.iItem = iSelected;
  1600. if (FALSE == ListView_GetItem(m_hwndList, &lvi))
  1601. {
  1602. fRet = FALSE;
  1603. goto exit;
  1604. }
  1605. pIRule = ((RULEINFO *) (lvi.lParam))->pIRule;
  1606. // Get the criteria from the rule
  1607. hr = m_pDescriptUI->HrGetCriteria(&pCritItem, &cCritItem);
  1608. if (FAILED(hr))
  1609. {
  1610. fRet = FALSE;
  1611. goto exit;
  1612. }
  1613. // Get the actions for the rule
  1614. hr = m_pDescriptUI->HrGetActions(&pActItem, &cActItem);
  1615. if (FAILED(hr))
  1616. {
  1617. fRet = FALSE;
  1618. goto exit;
  1619. }
  1620. // Set the criteria from the rule
  1621. PropVariantClear(&propvar);
  1622. propvar.vt = VT_BLOB;
  1623. propvar.blob.cbSize = cCritItem * sizeof(CRIT_ITEM);
  1624. propvar.blob.pBlobData = (BYTE *) pCritItem;
  1625. hr = pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar);
  1626. ZeroMemory(&propvar, sizeof(propvar));
  1627. if (FAILED(hr))
  1628. {
  1629. fRet = FALSE;
  1630. goto exit;
  1631. }
  1632. // Set the actions for the rule
  1633. PropVariantClear(&propvar);
  1634. propvar.vt = VT_BLOB;
  1635. propvar.blob.cbSize = cActItem * sizeof(ACT_ITEM);
  1636. propvar.blob.pBlobData = (BYTE *) pActItem;
  1637. hr = pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar);
  1638. ZeroMemory(&propvar, sizeof(propvar));
  1639. if (FAILED(hr))
  1640. {
  1641. fRet = FALSE;
  1642. goto exit;
  1643. }
  1644. // Mark the rule list as dirty
  1645. m_dwState |= STATE_DIRTY;
  1646. // Make sure we clear out the fact that we saved the rule
  1647. m_pDescriptUI->HrClearDirty();
  1648. // Set the proper return value
  1649. fRet = TRUE;
  1650. exit:
  1651. RuleUtil_HrFreeCriteriaItem(pCritItem, cCritItem);
  1652. SafeMemFree(pCritItem);
  1653. RuleUtil_HrFreeActionsItem(pActItem, cActItem);
  1654. SafeMemFree(pActItem);
  1655. return fRet;
  1656. }
  1657. ///////////////////////////////////////////////////////////////////////////////
  1658. //
  1659. // _NewRule
  1660. //
  1661. // This brings up a fresh rules editor
  1662. //
  1663. // Returns: NONE
  1664. //
  1665. ///////////////////////////////////////////////////////////////////////////////
  1666. void COEMailRulesPageUI::_NewRule(VOID)
  1667. {
  1668. HRESULT hr = S_OK;
  1669. IOERule * pIRule = NULL;
  1670. TCHAR szRes[CCHMAX_STRINGRES + 5];
  1671. ULONG cchRes = 0;
  1672. ULONG ulIndex = 0;
  1673. TCHAR szName[CCHMAX_STRINGRES + 5];
  1674. LVFINDINFO lvfinfo = {0};
  1675. PROPVARIANT propvar = {0};
  1676. CEditRuleUI * pEditRuleUI = NULL;
  1677. LONG cRules = 0;
  1678. UINT uiStrId = 0;
  1679. // Create a new rule object
  1680. if (FAILED(HrCreateRule(&pIRule)))
  1681. {
  1682. goto exit;
  1683. }
  1684. // Figure out the string Id
  1685. if (RULE_TYPE_NEWS == m_typeRule)
  1686. {
  1687. uiStrId = idsRuleNewsDefaultName;
  1688. }
  1689. else
  1690. {
  1691. uiStrId = idsRuleMailDefaultName;
  1692. }
  1693. // Figure out the name of the new rule ...
  1694. cchRes = LoadString(g_hLocRes, uiStrId, szRes, ARRAYSIZE(szRes));
  1695. if (0 == cchRes)
  1696. {
  1697. goto exit;
  1698. }
  1699. ulIndex = 1;
  1700. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulIndex);
  1701. lvfinfo.flags = LVFI_STRING;
  1702. lvfinfo.psz = szName;
  1703. while (-1 != ListView_FindItem(m_hwndList, -1, &lvfinfo))
  1704. {
  1705. ulIndex++;
  1706. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulIndex);
  1707. }
  1708. propvar.vt = VT_LPSTR;
  1709. propvar.pszVal = szName;
  1710. hr = pIRule->SetProp(RULE_PROP_NAME, 0, &propvar);
  1711. if (FAILED(hr))
  1712. {
  1713. goto exit;
  1714. }
  1715. // Create a rules editor object
  1716. pEditRuleUI = new CEditRuleUI;
  1717. if (NULL == pEditRuleUI)
  1718. {
  1719. goto exit;
  1720. }
  1721. // Initialize the editor object
  1722. if (FAILED(pEditRuleUI->HrInit(m_hwndDlg, ERF_NEWRULE, m_typeRule, pIRule, NULL)))
  1723. {
  1724. goto exit;
  1725. }
  1726. // Bring up the rules editor UI
  1727. hr = pEditRuleUI->HrShow();
  1728. if (FAILED(hr))
  1729. {
  1730. goto exit;
  1731. }
  1732. if (S_OK == hr)
  1733. {
  1734. // Mark the rule list as dirty
  1735. m_dwState |= STATE_DIRTY;
  1736. // Add the rule to the manager UI
  1737. cRules = ListView_GetItemCount(m_hwndList);
  1738. _FAddRuleToList(cRules, RULEID_INVALID, pIRule);
  1739. // Make sure the new item is selected
  1740. ListView_SetItemState(m_hwndList, cRules, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1741. // Make sure the new item is visible
  1742. ListView_EnsureVisible(m_hwndList, cRules, FALSE);
  1743. }
  1744. exit:
  1745. SafeRelease(pIRule);
  1746. if (NULL != pEditRuleUI)
  1747. {
  1748. delete pEditRuleUI;
  1749. }
  1750. return;
  1751. }
  1752. ///////////////////////////////////////////////////////////////////////////////
  1753. //
  1754. // _EditRule
  1755. //
  1756. // This brings up the edit UI for the selected rule from the mail rules list
  1757. //
  1758. // iSelected - index of the item in the listview to work on
  1759. //
  1760. // Returns: NONE
  1761. //
  1762. ///////////////////////////////////////////////////////////////////////////////
  1763. VOID COEMailRulesPageUI::_EditRule(int iSelected)
  1764. {
  1765. HRESULT hr = S_OK;
  1766. LVITEM lvitem = {0};
  1767. IOERule * pIRule = NULL;
  1768. CEditRuleUI * pEditRuleUI = NULL;
  1769. PROPVARIANT propvar = {0};
  1770. BOOL fNotValid = FALSE;
  1771. BOOL fDisabled = FALSE;
  1772. Assert(NULL != m_hwndList);
  1773. // Make sure we don't loose any changes
  1774. _FSaveRule(iSelected);
  1775. // Grab the rule from the list view
  1776. lvitem.iItem = iSelected;
  1777. lvitem.mask = LVIF_PARAM;
  1778. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  1779. {
  1780. goto exit;
  1781. }
  1782. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  1783. if (NULL == pIRule)
  1784. {
  1785. goto exit;
  1786. }
  1787. // Create the rules editor
  1788. pEditRuleUI = new CEditRuleUI;
  1789. if (NULL == pEditRuleUI)
  1790. {
  1791. goto exit;
  1792. }
  1793. // Initialize the editor object
  1794. if (FAILED(pEditRuleUI->HrInit(m_hwndDlg, 0, m_typeRule, pIRule, NULL)))
  1795. {
  1796. goto exit;
  1797. }
  1798. // Bring up the rules editor UI
  1799. hr = pEditRuleUI->HrShow();
  1800. if (FAILED(hr))
  1801. {
  1802. goto exit;
  1803. }
  1804. // If the rule changed, make sure we reload the description field
  1805. if (S_OK == hr)
  1806. {
  1807. // Mark the rule list as dirty
  1808. m_dwState |= STATE_DIRTY;
  1809. ZeroMemory(&lvitem, sizeof(lvitem));
  1810. lvitem.mask = LVIF_STATE;
  1811. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  1812. lvitem.iItem = iSelected;
  1813. // Is it disabled?
  1814. hr = pIRule->GetProp(RULE_PROP_DISABLED , 0, &propvar);
  1815. if (FAILED(hr))
  1816. {
  1817. goto exit;
  1818. }
  1819. fDisabled = !!propvar.boolVal;
  1820. // Need to check if the rule is valid
  1821. hr = pIRule->Validate(0);
  1822. if (FAILED(hr))
  1823. {
  1824. goto exit;
  1825. }
  1826. fNotValid = (hr == S_FALSE);
  1827. // Grab the rule name
  1828. PropVariantClear(&propvar);
  1829. hr = pIRule->GetProp(RULE_PROP_NAME, 0, &propvar);
  1830. if (FAILED(hr))
  1831. {
  1832. goto exit;
  1833. }
  1834. if ((VT_LPSTR == propvar.vt) && (NULL != propvar.pszVal) && ('\0' != propvar.pszVal[0]))
  1835. {
  1836. lvitem.mask |= LVIF_TEXT;
  1837. lvitem.pszText = propvar.pszVal;
  1838. lvitem.cchTextMax = lstrlen(propvar.pszVal) + 1;
  1839. }
  1840. // Grab the rule state
  1841. // Need to change the state to mark the rule as invalid
  1842. if (FALSE != fNotValid)
  1843. {
  1844. lvitem.state = INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1);
  1845. }
  1846. else
  1847. {
  1848. lvitem.state = fDisabled ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) :
  1849. INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1);
  1850. }
  1851. if (-1 == ListView_SetItem(m_hwndList, &lvitem))
  1852. {
  1853. goto exit;
  1854. }
  1855. _EnableButtons(iSelected);
  1856. }
  1857. exit:
  1858. PropVariantClear(&propvar);
  1859. if (NULL != pEditRuleUI)
  1860. {
  1861. delete pEditRuleUI;
  1862. }
  1863. return;
  1864. }
  1865. ///////////////////////////////////////////////////////////////////////////////
  1866. //
  1867. // _MoveRule
  1868. //
  1869. // This moves the selected rule in the desired direction
  1870. //
  1871. // iSelected - index of the item in the listview to work on
  1872. // dir - the direction to move the item
  1873. //
  1874. // Returns: NONE
  1875. //
  1876. ///////////////////////////////////////////////////////////////////////////////
  1877. void COEMailRulesPageUI::_MoveRule(INT iSelected, MOVE_DIR dir)
  1878. {
  1879. LVITEM lvitem = {0};
  1880. TCHAR szName[CCHMAX_STRINGRES];
  1881. IOERule * pIRule = NULL;
  1882. int nIndexNew = 0;
  1883. Assert(NULL != m_hwndList);
  1884. // Grab the rule from the list view
  1885. szName[0] = '\0';
  1886. lvitem.iItem = iSelected;
  1887. lvitem.mask = LVIF_STATE | LVIF_PARAM | LVIF_TEXT;
  1888. lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK;
  1889. lvitem.pszText = szName;
  1890. lvitem.cchTextMax = ARRAYSIZE(szName);
  1891. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  1892. {
  1893. goto exit;
  1894. }
  1895. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  1896. // Update the item in the list view
  1897. // Get the info for the new index
  1898. nIndexNew = iSelected;
  1899. nIndexNew += (MOVE_RULE_UP == dir) ? -1 : 2;
  1900. // Insert the new index
  1901. lvitem.iItem = nIndexNew;
  1902. if (-1 == ListView_InsertItem(m_hwndList, &lvitem))
  1903. {
  1904. goto exit;
  1905. }
  1906. // Ensure the new item is visible
  1907. ListView_EnsureVisible(m_hwndList, nIndexNew, FALSE);
  1908. ListView_RedrawItems(m_hwndList, nIndexNew, nIndexNew);
  1909. // If we moved up, then the old item is now one lower than before
  1910. if (MOVE_RULE_UP == dir)
  1911. {
  1912. iSelected++;
  1913. }
  1914. // Remove the old item
  1915. if (FALSE == ListView_DeleteItem(m_hwndList, iSelected))
  1916. {
  1917. goto exit;
  1918. }
  1919. // Mark the rule list as dirty
  1920. m_dwState |= STATE_DIRTY;
  1921. exit:
  1922. return;
  1923. }
  1924. ///////////////////////////////////////////////////////////////////////////////
  1925. //
  1926. // _RemoveRule
  1927. //
  1928. // This removes the selected rule from the mail rules list
  1929. //
  1930. // iSelected - index of the item in the listview to work on
  1931. //
  1932. // Returns: NONE
  1933. //
  1934. ///////////////////////////////////////////////////////////////////////////////
  1935. VOID COEMailRulesPageUI::_RemoveRule(int iSelected)
  1936. {
  1937. LVITEM lvitem = {0};
  1938. RULEINFO * pinfoRule = NULL;
  1939. PROPVARIANT propvar = {0};
  1940. int cRules = 0;
  1941. TCHAR szRes[CCHMAX_STRINGRES];
  1942. UINT cchRes = 0;
  1943. LPTSTR pszMessage = NULL;
  1944. Assert(NULL != m_hwndList);
  1945. // Grab the rule from the list view
  1946. lvitem.iItem = iSelected;
  1947. lvitem.mask = LVIF_PARAM;
  1948. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  1949. {
  1950. goto exit;
  1951. }
  1952. pinfoRule = (RULEINFO *) (lvitem.lParam);
  1953. if ((NULL == pinfoRule) || (NULL == pinfoRule->pIRule))
  1954. {
  1955. goto exit;
  1956. }
  1957. // Warn the user to make sure they know we are going to remove the rule
  1958. if (FAILED(pinfoRule->pIRule->GetProp(RULE_PROP_NAME, 0, &propvar)))
  1959. {
  1960. goto exit;
  1961. }
  1962. // Get the string template to display
  1963. cchRes = LoadString(g_hLocRes, idsRulesWarnDelete, szRes, ARRAYSIZE(szRes));
  1964. if (0 == cchRes)
  1965. {
  1966. goto exit;
  1967. }
  1968. // Allocate space to hold the final display string
  1969. DWORD cchSize = (cchRes + lstrlen(propvar.pszVal) + 1);
  1970. if (FAILED(HrAlloc((void ** ) &pszMessage, cchSize)))
  1971. {
  1972. goto exit;
  1973. }
  1974. // Build up the string and display it
  1975. wnsprintf(pszMessage, cchSize, szRes, propvar.pszVal);
  1976. if (IDNO == AthMessageBox(m_hwndDlg, MAKEINTRESOURCE(idsAthenaMail), pszMessage,
  1977. NULL, MB_YESNO | MB_ICONINFORMATION))
  1978. {
  1979. goto exit;
  1980. }
  1981. // Remove the item from the list
  1982. ListView_DeleteItem(m_hwndList, iSelected);
  1983. // Let's make sure we have a selection in the list
  1984. cRules = ListView_GetItemCount(m_hwndList);
  1985. if (cRules > 0)
  1986. {
  1987. // Did we delete the last item in the list
  1988. if (iSelected >= cRules)
  1989. {
  1990. // Move the selection to the new last item in the list
  1991. iSelected = cRules - 1;
  1992. }
  1993. // Set the new selection
  1994. ListView_SetItemState(m_hwndList, iSelected, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1995. // Let's make sure we can see this new item
  1996. ListView_EnsureVisible(m_hwndList, iSelected, FALSE);
  1997. }
  1998. else
  1999. {
  2000. // Make sure we clear out all of the buttons
  2001. _EnableButtons(-1);
  2002. }
  2003. // Release the rule
  2004. SafeRelease(pinfoRule->pIRule);
  2005. // Free up the memory
  2006. delete pinfoRule; // SafeMemFree(pinfoRule);
  2007. // Mark the rule list as dirty
  2008. m_dwState |= STATE_DIRTY;
  2009. exit:
  2010. PropVariantClear(&propvar);
  2011. SafeMemFree(pszMessage);
  2012. return;
  2013. }
  2014. ///////////////////////////////////////////////////////////////////////////////
  2015. //
  2016. // CopyRule
  2017. //
  2018. // This copies the selected rule from the rules manager
  2019. //
  2020. // iSelected - index of the item in the listview to work on
  2021. //
  2022. // Returns: NONE
  2023. //
  2024. ///////////////////////////////////////////////////////////////////////////////
  2025. VOID COEMailRulesPageUI::_CopyRule(INT iSelected)
  2026. {
  2027. LVITEM lvitem = {0};
  2028. IOERule * pIRule = NULL;
  2029. HRESULT hr = S_OK;
  2030. IOERule * pIRuleNew = NULL;
  2031. PROPVARIANT propvar = {0};
  2032. UINT cRules = 0;
  2033. TCHAR szRes[CCHMAX_STRINGRES];
  2034. UINT cchRes = 0;
  2035. LPTSTR pszName = NULL;
  2036. Assert(NULL != m_hwndList);
  2037. // Make sure we don't loose any changes
  2038. _FSaveRule(iSelected);
  2039. // Grab the rule from the list view
  2040. lvitem.iItem = iSelected;
  2041. lvitem.mask = LVIF_PARAM;
  2042. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  2043. {
  2044. goto exit;
  2045. }
  2046. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  2047. if (NULL == pIRule)
  2048. {
  2049. goto exit;
  2050. }
  2051. // Create a new rule object
  2052. hr = pIRule->Clone(&pIRuleNew);
  2053. if (FAILED(hr))
  2054. {
  2055. goto exit;
  2056. }
  2057. // Let's set the name
  2058. // Get the name from the source rule
  2059. hr = pIRule->GetProp(RULE_PROP_NAME, 0, &propvar);
  2060. if (FAILED(hr))
  2061. {
  2062. goto exit;
  2063. }
  2064. // Get the string template to display
  2065. cchRes = LoadString(g_hLocRes, idsRulesCopyName, szRes, ARRAYSIZE(szRes));
  2066. if (0 == cchRes)
  2067. {
  2068. goto exit;
  2069. }
  2070. // Allocate space to hold the final display string
  2071. DWORD cchSize = (cchRes + lstrlen(propvar.pszVal) + 1);
  2072. if (FAILED(HrAlloc((void ** ) &pszName, cchSize)))
  2073. {
  2074. goto exit;
  2075. }
  2076. // Build up the string and set it
  2077. wnsprintf(pszName, cchSize, szRes, propvar.pszVal);
  2078. PropVariantClear(&propvar);
  2079. propvar.vt = VT_LPSTR;
  2080. propvar.pszVal = pszName;
  2081. pszName = NULL;
  2082. // Set the name into the new rule
  2083. Assert(VT_LPSTR == propvar.vt);
  2084. Assert(NULL != propvar.pszVal);
  2085. hr = pIRuleNew->SetProp(RULE_PROP_NAME, 0, &propvar);
  2086. if (FAILED(hr))
  2087. {
  2088. goto exit;
  2089. }
  2090. // Clear the version of the new rule
  2091. PropVariantClear(&propvar);
  2092. propvar.vt = VT_UI4;
  2093. propvar.ulVal = 0;
  2094. hr = pIRuleNew->SetProp(RULE_PROP_VERSION, 0, &propvar);
  2095. if (FAILED(hr))
  2096. {
  2097. goto exit;
  2098. }
  2099. // Add the rule to the rules list right below
  2100. // the original rule
  2101. iSelected++;
  2102. _FAddRuleToList(iSelected, RULEID_INVALID, pIRuleNew);
  2103. // Make sure the new item is selected
  2104. ListView_SetItemState(m_hwndList, iSelected, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  2105. // Make sure the new item is visible
  2106. ListView_EnsureVisible(m_hwndList, iSelected, FALSE);
  2107. // Mark the rule list as dirty
  2108. m_dwState |= STATE_DIRTY;
  2109. exit:
  2110. SafeMemFree(pszName);
  2111. SafeRelease(pIRuleNew);
  2112. PropVariantClear(&propvar);
  2113. return;
  2114. }
  2115. ///////////////////////////////////////////////////////////////////////////////
  2116. //
  2117. // FOnApplyTo
  2118. //
  2119. // This applies the rules into a folder
  2120. //
  2121. // Returns: NONE
  2122. //
  2123. ///////////////////////////////////////////////////////////////////////////////
  2124. VOID COEMailRulesPageUI::_OnApplyTo(INT iSelected)
  2125. {
  2126. COEApplyRulesUI * pApplyRulesUI = NULL;
  2127. RULENODE * prnodeList = NULL;
  2128. RULENODE * prnodeWalk = NULL;
  2129. LVITEM lvitem = {0};
  2130. IOERule * pIRule = NULL;
  2131. HRESULT hr = S_OK;
  2132. // Create the rules UI object
  2133. pApplyRulesUI = new COEApplyRulesUI;
  2134. if (NULL == pApplyRulesUI)
  2135. {
  2136. goto exit;
  2137. }
  2138. // Get the rules from the page
  2139. if (FALSE == SendMessage(m_hwndOwner, WM_OE_GET_RULES, (WPARAM) m_typeRule, (LPARAM) &prnodeList))
  2140. {
  2141. goto exit;
  2142. }
  2143. if (NULL == prnodeList)
  2144. {
  2145. AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail),
  2146. (RULE_TYPE_NEWS == m_typeRule) ? MAKEINTRESOURCEW(idsErrorApplyRulesNews) : MAKEINTRESOURCEW(idsErrorApplyRulesMail),
  2147. NULL, MB_OK | MB_ICONERROR);
  2148. goto exit;
  2149. }
  2150. // Get the rule associated with the item
  2151. if (-1 != iSelected)
  2152. {
  2153. lvitem.iItem = iSelected;
  2154. lvitem.mask = LVIF_PARAM;
  2155. if (FALSE != ListView_GetItem(m_hwndList, &lvitem))
  2156. {
  2157. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  2158. if (NULL != pIRule)
  2159. {
  2160. // Verify that it is valid
  2161. hr = pIRule->Validate(0);
  2162. if ((FAILED(hr)) || (S_FALSE == hr))
  2163. {
  2164. pIRule = NULL;
  2165. }
  2166. }
  2167. }
  2168. }
  2169. if (FAILED(pApplyRulesUI->HrInit(m_hwndDlg, 0, m_typeRule, prnodeList, pIRule)))
  2170. {
  2171. goto exit;
  2172. }
  2173. prnodeList = NULL;
  2174. if (FAILED(pApplyRulesUI->HrShow()))
  2175. {
  2176. goto exit;
  2177. }
  2178. exit:
  2179. while (NULL != prnodeList)
  2180. {
  2181. prnodeWalk = prnodeList;
  2182. if (NULL != prnodeWalk->pIRule)
  2183. {
  2184. prnodeWalk->pIRule->Release();
  2185. }
  2186. prnodeList = prnodeList->pNext;
  2187. MemFree(prnodeWalk);
  2188. }
  2189. if (NULL != pApplyRulesUI)
  2190. {
  2191. delete pApplyRulesUI;
  2192. }
  2193. return;
  2194. }
  2195. ///////////////////////////////////////////////////////////////////////////////
  2196. //
  2197. // _FOnLabelEdit
  2198. //
  2199. // This brings up the edit UI for the selected rule from the mail rules list
  2200. //
  2201. // fBegin - is this for the LVN_BEGINLABELEDIT notification
  2202. // pdi - the display info for the message
  2203. //
  2204. // Returns: TRUE, if the message was handled
  2205. // FALSE, otherwise
  2206. //
  2207. ///////////////////////////////////////////////////////////////////////////////
  2208. BOOL COEMailRulesPageUI::_FOnLabelEdit(BOOL fBegin, NMLVDISPINFO * pdi)
  2209. {
  2210. BOOL fRet = FALSE;
  2211. HWND hwndEdit;
  2212. ULONG cchName = 0;
  2213. IOERule * pIRule = NULL;
  2214. LVITEM lvitem;
  2215. PROPVARIANT propvar;
  2216. Assert(NULL != m_hwndList);
  2217. if (NULL == pdi)
  2218. {
  2219. fRet = FALSE;
  2220. goto exit;
  2221. }
  2222. Assert(m_hwndList == pdi->hdr.hwndFrom);
  2223. if (FALSE != fBegin)
  2224. {
  2225. // Get the edit control
  2226. hwndEdit = ListView_GetEditControl(m_hwndList);
  2227. if (NULL == hwndEdit)
  2228. {
  2229. fRet = FALSE;
  2230. goto exit;
  2231. }
  2232. // Limit the amount of text for the name
  2233. SendMessage(hwndEdit, EM_LIMITTEXT, c_cchNameMax - 1, 0);
  2234. // Tell the dialog it's aok to proceed
  2235. SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE);
  2236. }
  2237. else
  2238. {
  2239. // Did something change?
  2240. if ((-1 != pdi->item.iItem) && (NULL != pdi->item.pszText))
  2241. {
  2242. cchName = lstrlen(pdi->item.pszText);
  2243. // Check to see if the rule name is valid
  2244. if ((0 == cchName) || (0 == UlStripWhitespace(pdi->item.pszText, TRUE, TRUE, &cchName)))
  2245. {
  2246. // Put up a message saying something is busted
  2247. AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail),
  2248. MAKEINTRESOURCEW(idsRulesErrorNoName), NULL,
  2249. MB_OK | MB_ICONINFORMATION);
  2250. SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE);
  2251. fRet = TRUE;
  2252. goto exit;
  2253. }
  2254. // Get the rule for the item
  2255. ZeroMemory(&lvitem, sizeof(lvitem));
  2256. lvitem.iItem = pdi->item.iItem;
  2257. lvitem.mask = LVIF_PARAM;
  2258. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  2259. {
  2260. SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE);
  2261. fRet = TRUE;
  2262. goto exit;
  2263. }
  2264. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  2265. if (NULL == pIRule)
  2266. {
  2267. SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE);
  2268. fRet = TRUE;
  2269. goto exit;
  2270. }
  2271. // Set the new name into the rule
  2272. ZeroMemory(&propvar, sizeof(propvar));
  2273. propvar.vt = VT_LPSTR;
  2274. propvar.pszVal = pdi->item.pszText;
  2275. SideAssert(S_OK == pIRule->SetProp(RULE_PROP_NAME, 0, &propvar));
  2276. // Mark the rule list as dirty
  2277. m_dwState |= STATE_DIRTY;
  2278. SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, TRUE);
  2279. }
  2280. }
  2281. fRet = TRUE;
  2282. exit:
  2283. return fRet;
  2284. }
  2285. ///////////////////////////////////////////////////////////////////////////////
  2286. //
  2287. // _FOnRuleDescValid
  2288. //
  2289. // This brings up the edit UI for the selected rule from the mail rules list
  2290. //
  2291. // Returns: TRUE, if the message was handled
  2292. // FALSE, otherwise
  2293. //
  2294. ///////////////////////////////////////////////////////////////////////////////
  2295. BOOL COEMailRulesPageUI::_FOnRuleDescValid(VOID)
  2296. {
  2297. BOOL fRet = FALSE;
  2298. INT iSelected = 0;
  2299. LVITEM lvitem;
  2300. IOERule * pIRule = NULL;
  2301. HRESULT hr = S_OK;
  2302. PROPVARIANT propvar;
  2303. Assert(NULL != m_hwndList);
  2304. // Get the selected item
  2305. iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
  2306. if (-1 == iSelected)
  2307. {
  2308. fRet = FALSE;
  2309. goto exit;
  2310. }
  2311. // Get the current state of the rule
  2312. ZeroMemory(&lvitem, sizeof(lvitem));
  2313. lvitem.mask = LVIF_PARAM | LVIF_STATE;
  2314. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  2315. lvitem.iItem = iSelected;
  2316. if (FALSE == ListView_GetItem(m_hwndList, &lvitem))
  2317. {
  2318. fRet = FALSE;
  2319. goto exit;
  2320. }
  2321. pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule;
  2322. // If the rule already valid, then bail
  2323. if (lvitem.state != INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1))
  2324. {
  2325. fRet = FALSE;
  2326. goto exit;
  2327. }
  2328. // If we are still, invalid then bail
  2329. hr = m_pDescriptUI->HrVerifyRule();
  2330. if (S_OK != hr)
  2331. {
  2332. fRet = FALSE;
  2333. goto exit;
  2334. }
  2335. // Figure out the new enabled value
  2336. hr = pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar);
  2337. if (FAILED(hr))
  2338. {
  2339. fRet = FALSE;
  2340. goto exit;
  2341. }
  2342. // Set the UI to the proper enabled state
  2343. ZeroMemory(&lvitem, sizeof(lvitem));
  2344. lvitem.mask = LVIF_STATE;
  2345. lvitem.iItem = iSelected;
  2346. lvitem.state = (!!propvar.boolVal) ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) :
  2347. INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1);
  2348. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  2349. ListView_SetItem(m_hwndList, &lvitem);
  2350. fRet = TRUE;
  2351. exit:
  2352. return fRet;
  2353. }