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.

3714 lines
107 KiB

  1. // --------------------------------------------------------------------------------
  2. // MIGRATE.CPP
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // --------------------------------------------------------------------------------
  5. #include "pch.hxx"
  6. #include "strconst.h"
  7. #include "resource.h"
  8. #include "storfldr.h"
  9. #include <imnact.h>
  10. #include <acctutil.h>
  11. #include "shlwapi.h"
  12. #include <mimeole.h>
  13. #include "xpcomm.h"
  14. #include "oerules.h"
  15. #include "goptions.h"
  16. #include "ruleutil.h"
  17. #include "criteria.h"
  18. #include "actions.h"
  19. #include "rule.h"
  20. #include "storutil.h"
  21. #include "shared.h"
  22. #include "multiusr.h"
  23. #include "msident.h"
  24. #include "imapute.h"
  25. #include <store.h>
  26. #include "demand.h"
  27. static const char c_szSettingsUpgraded[] = {"Settings Upgraded"};
  28. BOOL g_fMigrationDone = FALSE;
  29. void MigrateSettings(HKEY hkey);
  30. HRESULT MigrateStoreToV2(HKEY hkeyV2, LPTSTR pszSrc, DWORD cchSrc, LPTSTR pszDest, DWORD cchDest);
  31. HRESULT MigrateAccounts(void);
  32. HRESULT MigrateMailServers(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3, HKEY hkeySmtp);
  33. HRESULT MigrateNewsServers(IImnAccountManager *pAcctMan, HKEY hkeyNews);
  34. HRESULT MigrateBase64EncodedPassword(LPCSTR pszBase64, DWORD cch, DWORD dwPropId, IImnAccount *pAccount);
  35. HRESULT MigrateServerDataFiles(LPSTR pszServer, LPCSTR pszOldDir, LPCSTR pszSubDir);
  36. void MigrateAccessibilityKeys(void);
  37. HRESULT MigrateToPropertyStore(void);
  38. void MigrateMailRulesSettings(void);
  39. void ConvertToDBX(void);
  40. void MigrateAccConnSettings();
  41. void ForwardMigrateConnSettings();
  42. void MigrateBeta2Rules();
  43. void Stage5RulesMigration(VOID);
  44. void Stage6RulesMigration(VOID);
  45. #define VERLEN 20
  46. // Data structures
  47. typedef enum
  48. {
  49. VER_NONE = 0,
  50. VER_1_0,
  51. VER_1_1,
  52. VER_4_0,
  53. VER_5_0_B1,
  54. VER_5_0,
  55. VER_MAX,
  56. } SETUPVER;
  57. /*******************************************************************
  58. NAME: ConvertVerToEnum
  59. ********************************************************************/
  60. SETUPVER ConvertVerToEnum(WORD *pwVer)
  61. {
  62. SETUPVER sv;
  63. Assert(pwVer);
  64. switch (pwVer[0])
  65. {
  66. case 0:
  67. sv = VER_NONE;
  68. break;
  69. case 1:
  70. if (0 == pwVer[1])
  71. sv = VER_1_0;
  72. else
  73. sv = VER_1_1;
  74. break;
  75. case 4:
  76. sv = VER_4_0;
  77. break;
  78. case 5:
  79. sv = VER_5_0;
  80. break;
  81. default:
  82. sv = VER_MAX;
  83. }
  84. return sv;
  85. }
  86. /*******************************************************************
  87. NAME: ConvertStrToVer
  88. ********************************************************************/
  89. void ConvertStrToVer(LPCSTR pszStr, WORD *pwVer)
  90. {
  91. int i;
  92. Assert(pszStr);
  93. Assert(pwVer);
  94. ZeroMemory(pwVer, 4 * sizeof(WORD));
  95. for (i=0; i<4; i++)
  96. {
  97. while (*pszStr && (*pszStr != ',') && (*pszStr != '.'))
  98. {
  99. pwVer[i] *= 10;
  100. pwVer[i] += *pszStr - '0';
  101. pszStr++;
  102. }
  103. if (*pszStr)
  104. pszStr++;
  105. }
  106. return;
  107. }
  108. /*******************************************************************
  109. NAME: GetVerInfo
  110. ********************************************************************/
  111. void GetVerInfo(SETUPVER *psvCurr, SETUPVER *psvPrev)
  112. {
  113. HKEY hkeyT;
  114. DWORD cb;
  115. CHAR szVer[VERLEN];
  116. WORD wVer[4];
  117. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWABVerInfo, 0, KEY_QUERY_VALUE, &hkeyT))
  118. {
  119. if (psvCurr)
  120. {
  121. cb = sizeof(szVer);
  122. RegQueryValueExA(hkeyT, c_szRegCurrVer, NULL, NULL, (LPBYTE)szVer, &cb);
  123. ConvertStrToVer(szVer, wVer);
  124. *psvCurr = ConvertVerToEnum(wVer);
  125. }
  126. if (psvPrev)
  127. {
  128. cb = sizeof(szVer);
  129. RegQueryValueExA(hkeyT, c_szRegPrevVer, NULL, NULL, (LPBYTE)szVer, &cb);
  130. ConvertStrToVer(szVer, wVer);
  131. *psvPrev = ConvertVerToEnum(wVer);
  132. }
  133. RegCloseKey(hkeyT);
  134. }
  135. }
  136. // Entry Point
  137. HRESULT MigrateAndUpgrade()
  138. {
  139. DWORD dwMigrate, cb, type, fMigratedStore, fMigratedStoreOE5, fConvertedToDBX, dwRegVer=0, dwMasterVer=0;
  140. BOOL fNewID=FALSE;
  141. HKEY hkey, hkeyForceful;
  142. TCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
  143. // Keep this up to date!
  144. #define LAST_MIGVALUE 7
  145. if (g_fMigrationDone)
  146. return(S_OK);
  147. ForwardMigrateConnSettings();
  148. if (ERROR_SUCCESS == RegCreateKeyEx(MU_GetCurrentUserHKey(), c_szRegRoot, NULL, NULL,
  149. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &cb))
  150. {
  151. // Before anything else, see if this identity has had its registry initialized
  152. cb = sizeof(dwRegVer);
  153. if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szOEVerStamp, 0, &type, (LPBYTE)&dwRegVer, &cb))
  154. {
  155. HKEY hkeyDef;
  156. // No Defaults at all
  157. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegDefaultSettings, 0, KEY_READ, &hkeyDef))
  158. {
  159. CopyRegistry(hkeyDef, hkey);
  160. RegCloseKey(hkeyDef);
  161. }
  162. fNewID = TRUE;
  163. }
  164. else if (type != REG_DWORD || cb != sizeof(DWORD))
  165. {
  166. dwRegVer = 0;
  167. }
  168. // Compare to forceful setting reg value to see if we need those
  169. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegForcefulSettings, 0, KEY_READ, &hkeyForceful))
  170. {
  171. cb = sizeof(dwMasterVer);
  172. RegQueryValueEx(hkeyForceful, c_szOEVerStamp, 0, NULL, (LPBYTE)&dwMasterVer, &cb);
  173. // Do we need to copy these in?
  174. if (dwRegVer < dwMasterVer)
  175. {
  176. // The act of copying will set c_szOEVerStamp
  177. CopyRegistry(hkeyForceful, hkey);
  178. }
  179. RegCloseKey(hkeyForceful);
  180. }
  181. // Start with no paths
  182. szSrc[0] = szDest[0] = 0;
  183. // move the store from v1 location to new location.
  184. // this is done because v1 barfs when trying to look at v2 store.
  185. // when we uninstall, we try to move the store back to its v1 location
  186. // and we tweak the versions of the store files so v1 repairs the files
  187. // and can run without crashing
  188. // HKCU,"software/microsoft/outlook express/5.0","MSIMN"
  189. if (fNewID)
  190. {
  191. fMigratedStore = TRUE;
  192. RegSetValueEx(hkey, c_szMSIMN, NULL, REG_DWORD, (LPBYTE)&fMigratedStore, sizeof(fMigratedStore));
  193. }
  194. else
  195. {
  196. cb = sizeof(fMigratedStore);
  197. if (RegQueryValueEx(hkey, c_szMSIMN, NULL, NULL, (LPBYTE)&fMigratedStore, &cb) != ERROR_SUCCESS)
  198. fMigratedStore = FALSE;
  199. if (!fMigratedStore)
  200. {
  201. // See if there is a v1 store, if so, figure out source and dest
  202. MigrateStoreToV2(hkey, szSrc, ARRAYSIZE(szSrc), szDest, ARRAYSIZE(szDest));
  203. fMigratedStore = TRUE;
  204. RegSetValueEx(hkey, c_szMSIMN, NULL, REG_DWORD, (LPBYTE)&fMigratedStore, sizeof(fMigratedStore));
  205. }
  206. }
  207. // we need to do this everytime we startup.
  208. // thank the trident guys for this lovely perf hit.
  209. MigrateAccessibilityKeys();
  210. if (fNewID)
  211. dwMigrate = LAST_MIGVALUE;
  212. else
  213. {
  214. cb = sizeof(dwMigrate);
  215. if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSettingsUpgraded, 0, &type, (LPBYTE)&dwMigrate, &cb))
  216. dwMigrate = 0;
  217. }
  218. // ATTENTION! PLEASES READ THE FOLLOWING BEFORE CHANGING THE UPGRADE CODE,
  219. // SO YOU DON'T MESS ANYTHING UP. (i don't often comment anything so this must
  220. // be important.)
  221. //
  222. // everything in the dwMigrate == 0 case is pre-oe5 and before we had one place to do
  223. // upgrade and migration of previous oe settings. some of the pre-oe5 migration code used
  224. // their own reg values to indicate that migration had been performed, so we'll use those
  225. // in this case.
  226. // but from now on all migration should use the same reg value (c_szSettingsUpgraded) to
  227. // track what needs to be upgraded/migrated. as you change something and add migration code
  228. // bump up the value
  229. if (dwMigrate == 0)
  230. {
  231. SETUPVER svPrev;
  232. // HKCU,"software/microsoft/outlook express/5.0","Settings Migrated"
  233. MigrateSettings(hkey);
  234. GetVerInfo(NULL, &svPrev);
  235. if (VER_1_0 == svPrev || VER_1_1 == svPrev)
  236. MigrateAccounts();
  237. dwMigrate = 1;
  238. }
  239. if (dwMigrate == 1)
  240. {
  241. // MigrateCharSetMapSettings(); // We don't need to migrate this settings,
  242. // but need to keep dwMigrate for Beta2. (YST)
  243. dwMigrate = 2;
  244. }
  245. if (dwMigrate == 2)
  246. {
  247. //Migrate account connection settings
  248. MigrateAccConnSettings();
  249. dwMigrate = 3;
  250. }
  251. // More settings migratation are done after the store migration
  252. // For Outlook Express V5, we migrate the OE4 version store to the ObjectDB Store.
  253. // For V1 Users, the code above will have just executed and now they get to migrate again.
  254. if (fNewID)
  255. fMigratedStoreOE5 = TRUE;
  256. else
  257. {
  258. cb = sizeof(fMigratedStoreOE5);
  259. if (RegQueryValueEx(hkey, c_szStoreMigratedToOE5, NULL, NULL, (LPBYTE)&fMigratedStoreOE5, &cb) != ERROR_SUCCESS)
  260. fMigratedStoreOE5 = FALSE;
  261. }
  262. if (!fMigratedStoreOE5)
  263. {
  264. // If we didn't just come from v1, we don't know where we are coming from or going to...
  265. // Default to Store Root location
  266. if (!szSrc[0])
  267. {
  268. Assert(!szDest[0]);
  269. cb = sizeof(szSrc);
  270. RegQueryValueEx(hkey, c_szRegStoreRootDir, 0, &type, (LPBYTE)szSrc, &cb);
  271. if (REG_EXPAND_SZ == type)
  272. {
  273. ExpandEnvironmentStrings(szSrc, szDest, ARRAYSIZE(szDest));
  274. StrCpyN(szSrc, szDest, ARRAYSIZE(szSrc));
  275. }
  276. else
  277. StrCpyN(szDest, szSrc, ARRAYSIZE(szDest));
  278. }
  279. else
  280. Assert(szDest[0]);
  281. // Do we have anything to migrate?
  282. if (szSrc[0] && szDest[0])
  283. {
  284. if (SUCCEEDED(MigrateLocalStore(NULL, szSrc, szDest)))
  285. {
  286. // Since the store migration remapped the folder id
  287. // we must fix up the folder id in the rules
  288. ImapUtil_B2SetDirtyFlag();
  289. fMigratedStoreOE5 = TRUE;
  290. RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fMigratedStoreOE5, sizeof(fMigratedStoreOE5));
  291. }
  292. }
  293. else
  294. // Nothing to migrate = success!
  295. fMigratedStoreOE5 = TRUE;
  296. }
  297. // Save state
  298. RegSetValueEx(hkey, c_szStoreMigratedToOE5, NULL, REG_DWORD, (LPBYTE)&fMigratedStoreOE5, sizeof(fMigratedStoreOE5));
  299. if (fNewID)
  300. {
  301. fConvertedToDBX = TRUE;
  302. RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fConvertedToDBX, sizeof(fConvertedToDBX));
  303. }
  304. else
  305. {
  306. cb = sizeof(fConvertedToDBX);
  307. if (RegQueryValueEx(hkey, c_szConvertedToDBX, NULL, NULL, (LPBYTE)&fConvertedToDBX, &cb) != ERROR_SUCCESS)
  308. fConvertedToDBX = FALSE;
  309. if (!fConvertedToDBX)
  310. {
  311. fConvertedToDBX = TRUE;
  312. ConvertToDBX();
  313. RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fConvertedToDBX, sizeof(fConvertedToDBX));
  314. }
  315. }
  316. if (dwMigrate == 3)
  317. {
  318. //Migrate rules settings
  319. // This must be done after the store has been migrated
  320. MigrateMailRulesSettings();
  321. dwMigrate = 4;
  322. }
  323. if (dwMigrate == 4)
  324. {
  325. //Migrate from Beta 2 rules
  326. // This must be done after the store has been migrated
  327. MigrateBeta2Rules();
  328. dwMigrate = 5;
  329. }
  330. if (dwMigrate == 5)
  331. {
  332. //Migrate from Beta 2 rules
  333. // This must be done after the store has been migrated
  334. Stage5RulesMigration();
  335. dwMigrate = 6;
  336. }
  337. if (dwMigrate == 6)
  338. {
  339. //Migrate from Beta 2 rules
  340. // This must be done after the store has been migrated
  341. Stage6RulesMigration();
  342. dwMigrate = LAST_MIGVALUE;
  343. }
  344. // Write the present upgraded settings value
  345. RegSetValueEx(hkey, c_szSettingsUpgraded, 0, REG_DWORD, (LPBYTE)&dwMigrate, sizeof(dwMigrate));
  346. // Cleanup
  347. RegCloseKey(hkey);
  348. }
  349. g_fMigrationDone = TRUE;
  350. return(S_OK);
  351. }
  352. //--------------------------------------------------------------------------
  353. // MigrateAccConnSettings
  354. //
  355. // This migrates the connection settings for each account. This should be called
  356. // for the following upgrade scenarios. 1)Upgrade from pre-OE5 to OE5 Beta2 or more
  357. // 2)Upgrade from OeBeta1 to OE5 Beta2 or more
  358. // If the Connection Setting was previously LAN, we migrate it to use InternetConnection
  359. // (which is any connection available). If the previous setting was RAS, we leave it
  360. // as it is.
  361. //
  362. //--------------------------------------------------------------------------
  363. void MigrateAccConnSettings()
  364. {
  365. IImnEnumAccounts *pEnum = NULL;
  366. IImnAccount *pAccount = NULL;
  367. DWORD dwConnection;
  368. Assert(g_pAcctMan == NULL);
  369. if (FAILED(AcctUtil_CreateAccountManagerForIdentity(PGUIDCurrentOrDefault(), &g_pAcctMan)))
  370. {
  371. return;
  372. }
  373. if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum)))
  374. {
  375. while(SUCCEEDED(pEnum->GetNext(&pAccount)))
  376. {
  377. // Get Email Address
  378. if (SUCCEEDED(pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  379. {
  380. if (dwConnection == CONNECTION_TYPE_LAN)
  381. {
  382. pAccount->SetPropDw(AP_RAS_CONNECTION_TYPE, CONNECTION_TYPE_INETSETTINGS);
  383. pAccount->SaveChanges();
  384. }
  385. }
  386. SafeRelease(pAccount);
  387. }
  388. SafeRelease(pEnum);
  389. }
  390. g_pAcctMan->Release();
  391. g_pAcctMan = NULL;
  392. }
  393. void ForwardMigrateConnSettings()
  394. {
  395. /*
  396. We shouldn't have to do all the stuff we do above in MigrateAccConnSettings.
  397. We just need to look at the old regsitry settings at
  398. \\HKCU\Software\Microsoft\Internet Account Manager\Accounts.
  399. Migrating from OE4 to OE5 just uses the same location if there is only one identity.
  400. */
  401. HKEY hKeyAccounts = NULL;
  402. DWORD dwAcctSubKeys = 0;
  403. LONG retval;
  404. DWORD index = 0;
  405. LPTSTR lpszAccountName = NULL;
  406. HKEY hKeyAccountName = NULL;
  407. DWORD memsize = 0;
  408. DWORD dwValue;
  409. DWORD cbData = sizeof(DWORD);
  410. DWORD cbMaxAcctSubKeyLen;
  411. DWORD DataType;
  412. DWORD dwConnSettingsMigrated = 1;
  413. //This setting is in \\HKCU\Software\Microsoft\InternetAccountManager\Accounts
  414. retval = RegOpenKey(HKEY_CURRENT_USER, c_szIAMAccounts, &hKeyAccounts);
  415. if (ERROR_SUCCESS != retval)
  416. goto exit;
  417. retval = RegQueryValueEx(hKeyAccounts, c_szConnSettingsMigrated, NULL, &DataType,
  418. (LPBYTE)&dwConnSettingsMigrated, &cbData);
  419. if ((retval != ERROR_FILE_NOT_FOUND) && (retval != ERROR_SUCCESS || dwConnSettingsMigrated == 1))
  420. goto exit;
  421. retval = RegQueryInfoKey(hKeyAccounts, NULL, NULL, NULL, &dwAcctSubKeys,
  422. &cbMaxAcctSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
  423. if (ERROR_SUCCESS != retval)
  424. goto exit;
  425. memsize = sizeof(TCHAR) * cbMaxAcctSubKeyLen;
  426. if (!MemAlloc((LPVOID*)&lpszAccountName, memsize))
  427. {
  428. lpszAccountName = NULL;
  429. goto exit;
  430. }
  431. ZeroMemory(lpszAccountName, memsize);
  432. while (index < dwAcctSubKeys)
  433. {
  434. retval = RegEnumKey(hKeyAccounts, index, lpszAccountName, memsize);
  435. index++;
  436. if (retval == ERROR_SUCCESS)
  437. {
  438. retval = RegOpenKey(hKeyAccounts, lpszAccountName, &hKeyAccountName);
  439. if (retval == ERROR_SUCCESS)
  440. {
  441. cbData = sizeof(DWORD);
  442. retval = RegQueryValueEx(hKeyAccountName, c_szConnectionType, NULL, &DataType, (LPBYTE)&dwValue, &cbData);
  443. if (retval == ERROR_SUCCESS)
  444. {
  445. if (dwValue == CONNECTION_TYPE_LAN)
  446. {
  447. dwValue = CONNECTION_TYPE_INETSETTINGS;
  448. retval = RegSetValueEx(hKeyAccountName, c_szConnectionType, 0, REG_DWORD, (const BYTE *)&dwValue,
  449. sizeof(DWORD));
  450. }
  451. }
  452. RegCloseKey(hKeyAccountName);
  453. }
  454. }
  455. }
  456. //Set this to one so, when we downgrade when we do backward migration based on this key value
  457. dwConnSettingsMigrated = 1;
  458. RegSetValueEx(hKeyAccounts, c_szConnSettingsMigrated, 0, REG_DWORD, (const BYTE*)&dwConnSettingsMigrated,
  459. sizeof(DWORD));
  460. exit:
  461. SafeMemFree(lpszAccountName);
  462. if (hKeyAccounts)
  463. RegCloseKey(hKeyAccounts);
  464. }
  465. //--------------------------------------------------------------------------
  466. // ConvertToDBX
  467. //--------------------------------------------------------------------------
  468. void ConvertToDBX(void)
  469. {
  470. // Locals
  471. HRESULT hr=S_OK;
  472. CHAR szRootDir[MAX_PATH + MAX_PATH];
  473. CHAR szSrcFile[MAX_PATH + MAX_PATH];
  474. CHAR szDstFile[MAX_PATH + MAX_PATH];
  475. // Trace
  476. TraceCall("ConvertToDBX");
  477. // Get Root Directory
  478. IF_FAILEXIT(hr = GetStoreRootDirectory(szRootDir, ARRAYSIZE(szRootDir)));
  479. // Folders
  480. MakeFilePath(szRootDir, "folders.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
  481. MakeFilePath(szRootDir, "folders.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
  482. DeleteFile(szDstFile);
  483. MoveFile(szSrcFile, szDstFile);
  484. // Pop3uidl
  485. MakeFilePath(szRootDir, "pop3uidl.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
  486. MakeFilePath(szRootDir, "pop3uidl.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
  487. DeleteFile(szDstFile);
  488. MoveFile(szSrcFile, szDstFile);
  489. // Offline
  490. MakeFilePath(szRootDir, "Offline.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
  491. MakeFilePath(szRootDir, "Offline.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
  492. DeleteFile(szDstFile);
  493. MoveFile(szSrcFile, szDstFile);
  494. exit:
  495. // Done
  496. return;
  497. }
  498. HRESULT MigrateStoreToV2(HKEY hkeyV2, LPTSTR pszSrc, DWORD cchSrc, LPTSTR pszDest, DWORD cchDest)
  499. {
  500. HKEY hkeyV1;
  501. BOOL fMoved = FALSE;
  502. Assert(pszSrc);
  503. Assert(pszDest);
  504. Assert(cchSrc > 0);
  505. Assert(cchDest > 0);
  506. // Okay, this is the first time. Let's see if a previous version exists.
  507. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  508. c_szRegRoot_V1,
  509. 0,
  510. KEY_READ,
  511. &hkeyV1))
  512. {
  513. DWORD dwType;
  514. // No need to worry about REG_EXPAND_SZ here as V1 didn't write it
  515. if (ERROR_SUCCESS == RegQueryValueEx(hkeyV1,
  516. c_szRegStoreRootDir,
  517. NULL,
  518. &dwType,
  519. (LPBYTE)pszSrc,
  520. &cchSrc) && *pszSrc)
  521. {
  522. AssertSz(REG_EXPAND_SZ != dwType, "V1's store path is REG_EXPAND_SZ!");
  523. // Figure out new path
  524. GetDefaultStoreRoot(NULL, pszDest, cchDest);
  525. // Remember it
  526. RegSetValueEx(hkeyV2, c_szRegStoreRootDir, NULL, REG_SZ, (LPBYTE)pszDest, (lstrlen(pszDest)+1) * sizeof(TCHAR));
  527. }
  528. RegCloseKey(hkeyV1);
  529. }
  530. return(S_OK);
  531. }
  532. static const LPCTSTR c_rgCommonSettings[] =
  533. {
  534. c_szRegAlwaysSuggest,
  535. c_szRegIgnoreNumbers,
  536. c_szRegIgnoreUpper,
  537. c_szRegIgnoreProtect,
  538. c_szRegCheckOnSend,
  539. c_szRegIgnoreDBCS,
  540. c_szRasConnDetails
  541. };
  542. static const LPCTSTR c_rgMailSettings[] =
  543. {
  544. c_szOptNewMailSound,
  545. c_szPurgeWaste,
  546. c_szOptnSaveInSentItems,
  547. c_szRegIncludeMsg,
  548. c_szRegPollForMail,
  549. c_szRegSendImmediate,
  550. c_szRegSigType,
  551. c_szRegSigText,
  552. c_szRegSigFile,
  553. c_szMarkPreviewAsRead,
  554. c_szRegIndentChar,
  555. c_szLogSmtp,
  556. c_szLogPop3,
  557. c_szSmtpLogFile,
  558. c_szPop3LogFile
  559. };
  560. static const LPCTSTR c_rgNewsSettings[] =
  561. {
  562. c_szRegDownload,
  563. c_szRegAutoExpand,
  564. c_szRegNotifyNewGroups,
  565. c_szRegMarkAllRead,
  566. c_szRegSigType,
  567. c_szRegSigText,
  568. c_szRegSigFile,
  569. c_szRegNewsNoteAdvRead,
  570. c_szRegNewsNoteAdvSend,
  571. c_szRegNewsFillPreview,
  572. c_szCacheDelMsgDays,
  573. c_szCacheRead,
  574. c_szCacheCompactPer
  575. };
  576. // Copies values listed in ppszSettings from hkeyOld to hkey
  577. void MigrateNode(HKEY hkey, HKEY hkeyOld, LPCTSTR pszSub, LPCTSTR *ppszSettings, int cSettings)
  578. {
  579. int i;
  580. HKEY hkeyOldT, hkeyT;
  581. DWORD cValues, cbMax, cb, type;
  582. BYTE *pb;
  583. Assert(hkey != NULL);
  584. Assert(hkeyOld != NULL);
  585. Assert(ppszSettings != NULL);
  586. Assert(cSettings > 0);
  587. if (pszSub != NULL)
  588. {
  589. if (ERROR_SUCCESS != RegOpenKeyEx(hkeyOld, pszSub, 0, KEY_READ, &hkeyOldT))
  590. return;
  591. hkeyOld = hkeyOldT;
  592. if (ERROR_SUCCESS != RegCreateKeyEx(hkey, pszSub, NULL, NULL,
  593. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyT, &cb))
  594. {
  595. RegCloseKey(hkeyOldT);
  596. return;
  597. }
  598. hkey = hkeyT;
  599. }
  600. if (ERROR_SUCCESS == RegQueryInfoKey(hkeyOld, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  601. &cValues, &cbMax, NULL, NULL) &&
  602. cValues > 0 &&
  603. cbMax > 0 &&
  604. MemAlloc((void **)&pb, cbMax))
  605. {
  606. for (i = 0; i < cSettings; i++)
  607. {
  608. cb = cbMax;
  609. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, *ppszSettings, NULL, &type, pb, &cb))
  610. RegSetValueEx(hkey, *ppszSettings, 0, type, pb, cb);
  611. ppszSettings++;
  612. }
  613. MemFree(pb);
  614. }
  615. if (pszSub != NULL)
  616. {
  617. RegCloseKey(hkeyT);
  618. RegCloseKey(hkeyOldT);
  619. }
  620. }
  621. BOOL MigrateSignature(HKEY hkey, HKEY hkeyOld, DWORD dwSig, BOOL fMail)
  622. {
  623. BOOL fMigrate;
  624. DWORD dwSigType, dwSigOpt, cb, type;
  625. HKEY hkeySig;
  626. char *psz, sz[MAX_PATH];
  627. fMigrate = FALSE;
  628. dwSigType = LOWORD(dwSig);
  629. dwSigOpt = HIWORD(dwSig);
  630. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, (dwSigType == 2) ? c_szRegSigFile : c_szRegSigText, NULL, &type, NULL, &cb) &&
  631. cb > 1 &&
  632. MemAlloc((void **)&psz, cb))
  633. {
  634. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, (dwSigType == 2) ? c_szRegSigFile : c_szRegSigText, NULL, &type, (LPBYTE)psz, &cb))
  635. {
  636. wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szSigs, fMail ? c_szMail : c_szNews);
  637. if (ERROR_SUCCESS == RegCreateKeyEx(hkey, sz, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeySig, &type))
  638. {
  639. if (type == REG_CREATED_NEW_KEY)
  640. {
  641. // name
  642. AthLoadString(fMail ? idsMailSig : idsNewsSig, sz, ARRAYSIZE(sz));
  643. RegSetValueEx(hkeySig, c_szSigName, 0, REG_SZ, (LPBYTE)sz, lstrlen(sz) + 1);
  644. // text/file
  645. RegSetValueEx(hkeySig, (dwSigType == 2) ? c_szSigFile : c_szSigText, 0, REG_SZ, (LPBYTE)psz, cb);
  646. // type
  647. RegSetValueEx(hkeySig, c_szSigType, 0, REG_DWORD, (LPBYTE)&dwSigType, sizeof(dwSigType));
  648. fMigrate = TRUE;
  649. }
  650. RegCloseKey(hkeySig);
  651. }
  652. }
  653. MemFree(psz);
  654. }
  655. return(fMigrate);
  656. }
  657. static const TCHAR c_szSettingsMigrated[] = TEXT("Settings Migrated");
  658. void MigrateSettings(HKEY hkey)
  659. {
  660. HKEY hkeySrc, hkeyDst, hkeyOld;
  661. DWORD dw, cb, type, dwMigrate, dwSig, dwFlags;
  662. TCHAR szPath[MAX_PATH];
  663. cb = sizeof(dwMigrate);
  664. if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSettingsMigrated, NULL, &type, (LPBYTE)&dwMigrate, &cb))
  665. dwMigrate = 0;
  666. // v4.0 migration
  667. if (dwMigrate == 0)
  668. {
  669. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegRoot_V1, 0, KEY_READ, &hkeyOld))
  670. {
  671. MigrateNode(hkey, hkeyOld, NULL, (LPCTSTR *)c_rgCommonSettings, ARRAYSIZE(c_rgCommonSettings));
  672. MigrateNode(hkey, hkeyOld, c_szMail, (LPCTSTR *)c_rgMailSettings, ARRAYSIZE(c_rgMailSettings));
  673. MigrateNode(hkey, hkeyOld, c_szNews, (LPCTSTR *)c_rgNewsSettings, ARRAYSIZE(c_rgNewsSettings));
  674. RegCloseKey(hkeyOld);
  675. }
  676. // copy the inbox rules
  677. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szInboxRulesPath_V1, 0, KEY_READ, &hkeySrc))
  678. {
  679. StrCpyN(szPath, c_szRegRoot, ARRAYSIZE(szPath));
  680. StrCatBuff(szPath, c_szInboxRulesPath, ARRAYSIZE(szPath));
  681. if (ERROR_SUCCESS == RegCreateKeyEx(MU_GetCurrentUserHKey(), szPath, 0, NULL,
  682. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDst, &dw))
  683. {
  684. if (dw != REG_OPENED_EXISTING_KEY)
  685. CopyRegistry(hkeySrc, hkeyDst);
  686. RegCloseKey(hkeyDst);
  687. }
  688. RegCloseKey(hkeySrc);
  689. }
  690. dwMigrate = 1;
  691. }
  692. // v5.0 migration
  693. if (dwMigrate == 1)
  694. {
  695. dwFlags = 0xffffffff;
  696. // mail signature
  697. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, c_szMail, 0, KEY_READ, &hkeyOld))
  698. {
  699. cb = sizeof(dwSig);
  700. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, c_szRegSigType, NULL, &type, (LPBYTE)&dwSig, &cb) &&
  701. LOWORD(dwSig) != 0)
  702. {
  703. if (MigrateSignature(hkey, hkeyOld, dwSig, TRUE))
  704. dwFlags = HIWORD(dwSig);
  705. }
  706. RegCloseKey(hkeyOld);
  707. }
  708. // news signature
  709. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, c_szNews, 0, KEY_READ, &hkeyOld))
  710. {
  711. cb = sizeof(dwSig);
  712. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, c_szRegSigType, NULL, &type, (LPBYTE)&dwSig, &cb) &&
  713. LOWORD(dwSig) != 0)
  714. {
  715. if (MigrateSignature(hkey, hkeyOld, dwSig, FALSE) &&
  716. dwFlags == 0xffffffff)
  717. dwFlags = HIWORD(dwSig);
  718. }
  719. RegCloseKey(hkeyOld);
  720. }
  721. cb = sizeof(dw);
  722. if (dwFlags != 0xffffffff &&
  723. ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSigFlags, NULL, &type, (LPBYTE)&dw, &cb))
  724. {
  725. RegSetValueEx(hkey, c_szSigFlags, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
  726. }
  727. }
  728. }
  729. const static char c_szRegImnMail[] = {"Software\\Microsoft\\Internet Mail and News\\Mail"};
  730. const static char c_szMailPOP3Path[] = {"Software\\Microsoft\\Internet Mail and News\\Mail\\POP3"};
  731. const static char c_szMailSMTPPath[] = {"Software\\Microsoft\\Internet Mail and News\\Mail\\SMTP"};
  732. const static char c_szRegImnNews[] = {"Software\\Microsoft\\Internet Mail and News\\News"};
  733. const static char c_szDefaultSmtpServer[] = {"Default SMTP Server"};
  734. const static char c_szDefaultPop3Server[] = {"Default POP3 Server"};
  735. const static char c_szRegConnectType[] = {"Connection Type"};
  736. const static char c_szRegRasPhonebookEntry[] = {"RAS Phonebook Entry"};
  737. const static char c_szRegMailConnectType[] = {"Mail Connection Type"};
  738. const static char c_szSenderOrg[] = {"Sender Organization"};
  739. const static char c_szSenderEMail[] = {"Sender EMail"};
  740. const static char c_szSenderReplyTo[] = {"Reply To"};
  741. const static char c_szSendTimeout[] = {"SendTimeout"};
  742. const static char c_szRecvTimeout[] = {"RecvTimeout"};
  743. const static char c_szPort[] = {"Port"};
  744. const static char c_szRegBreakMessages[] = {"Break Message Size (KB)"};
  745. const static char c_szRegAccountName[] = {"Account Name"};
  746. const static char c_szRegUseSicily[] = {"Use Sicily"};
  747. const static char c_szRegSecureConnect[] = {"Secure Connection"};
  748. const static char c_szRegServerTimeout[] = {"Timeout"};
  749. const static char c_szRegServerPort[] = {"NNTP Port"};
  750. const static char c_szRegUseDesc[] = {"Use Group Descriptions"};
  751. const static char c_szRegNewsConnectFlags[] = {"Connection Flags"};
  752. const static char c_szRegDefServer[] = {"DefaultServer"};
  753. const static char c_szLeaveOnServer[] = {"LeaveMailOnServer"};
  754. const static char c_szRemoveDeleted[] = {"RemoveOnClientDelete"};
  755. const static char c_szRemoveExpired[] = {"RemoveExpire"};
  756. const static char c_szExpireDays[] = {"ExpireDays"};
  757. const static char c_szRegAccount[] = {"Account"};
  758. HRESULT MigrateAccounts()
  759. {
  760. HKEY hkeyPop3, hkeySmtp, hkeyMail, hkeyNews;
  761. HRESULT hr = S_OK;
  762. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegImnMail, 0, KEY_ALL_ACCESS, &hkeyMail) != ERROR_SUCCESS)
  763. hkeyMail = NULL;
  764. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegImnNews, 0, KEY_ALL_ACCESS, &hkeyNews) != ERROR_SUCCESS)
  765. hkeyNews = NULL;
  766. if (hkeyMail != NULL || hkeyNews != NULL)
  767. {
  768. // Create account manger because CSubList depends on g_pAcctMan
  769. Assert(g_pAcctMan == NULL);
  770. // Only ever migrate to DEFAULT user!
  771. hr = AcctUtil_CreateAccountManagerForIdentity((GUID *)&UID_GIBC_DEFAULT_USER, &g_pAcctMan);
  772. if (SUCCEEDED(hr))
  773. {
  774. // Try to open: HKCU\Software\Microsoft\IMN\Mail\POP3
  775. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szMailPOP3Path, 0, KEY_ALL_ACCESS, &hkeyPop3) == ERROR_SUCCESS)
  776. {
  777. // Try to open: HKCU\Software\Microsoft\IMN\Mail\SMTP
  778. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szMailSMTPPath, 0, KEY_ALL_ACCESS, &hkeySmtp) == ERROR_SUCCESS)
  779. {
  780. hr = MigrateMailServers(g_pAcctMan, hkeyMail, hkeyPop3, hkeySmtp);
  781. Assert(SUCCEEDED(hr));
  782. RegCloseKey(hkeySmtp);
  783. }
  784. RegCloseKey(hkeyPop3);
  785. }
  786. if (hkeyNews != NULL)
  787. {
  788. hr = MigrateNewsServers(g_pAcctMan, hkeyNews);
  789. Assert(SUCCEEDED(hr));
  790. }
  791. g_pAcctMan->Release();
  792. g_pAcctMan = NULL;
  793. }
  794. if (hkeyMail != NULL)
  795. RegCloseKey(hkeyMail);
  796. if (hkeyNews != NULL)
  797. RegCloseKey(hkeyNews);
  798. }
  799. return(hr);
  800. }
  801. typedef struct tagACCTMIGRATEMAP
  802. {
  803. LPCSTR szRegValue;
  804. DWORD dwProp;
  805. } ACCTMIGRATEMAP;
  806. typedef const ACCTMIGRATEMAP *LPCMIGRATEMAP;
  807. HRESULT MigrateAccountSettings(IImnAccount *pAccount, HKEY hkey, LPCMIGRATEMAP pMap, int cMap)
  808. {
  809. HRESULT hr;
  810. int i;
  811. LPBYTE pb;
  812. PROPTYPE ptype;
  813. DWORD dw, cb, type;
  814. char sz[512];
  815. Assert(pAccount != NULL);
  816. Assert(pMap != NULL);
  817. Assert(cMap > 0);
  818. for (i = 0; i < cMap; i++, pMap++)
  819. {
  820. ptype = PROPTAG_TYPE(pMap->dwProp);
  821. Assert(ptype == TYPE_STRING || ptype == TYPE_DWORD || ptype == TYPE_BOOL || ptype == TYPE_PASS);
  822. if (ptype == TYPE_STRING || ptype == TYPE_PASS)
  823. {
  824. cb = sizeof(sz);
  825. pb = (LPBYTE)sz;
  826. }
  827. else
  828. {
  829. cb = sizeof(dw);
  830. pb = (LPBYTE)&dw;
  831. }
  832. if (RegQueryValueEx(hkey, pMap->szRegValue, 0, &type, pb, &cb) == ERROR_SUCCESS)
  833. {
  834. if (ptype == TYPE_PASS)
  835. {
  836. // IMN's Password is stored as ANSI in a REG_BINARY with no NULL terminator
  837. // Be sure to let MigrateBase64EncodedPassword know how long the password is
  838. hr = MigrateBase64EncodedPassword(sz, cb, pMap->dwProp, pAccount);
  839. }
  840. else
  841. hr = pAccount->SetProp(pMap->dwProp, pb, cb);
  842. if (FAILED(hr))
  843. break;
  844. }
  845. }
  846. return(hr);
  847. }
  848. static const ACCTMIGRATEMAP c_rgMailMap[] =
  849. {
  850. {c_szRegConnectType, AP_RAS_CONNECTION_TYPE},
  851. {c_szRegRasPhonebookEntry, AP_RAS_CONNECTOID},
  852. {c_szRegMailConnectType, AP_RAS_CONNECTION_FLAGS},
  853. {c_szSenderName, AP_SMTP_DISPLAY_NAME},
  854. {c_szSenderOrg, AP_SMTP_ORG_NAME},
  855. {c_szSenderEMail, AP_SMTP_EMAIL_ADDRESS},
  856. {c_szSenderReplyTo, AP_SMTP_REPLY_EMAIL_ADDRESS},
  857. };
  858. static const ACCTMIGRATEMAP c_rgPop3Map[] =
  859. {
  860. {c_szSendTimeout, AP_SMTP_TIMEOUT},
  861. {c_szRecvTimeout, AP_POP3_TIMEOUT},
  862. {c_szPort, AP_POP3_PORT},
  863. {c_szLeaveOnServer, AP_POP3_LEAVE_ON_SERVER},
  864. {c_szRemoveDeleted, AP_POP3_REMOVE_DELETED},
  865. {c_szRemoveExpired, AP_POP3_REMOVE_EXPIRED},
  866. {c_szExpireDays, AP_POP3_EXPIRE_DAYS},
  867. {c_szRegAccount, AP_POP3_USERNAME},
  868. {c_szRegUseSicily, AP_POP3_USE_SICILY},
  869. {c_szPassword, AP_POP3_PASSWORD},
  870. };
  871. static const ACCTMIGRATEMAP c_rgSmtpMap[] =
  872. {
  873. {c_szPort, AP_SMTP_PORT}
  874. };
  875. HRESULT MigrateMailAccountSettings(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3Server,
  876. HKEY hkeySmtpServer, LPSTR szDefPop3Server, LPSTR szDefSmtpServer)
  877. {
  878. DWORD dw, cb;
  879. HRESULT hr;
  880. char sz[CCHMAX_ACCOUNT_NAME];
  881. IImnAccount *pAccount;
  882. Assert(pAcctMan != NULL);
  883. Assert(szDefPop3Server != NULL);
  884. Assert(szDefSmtpServer != NULL);
  885. hr = pAcctMan->CreateAccountObject(ACCT_MAIL, &pAccount);
  886. if (FAILED(hr))
  887. return(hr);
  888. CHECKHR(hr = pAccount->SetPropSz(AP_SMTP_SERVER, szDefSmtpServer));
  889. CHECKHR(hr = pAccount->SetPropSz(AP_POP3_SERVER, szDefPop3Server));
  890. // Set Friendly Name
  891. StrCpyN(sz, szDefPop3Server, ARRAYSIZE(sz));
  892. CHECKHR(hr = pAcctMan->GetUniqueAccountName(sz, ARRAYSIZE(sz)));
  893. CHECKHR(hr = pAccount->SetPropSz(AP_ACCOUNT_NAME, sz));
  894. cb = sizeof(dw);
  895. if (RegQueryValueEx(hkeyMail, c_szRegBreakMessages, 0, NULL, (LPBYTE)&dw, &cb) == ERROR_SUCCESS &&
  896. dw != 0xffffffff)
  897. {
  898. // AP_SPLITMSGS
  899. CHECKHR(hr = pAccount->SetPropDw(AP_SMTP_SPLIT_MESSAGES, TRUE));
  900. // AP_SPLITSIZE
  901. CHECKHR(hr = pAccount->SetPropDw(AP_SMTP_SPLIT_SIZE, dw));
  902. }
  903. CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyMail, c_rgMailMap, ARRAYSIZE(c_rgMailMap)));
  904. CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyPop3Server, c_rgPop3Map, ARRAYSIZE(c_rgPop3Map)));
  905. CHECKHR(hr = MigrateAccountSettings(pAccount, hkeySmtpServer, c_rgSmtpMap, ARRAYSIZE(c_rgSmtpMap)));
  906. // Save Account Changes
  907. hr = pAccount->SaveChanges();
  908. exit:
  909. pAccount->Release();
  910. return(hr);
  911. }
  912. // Note: This migrates only the default server, not un-supported multi servers
  913. HRESULT MigrateMailServers(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3, HKEY hkeySmtp)
  914. {
  915. char szDefSmtpServer[CCHMAX_SERVER_NAME],
  916. szDefPop3Server[CCHMAX_SERVER_NAME];
  917. ULONG cb;
  918. DWORD dw;
  919. HKEY hkeyPop3Server = NULL,
  920. hkeySmtpServer = NULL;
  921. BOOL fSmtpMigrated = FALSE,
  922. fPop3Migrated = FALSE;
  923. HRESULT hr = S_OK;
  924. Assert(pAcctMan != NULL);
  925. Assert(hkeyMail != NULL);
  926. Assert(hkeyPop3 != NULL);
  927. Assert(hkeySmtp != NULL);
  928. // Get Default SMTP Server
  929. cb = sizeof(szDefSmtpServer);
  930. if (RegQueryValueEx(hkeyMail, c_szDefaultSmtpServer, 0, NULL, (LPBYTE)szDefSmtpServer, &cb) == ERROR_SUCCESS &&
  931. !FIsEmpty(szDefSmtpServer))
  932. {
  933. // If we have a default smtp sever, lets open the key
  934. RegOpenKeyEx(hkeySmtp, szDefSmtpServer, 0, KEY_ALL_ACCESS, &hkeySmtpServer);
  935. }
  936. // Get Default POP3 Server
  937. cb = sizeof(szDefPop3Server);
  938. if (RegQueryValueEx(hkeyMail, c_szDefaultPop3Server, 0, NULL, (LPBYTE)szDefPop3Server, &cb) == ERROR_SUCCESS &&
  939. !FIsEmpty(szDefPop3Server))
  940. {
  941. // If we have a default pop3 sever, lets open the key
  942. RegOpenKeyEx(hkeyPop3, szDefPop3Server, 0, KEY_ALL_ACCESS, &hkeyPop3Server);
  943. }
  944. // If we couldn't open the pop3 server, lets look in the registry and use the first server
  945. if (hkeyPop3Server == NULL)
  946. {
  947. // Enumerate and open the first server in the list
  948. cb = sizeof(szDefPop3Server);
  949. if (RegEnumKeyEx(hkeyPop3, 0, szDefPop3Server, &cb, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
  950. RegOpenKeyEx(hkeyPop3, szDefPop3Server, 0, KEY_ALL_ACCESS, &hkeyPop3Server);
  951. }
  952. // If we couldn't open the pop3 server, lets look in the registry and use the first server
  953. if (hkeySmtpServer == NULL)
  954. {
  955. // Enumerate and open the first server in list
  956. cb = sizeof(szDefSmtpServer);
  957. if (RegEnumKeyEx(hkeySmtp, 0, szDefSmtpServer, &cb, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
  958. RegOpenKeyEx(hkeySmtp, szDefSmtpServer, 0, KEY_ALL_ACCESS, &hkeySmtpServer);
  959. }
  960. if (hkeySmtpServer != NULL)
  961. {
  962. cb = sizeof(fSmtpMigrated);
  963. RegQueryValueEx(hkeySmtpServer, c_szMigrated, 0, NULL, (LPBYTE)&fSmtpMigrated, &cb);
  964. if (hkeyPop3Server != NULL)
  965. {
  966. cb = sizeof(fPop3Migrated);
  967. RegQueryValueEx(hkeyPop3Server, c_szMigrated, 0, NULL, (LPBYTE)&fPop3Migrated, &cb);
  968. if (!fPop3Migrated && !fSmtpMigrated)
  969. {
  970. hr = MigrateMailAccountSettings(pAcctMan, hkeyMail, hkeyPop3Server,
  971. hkeySmtpServer, szDefPop3Server, szDefSmtpServer);
  972. if (SUCCEEDED(hr))
  973. {
  974. fSmtpMigrated = TRUE;
  975. RegSetValueEx(hkeySmtpServer, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fSmtpMigrated, sizeof(fSmtpMigrated));
  976. fPop3Migrated = TRUE;
  977. RegSetValueEx(hkeyPop3Server, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fPop3Migrated, sizeof(fPop3Migrated));
  978. }
  979. }
  980. RegCloseKey(hkeyPop3Server);
  981. }
  982. RegCloseKey(hkeySmtpServer);
  983. }
  984. return(S_OK);
  985. }
  986. static const ACCTMIGRATEMAP c_rgNewsMap[] =
  987. {
  988. {c_szSenderName, AP_NNTP_DISPLAY_NAME},
  989. {c_szSenderOrg, AP_NNTP_ORG_NAME},
  990. {c_szSenderEMail, AP_NNTP_EMAIL_ADDRESS},
  991. {c_szSenderReplyTo, AP_NNTP_REPLY_EMAIL_ADDRESS},
  992. };
  993. static const ACCTMIGRATEMAP c_rgNewsServerMap[] =
  994. {
  995. {c_szRegAccountName, AP_NNTP_USERNAME},
  996. {c_szRegUseSicily, AP_NNTP_USE_SICILY},
  997. {c_szRegSecureConnect, AP_NNTP_SSL},
  998. {c_szRegServerTimeout, AP_NNTP_TIMEOUT},
  999. {c_szRegServerPort, AP_NNTP_PORT},
  1000. {c_szRegUseDesc, AP_NNTP_USE_DESCRIPTIONS},
  1001. {c_szRegConnectType, AP_RAS_CONNECTION_TYPE},
  1002. {c_szRegRasPhonebookEntry, AP_RAS_CONNECTOID},
  1003. {c_szRegNewsConnectFlags, AP_RAS_CONNECTION_FLAGS},
  1004. {c_szPassword, AP_NNTP_PASSWORD},
  1005. };
  1006. HRESULT MigrateNewsAccountSettings(IImnAccountManager *pAcctMan, HKEY hkeyNews, HKEY hkeyServer, LPSTR szServer, BOOL fDefault)
  1007. {
  1008. IImnAccount *pAccount;
  1009. char sz[CCHMAX_ACCOUNT_NAME], szNewsDir[MAX_PATH], szDataDir[MAX_PATH];
  1010. HRESULT hr;
  1011. DWORD cb;
  1012. Assert(pAcctMan != NULL);
  1013. Assert(szServer != NULL);
  1014. hr = pAcctMan->CreateAccountObject(ACCT_NEWS, &pAccount);
  1015. if (FAILED(hr))
  1016. return(hr);
  1017. // AP_NNTP_SERVER
  1018. CHECKHR(hr = pAccount->SetPropSz(AP_NNTP_SERVER, szServer));
  1019. // Set Friendly Name
  1020. StrCpyN(sz, szServer, ARRAYSIZE(sz));
  1021. CHECKHR(hr = pAcctMan->GetUniqueAccountName(sz, ARRAYSIZE(sz)));
  1022. CHECKHR(hr = pAccount->SetPropSz(AP_ACCOUNT_NAME, sz));
  1023. CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyNews, c_rgNewsMap, ARRAYSIZE(c_rgNewsMap)));
  1024. CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyServer, c_rgNewsServerMap, ARRAYSIZE(c_rgNewsServerMap)));
  1025. CHECKHR(hr = pAccount->SaveChanges());
  1026. if (fDefault)
  1027. pAccount->SetAsDefault();
  1028. exit:
  1029. pAccount->Release();
  1030. return(hr);
  1031. }
  1032. HRESULT MigrateNewsServers(IImnAccountManager *pAcctMan, HKEY hkeyNews)
  1033. {
  1034. char szDefNntpServer[CCHMAX_SERVER_NAME],
  1035. szServer[CCHMAX_SERVER_NAME];
  1036. HKEY hkeyAthena = NULL, hkeyServer = NULL;
  1037. DWORD cb, dw, i;
  1038. BOOL fMigrated, fSetDefault, fDefault;
  1039. LONG lResult;
  1040. HRESULT hr = S_OK;
  1041. Assert(pAcctMan != NULL);
  1042. Assert(hkeyNews != NULL);
  1043. fSetDefault = FALSE;
  1044. hr = pAcctMan->GetDefaultAccountName(ACCT_NEWS, szServer, ARRAYSIZE(szServer));
  1045. if (FAILED(hr))
  1046. {
  1047. // Query for the default news account
  1048. cb = sizeof(szDefNntpServer);
  1049. if (RegQueryValueEx(hkeyNews, c_szRegDefServer, 0, NULL, (LPBYTE)szDefNntpServer, &cb) == ERROR_SUCCESS &&
  1050. !FIsEmpty(szDefNntpServer))
  1051. fSetDefault = TRUE;
  1052. }
  1053. // Enumerate through the keys
  1054. for (i = 0; ; i++)
  1055. {
  1056. // Enumerate Friendly Names
  1057. cb = sizeof(szServer);
  1058. lResult = RegEnumKeyEx(hkeyNews, i, szServer, &cb, 0, NULL, NULL, NULL);
  1059. // No more items
  1060. if (lResult == ERROR_NO_MORE_ITEMS)
  1061. break;
  1062. // Error, lets move onto the next account
  1063. if (lResult != ERROR_SUCCESS)
  1064. continue;
  1065. // Lets open they server key
  1066. if (RegOpenKeyEx(hkeyNews, szServer, 0, KEY_ALL_ACCESS, &hkeyServer) != ERROR_SUCCESS)
  1067. continue;
  1068. // Has this server been migrated yet ?
  1069. cb = sizeof(fMigrated);
  1070. if (RegQueryValueEx(hkeyServer, c_szMigrated, 0, NULL, (LPBYTE)&fMigrated, &cb) != ERROR_SUCCESS)
  1071. fMigrated = FALSE;
  1072. // If not migrated
  1073. if (!fMigrated)
  1074. {
  1075. fDefault = (fSetDefault && (0 == lstrcmpi(szServer, szDefNntpServer)));
  1076. hr = MigrateNewsAccountSettings(pAcctMan, hkeyNews, hkeyServer, szServer, fDefault);
  1077. if (SUCCEEDED(hr))
  1078. {
  1079. fMigrated = TRUE;
  1080. RegSetValueEx(hkeyServer, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fMigrated, sizeof(fMigrated));
  1081. }
  1082. if (fDefault)
  1083. fSetDefault = FALSE;
  1084. }
  1085. RegCloseKey(hkeyServer);
  1086. }
  1087. return(S_OK);
  1088. }
  1089. HRESULT MigrateBase64EncodedPassword(LPCSTR pszBase64, DWORD cch, DWORD dwPropId, IImnAccount *pAccount)
  1090. {
  1091. HRESULT hr=S_OK;
  1092. IStream *pstmBase64=NULL;
  1093. IStream *pstmDecoded=NULL;
  1094. IMimeBody *pBody=NULL;
  1095. LPSTR pszPassword=NULL;
  1096. // Invalid Arg
  1097. Assert(pszBase64 && pAccount);
  1098. // Create a mime body
  1099. CHECKHR(hr = MimeOleCreateBody(&pBody));
  1100. // InitNew
  1101. CHECKHR(hr = pBody->InitNew());
  1102. // Create a pstmBase64 Stream
  1103. CHECKHR(hr = CreateStreamOnHGlobal(NULL, TRUE, &pstmBase64));
  1104. // Write the pszBase64 into this
  1105. CHECKHR(hr = pstmBase64->Write(pszBase64, cch * sizeof(*pszBase64), NULL));
  1106. // Commit
  1107. CHECKHR(hr = pstmBase64->Commit(STGC_DEFAULT));
  1108. // Rewind it
  1109. CHECKHR(hr = HrRewindStream(pstmBase64));
  1110. // Set it into IMimeBody
  1111. CHECKHR(hr = pBody->SetData(IET_BASE64, NULL, NULL, IID_IStream, (LPVOID)pstmBase64));
  1112. // Get the decoded stream
  1113. CHECKHR(hr = pBody->GetData(IET_DECODED, &pstmDecoded));
  1114. // Convert to string
  1115. CHECKALLOC(pszPassword = PszFromANSIStreamA(pstmDecoded));
  1116. // Store the property
  1117. CHECKHR(hr = pAccount->SetPropSz(dwPropId, pszPassword));
  1118. exit:
  1119. // Cleanup
  1120. if (pszPassword)
  1121. ZeroMemory(pszPassword, sizeof(pszPassword[0]) * lstrlenA(pszPassword)); // Done for security.
  1122. SafeRelease(pstmBase64);
  1123. SafeRelease(pstmDecoded);
  1124. SafeRelease(pBody);
  1125. SafeMemFree(pszPassword);
  1126. return(hr);
  1127. }
  1128. static const char c_szAccessColors[] = "Always Use My Colors";
  1129. static const char c_szAccessFontFace[] = "Always Use My Font Face";
  1130. static const char c_szAccessFontSize[] = "Always Use My Font Size";
  1131. static const char c_szAccessSysCaret[] = "Move System Caret";
  1132. void MigrateAccessibilityKeys()
  1133. {
  1134. HKEY hkeyExplorer, hkeyAthena;
  1135. char szValue[MAX_PATH];
  1136. DWORD cbData, dw;
  1137. // Migrate keys from HKCU\SW\MS\InternetExplorer\Settings
  1138. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szIESettingsPath, 0, KEY_QUERY_VALUE, &hkeyExplorer) == ERROR_SUCCESS)
  1139. {
  1140. StrCpyN(szValue, c_szRegTriSettings, ARRAYSIZE(szValue));
  1141. if (RegCreateKeyEx(MU_GetCurrentUserHKey(), szValue, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAthena, &dw) == ERROR_SUCCESS)
  1142. {
  1143. cbData = sizeof(DWORD);
  1144. if (RegQueryValueEx(hkeyExplorer, c_szAccessColors, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
  1145. RegSetValueEx (hkeyAthena, c_szAccessColors, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
  1146. cbData = sizeof(DWORD);
  1147. if (RegQueryValueEx(hkeyExplorer, c_szAccessFontFace, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
  1148. RegSetValueEx (hkeyAthena, c_szAccessFontFace, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
  1149. cbData = sizeof(DWORD);
  1150. if (RegQueryValueEx(hkeyExplorer, c_szAccessFontSize, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
  1151. RegSetValueEx (hkeyAthena, c_szAccessFontSize, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
  1152. RegCloseKey(hkeyAthena);
  1153. }
  1154. RegCloseKey(hkeyExplorer);
  1155. }
  1156. // Migrate keys from HKCU\SW\MS\InternetExplorer\Main
  1157. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegKeyIEMain, 0, KEY_QUERY_VALUE, &hkeyExplorer) == ERROR_SUCCESS)
  1158. {
  1159. StrCpyN(szValue, c_szRegTriMain, ARRAYSIZE(szValue));
  1160. if (RegCreateKeyEx(MU_GetCurrentUserHKey(), szValue, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAthena, &dw) == ERROR_SUCCESS)
  1161. {
  1162. cbData = MAX_PATH;
  1163. if (RegQueryValueEx(hkeyExplorer, c_szAccessSysCaret, NULL, NULL, (LPBYTE)&szValue, &cbData) == ERROR_SUCCESS)
  1164. RegSetValueEx(hkeyAthena, c_szAccessSysCaret, 0, REG_SZ, (LPBYTE)szValue, cbData);
  1165. RegCloseKey(hkeyAthena);
  1166. }
  1167. RegCloseKey(hkeyExplorer);
  1168. }
  1169. }
  1170. ULONG UlBuildCritText(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
  1171. {
  1172. ULONG ulRet = 0;
  1173. DWORD cbData = 0;
  1174. LONG lErr = ERROR_SUCCESS;
  1175. LPSTR pszReg = NULL;
  1176. LPSTR pszVal = NULL;
  1177. LPSTR pszTokens = NULL;
  1178. LPSTR pszWalk = NULL;
  1179. LPSTR pszString = NULL;
  1180. CRIT_ITEM critItem;
  1181. // Initialize out local vars
  1182. ZeroMemory(&critItem, sizeof(critItem));
  1183. // Get the key string from the registry
  1184. cbData = 0;
  1185. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
  1186. if (ERROR_SUCCESS != lErr)
  1187. {
  1188. ulRet = 0;
  1189. goto exit;
  1190. }
  1191. if (0 == cbData)
  1192. {
  1193. ulRet = 0;
  1194. goto exit;
  1195. }
  1196. if (FAILED(HrAlloc((LPVOID *) &pszReg, cbData)))
  1197. {
  1198. ulRet = 0;
  1199. goto exit;
  1200. }
  1201. SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszReg, &cbData);
  1202. // If it is empty, then we're done
  1203. if (FALSE != FIsEmptyA(pszReg))
  1204. {
  1205. ulRet = 0;
  1206. goto exit;
  1207. }
  1208. // The strings are supposed to be in lowercase
  1209. CharLower(pszReg);
  1210. // Break up the strings into each search token
  1211. pszTokens = SzGetSearchTokens(pszReg);
  1212. if (NULL == pszTokens)
  1213. {
  1214. ulRet = 0;
  1215. goto exit;
  1216. }
  1217. // Count the space needed for the final string
  1218. cbData = 0;
  1219. for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  1220. {
  1221. // Skip empty strings
  1222. if (FALSE == FIsEmptyA(pszWalk))
  1223. {
  1224. cbData += lstrlen(pszWalk) + 1;
  1225. }
  1226. }
  1227. // Nothing to add
  1228. if (0 == cbData)
  1229. {
  1230. ulRet = 0;
  1231. goto exit;
  1232. }
  1233. // Add space to hold the string terminator
  1234. cbData += 2;
  1235. DWORD cchSizeString = cbData;
  1236. // Allocate space to hold the final string
  1237. if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
  1238. {
  1239. ulRet = 0;
  1240. goto exit;
  1241. }
  1242. // Build up the string
  1243. pszString = pszVal;
  1244. for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  1245. {
  1246. // Skip empty strings
  1247. if (FALSE == FIsEmptyA(pszWalk))
  1248. {
  1249. StrCpyNA(pszString, pszWalk, cchSizeString);
  1250. cchSizeString -= (lstrlen(pszString) + 1);
  1251. pszString += lstrlen(pszString) + 1;
  1252. }
  1253. }
  1254. // Terminate the string
  1255. pszString[0] = '\0';
  1256. pszString[1] = '\0';
  1257. // Build up the criteria
  1258. critItem.type = type;
  1259. critItem.logic = CRIT_LOGIC_NULL;
  1260. critItem.dwFlags = CRIT_FLAG_MULTIPLEAND;
  1261. critItem.propvar.vt = VT_BLOB;
  1262. critItem.propvar.blob.cbSize = cbData;
  1263. critItem.propvar.blob.pBlobData = (BYTE *) pszVal;
  1264. // Add it to the criteria object
  1265. if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
  1266. {
  1267. ulRet = 0;
  1268. goto exit;
  1269. }
  1270. exit:
  1271. SafeMemFree(pszTokens);
  1272. SafeMemFree(pszVal);
  1273. SafeMemFree(pszReg);
  1274. return ulRet;
  1275. }
  1276. ULONG UlBuildCritAcct(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
  1277. {
  1278. ULONG ulRet = 0;
  1279. DWORD cbData = 0;
  1280. LONG lErr = ERROR_SUCCESS;
  1281. LPSTR pszVal = NULL;
  1282. CRIT_ITEM critItem;
  1283. IImnAccount * pAccount = NULL;
  1284. CHAR szAccount[CCHMAX_ACCOUNT_NAME];
  1285. // Initialize out local vars
  1286. ZeroMemory(&critItem, sizeof(critItem));
  1287. // Get the key string from the registry
  1288. cbData = 0;
  1289. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
  1290. if (ERROR_SUCCESS != lErr)
  1291. {
  1292. ulRet = 0;
  1293. goto exit;
  1294. }
  1295. if (0 == cbData)
  1296. {
  1297. ulRet = 0;
  1298. goto exit;
  1299. }
  1300. if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
  1301. {
  1302. ulRet = 0;
  1303. goto exit;
  1304. }
  1305. SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
  1306. // If it is empty, then we're done
  1307. if (FALSE != FIsEmptyA(pszVal))
  1308. {
  1309. ulRet = 0;
  1310. goto exit;
  1311. }
  1312. if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_NAME, pszVal, &pAccount)))
  1313. {
  1314. if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_ID, szAccount, sizeof(szAccount))))
  1315. {
  1316. SafeMemFree(pszVal);
  1317. pszVal = PszDupA(szAccount);
  1318. if (NULL == pszVal)
  1319. {
  1320. ulRet = 0;
  1321. goto exit;
  1322. }
  1323. }
  1324. }
  1325. // Build up the criteria
  1326. critItem.type = type;
  1327. critItem.logic = CRIT_LOGIC_NULL;
  1328. critItem.dwFlags = CRIT_FLAG_DEFAULT;
  1329. critItem.propvar.vt = VT_LPSTR;
  1330. critItem.propvar.pszVal = pszVal;
  1331. // Add it to the criteria object
  1332. if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
  1333. {
  1334. ulRet = 0;
  1335. goto exit;
  1336. }
  1337. exit:
  1338. SafeMemFree(pszVal);
  1339. SafeRelease(pAccount);
  1340. return ulRet;
  1341. }
  1342. ULONG UlBuildCritAddr(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
  1343. {
  1344. ULONG ulRet = 0;
  1345. DWORD cbData = 0;
  1346. LONG lErr = ERROR_SUCCESS;
  1347. CRIT_ITEM critItem;
  1348. LPSTR pszReg = NULL;
  1349. LPSTR pszVal = NULL;
  1350. LPSTR pszTokens = NULL;
  1351. LPSTR pszWalk = NULL;
  1352. LPSTR pszString = NULL;
  1353. // Initialize out local vars
  1354. ZeroMemory(&critItem, sizeof(critItem));
  1355. // Get the key string from the registry
  1356. cbData = 0;
  1357. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
  1358. if (ERROR_SUCCESS != lErr)
  1359. {
  1360. ulRet = 0;
  1361. goto exit;
  1362. }
  1363. if (0 == cbData)
  1364. {
  1365. ulRet = 0;
  1366. goto exit;
  1367. }
  1368. if (FAILED(HrAlloc((LPVOID *) &(pszReg), cbData)))
  1369. {
  1370. ulRet = 0;
  1371. goto exit;
  1372. }
  1373. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszReg, &cbData);
  1374. if (ERROR_SUCCESS != lErr)
  1375. {
  1376. ulRet = 0;
  1377. goto exit;
  1378. }
  1379. // If it is empty, then we're done
  1380. if (FALSE != FIsEmptyA(pszReg))
  1381. {
  1382. ulRet = 0;
  1383. goto exit;
  1384. }
  1385. // The strings are supposed to be in lowercase
  1386. CharLower(pszReg);
  1387. // Break up the strings into each search token
  1388. pszTokens = SzGetSearchTokens(pszReg);
  1389. if (NULL == pszTokens)
  1390. {
  1391. ulRet = 0;
  1392. goto exit;
  1393. }
  1394. // Count the space needed for the final string
  1395. cbData = 0;
  1396. for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  1397. {
  1398. // Skip empty addresses
  1399. if (FALSE == FIsEmptyA(pszWalk))
  1400. {
  1401. cbData += lstrlen(pszWalk) + 1;
  1402. }
  1403. }
  1404. // Nothing to add
  1405. if (0 == cbData)
  1406. {
  1407. ulRet = 0;
  1408. goto exit;
  1409. }
  1410. // Add space to hold the string terminator
  1411. cbData += 2;
  1412. DWORD cchSizeString = cbData;
  1413. // Allocate space to hold the final string
  1414. if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
  1415. {
  1416. ulRet = 0;
  1417. goto exit;
  1418. }
  1419. // Build up the string
  1420. pszString = pszVal;
  1421. for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  1422. {
  1423. // Skip empty strings
  1424. if (FALSE == FIsEmptyA(pszWalk))
  1425. {
  1426. StrCpyN(pszString, pszWalk, cchSizeString);
  1427. cchSizeString -= (lstrlen(pszString) + 1);
  1428. pszString += lstrlen(pszString) + 1;
  1429. }
  1430. }
  1431. // Terminate the string
  1432. pszString[0] = '\0';
  1433. pszString[1] = '\0';
  1434. // Build up the criteria
  1435. critItem.type = type;
  1436. critItem.logic = CRIT_LOGIC_NULL;
  1437. critItem.dwFlags = CRIT_FLAG_MULTIPLEAND;
  1438. critItem.propvar.vt = VT_BLOB;
  1439. critItem.propvar.blob.cbSize = cbData;
  1440. critItem.propvar.blob.pBlobData = (BYTE *) pszVal;
  1441. // Add it to the criteria object
  1442. if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
  1443. {
  1444. ulRet = 0;
  1445. goto exit;
  1446. }
  1447. exit:
  1448. SafeMemFree(pszVal);
  1449. SafeMemFree(pszTokens);
  1450. SafeMemFree(pszReg);
  1451. return ulRet;
  1452. }
  1453. ULONG UlBuildCritKB(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
  1454. {
  1455. ULONG ulRet = 0;
  1456. DWORD cbData = 0;
  1457. LONG lErr = ERROR_SUCCESS;
  1458. ULONG ulVal = NULL;
  1459. CRIT_ITEM critItem;
  1460. // Initialize out local vars
  1461. ZeroMemory(&critItem, sizeof(critItem));
  1462. // Get the key long from the registry
  1463. cbData = sizeof(ulVal);
  1464. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) &ulVal, &cbData);
  1465. if (ERROR_SUCCESS != lErr)
  1466. {
  1467. ulRet = 0;
  1468. goto exit;
  1469. }
  1470. // Build up the criteria
  1471. critItem.type = type;
  1472. critItem.logic = CRIT_LOGIC_NULL;
  1473. critItem.dwFlags = CRIT_FLAG_DEFAULT;
  1474. critItem.propvar.vt = VT_UI4;
  1475. critItem.propvar.ulVal = ulVal;
  1476. // Add it to the criteria object
  1477. if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
  1478. {
  1479. ulRet = 0;
  1480. goto exit;
  1481. }
  1482. exit:
  1483. return ulRet;
  1484. }
  1485. ULONG UlBuildActFolder(HKEY hKeyRoot, IMessageStore * pStore, BYTE * pbFldIdMap, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
  1486. {
  1487. ULONG ulRet = 0;
  1488. DWORD cbData = 0;
  1489. LONG lErr = ERROR_SUCCESS;
  1490. ULONG ulVal = NULL;
  1491. ACT_ITEM actItem;
  1492. FOLDERID idFolder = FOLDERID_INVALID;
  1493. STOREUSERDATA UserData = {0};
  1494. RULEFOLDERDATA * prfdData = NULL;
  1495. // Initialize out local vars
  1496. ZeroMemory(&actItem, sizeof(actItem));
  1497. // Get the key long from the registry
  1498. cbData = sizeof(ulVal);
  1499. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) &ulVal, &cbData);
  1500. if (ERROR_SUCCESS != lErr)
  1501. {
  1502. ulRet = 0;
  1503. goto exit;
  1504. }
  1505. // Convert to V5 folder id
  1506. if ((NULL == pbFldIdMap) || (FAILED(RuleUtil_HrMapFldId(0, pbFldIdMap, (FOLDERID)((ULONG_PTR)ulVal), &idFolder))))
  1507. {
  1508. idFolder = (FOLDERID)((ULONG_PTR)ulVal);
  1509. }
  1510. // Create space for the data structure
  1511. if (FAILED(HrAlloc((VOID **) &prfdData, sizeof(*prfdData))))
  1512. {
  1513. ulRet = 0;
  1514. goto exit;
  1515. }
  1516. // Initialize the data struct
  1517. ZeroMemory(prfdData, sizeof(*prfdData));
  1518. // Get the timestamp for the store
  1519. if (FAILED(pStore->GetUserData(&UserData, sizeof(STOREUSERDATA))))
  1520. {
  1521. ulRet = 0;
  1522. goto exit;
  1523. }
  1524. // Set up the rule folder data
  1525. prfdData->ftStamp = UserData.ftCreated;
  1526. prfdData->idFolder = idFolder;
  1527. // Build up the actions
  1528. actItem.type = type;
  1529. actItem.dwFlags = ACT_FLAG_DEFAULT;
  1530. actItem.propvar.vt = VT_BLOB;
  1531. actItem.propvar.blob.cbSize = sizeof(*prfdData);
  1532. actItem.propvar.blob.pBlobData = (BYTE *) prfdData;
  1533. // Add it to the actions object
  1534. if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
  1535. {
  1536. ulRet = 0;
  1537. goto exit;
  1538. }
  1539. exit:
  1540. SafeMemFree(prfdData);
  1541. return ulRet;
  1542. }
  1543. ULONG UlBuildActFwd(HKEY hKeyRoot, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
  1544. {
  1545. ULONG ulRet = 0;
  1546. DWORD cbData = 0,
  1547. cchCount = 0;
  1548. LONG lErr = ERROR_SUCCESS;
  1549. LPSTR pszVal = NULL,
  1550. pszTokens = NULL;
  1551. LPWSTR pwszVal = NULL,
  1552. pwszTokens = NULL;
  1553. ACT_ITEM actItem;
  1554. ULONG ulIndex = 0;
  1555. // Initialize out local vars
  1556. ZeroMemory(&actItem, sizeof(actItem));
  1557. // Get the key string from the registry
  1558. cbData = 0;
  1559. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
  1560. if (ERROR_SUCCESS != lErr)
  1561. {
  1562. goto exit;
  1563. }
  1564. if (0 == cbData)
  1565. {
  1566. goto exit;
  1567. }
  1568. if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
  1569. {
  1570. goto exit;
  1571. }
  1572. SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
  1573. Assert(*pszVal);
  1574. // Convert the string to our format
  1575. for (ulIndex = 0; ulIndex < cbData; ulIndex++)
  1576. {
  1577. if (',' == pszVal[ulIndex])
  1578. {
  1579. pszVal[ulIndex] = ';';
  1580. }
  1581. }
  1582. pwszVal = PszToUnicode(CP_ACP, pszVal);
  1583. if (!pwszVal)
  1584. goto exit;
  1585. if (FAILED(RuleUtil_HrBuildEmailString(pwszVal, 0, &pwszTokens, &cchCount)))
  1586. {
  1587. goto exit;
  1588. }
  1589. Assert(pwszTokens);
  1590. pszTokens = PszToANSI(CP_ACP, pwszTokens);
  1591. if (!pszTokens)
  1592. goto exit;
  1593. // Build up the actions
  1594. actItem.type = type;
  1595. actItem.dwFlags = ACT_FLAG_DEFAULT;
  1596. actItem.propvar.vt = VT_LPSTR;
  1597. actItem.propvar.pszVal = pszTokens;
  1598. // Add it to the actions object
  1599. if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
  1600. {
  1601. ulRet = 0;
  1602. goto exit;
  1603. }
  1604. exit:
  1605. MemFree(pszVal);
  1606. MemFree(pwszVal);
  1607. MemFree(pszTokens);
  1608. MemFree(pwszTokens);
  1609. return ulRet;
  1610. }
  1611. ULONG UlBuildActFile(HKEY hKeyRoot, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
  1612. {
  1613. ULONG ulRet = 0;
  1614. DWORD cbData = 0;
  1615. LONG lErr = ERROR_SUCCESS;
  1616. LPSTR pszVal = NULL;
  1617. ACT_ITEM actItem;
  1618. // Initialize out local vars
  1619. ZeroMemory(&actItem, sizeof(actItem));
  1620. // Get the key string from the registry
  1621. cbData = 0;
  1622. lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
  1623. if (ERROR_SUCCESS != lErr)
  1624. {
  1625. ulRet = 0;
  1626. goto exit;
  1627. }
  1628. if (0 == cbData)
  1629. {
  1630. ulRet = 0;
  1631. goto exit;
  1632. }
  1633. if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
  1634. {
  1635. ulRet = 0;
  1636. goto exit;
  1637. }
  1638. SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
  1639. // If it is empty, then we're done
  1640. if (FALSE != FIsEmptyA(pszVal))
  1641. {
  1642. ulRet = 0;
  1643. goto exit;
  1644. }
  1645. // Build up the actions
  1646. actItem.type = type;
  1647. actItem.dwFlags = ACT_FLAG_DEFAULT;
  1648. actItem.propvar.vt = VT_LPSTR;
  1649. actItem.propvar.pszVal = pszVal;
  1650. // Add it to the actions object
  1651. if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
  1652. {
  1653. ulRet = 0;
  1654. goto exit;
  1655. }
  1656. exit:
  1657. SafeMemFree(pszVal);
  1658. return ulRet;
  1659. }
  1660. // The maximum possible size of the Athena V1 actions string
  1661. const int CCH_V1_ACTION_MAX = 255;
  1662. BOOL FConvertV1ActionsToV4(HKEY hkeyRule, IMessageStore * pStore, IOEActions * pIAct)
  1663. {
  1664. BOOL fRet = FALSE;
  1665. ULONG cbData = 0;
  1666. LONG lErr = ERROR_SUCCESS;
  1667. TCHAR szAction[CCH_V1_ACTION_MAX];
  1668. LPSTR pszFolderName = NULL;
  1669. FOLDERID idFolder = FOLDERID_INVALID;
  1670. ACT_ITEM actItem;
  1671. RULEFOLDERDATA rfdData = {0};
  1672. STOREUSERDATA UserData = {0};
  1673. Assert(NULL != hkeyRule);
  1674. Assert(NULL != pStore);
  1675. Assert(NULL != pIAct);
  1676. // Is there anything to do?
  1677. cbData = sizeof(szAction);
  1678. lErr = RegQueryValueEx(hkeyRule, c_szActionV1, NULL, NULL, (BYTE *) szAction, &cbData);
  1679. if (ERROR_SUCCESS != lErr)
  1680. {
  1681. fRet = FALSE;
  1682. goto exit;
  1683. }
  1684. Assert(0 == lstrcmpi(szAction, (LPTSTR) c_szMoveV1));
  1685. // Convert from old move to a V4 move
  1686. // Get the size of the folder name
  1687. lErr = RegQueryValueEx(hkeyRule, c_szFolderV1, NULL, NULL, NULL, &cbData);
  1688. if (ERROR_SUCCESS != lErr)
  1689. {
  1690. fRet = FALSE;
  1691. goto exit;
  1692. }
  1693. // Allocate space to hold the folder name
  1694. if (FAILED(HrAlloc( (VOID **) &pszFolderName, cbData)))
  1695. {
  1696. fRet = FALSE;
  1697. goto exit;
  1698. }
  1699. // Get the old folder name
  1700. lErr = RegQueryValueEx(hkeyRule, c_szFolderV1, NULL, NULL, (BYTE *) pszFolderName, &cbData);
  1701. if (ERROR_SUCCESS != lErr)
  1702. {
  1703. fRet = FALSE;
  1704. goto exit;
  1705. }
  1706. // Find the folder id from the folder name in the store
  1707. if (FAILED(GetFolderIdFromName(pStore, pszFolderName, FOLDERID_LOCAL_STORE, &idFolder)))
  1708. {
  1709. idFolder = FOLDERID_INVALID;
  1710. }
  1711. // Get the timestamp for the store
  1712. pStore->GetUserData(&UserData, sizeof(STOREUSERDATA));
  1713. // Set the timestamp and folder id
  1714. rfdData.ftStamp = UserData.ftCreated;
  1715. rfdData.idFolder = idFolder;
  1716. // Build up the actions
  1717. ZeroMemory(&actItem, sizeof(actItem));
  1718. actItem.type = ACT_TYPE_MOVE;
  1719. actItem.dwFlags = ACT_FLAG_DEFAULT;
  1720. actItem.propvar.vt = VT_BLOB;
  1721. actItem.propvar.blob.cbSize = sizeof(rfdData);
  1722. actItem.propvar.blob.pBlobData = (BYTE *) &rfdData;
  1723. // Add it to the actions object
  1724. if (FAILED(pIAct->AppendActions(0, &actItem, 1, NULL)))
  1725. {
  1726. fRet = FALSE;
  1727. goto exit;
  1728. }
  1729. // Set the return value
  1730. fRet = TRUE;
  1731. exit:
  1732. SafeMemFree(pszFolderName);
  1733. return fRet;
  1734. }
  1735. void MigrateMailRulesSettings(void)
  1736. {
  1737. IImnAccountManager *pAcctMan = NULL;
  1738. HKEY hkeyOldRoot = NULL;
  1739. LONG lErr = 0;
  1740. ULONG cSubKeys = 0;
  1741. HKEY hkeyNewRoot = NULL;
  1742. DWORD dwDisp = 0;
  1743. DWORD cbData = 0;
  1744. BYTE * pbFldIdMap = NULL;
  1745. HRESULT hr = S_OK;
  1746. ULONG ulIndex = 0;
  1747. TCHAR szNameOld[16];
  1748. HKEY hKeyOld = NULL;
  1749. IOERule * pIRule = NULL;
  1750. PROPVARIANT propvar = {0};
  1751. BOOL boolVal = FALSE;
  1752. IOECriteria * pICrit = NULL;
  1753. CRIT_ITEM critItem;
  1754. ULONG ccritItem = 0;
  1755. CRIT_ITEM * pCrit = NULL;
  1756. ULONG ccritItemAlloc = 0;
  1757. IOEActions * pIAct = NULL;
  1758. DWORD dwActs = 0;
  1759. ACT_ITEM actItem;
  1760. ULONG cactItem = 0;
  1761. ACT_ITEM * pAct = NULL;
  1762. ULONG cactItemAlloc = 0;
  1763. ULONG ulName = 0;
  1764. TCHAR szRes[CCHMAX_STRINGRES + 5];
  1765. TCHAR szName[CCHMAX_STRINGRES + 5];
  1766. IOERule * pIRuleFind = NULL;
  1767. RULEINFO infoRule = {0};
  1768. CHAR szStoreDir[MAX_PATH + MAX_PATH];
  1769. IMessageStore * pStore = NULL;
  1770. // Initialize the local vars
  1771. ZeroMemory(&critItem, sizeof(critItem));
  1772. ZeroMemory(&actItem, sizeof(actItem));
  1773. // Get the old key
  1774. lErr = AthUserOpenKey(c_szRegPathInboxRules, KEY_READ, &hkeyOldRoot);
  1775. if (lErr != ERROR_SUCCESS)
  1776. {
  1777. goto exit;
  1778. }
  1779. // Is there anything to do?
  1780. lErr = RegQueryInfoKey(hkeyOldRoot, NULL, NULL, NULL,
  1781. &cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  1782. if ((lErr != ERROR_SUCCESS) || (0 == cSubKeys))
  1783. {
  1784. goto exit;
  1785. }
  1786. // To make sure we don't get any sample rule created
  1787. // set up the registry to look like we've already been set-up
  1788. // Get the new rules key
  1789. lErr = AthUserCreateKey(c_szRulesMail, KEY_ALL_ACCESS, &hkeyNewRoot, &dwDisp);
  1790. if (lErr != ERROR_SUCCESS)
  1791. {
  1792. goto exit;
  1793. }
  1794. // Save out the rules version
  1795. cbData = RULESMGR_VERSION;
  1796. lErr = RegSetValueEx(hkeyNewRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &cbData, sizeof(cbData));
  1797. if (ERROR_SUCCESS != lErr)
  1798. {
  1799. goto exit;
  1800. }
  1801. // Figure out the size of the folderid map
  1802. lErr = AthUserGetValue(NULL, c_szFolderIdChange, NULL, NULL, &cbData);
  1803. if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr))
  1804. {
  1805. goto exit;
  1806. }
  1807. // If the map exists, then grab it
  1808. if (ERROR_SUCCESS == lErr)
  1809. {
  1810. // Allocate the space to hold the folderid map
  1811. if (FAILED(HrAlloc((void **) &pbFldIdMap, cbData)))
  1812. {
  1813. goto exit;
  1814. }
  1815. // Get the folderid map from the registry
  1816. lErr = AthUserGetValue(NULL, c_szFolderIdChange, NULL, pbFldIdMap, &cbData);
  1817. if (ERROR_SUCCESS != lErr)
  1818. {
  1819. goto exit;
  1820. }
  1821. }
  1822. // CoIncrementInit Global Options Manager
  1823. if (FALSE == InitGlobalOptions(NULL, NULL))
  1824. {
  1825. goto exit;
  1826. }
  1827. // Create the Rules Manager
  1828. Assert(NULL == g_pRulesMan);
  1829. hr = HrCreateRulesManager(NULL, (IUnknown **)&g_pRulesMan);
  1830. if (FAILED(hr))
  1831. {
  1832. goto exit;
  1833. }
  1834. // Initialize the rules manager
  1835. hr = g_pRulesMan->Initialize(0);
  1836. if (FAILED(hr))
  1837. {
  1838. goto exit;
  1839. }
  1840. // Create the Account Manager
  1841. Assert(g_pAcctMan == NULL);
  1842. hr = HrCreateAccountManager(&pAcctMan);
  1843. if (FAILED(hr))
  1844. {
  1845. goto exit;
  1846. }
  1847. hr = pAcctMan->QueryInterface(IID_IImnAccountManager2, (LPVOID *)&g_pAcctMan);
  1848. pAcctMan->Release();
  1849. if (FAILED(hr))
  1850. {
  1851. goto exit;
  1852. }
  1853. // Initialize the account manager
  1854. hr = g_pAcctMan->Init(NULL);
  1855. if (FAILED(hr))
  1856. {
  1857. goto exit;
  1858. }
  1859. // Get the store directory
  1860. hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
  1861. if (FAILED(hr))
  1862. {
  1863. goto exit;
  1864. }
  1865. // Create the store object
  1866. pStore = new CMessageStore(FALSE);
  1867. if (NULL == pStore)
  1868. {
  1869. goto exit;
  1870. }
  1871. // Initialize the store
  1872. hr = pStore->Initialize(szStoreDir);
  1873. if (FAILED(hr))
  1874. {
  1875. goto exit;
  1876. }
  1877. ulIndex = 0;
  1878. wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
  1879. if (0 == LoadString(g_hLocRes, idsRuleDefaultName, szRes, ARRAYSIZE(szRes)))
  1880. {
  1881. goto exit;
  1882. }
  1883. // For each entry in the old rules key
  1884. for (;RegOpenKeyEx(hkeyOldRoot, szNameOld, 0, KEY_READ, &hKeyOld) == ERROR_SUCCESS; RegCloseKey(hKeyOld))
  1885. {
  1886. // Create the new Rule
  1887. SafeRelease(pIRule);
  1888. hr = HrCreateRule(&pIRule);
  1889. if (FAILED(hr))
  1890. {
  1891. continue;
  1892. }
  1893. // Set the name on the rule
  1894. ulName = 1;
  1895. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
  1896. Assert(NULL != g_pRulesMan);
  1897. while (S_OK == g_pRulesMan->FindRule(szName, RULE_TYPE_MAIL, &pIRuleFind))
  1898. {
  1899. SafeRelease(pIRuleFind);
  1900. ulName++;
  1901. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
  1902. }
  1903. ZeroMemory(&propvar, sizeof(propvar));
  1904. propvar.vt = VT_LPSTR;
  1905. propvar.pszVal = szName;
  1906. pIRule->SetProp(RULE_PROP_NAME, 0, &propvar);
  1907. // Set the enabled state on the rule
  1908. cbData = sizeof(boolVal);
  1909. SHQueryValueEx(hKeyOld, c_szDisabled, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  1910. ZeroMemory(&propvar, sizeof(propvar));
  1911. propvar.vt = VT_BOOL;
  1912. propvar.boolVal = !!boolVal;
  1913. pIRule->SetProp(RULE_PROP_DISABLED, 0, &propvar);
  1914. // Copy over the criteria
  1915. SafeRelease(pICrit);
  1916. hr = HrCreateCriteria(&pICrit);
  1917. if (FAILED(hr))
  1918. {
  1919. continue;
  1920. }
  1921. ccritItem = 0;
  1922. // Check for All Messages
  1923. cbData = sizeof(boolVal);
  1924. SHQueryValueEx(hKeyOld, c_szFilterAllMessages, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  1925. if (FALSE != boolVal)
  1926. {
  1927. critItem.type = CRIT_TYPE_ALL;
  1928. critItem.propvar.vt = VT_EMPTY;
  1929. critItem.logic = CRIT_LOGIC_NULL;
  1930. critItem.dwFlags = CRIT_FLAG_DEFAULT;
  1931. if (SUCCEEDED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, NULL)))
  1932. {
  1933. ccritItem++;
  1934. }
  1935. }
  1936. else
  1937. {
  1938. // Check for account
  1939. cbData = sizeof(boolVal);
  1940. SHQueryValueEx(hKeyOld, c_szFilterByAccount, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  1941. if (FALSE != boolVal)
  1942. {
  1943. ccritItem += UlBuildCritAcct(hKeyOld, c_szAccount, CRIT_TYPE_ACCOUNT, pICrit);
  1944. }
  1945. // Check for size
  1946. cbData = sizeof(boolVal);
  1947. SHQueryValueEx(hKeyOld, c_szFilterOnSize, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  1948. if (FALSE != boolVal)
  1949. {
  1950. ccritItem += UlBuildCritKB(hKeyOld, c_szFilterSize, CRIT_TYPE_SIZE, pICrit);
  1951. }
  1952. // Check for subject
  1953. ccritItem += UlBuildCritText(hKeyOld, c_szSubject, CRIT_TYPE_SUBJECT, pICrit);
  1954. // Check for subject
  1955. ccritItem += UlBuildCritAddr(hKeyOld, c_szFrom, CRIT_TYPE_FROM, pICrit);
  1956. // Check for subject
  1957. ccritItem += UlBuildCritAddr(hKeyOld, c_szTo, CRIT_TYPE_TO, pICrit);
  1958. // Check for subject
  1959. ccritItem += UlBuildCritAddr(hKeyOld, c_szCC, CRIT_TYPE_CC, pICrit);
  1960. }
  1961. if (0 != ccritItem)
  1962. {
  1963. // Get the criteria from the criteria object and set it on the rule
  1964. RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
  1965. SafeMemFree(pCrit);
  1966. if (SUCCEEDED(pICrit->GetCriteria(0, &pCrit, &ccritItemAlloc)))
  1967. {
  1968. ZeroMemory(&propvar, sizeof(propvar));
  1969. propvar.vt = VT_BLOB;
  1970. propvar.blob.cbSize = ccritItem * sizeof(CRIT_ITEM);
  1971. propvar.blob.pBlobData = (BYTE *) pCrit;
  1972. if (FAILED(pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar)))
  1973. {
  1974. continue;
  1975. }
  1976. }
  1977. }
  1978. // Copy over the actions
  1979. SafeRelease(pIAct);
  1980. hr = HrCreateActions(&pIAct);
  1981. if (FAILED(hr))
  1982. {
  1983. continue;
  1984. }
  1985. cactItem = 0;
  1986. // Convert any old V1 actions to V4
  1987. if (FALSE != FConvertV1ActionsToV4(hKeyOld, pStore, pIAct))
  1988. {
  1989. cactItem = 1;
  1990. }
  1991. else
  1992. {
  1993. // Get list of actions
  1994. cbData = sizeof(dwActs);
  1995. SHQueryValueEx(hKeyOld, c_szActions, NULL, NULL, (LPVOID) (&dwActs), &cbData);
  1996. // Check for don't download
  1997. if (0 != (dwActs & ACT_DONTDOWNLOAD))
  1998. {
  1999. actItem.type = ACT_TYPE_DONTDOWNLOAD;
  2000. actItem.dwFlags = ACT_FLAG_DEFAULT;
  2001. actItem.propvar.vt = VT_EMPTY;
  2002. if (SUCCEEDED(pIAct->AppendActions(0, &actItem, 1, NULL)))
  2003. {
  2004. cactItem++;
  2005. }
  2006. }
  2007. // Check for delete from server
  2008. else if (0 != (dwActs & ACT_DELETEOFFSERVER))
  2009. {
  2010. actItem.type = ACT_TYPE_DELETESERVER;
  2011. actItem.dwFlags = ACT_FLAG_DEFAULT;
  2012. actItem.propvar.vt = VT_EMPTY;
  2013. if (SUCCEEDED(pIAct->AppendActions(0, &actItem, 1, NULL)))
  2014. {
  2015. cactItem++;
  2016. }
  2017. }
  2018. else
  2019. {
  2020. // Check for move to
  2021. if (0 != (dwActs & ACT_MOVETO))
  2022. {
  2023. cactItem += UlBuildActFolder(hKeyOld, pStore, pbFldIdMap, c_szMoveToHfolder, ACT_TYPE_MOVE, pIAct);
  2024. }
  2025. // Check for copy to
  2026. if (0 != (dwActs & ACT_COPYTO))
  2027. {
  2028. cactItem += UlBuildActFolder(hKeyOld, pStore, pbFldIdMap, c_szCopyToHfolder, ACT_TYPE_COPY, pIAct);
  2029. }
  2030. // Check for forward to
  2031. if (0 != (dwActs & ACT_FORWARDTO))
  2032. {
  2033. cactItem += UlBuildActFwd(hKeyOld, c_szForwardTo, ACT_TYPE_FWD, pIAct);
  2034. }
  2035. // Check for reply with
  2036. if (0 != (dwActs & ACT_REPLYWITH))
  2037. {
  2038. cactItem += UlBuildActFile(hKeyOld, c_szReplyWithFile, ACT_TYPE_REPLY, pIAct);
  2039. }
  2040. }
  2041. }
  2042. if (0 != cactItem)
  2043. {
  2044. // Get the actions from the action object and set it on the rule
  2045. RuleUtil_HrFreeActionsItem(pAct, cactItemAlloc);
  2046. SafeMemFree(pAct);
  2047. if (SUCCEEDED(pIAct->GetActions(0, &pAct, &cactItemAlloc)))
  2048. {
  2049. ZeroMemory(&propvar, sizeof(propvar));
  2050. propvar.vt = VT_BLOB;
  2051. propvar.blob.cbSize = cactItem * sizeof(ACT_ITEM);
  2052. propvar.blob.pBlobData = (BYTE *) pAct;
  2053. if (FAILED(pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar)))
  2054. {
  2055. continue;
  2056. }
  2057. }
  2058. }
  2059. // Initialize the rule info
  2060. infoRule.ridRule = RULEID_INVALID;
  2061. infoRule.pIRule = pIRule;
  2062. // Add it to the rules
  2063. g_pRulesMan->SetRules(SETF_APPEND, RULE_TYPE_MAIL, &infoRule, 1);
  2064. ulIndex++;
  2065. wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
  2066. }
  2067. exit:
  2068. RuleUtil_HrFreeActionsItem(pAct, cactItemAlloc);
  2069. SafeMemFree(pAct);
  2070. RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
  2071. SafeMemFree(pCrit);
  2072. SafeRelease(pIAct);
  2073. SafeRelease(pICrit);
  2074. SafeRelease(pIRule);
  2075. if (NULL != hKeyOld)
  2076. {
  2077. RegCloseKey(hKeyOld);
  2078. }
  2079. SafeRelease(pStore);
  2080. SafeRelease(g_pAcctMan);
  2081. SafeRelease(g_pRulesMan);
  2082. DeInitGlobalOptions();
  2083. SafeMemFree(pbFldIdMap);
  2084. if (NULL != hkeyNewRoot)
  2085. {
  2086. RegCloseKey(hkeyNewRoot);
  2087. }
  2088. if (NULL != hkeyOldRoot)
  2089. {
  2090. RegCloseKey(hkeyOldRoot);
  2091. }
  2092. }
  2093. void CopyBeta2RulesToRTM(VOID)
  2094. {
  2095. LONG lErr = ERROR_SUCCESS;
  2096. HKEY hKeyMail = NULL;
  2097. HKEY hkeyRTM = NULL;
  2098. DWORD dwDisp = 0;
  2099. // Get the Beta 2 hkey for rules
  2100. lErr = AthUserOpenKey(c_szMail, KEY_READ, &hKeyMail);
  2101. if (lErr != ERROR_SUCCESS)
  2102. {
  2103. goto exit;
  2104. }
  2105. // Create the RTM hkey for rules
  2106. lErr = AthUserCreateKey(c_szRulesMail, KEY_ALL_ACCESS, &hkeyRTM, &dwDisp);
  2107. if (lErr != ERROR_SUCCESS)
  2108. {
  2109. goto exit;
  2110. }
  2111. // Copy the Beta 2 rules to the new location
  2112. SHCopyKey(hKeyMail, c_szRules, hkeyRTM, NULL);
  2113. exit:
  2114. if (NULL != hkeyRTM)
  2115. {
  2116. RegCloseKey(hkeyRTM);
  2117. }
  2118. if (NULL != hKeyMail)
  2119. {
  2120. RegCloseKey(hKeyMail);
  2121. }
  2122. return;
  2123. }
  2124. void UpdateBeta2String(HKEY hkeyItem, LPCSTR pszSep, DWORD dwItemType)
  2125. {
  2126. HRESULT hr = S_OK;
  2127. LPSTR pszData = NULL;
  2128. ULONG cbData = 0;
  2129. LONG lErr = ERROR_SUCCESS;
  2130. DWORD dwData = 0;
  2131. Assert(NULL != hkeyItem);
  2132. // Get the new data
  2133. hr = RuleUtil_HrGetOldFormatString(hkeyItem, c_szCriteriaValue, g_szComma, &pszData, &cbData);
  2134. if (FAILED(hr))
  2135. {
  2136. goto exit;
  2137. }
  2138. // Write out the new data
  2139. lErr = RegSetValueEx(hkeyItem, c_szCriteriaValue, 0, REG_BINARY, (BYTE *) pszData, cbData);
  2140. if (lErr != ERROR_SUCCESS)
  2141. {
  2142. goto exit;
  2143. }
  2144. // Write out the proper value type
  2145. dwData = VT_BLOB;
  2146. cbData = sizeof(dwData);
  2147. lErr = RegSetValueEx(hkeyItem, c_szCriteriaValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2148. if (lErr != ERROR_SUCCESS)
  2149. {
  2150. goto exit;
  2151. }
  2152. // Write out the proper flags
  2153. dwData = CRIT_FLAG_MULTIPLEAND;
  2154. cbData = sizeof(dwData);
  2155. lErr = RegSetValueEx(hkeyItem, c_szCriteriaFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2156. if (lErr != ERROR_SUCCESS)
  2157. {
  2158. goto exit;
  2159. }
  2160. // Write the new type
  2161. cbData = sizeof(dwItemType);
  2162. lErr = RegSetValueEx(hkeyItem, c_szCriteriaType, 0, REG_DWORD, (BYTE *) &dwItemType, cbData);
  2163. if (lErr != ERROR_SUCCESS)
  2164. {
  2165. goto exit;
  2166. }
  2167. exit:
  2168. SafeMemFree(pszData);
  2169. return;
  2170. }
  2171. static IMessageStore * g_pStoreRulesMig = NULL;
  2172. VOID WriteOldOrderFormat(HKEY hkeyItem, LPSTR pszOrder)
  2173. {
  2174. ULONG cbData = 0;
  2175. LPSTR pszWalk = NULL;
  2176. ULONG cchWalk = 0;
  2177. // Convert the order string back to our old format
  2178. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += cchWalk + 1)
  2179. {
  2180. cchWalk = lstrlen(pszWalk);
  2181. *(pszWalk + cchWalk) = ' ';
  2182. cbData += cchWalk + 1;
  2183. }
  2184. // Make sure we terminate the order string
  2185. pszOrder[cbData - 1] = '\0';
  2186. // Save it
  2187. RegSetValueEx(hkeyItem, c_szRulesOrder, 0, REG_SZ, (BYTE *) pszOrder, cbData);
  2188. return;
  2189. }
  2190. static CRIT_TYPE g_rgtypeCritMerge[] =
  2191. {
  2192. CRIT_TYPE_FROM,
  2193. CRIT_TYPE_TO,
  2194. CRIT_TYPE_CC,
  2195. CRIT_TYPE_TOORCC
  2196. };
  2197. static const int g_ctypeCritMerge = sizeof(g_rgtypeCritMerge) / sizeof(g_rgtypeCritMerge[0]);
  2198. BOOL FMergeRuleData(HKEY hkeyItem, LPSTR pszSubKey, LPSTR * ppszData, ULONG * pcbData)
  2199. {
  2200. BOOL fRet = FALSE;
  2201. LONG lErr = ERROR_SUCCESS;
  2202. DWORD dwType = 0;
  2203. ULONG cbString = 0;
  2204. LPSTR pszData = NULL;
  2205. ULONG cbData = 0;
  2206. // Get the size of the original string
  2207. lErr = SHGetValue(hkeyItem, pszSubKey, c_szCriteriaValue, &dwType, NULL, &cbString);
  2208. if (ERROR_SUCCESS != lErr)
  2209. {
  2210. fRet = FALSE;
  2211. goto exit;
  2212. }
  2213. // Figure out the space for the final string
  2214. cbData = *pcbData + cbString - 2;
  2215. if (cbData < *pcbData)
  2216. cbData = *pcbData;
  2217. // Allocate space for the final data
  2218. if (FAILED(HrAlloc((VOID **) &pszData, cbData * sizeof(*pszData))))
  2219. {
  2220. fRet = FALSE;
  2221. goto exit;
  2222. }
  2223. // Copy over the original string
  2224. CopyMemory(pszData, *ppszData, *pcbData * sizeof(*pszData));
  2225. // Copy over the new data
  2226. lErr = SHGetValue(hkeyItem, pszSubKey, c_szCriteriaValue, &dwType, (BYTE *) (pszData + *pcbData - 2), &cbString);
  2227. if (ERROR_SUCCESS != lErr)
  2228. {
  2229. fRet = FALSE;
  2230. goto exit;
  2231. }
  2232. // Free the old data
  2233. SafeMemFree(*ppszData);
  2234. // Set the return values
  2235. *ppszData = pszData;
  2236. pszData = NULL;
  2237. *pcbData = cbData;
  2238. fRet = TRUE;
  2239. exit:
  2240. SafeMemFree(pszData);
  2241. return fRet;
  2242. }
  2243. void AddStopAction(HKEY hkeyItem, LPSTR * ppszOrder, ULONG * pcchOrder)
  2244. {
  2245. ULONG ulIndex = 0;
  2246. CHAR rgchTag[CCH_INDEX_MAX];
  2247. LPSTR pszWalk = NULL;
  2248. HKEY hkeyAction = NULL;
  2249. DWORD dwDisp = 0;
  2250. ULONG cbData = 0;
  2251. LONG lErr = 0;
  2252. ACT_TYPE typeAct = ACT_TYPE_NULL;
  2253. DWORD dwData = 0;
  2254. ULONG cchOrder = 0;
  2255. LPSTR pszOrder = NULL;
  2256. // Check to see if we need to add the stop processing action
  2257. if ('\0' == (*ppszOrder + lstrlen(*ppszOrder) + 1)[0])
  2258. {
  2259. // Get the action type
  2260. cbData = sizeof(typeAct);
  2261. lErr = SHGetValue(hkeyItem, *ppszOrder, c_szActionsType, NULL, (BYTE *) &typeAct, &cbData);
  2262. if (ERROR_SUCCESS == lErr)
  2263. {
  2264. if ((ACT_TYPE_DONTDOWNLOAD == typeAct) || (ACT_TYPE_DELETESERVER == typeAct))
  2265. {
  2266. goto exit;
  2267. }
  2268. }
  2269. }
  2270. // Spin through the order item looking for an open entry
  2271. for (ulIndex = 0; ulIndex < DWORD_INDEX_MAX; ulIndex++)
  2272. {
  2273. // Create the tag
  2274. wnsprintf(rgchTag, ARRAYSIZE(rgchTag), "%03X", ulIndex);
  2275. // Search for the tag in the list
  2276. for (pszWalk = *ppszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  2277. {
  2278. if (0 == lstrcmp(pszWalk, rgchTag))
  2279. {
  2280. // Found it
  2281. break;
  2282. }
  2283. }
  2284. // If we didn't find it
  2285. if ('\0' == pszWalk[0])
  2286. {
  2287. // Use this one
  2288. break;
  2289. }
  2290. }
  2291. // Did we find anything?
  2292. if (ulIndex >= DWORD_INDEX_MAX)
  2293. {
  2294. goto exit;
  2295. }
  2296. // Create the new entry
  2297. lErr = RegCreateKeyEx(hkeyItem, rgchTag, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAction, &dwDisp);
  2298. if (ERROR_SUCCESS != lErr)
  2299. {
  2300. goto exit;
  2301. }
  2302. // Set the action type
  2303. cbData = sizeof(typeAct);
  2304. typeAct = ACT_TYPE_STOP;
  2305. lErr = RegSetValueEx(hkeyAction, c_szActionsType, 0, REG_DWORD, (BYTE *) &typeAct, cbData);
  2306. if (lErr != ERROR_SUCCESS)
  2307. {
  2308. goto exit;
  2309. }
  2310. // Set the action flags
  2311. dwData = ACT_FLAG_DEFAULT;
  2312. cbData = sizeof(dwData);
  2313. lErr = RegSetValueEx(hkeyAction, c_szActionsFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2314. if (lErr != ERROR_SUCCESS)
  2315. {
  2316. goto exit;
  2317. }
  2318. // Allocate space to hold the new order string
  2319. cchOrder= *pcchOrder + CCH_INDEX_MAX;
  2320. if (FAILED(HrAlloc((VOID **) &pszOrder, cchOrder * sizeof (*pszOrder))))
  2321. {
  2322. goto exit;
  2323. }
  2324. // Copy over the old values
  2325. CopyMemory(pszOrder, *ppszOrder, (*pcchOrder) * sizeof(*pszOrder));
  2326. // Add it to the new order string
  2327. StrCpyN(pszOrder + *pcchOrder - 2, rgchTag, (cchOrder - *pcchOrder + 2));
  2328. // Terminate the new string
  2329. pszOrder[cchOrder - 2] = '\0';
  2330. pszOrder[cchOrder - 1] = '\0';
  2331. // Release the old string
  2332. SafeMemFree(*ppszOrder);
  2333. // Save the new string
  2334. *ppszOrder = pszOrder;
  2335. pszOrder = NULL;
  2336. *pcchOrder = cchOrder;
  2337. exit:
  2338. SafeMemFree(pszOrder);
  2339. if (NULL != hkeyAction)
  2340. {
  2341. RegCloseKey(hkeyAction);
  2342. }
  2343. return;
  2344. }
  2345. void MergeRTMCriteria(HKEY hkeyItem, CRIT_TYPE typeCrit, LPSTR pszOrder, ULONG cchOrder)
  2346. {
  2347. LONG lErr = ERROR_SUCCESS;
  2348. LPSTR pszWalk = NULL;
  2349. CRIT_TYPE typeCritNew = CRIT_TYPE_NULL;
  2350. ULONG cbData = 0;
  2351. LPSTR pszFirst = NULL;
  2352. DWORD dwType = 0;
  2353. ULONG cbString = 0;
  2354. LPSTR pszString = NULL;
  2355. LPSTR pszSrc = NULL;
  2356. // Look through each item
  2357. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  2358. {
  2359. cbData = sizeof(typeCritNew);
  2360. lErr = SHGetValue(hkeyItem, pszWalk, c_szCriteriaType, &dwType, (BYTE *) &typeCritNew, &cbData);
  2361. if (ERROR_SUCCESS != lErr)
  2362. {
  2363. continue;
  2364. }
  2365. if (typeCritNew == typeCrit)
  2366. {
  2367. break;
  2368. }
  2369. }
  2370. // If we couldn't find it we're done
  2371. if ('\0' == pszWalk[0])
  2372. {
  2373. goto exit;
  2374. }
  2375. // Get the size of the original string
  2376. pszFirst = pszWalk;
  2377. lErr = SHGetValue(hkeyItem, pszFirst, c_szCriteriaValue, &dwType, NULL, &cbString);
  2378. if (ERROR_SUCCESS != lErr)
  2379. {
  2380. goto exit;
  2381. }
  2382. if (FAILED(HrAlloc((VOID **) &pszString, cbString * sizeof(*pszString))))
  2383. {
  2384. goto exit;
  2385. }
  2386. // Get the original string
  2387. lErr = SHGetValue(hkeyItem, pszFirst, c_szCriteriaValue, &dwType, (BYTE *) pszString, &cbString);
  2388. if (ERROR_SUCCESS != lErr)
  2389. {
  2390. goto exit;
  2391. }
  2392. // Search for more entries of this type
  2393. for (pszWalk = pszFirst + lstrlen(pszFirst) + 1; '\0' != pszWalk[0]; )
  2394. {
  2395. cbData = sizeof(typeCritNew);
  2396. lErr = SHGetValue(hkeyItem, pszWalk, c_szCriteriaType, &dwType, (BYTE *) &typeCritNew, &cbData);
  2397. if (ERROR_SUCCESS != lErr)
  2398. {
  2399. continue;
  2400. }
  2401. if (typeCritNew == typeCrit)
  2402. {
  2403. if (FALSE == FMergeRuleData(hkeyItem, pszWalk, &pszString, &cbString))
  2404. {
  2405. break;
  2406. }
  2407. // Remove the old key
  2408. SHDeleteKey(hkeyItem, pszWalk);
  2409. // Remove the item from the order string
  2410. pszSrc = pszWalk + lstrlen(pszWalk) + 1;
  2411. MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
  2412. cchOrder -= (ULONG) (pszSrc - pszWalk);
  2413. }
  2414. else
  2415. {
  2416. pszWalk += lstrlen(pszWalk) + 1;
  2417. }
  2418. }
  2419. // Save out the final string
  2420. lErr = SHSetValue(hkeyItem, pszFirst, c_szCriteriaValue, REG_BINARY, (BYTE *) pszString, cbString);
  2421. if (ERROR_SUCCESS != lErr)
  2422. {
  2423. goto exit;
  2424. }
  2425. exit:
  2426. SafeMemFree(pszString);
  2427. return;
  2428. }
  2429. void UpdateBeta2Folder(HKEY hkeyItem)
  2430. {
  2431. LONG lErr = ERROR_SUCCESS;
  2432. DWORD dwType = 0;
  2433. FOLDERID idFolder = FOLDERID_INVALID;
  2434. ULONG cbData = 0;
  2435. STOREUSERDATA UserData = {0};
  2436. RULEFOLDERDATA rfdData = {0};
  2437. DWORD dwData = 0;
  2438. Assert(NULL != hkeyItem);
  2439. // Get the old folder id
  2440. cbData = sizeof(idFolder);
  2441. lErr = RegQueryValueEx(hkeyItem, c_szCriteriaValue, 0, &dwType, (BYTE *) &idFolder, &cbData);
  2442. if (ERROR_SUCCESS != lErr)
  2443. {
  2444. goto exit;
  2445. }
  2446. // Get the timestamp for the store
  2447. Assert(NULL != g_pStoreRulesMig);
  2448. if (FAILED(g_pStoreRulesMig->GetUserData(&UserData, sizeof(STOREUSERDATA))))
  2449. {
  2450. goto exit;
  2451. }
  2452. // Set up the new data
  2453. rfdData.idFolder = idFolder;
  2454. rfdData.ftStamp = UserData.ftCreated;
  2455. // Write out the new data
  2456. cbData = sizeof(rfdData);
  2457. lErr = RegSetValueEx(hkeyItem, c_szCriteriaValue, 0, REG_BINARY, (BYTE *) &rfdData, cbData);
  2458. if (lErr != ERROR_SUCCESS)
  2459. {
  2460. goto exit;
  2461. }
  2462. // Write out the proper value type
  2463. dwData = VT_BLOB;
  2464. cbData = sizeof(dwData);
  2465. lErr = RegSetValueEx(hkeyItem, c_szCriteriaValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2466. if (lErr != ERROR_SUCCESS)
  2467. {
  2468. goto exit;
  2469. }
  2470. exit:
  2471. return;
  2472. }
  2473. void UpdateBeta2Show(HKEY hkeyItem)
  2474. {
  2475. LONG lErr = ERROR_SUCCESS;
  2476. DWORD dwType = 0;
  2477. DWORD dwData = 0;
  2478. ULONG cbData = 0;
  2479. Assert(NULL != hkeyItem);
  2480. // Get the old flags
  2481. cbData = sizeof(dwData);
  2482. lErr = RegQueryValueEx(hkeyItem, c_szActionsFlags, 0, &dwType, (BYTE *) &dwData, &cbData);
  2483. if (ERROR_SUCCESS != lErr)
  2484. {
  2485. goto exit;
  2486. }
  2487. if (0 != (dwData & ACT_FLAG_INVERT))
  2488. {
  2489. dwData = ACT_DATA_HIDE;
  2490. }
  2491. else
  2492. {
  2493. dwData = ACT_DATA_SHOW;
  2494. }
  2495. // Write out the new data
  2496. cbData = sizeof(dwData);
  2497. lErr = RegSetValueEx(hkeyItem, c_szActionsValue, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2498. if (lErr != ERROR_SUCCESS)
  2499. {
  2500. goto exit;
  2501. }
  2502. // Write out the proper value type
  2503. dwData = VT_UI4;
  2504. cbData = sizeof(dwData);
  2505. lErr = RegSetValueEx(hkeyItem, c_szActionsValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2506. if (lErr != ERROR_SUCCESS)
  2507. {
  2508. goto exit;
  2509. }
  2510. // Write out the proper flags
  2511. dwData = ACT_FLAG_DEFAULT;
  2512. cbData = sizeof(dwData);
  2513. lErr = RegSetValueEx(hkeyItem, c_szActionsFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
  2514. if (lErr != ERROR_SUCCESS)
  2515. {
  2516. goto exit;
  2517. }
  2518. exit:
  2519. return;
  2520. }
  2521. void UpdateBeta2Criteria(HKEY hkeyItem, LPCSTR pszSubKey)
  2522. {
  2523. LONG lErr = ERROR_SUCCESS;
  2524. HKEY hkeyAtom = NULL;
  2525. CRIT_TYPE typeCrit = CRIT_TYPE_NULL;
  2526. DWORD dwType = 0;
  2527. ULONG cbData = 0;
  2528. lErr = RegOpenKeyEx(hkeyItem, pszSubKey, 0, KEY_ALL_ACCESS, &hkeyAtom);
  2529. if (lErr != ERROR_SUCCESS)
  2530. {
  2531. goto exit;
  2532. }
  2533. // Get the type of criteria
  2534. cbData = sizeof(typeCrit);
  2535. lErr = RegQueryValueEx(hkeyAtom, c_szCriteriaType, NULL, &dwType, (BYTE *) &typeCrit, &cbData);
  2536. if (lErr != ERROR_SUCCESS)
  2537. {
  2538. goto exit;
  2539. }
  2540. // For each criteria type
  2541. switch (typeCrit)
  2542. {
  2543. case CRIT_TYPE_FROM:
  2544. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_FROM);
  2545. break;
  2546. case CRIT_TYPE_FROMADDR:
  2547. UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_FROM);
  2548. break;
  2549. case CRIT_TYPE_TO:
  2550. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_TO);
  2551. break;
  2552. case CRIT_TYPE_TOADDR:
  2553. UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_TO);
  2554. break;
  2555. case CRIT_TYPE_CC:
  2556. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_CC);
  2557. break;
  2558. case CRIT_TYPE_CCADDR:
  2559. UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_CC);
  2560. break;
  2561. case CRIT_TYPE_TOORCC:
  2562. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_TOORCC);
  2563. break;
  2564. case CRIT_TYPE_TOORCCADDR:
  2565. UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_TOORCC);
  2566. break;
  2567. case CRIT_TYPE_SUBJECT:
  2568. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_SUBJECT);
  2569. break;
  2570. case CRIT_TYPE_BODY:
  2571. UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_BODY);
  2572. break;
  2573. case CRIT_TYPE_NEWSGROUP:
  2574. UpdateBeta2Folder(hkeyAtom);
  2575. break;
  2576. }
  2577. exit:
  2578. if (NULL != hkeyAtom)
  2579. {
  2580. RegCloseKey(hkeyAtom);
  2581. }
  2582. return;
  2583. }
  2584. void UpdateBeta2Actions(HKEY hkeyItem, LPCSTR pszSubKey)
  2585. {
  2586. LONG lErr = ERROR_SUCCESS;
  2587. HKEY hkeyAtom = NULL;
  2588. ACT_TYPE typeAct = ACT_TYPE_NULL;
  2589. DWORD dwType = 0;
  2590. ULONG cbData = 0;
  2591. lErr = RegOpenKeyEx(hkeyItem, pszSubKey, 0, KEY_ALL_ACCESS, &hkeyAtom);
  2592. if (lErr != ERROR_SUCCESS)
  2593. {
  2594. goto exit;
  2595. }
  2596. // Get the type of actions
  2597. cbData = sizeof(typeAct);
  2598. lErr = RegQueryValueEx(hkeyAtom, c_szActionsType, NULL, &dwType, (BYTE *) &typeAct, &cbData);
  2599. if (lErr != ERROR_SUCCESS)
  2600. {
  2601. goto exit;
  2602. }
  2603. // For each actions type
  2604. switch (typeAct)
  2605. {
  2606. case ACT_TYPE_MOVE:
  2607. case ACT_TYPE_COPY:
  2608. UpdateBeta2Folder(hkeyAtom);
  2609. break;
  2610. case ACT_TYPE_SHOW:
  2611. UpdateBeta2Show(hkeyAtom);
  2612. }
  2613. exit:
  2614. if (NULL != hkeyAtom)
  2615. {
  2616. RegCloseKey(hkeyAtom);
  2617. }
  2618. return;
  2619. }
  2620. void MigrateBeta2RuleItems(HKEY hkeyRule, LPCSTR pszSubkey, BOOL fActions, RULE_TYPE typeRule)
  2621. {
  2622. LONG lErr = ERROR_SUCCESS;
  2623. HKEY hkeySubkey = NULL;
  2624. HRESULT hr = S_OK;
  2625. LPSTR pszOrder = NULL;
  2626. LPSTR pszWalk = NULL;
  2627. ULONG ulIndex = 0;
  2628. ULONG cbData = 0;
  2629. ULONG cchWalk = 0;
  2630. lErr = RegOpenKeyEx(hkeyRule, pszSubkey, 0, KEY_ALL_ACCESS, &hkeySubkey);
  2631. if (lErr != ERROR_SUCCESS)
  2632. {
  2633. goto exit;
  2634. }
  2635. // Get the order string
  2636. hr = RuleUtil_HrGetOldFormatString(hkeySubkey, c_szRulesOrder, g_szSpace, &pszOrder, &cbData);
  2637. if (FAILED(hr))
  2638. {
  2639. goto exit;
  2640. }
  2641. // For each item in the order string
  2642. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  2643. {
  2644. // Update actions
  2645. if (FALSE != fActions)
  2646. {
  2647. UpdateBeta2Actions(hkeySubkey, pszWalk);
  2648. }
  2649. else
  2650. {
  2651. UpdateBeta2Criteria(hkeySubkey, pszWalk);
  2652. }
  2653. }
  2654. if (FALSE == fActions)
  2655. {
  2656. // For each item type
  2657. for (ulIndex = 0; ulIndex < g_ctypeCritMerge; ulIndex++)
  2658. {
  2659. MergeRTMCriteria(hkeySubkey, g_rgtypeCritMerge[ulIndex], pszOrder, cbData);
  2660. }
  2661. }
  2662. else
  2663. {
  2664. if (typeRule != RULE_TYPE_FILTER)
  2665. {
  2666. AddStopAction(hkeySubkey, &pszOrder, &cbData);
  2667. }
  2668. }
  2669. // Write out the order string
  2670. WriteOldOrderFormat(hkeySubkey, pszOrder);
  2671. exit:
  2672. SafeMemFree(pszOrder);
  2673. if (NULL != hkeySubkey)
  2674. {
  2675. RegCloseKey(hkeySubkey);
  2676. }
  2677. return;
  2678. }
  2679. void UpdateBeta2Rule(HKEY hkeyRoot, LPCSTR pszRule, RULE_TYPE typeRule)
  2680. {
  2681. HKEY hkeyRule = NULL;
  2682. LONG lErr = ERROR_SUCCESS;
  2683. // Open up the rule
  2684. lErr = RegOpenKeyEx(hkeyRoot, pszRule, 0, KEY_ALL_ACCESS, &hkeyRule);
  2685. if (ERROR_SUCCESS != lErr)
  2686. {
  2687. goto exit;
  2688. }
  2689. // Migrate the criteria
  2690. MigrateBeta2RuleItems(hkeyRule, c_szRuleCriteria, FALSE, typeRule);
  2691. // Migrate the actions
  2692. MigrateBeta2RuleItems(hkeyRule, c_szRuleActions, TRUE, typeRule);
  2693. exit:
  2694. if (NULL != hkeyRule)
  2695. {
  2696. RegCloseKey(hkeyRule);
  2697. }
  2698. return;
  2699. }
  2700. typedef struct _RULEREGKEY
  2701. {
  2702. LPCSTR pszRegKey;
  2703. RULE_TYPE typeRule;
  2704. } RULEREGKEY, * PRULEREGKEY;
  2705. static RULEREGKEY g_rgpszRuleRegKeys[] =
  2706. {
  2707. {c_szRulesMail, RULE_TYPE_MAIL},
  2708. {c_szRulesNews, RULE_TYPE_NEWS},
  2709. {c_szRulesFilter, RULE_TYPE_FILTER}
  2710. };
  2711. static const int g_cpszRuleRegKeys = sizeof(g_rgpszRuleRegKeys) / sizeof(g_rgpszRuleRegKeys[0]);
  2712. void UpdateBeta2RuleFormats(VOID)
  2713. {
  2714. ULONG ulIndex = 0;
  2715. LONG lErr = ERROR_SUCCESS;
  2716. HKEY hkeyRoot = NULL;
  2717. HRESULT hr = S_OK;
  2718. LPSTR pszOrder = NULL;
  2719. LPSTR pszWalk = NULL;
  2720. CHAR szStoreDir[MAX_PATH + MAX_PATH];
  2721. // Set up the global objects
  2722. // Get the store directory
  2723. hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
  2724. if (FAILED(hr))
  2725. {
  2726. goto exit;
  2727. }
  2728. // Create the store object
  2729. g_pStoreRulesMig = new CMessageStore(FALSE);
  2730. if (NULL == g_pStoreRulesMig)
  2731. {
  2732. goto exit;
  2733. }
  2734. // Initialize the store
  2735. hr = g_pStoreRulesMig->Initialize(szStoreDir);
  2736. if (FAILED(hr))
  2737. {
  2738. goto exit;
  2739. }
  2740. // For each type of rule
  2741. for (ulIndex = 0; ulIndex < g_cpszRuleRegKeys; ulIndex++)
  2742. {
  2743. // Open up the rule type reg key
  2744. if (NULL != hkeyRoot)
  2745. {
  2746. RegCloseKey(hkeyRoot);
  2747. }
  2748. lErr = AthUserOpenKey(g_rgpszRuleRegKeys[ulIndex].pszRegKey, KEY_ALL_ACCESS, &hkeyRoot);
  2749. if (lErr != ERROR_SUCCESS)
  2750. {
  2751. continue;
  2752. }
  2753. // Get the order string
  2754. SafeMemFree(pszOrder);
  2755. hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, NULL);
  2756. if (FAILED(hr))
  2757. {
  2758. continue;
  2759. }
  2760. // For each item in the order string
  2761. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  2762. {
  2763. // Update rule
  2764. UpdateBeta2Rule(hkeyRoot, pszWalk, g_rgpszRuleRegKeys[ulIndex].typeRule);
  2765. }
  2766. }
  2767. exit:
  2768. SafeMemFree(pszOrder);
  2769. if (NULL != hkeyRoot)
  2770. {
  2771. RegCloseKey(hkeyRoot);
  2772. }
  2773. SafeRelease(g_pStoreRulesMig);
  2774. return;
  2775. }
  2776. void MigrateBeta2Rules(VOID)
  2777. {
  2778. // Copy over all the items from the mail\rules area
  2779. // Get the new rules key
  2780. CopyBeta2RulesToRTM();
  2781. // Go through each rule type updating the formats
  2782. UpdateBeta2RuleFormats();
  2783. // Merge the items if neccessary
  2784. return;
  2785. }
  2786. void MigrateGroupFilterSettings(void)
  2787. {
  2788. IImnAccountManager *pAcctMan = NULL;
  2789. HKEY hkeyOldRoot = NULL;
  2790. LONG lErr = 0;
  2791. ULONG cSubKeys = 0;
  2792. HKEY hkeyNewRoot = NULL;
  2793. DWORD dwDisp = 0;
  2794. DWORD cbData = 0;
  2795. HRESULT hr = S_OK;
  2796. ULONG ulIndex = 0;
  2797. TCHAR szNameOld[16];
  2798. HKEY hKeyOld = NULL;
  2799. IOERule * pIRule = NULL;
  2800. PROPVARIANT propvar = {0};
  2801. BOOL boolVal = FALSE;
  2802. IOECriteria * pICrit = NULL;
  2803. CRIT_ITEM critItem;
  2804. ULONG ccritItem = 0;
  2805. CRIT_ITEM * pCrit = NULL;
  2806. ULONG ccritItemAlloc = 0;
  2807. DWORD dwActs = 0;
  2808. ACT_ITEM actItem;
  2809. ULONG cactItemAlloc = 0;
  2810. ULONG ulName = 0;
  2811. TCHAR szRes[CCHMAX_STRINGRES + 5];
  2812. TCHAR szName[CCHMAX_STRINGRES + 5];
  2813. IOERule * pIRuleFind = NULL;
  2814. RULEINFO infoRule = {0};
  2815. CHAR szStoreDir[MAX_PATH + MAX_PATH];
  2816. IMessageStore * pStore = NULL;
  2817. // Initialize the local vars
  2818. ZeroMemory(&critItem, sizeof(critItem));
  2819. ZeroMemory(&actItem, sizeof(actItem));
  2820. // Get the old key
  2821. lErr = AthUserOpenKey(c_szRegPathGroupFilters, KEY_READ, &hkeyOldRoot);
  2822. if (lErr != ERROR_SUCCESS)
  2823. {
  2824. goto exit;
  2825. }
  2826. // Is there anything to do?
  2827. lErr = RegQueryInfoKey(hkeyOldRoot, NULL, NULL, NULL,
  2828. &cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  2829. if ((lErr != ERROR_SUCCESS) || (0 == cSubKeys))
  2830. {
  2831. goto exit;
  2832. }
  2833. // To make sure we don't get any sample rule created
  2834. // set up the registry to look like we've already been set-up
  2835. // CoIncrementInit Global Options Manager
  2836. if (FALSE == InitGlobalOptions(NULL, NULL))
  2837. {
  2838. goto exit;
  2839. }
  2840. // Create the Rules Manager
  2841. Assert(NULL == g_pRulesMan);
  2842. hr = HrCreateRulesManager(NULL, (IUnknown **)&g_pRulesMan);
  2843. if (FAILED(hr))
  2844. {
  2845. goto exit;
  2846. }
  2847. // Initialize the rules manager
  2848. hr = g_pRulesMan->Initialize(0);
  2849. if (FAILED(hr))
  2850. {
  2851. goto exit;
  2852. }
  2853. // Create the Account Manager
  2854. Assert(g_pAcctMan == NULL);
  2855. hr = HrCreateAccountManager(&pAcctMan);
  2856. if (FAILED(hr))
  2857. {
  2858. goto exit;
  2859. }
  2860. hr = pAcctMan->QueryInterface(IID_IImnAccountManager2, (LPVOID *)&g_pAcctMan);
  2861. pAcctMan->Release();
  2862. if (FAILED(hr))
  2863. {
  2864. goto exit;
  2865. }
  2866. // Initialize the account manager
  2867. hr = g_pAcctMan->Init(NULL);
  2868. if (FAILED(hr))
  2869. {
  2870. goto exit;
  2871. }
  2872. // Get the store directory
  2873. hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
  2874. if (FAILED(hr))
  2875. {
  2876. goto exit;
  2877. }
  2878. // Create the store object
  2879. pStore = new CMessageStore(FALSE);
  2880. if (NULL == pStore)
  2881. {
  2882. goto exit;
  2883. }
  2884. // Initialize the store
  2885. hr = pStore->Initialize(szStoreDir);
  2886. if (FAILED(hr))
  2887. {
  2888. goto exit;
  2889. }
  2890. ulIndex = 0;
  2891. wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
  2892. // Initialize the action
  2893. actItem.type = ACT_TYPE_SHOW;
  2894. actItem.dwFlags = ACT_FLAG_DEFAULT;
  2895. actItem.propvar.vt = VT_UI4;
  2896. actItem.propvar.ulVal = ACT_DATA_HIDE;
  2897. if (0 == LoadString(g_hLocRes, idsNewsFilterDefaultName, szRes, ARRAYSIZE(szRes)))
  2898. {
  2899. goto exit;
  2900. }
  2901. // For each entry in the old rules key
  2902. for (;RegOpenKeyEx(hkeyOldRoot, szNameOld, 0, KEY_READ, &hKeyOld) == ERROR_SUCCESS; RegCloseKey(hKeyOld))
  2903. {
  2904. // Create the new Rule
  2905. SafeRelease(pIRule);
  2906. hr = HrCreateRule(&pIRule);
  2907. if (FAILED(hr))
  2908. {
  2909. continue;
  2910. }
  2911. // Set the name on the rule
  2912. ulName = 1;
  2913. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
  2914. Assert(NULL != g_pRulesMan);
  2915. while (S_OK == g_pRulesMan->FindRule(szName, RULE_TYPE_FILTER, &pIRuleFind))
  2916. {
  2917. SafeRelease(pIRuleFind);
  2918. ulName++;
  2919. wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
  2920. }
  2921. ZeroMemory(&propvar, sizeof(propvar));
  2922. propvar.vt = VT_LPSTR;
  2923. propvar.pszVal = szName;
  2924. pIRule->SetProp(RULE_PROP_NAME, 0, &propvar);
  2925. // Copy over the criteria
  2926. SafeRelease(pICrit);
  2927. hr = HrCreateCriteria(&pICrit);
  2928. if (FAILED(hr))
  2929. {
  2930. continue;
  2931. }
  2932. ccritItem = 0;
  2933. // Check for age
  2934. cbData = sizeof(boolVal);
  2935. SHQueryValueEx(hKeyOld, c_szFilterOnDate, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  2936. if (FALSE != boolVal)
  2937. {
  2938. ccritItem += UlBuildCritKB(hKeyOld, c_szFilterDays, CRIT_TYPE_AGE, pICrit);
  2939. }
  2940. // Check for lines
  2941. cbData = sizeof(boolVal);
  2942. SHQueryValueEx(hKeyOld, c_szFilterOnSize, NULL, NULL, (LPVOID) (&boolVal), &cbData);
  2943. if (FALSE != boolVal)
  2944. {
  2945. ccritItem += UlBuildCritKB(hKeyOld, c_szFilterSize, CRIT_TYPE_LINES, pICrit);
  2946. }
  2947. // Check for subject
  2948. ccritItem += UlBuildCritText(hKeyOld, c_szSubject, CRIT_TYPE_SUBJECT, pICrit);
  2949. // Check for From
  2950. ccritItem += UlBuildCritAddr(hKeyOld, c_szFrom, CRIT_TYPE_FROM, pICrit);
  2951. if (0 != ccritItem)
  2952. {
  2953. // Get the criteria from the criteria object and set it on the rule
  2954. RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
  2955. SafeMemFree(pCrit);
  2956. if (SUCCEEDED(pICrit->GetCriteria(0, &pCrit, &ccritItemAlloc)))
  2957. {
  2958. ZeroMemory(&propvar, sizeof(propvar));
  2959. propvar.vt = VT_BLOB;
  2960. propvar.blob.cbSize = ccritItem * sizeof(CRIT_ITEM);
  2961. propvar.blob.pBlobData = (BYTE *) pCrit;
  2962. if (FAILED(pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar)))
  2963. {
  2964. continue;
  2965. }
  2966. }
  2967. }
  2968. ZeroMemory(&propvar, sizeof(propvar));
  2969. propvar.vt = VT_BLOB;
  2970. propvar.blob.cbSize = sizeof(actItem);
  2971. propvar.blob.pBlobData = (BYTE *) &actItem;
  2972. if (FAILED(pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar)))
  2973. {
  2974. continue;
  2975. }
  2976. // Initialize the rule info
  2977. infoRule.ridRule = RULEID_INVALID;
  2978. infoRule.pIRule = pIRule;
  2979. // Add it to the rules
  2980. g_pRulesMan->SetRules(SETF_APPEND, RULE_TYPE_FILTER, &infoRule, 1);
  2981. ulIndex++;
  2982. wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
  2983. }
  2984. exit:
  2985. RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
  2986. SafeMemFree(pCrit);
  2987. SafeRelease(pICrit);
  2988. SafeRelease(pIRule);
  2989. if (NULL != hKeyOld)
  2990. {
  2991. RegCloseKey(hKeyOld);
  2992. }
  2993. SafeRelease(pStore);
  2994. SafeRelease(g_pAcctMan);
  2995. SafeRelease(g_pRulesMan);
  2996. DeInitGlobalOptions();
  2997. if (NULL != hkeyNewRoot)
  2998. {
  2999. RegCloseKey(hkeyNewRoot);
  3000. }
  3001. if (NULL != hkeyOldRoot)
  3002. {
  3003. RegCloseKey(hkeyOldRoot);
  3004. }
  3005. }
  3006. void RemoveDeletedFromFilters(VOID)
  3007. {
  3008. CHAR szDeleted[CCH_INDEX_MAX];
  3009. LONG lErr = ERROR_SUCCESS;
  3010. HKEY hkeyRoot = NULL;
  3011. HRESULT hr = S_OK;
  3012. LPSTR pszOrder = NULL;
  3013. ULONG cchOrder = 0;
  3014. LPSTR pszWalk = NULL;
  3015. LPSTR pszSrc = NULL;
  3016. // Create the DELETED key
  3017. wnsprintf(szDeleted, ARRAYSIZE(szDeleted), "%03X", RULEID_VIEW_DELETED);
  3018. // Open the filter key
  3019. lErr = AthUserOpenKey(c_szRulesFilter, KEY_ALL_ACCESS, &hkeyRoot);
  3020. if (lErr != ERROR_SUCCESS)
  3021. {
  3022. goto exit;
  3023. }
  3024. // Get the order string
  3025. hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, &cchOrder);
  3026. if (FAILED(hr))
  3027. {
  3028. goto exit;
  3029. }
  3030. // Search for RULEID_VIEW_DELETED
  3031. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  3032. {
  3033. if (0 == lstrcmpi(szDeleted, pszWalk))
  3034. {
  3035. break;
  3036. }
  3037. }
  3038. // If we found it, then remove it
  3039. if ('\0' != pszWalk[0])
  3040. {
  3041. // Delete the view
  3042. SHDeleteKey(hkeyRoot, szDeleted);
  3043. // Remove it from the order string
  3044. pszSrc = pszWalk + lstrlen(pszWalk) + 1;
  3045. MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
  3046. // Save the order string
  3047. WriteOldOrderFormat(hkeyRoot, pszOrder);
  3048. }
  3049. exit:
  3050. SafeMemFree(pszOrder);
  3051. if (NULL != hkeyRoot)
  3052. {
  3053. RegCloseKey(hkeyRoot);
  3054. }
  3055. return;
  3056. }
  3057. void Stage5RulesMigration(VOID)
  3058. {
  3059. // Remove CRIT_TYPE_DELETED from views
  3060. RemoveDeletedFromFilters();
  3061. // Migrate the newsgroup filters
  3062. MigrateGroupFilterSettings();
  3063. return;
  3064. }
  3065. void RemoveRepliesFromFilters(VOID)
  3066. {
  3067. CHAR szDeleted[CCH_INDEX_MAX];
  3068. LONG lErr = ERROR_SUCCESS;
  3069. HKEY hkeyRoot = NULL;
  3070. HRESULT hr = S_OK;
  3071. LPSTR pszOrder = NULL;
  3072. ULONG cchOrder = 0;
  3073. LPSTR pszWalk = NULL;
  3074. LPSTR pszSrc = NULL;
  3075. // Create the DELETED key
  3076. wnsprintf(szDeleted, ARRAYSIZE(szDeleted), "%03X", RULEID_VIEW_REPLIES);
  3077. // Open the filter key
  3078. lErr = AthUserOpenKey(c_szRulesFilter, KEY_ALL_ACCESS, &hkeyRoot);
  3079. if (lErr != ERROR_SUCCESS)
  3080. {
  3081. goto exit;
  3082. }
  3083. // Get the order string
  3084. hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, &cchOrder);
  3085. if (FAILED(hr))
  3086. {
  3087. goto exit;
  3088. }
  3089. // Search for RULEID_VIEW_REPLIES
  3090. for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
  3091. {
  3092. if (0 == lstrcmpi(szDeleted, pszWalk))
  3093. {
  3094. break;
  3095. }
  3096. }
  3097. // If we found it, then remove it
  3098. if ('\0' != pszWalk[0])
  3099. {
  3100. // Delete the view
  3101. SHDeleteKey(hkeyRoot, szDeleted);
  3102. // Remove it from the order string
  3103. pszSrc = pszWalk + lstrlen(pszWalk) + 1;
  3104. MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
  3105. // Save the order string
  3106. WriteOldOrderFormat(hkeyRoot, pszOrder);
  3107. }
  3108. exit:
  3109. SafeMemFree(pszOrder);
  3110. if (NULL != hkeyRoot)
  3111. {
  3112. RegCloseKey(hkeyRoot);
  3113. }
  3114. return;
  3115. }
  3116. void Stage6RulesMigration(VOID)
  3117. {
  3118. // Remove RULEID_VIEW_REPLIES from views
  3119. RemoveRepliesFromFilters();
  3120. return;
  3121. }