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.

2449 lines
66 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Criteria.cpp
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6. #include <pch.hxx>
  7. #include "criteria.h"
  8. #include "ruleutil.h"
  9. #include <xpcomm.h>
  10. #include <flagconv.h>
  11. #include <bodyutil.h>
  12. #include <demand.h>
  13. static const int CRIT_GROW = 16;
  14. BOOL FMatchCritItem(CRIT_ITEM * pItem, LPCSTR pszAcct, MESSAGEINFO * pMsgInfo,
  15. IMessageFolder * pFolder, IMimePropertySet * pIMPropSet,
  16. IMimeMessage * pIMMsg, ULONG cbMsgSize);
  17. BOOL FCritLoad_Account(IStream * pIStm, PROPVARIANT * ppropvar);
  18. BOOL FCritSave_Account(IStream * pIStm, PROPVARIANT * ppropvar);
  19. BOOL FCritLoad_Default(IStream * pIStm, PROPVARIANT * ppropvar);
  20. BOOL FCritSave_Default(IStream * pIStm, PROPVARIANT * ppropvar);
  21. DWORD DwGetFlagsFromMessage(IMimeMessage * pIMMsg);
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // HrCreateCriteria
  25. //
  26. // This creates a criteria container.
  27. //
  28. // ppICriteria - pointer to return the criteria container
  29. //
  30. // Returns: S_OK, on success
  31. // E_OUTOFMEMORY, if can't create the Criteria object
  32. //
  33. ///////////////////////////////////////////////////////////////////////////////
  34. HRESULT HrCreateCriteria(IOECriteria ** ppICriteria)
  35. {
  36. COECriteria * pCriteria = NULL;
  37. HRESULT hr = S_OK;
  38. // Check the incoming params
  39. if (NULL == ppICriteria)
  40. {
  41. hr = E_INVALIDARG;
  42. goto exit;
  43. }
  44. // Initialize outgoing params
  45. *ppICriteria = NULL;
  46. // Create the rules manager object
  47. pCriteria = new COECriteria;
  48. if (NULL == pCriteria)
  49. {
  50. hr = E_OUTOFMEMORY;
  51. goto exit;
  52. }
  53. // Get the rules manager interface
  54. hr = pCriteria->QueryInterface(IID_IOECriteria, (void **) ppICriteria);
  55. if (FAILED(hr))
  56. {
  57. goto exit;
  58. }
  59. pCriteria = NULL;
  60. // Set the proper return value
  61. hr = S_OK;
  62. exit:
  63. if (NULL != pCriteria)
  64. {
  65. delete pCriteria;
  66. }
  67. return hr;
  68. }
  69. COECriteria::~COECriteria()
  70. {
  71. AssertSz(m_cRef == 0, "Somebody still has a hold of us!!");
  72. Reset();
  73. }
  74. STDMETHODIMP_(ULONG) COECriteria::AddRef()
  75. {
  76. return ::InterlockedIncrement(&m_cRef);
  77. }
  78. STDMETHODIMP_(ULONG) COECriteria::Release()
  79. {
  80. LONG cRef = 0;
  81. cRef = ::InterlockedDecrement(&m_cRef);
  82. if (0 == cRef)
  83. {
  84. delete this;
  85. return cRef;
  86. }
  87. return cRef;
  88. }
  89. STDMETHODIMP COECriteria::QueryInterface(REFIID riid, void ** ppvObject)
  90. {
  91. HRESULT hr = S_OK;
  92. // Check the incoming params
  93. if (NULL == ppvObject)
  94. {
  95. hr = E_INVALIDARG;
  96. goto exit;
  97. }
  98. // Initialize outgoing param
  99. *ppvObject = NULL;
  100. if ((riid == IID_IUnknown) || (riid == IID_IOECriteria))
  101. {
  102. *ppvObject = static_cast<IOECriteria *>(this);
  103. }
  104. else if ((riid == IID_IPersistStream) || (riid == IID_IPersist))
  105. {
  106. *ppvObject = static_cast<IPersistStream *>(this);
  107. }
  108. else
  109. {
  110. hr = E_NOINTERFACE;
  111. goto exit;
  112. }
  113. reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
  114. hr = S_OK;
  115. exit:
  116. return hr;
  117. }
  118. STDMETHODIMP COECriteria::Reset(void)
  119. {
  120. HRESULT hr = S_OK;
  121. // See if there is something to do
  122. if (0 == m_cItems)
  123. {
  124. Assert(NULL == m_rgItems);
  125. hr = S_OK;
  126. goto exit;
  127. }
  128. RuleUtil_HrFreeCriteriaItem(m_rgItems, m_cItems);
  129. SafeMemFree(m_rgItems);
  130. m_cItems = 0;
  131. m_cItemsAlloc = 0;
  132. exit:
  133. return hr;
  134. }
  135. STDMETHODIMP COECriteria::GetState(DWORD * pdwState)
  136. {
  137. HRESULT hr = S_OK;
  138. DWORD dwState = CRIT_STATE_NULL;
  139. ULONG ulIndex = 0;
  140. // Check incoming params
  141. if (NULL == pdwState)
  142. {
  143. hr = E_INVALIDARG;
  144. goto exit;
  145. }
  146. // Init the outgoing param
  147. *pdwState = CRIT_STATE_NULL;
  148. // See if there is something to do
  149. if (0 == m_cItems)
  150. {
  151. Assert(NULL == m_rgItems);
  152. hr = S_OK;
  153. goto exit;
  154. }
  155. // Walk through the actions to figure out the state
  156. for (ulIndex = 0; ulIndex < m_cItems; ulIndex++)
  157. {
  158. if ((CRIT_TYPE_SECURE == m_rgItems[ulIndex].type) ||
  159. (CRIT_TYPE_BODY == m_rgItems[ulIndex].type) ||
  160. (CRIT_TYPE_ATTACH == m_rgItems[ulIndex].type))
  161. {
  162. dwState = CRIT_STATE_ALL;
  163. }
  164. else if (CRIT_STATE_ALL != dwState)
  165. {
  166. dwState = CRIT_STATE_HEADER;
  167. }
  168. }
  169. // Set the outgoing param
  170. *pdwState = dwState;
  171. // Set the proper return value
  172. hr = S_OK;
  173. exit:
  174. return hr;
  175. }
  176. STDMETHODIMP COECriteria::GetCriteria(DWORD dwFlags, PCRIT_ITEM * ppItem, ULONG * pcItem)
  177. {
  178. HRESULT hr = S_OK;
  179. CRIT_ITEM * pItemNew = NULL;
  180. // Check incoming params
  181. if ((NULL == ppItem) || (0 != dwFlags))
  182. {
  183. hr = E_INVALIDARG;
  184. goto exit;
  185. }
  186. // Initialize the out params
  187. *ppItem = NULL;
  188. if (NULL != pcItem)
  189. {
  190. *pcItem = 0;
  191. }
  192. // If we don't have any criteria, then return
  193. if (0 == m_cItems)
  194. {
  195. hr = E_FAIL;
  196. goto exit;
  197. }
  198. // Allocate space for the criteria
  199. hr = RuleUtil_HrDupCriteriaItem(m_rgItems, m_cItems, &pItemNew);
  200. if (FAILED(hr))
  201. {
  202. goto exit;
  203. }
  204. // Save the criteria
  205. *ppItem = pItemNew;
  206. pItemNew = NULL;
  207. if (NULL != pcItem)
  208. {
  209. *pcItem = m_cItems;
  210. }
  211. exit:
  212. RuleUtil_HrFreeCriteriaItem(pItemNew, m_cItems);
  213. SafeMemFree(pItemNew);
  214. return hr;
  215. }
  216. STDMETHODIMP COECriteria::SetCriteria(DWORD dwFlags, CRIT_ITEM * pItem, ULONG cItem)
  217. {
  218. HRESULT hr = S_OK;
  219. CRIT_ITEM * pItemNew = NULL;
  220. // Check incoming params
  221. if ((NULL == pItem) || (0 == cItem) || (0 != dwFlags))
  222. {
  223. hr = E_INVALIDARG;
  224. goto exit;
  225. }
  226. // If we have any criteria already, then reset
  227. if (0 != m_cItems)
  228. {
  229. Reset();
  230. }
  231. // Allocate space for the criteria
  232. hr = RuleUtil_HrDupCriteriaItem(pItem, cItem, &pItemNew);
  233. if (FAILED(hr))
  234. {
  235. goto exit;
  236. }
  237. // Save the criteria
  238. m_rgItems = pItemNew;
  239. pItemNew = NULL;
  240. m_cItems = cItem;
  241. m_cItemsAlloc = cItem;
  242. exit:
  243. RuleUtil_HrFreeCriteriaItem(pItemNew, cItem);
  244. SafeMemFree(pItemNew);
  245. return hr;
  246. }
  247. ///////////////////////////////////////////////////////////////////////////////
  248. //
  249. // ValidateCriteria
  250. //
  251. // This verifies each of the criteria values
  252. //
  253. // Returns: S_OK, if the criteria were valid
  254. // S_FALSE, otherwise
  255. //
  256. ///////////////////////////////////////////////////////////////////////////////
  257. STDMETHODIMP COECriteria::Validate(DWORD dwFlags)
  258. {
  259. HRESULT hr = S_OK;
  260. ULONG ulIndex = 0;
  261. LPSTR pszText = NULL;
  262. IImnAccount * pAccount = NULL;
  263. FOLDERINFO Folder = {0};
  264. LPTSTR pszWalk = NULL;
  265. ULONG cchText = 0;
  266. RULEFOLDERDATA * prfdData = NULL;
  267. // If we don't have any criteria, then we must be valid
  268. if (0 == m_cItems)
  269. {
  270. hr = S_OK;
  271. goto exit;
  272. }
  273. for (ulIndex = 0; ulIndex < m_cItems; ulIndex++)
  274. {
  275. if (0 != (m_rgItems[ulIndex].dwFlags & ~(CRIT_FLAG_INVERT | CRIT_FLAG_MULTIPLEAND)))
  276. {
  277. hr = S_FALSE;
  278. goto exit;
  279. }
  280. switch(m_rgItems[ulIndex].type)
  281. {
  282. case CRIT_TYPE_NEWSGROUP:
  283. if ((VT_BLOB != m_rgItems[ulIndex].propvar.vt) ||
  284. (0 == m_rgItems[ulIndex].propvar.blob.cbSize))
  285. {
  286. hr = S_FALSE;
  287. goto exit;
  288. }
  289. // Make life simpler
  290. prfdData = (RULEFOLDERDATA *) (m_rgItems[ulIndex].propvar.blob.pBlobData);
  291. // Validate the rule folder data
  292. if (S_OK != RuleUtil_HrValidateRuleFolderData(prfdData))
  293. {
  294. hr = S_FALSE;
  295. goto exit;
  296. }
  297. // Does the folder exist
  298. hr = g_pStore->GetFolderInfo(prfdData->idFolder, &Folder);
  299. if (FAILED(hr))
  300. {
  301. hr = S_FALSE;
  302. goto exit;
  303. }
  304. // Are we subscribed?
  305. if (0 == (Folder.dwFlags & FOLDER_SUBSCRIBED))
  306. {
  307. hr = S_FALSE;
  308. goto exit;
  309. }
  310. break;
  311. case CRIT_TYPE_ALL:
  312. case CRIT_TYPE_JUNK:
  313. case CRIT_TYPE_READ:
  314. case CRIT_TYPE_REPLIES:
  315. case CRIT_TYPE_DOWNLOADED:
  316. case CRIT_TYPE_DELETED:
  317. case CRIT_TYPE_ATTACH:
  318. case CRIT_TYPE_FLAGGED:
  319. if (VT_EMPTY != m_rgItems[ulIndex].propvar.vt)
  320. {
  321. hr = S_FALSE;
  322. goto exit;
  323. }
  324. break;
  325. case CRIT_TYPE_SUBJECT:
  326. case CRIT_TYPE_BODY:
  327. case CRIT_TYPE_TO:
  328. case CRIT_TYPE_CC:
  329. case CRIT_TYPE_TOORCC:
  330. case CRIT_TYPE_FROM:
  331. if ((VT_BLOB != m_rgItems[ulIndex].propvar.vt) ||
  332. (0 == m_rgItems[ulIndex].propvar.blob.cbSize) ||
  333. (NULL == m_rgItems[ulIndex].propvar.blob.pBlobData) ||
  334. ('\0' == m_rgItems[ulIndex].propvar.blob.pBlobData[0]))
  335. {
  336. hr = S_FALSE;
  337. goto exit;
  338. }
  339. // Spin through each item making sure it is perfect
  340. cchText = 0;
  341. for (pszWalk = (LPTSTR) m_rgItems[ulIndex].propvar.blob.pBlobData;
  342. '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  343. {
  344. cchText += lstrlen(pszWalk) + 1;
  345. }
  346. // For the terminator
  347. if ('\0' == pszWalk[0])
  348. {
  349. cchText++;
  350. }
  351. if ('\0' == pszWalk[1])
  352. {
  353. cchText++;
  354. }
  355. if (cchText != m_rgItems[ulIndex].propvar.blob.cbSize)
  356. {
  357. hr = S_FALSE;
  358. goto exit;
  359. }
  360. break;
  361. case CRIT_TYPE_SIZE:
  362. case CRIT_TYPE_THREADSTATE:
  363. case CRIT_TYPE_LINES:
  364. case CRIT_TYPE_PRIORITY:
  365. case CRIT_TYPE_AGE:
  366. case CRIT_TYPE_SECURE:
  367. if (VT_UI4 != m_rgItems[ulIndex].propvar.vt)
  368. {
  369. hr = S_FALSE;
  370. goto exit;
  371. }
  372. break;
  373. case CRIT_TYPE_ACCOUNT:
  374. if ((VT_LPSTR != m_rgItems[ulIndex].propvar.vt) ||
  375. (NULL == m_rgItems[ulIndex].propvar.pszVal))
  376. {
  377. hr = S_FALSE;
  378. goto exit;
  379. }
  380. Assert(g_pAcctMan);
  381. if (FAILED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, m_rgItems[ulIndex].propvar.pszVal, &pAccount)))
  382. {
  383. hr = S_FALSE;
  384. goto exit;
  385. }
  386. SafeRelease(pAccount);
  387. break;
  388. case CRIT_TYPE_SENDER:
  389. {
  390. LPWSTR pwszText = NULL,
  391. pwszVal = NULL;
  392. if ((VT_LPSTR != m_rgItems[ulIndex].propvar.vt) ||
  393. (NULL == m_rgItems[ulIndex].propvar.pszVal))
  394. {
  395. AssertSz(VT_LPWSTR != m_rgItems[ulIndex].propvar.vt, "We are getting UNICODE here.");
  396. hr = S_FALSE;
  397. goto exit;
  398. }
  399. // Verify the email string
  400. pwszVal = PszToUnicode(CP_ACP, m_rgItems[ulIndex].propvar.pszVal);
  401. if (!pwszVal)
  402. {
  403. hr = S_FALSE;
  404. goto exit;
  405. }
  406. hr = RuleUtil_HrParseEmailString(pwszVal, 0, &pwszText, NULL);
  407. MemFree(pwszText);
  408. MemFree(pwszVal);
  409. if (FAILED(hr))
  410. {
  411. hr = S_FALSE;
  412. goto exit;
  413. }
  414. break;
  415. }
  416. default:
  417. hr = S_FALSE;
  418. goto exit;
  419. break;
  420. }
  421. }
  422. // If we got here, then we must be AOK
  423. hr = S_OK;
  424. exit:
  425. g_pStore->FreeRecord(&Folder);
  426. SafeRelease(pAccount);
  427. return hr;
  428. }
  429. STDMETHODIMP COECriteria::AppendCriteria(DWORD dwFlags, CRIT_LOGIC logic,
  430. CRIT_ITEM * pItem, ULONG cItem, ULONG * pcItemAppended)
  431. {
  432. HRESULT hr = S_OK;
  433. CRIT_ITEM * pItemNew = NULL;
  434. // Check incoming parameters
  435. if ((0 != dwFlags) || (CRIT_LOGIC_NULL == logic) || (NULL == pItem) || (0 == cItem))
  436. {
  437. hr = E_INVALIDARG;
  438. goto exit;
  439. }
  440. // Let's init our outgoing parameters
  441. if (NULL != pcItemAppended)
  442. {
  443. *pcItemAppended = 0;
  444. }
  445. // Do we have to add more items?
  446. if (m_cItems == m_cItemsAlloc)
  447. {
  448. hr = HrRealloc((LPVOID *) &m_rgItems, sizeof(CRIT_ITEM) * (m_cItemsAlloc + CRIT_GROW));
  449. if (FAILED(hr))
  450. {
  451. goto exit;
  452. }
  453. ZeroMemory(m_rgItems + m_cItemsAlloc, sizeof(CRIT_ITEM) * CRIT_GROW);
  454. m_cItemsAlloc += CRIT_GROW;
  455. }
  456. // Let's duplicate the items that need to be added
  457. hr = RuleUtil_HrDupCriteriaItem(pItem, cItem, &pItemNew);
  458. if (FAILED(hr))
  459. {
  460. goto exit;
  461. }
  462. // Let's add them to the criteria array
  463. if (0 != m_cItems)
  464. {
  465. m_rgItems[m_cItems - 1].logic = logic;
  466. }
  467. CopyMemory(m_rgItems + m_cItems, pItemNew, sizeof(CRIT_ITEM) * cItem);
  468. m_cItems += cItem;
  469. // Set the proper outgoing parameter
  470. if (NULL != pcItemAppended)
  471. {
  472. *pcItemAppended = cItem;
  473. }
  474. // Set the proper return value
  475. hr = S_OK;
  476. exit:
  477. SafeMemFree(pItemNew);
  478. return hr;
  479. }
  480. STDMETHODIMP COECriteria::MatchMessage(LPCSTR pszAcct, MESSAGEINFO * pMsgInfo, IMessageFolder * pFolder,
  481. IMimePropertySet * pIMPropSet, IMimeMessage * pIMMsg, ULONG cbMsgSize)
  482. {
  483. HRESULT hr = S_OK;
  484. ULONG ulIndex = 0;
  485. BOOL fResult = FALSE;
  486. BOOL fResultNew = FALSE;
  487. CRIT_LOGIC logic;
  488. // Check incoming parameters
  489. if (((NULL == pMsgInfo) && (NULL == pIMPropSet)) || (0 == cbMsgSize))
  490. {
  491. hr = E_INVALIDARG;
  492. goto exit;
  493. }
  494. // Let's go through the criteria and see if we match
  495. fResult = FALSE;
  496. logic = CRIT_LOGIC_OR;
  497. for (ulIndex = 0; ulIndex < m_cItems; ulIndex++)
  498. {
  499. // Call matching function for this criteria item
  500. fResultNew = FMatchCritItem(&(m_rgItems[ulIndex]), pszAcct, pMsgInfo, pFolder, pIMPropSet, pIMMsg, cbMsgSize);
  501. // Slap it together with the old result
  502. if (CRIT_LOGIC_AND == logic)
  503. {
  504. fResult = (fResult && fResultNew);
  505. }
  506. else
  507. {
  508. Assert(CRIT_LOGIC_OR == logic);
  509. fResult = (fResult || fResultNew);
  510. }
  511. // Save of the next logical operation
  512. logic = m_rgItems[ulIndex].logic;
  513. }
  514. // Set the proper return value
  515. hr = (FALSE != fResult) ? S_OK : S_FALSE;
  516. exit:
  517. return hr;
  518. }
  519. ///////////////////////////////////////////////////////////////////////////////
  520. //
  521. // LoadReg
  522. //
  523. // This loads in the criteria from the registry. It loads in the criteria
  524. // order from the Order value. The string contains space delimitied values
  525. // and each value contains the subkey name for each criterion. Each criterion
  526. // is loaded in the order that is contained in the Order value. The criterion
  527. // are loaded with the Criterion Type and Logical Operator. The Criterion Value
  528. // Type is loaded if it exists. If a Criterion Value Type exists, then the
  529. // corresponding Criterion Value is loaded in.
  530. //
  531. // pszRegPath - the path to load the criteria from
  532. //
  533. // Returns: S_OK, if the criteria was loaded without problems
  534. // E_OUTOFMEMORY, if we couldn't allocate memory to hold the criteria
  535. // E_FAIL, otherwise
  536. //
  537. ///////////////////////////////////////////////////////////////////////////////
  538. STDMETHODIMP COECriteria::LoadReg(LPCSTR pszRegPath)
  539. {
  540. HRESULT hr = S_OK;
  541. LONG lErr = 0;
  542. HKEY hkeyRoot = NULL;
  543. ULONG cbData = 0;
  544. LPSTR pszOrder = NULL;
  545. ULONG cOrder = 0;
  546. LPSTR pszWalk = NULL;
  547. CRIT_ITEM * pItems = NULL;
  548. LPSTR pszNext = NULL;
  549. ULONG ulOrder = 0;
  550. HKEY hkeyCriteria = NULL;
  551. CRIT_TYPE typeCrit;
  552. CRIT_LOGIC logicCrit;
  553. PROPVARIANT propvar;
  554. DWORD dwType = 0;
  555. BYTE * pbData = NULL;
  556. DWORD dwFlags = CRIT_FLAG_DEFAULT;
  557. // Check incoming param
  558. if (NULL == pszRegPath)
  559. {
  560. hr = E_INVALIDARG;
  561. goto exit;
  562. }
  563. // Should we fail if we're already loaded?
  564. AssertSz(0 == (m_dwState & CRIT_STATE_LOADED), "We're already loaded!!!");
  565. // Open the reg key from the path
  566. lErr = AthUserOpenKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot);
  567. if (ERROR_SUCCESS != lErr)
  568. {
  569. hr = E_FAIL;
  570. goto exit;
  571. }
  572. // Get the criteria order
  573. hr = RuleUtil_HrGetRegValue(hkeyRoot, c_szCriteriaOrder, NULL, (BYTE **) &pszOrder, &cbData);
  574. if (FAILED(hr))
  575. {
  576. goto exit;
  577. }
  578. // Make sure we actually have something to load
  579. if ('\0' == *pszOrder)
  580. {
  581. AssertSz(FALSE, "The order string for the criteria is mis-formatted in the registry");
  582. hr = E_FAIL;
  583. goto exit;
  584. }
  585. // Convert the criteria string to a more useful format
  586. pszWalk = pszOrder;
  587. cOrder = 1;
  588. for (pszWalk = StrStr(pszOrder, g_szSpace); NULL != pszWalk; pszWalk = StrStr(pszWalk, g_szSpace))
  589. {
  590. // Terminate the order item
  591. *pszWalk = '\0';
  592. pszWalk++;
  593. cOrder++;
  594. }
  595. // Allocate the space to hold all the criteria
  596. hr = HrAlloc((void **) &pItems, cOrder * sizeof(CRIT_ITEM));
  597. if (FAILED(hr))
  598. {
  599. goto exit;
  600. }
  601. // Initialize it to a known value
  602. ZeroMemory(pItems, cOrder * sizeof(CRIT_ITEM));
  603. // For each criteria in the order string
  604. pszWalk = pszOrder;
  605. for (ulOrder = 0, pszWalk = pszOrder; ulOrder < cOrder; ulOrder++, pszWalk += lstrlen(pszWalk) + 1)
  606. {
  607. // Open up the criteria reg key
  608. lErr = RegOpenKeyEx(hkeyRoot, pszWalk, 0, KEY_READ, &hkeyCriteria);
  609. if (ERROR_SUCCESS != lErr)
  610. {
  611. AssertSz(FALSE, "Part of the criteria is mis-formatted in the registry");
  612. hr = E_FAIL;
  613. goto exit;
  614. }
  615. // Get the criteria type
  616. cbData = sizeof(typeCrit);
  617. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaType, 0, NULL,
  618. (BYTE *) &(typeCrit), &cbData);
  619. if (ERROR_SUCCESS != lErr)
  620. {
  621. hr = E_FAIL;
  622. goto exit;
  623. }
  624. // Get the criteria logicial op
  625. cbData = sizeof(logicCrit);
  626. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaLogic, 0, NULL,
  627. (BYTE *) &(logicCrit), &cbData);
  628. if (ERROR_SUCCESS != lErr)
  629. {
  630. hr = E_FAIL;
  631. goto exit;
  632. }
  633. // Get the criteria flags
  634. cbData = sizeof(dwFlags);
  635. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaFlags, 0, NULL,
  636. (BYTE *) &(dwFlags), &cbData);
  637. if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr))
  638. {
  639. hr = E_FAIL;
  640. goto exit;
  641. }
  642. // If it didn't exist then assign it to the default
  643. if (ERROR_FILE_NOT_FOUND == lErr)
  644. {
  645. dwFlags = CRIT_FLAG_DEFAULT;
  646. }
  647. // Initialize the new space to a known value
  648. ZeroMemory(&propvar, sizeof(propvar));
  649. // Does a criteria value type exist
  650. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaValueType, 0, NULL, NULL, &cbData);
  651. if ((ERROR_SUCCESS == lErr) && (0 != cbData))
  652. {
  653. // Load the criteria value in
  654. cbData = sizeof(dwType);
  655. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaValueType, 0, NULL,
  656. (BYTE *) &dwType, &cbData);
  657. if (ERROR_SUCCESS != lErr)
  658. {
  659. hr = E_FAIL;
  660. goto exit;
  661. }
  662. propvar.vt = (VARTYPE) dwType;
  663. switch (propvar.vt)
  664. {
  665. case VT_UI4:
  666. // Get the criteria value
  667. cbData = sizeof(propvar.ulVal);
  668. lErr = RegQueryValueEx(hkeyCriteria, c_szCriteriaValue, 0, NULL,
  669. (BYTE * ) &(propvar.ulVal), &cbData);
  670. if (ERROR_SUCCESS != lErr)
  671. {
  672. hr = E_FAIL;
  673. goto exit;
  674. }
  675. break;
  676. case VT_LPSTR:
  677. case VT_BLOB:
  678. // Get the criteria value
  679. hr = RuleUtil_HrGetRegValue(hkeyCriteria, c_szCriteriaValue, NULL, (BYTE **) &pbData, &cbData);
  680. if (FAILED(hr))
  681. {
  682. goto exit;
  683. }
  684. // Save the space so we can free it
  685. if (VT_LPSTR == propvar.vt)
  686. {
  687. propvar.pszVal = (LPSTR) pbData;
  688. }
  689. else
  690. {
  691. propvar.blob.cbSize = cbData;
  692. propvar.blob.pBlobData = pbData;
  693. }
  694. pbData = NULL;
  695. break;
  696. default:
  697. AssertSz(FALSE, "Why are we loading in a invalid criteria type?");
  698. hr = E_FAIL;
  699. goto exit;
  700. break;
  701. }
  702. }
  703. // Save the value into the criteria array
  704. pItems[ulOrder].type = typeCrit;
  705. pItems[ulOrder].dwFlags = dwFlags;
  706. pItems[ulOrder].logic = logicCrit;
  707. pItems[ulOrder].propvar = propvar;
  708. // Close the criteria
  709. SideAssert(ERROR_SUCCESS == RegCloseKey(hkeyCriteria));
  710. hkeyCriteria = NULL;
  711. }
  712. // Free up the current criteria
  713. SafeMemFree(m_rgItems);
  714. // Save the new values
  715. m_rgItems = pItems;
  716. pItems = NULL;
  717. m_cItems = cOrder;
  718. // Make sure we clear the dirty bit
  719. m_dwState &= ~CRIT_STATE_DIRTY;
  720. // Note that we have been loaded
  721. m_dwState |= CRIT_STATE_LOADED;
  722. // Set the return value
  723. hr = S_OK;
  724. exit:
  725. SafeMemFree(pbData);
  726. RuleUtil_HrFreeCriteriaItem(pItems, cOrder);
  727. SafeMemFree(pItems);
  728. SafeMemFree(pszOrder);
  729. if (NULL != hkeyCriteria)
  730. {
  731. RegCloseKey(hkeyCriteria);
  732. }
  733. if (NULL != hkeyRoot)
  734. {
  735. RegCloseKey(hkeyRoot);
  736. }
  737. return hr;
  738. }
  739. STDMETHODIMP COECriteria::SaveReg(LPCSTR pszRegPath, BOOL fClearDirty)
  740. {
  741. HRESULT hr = S_OK;
  742. LONG lErr = 0;
  743. HKEY hkeyRoot = NULL;
  744. DWORD dwDisp = 0;
  745. LPSTR pszOrder = NULL;
  746. ULONG ulIndex = 0;
  747. CRIT_ITEM * pItem = NULL;
  748. CHAR rgchTag[CCH_CRIT_ORDER];
  749. HKEY hkeyCriteria = NULL;
  750. ULONG cbData = 0;
  751. BYTE * pbData = NULL;
  752. // Check incoming param
  753. if (NULL == pszRegPath)
  754. {
  755. hr = E_INVALIDARG;
  756. goto exit;
  757. }
  758. // If there's nothing to save, then fail
  759. if (NULL == m_rgItems)
  760. {
  761. hr = E_FAIL;
  762. goto exit;
  763. }
  764. // Let's make sure we clear out the key first
  765. AthUserDeleteKey(pszRegPath);
  766. // Create the reg key from the path
  767. lErr = AthUserCreateKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp);
  768. if (ERROR_SUCCESS != lErr)
  769. {
  770. hr = E_FAIL;
  771. goto exit;
  772. }
  773. Assert(REG_CREATED_NEW_KEY == dwDisp);
  774. Assert(m_cItems < CRIT_COUNT_MAX);
  775. // Allocate space to hold the order
  776. DWORD cchSize = (m_cItems * CCH_CRIT_ORDER);
  777. hr = HrAlloc((void **) &pszOrder, cchSize * sizeof(*pszOrder));
  778. if (FAILED(hr))
  779. {
  780. goto exit;
  781. }
  782. pszOrder[0] = '\0';
  783. // Write out each of the criteria
  784. for (ulIndex = 0, pItem = m_rgItems; ulIndex < m_cItems; ulIndex++, pItem++)
  785. {
  786. // Get the new criteria tag
  787. wnsprintf(rgchTag, ARRAYSIZE(rgchTag), "%03X", ulIndex);
  788. // Add the new tag to the order
  789. if (0 != ulIndex)
  790. {
  791. StrCatBuff(pszOrder, g_szSpace, cchSize);
  792. }
  793. StrCatBuff(pszOrder, rgchTag, cchSize);
  794. // Create the new criteria
  795. lErr = RegCreateKeyEx(hkeyRoot, rgchTag, 0, NULL,
  796. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyCriteria, &dwDisp);
  797. if (ERROR_SUCCESS != lErr)
  798. {
  799. hr = E_FAIL;
  800. goto exit;
  801. }
  802. Assert(REG_CREATED_NEW_KEY == dwDisp);
  803. // Write out the criteria type
  804. lErr = RegSetValueEx(hkeyCriteria, c_szCriteriaType, 0, REG_DWORD,
  805. (BYTE *) &(pItem->type), sizeof(pItem->type));
  806. if (ERROR_SUCCESS != lErr)
  807. {
  808. hr = E_FAIL;
  809. goto exit;
  810. }
  811. // Write out the criteria logicial op
  812. lErr = RegSetValueEx(hkeyCriteria, c_szCriteriaLogic, 0, REG_DWORD,
  813. (BYTE *) &(pItem->logic), sizeof(pItem->logic));
  814. if (ERROR_SUCCESS != lErr)
  815. {
  816. hr = E_FAIL;
  817. goto exit;
  818. }
  819. // Write out the criteria flags
  820. lErr = RegSetValueEx(hkeyCriteria, c_szCriteriaFlags, 0, REG_DWORD,
  821. (BYTE *) &(pItem->dwFlags), sizeof(pItem->dwFlags));
  822. if (ERROR_SUCCESS != lErr)
  823. {
  824. hr = E_FAIL;
  825. goto exit;
  826. }
  827. // Do we have a criteria value?
  828. if (VT_EMPTY != pItem->propvar.vt)
  829. {
  830. // Write out the criteria value type
  831. dwDisp = pItem->propvar.vt;
  832. lErr = RegSetValueEx(hkeyCriteria, c_szCriteriaValueType, 0, REG_DWORD, (BYTE *) &dwDisp, sizeof(dwDisp));
  833. if (ERROR_SUCCESS != lErr)
  834. {
  835. hr = E_FAIL;
  836. goto exit;
  837. }
  838. // Write out the criteria value
  839. switch (pItem->propvar.vt)
  840. {
  841. case VT_UI4:
  842. dwDisp = REG_DWORD;
  843. pbData = (BYTE * ) &(pItem->propvar.ulVal);
  844. cbData = sizeof(pItem->propvar.ulVal);
  845. break;
  846. case VT_LPSTR:
  847. dwDisp = REG_SZ;
  848. pbData = (BYTE * ) (pItem->propvar.pszVal);
  849. cbData = lstrlen(pItem->propvar.pszVal) + 1;
  850. break;
  851. case VT_BLOB:
  852. dwDisp = REG_BINARY;
  853. pbData = pItem->propvar.blob.pBlobData;
  854. cbData = pItem->propvar.blob.cbSize;
  855. break;
  856. default:
  857. AssertSz(FALSE, "Why are we trying to save in a invalid criteria type?");
  858. hr = E_FAIL;
  859. goto exit;
  860. break;
  861. }
  862. // Write out the criteria value
  863. lErr = RegSetValueEx(hkeyCriteria, c_szCriteriaValue, 0, dwDisp, pbData, cbData);
  864. if (ERROR_SUCCESS != lErr)
  865. {
  866. hr = E_FAIL;
  867. goto exit;
  868. }
  869. }
  870. // Close the criteria
  871. SideAssert(ERROR_SUCCESS == RegCloseKey(hkeyCriteria));
  872. hkeyCriteria = NULL;
  873. }
  874. // Write out the order string.
  875. lErr = RegSetValueEx(hkeyRoot, c_szCriteriaOrder, 0, REG_SZ,
  876. (BYTE *) pszOrder, lstrlen(pszOrder) + 1);
  877. if (ERROR_SUCCESS != lErr)
  878. {
  879. hr = E_FAIL;
  880. goto exit;
  881. }
  882. // Should we clear the dirty bit?
  883. if (FALSE != fClearDirty)
  884. {
  885. m_dwState &= ~CRIT_STATE_DIRTY;
  886. }
  887. // Set the return value
  888. hr = S_OK;
  889. exit:
  890. if (NULL != hkeyCriteria)
  891. {
  892. RegCloseKey(hkeyCriteria);
  893. }
  894. SafeMemFree(pszOrder);
  895. if (NULL != hkeyRoot)
  896. {
  897. RegCloseKey(hkeyRoot);
  898. }
  899. return hr;
  900. }
  901. STDMETHODIMP COECriteria::Clone(IOECriteria ** ppICriteria)
  902. {
  903. HRESULT hr = S_OK;
  904. COECriteria * pCriteria = NULL;
  905. // Check incoming params
  906. if (NULL == ppICriteria)
  907. {
  908. hr = E_INVALIDARG;
  909. goto exit;
  910. }
  911. // Initialize the outgoing params
  912. *ppICriteria = NULL;
  913. // Create a new criteria
  914. pCriteria = new COECriteria;
  915. if (NULL == pCriteria)
  916. {
  917. hr = E_OUTOFMEMORY;
  918. goto exit;
  919. }
  920. // Copy over the list of criteria
  921. hr = pCriteria->SetCriteria(0, m_rgItems, m_cItems);
  922. if (FAILED(hr))
  923. {
  924. goto exit;
  925. }
  926. // Get the criteria interface
  927. hr = pCriteria->QueryInterface(IID_IOECriteria, (void **) ppICriteria);
  928. if (FAILED(hr))
  929. {
  930. goto exit;
  931. }
  932. pCriteria = NULL;
  933. // Set the proper return value
  934. hr = S_OK;
  935. exit:
  936. if (NULL != pCriteria)
  937. {
  938. delete pCriteria;
  939. }
  940. return hr;
  941. }
  942. STDMETHODIMP COECriteria::GetClassID(CLSID * pclsid)
  943. {
  944. HRESULT hr = S_OK;
  945. if (NULL == pclsid)
  946. {
  947. hr = E_INVALIDARG;
  948. goto exit;
  949. }
  950. *pclsid = CLSID_OECriteria;
  951. // Set the proper return value
  952. hr = S_OK;
  953. exit:
  954. return hr;
  955. }
  956. STDMETHODIMP COECriteria::IsDirty(void)
  957. {
  958. HRESULT hr = S_OK;
  959. hr = (CRIT_STATE_DIRTY == (m_dwState & CRIT_STATE_DIRTY)) ? S_OK : S_FALSE;
  960. return hr;
  961. }
  962. STDMETHODIMP COECriteria::Load(IStream * pStm)
  963. {
  964. HRESULT hr = S_OK;
  965. ULONG cbData = 0;
  966. ULONG cbRead = 0;
  967. DWORD dwData = 0;
  968. ULONG cItems = 0;
  969. CRIT_ITEM * pItems = NULL;
  970. ULONG ulIndex = 0;
  971. CRIT_ITEM * pItem = NULL;
  972. CRIT_TYPE typeCrit;
  973. CRIT_LOGIC logicCrit;
  974. DWORD dwFlags = CRIT_FLAG_DEFAULT;
  975. PROPVARIANT propvar = {0};
  976. BYTE * pbData = NULL;
  977. // Check incoming param
  978. if (NULL == pStm)
  979. {
  980. hr = E_INVALIDARG;
  981. goto exit;
  982. }
  983. // Verify we have the correct version
  984. hr = pStm->Read(&dwData, sizeof(dwData), &cbRead);
  985. if (FAILED(hr))
  986. {
  987. goto exit;
  988. }
  989. if ((cbRead != sizeof(dwData)) || (dwData != CRIT_VERSION))
  990. {
  991. hr = E_FAIL;
  992. goto exit;
  993. }
  994. // Get the number of criteria
  995. hr = pStm->Read(&cItems, sizeof(cItems), &cbRead);
  996. if (FAILED(hr))
  997. {
  998. goto exit;
  999. }
  1000. if ((cbRead != sizeof(cItems)) || (0 == cItems))
  1001. {
  1002. hr = E_FAIL;
  1003. goto exit;
  1004. }
  1005. // Allocate space to hold all the criteria
  1006. hr = HrAlloc( (void **) &pItems, cItems * sizeof(*pItems));
  1007. if (FAILED(hr))
  1008. {
  1009. goto exit;
  1010. }
  1011. // Initialize the criteria to a known value
  1012. ZeroMemory(pItems, cItems * sizeof(*pItems));
  1013. // for each criteria
  1014. for (ulIndex = 0, pItem = pItems; ulIndex < cItems; ulIndex++, pItem++)
  1015. {
  1016. // Read in the criteria type
  1017. hr = pStm->Read(&typeCrit, sizeof(typeCrit), &cbRead);
  1018. if ((FAILED(hr)) || (cbRead != sizeof(typeCrit)))
  1019. {
  1020. hr = E_FAIL;
  1021. goto exit;
  1022. }
  1023. // Read in the criteria logical op
  1024. hr = pStm->Read(&logicCrit, sizeof(logicCrit), &cbRead);
  1025. if ((FAILED(hr)) || (cbRead != sizeof(logicCrit)))
  1026. {
  1027. hr = E_FAIL;
  1028. goto exit;
  1029. }
  1030. // Read in the criteria flags
  1031. hr = pStm->Read(&dwFlags, sizeof(dwFlags), &cbRead);
  1032. if ((FAILED(hr)) || (cbRead != sizeof(dwFlags)))
  1033. {
  1034. hr = E_FAIL;
  1035. goto exit;
  1036. }
  1037. // Read in the proper criteria value
  1038. switch(typeCrit)
  1039. {
  1040. case CRIT_TYPE_ACCOUNT:
  1041. if (FALSE == FCritLoad_Account(pStm, &propvar))
  1042. {
  1043. hr = E_FAIL;
  1044. goto exit;
  1045. }
  1046. break;
  1047. default:
  1048. if (FALSE == FCritLoad_Default(pStm, &propvar))
  1049. {
  1050. hr = E_FAIL;
  1051. goto exit;
  1052. }
  1053. break;
  1054. }
  1055. // Assign the values
  1056. pItem->type = typeCrit;
  1057. pItem->logic = logicCrit;
  1058. pItem->dwFlags = dwFlags;
  1059. pItem->propvar = propvar;
  1060. ZeroMemory(&propvar, sizeof(propvar));
  1061. }
  1062. // Free up the current criteria
  1063. SafeMemFree(m_rgItems);
  1064. // Save the new values
  1065. m_rgItems = pItems;
  1066. pItems = NULL;
  1067. m_cItems = cItems;
  1068. // Make sure we clear the dirty bit
  1069. m_dwState &= ~CRIT_STATE_DIRTY;
  1070. // Note that we have been loaded
  1071. m_dwState |= CRIT_STATE_LOADED;
  1072. // Set the return value
  1073. hr = S_OK;
  1074. exit:
  1075. RuleUtil_HrFreeCriteriaItem(pItems, cItems);
  1076. SafeMemFree(pItems);
  1077. PropVariantClear(&propvar);
  1078. return hr;
  1079. }
  1080. STDMETHODIMP COECriteria::Save(IStream * pStm, BOOL fClearDirty)
  1081. {
  1082. HRESULT hr = S_OK;
  1083. ULONG cbData = 0;
  1084. ULONG cbWritten = 0;
  1085. DWORD dwData = 0;
  1086. ULONG ulIndex = 0;
  1087. CRIT_ITEM * pItem = NULL;
  1088. BYTE * pbData = NULL;
  1089. // Check incoming param
  1090. if (NULL == pStm)
  1091. {
  1092. hr = E_INVALIDARG;
  1093. goto exit;
  1094. }
  1095. // Write out the version
  1096. dwData = CRIT_VERSION;
  1097. hr = pStm->Write(&dwData, sizeof(dwData), &cbWritten);
  1098. if (FAILED(hr))
  1099. {
  1100. goto exit;
  1101. }
  1102. Assert(cbWritten == sizeof(dwData));
  1103. // Write out the count of criteria
  1104. hr = pStm->Write(&m_cItems, sizeof(m_cItems), &cbWritten);
  1105. if (FAILED(hr))
  1106. {
  1107. goto exit;
  1108. }
  1109. Assert(cbWritten == sizeof(m_cItems));
  1110. // Loop through each of the criteria
  1111. for (ulIndex = 0, pItem = m_rgItems; ulIndex < m_cItems; ulIndex++, pItem++)
  1112. {
  1113. // Write out the criteria type
  1114. hr = pStm->Write(&(pItem->type), sizeof(pItem->type), &cbWritten);
  1115. if (FAILED(hr))
  1116. {
  1117. goto exit;
  1118. }
  1119. Assert(cbWritten == sizeof(pItem->type));
  1120. // Write out the criteria logical op
  1121. hr = pStm->Write(&(pItem->logic), sizeof(pItem->logic), &cbWritten);
  1122. if (FAILED(hr))
  1123. {
  1124. goto exit;
  1125. }
  1126. Assert(cbWritten == sizeof(pItem->logic));
  1127. // Write out the criteria flags
  1128. hr = pStm->Write(&(pItem->dwFlags), sizeof(pItem->dwFlags), &cbWritten);
  1129. if (FAILED(hr))
  1130. {
  1131. goto exit;
  1132. }
  1133. Assert(cbWritten == sizeof(pItem->dwFlags));
  1134. // Write out the proper criteria value
  1135. switch(pItem->type)
  1136. {
  1137. case CRIT_TYPE_ACCOUNT:
  1138. if (FALSE == FCritSave_Account(pStm, &(pItem->propvar)))
  1139. {
  1140. hr = E_FAIL;
  1141. goto exit;
  1142. }
  1143. break;
  1144. default:
  1145. if (FALSE == FCritSave_Default(pStm, &(pItem->propvar)))
  1146. {
  1147. hr = E_FAIL;
  1148. goto exit;
  1149. }
  1150. break;
  1151. }
  1152. }
  1153. // Should we clear out the dirty bit
  1154. if (FALSE != fClearDirty)
  1155. {
  1156. m_dwState &= ~CRIT_STATE_DIRTY;
  1157. }
  1158. // Set the return value
  1159. hr = S_OK;
  1160. exit:
  1161. return hr;
  1162. }
  1163. BOOL CritFunc_Query(CRIT_ITEM * pItem, LPCSTR pszQuery, IMimePropertySet * pIMPropSet);
  1164. BOOL CritFunc_Text(CRIT_ITEM * pItem, LPSTR pszText);
  1165. BOOL CritFunc_Sender(CRIT_ITEM * pItem, LPSTR pszAddr);
  1166. BOOL CritFunc_Priority(CRIT_ITEM * pItem, WORD wPriority);
  1167. BOOL CritFunc_Secure(CRIT_ITEM * pItem, DWORD dwFlags);
  1168. BOOL CritFunc_Age(CRIT_ITEM * pItem, FILETIME * pftSent);
  1169. BOOL CritFunc_Body(CRIT_ITEM * pItem, IMimeMessage * pIMMsg);
  1170. BOOL _FMatchBlobString(CRIT_ITEM * pItem, LPSTR pszText);
  1171. BOOL _FQueryBlobString(CRIT_ITEM * pItem, LPCSTR pszQuery, IMimePropertySet * pIMPropSet);
  1172. BOOL FMatchCritItem(CRIT_ITEM * pItem, LPCSTR pszAcct, MESSAGEINFO * pMsgInfo,
  1173. IMessageFolder * pFolder, IMimePropertySet * pIMPropSet,
  1174. IMimeMessage * pIMMsg, ULONG cbMsgSize)
  1175. {
  1176. BOOL fRet = FALSE;
  1177. ULONG ulIndex = 0;
  1178. PROPVARIANT propvar = {0};
  1179. ADDRESSLIST addrList = {0};
  1180. FOLDERID idFolder = 0;
  1181. RULEFOLDERDATA * prfdData = NULL;
  1182. Assert((NULL != pItem) && ((NULL != pMsgInfo) || (NULL != pIMPropSet)) && (0 != cbMsgSize))
  1183. switch (pItem->type)
  1184. {
  1185. case CRIT_TYPE_ALL:
  1186. Assert(VT_EMPTY == pItem->propvar.vt);
  1187. fRet = TRUE;
  1188. break;
  1189. case CRIT_TYPE_ACCOUNT:
  1190. Assert(VT_LPSTR == pItem->propvar.vt);
  1191. fRet = FALSE;
  1192. if ((NULL != pszAcct) && (NULL != pItem->propvar.pszVal))
  1193. {
  1194. fRet = (0 == lstrcmpi(pItem->propvar.pszVal, pszAcct));
  1195. }
  1196. break;
  1197. case CRIT_TYPE_NEWSGROUP:
  1198. Assert(VT_BLOB == pItem->propvar.vt);
  1199. fRet = FALSE;
  1200. if ((NULL != pFolder) && (0 != pItem->propvar.blob.cbSize))
  1201. {
  1202. // Make life simpler
  1203. prfdData = (RULEFOLDERDATA *) (pItem->propvar.blob.pBlobData);
  1204. // Validate the rule folder data
  1205. if (S_OK != RuleUtil_HrValidateRuleFolderData(prfdData))
  1206. {
  1207. fRet = FALSE;
  1208. }
  1209. else if (SUCCEEDED(pFolder->GetFolderId(&idFolder)))
  1210. {
  1211. fRet = (idFolder == prfdData->idFolder);
  1212. }
  1213. }
  1214. break;
  1215. case CRIT_TYPE_SIZE:
  1216. Assert(VT_UI4 == pItem->propvar.vt);
  1217. // Set the size of the message to Kilobytes
  1218. cbMsgSize = cbMsgSize / 1024;
  1219. fRet = (cbMsgSize > pItem->propvar.ulVal);
  1220. break;
  1221. case CRIT_TYPE_LINES:
  1222. Assert(VT_UI4 == pItem->propvar.vt);
  1223. fRet = FALSE;
  1224. if (NULL != pMsgInfo)
  1225. {
  1226. fRet = (pMsgInfo->cLines > pItem->propvar.ulVal);
  1227. }
  1228. break;
  1229. case CRIT_TYPE_AGE:
  1230. Assert(VT_UI4 == pItem->propvar.vt);
  1231. fRet = FALSE;
  1232. if (NULL != pMsgInfo)
  1233. {
  1234. fRet = CritFunc_Age(pItem, &(pMsgInfo->ftSent));
  1235. }
  1236. else if ((NULL != pIMPropSet) && (SUCCEEDED(pIMPropSet->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &propvar))))
  1237. {
  1238. fRet = CritFunc_Age(pItem, &(propvar.filetime));
  1239. }
  1240. break;
  1241. case CRIT_TYPE_ATTACH:
  1242. Assert(VT_EMPTY == pItem->propvar.vt);
  1243. fRet = TRUE;
  1244. if (NULL != pMsgInfo)
  1245. {
  1246. fRet = (0 != (pMsgInfo->dwFlags & ARF_HASATTACH));
  1247. }
  1248. else if (NULL != pIMMsg)
  1249. {
  1250. fRet = (0 != (DwGetFlagsFromMessage(pIMMsg) & ARF_HASATTACH));
  1251. }
  1252. break;
  1253. case CRIT_TYPE_PRIORITY:
  1254. Assert(VT_UI4 == pItem->propvar.vt);
  1255. fRet = FALSE;
  1256. if (NULL != pMsgInfo)
  1257. {
  1258. fRet = CritFunc_Priority(pItem, pMsgInfo->wPriority);
  1259. }
  1260. else if ((NULL != pIMPropSet) && (SUCCEEDED(pIMPropSet->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &propvar))))
  1261. {
  1262. fRet = CritFunc_Priority(pItem, (WORD) (propvar.ulVal));
  1263. }
  1264. break;
  1265. case CRIT_TYPE_SECURE:
  1266. Assert(VT_UI4 == pItem->propvar.vt);
  1267. fRet = FALSE;
  1268. if (NULL != pMsgInfo)
  1269. {
  1270. fRet = CritFunc_Secure(pItem, pMsgInfo->dwFlags);
  1271. }
  1272. else if (NULL != pIMMsg)
  1273. {
  1274. fRet = CritFunc_Secure(pItem, DwGetFlagsFromMessage(pIMMsg));
  1275. }
  1276. break;
  1277. case CRIT_TYPE_TOORCC:
  1278. Assert(VT_BLOB == pItem->propvar.vt);
  1279. fRet = FALSE;
  1280. if (NULL != pIMPropSet)
  1281. {
  1282. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_TO), pIMPropSet);
  1283. if (((0 != (pItem->dwFlags & CRIT_FLAG_INVERT)) && (FALSE != fRet)) ||
  1284. ((0 == (pItem->dwFlags & CRIT_FLAG_INVERT)) && (FALSE == fRet)))
  1285. {
  1286. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_CC), pIMPropSet);
  1287. }
  1288. }
  1289. break;
  1290. case CRIT_TYPE_SENDER:
  1291. Assert(VT_LPSTR == pItem->propvar.vt);
  1292. fRet = FALSE;
  1293. if ((NULL == pItem->propvar.pszVal) || ('\0' == pItem->propvar.pszVal[0]))
  1294. {
  1295. Assert(FALSE);
  1296. }
  1297. else if (S_OK == RuleUtil_HrMatchSender(pItem->propvar.pszVal, pMsgInfo, pIMMsg, pIMPropSet))
  1298. {
  1299. fRet = TRUE;
  1300. }
  1301. break;
  1302. case CRIT_TYPE_SUBJECT:
  1303. Assert(VT_BLOB == pItem->propvar.vt);
  1304. fRet = FALSE;
  1305. if ((0 == pItem->propvar.blob.cbSize) ||
  1306. (NULL == pItem->propvar.blob.pBlobData) ||
  1307. ('\0' == pItem->propvar.blob.pBlobData[0]))
  1308. {
  1309. Assert(FALSE);
  1310. fRet = FALSE;
  1311. }
  1312. else if ((NULL != pMsgInfo) && (NULL != pMsgInfo->pszSubject))
  1313. {
  1314. fRet = _FMatchBlobString(pItem, pMsgInfo->pszSubject);
  1315. }
  1316. else
  1317. {
  1318. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_SUBJECT), pIMPropSet);
  1319. }
  1320. break;
  1321. case CRIT_TYPE_BODY:
  1322. Assert(VT_BLOB == pItem->propvar.vt);
  1323. fRet = FALSE;
  1324. if ((0 == pItem->propvar.blob.cbSize) ||
  1325. (NULL == pItem->propvar.blob.pBlobData) ||
  1326. ('\0' == pItem->propvar.blob.pBlobData[0]))
  1327. {
  1328. Assert(FALSE);
  1329. fRet = FALSE;
  1330. }
  1331. else if (NULL != pIMMsg)
  1332. {
  1333. fRet = CritFunc_Body(pItem, pIMMsg);
  1334. }
  1335. break;
  1336. case CRIT_TYPE_FROM:
  1337. Assert(VT_BLOB == pItem->propvar.vt);
  1338. fRet = FALSE;
  1339. if ((0 == pItem->propvar.blob.cbSize) ||
  1340. (NULL == pItem->propvar.blob.pBlobData) ||
  1341. ('\0' == pItem->propvar.blob.pBlobData[0]))
  1342. {
  1343. Assert(FALSE);
  1344. fRet = FALSE;
  1345. }
  1346. else if ((NULL != pMsgInfo) && (NULL != pMsgInfo->pszFromHeader))
  1347. {
  1348. fRet = _FMatchBlobString(pItem, pMsgInfo->pszFromHeader);
  1349. }
  1350. else
  1351. {
  1352. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_FROM), pIMPropSet);
  1353. }
  1354. break;
  1355. case CRIT_TYPE_TO:
  1356. Assert(VT_BLOB == pItem->propvar.vt);
  1357. fRet = FALSE;
  1358. if ((0 == pItem->propvar.blob.cbSize) ||
  1359. (NULL == pItem->propvar.blob.pBlobData) ||
  1360. ('\0' == pItem->propvar.blob.pBlobData[0]))
  1361. {
  1362. Assert(FALSE);
  1363. fRet = FALSE;
  1364. }
  1365. else
  1366. {
  1367. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_TO), pIMPropSet);
  1368. }
  1369. break;
  1370. case CRIT_TYPE_CC:
  1371. Assert(VT_BLOB == pItem->propvar.vt);
  1372. fRet = FALSE;
  1373. if ((0 == pItem->propvar.blob.cbSize) ||
  1374. (NULL == pItem->propvar.blob.pBlobData) ||
  1375. ('\0' == pItem->propvar.blob.pBlobData[0]))
  1376. {
  1377. Assert(FALSE);
  1378. fRet = FALSE;
  1379. }
  1380. else
  1381. {
  1382. fRet = _FQueryBlobString(pItem, PIDTOSTR(PID_HDR_CC), pIMPropSet);
  1383. }
  1384. break;
  1385. default:
  1386. fRet = FALSE;
  1387. break;
  1388. }
  1389. PropVariantClear(&propvar);
  1390. return fRet;
  1391. }
  1392. BOOL CritFunc_Query(CRIT_ITEM * pItem, LPCSTR pszQuery, IMimePropertySet * pIMPropSet)
  1393. {
  1394. BOOL fRet = FALSE;
  1395. LPSTR pszWalk = NULL;
  1396. LPSTR pszAddr = NULL;
  1397. LPSTR pszTerm = NULL;
  1398. HRESULT hr = S_OK;
  1399. if (NULL == pIMPropSet)
  1400. {
  1401. fRet = FALSE;
  1402. goto exit;
  1403. }
  1404. // Dup the string
  1405. pszAddr = PszDupA(pItem->propvar.pszVal);
  1406. if (NULL == pszAddr)
  1407. {
  1408. fRet = FALSE;
  1409. goto exit;
  1410. }
  1411. pszWalk = pszAddr;
  1412. pszTerm = pszWalk;
  1413. while (NULL != pszTerm)
  1414. {
  1415. pszTerm = StrStr(pszWalk, g_szComma);
  1416. if (NULL != pszTerm)
  1417. {
  1418. pszTerm[0] = '\0';
  1419. }
  1420. fRet = (S_OK == pIMPropSet->QueryProp(pszQuery, pszWalk, TRUE, FALSE));
  1421. if (FALSE == fRet)
  1422. {
  1423. break;
  1424. }
  1425. pszWalk = pszWalk + lstrlen(pszWalk) + 1;
  1426. }
  1427. exit:
  1428. SafeMemFree(pszAddr);
  1429. return fRet;
  1430. }
  1431. BOOL CritFunc_Priority(CRIT_ITEM * pItem, WORD wPriority)
  1432. {
  1433. BOOL fRet = FALSE;
  1434. Assert(NULL != pItem);
  1435. Assert(VT_UI4 == pItem->propvar.vt);
  1436. if (CRIT_DATA_HIPRI == pItem->propvar.ulVal)
  1437. {
  1438. fRet = (wPriority == (WORD) IMSG_PRI_HIGH);
  1439. }
  1440. else if (CRIT_DATA_LOPRI == pItem->propvar.ulVal)
  1441. {
  1442. fRet = (wPriority == (WORD) IMSG_PRI_LOW);
  1443. }
  1444. else
  1445. {
  1446. fRet = (wPriority == (WORD) IMSG_PRI_NORMAL);
  1447. }
  1448. return fRet;
  1449. }
  1450. BOOL CritFunc_Secure(CRIT_ITEM * pItem, DWORD dwFlags)
  1451. {
  1452. BOOL fRet = FALSE;
  1453. Assert(NULL != pItem);
  1454. Assert(VT_UI4 == pItem->propvar.vt);
  1455. // Should we be checking signed messages
  1456. if (0 != (pItem->propvar.ulVal & CRIT_DATA_SIGNEDSECURE))
  1457. {
  1458. fRet = (0 != (dwFlags & ARF_SIGNED));
  1459. }
  1460. else if (0 != (pItem->propvar.ulVal & CRIT_DATA_ENCRYPTSECURE))
  1461. // Should we be checking encrypted messages
  1462. {
  1463. fRet = (0 != (dwFlags & ARF_ENCRYPTED));
  1464. }
  1465. else
  1466. {
  1467. fRet = (0 == (dwFlags & (ARF_ENCRYPTED | ARF_SIGNED)));
  1468. }
  1469. return fRet;
  1470. }
  1471. BOOL CritFunc_Age(CRIT_ITEM * pItem, FILETIME * pftSent)
  1472. {
  1473. BOOL fRet = FALSE;
  1474. SYSTEMTIME sysTime = {0};
  1475. FILETIME ftTime = {0};
  1476. ULONG ulSeconds;
  1477. Assert(VT_UI4 == pItem->propvar.vt);
  1478. if ((NULL == pftSent) || ((0 == pftSent->dwLowDateTime) && (0 == pftSent->dwHighDateTime)))
  1479. {
  1480. fRet = FALSE;
  1481. goto exit;
  1482. }
  1483. // Get the current time
  1484. GetSystemTime(&sysTime);
  1485. SystemTimeToFileTime(&sysTime, &ftTime);
  1486. ulSeconds = UlDateDiff(pftSent, &ftTime);
  1487. fRet = ((ulSeconds / SECONDS_INA_DAY) > pItem->propvar.ulVal);
  1488. exit:
  1489. return fRet;
  1490. }
  1491. BOOL CritFunc_Sender(CRIT_ITEM * pItem, LPSTR pszAddr)
  1492. {
  1493. BOOL fRet = FALSE;
  1494. ULONG cchVal = 0;
  1495. ULONG cchEmail = 0;
  1496. CHAR chTest = 0;
  1497. Assert(VT_LPSTR == pItem->propvar.vt);
  1498. // Check to make sure that there's something to match
  1499. if ((NULL == pszAddr) || ('\0' == pszAddr[0]))
  1500. {
  1501. fRet = FALSE;
  1502. goto exit;
  1503. }
  1504. // Check to see if it is an address
  1505. if (NULL != StrStr(pItem->propvar.pszVal, "@"))
  1506. {
  1507. fRet = (0 == lstrcmpi(pItem->propvar.pszVal, pszAddr));
  1508. }
  1509. else
  1510. {
  1511. cchVal = lstrlen(pItem->propvar.pszVal);
  1512. cchEmail = lstrlen(pszAddr);
  1513. if (cchVal <= cchEmail)
  1514. {
  1515. fRet = (0 == lstrcmpi(pItem->propvar.pszVal, pszAddr + (cchEmail - cchVal)));
  1516. if ((FALSE != fRet) && (cchVal != cchEmail))
  1517. {
  1518. chTest = *(pszAddr + (cchEmail - cchVal - 1));
  1519. if (('@' != chTest) && ('.' != chTest))
  1520. {
  1521. fRet = FALSE;
  1522. }
  1523. }
  1524. }
  1525. }
  1526. exit:
  1527. return fRet;
  1528. }
  1529. BOOL _FMatchBlobString(CRIT_ITEM * pItem, LPSTR pszText)
  1530. {
  1531. BOOL fRet = FALSE;
  1532. LPSTR pszWalk = NULL;
  1533. // Walk each of the strings looking for a match
  1534. for (pszWalk = (LPSTR) (pItem->propvar.blob.pBlobData); '\0' != pszWalk[0];
  1535. pszWalk = pszWalk + lstrlen(pszWalk) + 1)
  1536. {
  1537. // Do the comparison
  1538. fRet = (NULL != StrStrI(pszText, pszWalk));
  1539. // If we are doing an AND of the multiple criteria
  1540. if (0 != (pItem->dwFlags & CRIT_FLAG_MULTIPLEAND))
  1541. {
  1542. // if we don't have a match, then we're done
  1543. if (FALSE == fRet)
  1544. {
  1545. break;
  1546. }
  1547. }
  1548. else
  1549. {
  1550. // if we do have a match, then we're done
  1551. if (FALSE != fRet)
  1552. {
  1553. break;
  1554. }
  1555. }
  1556. }
  1557. // Invert the result if needed
  1558. if (0 != (pItem->dwFlags & CRIT_FLAG_INVERT))
  1559. {
  1560. fRet = !fRet;
  1561. }
  1562. return fRet;
  1563. }
  1564. BOOL _FQueryBlobString(CRIT_ITEM * pItem, LPCSTR pszQuery, IMimePropertySet * pIMPropSet)
  1565. {
  1566. BOOL fRet = FALSE;
  1567. LPSTR pszWalk = NULL;
  1568. if (NULL == pIMPropSet)
  1569. {
  1570. fRet = FALSE;
  1571. goto exit;
  1572. }
  1573. // Walk each of the strings looking for a match
  1574. for (pszWalk = (LPSTR) (pItem->propvar.blob.pBlobData); '\0' != pszWalk[0];
  1575. pszWalk = pszWalk + lstrlen(pszWalk) + 1)
  1576. {
  1577. // Do the comparison
  1578. fRet = (S_OK == pIMPropSet->QueryProp(pszQuery, pszWalk, TRUE, FALSE));
  1579. // If we are doing an AND of the multiple criteria
  1580. if (0 != (pItem->dwFlags & CRIT_FLAG_MULTIPLEAND))
  1581. {
  1582. // if we don't have a match, then we're done
  1583. if (FALSE == fRet)
  1584. {
  1585. break;
  1586. }
  1587. }
  1588. else
  1589. {
  1590. // if we do have a match, then we're done
  1591. if (FALSE != fRet)
  1592. {
  1593. break;
  1594. }
  1595. }
  1596. }
  1597. // Invert the result if needed
  1598. if (0 != (pItem->dwFlags & CRIT_FLAG_INVERT))
  1599. {
  1600. fRet = !fRet;
  1601. }
  1602. exit:
  1603. return fRet;
  1604. }
  1605. BOOL CritFunc_Text(CRIT_ITEM * pItem, LPSTR pszText)
  1606. {
  1607. BOOL fRet = FALSE;
  1608. LPSTR pszWalk = NULL;
  1609. LPSTR pszAddr = NULL;
  1610. LPSTR pszTerm = NULL;
  1611. // Dup the string
  1612. pszAddr = PszDupA(pItem->propvar.pszVal);
  1613. if (NULL == pszAddr)
  1614. {
  1615. fRet = FALSE;
  1616. goto exit;
  1617. }
  1618. pszWalk = pszAddr;
  1619. pszTerm = pszWalk;
  1620. while (NULL != pszTerm)
  1621. {
  1622. pszTerm = StrStr(pszWalk, g_szComma);
  1623. if (NULL != pszTerm)
  1624. {
  1625. pszTerm[0] = '\0';
  1626. }
  1627. fRet = (NULL != StrStrI(pszText, pszWalk));
  1628. if (FALSE == fRet)
  1629. {
  1630. break;
  1631. }
  1632. pszWalk = pszWalk + lstrlen(pszWalk) + 1;
  1633. }
  1634. exit:
  1635. SafeMemFree(pszAddr);
  1636. return fRet;
  1637. }
  1638. BOOL CritFunc_Body(CRIT_ITEM * pItem, IMimeMessage * pIMMsg)
  1639. {
  1640. BOOL fRet = FALSE;
  1641. LPSTR pszWalk = NULL;
  1642. IStream * pStream = NULL;
  1643. IStream * pStreamHtml = NULL;
  1644. pszWalk = (LPTSTR) (pItem->propvar.blob.pBlobData);
  1645. if (NULL == pszWalk)
  1646. {
  1647. fRet = FALSE;
  1648. goto exit;
  1649. }
  1650. // Try to Get the Plain Text Stream
  1651. if (FAILED(pIMMsg->GetTextBody(TXT_PLAIN, IET_DECODED, &pStream, NULL)))
  1652. {
  1653. // Try to get the HTML stream and convert it to text...
  1654. if (SUCCEEDED(pIMMsg->GetTextBody(TXT_HTML, IET_DECODED, &pStreamHtml, NULL)))
  1655. {
  1656. if (FAILED(HrConvertHTMLToPlainText(pStreamHtml, &pStream, CF_TEXT)))
  1657. {
  1658. fRet = FALSE;
  1659. goto exit;
  1660. }
  1661. }
  1662. }
  1663. if (NULL == pStream)
  1664. {
  1665. fRet = FALSE;
  1666. goto exit;
  1667. }
  1668. for (; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  1669. {
  1670. fRet = StreamSubStringMatch(pStream, pszWalk);
  1671. // If we are doing an AND of the multiple criteria
  1672. if (0 != (pItem->dwFlags & CRIT_FLAG_MULTIPLEAND))
  1673. {
  1674. // if we don't have a match, then we're done
  1675. if (FALSE == fRet)
  1676. {
  1677. break;
  1678. }
  1679. }
  1680. else
  1681. {
  1682. // if we do have a match, then we're done
  1683. if (FALSE != fRet)
  1684. {
  1685. break;
  1686. }
  1687. }
  1688. }
  1689. // Invert the result if needed
  1690. if (0 != (pItem->dwFlags & CRIT_FLAG_INVERT))
  1691. {
  1692. fRet = !fRet;
  1693. }
  1694. exit:
  1695. SafeRelease(pStreamHtml);
  1696. SafeRelease(pStream);
  1697. return fRet;
  1698. }
  1699. BOOL FCrit_GetAcctInfo(DWORD dwServerTypes, DWORD * pdwServerType, DWORD * pdwPropTag)
  1700. {
  1701. BOOL fRet = FALSE;
  1702. Assert((NULL != pdwServerType) && (NULL != pdwPropTag));
  1703. // Figure out the type of the account
  1704. // and the server property
  1705. if (0 != (dwServerTypes & SRV_NNTP))
  1706. {
  1707. *pdwServerType = SRV_NNTP;
  1708. *pdwPropTag = AP_NNTP_SERVER;
  1709. }
  1710. else if (0 != (dwServerTypes & SRV_IMAP))
  1711. {
  1712. *pdwServerType = SRV_IMAP;
  1713. *pdwPropTag = AP_IMAP_SERVER;
  1714. }
  1715. else if (0 != (dwServerTypes & SRV_POP3))
  1716. {
  1717. *pdwServerType = SRV_POP3;
  1718. *pdwPropTag = AP_POP3_SERVER;
  1719. }
  1720. else if (0 != (dwServerTypes & SRV_HTTPMAIL))
  1721. {
  1722. *pdwServerType = SRV_HTTPMAIL;
  1723. *pdwPropTag = AP_HTTPMAIL_SERVER;
  1724. }
  1725. else
  1726. {
  1727. Assert(FALSE);
  1728. fRet = FALSE;
  1729. goto exit;
  1730. }
  1731. // Set the return value
  1732. fRet = TRUE;
  1733. exit:
  1734. return fRet;
  1735. }
  1736. BOOL FCritLoad_Account(IStream * pIStm, PROPVARIANT * ppropvar)
  1737. {
  1738. BOOL fRet = FALSE;
  1739. HRESULT hr = S_OK;
  1740. DWORD dwData = 0;
  1741. DWORD dwPropTag = 0;
  1742. ULONG cbRead = 0;
  1743. BYTE * pbData = NULL;
  1744. ULONG cbData = 0;
  1745. IImnEnumAccounts * pIEnumAcct = NULL;
  1746. IImnAccount * pAccount = NULL;
  1747. CHAR szAccount[CCHMAX_SERVER_NAME];
  1748. LPSTR pszAcct = NULL;
  1749. BOOL fFound = FALSE;
  1750. // Check the incoming params
  1751. if ((NULL == pIStm) || (NULL == ppropvar))
  1752. {
  1753. fRet = FALSE;
  1754. goto exit;
  1755. }
  1756. // Initialize the outgoing param
  1757. ZeroMemory(ppropvar, sizeof(*ppropvar));
  1758. // Read in the account server type
  1759. hr = pIStm->Read(&dwData, sizeof(dwData), &cbRead);
  1760. if ((FAILED(hr)) || (cbRead != sizeof(dwData)))
  1761. {
  1762. fRet = FALSE;
  1763. goto exit;
  1764. }
  1765. // Figure out the type of the account
  1766. // and the server property
  1767. fRet = FCrit_GetAcctInfo(dwData, &dwData, &dwPropTag);
  1768. if (FALSE == fRet)
  1769. {
  1770. goto exit;
  1771. }
  1772. // Get the size of the server name
  1773. hr = pIStm->Read(&cbData, sizeof(cbData), &cbRead);
  1774. if ((FAILED(hr)) || (cbRead != sizeof(cbData)))
  1775. {
  1776. fRet = FALSE;
  1777. goto exit;
  1778. }
  1779. // Allocate the space to hold the server name
  1780. hr = HrAlloc((VOID **) &pbData, cbData);
  1781. if (FAILED(hr))
  1782. {
  1783. fRet = FALSE;
  1784. goto exit;
  1785. }
  1786. // Read in the server name
  1787. hr = pIStm->Read(pbData, cbData, &cbRead);
  1788. if ((FAILED(hr)) || (cbRead != cbData))
  1789. {
  1790. fRet = FALSE;
  1791. goto exit;
  1792. }
  1793. // Get an account enumerator
  1794. Assert(g_pAcctMan);
  1795. if (FAILED(g_pAcctMan->Enumerate(dwData, &pIEnumAcct)))
  1796. {
  1797. fRet = FALSE;
  1798. goto exit;
  1799. }
  1800. // Search each account for the server name
  1801. while(SUCCEEDED(pIEnumAcct->GetNext(&pAccount)))
  1802. {
  1803. // We can get back NULL accounts
  1804. if (NULL == pAccount)
  1805. {
  1806. break;
  1807. }
  1808. // Get the server name
  1809. if (FAILED(pAccount->GetPropSz(dwPropTag, szAccount, sizeof(szAccount))))
  1810. {
  1811. SafeRelease(pAccount);
  1812. continue;
  1813. }
  1814. // Do we have a match?
  1815. if (0 == lstrcmpi(szAccount, (LPSTR) pbData))
  1816. {
  1817. fFound = TRUE;
  1818. break;
  1819. }
  1820. // We have a match
  1821. // Release it
  1822. SafeRelease(pAccount);
  1823. }
  1824. // Did we find anything?
  1825. if (FALSE == fFound)
  1826. {
  1827. fRet = FALSE;
  1828. goto exit;
  1829. }
  1830. // Get the account
  1831. if (FAILED(pAccount->GetPropSz(AP_ACCOUNT_ID, szAccount, sizeof(szAccount))))
  1832. {
  1833. fRet = FALSE;
  1834. goto exit;
  1835. }
  1836. // Save off the account ID
  1837. pszAcct = PszDupA(szAccount);
  1838. if (NULL == pszAcct)
  1839. {
  1840. fRet = FALSE;
  1841. goto exit;
  1842. }
  1843. // Set the outgoing param
  1844. ppropvar->vt = VT_LPSTR;
  1845. ppropvar->pszVal = pszAcct;
  1846. pszAcct = NULL;
  1847. // Set the return value
  1848. fRet = TRUE;
  1849. exit:
  1850. SafeMemFree(pszAcct);
  1851. SafeRelease(pAccount);
  1852. SafeRelease(pIEnumAcct);
  1853. SafeMemFree(pbData);
  1854. return fRet;
  1855. }
  1856. BOOL FCritSave_Account(IStream * pIStm, PROPVARIANT * ppropvar)
  1857. {
  1858. BOOL fRet = FALSE;
  1859. HRESULT hr = S_OK;
  1860. IImnAccount * pAccount = NULL;
  1861. DWORD dwServerTypes = 0;
  1862. DWORD dwPropTag = 0;
  1863. LPSTR pszServer = NULL;
  1864. ULONG cbWritten = 0;
  1865. ULONG cbData = 0;
  1866. // Check the incoming params
  1867. if ((NULL == pIStm) || (NULL == ppropvar))
  1868. {
  1869. fRet = FALSE;
  1870. goto exit;
  1871. }
  1872. Assert(g_pAcctMan);
  1873. if (FAILED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, ppropvar->pszVal, &pAccount)))
  1874. {
  1875. fRet = FALSE;
  1876. goto exit;
  1877. }
  1878. // Get the server type
  1879. if (FAILED(pAccount->GetServerTypes(&dwServerTypes)))
  1880. {
  1881. fRet = FALSE;
  1882. goto exit;
  1883. }
  1884. // Figure out the type of the account
  1885. // and the server property
  1886. fRet = FCrit_GetAcctInfo(dwServerTypes, &dwServerTypes, &dwPropTag);
  1887. if (FALSE == fRet)
  1888. {
  1889. goto exit;
  1890. }
  1891. // Allocate space to hold the server name
  1892. if (FAILED(HrAlloc((void **) &pszServer, CCHMAX_SERVER_NAME + 1)))
  1893. {
  1894. fRet = FALSE;
  1895. goto exit;
  1896. }
  1897. // Get the server name
  1898. if (FAILED(pAccount->GetPropSz(dwPropTag, pszServer, CCHMAX_SERVER_NAME)))
  1899. {
  1900. fRet = FALSE;
  1901. goto exit;
  1902. }
  1903. // Write out the server type
  1904. hr = pIStm->Write(&(dwServerTypes), sizeof(dwServerTypes), &cbWritten);
  1905. if (FAILED(hr))
  1906. {
  1907. fRet = FALSE;
  1908. goto exit;
  1909. }
  1910. Assert(cbWritten == sizeof(dwServerTypes));
  1911. // Write out the count of chars in the name
  1912. cbData = lstrlen(pszServer) + 1;
  1913. hr = pIStm->Write(&cbData, sizeof(cbData), &cbWritten);
  1914. if (FAILED(hr))
  1915. {
  1916. fRet = TRUE;
  1917. goto exit;
  1918. }
  1919. Assert(cbWritten == sizeof(cbData));
  1920. // Write out the server name
  1921. hr = pIStm->Write((BYTE *) pszServer, cbData, &cbWritten);
  1922. if (FAILED(hr))
  1923. {
  1924. fRet = TRUE;
  1925. goto exit;
  1926. }
  1927. Assert(cbWritten == cbData);
  1928. // Set the return value
  1929. fRet = TRUE;
  1930. exit:
  1931. SafeMemFree(pszServer);
  1932. SafeRelease(pAccount);
  1933. return fRet;
  1934. }
  1935. BOOL FCritLoad_Default(IStream * pIStm, PROPVARIANT * ppropvar)
  1936. {
  1937. BOOL fRet = FALSE;
  1938. HRESULT hr = S_OK;
  1939. DWORD dwData = 0;
  1940. ULONG cbRead = 0;
  1941. BYTE * pbData = NULL;
  1942. ULONG cbData = 0;
  1943. // Check the incoming params
  1944. if ((NULL == pIStm) || (NULL == ppropvar))
  1945. {
  1946. fRet = FALSE;
  1947. goto exit;
  1948. }
  1949. // Initialize the outgoing param
  1950. ZeroMemory(ppropvar, sizeof(*ppropvar));
  1951. // Read in the criteria value type
  1952. hr = pIStm->Read(&dwData, sizeof(dwData), &cbRead);
  1953. if ((FAILED(hr)) || (cbRead != sizeof(dwData)))
  1954. {
  1955. fRet = FALSE;
  1956. goto exit;
  1957. }
  1958. // Do we have any more data to get
  1959. if (dwData != VT_EMPTY)
  1960. {
  1961. ppropvar->vt = (VARTYPE) dwData;
  1962. // Get the size of the criteria value
  1963. hr = pIStm->Read(&cbData, sizeof(cbData), &cbRead);
  1964. if ((FAILED(hr)) || (cbRead != sizeof(cbData)))
  1965. {
  1966. fRet = FALSE;
  1967. goto exit;
  1968. }
  1969. // Allocate space to hold the criteria value data
  1970. switch (ppropvar->vt)
  1971. {
  1972. case VT_UI4:
  1973. pbData = (BYTE * ) &(ppropvar->ulVal);
  1974. break;
  1975. case VT_BLOB:
  1976. case VT_LPSTR:
  1977. // Allocate the space to hold the data
  1978. hr = HrAlloc((void **) &pbData, cbData);
  1979. if (FAILED(hr))
  1980. {
  1981. fRet = FALSE;
  1982. goto exit;
  1983. }
  1984. // Make sure we don't lose the allocated memory
  1985. if (VT_LPSTR == ppropvar->vt)
  1986. {
  1987. ppropvar->pszVal = (LPSTR) pbData;
  1988. }
  1989. else
  1990. {
  1991. ppropvar->blob.cbSize = cbData;
  1992. ppropvar->blob.pBlobData = pbData;
  1993. }
  1994. break;
  1995. default:
  1996. AssertSz(FALSE, "Why are we trying to save in a invalid criteria type?");
  1997. fRet = FALSE;
  1998. goto exit;
  1999. break;
  2000. }
  2001. // Read in the criteria value
  2002. hr = pIStm->Read(pbData, cbData, &cbRead);
  2003. if ((FAILED(hr)) || (cbRead != cbData))
  2004. {
  2005. fRet = FALSE;
  2006. goto exit;
  2007. }
  2008. }
  2009. // Set the return value
  2010. fRet = TRUE;
  2011. exit:
  2012. return fRet;
  2013. }
  2014. BOOL FCritSave_Default(IStream * pIStm, PROPVARIANT * ppropvar)
  2015. {
  2016. BOOL fRet = FALSE;
  2017. HRESULT hr = S_OK;
  2018. DWORD dwData = 0;
  2019. ULONG cbWritten = 0;
  2020. BYTE * pbData = NULL;
  2021. ULONG cbData = 0;
  2022. // Check the incoming params
  2023. if ((NULL == pIStm) || (NULL == ppropvar))
  2024. {
  2025. fRet = FALSE;
  2026. goto exit;
  2027. }
  2028. // Write out the value type
  2029. dwData = ppropvar->vt;
  2030. hr = pIStm->Write(&(dwData), sizeof(dwData), &cbWritten);
  2031. if (FAILED(hr))
  2032. {
  2033. fRet = FALSE;
  2034. goto exit;
  2035. }
  2036. Assert(cbWritten == sizeof(dwData));
  2037. // We don't have to save out the criteria value
  2038. // if we don't have one
  2039. if (VT_EMPTY == ppropvar->vt)
  2040. {
  2041. fRet = TRUE;
  2042. goto exit;
  2043. }
  2044. // Figure out the size of the criteria value
  2045. switch (ppropvar->vt)
  2046. {
  2047. case VT_UI4:
  2048. pbData = (BYTE * ) &(ppropvar->ulVal);
  2049. cbData = sizeof(ppropvar->ulVal);
  2050. break;
  2051. case VT_LPSTR:
  2052. pbData = (BYTE * ) (ppropvar->pszVal);
  2053. cbData = lstrlen(ppropvar->pszVal) + 1;
  2054. break;
  2055. case VT_BLOB:
  2056. pbData = ppropvar->blob.pBlobData;
  2057. cbData = ppropvar->blob.cbSize;
  2058. break;
  2059. default:
  2060. AssertSz(FALSE, "Why are we trying to save in a invalid criteria type?");
  2061. fRet = FALSE;
  2062. goto exit;
  2063. break;
  2064. }
  2065. // Write out the criteria value size
  2066. hr = pIStm->Write(&cbData, sizeof(cbData), &cbWritten);
  2067. if (FAILED(hr))
  2068. {
  2069. fRet = TRUE;
  2070. goto exit;
  2071. }
  2072. Assert(cbWritten == sizeof(cbData));
  2073. // Write out the criteria value
  2074. hr = pIStm->Write(pbData, cbData, &cbWritten);
  2075. if (FAILED(hr))
  2076. {
  2077. fRet = TRUE;
  2078. goto exit;
  2079. }
  2080. Assert(cbWritten == cbData);
  2081. // Set the return value
  2082. fRet = TRUE;
  2083. exit:
  2084. return fRet;
  2085. }
  2086. DWORD DwGetFlagsFromMessage(IMimeMessage * pIMMsg)
  2087. {
  2088. DWORD dwFlags = 0;
  2089. DWORD dwImf = 0;
  2090. Assert(NULL != pIMMsg);
  2091. if (SUCCEEDED(pIMMsg->GetFlags(&dwImf)))
  2092. {
  2093. dwFlags = ConvertIMFFlagsToARF(dwImf);
  2094. }
  2095. return dwFlags;
  2096. }