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
1688 lines
61 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
oe.c
|
|
|
|
Abstract:
|
|
|
|
Implements Outlook Express utilities
|
|
|
|
Author:
|
|
|
|
Jay Thaler (jthaler) 05-Apr-2001
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "v1p.h"
|
|
#include <wab.h>
|
|
#include <sddl.h>
|
|
#include <rpcdce.h>
|
|
#define COBJMACROS
|
|
#include <msoeimp.h>
|
|
|
|
#define DBG_V1 "v1"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
#define OETEMPDIR TEXT("%CSIDL_LOCAL_APPDATA%\\Identities\\USMTTMP")
|
|
#define DEFAULTWAB TEXT("default.wab")
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
#define IF_NULLEND(x) if (NULL==x) { goto end; }
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef IMailImport * (STDMETHODCALLTYPE OECREATE)(
|
|
LPCSTR pszSrcDir
|
|
);
|
|
typedef OECREATE FAR *LPOECREATE;
|
|
|
|
typedef HRESULT (STDMETHODCALLTYPE IMPORTSTORE)(
|
|
IMailImport *pMailImport,
|
|
GUID *pDestUUID,
|
|
LPCSTR pszDestDir
|
|
);
|
|
typedef IMPORTSTORE FAR *LPIMPORTSTORE;
|
|
|
|
typedef HRESULT (STDMETHODCALLTYPE IMPORTNEWS)(
|
|
LPCSTR pszSrcDir,
|
|
GUID *pDestUUID,
|
|
LPCSTR pszDestDir
|
|
);
|
|
typedef IMPORTNEWS FAR *LPIMPORTNEWS;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
PTSTR g_DestAssociatedId = NULL;
|
|
HMODULE g_msoedll = NULL;
|
|
HMODULE g_oemiglib = NULL;
|
|
BOOL g_CoInit = FALSE;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
pUuidFromBracketedString (
|
|
PCTSTR InStr,
|
|
UUID *Uuid
|
|
)
|
|
{
|
|
PTSTR strippedStr = NULL;
|
|
TCHAR *p;
|
|
BOOL retval = FALSE;
|
|
|
|
if (!InStr || !Uuid)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (*InStr == TEXT('{')) {
|
|
strippedStr = DuplicateText(_tcsinc(InStr));
|
|
p = _tcsrchr (strippedStr, TEXT('}'));
|
|
if (p) {
|
|
*p = 0;
|
|
}
|
|
} else {
|
|
strippedStr = DuplicateText(InStr);
|
|
}
|
|
|
|
if (strippedStr) {
|
|
if (RPC_S_OK == UuidFromString(strippedStr, Uuid)) {
|
|
retval = TRUE;
|
|
}
|
|
FreeText(strippedStr);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
pBuildStoreRootKeyForId (
|
|
PCTSTR Identity
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName = NULL;
|
|
PTSTR tmpStr;
|
|
|
|
tmpStr = JoinPathsInPoolEx ((
|
|
NULL,
|
|
TEXT("HKCU\\Identities"),
|
|
Identity,
|
|
TEXT("Software\\Microsoft\\Outlook Express\\5.0"),
|
|
NULL
|
|
));
|
|
|
|
if (tmpStr) {
|
|
objectName = IsmCreateObjectHandle (tmpStr, TEXT("Store Root"));
|
|
FreePathString (tmpStr);
|
|
tmpStr = NULL;
|
|
}
|
|
|
|
return objectName;
|
|
}
|
|
|
|
|
|
PTSTR
|
|
pGetDestStoreRootForId (
|
|
PCTSTR Identity
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_CONTENT objectContent;
|
|
PTSTR retval = NULL;
|
|
PTSTR tmpStr;
|
|
PCTSTR destStore;
|
|
|
|
objectName = pBuildStoreRootKeyForId (Identity);
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
objectName,
|
|
&objectContent)) {
|
|
if (IsValidRegSz(&objectContent)) {
|
|
destStore = IsmExpandEnvironmentString (PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR)objectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
if (destStore) {
|
|
retval = DuplicateText(destStore);
|
|
IsmReleaseMemory(destStore);
|
|
}
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle(objectName);
|
|
|
|
return retval;
|
|
}
|
|
|
|
VOID
|
|
WABMerge (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE filteredName = NULL;
|
|
MIG_OBJECTSTRINGHANDLE objectName = NULL;
|
|
MIG_OBJECTSTRINGHANDLE destObjectName;
|
|
MIG_OBJECTSTRINGHANDLE lpWABObjectName = NULL;
|
|
MIG_CONTENT objectContent;
|
|
PCTSTR srcFile = NULL;
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcLeaf = NULL;
|
|
PTSTR destFile = NULL;
|
|
PCTSTR wabKey = NULL;
|
|
PCTSTR wabPath = NULL;
|
|
PCTSTR destPath;
|
|
HANDLE lib;
|
|
LPWABOPEN lpfnWABOpen = NULL;
|
|
LPWABOBJECT lpWABObject;
|
|
LPADRBOOK lpAdrBookWAB;
|
|
WAB_PARAM wabParams;
|
|
WABIMPORTPARAM wabImportParam;
|
|
HRESULT hr;
|
|
PCTSTR srcIdentity;
|
|
PCTSTR destIdentity;
|
|
PCTSTR destNode;
|
|
PCTSTR defaultWABPath = NULL;
|
|
BOOL fNewOE = FALSE;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
(IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT) ||
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT))) {
|
|
//
|
|
// Get the source WAB filename
|
|
//
|
|
lpWABObjectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\WAB\\WAB4\\Wab File Name"), TEXT(""));
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE,
|
|
lpWABObjectName,
|
|
&objectContent)) {
|
|
if (IsValidRegSz (&objectContent)) {
|
|
objectName = TurnFileStringIntoHandle ((PCTSTR)objectContent.MemoryContent.ContentBytes,
|
|
PFF_NO_PATTERNS_ALLOWED);
|
|
filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
|
|
objectName,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (filteredName) {
|
|
IsmCreateObjectStringsFromHandle (filteredName, &srcNode, &srcLeaf);
|
|
IsmDestroyObjectHandle (filteredName);
|
|
} else {
|
|
IsmCreateObjectStringsFromHandle (objectName, &srcNode, &srcLeaf);
|
|
}
|
|
srcFile = JoinPaths (srcNode, srcLeaf);
|
|
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcLeaf);
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
|
|
//
|
|
// Get the dest WAB filename
|
|
//
|
|
if (srcFile) {
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
lpWABObjectName,
|
|
&objectContent)) {
|
|
if (IsValidRegSz (&objectContent)) {
|
|
destFile = DuplicateText ((PCTSTR)objectContent.MemoryContent.ContentBytes);
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
}
|
|
|
|
if (destFile) {
|
|
// If we are upgrading from an old WAB version, and the destination does not have
|
|
// a new WAB already, then we need to supply a new filename to WABOpen
|
|
|
|
// if srcFile = destFile, then we wrote destFile during migration, which means it
|
|
// didn't exist before. They would not otherwise be equal, because we'd filename
|
|
// collide the wab
|
|
if (StringIMatch (srcFile, destFile)) {
|
|
fNewOE = TRUE;
|
|
|
|
defaultWABPath = GetStringResource (OE_DEFAULT_WAB_PATH);
|
|
if (defaultWABPath) {
|
|
destPath = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
defaultWABPath,
|
|
NULL);
|
|
|
|
FreeStringResource (defaultWABPath);
|
|
}
|
|
|
|
FreeText (destFile);
|
|
destFile = AllocText (TcharCount(destPath) + TcharCount(DEFAULTWAB) + 1);
|
|
StringCopy (destFile, destPath);
|
|
StringCat (destFile, DEFAULTWAB);
|
|
|
|
if StringIMatch (srcFile, destFile) {
|
|
// Crud! Now what?
|
|
// We should name collide the default wab filename in this case, which
|
|
// would mean allocating a bigger destFile
|
|
}
|
|
if (!DoesFileExist (destPath)) {
|
|
BfCreateDirectory (destPath);
|
|
}
|
|
|
|
IsmReleaseMemory (destPath);
|
|
|
|
// Set HKCU\Software\Microsoft\WAB\WAB4\Wab File Name [] = destFile
|
|
ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
|
|
objectContent.ObjectTypeId = g_RegType;
|
|
objectContent.Details.DetailsSize = sizeof(DWORD);
|
|
objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
|
|
*((PDWORD)objectContent.Details.DetailsData) = REG_SZ;
|
|
objectContent.MemoryContent.ContentSize = SizeOfString (destFile);
|
|
objectContent.MemoryContent.ContentBytes = IsmGetMemory (objectContent.MemoryContent.ContentSize);
|
|
CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes,
|
|
destFile,
|
|
objectContent.MemoryContent.ContentSize);
|
|
|
|
objectName = IsmCreateObjectHandle(TEXT("HKCU\\Software\\Microsoft\\WAB\\WAB4\\Wab File Name"),
|
|
TEXT(""));
|
|
if (objectName) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
|
|
IsmReleaseMemory (objectContent.Details.DetailsData);
|
|
}
|
|
}
|
|
|
|
if (destFile) {
|
|
// Get the WAB32.DLL location
|
|
wabKey = JoinPaths (TEXT("HKLM"), WAB_DLL_PATH_KEY);
|
|
objectName = IsmCreateObjectHandle (wabKey, TEXT(""));
|
|
FreePathString (wabKey);
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
objectName,
|
|
&objectContent)) {
|
|
if (IsValidRegSz (&objectContent)) {
|
|
wabPath = DuplicateText ((PCTSTR)objectContent.MemoryContent.ContentBytes);
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
|
|
if (wabPath) {
|
|
// Loadlibrary the DLL
|
|
lib = LoadLibrary (wabPath);
|
|
if (lib) {
|
|
|
|
// Open the destination WAB
|
|
lpfnWABOpen = (LPWABOPEN) GetProcAddress (lib, "WABOpen");
|
|
if (lpfnWABOpen) {
|
|
ZeroMemory (&wabParams, sizeof (WAB_PARAM));
|
|
wabParams.cbSize = sizeof (WAB_PARAM);
|
|
if (!fNewOE) {
|
|
wabParams.ulFlags = WAB_ENABLE_PROFILES | MAPI_UNICODE;
|
|
}
|
|
#ifdef UNICODE
|
|
wabParams.szFileName = (PSTR) ConvertWtoA (destFile);
|
|
#else
|
|
wabParams.szFileName = (PSTR) destFile;
|
|
#endif
|
|
hr = lpfnWABOpen (&lpAdrBookWAB, &lpWABObject, &wabParams, 0);
|
|
#ifdef UNICODE
|
|
FreeConvertedStr (wabParams.szFileName);
|
|
#endif
|
|
if (hr == S_OK) {
|
|
|
|
// Import the source WAB
|
|
ZeroMemory (&wabImportParam, sizeof (WABIMPORTPARAM));
|
|
wabImportParam.cbSize = sizeof (WABIMPORTPARAM);
|
|
wabImportParam.lpAdrBook = lpAdrBookWAB;
|
|
#ifdef UNICODE
|
|
wabImportParam.lpszFileName = (PSTR) ConvertWtoA (srcFile);
|
|
#else
|
|
wabImportParam.lpszFileName = (PSTR) srcFile;
|
|
#endif
|
|
hr = lpWABObject->lpVtbl->Import (lpWABObject, (LPSTR)&wabImportParam);
|
|
#ifdef UNICODE
|
|
FreeConvertedStr (wabImportParam.lpszFileName);
|
|
#endif
|
|
if (hr == S_OK) {
|
|
if (!StringIMatch (srcFile, destFile)) {
|
|
// Delete the source WAB
|
|
DeleteFile (srcFile);
|
|
}
|
|
} else {
|
|
// Log a message that the user must manually import the WAB
|
|
LOG ((LOG_WARNING, (PCSTR) MSG_WAB_MERGE_FAILED, srcFile));
|
|
}
|
|
|
|
lpWABObject->lpVtbl->Release (lpWABObject);
|
|
lpAdrBookWAB->lpVtbl->Release (lpAdrBookWAB);
|
|
}
|
|
}
|
|
FreeLibrary (lib);
|
|
}
|
|
}
|
|
|
|
if (srcFile) {
|
|
FreePathString (srcFile);
|
|
}
|
|
if (destFile) {
|
|
FreeText (destFile);
|
|
}
|
|
if (wabPath) {
|
|
FreeText (wabPath);
|
|
}
|
|
if (lpWABObjectName) {
|
|
IsmDestroyObjectHandle (lpWABObjectName);
|
|
}
|
|
}
|
|
}
|
|
|
|
PCTSTR
|
|
pBuildDefaultStoreRoot (
|
|
IN PCTSTR Guid,
|
|
IN BOOL GuidHasBrackets
|
|
)
|
|
{
|
|
PTSTR storeRoot = NULL;
|
|
PCTSTR storeBegin = NULL;
|
|
UINT charCount;
|
|
|
|
// output should be "%UserProfile%\Local Settings\Application Data\Identities\{guid}\Microsoft\Outlook Express"
|
|
|
|
#define STOREEND TEXT("\\Microsoft\\Outlook Express")
|
|
|
|
storeBegin = GetStringResource (OE_DEFAULT_ID_PATH);
|
|
if (storeBegin) {
|
|
storeRoot = AllocText(TcharCount(storeBegin) +
|
|
TcharCount(Guid) +
|
|
TcharCount(STOREEND) +
|
|
(GuidHasBrackets ? 1 : 3));
|
|
if (!storeRoot) {
|
|
// Out of memory?
|
|
return NULL;
|
|
}
|
|
StringCopy (storeRoot, storeBegin);
|
|
FreeStringResource (storeBegin);
|
|
}
|
|
if (FALSE == GuidHasBrackets) {
|
|
StringCat (storeRoot, TEXT("{"));
|
|
}
|
|
StringCat (storeRoot, Guid);
|
|
if (FALSE == GuidHasBrackets) {
|
|
StringCat (storeRoot, TEXT("}"));
|
|
}
|
|
StringCat (storeRoot, STOREEND);
|
|
|
|
return storeRoot;
|
|
}
|
|
|
|
BOOL
|
|
pOE5Import (
|
|
IN PCTSTR SourceDir,
|
|
IN PCTSTR DestDir,
|
|
IN PCTSTR DestIdentity
|
|
)
|
|
{
|
|
UUID uid;
|
|
BOOL result = FALSE;
|
|
PSTR szSrcPath;
|
|
PSTR szDestPath;
|
|
|
|
MIG_CONTENT dllObjectContent;
|
|
MIG_OBJECTSTRINGHANDLE dllObjectName = NULL;
|
|
PCTSTR dllExpPath = NULL;
|
|
PTSTR dllTmpPath = NULL;
|
|
IMailImport *mailImport = NULL;
|
|
static LPOECREATE lpfnOE5SimpleCreate = NULL;
|
|
static LPIMPORTSTORE lpfnImportMailStoreToGUID = NULL;
|
|
static LPIMPORTNEWS lpfnImportNewsListToGUID = NULL;
|
|
|
|
if (g_msoedll == NULL) {
|
|
CoInitialize(NULL);
|
|
g_CoInit = TRUE;
|
|
|
|
dllObjectName = IsmCreateObjectHandle (TEXT("HKLM\\Software\\Microsoft\\Outlook Express"),
|
|
TEXT("InstallRoot"));
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
dllObjectName,
|
|
&dllObjectContent)) {
|
|
// dllObjectContent should be "%ProgramFiles%\\Outlook Express"
|
|
|
|
if (IsValidRegSz (&dllObjectContent)) {
|
|
dllExpPath = IsmExpandEnvironmentString(PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR)dllObjectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
}
|
|
if (dllExpPath) {
|
|
|
|
dllTmpPath = JoinPaths (dllExpPath, TEXT("oemiglib.dll"));
|
|
if (dllTmpPath) {
|
|
g_oemiglib = LoadLibrary(dllTmpPath);
|
|
FreePathString (dllTmpPath);
|
|
}
|
|
|
|
dllTmpPath = JoinPaths (dllExpPath, TEXT("msoe.dll"));
|
|
if (dllTmpPath) {
|
|
g_msoedll = LoadLibrary(dllTmpPath);
|
|
FreePathString (dllTmpPath);
|
|
}
|
|
|
|
IsmReleaseMemory (dllExpPath);
|
|
}
|
|
IsmReleaseObject (&dllObjectContent);
|
|
}
|
|
IsmDestroyObjectHandle (dllObjectName);
|
|
|
|
if (g_msoedll && g_oemiglib) {
|
|
lpfnOE5SimpleCreate = (LPOECREATE) GetProcAddress (g_oemiglib, "OE5SimpleCreate");
|
|
lpfnImportMailStoreToGUID = (LPIMPORTSTORE) GetProcAddress (g_msoedll, "ImportMailStoreToGUID");
|
|
lpfnImportNewsListToGUID = (LPIMPORTNEWS) GetProcAddress (g_msoedll, "ImportNewsListToGUID");
|
|
}
|
|
}
|
|
|
|
if (DestDir) {
|
|
if (lpfnOE5SimpleCreate &&
|
|
lpfnImportMailStoreToGUID &&
|
|
lpfnImportNewsListToGUID) {
|
|
|
|
// Convert to GUID *
|
|
if (pUuidFromBracketedString(DestIdentity, &uid)) {
|
|
#ifdef UNICODE
|
|
szSrcPath = (PSTR) ConvertWtoA (SourceDir);
|
|
szDestPath = (PSTR) ConvertWtoA (DestDir);
|
|
#else
|
|
szSrcPath = (PSTR) SourceDir;
|
|
szDestPath = (PSTR) DestDir;
|
|
#endif
|
|
mailImport = lpfnOE5SimpleCreate(szSrcPath);
|
|
|
|
if (mailImport) {
|
|
lpfnImportMailStoreToGUID(mailImport, &uid, szDestPath);
|
|
IMailImport_Release(mailImport);
|
|
mailImport = NULL;
|
|
result = TRUE;
|
|
}
|
|
|
|
lpfnImportNewsListToGUID (szSrcPath, &uid, szDestPath);
|
|
#ifdef UNICODE
|
|
FreeConvertedStr (szSrcPath);
|
|
FreeConvertedStr (szDestPath);
|
|
#endif
|
|
}
|
|
}
|
|
if (SourceDir && DestDir) {
|
|
// Copy source folder to dest folder, but never overwrite
|
|
if (!DoesFileExist (DestDir)) {
|
|
BfCreateDirectory (DestDir);
|
|
}
|
|
FiCopyAllFilesInTreeEx(SourceDir, DestDir, TRUE);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// OE5MergeStorefolders
|
|
// This cycles through every store folder and decides whether to just copy it to the
|
|
// destination or merge into an existing store folder in the destination
|
|
VOID
|
|
OE5MergeStoreFolders (
|
|
VOID
|
|
)
|
|
{
|
|
TCHAR szGuid[37];
|
|
MIG_OBJECTSTRINGHANDLE objectName = NULL;
|
|
MIG_OBJECTSTRINGHANDLE filteredName = NULL;
|
|
MIG_CONTENT objectContent;
|
|
MIG_CONTENT destObjectContent;
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
MIG_OBJECTSTRINGHANDLE enumPattern;
|
|
PTSTR srcStoreRoot = NULL;
|
|
PCTSTR destStoreRoot = NULL;
|
|
PCTSTR destFolderFile = NULL;
|
|
PTSTR node;
|
|
PTSTR leaf;
|
|
PTSTR junk;
|
|
PCTSTR expandedName = NULL;
|
|
BOOL fImport;
|
|
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
|
|
|
|
// Enumerate each source Store Folder
|
|
enumPattern = IsmCreateSimpleObjectPattern (
|
|
TEXT("HKCU\\Identities"),
|
|
TRUE,
|
|
TEXT("Store Root"),
|
|
FALSE);
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
|
|
do {
|
|
fImport = FALSE;
|
|
|
|
IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
|
|
if (leaf && *leaf) {
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE, objectEnum.ObjectName, &objectContent)) {
|
|
if (IsValidRegSz (&objectContent)) {
|
|
expandedName = IsmExpandEnvironmentString (
|
|
PLATFORM_SOURCE,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR)objectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
}
|
|
if (expandedName) {
|
|
objectName = IsmCreateObjectHandle(expandedName, NULL);
|
|
IsmReleaseMemory (expandedName);
|
|
expandedName = NULL;
|
|
}
|
|
|
|
if (objectName) {
|
|
filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
|
|
objectName,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (filteredName) {
|
|
IsmCreateObjectStringsFromHandle (filteredName, &srcStoreRoot, &junk);
|
|
// srcStoreRoot is now the source directory
|
|
|
|
IsmDestroyObjectHandle (filteredName);
|
|
filteredName = NULL;
|
|
} else {
|
|
IsmCreateObjectStringsFromHandle(objectName, &srcStoreRoot, &junk);
|
|
}
|
|
|
|
if (junk) {
|
|
IsmDestroyObjectString (junk);
|
|
junk = NULL;
|
|
}
|
|
|
|
IsmDestroyObjectHandle (objectName);
|
|
objectName = NULL;
|
|
}
|
|
|
|
// Now check to see if the dest Store Root previously existed
|
|
if (srcStoreRoot) {
|
|
filteredName = IsmFilterObject (g_RegType | PLATFORM_SOURCE,
|
|
objectEnum.ObjectName,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
// Extract GUID out of destination object name
|
|
_stscanf(filteredName ? filteredName : objectEnum.ObjectName,
|
|
TEXT("%*[^{]{%[^}]"),
|
|
szGuid);
|
|
// szGuid is now the destination identity guid, minus the {}
|
|
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
filteredName ? filteredName : objectEnum.ObjectName,
|
|
&destObjectContent)) {
|
|
if (IsValidRegSz (&destObjectContent)) {
|
|
destStoreRoot = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR)destObjectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
}
|
|
if (destStoreRoot) {
|
|
destFolderFile = JoinPaths(destStoreRoot, TEXT("folders.dbx"));
|
|
}
|
|
if (destFolderFile) {
|
|
if ((!StringIMatch(srcStoreRoot, destStoreRoot)) &&
|
|
(DoesFileExist(destFolderFile))) {
|
|
fImport = TRUE;
|
|
}
|
|
FreePathString(destFolderFile);
|
|
}
|
|
IsmReleaseObject (&destObjectContent);
|
|
}
|
|
}
|
|
|
|
if (szGuid[0]) {
|
|
if (!fImport) {
|
|
// This is a FIRST migration, so set the dest store root to default
|
|
IsmReleaseMemory(destStoreRoot);
|
|
destStoreRoot = pBuildDefaultStoreRoot(szGuid, FALSE);
|
|
|
|
// Set [StoreRoot] = destStoreRoot
|
|
ZeroMemory (&destObjectContent, sizeof(MIG_CONTENT));
|
|
destObjectContent.ObjectTypeId = g_RegType;
|
|
destObjectContent.Details.DetailsSize = sizeof(DWORD);
|
|
destObjectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
|
|
*((PDWORD)destObjectContent.Details.DetailsData) = REG_EXPAND_SZ;
|
|
destObjectContent.MemoryContent.ContentSize = SizeOfString (destStoreRoot);
|
|
destObjectContent.MemoryContent.ContentBytes = (PBYTE)destStoreRoot;
|
|
|
|
IsmReplacePhysicalObject (g_RegType,
|
|
filteredName ? filteredName : objectEnum.ObjectName,
|
|
&destObjectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
|
|
// expand environment on destStoreRoot
|
|
FreeText(destStoreRoot);
|
|
|
|
destStoreRoot = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR)destObjectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
|
|
// Cleanup the objectContent we allocated
|
|
IsmReleaseMemory (destObjectContent.Details.DetailsData);
|
|
}
|
|
|
|
if (srcStoreRoot && destStoreRoot) {
|
|
if (!DoesFileExist (destStoreRoot)) {
|
|
BfCreateDirectory (destStoreRoot);
|
|
}
|
|
pOE5Import(srcStoreRoot, destStoreRoot, szGuid);
|
|
}
|
|
}
|
|
|
|
|
|
if (filteredName) {
|
|
IsmDestroyObjectHandle(filteredName);
|
|
filteredName = NULL;
|
|
}
|
|
|
|
if (destStoreRoot) {
|
|
IsmReleaseMemory(destStoreRoot);
|
|
destStoreRoot = NULL;
|
|
}
|
|
|
|
if (srcStoreRoot) {
|
|
IsmDestroyObjectString (srcStoreRoot);
|
|
srcStoreRoot = NULL;
|
|
}
|
|
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
}
|
|
IsmDestroyObjectString (node);
|
|
IsmDestroyObjectString (leaf);
|
|
} while (IsmEnumNextObject (&objectEnum));
|
|
|
|
// Remove temp folder
|
|
expandedName = IsmExpandEnvironmentString (PLATFORM_DESTINATION, S_SYSENVVAR_GROUP, OETEMPDIR, NULL);
|
|
if (expandedName) {
|
|
FiRemoveAllFilesInTree (expandedName);
|
|
IsmReleaseMemory (expandedName);
|
|
} else {
|
|
FiRemoveAllFilesInTree (OETEMPDIR);
|
|
}
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
OE4MergeStoreFolder (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE regKey;
|
|
MIG_OBJECTSTRINGHANDLE objectName = NULL;
|
|
MIG_OBJECTSTRINGHANDLE filteredName;
|
|
MIG_CONTENT objectContent;
|
|
HANDLE h;
|
|
PCTSTR srcStorePath = NULL;
|
|
PCTSTR expPath = NULL;
|
|
PTSTR destIdentity = NULL;
|
|
PTSTR tmpStr = NULL;
|
|
PTSTR tmpNode = NULL;
|
|
PTSTR cmdLine = NULL;
|
|
PCTSTR sid = NULL;
|
|
DWORD exitCode;
|
|
DWORD cmdLen;
|
|
TCHAR tmpDir[MAX_PATH];
|
|
PCTSTR destDir = NULL;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT)) {
|
|
|
|
objectName = IsmCreateObjectHandle (TEXT("HKLM\\Software\\Microsoft\\Outlook Express"),
|
|
TEXT("InstallRoot"));
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION,
|
|
objectName,
|
|
&objectContent)) {
|
|
|
|
// objectContent should be "%ProgramFiles%\\Outlook Express"
|
|
|
|
if (IsValidRegSz (&objectContent)) {
|
|
tmpStr = JoinPaths (objectContent.MemoryContent.ContentBytes, TEXT("oemig50.exe"));
|
|
|
|
// tmpStr should be "%ProgramFiles%\\OutlookExpress\\oemig50.exe"
|
|
expPath = IsmExpandEnvironmentString (PLATFORM_DESTINATION, S_SYSENVVAR_GROUP, tmpStr, NULL);
|
|
|
|
FreePathString (tmpStr);
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
|
|
// Get the dest identity
|
|
if (expPath) {
|
|
destIdentity = OEGetDefaultId (PLATFORM_DESTINATION);
|
|
}
|
|
|
|
// Now get the source's Store Root
|
|
if (destIdentity) {
|
|
objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Outlook Express"),
|
|
TEXT("Store Root"));
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_SOURCE,
|
|
objectName,
|
|
&objectContent)) {
|
|
if (IsValidRegSz (&objectContent)) {
|
|
IsmDestroyObjectHandle (objectName);
|
|
objectName = IsmCreateObjectHandle ((PCTSTR) objectContent.MemoryContent.ContentBytes,
|
|
NULL);
|
|
filteredName = IsmFilterObject (g_FileType | PLATFORM_SOURCE,
|
|
objectName,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (filteredName) {
|
|
IsmCreateObjectStringsFromHandle (filteredName, &srcStorePath, NULL);
|
|
IsmDestroyObjectHandle (filteredName);
|
|
} else {
|
|
IsmCreateObjectStringsFromHandle (objectName, &srcStorePath, NULL);
|
|
}
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
|
|
// Now grab a temporary place to stuff the upgraded files
|
|
IsmGetTempDirectory(tmpDir, ARRAYSIZE(tmpDir));
|
|
|
|
// Call the external upgrade exe
|
|
if (srcStorePath != NULL &&
|
|
expPath != NULL) {
|
|
|
|
|
|
sid = IsmGetCurrentSidString();
|
|
|
|
cmdLen = TcharCount(expPath) + TcharCount(srcStorePath) + TcharCount(tmpDir) + 35;
|
|
if (sid) {
|
|
cmdLen += TcharCount(sid) + 6;
|
|
}
|
|
cmdLine = AllocText (cmdLen);
|
|
StringCopy (cmdLine, expPath);
|
|
StringCat (cmdLine, TEXT(" /type:V1+V4-V5 /src:")); // 21
|
|
StringCat (cmdLine, srcStorePath);
|
|
StringCat (cmdLine, TEXT(" /dst:")); // 6
|
|
StringCat (cmdLine, tmpDir);
|
|
StringCat (cmdLine, TEXT(" /quiet")); // 7
|
|
if (sid) {
|
|
StringCat (cmdLine, TEXT(" /key:")); // (6)
|
|
StringCat (cmdLine, sid);
|
|
}
|
|
|
|
LOG ((LOG_INFORMATION, (PCSTR) MSG_SPAWNING_PROCESS_INFO, cmdLine));
|
|
|
|
h = StartProcess (cmdLine);
|
|
if (h != NULL) {
|
|
WaitForSingleObject (h, INFINITE);
|
|
if (GetExitCodeProcess (h, &exitCode)) {
|
|
if ((exitCode != STILL_ACTIVE) && ((exitCode & 0xFFFF) != 800 )) {
|
|
LOG ((LOG_ERROR, (PCSTR)MSG_OE4_UPGRADE_FAILED));
|
|
}
|
|
}
|
|
CloseHandle (h);
|
|
|
|
FreeText (cmdLine);
|
|
|
|
// Cleanup the source store
|
|
FiRemoveAllFilesInTree (srcStorePath);
|
|
}
|
|
|
|
destDir = pGetDestStoreRootForId(destIdentity);
|
|
if (destDir) {
|
|
if (!DoesFileExist (destDir)) {
|
|
// Just copy into to the dest dir
|
|
BfCreateDirectory (destDir);
|
|
FiCopyAllFilesInTreeEx(tmpDir, destDir, TRUE);
|
|
} else {
|
|
// Now do an OE5 Import from tmpDir to destIdentity
|
|
pOE5Import(tmpDir, destDir, destIdentity);
|
|
}
|
|
FreeText(destDir);
|
|
}
|
|
FiRemoveAllFilesInTree (tmpDir);
|
|
|
|
// Set [StoreMigratedV5] = 1
|
|
// Set [ConvertedToDBX] = 1
|
|
tmpStr = JoinText(TEXT("HKCU\\Identities\\"), destIdentity);
|
|
if (tmpStr) {
|
|
tmpNode = JoinText(tmpStr, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0"));
|
|
if (tmpNode) {
|
|
CreateDwordRegObject (tmpNode, TEXT("StoreMigratedV5"), 1);
|
|
CreateDwordRegObject (tmpNode, TEXT("ConvertedToDBX"), 1);
|
|
FreeText(tmpNode);
|
|
}
|
|
|
|
FreeText(tmpStr);
|
|
}
|
|
}
|
|
|
|
if (destIdentity) {
|
|
FreeText(destIdentity);
|
|
}
|
|
if (sid) {
|
|
IsmReleaseMemory (sid);
|
|
}
|
|
if (expPath) {
|
|
IsmReleaseMemory (expPath);
|
|
}
|
|
if (srcStorePath) {
|
|
IsmDestroyObjectString (srcStorePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
OEIAMAssociateId (
|
|
IN PTSTR SrcId
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_OBJECTTYPEID objectTypeId;
|
|
MIG_CONTENT objectContent;
|
|
PTSTR srcStr;
|
|
TCHAR *p;
|
|
UUID srcUUID;
|
|
RPC_STATUS status;
|
|
BOOL retval = FALSE;
|
|
DWORD regType = REG_BINARY;
|
|
|
|
if (pUuidFromBracketedString (SrcId, &srcUUID)) {
|
|
// Create [AssociatedID] = Uuid
|
|
|
|
objectTypeId = g_RegType | PLATFORM_DESTINATION;
|
|
|
|
ZeroMemory(&objectContent, sizeof(MIG_CONTENT));
|
|
|
|
objectContent.ContentInFile = FALSE;
|
|
objectContent.MemoryContent.ContentSize = sizeof(UUID);
|
|
objectContent.MemoryContent.ContentBytes = IsmGetMemory(sizeof(UUID));
|
|
CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes, &srcUUID, sizeof(UUID));
|
|
objectContent.Details.DetailsData = ®Type;
|
|
|
|
objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Internet Account Manager\\Accounts"),
|
|
TEXT("AssociatedID"));
|
|
if (objectName) {
|
|
retval = IsmReplacePhysicalObject (objectTypeId, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
g_DestAssociatedId = DuplicateText(SrcId);
|
|
}
|
|
|
|
IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
BOOL
|
|
OEIsIdentityAssociated (
|
|
IN PTSTR IdStr
|
|
)
|
|
{
|
|
BOOL associated = FALSE;
|
|
|
|
if (!g_DestAssociatedId) {
|
|
g_DestAssociatedId = OEGetAssociatedId(PLATFORM_DESTINATION);
|
|
}
|
|
|
|
if (g_DestAssociatedId) {
|
|
associated = StringIMatch(IdStr, g_DestAssociatedId);
|
|
} else {
|
|
// Apparently there is no associated ID. Let's claim it.
|
|
OEIAMAssociateId(IdStr);
|
|
associated = TRUE;
|
|
}
|
|
return associated;
|
|
}
|
|
|
|
PTSTR
|
|
OEGetRemappedId(
|
|
IN PCTSTR IdStr
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_OBJECTSTRINGHANDLE filteredName;
|
|
PTSTR tmpName;
|
|
PTSTR node;
|
|
PTSTR leaf;
|
|
PTSTR result = NULL;
|
|
TCHAR *p;
|
|
|
|
tmpName = JoinText(TEXT("HKCU\\Identities\\"), IdStr);
|
|
if (tmpName) {
|
|
objectName = IsmCreateObjectHandle(tmpName, NULL);
|
|
if (objectName) {
|
|
filteredName = IsmFilterObject(g_RegType | PLATFORM_SOURCE,
|
|
objectName,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (filteredName) {
|
|
IsmCreateObjectStringsFromHandle (filteredName, &node, &leaf);
|
|
if (node) {
|
|
p = (PTSTR)FindLastWack(node);
|
|
if (p) {
|
|
result = DuplicateText(_tcsinc(p));
|
|
}
|
|
IsmDestroyObjectString(node);
|
|
}
|
|
if (leaf) {
|
|
IsmDestroyObjectString (leaf);
|
|
}
|
|
IsmDestroyObjectHandle(filteredName);
|
|
} else {
|
|
result = DuplicateText(IdStr);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
FreeText(tmpName);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PTSTR
|
|
OEGetDefaultId (
|
|
IN MIG_PLATFORMTYPEID Platform
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_CONTENT objectContent;
|
|
PTSTR retval = NULL;
|
|
|
|
|
|
objectName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"),
|
|
TEXT("Default User ID"));
|
|
if (objectName) {
|
|
if (IsmAcquireObject ( g_RegType | Platform, objectName, &objectContent)) {
|
|
if (IsValidRegSz(&objectContent)) {
|
|
retval = DuplicateText((PTSTR)objectContent.MemoryContent.ContentBytes);
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
PTSTR
|
|
OEGetAssociatedId (
|
|
IN MIG_PLATFORMTYPEID Platform
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_CONTENT objectContent;
|
|
PTSTR uuidStr;
|
|
PTSTR retval = NULL;
|
|
|
|
objectName = IsmCreateObjectHandle (TEXT("HKCU\\Software\\Microsoft\\Internet Account Manager\\Accounts"),
|
|
TEXT("AssociatedID"));
|
|
if (objectName) {
|
|
if (IsmAcquireObject ( g_RegType | Platform, objectName, &objectContent)) {
|
|
if (IsValidRegType(&objectContent, REG_BINARY)) {
|
|
if (RPC_S_OK == UuidToString ((UUID *)objectContent.MemoryContent.ContentBytes, &uuidStr)) {
|
|
retval = AllocText(CharCount(uuidStr) + 3);
|
|
if (retval) {
|
|
StringCopy(retval, TEXT("{"));
|
|
StringCat(retval, uuidStr);
|
|
StringCat(retval, TEXT("}"));
|
|
}
|
|
RpcStringFree(&uuidStr);
|
|
}
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
VOID
|
|
OETerminate (
|
|
VOID
|
|
)
|
|
{
|
|
if (g_DestAssociatedId) {
|
|
FreeText(g_DestAssociatedId);
|
|
}
|
|
if (g_msoedll) {
|
|
FreeLibrary(g_msoedll);
|
|
g_msoedll = NULL;
|
|
}
|
|
if (g_oemiglib) {
|
|
FreeLibrary(g_oemiglib);
|
|
g_oemiglib = NULL;
|
|
}
|
|
if (g_CoInit) {
|
|
CoUninitialize();
|
|
g_CoInit = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
pRenameRegTreePattern (
|
|
IN MIG_OBJECTSTRINGHANDLE Pattern,
|
|
IN PCMIG_BLOB SrcBlob,
|
|
IN PCMIG_BLOB DestBlob,
|
|
IN BOOL ReplaceOld
|
|
)
|
|
{
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, Pattern)) {
|
|
if (!g_RenameOp) {
|
|
g_RenameOp = IsmRegisterOperation (S_OPERATION_MOVE, FALSE);
|
|
}
|
|
|
|
do {
|
|
// Set operation on all source objects in this ID
|
|
if (ReplaceOld) {
|
|
IsmClearOperationOnObject(g_RegType | PLATFORM_SOURCE,
|
|
objectEnum.ObjectName,
|
|
g_RenameOp);
|
|
}
|
|
IsmSetOperationOnObject(g_RegType | PLATFORM_SOURCE,
|
|
objectEnum.ObjectName,
|
|
g_RenameOp,
|
|
SrcBlob,
|
|
DestBlob);
|
|
} while (IsmEnumNextObject(&objectEnum));
|
|
}
|
|
}
|
|
|
|
pRenameRegTree (
|
|
IN PCTSTR SrcIdName,
|
|
IN PCTSTR DestIdName,
|
|
IN BOOL ReplaceOld
|
|
)
|
|
{
|
|
MIG_BLOB srcBlob;
|
|
MIG_BLOB destBlob;
|
|
MIG_OBJECTSTRINGHANDLE pattern;
|
|
|
|
|
|
srcBlob.Type = BLOBTYPE_STRING;
|
|
srcBlob.String = IsmCreateObjectHandle(SrcIdName, NULL);
|
|
if (srcBlob.String) {
|
|
destBlob.Type = BLOBTYPE_STRING;
|
|
destBlob.String = IsmCreateObjectHandle(DestIdName, NULL);
|
|
if (destBlob.String) {
|
|
|
|
// Recursive
|
|
pattern = IsmCreateSimpleObjectPattern(SrcIdName, TRUE, NULL, TRUE);
|
|
if (pattern) {
|
|
pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
|
|
IsmDestroyObjectHandle(pattern);
|
|
}
|
|
|
|
// Now for the node's values
|
|
pattern = IsmCreateSimpleObjectPattern(SrcIdName, FALSE, NULL, TRUE);
|
|
if (pattern) {
|
|
pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
|
|
IsmDestroyObjectHandle(pattern);
|
|
}
|
|
|
|
// Now for only the node itself
|
|
pattern = IsmCreateSimpleObjectPattern(SrcIdName, FALSE, NULL, FALSE);
|
|
if (pattern) {
|
|
pRenameRegTreePattern(pattern, &srcBlob, &destBlob, ReplaceOld);
|
|
IsmDestroyObjectHandle(pattern);
|
|
}
|
|
IsmDestroyObjectHandle(destBlob.String);
|
|
}
|
|
IsmDestroyObjectHandle(srcBlob.String);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
pClearApply (
|
|
IN PCTSTR Node,
|
|
IN PCTSTR Leaf
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
BOOL result = FALSE;
|
|
|
|
objectName = IsmCreateObjectHandle(Node, Leaf);
|
|
if (objectName) {
|
|
IsmClearApplyOnObject((g_RegType & (~PLATFORM_MASK)) | PLATFORM_SOURCE, objectName);
|
|
IsmDestroyObjectHandle (objectName);
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
OE5RemapDefaultId (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE destObjectName;
|
|
MIG_OBJECTSTRINGHANDLE pattern;
|
|
MIG_CONTENT destIdObjectContent;
|
|
PTSTR idName;
|
|
PTSTR destIdName;
|
|
PTSTR srcDefaultId;
|
|
PTSTR destDefaultId;
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
|
|
|
|
srcDefaultId = OEGetDefaultId(PLATFORM_SOURCE);
|
|
if (srcDefaultId) {
|
|
destDefaultId = OEGetDefaultId(PLATFORM_DESTINATION);
|
|
if (destDefaultId) {
|
|
if (!StringIMatch (srcDefaultId, destDefaultId)) {
|
|
// different default IDs
|
|
idName = JoinText(TEXT("HKCU\\Identities\\"), srcDefaultId);
|
|
if (idName) {
|
|
destObjectName = IsmCreateObjectHandle(idName, NULL);
|
|
if (IsmAcquireObject(
|
|
g_RegType | PLATFORM_DESTINATION,
|
|
destObjectName,
|
|
&destIdObjectContent)) {
|
|
|
|
// The source ID already exists on the dest.. do nothing extra
|
|
IsmReleaseObject(&destIdObjectContent);
|
|
} else {
|
|
// Remap this identity into destination default
|
|
destIdName = JoinText(TEXT("HKCU\\Identities\\"),
|
|
destDefaultId);
|
|
if (destIdName) {
|
|
pRenameRegTree(idName, destIdName, TRUE);
|
|
FreeText(destIdName);
|
|
}
|
|
pClearApply(TEXT("HKCU\\Identities"), TEXT("Default User ID"));
|
|
pClearApply(TEXT("HKCU\\Identities"), TEXT("Last User ID"));
|
|
pClearApply(TEXT("HKCU\\Identities"), TEXT("Last Username"));
|
|
|
|
// ForceDestReg the top level Identities values
|
|
pattern = IsmCreateSimpleObjectPattern(idName, FALSE, NULL, TRUE);
|
|
if (pattern) {
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, pattern)) {
|
|
do {
|
|
IsmClearApplyOnObject(
|
|
(g_RegType & (~PLATFORM_MASK)) | PLATFORM_SOURCE,
|
|
objectEnum.ObjectName);
|
|
} while (IsmEnumNextObject(&objectEnum));
|
|
}
|
|
IsmDestroyObjectHandle(pattern);
|
|
}
|
|
}
|
|
IsmDestroyObjectHandle(destObjectName);
|
|
FreeText(idName);
|
|
}
|
|
}
|
|
FreeText(destDefaultId);
|
|
}
|
|
FreeText(srcDefaultId);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// pOE5RemapRules
|
|
// This adds a renregfn rule for \ConvertOE5MailRules to
|
|
// HKCU\Identities\{*}\Software\Microsoft\Outlook Express\5.0\Rules\Mail\*
|
|
// ditto for News rules
|
|
// Also for Block Senders\Mail\Criteria\* and News
|
|
BOOL
|
|
pOE5RemapRules (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
MIG_OBJECTSTRINGHANDLE enumPattern;
|
|
MIG_OBJECTSTRINGHANDLE subPattern;
|
|
PTSTR tmpNode;
|
|
PTSTR node;
|
|
PTSTR leaf;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
|
|
|
|
// Find HKCU\Identities\{*}\Software\Microsoft\Outlook Express\5.0\Rules\Mail\*
|
|
// First enum each identity
|
|
enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
|
|
TEXT("User ID"), FALSE);
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
|
|
do {
|
|
IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
|
|
if (node && leaf) {
|
|
// Enum the Rules keys under this identity
|
|
tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Rules\\Mail"));
|
|
if (tmpNode) {
|
|
subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
|
|
if (subPattern) {
|
|
AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5MailRules"));
|
|
IsmDestroyObjectHandle(subPattern);
|
|
}
|
|
FreeText(tmpNode);
|
|
}
|
|
tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Rules\\News"));
|
|
if (tmpNode) {
|
|
subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
|
|
if (subPattern) {
|
|
AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5NewsRules"));
|
|
IsmDestroyObjectHandle(subPattern);
|
|
}
|
|
FreeText(tmpNode);
|
|
}
|
|
tmpNode = JoinText(
|
|
node,
|
|
TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Block Senders\\Mail\\Criteria")
|
|
);
|
|
if (tmpNode) {
|
|
subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
|
|
if (subPattern) {
|
|
AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5Block"));
|
|
IsmDestroyObjectHandle(subPattern);
|
|
}
|
|
FreeText(tmpNode);
|
|
}
|
|
tmpNode = JoinText(
|
|
node,
|
|
TEXT("\\Software\\Microsoft\\Outlook Express\\5.0\\Block Senders\\News\\Criteria")
|
|
);
|
|
if (tmpNode) {
|
|
subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
|
|
if (subPattern) {
|
|
AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5Block"));
|
|
IsmDestroyObjectHandle(subPattern);
|
|
}
|
|
FreeText(tmpNode);
|
|
}
|
|
}
|
|
IsmDestroyObjectString(node);
|
|
if (leaf) {
|
|
IsmDestroyObjectString(leaf);
|
|
}
|
|
} while (IsmEnumNextObject (&objectEnum));
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// pOE5RemapAccounts
|
|
// This adds a renregfn rule for \ConvertOE5IdIAM to
|
|
// HKCU\Identities\{*}\Software\Microsoft\Internet Account Manager\*
|
|
BOOL
|
|
pOE5RemapAccounts (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
MIG_OBJECTSTRINGHANDLE enumPattern;
|
|
MIG_OBJECTSTRINGHANDLE subPattern;
|
|
PTSTR tmpNode;
|
|
PTSTR node;
|
|
PTSTR leaf;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
|
|
|
|
// Find HKCU\Identities\{*}\Software\Microsoft\Internet Account Manger\*
|
|
// First enum each identity
|
|
enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
|
|
TEXT("User ID"), FALSE);
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
|
|
do {
|
|
IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
|
|
if (node && leaf) {
|
|
// Enum the IAM keys under this identity
|
|
tmpNode = JoinText(node, TEXT("\\Software\\Microsoft\\Internet Account Manager"));
|
|
if (tmpNode) {
|
|
subPattern = IsmCreateSimpleObjectPattern (tmpNode, TRUE, NULL, TRUE);
|
|
if (subPattern) {
|
|
AddSpecialRenameRule (subPattern, TEXT("\\ConvertOE5IdIAM"));
|
|
IsmDestroyObjectHandle(subPattern);
|
|
}
|
|
FreeText(tmpNode);
|
|
}
|
|
}
|
|
IsmDestroyObjectString(node);
|
|
if (leaf) {
|
|
IsmDestroyObjectString(leaf);
|
|
}
|
|
} while (IsmEnumNextObject (&objectEnum));
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// OECreateFirstIdentity
|
|
// This is used to create the very first identity for a user that we just created
|
|
PTSTR
|
|
OECreateFirstIdentity (
|
|
VOID
|
|
)
|
|
{
|
|
PTSTR destID = NULL;
|
|
PTSTR uuidStr;
|
|
UUID uuid;
|
|
RPC_STATUS result;
|
|
MIG_OBJECTSTRINGHANDLE objectName = NULL;
|
|
MIG_CONTENT objectContent;
|
|
PTSTR node;
|
|
PCTSTR defaultStore;
|
|
|
|
result = UuidCreate (&uuid);
|
|
if (result == RPC_S_OK || result == RPC_S_UUID_LOCAL_ONLY) {
|
|
result = UuidToString (&uuid, &uuidStr);
|
|
if (result == RPC_S_OK) {
|
|
destID = AllocText (CharCount (uuidStr) + 3);
|
|
wsprintf (destID, TEXT("{%s}"), uuidStr);
|
|
RpcStringFree (&uuidStr);
|
|
}
|
|
}
|
|
if (destID) {
|
|
// Create [Default User ID] = &destID
|
|
ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
|
|
objectContent.ObjectTypeId = g_RegType;
|
|
objectContent.Details.DetailsSize = sizeof(DWORD);
|
|
objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
|
|
*((PDWORD)objectContent.Details.DetailsData) = REG_SZ;
|
|
objectContent.MemoryContent.ContentSize = SizeOfString (destID);
|
|
objectContent.MemoryContent.ContentBytes = IsmGetMemory (objectContent.MemoryContent.ContentSize);
|
|
CopyMemory ((PVOID)objectContent.MemoryContent.ContentBytes, destID, objectContent.MemoryContent.ContentSize);
|
|
|
|
objectName = IsmCreateObjectHandle(TEXT("HKCU\\Identities"), TEXT("Default User ID"));
|
|
if (objectName) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
objectName = NULL;
|
|
}
|
|
|
|
// Set [Last User ID] = &destID
|
|
objectName = IsmCreateObjectHandle(TEXT("HKCU\\Identities"), TEXT("Last User ID"));
|
|
if (objectName) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
objectName = NULL;
|
|
}
|
|
// Create [User ID] = &destID
|
|
node = JoinPaths (TEXT("HKCU\\Identities"), destID);
|
|
if (node) {
|
|
objectName = IsmCreateObjectHandle(node, TEXT("User ID"));
|
|
FreePathString (node);
|
|
}
|
|
if (objectName) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
objectName = NULL;
|
|
}
|
|
|
|
IsmReleaseMemory (objectContent.MemoryContent.ContentBytes);
|
|
|
|
// Set [Store Root] = %UserProfile%\Local Settings\Application Data\Identities\&destID\Microsoft\Outlook Express
|
|
defaultStore = pBuildDefaultStoreRoot(destID, TRUE);
|
|
if (defaultStore) {
|
|
objectContent.MemoryContent.ContentBytes = (PCBYTE)defaultStore;
|
|
objectContent.MemoryContent.ContentSize = SizeOfString(defaultStore);
|
|
*((PDWORD)objectContent.Details.DetailsData) = REG_EXPAND_SZ;
|
|
|
|
node = JoinPathsInPoolEx ((
|
|
NULL,
|
|
TEXT("HKCU\\Identities"),
|
|
destID,
|
|
TEXT("Software\\Microsoft\\Outlook Express\\5.0"),
|
|
NULL
|
|
));
|
|
if (node) {
|
|
objectName = IsmCreateObjectHandle(node, TEXT("Store Root"));
|
|
FreePathString (node);
|
|
}
|
|
if (objectName) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &objectContent);
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
FreeText(defaultStore);
|
|
}
|
|
IsmReleaseMemory (objectContent.Details.DetailsData);
|
|
|
|
OEIAMAssociateId (destID);
|
|
}
|
|
|
|
return destID;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// OEInitializeIdentity
|
|
// This is used to initialize a destination identity that has been created but never used.
|
|
BOOL
|
|
OEInitializeIdentity (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE storeRootKey = NULL;
|
|
MIG_CONTENT objectContent;
|
|
PCTSTR defaultId;
|
|
PCTSTR defaultStoreRoot;
|
|
BOOL reinit = TRUE;
|
|
|
|
defaultId = OEGetDefaultId (PLATFORM_DESTINATION);
|
|
if (defaultId) {
|
|
storeRootKey = pBuildStoreRootKeyForId (defaultId);
|
|
if (storeRootKey) {
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, storeRootKey, &objectContent)) {
|
|
if (IsValidRegSz(&objectContent)) {
|
|
reinit = FALSE;
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
}
|
|
|
|
if (reinit) {
|
|
defaultStoreRoot = pBuildDefaultStoreRoot (defaultId, TRUE);
|
|
if (defaultStoreRoot) {
|
|
ZeroMemory (&objectContent, sizeof(MIG_CONTENT));
|
|
objectContent.ObjectTypeId = g_RegType;
|
|
objectContent.Details.DetailsSize = sizeof(DWORD);
|
|
objectContent.Details.DetailsData = IsmGetMemory (sizeof(DWORD));
|
|
*((PDWORD)objectContent.Details.DetailsData) = REG_EXPAND_SZ;
|
|
objectContent.MemoryContent.ContentSize = SizeOfString (defaultStoreRoot);
|
|
objectContent.MemoryContent.ContentBytes = (PBYTE)defaultStoreRoot;
|
|
|
|
IsmReplacePhysicalObject (g_RegType, storeRootKey, &objectContent);
|
|
|
|
IsmReleaseMemory (objectContent.Details.DetailsData);
|
|
FreeText(defaultStoreRoot);
|
|
}
|
|
}
|
|
IsmDestroyObjectHandle(storeRootKey);
|
|
}
|
|
FreeText(defaultId);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// pOE5RemapStores
|
|
// This is used to set a special RegFolder rule for the OE5 [Store Root] values
|
|
// The rule will redirect all store folders into a temporary directory. Later,
|
|
// OE5MergeStorefolders will decide whether to copy or merge them into the proper
|
|
// location on the destination
|
|
BOOL
|
|
pOE5RemapStores (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE enumPattern;
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
PTSTR node;
|
|
PTSTR leaf;
|
|
TCHAR tmpDir[MAX_PATH];
|
|
BOOL result = FALSE;
|
|
ACTION_STRUCT actionStruct;
|
|
DWORD index = 0;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT)) {
|
|
|
|
// Find HKCU\Identities\* [Store Root]
|
|
// First enum each identity
|
|
enumPattern = IsmCreateSimpleObjectPattern (TEXT("HKCU\\Identities"), TRUE,
|
|
TEXT("Store Root"), FALSE);
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
|
|
do {
|
|
IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf);
|
|
if (node && leaf) {
|
|
// Regfolder the rule with a destination to a unique TEMP directory
|
|
// Grab a temporary place to copy the mail store
|
|
wsprintf(tmpDir, TEXT("%s\\%03x"), OETEMPDIR, index++);
|
|
|
|
ZeroMemory(&actionStruct, sizeof(ACTION_STRUCT));
|
|
actionStruct.ObjectBase = objectEnum.ObjectName;
|
|
actionStruct.AddnlDest = TurnFileStringIntoHandle (
|
|
tmpDir,
|
|
PFF_COMPUTE_BASE|
|
|
PFF_NO_SUBDIR_PATTERN|
|
|
PFF_NO_PATTERNS_ALLOWED|
|
|
PFF_NO_LEAF_AT_ALL
|
|
);
|
|
result = AddRule (g_RegType,
|
|
objectEnum.ObjectName,
|
|
objectEnum.ObjectName,
|
|
ACTIONGROUP_INCFOLDER,
|
|
ACTION_PERSIST_PATH_IN_DATA,
|
|
&actionStruct);
|
|
}
|
|
IsmDestroyObjectString(node);
|
|
if (leaf) {
|
|
IsmDestroyObjectString(leaf);
|
|
}
|
|
} while (IsmEnumNextObject (&objectEnum));
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
OEAddComplexRules (
|
|
VOID
|
|
)
|
|
{
|
|
pOE5RemapRules();
|
|
pOE5RemapAccounts();
|
|
pOE5RemapStores();
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// OEFixLastUser
|
|
// If for some reason the [Last User ID] value is set to zeroes or does not exist,
|
|
// we'll copy in the [Default User ID] value. If we dont do this, we'll get a popup
|
|
// during migration asking the user to select an identity, which would be really bad.
|
|
BOOL
|
|
OEFixLastUser (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
MIG_CONTENT objectContent;
|
|
MIG_OBJECTSTRINGHANDLE defName;
|
|
MIG_CONTENT defContent;
|
|
BOOL fFix = FALSE;
|
|
|
|
if (IsmIsComponentSelected (S_OE_COMPONENT, 0) &&
|
|
(IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE4_APPDETECT) ||
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OE5_APPDETECT))) {
|
|
|
|
objectName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"), TEXT("Last User ID"));
|
|
if (objectName) {
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, objectName, &objectContent)) {
|
|
if (IsValidRegSz(&objectContent) &&
|
|
StringMatch((PCTSTR)objectContent.MemoryContent.ContentBytes,
|
|
TEXT("{00000000-0000-0000-0000-000000000000}"))) {
|
|
fFix = TRUE;
|
|
}
|
|
IsmReleaseObject (&objectContent);
|
|
} else {
|
|
fFix = TRUE;
|
|
}
|
|
|
|
if (fFix) {
|
|
defName = IsmCreateObjectHandle (TEXT("HKCU\\Identities"), TEXT("Default User ID"));
|
|
if (defName) {
|
|
if (IsmAcquireObject (g_RegType | PLATFORM_DESTINATION, defName, &defContent)) {
|
|
if (IsValidRegSz (&defContent)) {
|
|
IsmReplacePhysicalObject (g_RegType, objectName, &defContent);
|
|
}
|
|
IsmReleaseObject (&defContent);
|
|
}
|
|
IsmDestroyObjectHandle (defName);
|
|
}
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|