Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1663 lines
58 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. oe.c
  5. Abstract:
  6. Implements Outlook Express utilities
  7. Author:
  8. Jay Thaler (jthaler) 05-Apr-2001
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #include <wab.h>
  18. #include <sddl.h>
  19. #include <rpcdce.h>
  20. #define COBJMACROS
  21. #include <msoeimp.h>
  22. #define DBG_V1 "v1"
  23. //
  24. // Strings
  25. //
  26. // None
  27. //
  28. // Constants
  29. //
  30. #define OETEMPDIR TEXT("%CSIDL_LOCAL_APPDATA%\\Identities\\USMTTMP")
  31. #define DEFAULTWAB TEXT("default.wab")
  32. //
  33. // Macros
  34. //
  35. #define IF_NULLEND(x) if (NULL==x) { goto end; }
  36. //
  37. // Types
  38. //
  39. typedef IMailImport * (STDMETHODCALLTYPE OECREATE)(
  40. LPCSTR pszSrcDir
  41. );
  42. typedef OECREATE FAR *LPOECREATE;
  43. typedef HRESULT (STDMETHODCALLTYPE IMPORTSTORE)(
  44. IMailImport *pMailImport,
  45. GUID *pDestUUID,
  46. LPCSTR pszDestDir
  47. );
  48. typedef IMPORTSTORE FAR *LPIMPORTSTORE;
  49. typedef HRESULT (STDMETHODCALLTYPE IMPORTNEWS)(
  50. LPCSTR pszSrcDir,
  51. GUID *pDestUUID,
  52. LPCSTR pszDestDir
  53. );
  54. typedef IMPORTNEWS FAR *LPIMPORTNEWS;
  55. //
  56. // Globals
  57. //
  58. PTSTR g_DestAssociatedId = NULL;
  59. HMODULE g_msoedll = NULL;
  60. HMODULE g_oemiglib = NULL;
  61. BOOL g_CoInit = FALSE;
  62. //
  63. // Macro expansion list
  64. //
  65. // None
  66. //
  67. // Private function prototypes
  68. //
  69. // None
  70. //
  71. // Macro expansion definition
  72. //
  73. // None
  74. //
  75. // Code
  76. //
  77. BOOL
  78. pUuidFromBracketedString (
  79. PCTSTR InStr,
  80. UUID *Uuid
  81. )
  82. {
  83. PTSTR strippedStr = NULL;
  84. TCHAR *p;
  85. BOOL retval = FALSE;
  86. if (!InStr || !Uuid)
  87. {
  88. return FALSE;
  89. }
  90. if (*InStr == TEXT('{')) {
  91. strippedStr = DuplicateText(_tcsinc(InStr));
  92. p = _tcsrchr (strippedStr, TEXT('}'));
  93. if (p) {
  94. *p = 0;
  95. }
  96. } else {
  97. strippedStr = DuplicateText(InStr);
  98. }
  99. if (strippedStr) {
  100. if (RPC_S_OK == UuidFromString(strippedStr, Uuid)) {
  101. retval = TRUE;
  102. }
  103. FreeText(strippedStr);
  104. }
  105. return retval;
  106. }
  107. MIG_OBJECTSTRINGHANDLE
  108. pBuildStoreRootKeyForId (
  109. PCTSTR Identity
  110. )
  111. {
  112. MIG_OBJECTSTRINGHANDLE objectName = NULL;
  113. PTSTR tmpStr;
  114. tmpStr = AllocText (CharCount(TEXT("HKCU\\Identities\\")) +
  115. CharCount(Identity) +
  116. CharCount(TEXT("\\Software\\Microsoft\\Outlook Express\\5.0")) + 1);
  117. if (tmpStr) {
  118. StringCopy(tmpStr, TEXT("HKCU\\Identities\\"));
  119. StringCat(tmpStr, Identity);
  120. StringCat(tmpStr, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0"));
  121. objectName = IsmCreateObjectHandle (tmpStr, TEXT("Store Root"));
  122. FreeText (tmpStr);
  123. tmpStr = NULL;
  124. }
  125. return objectName;
  126. }
  127. PTSTR
  128. pGetDestStoreRootForId (
  129. PCTSTR Identity
  130. )
  131. {
  132. MIG_OBJECTSTRINGHANDLE objectName;
  133. MIG_CONTENT objectContent;
  134. PTSTR retval = NULL;
  135. PTSTR tmpStr;
  136. PCTSTR destStore;
  137. objectName = pBuildStoreRootKeyForId (Identity);
  138. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  139. objectName,
  140. &objectContent)) {
  141. if (IsValidRegSz(&objectContent)) {
  142. destStore = IsmExpandEnvironmentString (PLATFORM_DESTINATION,
  143. S_SYSENVVAR_GROUP,
  144. (PCTSTR)objectContent.MemoryContent.ContentBytes,
  145. NULL);
  146. if (destStore) {
  147. retval = DuplicateText(destStore);
  148. IsmReleaseMemory(destStore);
  149. }
  150. }
  151. IsmReleaseObject (&objectContent);
  152. }
  153. IsmDestroyObjectHandle(objectName);
  154. return retval;
  155. }
  156. VOID
  157. WABMerge (
  158. VOID
  159. )
  160. {
  161. MIG_OBJECTSTRINGHANDLE filteredName = NULL;
  162. MIG_OBJECTSTRINGHANDLE objectName = NULL;
  163. MIG_OBJECTSTRINGHANDLE destObjectName;
  164. MIG_OBJECTSTRINGHANDLE lpWABObjectName = NULL;
  165. MIG_CONTENT objectContent;
  166. PCTSTR srcFile = NULL;
  167. PCTSTR srcNode = NULL;
  168. PCTSTR srcLeaf = NULL;
  169. PTSTR destFile = NULL;
  170. PCTSTR wabKey = NULL;
  171. PCTSTR wabPath = NULL;
  172. PCTSTR destPath;
  173. HANDLE lib;
  174. LPWABOPEN lpfnWABOpen = NULL;
  175. LPWABOBJECT lpWABObject;
  176. LPADRBOOK lpAdrBookWAB;
  177. WAB_PARAM wabParams;
  178. WABIMPORTPARAM wabImportParam;
  179. HRESULT hr;
  180. PCTSTR srcIdentity;
  181. PCTSTR destIdentity;
  182. PCTSTR destNode;
  183. BOOL fNewOE = FALSE;
  184. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  185. (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT) ||
  186. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT))) {
  187. //
  188. // Get the source WAB filename
  189. //
  190. lpWABObjectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\WAB\\WAB4\\Wab File Name"), TEXT(""));
  191. if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE,
  192. lpWABObjectName,
  193. &objectContent)) {
  194. if (IsValidRegSz (&objectContent)) {
  195. objectName = TurnFileStringIntoHandle ((PCTSTR)objectContent.MemoryContent.ContentBytes,
  196. PFF_NO_PATTERNS_ALLOWED);
  197. filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
  198. objectName,
  199. NULL,
  200. NULL,
  201. NULL);
  202. if (filteredName) {
  203. IsmCreateObjectStringsFromHandle (filteredName, &srcNode, &srcLeaf);
  204. IsmDestroyObjectHandle (filteredName);
  205. } else {
  206. IsmCreateObjectStringsFromHandle (objectName, &srcNode, &srcLeaf);
  207. }
  208. srcFile = JoinPaths (srcNode, srcLeaf);
  209. IsmDestroyObjectString (srcNode);
  210. IsmDestroyObjectString (srcLeaf);
  211. IsmDestroyObjectHandle (objectName);
  212. }
  213. IsmReleaseObject (&objectContent);
  214. }
  215. //
  216. // Get the dest WAB filename
  217. //
  218. if (srcFile) {
  219. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  220. lpWABObjectName,
  221. &objectContent)) {
  222. if (IsValidRegSz (&objectContent)) {
  223. destFile = DuplicateText ((PCTSTR)objectContent.MemoryContent.ContentBytes);
  224. }
  225. IsmReleaseObject (&objectContent);
  226. }
  227. }
  228. if (destFile) {
  229. // If we are upgrading from an old WAB version, and the destination does not have
  230. // a new WAB already, then we need to supply a new filename to WABOpen
  231. if (StringIMatch (srcFile, destFile)) {
  232. fNewOE = TRUE;
  233. destPath = IsmExpandEnvironmentString (
  234. PLATFORM_DESTINATION,
  235. S_SYSENVVAR_GROUP,
  236. TEXT("%UserProfile%\\Application Data\\Microsoft\\Address Book\\"),
  237. NULL);
  238. FreeText (destFile);
  239. destFile = AllocText (TcharCount(destPath) + TcharCount(DEFAULTWAB) + 1);
  240. StringCopy (destFile, destPath);
  241. StringCat (destFile, DEFAULTWAB);
  242. if StringIMatch (srcFile, destFile) {
  243. // Crud! Now what?
  244. }
  245. if (!DoesFileExist (destPath)) {
  246. BfCreateDirectory (destPath);
  247. }
  248. IsmReleaseMemory (destPath);
  249. // Set HKCU\Software\Microsoft\WAB\WAB4\Wab File Name [] = destFile
  250. ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
  251. objectContent.ObjectTypeId = g_RegType;
  252. objectContent.Details.DetailsSize = sizeof(DWORD);
  253. objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
  254. *((PDWORD)objectContent.Details.DetailsData) = REG_SZ;
  255. objectContent.MemoryContent.ContentSize = SizeOfString (destFile);
  256. objectContent.MemoryContent.ContentBytes = IsmGetMemory (objectContent.MemoryContent.ContentSize);
  257. CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes,
  258. destFile,
  259. objectContent.MemoryContent.ContentSize);
  260. objectName = IsmCreateObjectHandle(TEXT("HKCU\\Software\\Microsoft\\WAB\\WAB4\\Wab File Name"),
  261. TEXT(""));
  262. if (objectName) {
  263. IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
  264. IsmDestroyObjectHandle (objectName);
  265. }
  266. IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
  267. IsmReleaseMemory (objectContent.Details.DetailsData);
  268. }
  269. }
  270. if (destFile) {
  271. // Get the WAB32.DLL location
  272. wabKey = JoinPaths (TEXT("HKLM"), WAB_DLL_PATH_KEY);
  273. objectName = IsmCreateObjectHandle (wabKey, TEXT(""));
  274. FreePathString (wabKey);
  275. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  276. objectName,
  277. &objectContent)) {
  278. if (IsValidRegSz (&objectContent)) {
  279. wabPath = DuplicateText ((PCTSTR)objectContent.MemoryContent.ContentBytes);
  280. }
  281. IsmReleaseObject (&objectContent);
  282. }
  283. IsmDestroyObjectHandle (objectName);
  284. }
  285. if (wabPath) {
  286. // Loadlibrary the DLL
  287. lib = LoadLibrary (wabPath);
  288. if (lib) {
  289. // Open the destination WAB
  290. lpfnWABOpen = (LPWABOPEN) GetProcAddress (lib, "WABOpen");
  291. if (lpfnWABOpen) {
  292. ZeroMemory (&wabParams, sizeof (WAB_PARAM));
  293. wabParams.cbSize = sizeof (WAB_PARAM);
  294. if (!fNewOE) {
  295. wabParams.ulFlags = WAB_ENABLE_PROFILES | MAPI_UNICODE;
  296. }
  297. #ifdef UNICODE
  298. wabParams.szFileName = (PSTR) ConvertWtoA (destFile);
  299. #else
  300. wabParams.szFileName = (PSTR) destFile;
  301. #endif
  302. hr = lpfnWABOpen (&lpAdrBookWAB, &lpWABObject, &wabParams, 0);
  303. #ifdef UNICODE
  304. FreeConvertedStr (wabParams.szFileName);
  305. #endif
  306. if (hr == S_OK) {
  307. // Import the source WAB
  308. ZeroMemory (&wabImportParam, sizeof (WABIMPORTPARAM));
  309. wabImportParam.cbSize = sizeof (WABIMPORTPARAM);
  310. wabImportParam.lpAdrBook = lpAdrBookWAB;
  311. #ifdef UNICODE
  312. wabImportParam.lpszFileName = (PSTR) ConvertWtoA (srcFile);
  313. #else
  314. wabImportParam.lpszFileName = (PSTR) srcFile;
  315. #endif
  316. hr = lpWABObject->lpVtbl->Import (lpWABObject, (LPSTR)&wabImportParam);
  317. #ifdef UNICODE
  318. FreeConvertedStr (wabImportParam.lpszFileName);
  319. #endif
  320. if (hr == S_OK) {
  321. if (!StringIMatch (srcFile, destFile)) {
  322. // Delete the source WAB
  323. DeleteFile (srcFile);
  324. }
  325. } else {
  326. // Log a message that the user must manually import the WAB
  327. LOG ((LOG_WARNING, (PCSTR) MSG_WAB_MERGE_FAILED, srcFile));
  328. }
  329. lpWABObject->lpVtbl->Release (lpWABObject);
  330. lpAdrBookWAB->lpVtbl->Release (lpAdrBookWAB);
  331. }
  332. }
  333. FreeLibrary (lib);
  334. }
  335. }
  336. if (srcFile) {
  337. FreePathString (srcFile);
  338. }
  339. if (destFile) {
  340. FreeText (destFile);
  341. }
  342. if (wabPath) {
  343. FreeText (wabPath);
  344. }
  345. if (lpWABObjectName) {
  346. IsmDestroyObjectHandle (lpWABObjectName);
  347. }
  348. }
  349. }
  350. PCTSTR
  351. pBuildDefaultStoreRoot (
  352. IN PCTSTR Guid,
  353. IN BOOL GuidHasBrackets
  354. )
  355. {
  356. PTSTR storeRoot = NULL;
  357. UINT charCount;
  358. // output should be "%UserProfile%\Local Settings\Application Data\Identities\{guid}\Microsoft\Outlook Express"
  359. #define STOREBEGIN TEXT("%UserProfile%\\Local Settings\\Application Data\\Identities\\")
  360. #define STOREEND TEXT("\\Microsoft\\Outlook Express")
  361. storeRoot = AllocText(TcharCount(STOREBEGIN) +
  362. TcharCount(Guid) +
  363. TcharCount(STOREEND) +
  364. (GuidHasBrackets ? 1 : 3));
  365. StringCopy (storeRoot, STOREBEGIN);
  366. if (FALSE == GuidHasBrackets) {
  367. StringCat (storeRoot, TEXT("{"));
  368. }
  369. StringCat (storeRoot, Guid);
  370. if (FALSE == GuidHasBrackets) {
  371. StringCat (storeRoot, TEXT("}"));
  372. }
  373. StringCat (storeRoot, STOREEND);
  374. return storeRoot;
  375. }
  376. BOOL
  377. pOE5Import (
  378. IN PCTSTR SourceDir,
  379. IN PCTSTR DestDir,
  380. IN PCTSTR DestIdentity
  381. )
  382. {
  383. UUID uid;
  384. BOOL result = FALSE;
  385. PSTR szSrcPath;
  386. PSTR szDestPath;
  387. MIG_CONTENT dllObjectContent;
  388. MIG_OBJECTSTRINGHANDLE dllObjectName = NULL;
  389. PCTSTR dllExpPath = NULL;
  390. PTSTR dllTmpPath = NULL;
  391. IMailImport *mailImport = NULL;
  392. static LPOECREATE lpfnOE5SimpleCreate = NULL;
  393. static LPIMPORTSTORE lpfnImportMailStoreToGUID = NULL;
  394. static LPIMPORTNEWS lpfnImportNewsListToGUID = NULL;
  395. if (g_msoedll == NULL) {
  396. CoInitialize(NULL);
  397. g_CoInit = TRUE;
  398. dllObjectName = IsmCreateObjectHandle (TEXT("HKLM\\Software\\Microsoft\\Outlook Express"),
  399. TEXT("InstallRoot"));
  400. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  401. dllObjectName,
  402. &dllObjectContent)) {
  403. // dllObjectContent should be "%ProgramFiles%\\Outlook Express"
  404. if (IsValidRegSz (&dllObjectContent)) {
  405. dllExpPath = IsmExpandEnvironmentString(PLATFORM_DESTINATION,
  406. S_SYSENVVAR_GROUP,
  407. (PCTSTR)dllObjectContent.MemoryContent.ContentBytes,
  408. NULL);
  409. }
  410. if (dllExpPath) {
  411. dllTmpPath = JoinPaths (dllExpPath, TEXT("oemiglib.dll"));
  412. if (dllTmpPath) {
  413. g_oemiglib = LoadLibrary(dllTmpPath);
  414. FreePathString (dllTmpPath);
  415. }
  416. dllTmpPath = JoinPaths (dllExpPath, TEXT("msoe.dll"));
  417. if (dllTmpPath) {
  418. g_msoedll = LoadLibrary(dllTmpPath);
  419. FreePathString (dllTmpPath);
  420. }
  421. IsmReleaseMemory (dllExpPath);
  422. }
  423. IsmReleaseObject (&dllObjectContent);
  424. }
  425. IsmDestroyObjectHandle (dllObjectName);
  426. if (g_msoedll && g_oemiglib) {
  427. lpfnOE5SimpleCreate = (LPOECREATE) GetProcAddress (g_oemiglib, "OE5SimpleCreate");
  428. lpfnImportMailStoreToGUID = (LPIMPORTSTORE) GetProcAddress (g_msoedll, "ImportMailStoreToGUID");
  429. lpfnImportNewsListToGUID = (LPIMPORTNEWS) GetProcAddress (g_msoedll, "ImportNewsListToGUID");
  430. }
  431. }
  432. if (DestDir) {
  433. if (lpfnOE5SimpleCreate &&
  434. lpfnImportMailStoreToGUID &&
  435. lpfnImportNewsListToGUID) {
  436. // Convert to GUID *
  437. if (pUuidFromBracketedString(DestIdentity, &uid)) {
  438. #ifdef UNICODE
  439. szSrcPath = (PSTR) ConvertWtoA (SourceDir);
  440. szDestPath = (PSTR) ConvertWtoA (DestDir);
  441. #else
  442. szSrcPath = (PSTR) SourceDir;
  443. szDestPath = (PSTR) DestDir;
  444. #endif
  445. mailImport = lpfnOE5SimpleCreate(szSrcPath);
  446. if (mailImport) {
  447. lpfnImportMailStoreToGUID(mailImport, &uid, szDestPath);
  448. IMailImport_Release(mailImport);
  449. mailImport = NULL;
  450. result = TRUE;
  451. }
  452. lpfnImportNewsListToGUID (szSrcPath, &uid, szDestPath);
  453. #ifdef UNICODE
  454. FreeConvertedStr (szSrcPath);
  455. FreeConvertedStr (szDestPath);
  456. #endif
  457. }
  458. }
  459. if (SourceDir && DestDir) {
  460. // Copy source folder to dest folder, but never overwrite
  461. if (!DoesFileExist (DestDir)) {
  462. BfCreateDirectory (DestDir);
  463. }
  464. FiCopyAllFilesInTreeEx(SourceDir, DestDir, TRUE);
  465. }
  466. }
  467. return result;
  468. }
  469. //////////////////////////////////////////////////////////////////////////////////////
  470. // OE5MergeStorefolders
  471. // This cycles through every store folder and decides whether to just copy it to the
  472. // destination or merge into an existing store folder in the destination
  473. VOID
  474. OE5MergeStoreFolders (
  475. VOID
  476. )
  477. {
  478. TCHAR szGuid[37];
  479. MIG_OBJECTSTRINGHANDLE objectName = NULL;
  480. MIG_OBJECTSTRINGHANDLE filteredName = NULL;
  481. MIG_CONTENT objectContent;
  482. MIG_CONTENT destObjectContent;
  483. MIG_OBJECT_ENUM objectEnum;
  484. MIG_OBJECTSTRINGHANDLE enumPattern;
  485. PTSTR srcStoreRoot = NULL;
  486. PCTSTR destStoreRoot = NULL;
  487. PCTSTR destFolderFile = NULL;
  488. PTSTR node;
  489. PTSTR leaf;
  490. PTSTR junk;
  491. PCTSTR expandedName = NULL;
  492. BOOL fImport;
  493. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  494. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
  495. // Enumerate each source Store Folder
  496. enumPattern = IsmCreateSimpleObjectPattern (
  497. TEXT("HKCU\\Identities"),
  498. TRUE,
  499. TEXT("Store Root"),
  500. FALSE);
  501. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  502. do {
  503. fImport = FALSE;
  504. IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
  505. if (leaf && *leaf) {
  506. if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE, objectEnum.ObjectName, &objectContent)) {
  507. if (IsValidRegSz (&objectContent)) {
  508. expandedName = IsmExpandEnvironmentString (
  509. PLATFORM_SOURCE,
  510. S_SYSENVVAR_GROUP,
  511. (PCTSTR)objectContent.MemoryContent.ContentBytes,
  512. NULL);
  513. }
  514. if (expandedName) {
  515. objectName = IsmCreateObjectHandle(expandedName, NULL);
  516. IsmReleaseMemory (expandedName);
  517. expandedName = NULL;
  518. }
  519. if (objectName) {
  520. filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
  521. objectName,
  522. NULL,
  523. NULL,
  524. NULL);
  525. if (filteredName) {
  526. IsmCreateObjectStringsFromHandle (filteredName, &srcStoreRoot, &junk);
  527. // srcStoreRoot is now the source directory
  528. IsmDestroyObjectHandle (filteredName);
  529. filteredName = NULL;
  530. } else {
  531. IsmCreateObjectStringsFromHandle(objectName, &srcStoreRoot, &junk);
  532. }
  533. if (junk) {
  534. IsmDestroyObjectString (junk);
  535. junk = NULL;
  536. }
  537. IsmDestroyObjectHandle (objectName);
  538. objectName = NULL;
  539. }
  540. // Now check to see if the dest Store Root previously existed
  541. if (srcStoreRoot) {
  542. filteredName = IsmFilterObject (g_RegType | PLATFORM_SOURCE,
  543. objectEnum.ObjectName,
  544. NULL,
  545. NULL,
  546. NULL);
  547. // Extract GUID out of destination object name
  548. _stscanf(filteredName ? filteredName : objectEnum.ObjectName,
  549. TEXT("%*[^{]{%[^}]"),
  550. szGuid);
  551. // szGuid is now the destination identity guid, minus the {}
  552. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  553. filteredName ? filteredName : objectEnum.ObjectName,
  554. &destObjectContent)) {
  555. if (IsValidRegSz (&destObjectContent)) {
  556. destStoreRoot = IsmExpandEnvironmentString (
  557. PLATFORM_DESTINATION,
  558. S_SYSENVVAR_GROUP,
  559. (PCTSTR)destObjectContent.MemoryContent.ContentBytes,
  560. NULL);
  561. }
  562. if (destStoreRoot) {
  563. destFolderFile = JoinPaths(destStoreRoot, TEXT("folders.dbx"));
  564. }
  565. if (destFolderFile) {
  566. if ((!StringIMatch(srcStoreRoot, destStoreRoot)) &&
  567. (DoesFileExist(destFolderFile))) {
  568. fImport = TRUE;
  569. }
  570. FreePathString(destFolderFile);
  571. }
  572. IsmReleaseObject (&destObjectContent);
  573. }
  574. }
  575. if (szGuid[0]) {
  576. if (!fImport) {
  577. // This is a FIRST migration, so set the dest store root to default
  578. IsmReleaseMemory(destStoreRoot);
  579. destStoreRoot = pBuildDefaultStoreRoot(szGuid, FALSE);
  580. // Set [StoreRoot] = destStoreRoot
  581. ZeroMemory (&destObjectContent, sizeof(MIG_CONTENT));
  582. destObjectContent.ObjectTypeId = g_RegType;
  583. destObjectContent.Details.DetailsSize = sizeof(DWORD);
  584. destObjectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
  585. *((PDWORD)destObjectContent.Details.DetailsData) = REG_EXPAND_SZ;
  586. destObjectContent.MemoryContent.ContentSize = SizeOfString (destStoreRoot);
  587. destObjectContent.MemoryContent.ContentBytes = (PBYTE)destStoreRoot;
  588. IsmReplacePhysicalObject (g_RegType,
  589. filteredName ? filteredName : objectEnum.ObjectName,
  590. &destObjectContent);
  591. IsmDestroyObjectHandle (objectName);
  592. // expand environment on destStoreRoot
  593. FreeText(destStoreRoot);
  594. destStoreRoot = IsmExpandEnvironmentString (
  595. PLATFORM_DESTINATION,
  596. S_SYSENVVAR_GROUP,
  597. (PCTSTR)destObjectContent.MemoryContent.ContentBytes,
  598. NULL);
  599. // Cleanup the objectContent we allocated
  600. IsmReleaseMemory (destObjectContent.Details.DetailsData);
  601. }
  602. if (srcStoreRoot && destStoreRoot) {
  603. if (!DoesFileExist (destStoreRoot)) {
  604. BfCreateDirectory (destStoreRoot);
  605. }
  606. pOE5Import(srcStoreRoot, destStoreRoot, szGuid);
  607. }
  608. }
  609. if (filteredName) {
  610. IsmDestroyObjectHandle(filteredName);
  611. filteredName = NULL;
  612. }
  613. if (destStoreRoot) {
  614. IsmReleaseMemory(destStoreRoot);
  615. destStoreRoot = NULL;
  616. }
  617. if (srcStoreRoot) {
  618. IsmDestroyObjectString (srcStoreRoot);
  619. srcStoreRoot = NULL;
  620. }
  621. IsmReleaseObject (&objectContent);
  622. }
  623. IsmDestroyObjectString (leaf);
  624. }
  625. IsmDestroyObjectString (node);
  626. } while (IsmEnumNextObject (&objectEnum));
  627. // Remove temp folder
  628. expandedName = IsmExpandEnvironmentString (PLATFORM_DESTINATION, S_SYSENVVAR_GROUP, OETEMPDIR, NULL);
  629. if (expandedName) {
  630. FiRemoveAllFilesInTree (expandedName);
  631. IsmReleaseMemory (expandedName);
  632. } else {
  633. FiRemoveAllFilesInTree (OETEMPDIR);
  634. }
  635. }
  636. IsmDestroyObjectHandle (enumPattern);
  637. }
  638. }
  639. VOID
  640. OE4MergeStoreFolder (
  641. VOID
  642. )
  643. {
  644. MIG_OBJECTSTRINGHANDLE regKey;
  645. MIG_OBJECTSTRINGHANDLE objectName = NULL;
  646. MIG_OBJECTSTRINGHANDLE filteredName;
  647. MIG_CONTENT objectContent;
  648. HANDLE h;
  649. PCTSTR srcStorePath = NULL;
  650. PCTSTR expPath = NULL;
  651. PTSTR destIdentity = NULL;
  652. PTSTR tmpStr = NULL;
  653. PTSTR tmpNode = NULL;
  654. PTSTR cmdLine = NULL;
  655. PCTSTR sid = NULL;
  656. DWORD exitCode;
  657. DWORD cmdLen;
  658. TCHAR tmpDir[MAX_PATH];
  659. PCTSTR destDir = NULL;
  660. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  661. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT)) {
  662. objectName = IsmCreateObjectHandle (TEXT("HKLM\\Software\\Microsoft\\Outlook Express"),
  663. TEXT("InstallRoot"));
  664. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
  665. objectName,
  666. &objectContent)) {
  667. // objectContent should be "%ProgramFiles%\\Outlook Express"
  668. if (IsValidRegSz (&objectContent)) {
  669. tmpStr = JoinPaths (objectContent.MemoryContent.ContentBytes, TEXT("oemig50.exe"));
  670. // tmpStr should be "%ProgramFiles%\\OutlookExpress\\oemig50.exe"
  671. expPath = IsmExpandEnvironmentString (PLATFORM_DESTINATION, S_SYSENVVAR_GROUP, tmpStr, NULL);
  672. FreePathString (tmpStr);
  673. }
  674. IsmReleaseObject (&objectContent);
  675. }
  676. IsmDestroyObjectHandle (objectName);
  677. // Get the dest identity
  678. if (expPath) {
  679. destIdentity = OEGetDefaultId (PLATFORM_DESTINATION);
  680. }
  681. // Now get the source's Store Root
  682. if (destIdentity) {
  683. objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Outlook Express"),
  684. TEXT("Store Root"));
  685. if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE,
  686. objectName,
  687. &objectContent)) {
  688. if (IsValidRegSz (&objectContent)) {
  689. IsmDestroyObjectHandle (objectName);
  690. objectName = IsmCreateObjectHandle ((PCTSTR) objectContent.MemoryContent.ContentBytes,
  691. NULL);
  692. filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
  693. objectName,
  694. NULL,
  695. NULL,
  696. NULL);
  697. if (filteredName) {
  698. IsmCreateObjectStringsFromHandle (filteredName, &srcStorePath, NULL);
  699. IsmDestroyObjectHandle (filteredName);
  700. } else {
  701. IsmCreateObjectStringsFromHandle (objectName, &srcStorePath, NULL);
  702. }
  703. }
  704. IsmReleaseObject (&objectContent);
  705. }
  706. IsmDestroyObjectHandle (objectName);
  707. }
  708. // Now grab a temporary place to stuff the upgraded files
  709. IsmGetTempDirectory(tmpDir, ARRAYSIZE(tmpDir));
  710. // Call the external upgrade exe
  711. if (srcStorePath != NULL &&
  712. expPath != NULL) {
  713. sid = IsmGetCurrentSidString();
  714. cmdLen = TcharCount(expPath) + TcharCount(srcStorePath) + TcharCount(tmpDir) + 35;
  715. if (sid) {
  716. cmdLen += TcharCount(sid) + 6;
  717. }
  718. cmdLine = AllocText (cmdLen);
  719. StringCopy (cmdLine, expPath);
  720. StringCat (cmdLine, TEXT(" /type:V1+V4-V5 /src:")); // 21
  721. StringCat (cmdLine, srcStorePath);
  722. StringCat (cmdLine, TEXT(" /dst:")); // 6
  723. StringCat (cmdLine, tmpDir);
  724. StringCat (cmdLine, TEXT(" /quiet")); // 7
  725. if (sid) {
  726. StringCat (cmdLine, TEXT(" /key:")); // (6)
  727. StringCat (cmdLine, sid);
  728. }
  729. LOG ((LOG_INFORMATION, (PCSTR) MSG_SPAWNING_PROCESS_INFO, cmdLine));
  730. h = StartProcess (cmdLine);
  731. if (h != NULL) {
  732. WaitForSingleObject (h, INFINITE);
  733. if (GetExitCodeProcess (h, &exitCode)) {
  734. if ((exitCode != STILL_ACTIVE) && ((exitCode & 0xFFFF) != 800 )) {
  735. LOG ((LOG_ERROR, (PCSTR)MSG_OE4_UPGRADE_FAILED));
  736. }
  737. }
  738. CloseHandle (h);
  739. FreeText (cmdLine);
  740. // Cleanup the source store
  741. FiRemoveAllFilesInTree (srcStorePath);
  742. }
  743. destDir = pGetDestStoreRootForId(destIdentity);
  744. if (destDir) {
  745. if (!DoesFileExist (destDir)) {
  746. // Just copy into to the dest dir
  747. BfCreateDirectory (destDir);
  748. FiCopyAllFilesInTreeEx(tmpDir, destDir, TRUE);
  749. } else {
  750. // Now do an OE5 Import from tmpDir to destIdentity
  751. pOE5Import(tmpDir, destDir, destIdentity);
  752. }
  753. FreeText(destDir);
  754. }
  755. FiRemoveAllFilesInTree (tmpDir);
  756. // Set [StoreMigratedV5] = 1
  757. // Set [ConvertedToDBX] = 1
  758. tmpStr = JoinText(TEXT("HKCU\\Identities\\"), destIdentity);
  759. if (tmpStr) {
  760. tmpNode = JoinText(tmpStr, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0"));
  761. if (tmpNode) {
  762. CreateDwordRegObject (tmpNode, TEXT("StoreMigratedV5"), 1);
  763. CreateDwordRegObject (tmpNode, TEXT("ConvertedToDBX"), 1);
  764. FreeText(tmpNode);
  765. }
  766. FreeText(tmpStr);
  767. }
  768. }
  769. if (destIdentity) {
  770. FreeText(destIdentity);
  771. }
  772. if (sid) {
  773. IsmReleaseMemory (sid);
  774. }
  775. if (expPath) {
  776. IsmReleaseMemory (expPath);
  777. }
  778. if (srcStorePath) {
  779. IsmDestroyObjectString (srcStorePath);
  780. }
  781. }
  782. }
  783. BOOL
  784. OEIAMAssociateId (
  785. IN PTSTR SrcId
  786. )
  787. {
  788. MIG_OBJECTSTRINGHANDLE objectName;
  789. MIG_OBJECTTYPEID objectTypeId;
  790. MIG_CONTENT objectContent;
  791. PTSTR srcStr;
  792. TCHAR *p;
  793. UUID srcUUID;
  794. RPC_STATUS status;
  795. BOOL retval = FALSE;
  796. DWORD regType = REG_BINARY;
  797. if (pUuidFromBracketedString (SrcId, &srcUUID)) {
  798. // Create [AssociatedID] = Uuid
  799. objectTypeId = g_RegType | PLATFORM_DESTINATION;
  800. ZeroMemory(&objectContent, sizeof(MIG_CONTENT));
  801. objectContent.ContentInFile = FALSE;
  802. objectContent.MemoryContent.ContentSize = sizeof(UUID);
  803. objectContent.MemoryContent.ContentBytes = IsmGetMemory(sizeof(UUID));
  804. CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes, &srcUUID, sizeof(UUID));
  805. objectContent.Details.DetailsData = &regType;
  806. objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Internet Account Manager\\Accounts"),
  807. TEXT("AssociatedID"));
  808. if (objectName) {
  809. retval = IsmReplacePhysicalObject (objectTypeId, objectName, &objectContent);
  810. IsmDestroyObjectHandle (objectName);
  811. g_DestAssociatedId = DuplicateText(SrcId);
  812. }
  813. IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
  814. }
  815. return retval;
  816. }
  817. BOOL
  818. OEIsIdentityAssociated (
  819. IN PTSTR IdStr
  820. )
  821. {
  822. BOOL associated = FALSE;
  823. if (!g_DestAssociatedId) {
  824. g_DestAssociatedId = OEGetAssociatedId(PLATFORM_DESTINATION);
  825. }
  826. if (g_DestAssociatedId) {
  827. associated = StringIMatch(IdStr, g_DestAssociatedId);
  828. } else {
  829. // Apparently there is no associated ID. Let's claim it.
  830. OEIAMAssociateId(IdStr);
  831. associated = TRUE;
  832. }
  833. return associated;
  834. }
  835. PTSTR
  836. OEGetRemappedId(
  837. IN PCTSTR IdStr
  838. )
  839. {
  840. MIG_OBJECTSTRINGHANDLE objectName;
  841. MIG_OBJECTSTRINGHANDLE filteredName;
  842. PTSTR tmpName;
  843. PTSTR node;
  844. PTSTR leaf;
  845. PTSTR result = NULL;
  846. TCHAR *p;
  847. tmpName = JoinText(TEXT("HKCU\\Identities\\"), IdStr);
  848. if (tmpName) {
  849. objectName = IsmCreateObjectHandle(tmpName, NULL);
  850. if (objectName) {
  851. filteredName = IsmFilterObject(g_RegType | PLATFORM_SOURCE,
  852. objectName,
  853. NULL,
  854. NULL,
  855. NULL);
  856. if (filteredName) {
  857. IsmCreateObjectStringsFromHandle (filteredName, &node, &leaf);
  858. if (node) {
  859. p = (PTSTR)FindLastWack(node);
  860. if (p) {
  861. result = DuplicateText(_tcsinc(p));
  862. }
  863. IsmDestroyObjectString(node);
  864. }
  865. if (leaf) {
  866. IsmDestroyObjectString (leaf);
  867. }
  868. IsmDestroyObjectHandle(filteredName);
  869. } else {
  870. result = DuplicateText(IdStr);
  871. }
  872. IsmDestroyObjectHandle (objectName);
  873. }
  874. FreeText(tmpName);
  875. }
  876. return result;
  877. }
  878. PTSTR
  879. OEGetDefaultId (
  880. IN MIG_PLATFORMTYPEID Platform
  881. )
  882. {
  883. MIG_OBJECTSTRINGHANDLE objectName;
  884. MIG_CONTENT objectContent;
  885. PTSTR retval = NULL;
  886. objectName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"),
  887. TEXT("Default User ID"));
  888. if (objectName) {
  889. if (IsmAcquireObject ( g_RegType | Platform, objectName, &objectContent)) {
  890. if (IsValidRegSz(&objectContent)) {
  891. retval = DuplicateText((PTSTR)objectContent.MemoryContent.ContentBytes);
  892. }
  893. IsmReleaseObject (&objectContent);
  894. }
  895. IsmDestroyObjectHandle (objectName);
  896. }
  897. return retval;
  898. }
  899. PTSTR
  900. OEGetAssociatedId (
  901. IN MIG_PLATFORMTYPEID Platform
  902. )
  903. {
  904. MIG_OBJECTSTRINGHANDLE objectName;
  905. MIG_CONTENT objectContent;
  906. PTSTR uuidStr;
  907. PTSTR retval = NULL;
  908. objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Internet Account Manager\\Accounts"),
  909. TEXT("AssociatedID"));
  910. if (objectName) {
  911. if (IsmAcquireObject ( g_RegType | Platform, objectName, &objectContent)) {
  912. if (IsValidRegType(&objectContent, REG_BINARY)) {
  913. if (RPC_S_OK == UuidToString ((UUID *)objectContent.MemoryContent.ContentBytes, &uuidStr)) {
  914. retval = AllocText(CharCount(uuidStr) + 3);
  915. if (retval) {
  916. StringCopy(retval, TEXT("{"));
  917. StringCat(retval, uuidStr);
  918. StringCat(retval, TEXT("}"));
  919. }
  920. RpcStringFree(&uuidStr);
  921. }
  922. }
  923. IsmReleaseObject (&objectContent);
  924. }
  925. IsmDestroyObjectHandle (objectName);
  926. }
  927. return retval;
  928. }
  929. VOID
  930. OETerminate (
  931. VOID
  932. )
  933. {
  934. if (g_DestAssociatedId) {
  935. FreeText(g_DestAssociatedId);
  936. }
  937. if (g_msoedll) {
  938. FreeLibrary(g_msoedll);
  939. g_msoedll = NULL;
  940. }
  941. if (g_oemiglib) {
  942. FreeLibrary(g_oemiglib);
  943. g_oemiglib = NULL;
  944. }
  945. if (g_CoInit) {
  946. CoUninitialize();
  947. g_CoInit = FALSE;
  948. }
  949. }
  950. pRenameRegTreePattern (
  951. IN MIG_OBJECTSTRINGHANDLE Pattern,
  952. IN PCMIG_BLOB SrcBlob,
  953. IN PCMIG_BLOB DestBlob,
  954. IN BOOL ReplaceOld
  955. )
  956. {
  957. MIG_OBJECT_ENUM objectEnum;
  958. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, Pattern)) {
  959. if (!g_RenameOp) {
  960. g_RenameOp = IsmRegisterOperation (S_OPERATION_MOVE, FALSE);
  961. }
  962. do {
  963. // Set operation on all source objects in this ID
  964. if (ReplaceOld) {
  965. IsmClearOperationOnObject(g_RegType | PLATFORM_SOURCE,
  966. objectEnum.ObjectName,
  967. g_RenameOp);
  968. }
  969. IsmSetOperationOnObject(g_RegType | PLATFORM_SOURCE,
  970. objectEnum.ObjectName,
  971. g_RenameOp,
  972. SrcBlob,
  973. DestBlob);
  974. } while (IsmEnumNextObject(&objectEnum));
  975. }
  976. }
  977. pRenameRegTree (
  978. IN PCTSTR SrcIdName,
  979. IN PCTSTR DestIdName,
  980. IN BOOL ReplaceOld
  981. )
  982. {
  983. MIG_BLOB srcBlob;
  984. MIG_BLOB destBlob;
  985. MIG_OBJECTSTRINGHANDLE pattern;
  986. srcBlob.Type = BLOBTYPE_STRING;
  987. srcBlob.String = IsmCreateObjectHandle(SrcIdName, NULL);
  988. if (srcBlob.String) {
  989. destBlob.Type = BLOBTYPE_STRING;
  990. destBlob.String = IsmCreateObjectHandle(DestIdName, NULL);
  991. if (destBlob.String) {
  992. // Recursive
  993. pattern = IsmCreateSimpleObjectPattern(SrcIdName, TRUE, NULL, TRUE);
  994. if (pattern) {
  995. pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
  996. IsmDestroyObjectHandle(pattern);
  997. }
  998. // Now for the node's values
  999. pattern = IsmCreateSimpleObjectPattern(SrcIdName, FALSE, NULL, TRUE);
  1000. if (pattern) {
  1001. pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
  1002. IsmDestroyObjectHandle(pattern);
  1003. }
  1004. // Now for only the node itself
  1005. pattern = IsmCreateSimpleObjectPattern(SrcIdName, FALSE, NULL, FALSE);
  1006. if (pattern) {
  1007. pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
  1008. IsmDestroyObjectHandle(pattern);
  1009. }
  1010. IsmDestroyObjectHandle(destBlob.String);
  1011. }
  1012. IsmDestroyObjectHandle(srcBlob.String);
  1013. }
  1014. }
  1015. BOOL
  1016. pClearApply (
  1017. IN PCTSTR Node,
  1018. IN PCTSTR Leaf
  1019. )
  1020. {
  1021. MIG_OBJECTSTRINGHANDLE objectName;
  1022. BOOL result = FALSE;
  1023. objectName = IsmCreateObjectHandle(Node, Leaf);
  1024. if (objectName) {
  1025. IsmClearApplyOnObject((g_RegType & (~PLATFORM_MASK)) | PLATFORM_SOURCE, objectName);
  1026. IsmDestroyObjectHandle (objectName);
  1027. result = TRUE;
  1028. }
  1029. return result;
  1030. }
  1031. BOOL
  1032. OE5RemapDefaultId (
  1033. VOID
  1034. )
  1035. {
  1036. MIG_OBJECTSTRINGHANDLE destObjectName;
  1037. MIG_OBJECTSTRINGHANDLE pattern;
  1038. MIG_CONTENT destIdObjectContent;
  1039. PTSTR idName;
  1040. PTSTR destIdName;
  1041. PTSTR srcDefaultId;
  1042. PTSTR destDefaultId;
  1043. MIG_OBJECT_ENUM objectEnum;
  1044. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  1045. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
  1046. srcDefaultId = OEGetDefaultId(PLATFORM_SOURCE);
  1047. if (srcDefaultId) {
  1048. destDefaultId = OEGetDefaultId(PLATFORM_DESTINATION);
  1049. if (destDefaultId) {
  1050. if (!StringIMatch (srcDefaultId, destDefaultId)) {
  1051. // different default IDs
  1052. idName = JoinText(TEXT("HKCU\\Identities\\"), srcDefaultId);
  1053. if (idName) {
  1054. destObjectName = IsmCreateObjectHandle(idName, NULL);
  1055. if (IsmAcquireObject(
  1056. g_RegType | PLATFORM_DESTINATION,
  1057. destObjectName,
  1058. &destIdObjectContent)) {
  1059. // The source ID already exists on the dest.. do nothing extra
  1060. IsmReleaseObject(&destIdObjectContent);
  1061. } else {
  1062. // Remap this identity into destination default
  1063. destIdName = JoinText(TEXT("HKCU\\Identities\\"),
  1064. destDefaultId);
  1065. if (destIdName) {
  1066. pRenameRegTree(idName, destIdName, TRUE);
  1067. FreeText(destIdName);
  1068. }
  1069. pClearApply(TEXT("HKCU\\Identities"), TEXT("Default User ID"));
  1070. pClearApply(TEXT("HKCU\\Identities"), TEXT("Last User ID"));
  1071. pClearApply(TEXT("HKCU\\Identities"), TEXT("Last Username"));
  1072. // ForceDestReg the top level Identities values
  1073. pattern = IsmCreateSimpleObjectPattern(idName, FALSE, NULL, TRUE);
  1074. if (pattern) {
  1075. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, pattern)) {
  1076. do {
  1077. IsmClearApplyOnObject(
  1078. (g_RegType & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
  1079. objectEnum.ObjectName);
  1080. } while (IsmEnumNextObject(&objectEnum));
  1081. }
  1082. IsmDestroyObjectHandle(pattern);
  1083. }
  1084. }
  1085. IsmDestroyObjectHandle(destObjectName);
  1086. FreeText(idName);
  1087. }
  1088. }
  1089. FreeText(destDefaultId);
  1090. }
  1091. FreeText(srcDefaultId);
  1092. }
  1093. }
  1094. return TRUE;
  1095. }
  1096. //////////////////////////////////////////////////////////////////////////////////////
  1097. // pOE5RemapRules
  1098. // This adds a renregfn rule for \ConvertOE5MailRules to
  1099. // HKCU\Identities\{*}\Software\Microsoft\Outlook Express\5.0\Rules\Mail\*
  1100. // ditto for News rules
  1101. // Also for Block Senders\Mail\Criteria\* and News
  1102. BOOL
  1103. pOE5RemapRules (
  1104. VOID
  1105. )
  1106. {
  1107. MIG_OBJECT_ENUM objectEnum;
  1108. MIG_OBJECTSTRINGHANDLE enumPattern;
  1109. MIG_OBJECTSTRINGHANDLE subPattern;
  1110. PTSTR tmpNode;
  1111. PTSTR node;
  1112. PTSTR leaf;
  1113. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  1114. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
  1115. // Find HKCU\Identities\{*}\Software\Microsoft\Outlook Express\5.0\Rules\Mail\*
  1116. // First enum each identity
  1117. enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
  1118. TEXT("User ID"), FALSE);
  1119. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  1120. do {
  1121. IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
  1122. if (node && leaf) {
  1123. // Enum the Rules keys under this identity
  1124. tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Rules\\Mail"));
  1125. if (tmpNode) {
  1126. subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
  1127. if (subPattern) {
  1128. AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5MailRules"));
  1129. IsmDestroyObjectHandle(subPattern);
  1130. }
  1131. FreeText(tmpNode);
  1132. }
  1133. tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Rules\\News"));
  1134. if (tmpNode) {
  1135. subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
  1136. if (subPattern) {
  1137. AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5NewsRules"));
  1138. IsmDestroyObjectHandle(subPattern);
  1139. }
  1140. FreeText(tmpNode);
  1141. }
  1142. tmpNode = JoinText(
  1143. node,
  1144. TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Block Senders\\Mail\\Criteria")
  1145. );
  1146. if (tmpNode) {
  1147. subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
  1148. if (subPattern) {
  1149. AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5Block"));
  1150. IsmDestroyObjectHandle(subPattern);
  1151. }
  1152. FreeText(tmpNode);
  1153. }
  1154. tmpNode = JoinText(
  1155. node,
  1156. TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Block Senders\\News\\Criteria")
  1157. );
  1158. if (tmpNode) {
  1159. subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
  1160. if (subPattern) {
  1161. AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5Block"));
  1162. IsmDestroyObjectHandle(subPattern);
  1163. }
  1164. FreeText(tmpNode);
  1165. }
  1166. }
  1167. IsmDestroyObjectString(node);
  1168. if (leaf) {
  1169. IsmDestroyObjectString(leaf);
  1170. }
  1171. } while (IsmEnumNextObject (&objectEnum));
  1172. }
  1173. IsmDestroyObjectHandle (enumPattern);
  1174. }
  1175. return TRUE;
  1176. }
  1177. //////////////////////////////////////////////////////////////////////////////////////
  1178. // pOE5RemapAccounts
  1179. // This adds a renregfn rule for \ConvertOE5IdIAM to
  1180. // HKCU\Identities\{*}\Software\Microsoft\Internet Account Manager\*
  1181. BOOL
  1182. pOE5RemapAccounts (
  1183. VOID
  1184. )
  1185. {
  1186. MIG_OBJECT_ENUM objectEnum;
  1187. MIG_OBJECTSTRINGHANDLE enumPattern;
  1188. MIG_OBJECTSTRINGHANDLE subPattern;
  1189. PTSTR tmpNode;
  1190. PTSTR node;
  1191. PTSTR leaf;
  1192. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  1193. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
  1194. // Find HKCU\Identities\{*}\Software\Microsoft\Internet Account Manger\*
  1195. // First enum each identity
  1196. enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
  1197. TEXT("User ID"), FALSE);
  1198. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  1199. do {
  1200. IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
  1201. if (node && leaf) {
  1202. // Enum the IAM keys under this identity
  1203. tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Internet Account Manager"));
  1204. if (tmpNode) {
  1205. subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
  1206. if (subPattern) {
  1207. AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5IdIAM"));
  1208. IsmDestroyObjectHandle(subPattern);
  1209. }
  1210. FreeText(tmpNode);
  1211. }
  1212. }
  1213. IsmDestroyObjectString(node);
  1214. if (leaf) {
  1215. IsmDestroyObjectString(leaf);
  1216. }
  1217. } while (IsmEnumNextObject (&objectEnum));
  1218. }
  1219. IsmDestroyObjectHandle (enumPattern);
  1220. }
  1221. return TRUE;
  1222. }
  1223. //////////////////////////////////////////////////////////////////////////////////////
  1224. // OECreateFirstIdentity
  1225. // This is used to create the very first identity for a user that we just created
  1226. PTSTR
  1227. OECreateFirstIdentity (
  1228. VOID
  1229. )
  1230. {
  1231. PTSTR destID = NULL;
  1232. PTSTR uuidStr;
  1233. UUID uuid;
  1234. RPC_STATUS result;
  1235. MIG_OBJECTSTRINGHANDLE objectName = NULL;
  1236. MIG_CONTENT objectContent;
  1237. PTSTR node;
  1238. PCTSTR defaultStore;
  1239. result = UuidCreate (&uuid);
  1240. if (result == RPC_S_OK || result == RPC_S_UUID_LOCAL_ONLY) {
  1241. result = UuidToString (&uuid, &uuidStr);
  1242. if (result == RPC_S_OK) {
  1243. destID = AllocText (CharCount (uuidStr) + 3);
  1244. wsprintf (destID, TEXT("{%s}"), uuidStr);
  1245. RpcStringFree (&uuidStr);
  1246. }
  1247. }
  1248. if (destID) {
  1249. // Create [Default User ID] = &destID
  1250. ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
  1251. objectContent.ObjectTypeId = g_RegType;
  1252. objectContent.Details.DetailsSize = sizeof(DWORD);
  1253. objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
  1254. *((PDWORD)objectContent.Details.DetailsData) = REG_SZ;
  1255. objectContent.MemoryContent.ContentSize = SizeOfString (destID);
  1256. objectContent.MemoryContent.ContentBytes = IsmGetMemory (objectContent.MemoryContent.ContentSize);
  1257. CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes, destID, objectContent.MemoryContent.ContentSize);
  1258. objectName = IsmCreateObjectHandle(TEXT("HKCU\\Identities"), TEXT("Default User ID"));
  1259. if (objectName) {
  1260. IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
  1261. IsmDestroyObjectHandle (objectName);
  1262. objectName = NULL;
  1263. }
  1264. // Set [Last User ID] = &destID
  1265. objectName = IsmCreateObjectHandle(TEXT("HKCU\\Identities"), TEXT("Last User ID"));
  1266. if (objectName) {
  1267. IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
  1268. IsmDestroyObjectHandle (objectName);
  1269. objectName = NULL;
  1270. }
  1271. // Create [User ID] = &destID
  1272. node = AllocText (17 + CharCount (destID));
  1273. if (node) {
  1274. wsprintf (node, TEXT("HKCU\\Identities\\%s"), destID);
  1275. objectName = IsmCreateObjectHandle(node, TEXT("User ID"));
  1276. FreeText (node);
  1277. }
  1278. if (objectName) {
  1279. IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
  1280. IsmDestroyObjectHandle (objectName);
  1281. objectName = NULL;
  1282. }
  1283. IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
  1284. // Set [Store Root] = %UserProfile%\Local Settings\Application Data\Identities\&destID\Microsoft\Outlook Express
  1285. defaultStore = pBuildDefaultStoreRoot(destID, TRUE);
  1286. if (defaultStore) {
  1287. objectContent.MemoryContent.ContentBytes = (PCBYTE)defaultStore;
  1288. objectContent.MemoryContent.ContentSize = SizeOfString(defaultStore);
  1289. *((PDWORD)objectContent.Details.DetailsData) = REG_EXPAND_SZ;
  1290. node = AllocText (56 + CharCount (destID));
  1291. if (node) {
  1292. wsprintf (node, TEXT("HKCU\\Identities\\%s\\Software\\Microsoft\\Outlook Express\\5.0"), destID);
  1293. objectName = IsmCreateObjectHandle(node, TEXT("Store Root"));
  1294. FreeText (node);
  1295. }
  1296. if (objectName) {
  1297. IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
  1298. IsmDestroyObjectHandle (objectName);
  1299. }
  1300. FreeText(defaultStore);
  1301. }
  1302. IsmReleaseMemory (objectContent.Details.DetailsData);
  1303. OEIAMAssociateId (destID);
  1304. }
  1305. return destID;
  1306. }
  1307. //////////////////////////////////////////////////////////////////////////////////////
  1308. // OEInitializeIdentity
  1309. // This is used to initialize a destination identity that has been created but never used.
  1310. BOOL
  1311. OEInitializeIdentity (
  1312. VOID
  1313. )
  1314. {
  1315. MIG_OBJECTSTRINGHANDLE storeRootKey = NULL;
  1316. MIG_CONTENT objectContent;
  1317. PCTSTR defaultId;
  1318. PCTSTR defaultStoreRoot;
  1319. BOOL reinit = TRUE;
  1320. defaultId = OEGetDefaultId (PLATFORM_DESTINATION);
  1321. if (defaultId) {
  1322. storeRootKey = pBuildStoreRootKeyForId (defaultId);
  1323. if (storeRootKey) {
  1324. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, storeRootKey, &objectContent)) {
  1325. if (IsValidRegSz(&objectContent)) {
  1326. reinit = FALSE;
  1327. }
  1328. IsmReleaseObject (&objectContent);
  1329. }
  1330. if (reinit) {
  1331. defaultStoreRoot = pBuildDefaultStoreRoot (defaultId, TRUE);
  1332. if (defaultStoreRoot) {
  1333. ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
  1334. objectContent.ObjectTypeId = g_RegType;
  1335. objectContent.Details.DetailsSize = sizeof(DWORD);
  1336. objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
  1337. *((PDWORD)objectContent.Details.DetailsData) = REG_EXPAND_SZ;
  1338. objectContent.MemoryContent.ContentSize = SizeOfString (defaultStoreRoot);
  1339. objectContent.MemoryContent.ContentBytes = (PBYTE)defaultStoreRoot;
  1340. IsmReplacePhysicalObject (g_RegType, storeRootKey, &objectContent);
  1341. IsmReleaseMemory (objectContent.Details.DetailsData);
  1342. FreeText(defaultStoreRoot);
  1343. }
  1344. }
  1345. IsmDestroyObjectHandle(storeRootKey);
  1346. }
  1347. FreeText(defaultId);
  1348. }
  1349. return TRUE;
  1350. }
  1351. //////////////////////////////////////////////////////////////////////////////////////
  1352. // pOE5RemapStores
  1353. // This is used to set a special RegFolder rule for the OE5 [Store Root] values
  1354. // The rule will redirect all store folders into a temporary directory. Later,
  1355. // OE5MergeStorefolders will decide whether to copy or merge them into the proper
  1356. // location on the destination
  1357. BOOL
  1358. pOE5RemapStores (
  1359. VOID
  1360. )
  1361. {
  1362. MIG_OBJECTSTRINGHANDLE enumPattern;
  1363. MIG_OBJECT_ENUM objectEnum;
  1364. PTSTR node;
  1365. PTSTR leaf;
  1366. TCHAR tmpDir[MAX_PATH];
  1367. BOOL result = FALSE;
  1368. ACTION_STRUCT actionStruct;
  1369. DWORD index = 0;
  1370. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  1371. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
  1372. // Find HKCU\Identities\* [Store Root]
  1373. // First enum each identity
  1374. enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
  1375. TEXT("Store Root"), FALSE);
  1376. if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
  1377. do {
  1378. IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
  1379. if (node && leaf) {
  1380. // Regfolder the rule with a destination to a unique TEMP directory
  1381. // Grab a temporary place to copy the mail store
  1382. wsprintf(tmpDir, TEXT("%s\\%03x"), OETEMPDIR, index++);
  1383. ZeroMemory(&actionStruct, sizeof(ACTION_STRUCT));
  1384. actionStruct.ObjectBase = objectEnum.ObjectName;
  1385. actionStruct.AddnlDest = TurnFileStringIntoHandle (
  1386. tmpDir,
  1387. PFF_COMPUTE_BASE|
  1388. PFF_NO_SUBDIR_PATTERN|
  1389. PFF_NO_PATTERNS_ALLOWED|
  1390. PFF_NO_LEAF_AT_ALL
  1391. );
  1392. result = AddRule (g_RegType,
  1393. objectEnum.ObjectName,
  1394. objectEnum.ObjectName,
  1395. ACTIONGROUP_REGFOLDER,
  1396. ACTION_PERSIST_PATH_IN_DATA,
  1397. &actionStruct);
  1398. }
  1399. IsmDestroyObjectString(node);
  1400. if (leaf) {
  1401. IsmDestroyObjectString(leaf);
  1402. }
  1403. } while (IsmEnumNextObject (&objectEnum));
  1404. }
  1405. IsmDestroyObjectHandle (enumPattern);
  1406. }
  1407. return result;
  1408. }
  1409. BOOL
  1410. OEAddComplexRules (
  1411. VOID
  1412. )
  1413. {
  1414. pOE5RemapRules();
  1415. pOE5RemapAccounts();
  1416. pOE5RemapStores();
  1417. return TRUE;
  1418. }
  1419. //////////////////////////////////////////////////////////////////////////////////////
  1420. // OEFixLastUser
  1421. // If for some reason the [Last User ID] value is set to zeroes or does not exist,
  1422. // we'll copy in the [Default User ID] value. If we dont do this, we'll get a popup
  1423. // asking the user to select an identity, which would be really bad.
  1424. BOOL
  1425. OEFixLastUser (
  1426. VOID
  1427. )
  1428. {
  1429. MIG_OBJECTSTRINGHANDLE objectName;
  1430. MIG_CONTENT objectContent;
  1431. MIG_OBJECTSTRINGHANDLE defName;
  1432. MIG_CONTENT defContent;
  1433. BOOL fFix = FALSE;
  1434. if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
  1435. (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT) ||
  1436. IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT))) {
  1437. objectName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"), TEXT("Last User ID"));
  1438. if (objectName) {
  1439. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, objectName, &objectContent)) {
  1440. if (IsValidRegSz(&objectContent) &&
  1441. StringMatch((PCTSTR)objectContent.MemoryContent.ContentBytes,
  1442. TEXT("{00000000-0000-0000-0000-000000000000}"))) {
  1443. fFix = TRUE;
  1444. }
  1445. IsmReleaseObject (&objectContent);
  1446. } else {
  1447. fFix = TRUE;
  1448. }
  1449. if (fFix) {
  1450. defName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"), TEXT("Default User ID"));
  1451. if (defName) {
  1452. if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, defName, &defContent)) {
  1453. if (IsValidRegSz (&defContent)) {
  1454. IsmReplacePhysicalObject (g_RegType, objectName, &defContent);
  1455. }
  1456. IsmReleaseObject (&defContent);
  1457. }
  1458. IsmDestroyObjectHandle (defName);
  1459. }
  1460. }
  1461. IsmDestroyObjectHandle (objectName);
  1462. }
  1463. }
  1464. return TRUE;
  1465. }