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.

1306 lines
35 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Actions.cpp
  4. //
  5. ///////////////////////////////////////////////////////////////////////////////
  6. #include <pch.hxx>
  7. #include "actions.h"
  8. #include "storutil.h"
  9. #include "ruleutil.h"
  10. static const int ACT_GROW = 16;
  11. ///////////////////////////////////////////////////////////////////////////////
  12. //
  13. // HrCreateActions
  14. //
  15. // This creates an actions container.
  16. //
  17. // ppIActions - pointer to return the criteria container
  18. //
  19. // Returns: S_OK, on success
  20. // E_OUTOFMEMORY, if can't create the IOEActions object
  21. //
  22. ///////////////////////////////////////////////////////////////////////////////
  23. HRESULT HrCreateActions(IOEActions ** ppIActions)
  24. {
  25. COEActions * pActions = NULL;
  26. HRESULT hr = S_OK;
  27. // Check the incoming params
  28. if (NULL == ppIActions)
  29. {
  30. hr = E_INVALIDARG;
  31. goto exit;
  32. }
  33. // Initialize outgoing params
  34. *ppIActions = NULL;
  35. // Create the rules manager object
  36. pActions = new COEActions;
  37. if (NULL == pActions)
  38. {
  39. hr = E_OUTOFMEMORY;
  40. goto exit;
  41. }
  42. // Get the rules manager interface
  43. hr = pActions->QueryInterface(IID_IOEActions, (void **) ppIActions);
  44. if (FAILED(hr))
  45. {
  46. goto exit;
  47. }
  48. pActions = NULL;
  49. // Set the proper return value
  50. hr = S_OK;
  51. exit:
  52. if (NULL != pActions)
  53. {
  54. delete pActions;
  55. }
  56. return hr;
  57. }
  58. COEActions::~COEActions()
  59. {
  60. AssertSz(m_cRef == 0, "Somebody still has a hold of us!!");
  61. Reset();
  62. }
  63. STDMETHODIMP_(ULONG) COEActions::AddRef()
  64. {
  65. return ::InterlockedIncrement(&m_cRef);
  66. }
  67. STDMETHODIMP_(ULONG) COEActions::Release()
  68. {
  69. LONG cRef = 0;
  70. cRef = ::InterlockedDecrement(&m_cRef);
  71. if (0 == cRef)
  72. {
  73. delete this;
  74. return cRef;
  75. }
  76. return cRef;
  77. }
  78. STDMETHODIMP COEActions::QueryInterface(REFIID riid, void ** ppvObject)
  79. {
  80. HRESULT hr = S_OK;
  81. // Check the incoming params
  82. if (NULL == ppvObject)
  83. {
  84. hr = E_INVALIDARG;
  85. goto exit;
  86. }
  87. // Initialize outgoing param
  88. *ppvObject = NULL;
  89. if ((riid == IID_IUnknown) || (riid == IID_IOEActions))
  90. {
  91. *ppvObject = static_cast<IOEActions *>(this);
  92. }
  93. else if ((riid == IID_IPersistStream) || (riid == IID_IPersist))
  94. {
  95. *ppvObject = static_cast<IPersistStream *>(this);
  96. }
  97. else
  98. {
  99. hr = E_NOINTERFACE;
  100. goto exit;
  101. }
  102. reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
  103. hr = S_OK;
  104. exit:
  105. return hr;
  106. }
  107. STDMETHODIMP COEActions::Reset(void)
  108. {
  109. HRESULT hr = S_OK;
  110. // See if there is something to do
  111. if (0 == m_cItems)
  112. {
  113. Assert(NULL == m_rgItems);
  114. hr = S_OK;
  115. goto exit;
  116. }
  117. RuleUtil_HrFreeActionsItem(m_rgItems, m_cItems);
  118. SafeMemFree(m_rgItems);
  119. m_cItems = 0;
  120. m_cItemsAlloc = 0;
  121. exit:
  122. return hr;
  123. }
  124. STDMETHODIMP COEActions::GetState(DWORD * pdwState)
  125. {
  126. HRESULT hr = S_OK;
  127. DWORD dwState = ACT_STATE_NULL;
  128. ULONG ulIndex = 0;
  129. // Check incoming params
  130. if (NULL == pdwState)
  131. {
  132. hr = E_INVALIDARG;
  133. goto exit;
  134. }
  135. // Init the outgoing param
  136. *pdwState = ACT_STATE_NULL;
  137. // See if there is something to do
  138. if (0 == m_cItems)
  139. {
  140. Assert(NULL == m_rgItems);
  141. hr = S_OK;
  142. goto exit;
  143. }
  144. // Walk through the actions to figure out the state
  145. for (ulIndex = 0; ulIndex < m_cItems; ulIndex++)
  146. {
  147. if ((ACT_STATE_NULL == dwState) &&
  148. ((ACT_TYPE_DELETESERVER == m_rgItems[ulIndex].type) ||
  149. (ACT_TYPE_DONTDOWNLOAD == m_rgItems[ulIndex].type)))
  150. {
  151. dwState = ACT_STATE_SERVER;
  152. }
  153. else
  154. {
  155. dwState = ACT_STATE_LOCAL;
  156. }
  157. }
  158. // Set the outgoing param
  159. *pdwState = dwState;
  160. // Set the proper return value
  161. hr = S_OK;
  162. exit:
  163. return hr;
  164. }
  165. STDMETHODIMP COEActions::GetActions(DWORD dwFlags, PACT_ITEM * ppItem, ULONG * pcItem)
  166. {
  167. HRESULT hr = S_OK;
  168. ACT_ITEM * pItemNew = NULL;
  169. // Check incoming params
  170. if ((NULL == ppItem) || (0 != dwFlags))
  171. {
  172. hr = E_INVALIDARG;
  173. goto exit;
  174. }
  175. // Initialize the out params
  176. *ppItem = NULL;
  177. if (NULL != pcItem)
  178. {
  179. *pcItem = 0;
  180. }
  181. // If we don't have any criteria, then return
  182. if (0 == m_cItems)
  183. {
  184. hr = E_FAIL;
  185. goto exit;
  186. }
  187. // Allocate space for the criteria
  188. hr = RuleUtil_HrDupActionsItem(m_rgItems, m_cItems, &pItemNew);
  189. if (FAILED(hr))
  190. {
  191. goto exit;
  192. }
  193. // Save the criteria
  194. *ppItem = pItemNew;
  195. pItemNew = NULL;
  196. if (NULL != pcItem)
  197. {
  198. *pcItem = m_cItems;
  199. }
  200. exit:
  201. RuleUtil_HrFreeActionsItem(pItemNew, m_cItems);
  202. SafeMemFree(pItemNew);
  203. return hr;
  204. }
  205. STDMETHODIMP COEActions::SetActions(DWORD dwFlags, ACT_ITEM * pItem, ULONG cItem)
  206. {
  207. HRESULT hr = S_OK;
  208. ACT_ITEM * pItemNew = NULL;
  209. // Check incoming params
  210. if ((NULL == pItem) || (0 == cItem) || (0 != dwFlags))
  211. {
  212. hr = E_INVALIDARG;
  213. goto exit;
  214. }
  215. // If we have any criteria already, then reset
  216. if (0 != m_cItems)
  217. {
  218. Reset();
  219. }
  220. // Allocate space for the criteria
  221. hr = RuleUtil_HrDupActionsItem(pItem, cItem, &pItemNew);
  222. if (FAILED(hr))
  223. {
  224. goto exit;
  225. }
  226. // Save the criteria
  227. m_rgItems = pItemNew;
  228. pItemNew = NULL;
  229. m_cItems = cItem;
  230. m_cItemsAlloc = cItem;
  231. exit:
  232. RuleUtil_HrFreeActionsItem(pItemNew, cItem);
  233. SafeMemFree(pItemNew);
  234. return hr;
  235. }
  236. ///////////////////////////////////////////////////////////////////////////////
  237. //
  238. // ValidateActions
  239. //
  240. // This verifies each of the action values
  241. //
  242. // Returns: S_OK, if the actions were valid
  243. // S_FALSE, otherwise
  244. //
  245. ///////////////////////////////////////////////////////////////////////////////
  246. STDMETHODIMP COEActions::Validate(DWORD dwFlags)
  247. {
  248. HRESULT hr = S_OK;
  249. ULONG ulIndex = 0;
  250. LPSTR pszText = NULL;
  251. FOLDERINFO Folder={0};
  252. RULEFOLDERDATA * prfdData = NULL;
  253. // If we don't have any actions, then we must be valid
  254. if (0 == m_cItems)
  255. {
  256. hr = S_OK;
  257. goto exit;
  258. }
  259. for (ulIndex = 0; ulIndex < m_cItems; ulIndex++)
  260. {
  261. switch(m_rgItems[ulIndex].type)
  262. {
  263. // These ones are always valid
  264. case ACT_TYPE_DELETESERVER:
  265. case ACT_TYPE_DONTDOWNLOAD:
  266. case ACT_TYPE_FLAG:
  267. case ACT_TYPE_READ:
  268. case ACT_TYPE_MARKDOWNLOAD:
  269. case ACT_TYPE_DELETE:
  270. case ACT_TYPE_JUNKMAIL:
  271. case ACT_TYPE_STOP:
  272. if (VT_EMPTY != m_rgItems[ulIndex].propvar.vt)
  273. {
  274. hr = S_FALSE;
  275. goto exit;
  276. }
  277. break;
  278. case ACT_TYPE_HIGHLIGHT:
  279. if (VT_UI4 != m_rgItems[ulIndex].propvar.vt)
  280. {
  281. hr = S_FALSE;
  282. goto exit;
  283. }
  284. break;
  285. case ACT_TYPE_WATCH:
  286. case ACT_TYPE_SHOW:
  287. if (VT_UI4 != m_rgItems[ulIndex].propvar.vt)
  288. {
  289. hr = S_FALSE;
  290. goto exit;
  291. }
  292. if (ACT_DATA_NULL == m_rgItems[ulIndex].propvar.ulVal)
  293. {
  294. hr = S_FALSE;
  295. goto exit;
  296. }
  297. break;
  298. case ACT_TYPE_COPY:
  299. case ACT_TYPE_MOVE:
  300. if ((VT_BLOB != m_rgItems[ulIndex].propvar.vt) ||
  301. (0 == m_rgItems[ulIndex].propvar.blob.cbSize))
  302. {
  303. hr = S_FALSE;
  304. goto exit;
  305. }
  306. // Make life simpler
  307. prfdData = (RULEFOLDERDATA *) (m_rgItems[ulIndex].propvar.blob.pBlobData);
  308. // Validate the rule folder data
  309. if (S_OK != RuleUtil_HrValidateRuleFolderData(prfdData))
  310. {
  311. hr = S_FALSE;
  312. goto exit;
  313. }
  314. hr = g_pStore->GetFolderInfo(prfdData->idFolder, &Folder);
  315. if (FAILED(hr))
  316. {
  317. hr = S_FALSE;
  318. goto exit;
  319. }
  320. else
  321. g_pStore->FreeRecord(&Folder);
  322. break;
  323. case ACT_TYPE_REPLY:
  324. case ACT_TYPE_NOTIFYSND:
  325. if ((VT_LPSTR != m_rgItems[ulIndex].propvar.vt) ||
  326. (NULL == m_rgItems[ulIndex].propvar.pszVal))
  327. {
  328. hr = S_FALSE;
  329. goto exit;
  330. }
  331. Assert(lstrlen(m_rgItems[ulIndex].propvar.pszVal) <= MAX_PATH)
  332. if (0xFFFFFFFF == GetFileAttributes(m_rgItems[ulIndex].propvar.pszVal))
  333. {
  334. hr = S_FALSE;
  335. goto exit;
  336. }
  337. break;
  338. case ACT_TYPE_FWD:
  339. {
  340. LPWSTR pwszVal = NULL,
  341. pwszText = NULL;
  342. if ((VT_LPSTR != m_rgItems[ulIndex].propvar.vt) ||
  343. (NULL == m_rgItems[ulIndex].propvar.pszVal))
  344. {
  345. AssertSz(VT_LPWSTR != m_rgItems[ulIndex].propvar.vt, "We are getting UNICODE here.");
  346. hr = S_FALSE;
  347. goto exit;
  348. }
  349. // Update the display string
  350. pwszVal = PszToUnicode(CP_ACP, m_rgItems[ulIndex].propvar.pszVal);
  351. if (!pwszVal)
  352. {
  353. hr = S_FALSE;
  354. goto exit;
  355. }
  356. hr = RuleUtil_HrParseEmailString(pwszVal, 0, &pwszText, NULL);
  357. MemFree(pwszText);
  358. MemFree(pwszVal);
  359. if (FAILED(hr))
  360. {
  361. hr = S_FALSE;
  362. goto exit;
  363. }
  364. // If either always encrypt or always sign is turned on
  365. // we can't do anything
  366. if ((0 != DwGetOption(OPT_MAIL_DIGSIGNMESSAGES)) || (0 != DwGetOption(OPT_MAIL_ENCRYPTMESSAGES)))
  367. {
  368. hr = S_FALSE;
  369. goto exit;
  370. }
  371. break;
  372. }
  373. default:
  374. hr = S_FALSE;
  375. goto exit;
  376. break;
  377. }
  378. }
  379. // If we got here, the we must be AOK
  380. hr = S_OK;
  381. exit:
  382. SafeMemFree(pszText);
  383. return hr;
  384. }
  385. STDMETHODIMP COEActions::AppendActions(DWORD dwFlags, ACT_ITEM * pItem, ULONG cItem, ULONG * pcItemAppended)
  386. {
  387. HRESULT hr = S_OK;
  388. ACT_ITEM * pItemNew = NULL;
  389. // Check incoming parameters
  390. if ((0 != dwFlags) || (NULL == pItem) || (0 == cItem))
  391. {
  392. hr = E_INVALIDARG;
  393. goto exit;
  394. }
  395. // Let's init our outgoing parameters
  396. if (NULL != pcItemAppended)
  397. {
  398. *pcItemAppended = 0;
  399. }
  400. // Do we have to add more items?
  401. if (m_cItems == m_cItemsAlloc)
  402. {
  403. hr = HrRealloc((LPVOID *) &m_rgItems, sizeof(ACT_ITEM) * (m_cItemsAlloc + ACT_GROW));
  404. if (FAILED(hr))
  405. {
  406. goto exit;
  407. }
  408. ZeroMemory(m_rgItems + m_cItemsAlloc, sizeof(ACT_ITEM) * ACT_GROW);
  409. m_cItemsAlloc += ACT_GROW;
  410. }
  411. // Let's duplicate the items that need to be added
  412. hr = RuleUtil_HrDupActionsItem(pItem, cItem, &pItemNew);
  413. if (FAILED(hr))
  414. {
  415. goto exit;
  416. }
  417. // Let's add them to the criteria array
  418. CopyMemory(m_rgItems + m_cItems, pItemNew, sizeof(ACT_ITEM) * cItem);
  419. m_cItems += cItem;
  420. // Set the proper outgoing parameter
  421. if (NULL != pcItemAppended)
  422. {
  423. *pcItemAppended = cItem;
  424. }
  425. // Set the proper return value
  426. hr = S_OK;
  427. exit:
  428. SafeMemFree(pItemNew);
  429. return hr;
  430. }
  431. ///////////////////////////////////////////////////////////////////////////////
  432. //
  433. // LoadReg
  434. //
  435. // This loads in the actions from the registry. It loads in the actions
  436. // order from the Order value. The string contains space delimitied values
  437. // and each value contains the subkey name for each action. Each action
  438. // is loaded in the order that is contained in the Order value. The actions
  439. // are loaded with the Actions Type. The Actions Value Type is loaded if it exists.
  440. // If an Action Value Type exists, then the corresponding Action Value is loaded in.
  441. //
  442. // pszRegPath - the path to load the actions from
  443. //
  444. // Returns: S_OK, if the actions were loaded without problems
  445. // E_OUTOFMEMORY, if we couldn't allocate memory to hold the actions
  446. // E_FAIL, otherwise
  447. //
  448. ///////////////////////////////////////////////////////////////////////////////
  449. STDMETHODIMP COEActions::LoadReg(LPCSTR pszRegPath)
  450. {
  451. HRESULT hr = S_OK;
  452. LONG lErr = 0;
  453. HKEY hkeyRoot = NULL;
  454. ULONG cbData = 0;
  455. LPSTR pszOrder = NULL;
  456. ULONG cOrder = 0;
  457. LPSTR pszWalk = NULL;
  458. ACT_ITEM * pItems = NULL;
  459. LPSTR pszNext = NULL;
  460. ULONG ulOrder = 0;
  461. HKEY hkeyAction = NULL;
  462. ACT_TYPE typeAct;
  463. PROPVARIANT propvar = {0};
  464. DWORD dwType = 0;
  465. BYTE * pbData = NULL;
  466. DWORD dwFlags = ACT_FLAG_DEFAULT;
  467. // Check incoming param
  468. if (NULL == pszRegPath)
  469. {
  470. hr = E_INVALIDARG;
  471. goto exit;
  472. }
  473. // Should we fail if we're already loaded?
  474. AssertSz(0 == (m_dwState & ACT_STATE_LOADED), "We're already loaded!!!");
  475. // Open the reg key from the path
  476. lErr = AthUserOpenKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot);
  477. if (ERROR_SUCCESS != lErr)
  478. {
  479. hr = E_FAIL;
  480. goto exit;
  481. }
  482. // Get the actions order
  483. hr = RuleUtil_HrGetRegValue(hkeyRoot, c_szActionsOrder, NULL, (BYTE **) &pszOrder, &cbData);
  484. if (FAILED(hr))
  485. {
  486. goto exit;
  487. }
  488. // Make sure we actually have something to load
  489. if ('\0' == *pszOrder)
  490. {
  491. AssertSz(FALSE, "The order string for the actions is mis-formatted in the registry");
  492. hr = E_FAIL;
  493. goto exit;
  494. }
  495. // Convert the actions string to a more useful format
  496. pszWalk = pszOrder;
  497. cOrder = 1;
  498. for (pszWalk = StrStr(pszOrder, g_szSpace); NULL != pszWalk; pszWalk = StrStr(pszWalk, g_szSpace))
  499. {
  500. // Terminate the order item
  501. *pszWalk = '\0';
  502. pszWalk++;
  503. cOrder++;
  504. }
  505. // Allocate the space to hold all the actions
  506. cbData = cOrder * sizeof(ACT_ITEM);
  507. hr = HrAlloc((void **) &pItems, cbData);
  508. if (FAILED(hr))
  509. {
  510. goto exit;
  511. }
  512. // Initialize it to a known value
  513. ZeroMemory(pItems, cbData);
  514. // For each action in the order string
  515. pszWalk = pszOrder;
  516. for (ulOrder = 0, pszWalk = pszOrder; ulOrder < cOrder; ulOrder++, pszWalk += lstrlen(pszWalk) + 1)
  517. {
  518. // Open up the action reg key
  519. lErr = RegOpenKeyEx(hkeyRoot, pszWalk, 0, KEY_READ, &hkeyAction);
  520. if (ERROR_SUCCESS != lErr)
  521. {
  522. AssertSz(FALSE, "Part of the criteria is mis-formatted in the registry");
  523. hr = E_FAIL;
  524. goto exit;
  525. }
  526. // Get the action type
  527. cbData = sizeof(typeAct);
  528. lErr = RegQueryValueEx(hkeyAction, c_szActionsType, 0, NULL,
  529. (BYTE *) &(typeAct), &cbData);
  530. if (ERROR_SUCCESS != lErr)
  531. {
  532. hr = E_FAIL;
  533. goto exit;
  534. }
  535. // Get the action flags
  536. cbData = sizeof(dwFlags);
  537. lErr = RegQueryValueEx(hkeyAction, c_szActionsFlags, 0, NULL,
  538. (BYTE *) &(dwFlags), &cbData);
  539. if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr))
  540. {
  541. hr = E_FAIL;
  542. goto exit;
  543. }
  544. // If it didn't exist then assign it to the default
  545. if (ERROR_FILE_NOT_FOUND == lErr)
  546. {
  547. dwFlags = ACT_FLAG_DEFAULT;
  548. }
  549. // Does a action value type exist
  550. lErr = RegQueryValueEx(hkeyAction, c_szActionsValueType, 0, NULL, NULL, &cbData);
  551. if ((ERROR_SUCCESS == lErr) && (0 != cbData))
  552. {
  553. // Load the action value in
  554. cbData = sizeof(dwType);
  555. lErr = RegQueryValueEx(hkeyAction, c_szActionsValueType, 0, NULL,
  556. (BYTE *) &dwType, &cbData);
  557. if (ERROR_SUCCESS != lErr)
  558. {
  559. hr = E_FAIL;
  560. goto exit;
  561. }
  562. propvar.vt = (VARTYPE) dwType;
  563. switch (propvar.vt)
  564. {
  565. case VT_UI4:
  566. // Get the action value
  567. cbData = sizeof(propvar.ulVal);
  568. lErr = RegQueryValueEx(hkeyAction, c_szActionsValue, 0, NULL,
  569. (BYTE * ) &(propvar.ulVal), &cbData);
  570. if (ERROR_SUCCESS != lErr)
  571. {
  572. hr = E_FAIL;
  573. goto exit;
  574. }
  575. break;
  576. case VT_LPSTR:
  577. case VT_BLOB:
  578. // Get the criteria value
  579. hr = RuleUtil_HrGetRegValue(hkeyAction, c_szActionsValue, NULL, (BYTE **) &pbData, &cbData);
  580. if (FAILED(hr))
  581. {
  582. goto exit;
  583. }
  584. // Save the space so we can free it
  585. if (VT_LPSTR == propvar.vt)
  586. {
  587. propvar.pszVal = (LPSTR) pbData;
  588. }
  589. else
  590. {
  591. propvar.blob.cbSize = cbData;
  592. propvar.blob.pBlobData = pbData;
  593. }
  594. pbData = NULL;
  595. break;
  596. default:
  597. AssertSz(FALSE, "Why are we loading in an invalid action type?");
  598. hr = E_FAIL;
  599. goto exit;
  600. break;
  601. }
  602. }
  603. // Save the value into the criteria array
  604. pItems[ulOrder].type = typeAct;
  605. pItems[ulOrder].dwFlags = dwFlags;
  606. pItems[ulOrder].propvar = propvar;
  607. ZeroMemory(&propvar, sizeof(propvar));
  608. // Close the action
  609. SideAssert(ERROR_SUCCESS == RegCloseKey(hkeyAction));
  610. hkeyAction = NULL;
  611. }
  612. // Free up the current actions
  613. SafeMemFree(m_rgItems);
  614. // Save the new values
  615. m_rgItems = pItems;
  616. pItems = NULL;
  617. m_cItems = cOrder;
  618. // Make sure we clear the dirty bit
  619. m_dwState &= ~ACT_STATE_DIRTY;
  620. // Note that we have been loaded
  621. m_dwState |= ACT_STATE_LOADED;
  622. // Set the return value
  623. hr = S_OK;
  624. exit:
  625. SafeMemFree(pbData);
  626. PropVariantClear(&propvar);
  627. RuleUtil_HrFreeActionsItem(pItems, cOrder);
  628. SafeMemFree(pItems);
  629. SafeMemFree(pszOrder);
  630. if (NULL != hkeyAction)
  631. {
  632. RegCloseKey(hkeyAction);
  633. }
  634. if (NULL != hkeyRoot)
  635. {
  636. RegCloseKey(hkeyRoot);
  637. }
  638. return hr;
  639. }
  640. STDMETHODIMP COEActions::SaveReg(LPCSTR pszRegPath, BOOL fClearDirty)
  641. {
  642. HRESULT hr = S_OK;
  643. LONG lErr = 0;
  644. HKEY hkeyRoot = NULL;
  645. DWORD dwDisp = 0;
  646. LPSTR pszOrder = NULL;
  647. ULONG ulIndex = 0;
  648. ACT_ITEM * pItem = NULL;
  649. CHAR rgchTag[CCH_ACT_ORDER];
  650. HKEY hkeyAction = NULL;
  651. ULONG cbData = 0;
  652. BYTE * pbData = NULL;
  653. // Check incoming param
  654. if (NULL == pszRegPath)
  655. {
  656. hr = E_INVALIDARG;
  657. goto exit;
  658. }
  659. // If there's nothing to save, then fail
  660. if (NULL == m_rgItems)
  661. {
  662. hr = E_FAIL;
  663. goto exit;
  664. }
  665. // Let's make sure we clear out the key first
  666. AthUserDeleteKey(pszRegPath);
  667. // Create the reg key from the path
  668. lErr = AthUserCreateKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp);
  669. if (ERROR_SUCCESS != lErr)
  670. {
  671. hr = E_FAIL;
  672. goto exit;
  673. }
  674. Assert(REG_CREATED_NEW_KEY == dwDisp);
  675. Assert(m_cItems < ACT_COUNT_MAX);
  676. // Allocate space to hold the order
  677. DWORD cchSize = (m_cItems * CCH_ACT_ORDER);
  678. hr = HrAlloc((void **) &pszOrder, cchSize * sizeof(*pszOrder));
  679. if (FAILED(hr))
  680. {
  681. goto exit;
  682. }
  683. pszOrder[0] = '\0';
  684. // Write out each of the actions
  685. for (ulIndex = 0, pItem = m_rgItems; ulIndex < m_cItems; ulIndex++, pItem++)
  686. {
  687. // Get the new action tag
  688. wnsprintf(rgchTag, ARRAYSIZE(rgchTag), "%03X", ulIndex);
  689. // Add the new tag to the order
  690. if (0 != ulIndex)
  691. {
  692. StrCatBuff(pszOrder, g_szSpace, cchSize);
  693. }
  694. StrCatBuff(pszOrder, rgchTag, cchSize);
  695. // Create the new action
  696. lErr = RegCreateKeyEx(hkeyRoot, rgchTag, 0, NULL,
  697. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAction, &dwDisp);
  698. if (ERROR_SUCCESS != lErr)
  699. {
  700. hr = E_FAIL;
  701. goto exit;
  702. }
  703. Assert(REG_CREATED_NEW_KEY == dwDisp);
  704. // Write out the action type
  705. lErr = RegSetValueEx(hkeyAction, c_szActionsType, 0, REG_DWORD,
  706. (BYTE *) &(pItem->type), sizeof(pItem->type));
  707. if (ERROR_SUCCESS != lErr)
  708. {
  709. hr = E_FAIL;
  710. goto exit;
  711. }
  712. // Write out the action type
  713. lErr = RegSetValueEx(hkeyAction, c_szActionsFlags, 0, REG_DWORD,
  714. (BYTE *) &(pItem->dwFlags), sizeof(pItem->dwFlags));
  715. if (ERROR_SUCCESS != lErr)
  716. {
  717. hr = E_FAIL;
  718. goto exit;
  719. }
  720. // Do we have an action value?
  721. if (VT_EMPTY != pItem->propvar.vt)
  722. {
  723. // Write out the criteria value type
  724. dwDisp = pItem->propvar.vt;
  725. lErr = RegSetValueEx(hkeyAction, c_szActionsValueType, 0, REG_DWORD, (BYTE *) &dwDisp, sizeof(dwDisp));
  726. if (ERROR_SUCCESS != lErr)
  727. {
  728. hr = E_FAIL;
  729. goto exit;
  730. }
  731. // Write out the action value
  732. switch (pItem->propvar.vt)
  733. {
  734. case VT_UI4:
  735. dwDisp = REG_DWORD;
  736. pbData = (BYTE * ) &(pItem->propvar.ulVal);
  737. cbData = sizeof(pItem->propvar.ulVal);
  738. break;
  739. case VT_LPSTR:
  740. dwDisp = REG_SZ;
  741. pbData = (BYTE * ) (pItem->propvar.pszVal);
  742. cbData = lstrlen(pItem->propvar.pszVal) + 1;
  743. break;
  744. case VT_BLOB:
  745. dwDisp = REG_BINARY;
  746. pbData = pItem->propvar.blob.pBlobData;
  747. cbData = pItem->propvar.blob.cbSize;
  748. break;
  749. default:
  750. AssertSz(FALSE, "Why are we trying to save in an invalid action type?");
  751. hr = E_FAIL;
  752. goto exit;
  753. break;
  754. }
  755. // Write out the action value
  756. lErr = RegSetValueEx(hkeyAction, c_szActionsValue, 0, dwDisp, pbData, cbData);
  757. if (ERROR_SUCCESS != lErr)
  758. {
  759. hr = E_FAIL;
  760. goto exit;
  761. }
  762. }
  763. // Close the action
  764. SideAssert(ERROR_SUCCESS == RegCloseKey(hkeyAction));
  765. hkeyAction = NULL;
  766. }
  767. // Write out the order string.
  768. lErr = RegSetValueEx(hkeyRoot, c_szActionsOrder, 0, REG_SZ,
  769. (BYTE *) pszOrder, lstrlen(pszOrder) + 1);
  770. if (ERROR_SUCCESS != lErr)
  771. {
  772. hr = E_FAIL;
  773. goto exit;
  774. }
  775. // Should we clear the dirty bit?
  776. if (FALSE != fClearDirty)
  777. {
  778. m_dwState &= ~ACT_STATE_DIRTY;
  779. }
  780. // Set the return value
  781. hr = S_OK;
  782. exit:
  783. if (NULL != hkeyAction)
  784. {
  785. RegCloseKey(hkeyAction);
  786. }
  787. SafeMemFree(pszOrder);
  788. if (NULL != hkeyRoot)
  789. {
  790. RegCloseKey(hkeyRoot);
  791. }
  792. return hr;
  793. }
  794. STDMETHODIMP COEActions::Clone(IOEActions ** ppIActions)
  795. {
  796. HRESULT hr = S_OK;
  797. COEActions * pActions = NULL;
  798. // Check incoming params
  799. if (NULL == ppIActions)
  800. {
  801. hr = E_INVALIDARG;
  802. goto exit;
  803. }
  804. // Initialize the outgoing params
  805. *ppIActions = NULL;
  806. // Create a new actions
  807. pActions = new COEActions;
  808. if (NULL == pActions)
  809. {
  810. hr = E_OUTOFMEMORY;
  811. goto exit;
  812. }
  813. // Copy over the list of actions
  814. hr = pActions->SetActions(0, m_rgItems, m_cItems);
  815. if (FAILED(hr))
  816. {
  817. goto exit;
  818. }
  819. // Get the actions interface
  820. hr = pActions->QueryInterface(IID_IOEActions, (void **) ppIActions);
  821. if (FAILED(hr))
  822. {
  823. goto exit;
  824. }
  825. pActions = NULL;
  826. // Set the proper return value
  827. hr = S_OK;
  828. exit:
  829. if (NULL != pActions)
  830. {
  831. delete pActions;
  832. }
  833. return hr;
  834. }
  835. STDMETHODIMP COEActions::GetClassID(CLSID * pclsid)
  836. {
  837. HRESULT hr = S_OK;
  838. if (NULL == pclsid)
  839. {
  840. hr = E_INVALIDARG;
  841. goto exit;
  842. }
  843. *pclsid = CLSID_OEActions;
  844. // Set the proper return value
  845. hr = S_OK;
  846. exit:
  847. return hr;
  848. }
  849. STDMETHODIMP COEActions::IsDirty(void)
  850. {
  851. HRESULT hr = S_OK;
  852. hr = (ACT_STATE_DIRTY == (m_dwState & ACT_STATE_DIRTY)) ? S_OK : S_FALSE;
  853. return hr;
  854. }
  855. STDMETHODIMP COEActions::Load(IStream * pStm)
  856. {
  857. HRESULT hr = S_OK;
  858. ULONG cbData = 0;
  859. ULONG cbRead = 0;
  860. DWORD dwData = 0;
  861. ULONG cItems = 0;
  862. ACT_ITEM * pItems = NULL;
  863. ULONG ulIndex = 0;
  864. ACT_ITEM * pItem = NULL;
  865. ACT_TYPE typeAct;
  866. PROPVARIANT propvar = {0};
  867. BYTE * pbData = NULL;
  868. DWORD dwFlags = ACT_FLAG_DEFAULT;
  869. // Check incoming param
  870. if (NULL == pStm)
  871. {
  872. hr = E_INVALIDARG;
  873. goto exit;
  874. }
  875. // Verify we have the correct version
  876. hr = pStm->Read(&dwData, sizeof(dwData), &cbRead);
  877. if (FAILED(hr))
  878. {
  879. goto exit;
  880. }
  881. if ((cbRead != sizeof(dwData)) || (dwData != ACT_VERSION))
  882. {
  883. hr = E_FAIL;
  884. goto exit;
  885. }
  886. // Get the number of actions
  887. hr = pStm->Read(&cItems, sizeof(cItems), &cbRead);
  888. if (FAILED(hr))
  889. {
  890. goto exit;
  891. }
  892. if ((cbRead != sizeof(cItems)) || (0 == cItems))
  893. {
  894. hr = E_FAIL;
  895. goto exit;
  896. }
  897. // Allocate space to hold all the actions
  898. hr = HrAlloc( (void **) &pItems, cItems * sizeof(*pItems));
  899. if (FAILED(hr))
  900. {
  901. goto exit;
  902. }
  903. // Initialize the actions to a known value
  904. ZeroMemory(pItems, cItems * sizeof(*pItems));
  905. // for each action
  906. for (ulIndex = 0, pItem = pItems; ulIndex < cItems; ulIndex++, pItem++)
  907. {
  908. // Read in the action type
  909. hr = pStm->Read(&typeAct, sizeof(typeAct), &cbRead);
  910. if (FAILED(hr))
  911. {
  912. goto exit;
  913. }
  914. if (cbRead != sizeof(typeAct))
  915. {
  916. hr = E_FAIL;
  917. goto exit;
  918. }
  919. // Read in the action flags
  920. hr = pStm->Read(&dwFlags, sizeof(dwFlags), &cbRead);
  921. if ((FAILED(hr)) || (cbRead != sizeof(dwFlags)))
  922. {
  923. goto exit;
  924. }
  925. // Read in the action value type
  926. hr = pStm->Read(&dwData, sizeof(dwData), &cbRead);
  927. if ((FAILED(hr)) || (cbRead != sizeof(dwData)))
  928. {
  929. goto exit;
  930. }
  931. propvar.vt = (VARTYPE) dwData;
  932. if (VT_EMPTY != propvar.vt)
  933. {
  934. // Get the size of the action value
  935. hr = pStm->Read(&cbData, sizeof(cbData), &cbRead);
  936. if (FAILED(hr))
  937. {
  938. goto exit;
  939. }
  940. if (cbRead != sizeof(cbData))
  941. {
  942. hr = E_FAIL;
  943. goto exit;
  944. }
  945. // Allocate space to hold the action value data
  946. switch (propvar.vt)
  947. {
  948. case VT_UI4:
  949. pbData = (BYTE * ) &(propvar.ulVal);
  950. break;
  951. case VT_BLOB:
  952. case VT_LPSTR:
  953. hr = HrAlloc((void **) &pbData, cbData);
  954. if (FAILED(hr))
  955. {
  956. goto exit;
  957. }
  958. if (VT_LPSTR == propvar.vt)
  959. {
  960. propvar.pszVal = (LPSTR) pbData;
  961. }
  962. else
  963. {
  964. propvar.blob.cbSize = cbData;
  965. propvar.blob.pBlobData = pbData;
  966. }
  967. break;
  968. default:
  969. AssertSz(FALSE, "Why are we trying to save in a invalid action type?");
  970. hr = E_FAIL;
  971. goto exit;
  972. break;
  973. }
  974. // Read in the action value
  975. hr = pStm->Read(pbData, cbData, &cbRead);
  976. if (FAILED(hr))
  977. {
  978. goto exit;
  979. }
  980. if (cbRead != cbData)
  981. {
  982. hr = E_FAIL;
  983. goto exit;
  984. }
  985. }
  986. pItem->type = typeAct;
  987. pItem->dwFlags = dwFlags;
  988. pItem->propvar = propvar;
  989. ZeroMemory(&propvar, sizeof(propvar));
  990. }
  991. // Free up the current actions
  992. SafeMemFree(m_rgItems);
  993. // Save the new values
  994. m_rgItems = pItems;
  995. pItems = NULL;
  996. m_cItems = cItems;
  997. // Make sure we clear the dirty bit
  998. m_dwState &= ~ACT_STATE_DIRTY;
  999. // Note that we have been loaded
  1000. m_dwState |= ACT_STATE_LOADED;
  1001. // Set the return value
  1002. hr = S_OK;
  1003. exit:
  1004. PropVariantClear(&propvar);
  1005. RuleUtil_HrFreeActionsItem(pItems, cItems);
  1006. SafeMemFree(pItems);
  1007. return hr;
  1008. }
  1009. STDMETHODIMP COEActions::Save(IStream * pStm, BOOL fClearDirty)
  1010. {
  1011. HRESULT hr = S_OK;
  1012. ULONG cbData = 0;
  1013. ULONG cbWritten = 0;
  1014. DWORD dwData = 0;
  1015. ULONG ulIndex = 0;
  1016. ACT_ITEM * pItem = NULL;
  1017. BYTE * pbData = NULL;
  1018. // Check incoming param
  1019. if (NULL == pStm)
  1020. {
  1021. hr = E_INVALIDARG;
  1022. goto exit;
  1023. }
  1024. // Write out the version
  1025. dwData = ACT_VERSION;
  1026. hr = pStm->Write(&dwData, sizeof(dwData), &cbWritten);
  1027. if (FAILED(hr))
  1028. {
  1029. goto exit;
  1030. }
  1031. Assert(cbWritten == sizeof(dwData));
  1032. // Write out the count of actions
  1033. hr = pStm->Write(&m_cItems, sizeof(m_cItems), &cbWritten);
  1034. if (FAILED(hr))
  1035. {
  1036. goto exit;
  1037. }
  1038. Assert(cbWritten == sizeof(m_cItems));
  1039. // Loop through each of the actions
  1040. for (ulIndex = 0, pItem = m_rgItems; ulIndex < m_cItems; ulIndex++, pItem++)
  1041. {
  1042. // Write out the action type
  1043. hr = pStm->Write(&(pItem->type), sizeof(pItem->type), &cbWritten);
  1044. if (FAILED(hr))
  1045. {
  1046. goto exit;
  1047. }
  1048. Assert(cbWritten == sizeof(pItem->type));
  1049. // Write out the actions flags
  1050. hr = pStm->Write(&(pItem->dwFlags), sizeof(pItem->dwFlags), &cbWritten);
  1051. if (FAILED(hr))
  1052. {
  1053. goto exit;
  1054. }
  1055. Assert(cbWritten == sizeof(pItem->dwFlags));
  1056. // Write out the value type
  1057. dwData = pItem->propvar.vt;
  1058. hr = pStm->Write(&(dwData), sizeof(dwData), &cbWritten);
  1059. if (FAILED(hr))
  1060. {
  1061. goto exit;
  1062. }
  1063. Assert(cbWritten == sizeof(dwData));
  1064. if (VT_EMPTY == pItem->propvar.vt)
  1065. {
  1066. continue;
  1067. }
  1068. // Figure out the size of the action value
  1069. switch (pItem->propvar.vt)
  1070. {
  1071. case VT_UI4:
  1072. pbData = (BYTE * ) &(pItem->propvar.ulVal);
  1073. cbData = sizeof(pItem->propvar.ulVal);
  1074. break;
  1075. case VT_LPSTR:
  1076. pbData = (BYTE * ) (pItem->propvar.pszVal);
  1077. cbData = lstrlen(pItem->propvar.pszVal) + 1;
  1078. break;
  1079. case VT_BLOB:
  1080. pbData = pItem->propvar.blob.pBlobData;
  1081. cbData = pItem->propvar.blob.cbSize;
  1082. break;
  1083. default:
  1084. AssertSz(FALSE, "Why are we trying to save in a invalid action type?");
  1085. hr = E_FAIL;
  1086. goto exit;
  1087. break;
  1088. }
  1089. // Write out the action value size
  1090. hr = pStm->Write(&cbData, sizeof(cbData), &cbWritten);
  1091. if (FAILED(hr))
  1092. {
  1093. goto exit;
  1094. }
  1095. Assert(cbWritten == sizeof(cbData));
  1096. // Write out the action value
  1097. hr = pStm->Write(pbData, cbData, &cbWritten);
  1098. if (FAILED(hr))
  1099. {
  1100. goto exit;
  1101. }
  1102. Assert(cbWritten == cbData);
  1103. }
  1104. // Should we clear out the dirty bit
  1105. if (FALSE != fClearDirty)
  1106. {
  1107. m_dwState &= ~ACT_STATE_DIRTY;
  1108. }
  1109. // Set the return value
  1110. hr = S_OK;
  1111. exit:
  1112. return hr;
  1113. }