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.

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