You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3714 lines
107 KiB
3714 lines
107 KiB
// --------------------------------------------------------------------------------
|
|
// MIGRATE.CPP
|
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
// --------------------------------------------------------------------------------
|
|
#include "pch.hxx"
|
|
#include "strconst.h"
|
|
#include "resource.h"
|
|
#include "storfldr.h"
|
|
#include <imnact.h>
|
|
#include <acctutil.h>
|
|
#include "shlwapi.h"
|
|
#include <mimeole.h>
|
|
#include "xpcomm.h"
|
|
#include "oerules.h"
|
|
#include "goptions.h"
|
|
#include "ruleutil.h"
|
|
#include "criteria.h"
|
|
#include "actions.h"
|
|
#include "rule.h"
|
|
#include "storutil.h"
|
|
#include "shared.h"
|
|
#include "multiusr.h"
|
|
#include "msident.h"
|
|
#include "imapute.h"
|
|
#include <store.h>
|
|
|
|
#include "demand.h"
|
|
|
|
static const char c_szSettingsUpgraded[] = {"Settings Upgraded"};
|
|
|
|
BOOL g_fMigrationDone = FALSE;
|
|
|
|
void MigrateSettings(HKEY hkey);
|
|
HRESULT MigrateStoreToV2(HKEY hkeyV2, LPTSTR pszSrc, DWORD cchSrc, LPTSTR pszDest, DWORD cchDest);
|
|
HRESULT MigrateAccounts(void);
|
|
HRESULT MigrateMailServers(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3, HKEY hkeySmtp);
|
|
HRESULT MigrateNewsServers(IImnAccountManager *pAcctMan, HKEY hkeyNews);
|
|
HRESULT MigrateBase64EncodedPassword(LPCSTR pszBase64, DWORD cch, DWORD dwPropId, IImnAccount *pAccount);
|
|
HRESULT MigrateServerDataFiles(LPSTR pszServer, LPCSTR pszOldDir, LPCSTR pszSubDir);
|
|
void MigrateAccessibilityKeys(void);
|
|
HRESULT MigrateToPropertyStore(void);
|
|
void MigrateMailRulesSettings(void);
|
|
void ConvertToDBX(void);
|
|
void MigrateAccConnSettings();
|
|
void ForwardMigrateConnSettings();
|
|
void MigrateBeta2Rules();
|
|
void Stage5RulesMigration(VOID);
|
|
void Stage6RulesMigration(VOID);
|
|
#define VERLEN 20
|
|
|
|
// Data structures
|
|
typedef enum
|
|
{
|
|
VER_NONE = 0,
|
|
VER_1_0,
|
|
VER_1_1,
|
|
VER_4_0,
|
|
VER_5_0_B1,
|
|
VER_5_0,
|
|
VER_MAX,
|
|
} SETUPVER;
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ConvertVerToEnum
|
|
|
|
********************************************************************/
|
|
SETUPVER ConvertVerToEnum(WORD *pwVer)
|
|
{
|
|
SETUPVER sv;
|
|
Assert(pwVer);
|
|
|
|
switch (pwVer[0])
|
|
{
|
|
case 0:
|
|
sv = VER_NONE;
|
|
break;
|
|
|
|
case 1:
|
|
if (0 == pwVer[1])
|
|
sv = VER_1_0;
|
|
else
|
|
sv = VER_1_1;
|
|
break;
|
|
|
|
case 4:
|
|
sv = VER_4_0;
|
|
break;
|
|
|
|
case 5:
|
|
sv = VER_5_0;
|
|
break;
|
|
|
|
default:
|
|
sv = VER_MAX;
|
|
}
|
|
|
|
return sv;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ConvertStrToVer
|
|
|
|
********************************************************************/
|
|
void ConvertStrToVer(LPCSTR pszStr, WORD *pwVer)
|
|
{
|
|
int i;
|
|
|
|
Assert(pszStr);
|
|
Assert(pwVer);
|
|
|
|
ZeroMemory(pwVer, 4 * sizeof(WORD));
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
while (*pszStr && (*pszStr != ',') && (*pszStr != '.'))
|
|
{
|
|
pwVer[i] *= 10;
|
|
pwVer[i] += *pszStr - '0';
|
|
pszStr++;
|
|
}
|
|
if (*pszStr)
|
|
pszStr++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: GetVerInfo
|
|
|
|
********************************************************************/
|
|
void GetVerInfo(SETUPVER *psvCurr, SETUPVER *psvPrev)
|
|
{
|
|
HKEY hkeyT;
|
|
DWORD cb;
|
|
CHAR szVer[VERLEN];
|
|
WORD wVer[4];
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWABVerInfo, 0, KEY_QUERY_VALUE, &hkeyT))
|
|
{
|
|
if (psvCurr)
|
|
{
|
|
cb = sizeof(szVer);
|
|
RegQueryValueExA(hkeyT, c_szRegCurrVer, NULL, NULL, (LPBYTE)szVer, &cb);
|
|
ConvertStrToVer(szVer, wVer);
|
|
*psvCurr = ConvertVerToEnum(wVer);
|
|
}
|
|
|
|
if (psvPrev)
|
|
{
|
|
cb = sizeof(szVer);
|
|
RegQueryValueExA(hkeyT, c_szRegPrevVer, NULL, NULL, (LPBYTE)szVer, &cb);
|
|
ConvertStrToVer(szVer, wVer);
|
|
*psvPrev = ConvertVerToEnum(wVer);
|
|
}
|
|
|
|
RegCloseKey(hkeyT);
|
|
}
|
|
}
|
|
|
|
// Entry Point
|
|
HRESULT MigrateAndUpgrade()
|
|
{
|
|
DWORD dwMigrate, cb, type, fMigratedStore, fMigratedStoreOE5, fConvertedToDBX, dwRegVer=0, dwMasterVer=0;
|
|
BOOL fNewID=FALSE;
|
|
HKEY hkey, hkeyForceful;
|
|
TCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
|
|
|
|
// Keep this up to date!
|
|
#define LAST_MIGVALUE 7
|
|
|
|
if (g_fMigrationDone)
|
|
return(S_OK);
|
|
|
|
ForwardMigrateConnSettings();
|
|
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(MU_GetCurrentUserHKey(), c_szRegRoot, NULL, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &cb))
|
|
{
|
|
// Before anything else, see if this identity has had its registry initialized
|
|
cb = sizeof(dwRegVer);
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szOEVerStamp, 0, &type, (LPBYTE)&dwRegVer, &cb))
|
|
{
|
|
HKEY hkeyDef;
|
|
|
|
// No Defaults at all
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegDefaultSettings, 0, KEY_READ, &hkeyDef))
|
|
{
|
|
CopyRegistry(hkeyDef, hkey);
|
|
RegCloseKey(hkeyDef);
|
|
}
|
|
|
|
fNewID = TRUE;
|
|
}
|
|
else if (type != REG_DWORD || cb != sizeof(DWORD))
|
|
{
|
|
dwRegVer = 0;
|
|
}
|
|
|
|
// Compare to forceful setting reg value to see if we need those
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegForcefulSettings, 0, KEY_READ, &hkeyForceful))
|
|
{
|
|
cb = sizeof(dwMasterVer);
|
|
RegQueryValueEx(hkeyForceful, c_szOEVerStamp, 0, NULL, (LPBYTE)&dwMasterVer, &cb);
|
|
|
|
// Do we need to copy these in?
|
|
if (dwRegVer < dwMasterVer)
|
|
{
|
|
// The act of copying will set c_szOEVerStamp
|
|
CopyRegistry(hkeyForceful, hkey);
|
|
}
|
|
|
|
RegCloseKey(hkeyForceful);
|
|
}
|
|
|
|
|
|
// Start with no paths
|
|
szSrc[0] = szDest[0] = 0;
|
|
|
|
// move the store from v1 location to new location.
|
|
// this is done because v1 barfs when trying to look at v2 store.
|
|
// when we uninstall, we try to move the store back to its v1 location
|
|
// and we tweak the versions of the store files so v1 repairs the files
|
|
// and can run without crashing
|
|
// HKCU,"software/microsoft/outlook express/5.0","MSIMN"
|
|
if (fNewID)
|
|
{
|
|
fMigratedStore = TRUE;
|
|
RegSetValueEx(hkey, c_szMSIMN, NULL, REG_DWORD, (LPBYTE)&fMigratedStore, sizeof(fMigratedStore));
|
|
}
|
|
else
|
|
{
|
|
cb = sizeof(fMigratedStore);
|
|
if (RegQueryValueEx(hkey, c_szMSIMN, NULL, NULL, (LPBYTE)&fMigratedStore, &cb) != ERROR_SUCCESS)
|
|
fMigratedStore = FALSE;
|
|
|
|
if (!fMigratedStore)
|
|
{
|
|
// See if there is a v1 store, if so, figure out source and dest
|
|
MigrateStoreToV2(hkey, szSrc, ARRAYSIZE(szSrc), szDest, ARRAYSIZE(szDest));
|
|
fMigratedStore = TRUE;
|
|
RegSetValueEx(hkey, c_szMSIMN, NULL, REG_DWORD, (LPBYTE)&fMigratedStore, sizeof(fMigratedStore));
|
|
}
|
|
}
|
|
|
|
// we need to do this everytime we startup.
|
|
// thank the trident guys for this lovely perf hit.
|
|
MigrateAccessibilityKeys();
|
|
|
|
if (fNewID)
|
|
dwMigrate = LAST_MIGVALUE;
|
|
else
|
|
{
|
|
cb = sizeof(dwMigrate);
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSettingsUpgraded, 0, &type, (LPBYTE)&dwMigrate, &cb))
|
|
dwMigrate = 0;
|
|
}
|
|
|
|
// ATTENTION! PLEASES READ THE FOLLOWING BEFORE CHANGING THE UPGRADE CODE,
|
|
// SO YOU DON'T MESS ANYTHING UP. (i don't often comment anything so this must
|
|
// be important.)
|
|
//
|
|
// everything in the dwMigrate == 0 case is pre-oe5 and before we had one place to do
|
|
// upgrade and migration of previous oe settings. some of the pre-oe5 migration code used
|
|
// their own reg values to indicate that migration had been performed, so we'll use those
|
|
// in this case.
|
|
// but from now on all migration should use the same reg value (c_szSettingsUpgraded) to
|
|
// track what needs to be upgraded/migrated. as you change something and add migration code
|
|
// bump up the value
|
|
|
|
if (dwMigrate == 0)
|
|
{
|
|
SETUPVER svPrev;
|
|
|
|
// HKCU,"software/microsoft/outlook express/5.0","Settings Migrated"
|
|
MigrateSettings(hkey);
|
|
|
|
GetVerInfo(NULL, &svPrev);
|
|
if (VER_1_0 == svPrev || VER_1_1 == svPrev)
|
|
MigrateAccounts();
|
|
|
|
dwMigrate = 1;
|
|
}
|
|
|
|
if (dwMigrate == 1)
|
|
{
|
|
// MigrateCharSetMapSettings(); // We don't need to migrate this settings,
|
|
// but need to keep dwMigrate for Beta2. (YST)
|
|
|
|
dwMigrate = 2;
|
|
}
|
|
|
|
if (dwMigrate == 2)
|
|
{
|
|
//Migrate account connection settings
|
|
MigrateAccConnSettings();
|
|
|
|
dwMigrate = 3;
|
|
}
|
|
|
|
// More settings migratation are done after the store migration
|
|
|
|
// For Outlook Express V5, we migrate the OE4 version store to the ObjectDB Store.
|
|
// For V1 Users, the code above will have just executed and now they get to migrate again.
|
|
if (fNewID)
|
|
fMigratedStoreOE5 = TRUE;
|
|
else
|
|
{
|
|
cb = sizeof(fMigratedStoreOE5);
|
|
if (RegQueryValueEx(hkey, c_szStoreMigratedToOE5, NULL, NULL, (LPBYTE)&fMigratedStoreOE5, &cb) != ERROR_SUCCESS)
|
|
fMigratedStoreOE5 = FALSE;
|
|
}
|
|
|
|
if (!fMigratedStoreOE5)
|
|
{
|
|
// If we didn't just come from v1, we don't know where we are coming from or going to...
|
|
// Default to Store Root location
|
|
if (!szSrc[0])
|
|
{
|
|
Assert(!szDest[0]);
|
|
|
|
cb = sizeof(szSrc);
|
|
RegQueryValueEx(hkey, c_szRegStoreRootDir, 0, &type, (LPBYTE)szSrc, &cb);
|
|
if (REG_EXPAND_SZ == type)
|
|
{
|
|
ExpandEnvironmentStrings(szSrc, szDest, ARRAYSIZE(szDest));
|
|
StrCpyN(szSrc, szDest, ARRAYSIZE(szSrc));
|
|
}
|
|
else
|
|
StrCpyN(szDest, szSrc, ARRAYSIZE(szDest));
|
|
}
|
|
else
|
|
Assert(szDest[0]);
|
|
|
|
// Do we have anything to migrate?
|
|
if (szSrc[0] && szDest[0])
|
|
{
|
|
if (SUCCEEDED(MigrateLocalStore(NULL, szSrc, szDest)))
|
|
{
|
|
// Since the store migration remapped the folder id
|
|
// we must fix up the folder id in the rules
|
|
ImapUtil_B2SetDirtyFlag();
|
|
|
|
fMigratedStoreOE5 = TRUE;
|
|
RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fMigratedStoreOE5, sizeof(fMigratedStoreOE5));
|
|
}
|
|
}
|
|
else
|
|
// Nothing to migrate = success!
|
|
fMigratedStoreOE5 = TRUE;
|
|
|
|
}
|
|
|
|
// Save state
|
|
RegSetValueEx(hkey, c_szStoreMigratedToOE5, NULL, REG_DWORD, (LPBYTE)&fMigratedStoreOE5, sizeof(fMigratedStoreOE5));
|
|
|
|
if (fNewID)
|
|
{
|
|
fConvertedToDBX = TRUE;
|
|
RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fConvertedToDBX, sizeof(fConvertedToDBX));
|
|
}
|
|
else
|
|
{
|
|
cb = sizeof(fConvertedToDBX);
|
|
if (RegQueryValueEx(hkey, c_szConvertedToDBX, NULL, NULL, (LPBYTE)&fConvertedToDBX, &cb) != ERROR_SUCCESS)
|
|
fConvertedToDBX = FALSE;
|
|
if (!fConvertedToDBX)
|
|
{
|
|
fConvertedToDBX = TRUE;
|
|
ConvertToDBX();
|
|
RegSetValueEx(hkey, c_szConvertedToDBX, NULL, REG_DWORD, (LPBYTE)&fConvertedToDBX, sizeof(fConvertedToDBX));
|
|
}
|
|
}
|
|
|
|
if (dwMigrate == 3)
|
|
{
|
|
//Migrate rules settings
|
|
|
|
// This must be done after the store has been migrated
|
|
MigrateMailRulesSettings();
|
|
|
|
dwMigrate = 4;
|
|
}
|
|
|
|
if (dwMigrate == 4)
|
|
{
|
|
//Migrate from Beta 2 rules
|
|
|
|
// This must be done after the store has been migrated
|
|
MigrateBeta2Rules();
|
|
|
|
dwMigrate = 5;
|
|
}
|
|
|
|
if (dwMigrate == 5)
|
|
{
|
|
//Migrate from Beta 2 rules
|
|
|
|
// This must be done after the store has been migrated
|
|
Stage5RulesMigration();
|
|
|
|
dwMigrate = 6;
|
|
}
|
|
|
|
if (dwMigrate == 6)
|
|
{
|
|
//Migrate from Beta 2 rules
|
|
|
|
// This must be done after the store has been migrated
|
|
Stage6RulesMigration();
|
|
|
|
dwMigrate = LAST_MIGVALUE;
|
|
}
|
|
|
|
// Write the present upgraded settings value
|
|
RegSetValueEx(hkey, c_szSettingsUpgraded, 0, REG_DWORD, (LPBYTE)&dwMigrate, sizeof(dwMigrate));
|
|
|
|
// Cleanup
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
g_fMigrationDone = TRUE;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// MigrateAccConnSettings
|
|
//
|
|
// This migrates the connection settings for each account. This should be called
|
|
// for the following upgrade scenarios. 1)Upgrade from pre-OE5 to OE5 Beta2 or more
|
|
// 2)Upgrade from OeBeta1 to OE5 Beta2 or more
|
|
// If the Connection Setting was previously LAN, we migrate it to use InternetConnection
|
|
// (which is any connection available). If the previous setting was RAS, we leave it
|
|
// as it is.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
void MigrateAccConnSettings()
|
|
{
|
|
|
|
IImnEnumAccounts *pEnum = NULL;
|
|
IImnAccount *pAccount = NULL;
|
|
DWORD dwConnection;
|
|
|
|
Assert(g_pAcctMan == NULL);
|
|
|
|
if (FAILED(AcctUtil_CreateAccountManagerForIdentity(PGUIDCurrentOrDefault(), &g_pAcctMan)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum)))
|
|
{
|
|
while(SUCCEEDED(pEnum->GetNext(&pAccount)))
|
|
{
|
|
// Get Email Address
|
|
if (SUCCEEDED(pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
|
|
{
|
|
if (dwConnection == CONNECTION_TYPE_LAN)
|
|
{
|
|
pAccount->SetPropDw(AP_RAS_CONNECTION_TYPE, CONNECTION_TYPE_INETSETTINGS);
|
|
pAccount->SaveChanges();
|
|
}
|
|
}
|
|
|
|
SafeRelease(pAccount);
|
|
}
|
|
|
|
SafeRelease(pEnum);
|
|
}
|
|
|
|
g_pAcctMan->Release();
|
|
g_pAcctMan = NULL;
|
|
|
|
}
|
|
|
|
void ForwardMigrateConnSettings()
|
|
{
|
|
/*
|
|
We shouldn't have to do all the stuff we do above in MigrateAccConnSettings.
|
|
We just need to look at the old regsitry settings at
|
|
\\HKCU\Software\Microsoft\Internet Account Manager\Accounts.
|
|
Migrating from OE4 to OE5 just uses the same location if there is only one identity.
|
|
*/
|
|
|
|
HKEY hKeyAccounts = NULL;
|
|
DWORD dwAcctSubKeys = 0;
|
|
LONG retval;
|
|
DWORD index = 0;
|
|
LPTSTR lpszAccountName = NULL;
|
|
HKEY hKeyAccountName = NULL;
|
|
DWORD memsize = 0;
|
|
DWORD dwValue;
|
|
DWORD cbData = sizeof(DWORD);
|
|
DWORD cbMaxAcctSubKeyLen;
|
|
DWORD DataType;
|
|
DWORD dwConnSettingsMigrated = 1;
|
|
|
|
//This setting is in \\HKCU\Software\Microsoft\InternetAccountManager\Accounts
|
|
|
|
retval = RegOpenKey(HKEY_CURRENT_USER, c_szIAMAccounts, &hKeyAccounts);
|
|
if (ERROR_SUCCESS != retval)
|
|
goto exit;
|
|
|
|
retval = RegQueryValueEx(hKeyAccounts, c_szConnSettingsMigrated, NULL, &DataType,
|
|
(LPBYTE)&dwConnSettingsMigrated, &cbData);
|
|
|
|
if ((retval != ERROR_FILE_NOT_FOUND) && (retval != ERROR_SUCCESS || dwConnSettingsMigrated == 1))
|
|
goto exit;
|
|
|
|
retval = RegQueryInfoKey(hKeyAccounts, NULL, NULL, NULL, &dwAcctSubKeys,
|
|
&cbMaxAcctSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
if (ERROR_SUCCESS != retval)
|
|
goto exit;
|
|
|
|
memsize = sizeof(TCHAR) * cbMaxAcctSubKeyLen;
|
|
|
|
if (!MemAlloc((LPVOID*)&lpszAccountName, memsize))
|
|
{
|
|
lpszAccountName = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
ZeroMemory(lpszAccountName, memsize);
|
|
|
|
while (index < dwAcctSubKeys)
|
|
{
|
|
retval = RegEnumKey(hKeyAccounts, index, lpszAccountName, memsize);
|
|
|
|
index++;
|
|
|
|
if (retval == ERROR_SUCCESS)
|
|
{
|
|
retval = RegOpenKey(hKeyAccounts, lpszAccountName, &hKeyAccountName);
|
|
if (retval == ERROR_SUCCESS)
|
|
{
|
|
cbData = sizeof(DWORD);
|
|
retval = RegQueryValueEx(hKeyAccountName, c_szConnectionType, NULL, &DataType, (LPBYTE)&dwValue, &cbData);
|
|
if (retval == ERROR_SUCCESS)
|
|
{
|
|
if (dwValue == CONNECTION_TYPE_LAN)
|
|
{
|
|
dwValue = CONNECTION_TYPE_INETSETTINGS;
|
|
retval = RegSetValueEx(hKeyAccountName, c_szConnectionType, 0, REG_DWORD, (const BYTE *)&dwValue,
|
|
sizeof(DWORD));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyAccountName);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Set this to one so, when we downgrade when we do backward migration based on this key value
|
|
dwConnSettingsMigrated = 1;
|
|
RegSetValueEx(hKeyAccounts, c_szConnSettingsMigrated, 0, REG_DWORD, (const BYTE*)&dwConnSettingsMigrated,
|
|
sizeof(DWORD));
|
|
|
|
exit:
|
|
SafeMemFree(lpszAccountName);
|
|
|
|
if (hKeyAccounts)
|
|
RegCloseKey(hKeyAccounts);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ConvertToDBX
|
|
//--------------------------------------------------------------------------
|
|
void ConvertToDBX(void)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
CHAR szRootDir[MAX_PATH + MAX_PATH];
|
|
CHAR szSrcFile[MAX_PATH + MAX_PATH];
|
|
CHAR szDstFile[MAX_PATH + MAX_PATH];
|
|
|
|
// Trace
|
|
TraceCall("ConvertToDBX");
|
|
|
|
// Get Root Directory
|
|
IF_FAILEXIT(hr = GetStoreRootDirectory(szRootDir, ARRAYSIZE(szRootDir)));
|
|
|
|
// Folders
|
|
MakeFilePath(szRootDir, "folders.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
|
|
MakeFilePath(szRootDir, "folders.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
|
|
DeleteFile(szDstFile);
|
|
MoveFile(szSrcFile, szDstFile);
|
|
|
|
// Pop3uidl
|
|
MakeFilePath(szRootDir, "pop3uidl.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
|
|
MakeFilePath(szRootDir, "pop3uidl.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
|
|
DeleteFile(szDstFile);
|
|
MoveFile(szSrcFile, szDstFile);
|
|
|
|
// Offline
|
|
MakeFilePath(szRootDir, "Offline.ods", "", szSrcFile, ARRAYSIZE(szSrcFile));
|
|
MakeFilePath(szRootDir, "Offline.dbx", "", szDstFile, ARRAYSIZE(szSrcFile));
|
|
DeleteFile(szDstFile);
|
|
MoveFile(szSrcFile, szDstFile);
|
|
|
|
exit:
|
|
// Done
|
|
return;
|
|
}
|
|
|
|
HRESULT MigrateStoreToV2(HKEY hkeyV2, LPTSTR pszSrc, DWORD cchSrc, LPTSTR pszDest, DWORD cchDest)
|
|
{
|
|
HKEY hkeyV1;
|
|
BOOL fMoved = FALSE;
|
|
|
|
Assert(pszSrc);
|
|
Assert(pszDest);
|
|
Assert(cchSrc > 0);
|
|
Assert(cchDest > 0);
|
|
|
|
// Okay, this is the first time. Let's see if a previous version exists.
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
c_szRegRoot_V1,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyV1))
|
|
{
|
|
DWORD dwType;
|
|
|
|
// No need to worry about REG_EXPAND_SZ here as V1 didn't write it
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyV1,
|
|
c_szRegStoreRootDir,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)pszSrc,
|
|
&cchSrc) && *pszSrc)
|
|
{
|
|
AssertSz(REG_EXPAND_SZ != dwType, "V1's store path is REG_EXPAND_SZ!");
|
|
|
|
// Figure out new path
|
|
GetDefaultStoreRoot(NULL, pszDest, cchDest);
|
|
|
|
// Remember it
|
|
RegSetValueEx(hkeyV2, c_szRegStoreRootDir, NULL, REG_SZ, (LPBYTE)pszDest, (lstrlen(pszDest)+1) * sizeof(TCHAR));
|
|
}
|
|
|
|
RegCloseKey(hkeyV1);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
static const LPCTSTR c_rgCommonSettings[] =
|
|
{
|
|
c_szRegAlwaysSuggest,
|
|
c_szRegIgnoreNumbers,
|
|
c_szRegIgnoreUpper,
|
|
c_szRegIgnoreProtect,
|
|
c_szRegCheckOnSend,
|
|
c_szRegIgnoreDBCS,
|
|
c_szRasConnDetails
|
|
};
|
|
|
|
static const LPCTSTR c_rgMailSettings[] =
|
|
{
|
|
c_szOptNewMailSound,
|
|
c_szPurgeWaste,
|
|
c_szOptnSaveInSentItems,
|
|
c_szRegIncludeMsg,
|
|
c_szRegPollForMail,
|
|
c_szRegSendImmediate,
|
|
c_szRegSigType,
|
|
c_szRegSigText,
|
|
c_szRegSigFile,
|
|
c_szMarkPreviewAsRead,
|
|
c_szRegIndentChar,
|
|
c_szLogSmtp,
|
|
c_szLogPop3,
|
|
c_szSmtpLogFile,
|
|
c_szPop3LogFile
|
|
};
|
|
|
|
static const LPCTSTR c_rgNewsSettings[] =
|
|
{
|
|
c_szRegDownload,
|
|
c_szRegAutoExpand,
|
|
c_szRegNotifyNewGroups,
|
|
c_szRegMarkAllRead,
|
|
c_szRegSigType,
|
|
c_szRegSigText,
|
|
c_szRegSigFile,
|
|
c_szRegNewsNoteAdvRead,
|
|
c_szRegNewsNoteAdvSend,
|
|
c_szRegNewsFillPreview,
|
|
c_szCacheDelMsgDays,
|
|
c_szCacheRead,
|
|
c_szCacheCompactPer
|
|
};
|
|
|
|
// Copies values listed in ppszSettings from hkeyOld to hkey
|
|
void MigrateNode(HKEY hkey, HKEY hkeyOld, LPCTSTR pszSub, LPCTSTR *ppszSettings, int cSettings)
|
|
{
|
|
int i;
|
|
HKEY hkeyOldT, hkeyT;
|
|
DWORD cValues, cbMax, cb, type;
|
|
BYTE *pb;
|
|
|
|
Assert(hkey != NULL);
|
|
Assert(hkeyOld != NULL);
|
|
Assert(ppszSettings != NULL);
|
|
Assert(cSettings > 0);
|
|
|
|
if (pszSub != NULL)
|
|
{
|
|
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyOld, pszSub, 0, KEY_READ, &hkeyOldT))
|
|
return;
|
|
hkeyOld = hkeyOldT;
|
|
|
|
if (ERROR_SUCCESS != RegCreateKeyEx(hkey, pszSub, NULL, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyT, &cb))
|
|
{
|
|
RegCloseKey(hkeyOldT);
|
|
return;
|
|
}
|
|
hkey = hkeyT;
|
|
}
|
|
|
|
if (ERROR_SUCCESS == RegQueryInfoKey(hkeyOld, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&cValues, &cbMax, NULL, NULL) &&
|
|
cValues > 0 &&
|
|
cbMax > 0 &&
|
|
MemAlloc((void **)&pb, cbMax))
|
|
{
|
|
for (i = 0; i < cSettings; i++)
|
|
{
|
|
cb = cbMax;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, *ppszSettings, NULL, &type, pb, &cb))
|
|
RegSetValueEx(hkey, *ppszSettings, 0, type, pb, cb);
|
|
|
|
ppszSettings++;
|
|
}
|
|
|
|
MemFree(pb);
|
|
}
|
|
|
|
if (pszSub != NULL)
|
|
{
|
|
RegCloseKey(hkeyT);
|
|
RegCloseKey(hkeyOldT);
|
|
}
|
|
}
|
|
|
|
BOOL MigrateSignature(HKEY hkey, HKEY hkeyOld, DWORD dwSig, BOOL fMail)
|
|
{
|
|
BOOL fMigrate;
|
|
DWORD dwSigType, dwSigOpt, cb, type;
|
|
HKEY hkeySig;
|
|
char *psz, sz[MAX_PATH];
|
|
|
|
fMigrate = FALSE;
|
|
|
|
dwSigType = LOWORD(dwSig);
|
|
dwSigOpt = HIWORD(dwSig);
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, (dwSigType == 2) ? c_szRegSigFile : c_szRegSigText, NULL, &type, NULL, &cb) &&
|
|
cb > 1 &&
|
|
MemAlloc((void **)&psz, cb))
|
|
{
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, (dwSigType == 2) ? c_szRegSigFile : c_szRegSigText, NULL, &type, (LPBYTE)psz, &cb))
|
|
{
|
|
wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szSigs, fMail ? c_szMail : c_szNews);
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(hkey, sz, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeySig, &type))
|
|
{
|
|
if (type == REG_CREATED_NEW_KEY)
|
|
{
|
|
// name
|
|
AthLoadString(fMail ? idsMailSig : idsNewsSig, sz, ARRAYSIZE(sz));
|
|
RegSetValueEx(hkeySig, c_szSigName, 0, REG_SZ, (LPBYTE)sz, lstrlen(sz) + 1);
|
|
|
|
// text/file
|
|
RegSetValueEx(hkeySig, (dwSigType == 2) ? c_szSigFile : c_szSigText, 0, REG_SZ, (LPBYTE)psz, cb);
|
|
|
|
// type
|
|
RegSetValueEx(hkeySig, c_szSigType, 0, REG_DWORD, (LPBYTE)&dwSigType, sizeof(dwSigType));
|
|
|
|
fMigrate = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkeySig);
|
|
}
|
|
}
|
|
|
|
MemFree(psz);
|
|
}
|
|
|
|
return(fMigrate);
|
|
}
|
|
|
|
static const TCHAR c_szSettingsMigrated[] = TEXT("Settings Migrated");
|
|
|
|
void MigrateSettings(HKEY hkey)
|
|
{
|
|
HKEY hkeySrc, hkeyDst, hkeyOld;
|
|
DWORD dw, cb, type, dwMigrate, dwSig, dwFlags;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
cb = sizeof(dwMigrate);
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSettingsMigrated, NULL, &type, (LPBYTE)&dwMigrate, &cb))
|
|
dwMigrate = 0;
|
|
|
|
// v4.0 migration
|
|
if (dwMigrate == 0)
|
|
{
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegRoot_V1, 0, KEY_READ, &hkeyOld))
|
|
{
|
|
MigrateNode(hkey, hkeyOld, NULL, (LPCTSTR *)c_rgCommonSettings, ARRAYSIZE(c_rgCommonSettings));
|
|
MigrateNode(hkey, hkeyOld, c_szMail, (LPCTSTR *)c_rgMailSettings, ARRAYSIZE(c_rgMailSettings));
|
|
MigrateNode(hkey, hkeyOld, c_szNews, (LPCTSTR *)c_rgNewsSettings, ARRAYSIZE(c_rgNewsSettings));
|
|
|
|
RegCloseKey(hkeyOld);
|
|
}
|
|
|
|
// copy the inbox rules
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szInboxRulesPath_V1, 0, KEY_READ, &hkeySrc))
|
|
{
|
|
StrCpyN(szPath, c_szRegRoot, ARRAYSIZE(szPath));
|
|
StrCatBuff(szPath, c_szInboxRulesPath, ARRAYSIZE(szPath));
|
|
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(MU_GetCurrentUserHKey(), szPath, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDst, &dw))
|
|
{
|
|
if (dw != REG_OPENED_EXISTING_KEY)
|
|
CopyRegistry(hkeySrc, hkeyDst);
|
|
RegCloseKey(hkeyDst);
|
|
}
|
|
|
|
RegCloseKey(hkeySrc);
|
|
}
|
|
|
|
dwMigrate = 1;
|
|
}
|
|
|
|
// v5.0 migration
|
|
if (dwMigrate == 1)
|
|
{
|
|
dwFlags = 0xffffffff;
|
|
|
|
// mail signature
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, c_szMail, 0, KEY_READ, &hkeyOld))
|
|
{
|
|
cb = sizeof(dwSig);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, c_szRegSigType, NULL, &type, (LPBYTE)&dwSig, &cb) &&
|
|
LOWORD(dwSig) != 0)
|
|
{
|
|
if (MigrateSignature(hkey, hkeyOld, dwSig, TRUE))
|
|
dwFlags = HIWORD(dwSig);
|
|
}
|
|
|
|
RegCloseKey(hkeyOld);
|
|
}
|
|
|
|
// news signature
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, c_szNews, 0, KEY_READ, &hkeyOld))
|
|
{
|
|
cb = sizeof(dwSig);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyOld, c_szRegSigType, NULL, &type, (LPBYTE)&dwSig, &cb) &&
|
|
LOWORD(dwSig) != 0)
|
|
{
|
|
if (MigrateSignature(hkey, hkeyOld, dwSig, FALSE) &&
|
|
dwFlags == 0xffffffff)
|
|
dwFlags = HIWORD(dwSig);
|
|
}
|
|
|
|
RegCloseKey(hkeyOld);
|
|
}
|
|
|
|
cb = sizeof(dw);
|
|
if (dwFlags != 0xffffffff &&
|
|
ERROR_SUCCESS != RegQueryValueEx(hkey, c_szSigFlags, NULL, &type, (LPBYTE)&dw, &cb))
|
|
{
|
|
RegSetValueEx(hkey, c_szSigFlags, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
|
|
}
|
|
}
|
|
}
|
|
|
|
const static char c_szRegImnMail[] = {"Software\\Microsoft\\Internet Mail and News\\Mail"};
|
|
const static char c_szMailPOP3Path[] = {"Software\\Microsoft\\Internet Mail and News\\Mail\\POP3"};
|
|
const static char c_szMailSMTPPath[] = {"Software\\Microsoft\\Internet Mail and News\\Mail\\SMTP"};
|
|
const static char c_szRegImnNews[] = {"Software\\Microsoft\\Internet Mail and News\\News"};
|
|
|
|
const static char c_szDefaultSmtpServer[] = {"Default SMTP Server"};
|
|
const static char c_szDefaultPop3Server[] = {"Default POP3 Server"};
|
|
const static char c_szRegConnectType[] = {"Connection Type"};
|
|
const static char c_szRegRasPhonebookEntry[] = {"RAS Phonebook Entry"};
|
|
const static char c_szRegMailConnectType[] = {"Mail Connection Type"};
|
|
const static char c_szSenderOrg[] = {"Sender Organization"};
|
|
const static char c_szSenderEMail[] = {"Sender EMail"};
|
|
const static char c_szSenderReplyTo[] = {"Reply To"};
|
|
const static char c_szSendTimeout[] = {"SendTimeout"};
|
|
const static char c_szRecvTimeout[] = {"RecvTimeout"};
|
|
const static char c_szPort[] = {"Port"};
|
|
const static char c_szRegBreakMessages[] = {"Break Message Size (KB)"};
|
|
const static char c_szRegAccountName[] = {"Account Name"};
|
|
const static char c_szRegUseSicily[] = {"Use Sicily"};
|
|
const static char c_szRegSecureConnect[] = {"Secure Connection"};
|
|
const static char c_szRegServerTimeout[] = {"Timeout"};
|
|
const static char c_szRegServerPort[] = {"NNTP Port"};
|
|
const static char c_szRegUseDesc[] = {"Use Group Descriptions"};
|
|
const static char c_szRegNewsConnectFlags[] = {"Connection Flags"};
|
|
const static char c_szRegDefServer[] = {"DefaultServer"};
|
|
const static char c_szLeaveOnServer[] = {"LeaveMailOnServer"};
|
|
const static char c_szRemoveDeleted[] = {"RemoveOnClientDelete"};
|
|
const static char c_szRemoveExpired[] = {"RemoveExpire"};
|
|
const static char c_szExpireDays[] = {"ExpireDays"};
|
|
const static char c_szRegAccount[] = {"Account"};
|
|
|
|
HRESULT MigrateAccounts()
|
|
{
|
|
HKEY hkeyPop3, hkeySmtp, hkeyMail, hkeyNews;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegImnMail, 0, KEY_ALL_ACCESS, &hkeyMail) != ERROR_SUCCESS)
|
|
hkeyMail = NULL;
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegImnNews, 0, KEY_ALL_ACCESS, &hkeyNews) != ERROR_SUCCESS)
|
|
hkeyNews = NULL;
|
|
|
|
if (hkeyMail != NULL || hkeyNews != NULL)
|
|
{
|
|
// Create account manger because CSubList depends on g_pAcctMan
|
|
Assert(g_pAcctMan == NULL);
|
|
// Only ever migrate to DEFAULT user!
|
|
hr = AcctUtil_CreateAccountManagerForIdentity((GUID *)&UID_GIBC_DEFAULT_USER, &g_pAcctMan);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Try to open: HKCU\Software\Microsoft\IMN\Mail\POP3
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szMailPOP3Path, 0, KEY_ALL_ACCESS, &hkeyPop3) == ERROR_SUCCESS)
|
|
{
|
|
// Try to open: HKCU\Software\Microsoft\IMN\Mail\SMTP
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szMailSMTPPath, 0, KEY_ALL_ACCESS, &hkeySmtp) == ERROR_SUCCESS)
|
|
{
|
|
hr = MigrateMailServers(g_pAcctMan, hkeyMail, hkeyPop3, hkeySmtp);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
RegCloseKey(hkeySmtp);
|
|
}
|
|
|
|
RegCloseKey(hkeyPop3);
|
|
}
|
|
|
|
if (hkeyNews != NULL)
|
|
{
|
|
hr = MigrateNewsServers(g_pAcctMan, hkeyNews);
|
|
Assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
g_pAcctMan->Release();
|
|
g_pAcctMan = NULL;
|
|
}
|
|
|
|
if (hkeyMail != NULL)
|
|
RegCloseKey(hkeyMail);
|
|
if (hkeyNews != NULL)
|
|
RegCloseKey(hkeyNews);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
typedef struct tagACCTMIGRATEMAP
|
|
{
|
|
LPCSTR szRegValue;
|
|
DWORD dwProp;
|
|
} ACCTMIGRATEMAP;
|
|
|
|
typedef const ACCTMIGRATEMAP *LPCMIGRATEMAP;
|
|
|
|
HRESULT MigrateAccountSettings(IImnAccount *pAccount, HKEY hkey, LPCMIGRATEMAP pMap, int cMap)
|
|
{
|
|
HRESULT hr;
|
|
int i;
|
|
LPBYTE pb;
|
|
PROPTYPE ptype;
|
|
DWORD dw, cb, type;
|
|
char sz[512];
|
|
|
|
Assert(pAccount != NULL);
|
|
Assert(pMap != NULL);
|
|
Assert(cMap > 0);
|
|
|
|
for (i = 0; i < cMap; i++, pMap++)
|
|
{
|
|
ptype = PROPTAG_TYPE(pMap->dwProp);
|
|
Assert(ptype == TYPE_STRING || ptype == TYPE_DWORD || ptype == TYPE_BOOL || ptype == TYPE_PASS);
|
|
|
|
if (ptype == TYPE_STRING || ptype == TYPE_PASS)
|
|
{
|
|
cb = sizeof(sz);
|
|
pb = (LPBYTE)sz;
|
|
}
|
|
else
|
|
{
|
|
cb = sizeof(dw);
|
|
pb = (LPBYTE)&dw;
|
|
}
|
|
|
|
if (RegQueryValueEx(hkey, pMap->szRegValue, 0, &type, pb, &cb) == ERROR_SUCCESS)
|
|
{
|
|
if (ptype == TYPE_PASS)
|
|
{
|
|
// IMN's Password is stored as ANSI in a REG_BINARY with no NULL terminator
|
|
// Be sure to let MigrateBase64EncodedPassword know how long the password is
|
|
hr = MigrateBase64EncodedPassword(sz, cb, pMap->dwProp, pAccount);
|
|
}
|
|
else
|
|
hr = pAccount->SetProp(pMap->dwProp, pb, cb);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
static const ACCTMIGRATEMAP c_rgMailMap[] =
|
|
{
|
|
{c_szRegConnectType, AP_RAS_CONNECTION_TYPE},
|
|
{c_szRegRasPhonebookEntry, AP_RAS_CONNECTOID},
|
|
{c_szRegMailConnectType, AP_RAS_CONNECTION_FLAGS},
|
|
{c_szSenderName, AP_SMTP_DISPLAY_NAME},
|
|
{c_szSenderOrg, AP_SMTP_ORG_NAME},
|
|
{c_szSenderEMail, AP_SMTP_EMAIL_ADDRESS},
|
|
{c_szSenderReplyTo, AP_SMTP_REPLY_EMAIL_ADDRESS},
|
|
};
|
|
|
|
static const ACCTMIGRATEMAP c_rgPop3Map[] =
|
|
{
|
|
{c_szSendTimeout, AP_SMTP_TIMEOUT},
|
|
{c_szRecvTimeout, AP_POP3_TIMEOUT},
|
|
{c_szPort, AP_POP3_PORT},
|
|
{c_szLeaveOnServer, AP_POP3_LEAVE_ON_SERVER},
|
|
{c_szRemoveDeleted, AP_POP3_REMOVE_DELETED},
|
|
{c_szRemoveExpired, AP_POP3_REMOVE_EXPIRED},
|
|
{c_szExpireDays, AP_POP3_EXPIRE_DAYS},
|
|
{c_szRegAccount, AP_POP3_USERNAME},
|
|
{c_szRegUseSicily, AP_POP3_USE_SICILY},
|
|
{c_szPassword, AP_POP3_PASSWORD},
|
|
};
|
|
|
|
static const ACCTMIGRATEMAP c_rgSmtpMap[] =
|
|
{
|
|
{c_szPort, AP_SMTP_PORT}
|
|
};
|
|
|
|
HRESULT MigrateMailAccountSettings(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3Server,
|
|
HKEY hkeySmtpServer, LPSTR szDefPop3Server, LPSTR szDefSmtpServer)
|
|
{
|
|
DWORD dw, cb;
|
|
HRESULT hr;
|
|
char sz[CCHMAX_ACCOUNT_NAME];
|
|
IImnAccount *pAccount;
|
|
|
|
Assert(pAcctMan != NULL);
|
|
Assert(szDefPop3Server != NULL);
|
|
Assert(szDefSmtpServer != NULL);
|
|
|
|
hr = pAcctMan->CreateAccountObject(ACCT_MAIL, &pAccount);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
CHECKHR(hr = pAccount->SetPropSz(AP_SMTP_SERVER, szDefSmtpServer));
|
|
|
|
CHECKHR(hr = pAccount->SetPropSz(AP_POP3_SERVER, szDefPop3Server));
|
|
|
|
// Set Friendly Name
|
|
StrCpyN(sz, szDefPop3Server, ARRAYSIZE(sz));
|
|
CHECKHR(hr = pAcctMan->GetUniqueAccountName(sz, ARRAYSIZE(sz)));
|
|
CHECKHR(hr = pAccount->SetPropSz(AP_ACCOUNT_NAME, sz));
|
|
|
|
cb = sizeof(dw);
|
|
if (RegQueryValueEx(hkeyMail, c_szRegBreakMessages, 0, NULL, (LPBYTE)&dw, &cb) == ERROR_SUCCESS &&
|
|
dw != 0xffffffff)
|
|
{
|
|
// AP_SPLITMSGS
|
|
CHECKHR(hr = pAccount->SetPropDw(AP_SMTP_SPLIT_MESSAGES, TRUE));
|
|
|
|
// AP_SPLITSIZE
|
|
CHECKHR(hr = pAccount->SetPropDw(AP_SMTP_SPLIT_SIZE, dw));
|
|
}
|
|
|
|
CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyMail, c_rgMailMap, ARRAYSIZE(c_rgMailMap)));
|
|
CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyPop3Server, c_rgPop3Map, ARRAYSIZE(c_rgPop3Map)));
|
|
CHECKHR(hr = MigrateAccountSettings(pAccount, hkeySmtpServer, c_rgSmtpMap, ARRAYSIZE(c_rgSmtpMap)));
|
|
|
|
// Save Account Changes
|
|
hr = pAccount->SaveChanges();
|
|
|
|
exit:
|
|
pAccount->Release();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// Note: This migrates only the default server, not un-supported multi servers
|
|
HRESULT MigrateMailServers(IImnAccountManager *pAcctMan, HKEY hkeyMail, HKEY hkeyPop3, HKEY hkeySmtp)
|
|
{
|
|
char szDefSmtpServer[CCHMAX_SERVER_NAME],
|
|
szDefPop3Server[CCHMAX_SERVER_NAME];
|
|
ULONG cb;
|
|
DWORD dw;
|
|
HKEY hkeyPop3Server = NULL,
|
|
hkeySmtpServer = NULL;
|
|
BOOL fSmtpMigrated = FALSE,
|
|
fPop3Migrated = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(pAcctMan != NULL);
|
|
Assert(hkeyMail != NULL);
|
|
Assert(hkeyPop3 != NULL);
|
|
Assert(hkeySmtp != NULL);
|
|
|
|
// Get Default SMTP Server
|
|
cb = sizeof(szDefSmtpServer);
|
|
if (RegQueryValueEx(hkeyMail, c_szDefaultSmtpServer, 0, NULL, (LPBYTE)szDefSmtpServer, &cb) == ERROR_SUCCESS &&
|
|
!FIsEmpty(szDefSmtpServer))
|
|
{
|
|
// If we have a default smtp sever, lets open the key
|
|
RegOpenKeyEx(hkeySmtp, szDefSmtpServer, 0, KEY_ALL_ACCESS, &hkeySmtpServer);
|
|
}
|
|
|
|
// Get Default POP3 Server
|
|
cb = sizeof(szDefPop3Server);
|
|
if (RegQueryValueEx(hkeyMail, c_szDefaultPop3Server, 0, NULL, (LPBYTE)szDefPop3Server, &cb) == ERROR_SUCCESS &&
|
|
!FIsEmpty(szDefPop3Server))
|
|
{
|
|
// If we have a default pop3 sever, lets open the key
|
|
RegOpenKeyEx(hkeyPop3, szDefPop3Server, 0, KEY_ALL_ACCESS, &hkeyPop3Server);
|
|
}
|
|
|
|
// If we couldn't open the pop3 server, lets look in the registry and use the first server
|
|
if (hkeyPop3Server == NULL)
|
|
{
|
|
// Enumerate and open the first server in the list
|
|
cb = sizeof(szDefPop3Server);
|
|
if (RegEnumKeyEx(hkeyPop3, 0, szDefPop3Server, &cb, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
RegOpenKeyEx(hkeyPop3, szDefPop3Server, 0, KEY_ALL_ACCESS, &hkeyPop3Server);
|
|
}
|
|
|
|
// If we couldn't open the pop3 server, lets look in the registry and use the first server
|
|
if (hkeySmtpServer == NULL)
|
|
{
|
|
// Enumerate and open the first server in list
|
|
cb = sizeof(szDefSmtpServer);
|
|
if (RegEnumKeyEx(hkeySmtp, 0, szDefSmtpServer, &cb, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
RegOpenKeyEx(hkeySmtp, szDefSmtpServer, 0, KEY_ALL_ACCESS, &hkeySmtpServer);
|
|
}
|
|
|
|
if (hkeySmtpServer != NULL)
|
|
{
|
|
cb = sizeof(fSmtpMigrated);
|
|
RegQueryValueEx(hkeySmtpServer, c_szMigrated, 0, NULL, (LPBYTE)&fSmtpMigrated, &cb);
|
|
|
|
if (hkeyPop3Server != NULL)
|
|
{
|
|
cb = sizeof(fPop3Migrated);
|
|
RegQueryValueEx(hkeyPop3Server, c_szMigrated, 0, NULL, (LPBYTE)&fPop3Migrated, &cb);
|
|
|
|
if (!fPop3Migrated && !fSmtpMigrated)
|
|
{
|
|
hr = MigrateMailAccountSettings(pAcctMan, hkeyMail, hkeyPop3Server,
|
|
hkeySmtpServer, szDefPop3Server, szDefSmtpServer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fSmtpMigrated = TRUE;
|
|
RegSetValueEx(hkeySmtpServer, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fSmtpMigrated, sizeof(fSmtpMigrated));
|
|
|
|
fPop3Migrated = TRUE;
|
|
RegSetValueEx(hkeyPop3Server, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fPop3Migrated, sizeof(fPop3Migrated));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyPop3Server);
|
|
}
|
|
|
|
RegCloseKey(hkeySmtpServer);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
static const ACCTMIGRATEMAP c_rgNewsMap[] =
|
|
{
|
|
{c_szSenderName, AP_NNTP_DISPLAY_NAME},
|
|
{c_szSenderOrg, AP_NNTP_ORG_NAME},
|
|
{c_szSenderEMail, AP_NNTP_EMAIL_ADDRESS},
|
|
{c_szSenderReplyTo, AP_NNTP_REPLY_EMAIL_ADDRESS},
|
|
};
|
|
|
|
static const ACCTMIGRATEMAP c_rgNewsServerMap[] =
|
|
{
|
|
{c_szRegAccountName, AP_NNTP_USERNAME},
|
|
{c_szRegUseSicily, AP_NNTP_USE_SICILY},
|
|
{c_szRegSecureConnect, AP_NNTP_SSL},
|
|
{c_szRegServerTimeout, AP_NNTP_TIMEOUT},
|
|
{c_szRegServerPort, AP_NNTP_PORT},
|
|
{c_szRegUseDesc, AP_NNTP_USE_DESCRIPTIONS},
|
|
{c_szRegConnectType, AP_RAS_CONNECTION_TYPE},
|
|
{c_szRegRasPhonebookEntry, AP_RAS_CONNECTOID},
|
|
{c_szRegNewsConnectFlags, AP_RAS_CONNECTION_FLAGS},
|
|
{c_szPassword, AP_NNTP_PASSWORD},
|
|
};
|
|
|
|
HRESULT MigrateNewsAccountSettings(IImnAccountManager *pAcctMan, HKEY hkeyNews, HKEY hkeyServer, LPSTR szServer, BOOL fDefault)
|
|
{
|
|
IImnAccount *pAccount;
|
|
char sz[CCHMAX_ACCOUNT_NAME], szNewsDir[MAX_PATH], szDataDir[MAX_PATH];
|
|
HRESULT hr;
|
|
DWORD cb;
|
|
|
|
Assert(pAcctMan != NULL);
|
|
Assert(szServer != NULL);
|
|
|
|
hr = pAcctMan->CreateAccountObject(ACCT_NEWS, &pAccount);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
// AP_NNTP_SERVER
|
|
CHECKHR(hr = pAccount->SetPropSz(AP_NNTP_SERVER, szServer));
|
|
|
|
// Set Friendly Name
|
|
StrCpyN(sz, szServer, ARRAYSIZE(sz));
|
|
CHECKHR(hr = pAcctMan->GetUniqueAccountName(sz, ARRAYSIZE(sz)));
|
|
CHECKHR(hr = pAccount->SetPropSz(AP_ACCOUNT_NAME, sz));
|
|
|
|
CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyNews, c_rgNewsMap, ARRAYSIZE(c_rgNewsMap)));
|
|
CHECKHR(hr = MigrateAccountSettings(pAccount, hkeyServer, c_rgNewsServerMap, ARRAYSIZE(c_rgNewsServerMap)));
|
|
|
|
CHECKHR(hr = pAccount->SaveChanges());
|
|
|
|
if (fDefault)
|
|
pAccount->SetAsDefault();
|
|
|
|
exit:
|
|
pAccount->Release();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT MigrateNewsServers(IImnAccountManager *pAcctMan, HKEY hkeyNews)
|
|
{
|
|
char szDefNntpServer[CCHMAX_SERVER_NAME],
|
|
szServer[CCHMAX_SERVER_NAME];
|
|
HKEY hkeyAthena = NULL, hkeyServer = NULL;
|
|
DWORD cb, dw, i;
|
|
BOOL fMigrated, fSetDefault, fDefault;
|
|
LONG lResult;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(pAcctMan != NULL);
|
|
Assert(hkeyNews != NULL);
|
|
|
|
fSetDefault = FALSE;
|
|
hr = pAcctMan->GetDefaultAccountName(ACCT_NEWS, szServer, ARRAYSIZE(szServer));
|
|
if (FAILED(hr))
|
|
{
|
|
// Query for the default news account
|
|
cb = sizeof(szDefNntpServer);
|
|
if (RegQueryValueEx(hkeyNews, c_szRegDefServer, 0, NULL, (LPBYTE)szDefNntpServer, &cb) == ERROR_SUCCESS &&
|
|
!FIsEmpty(szDefNntpServer))
|
|
fSetDefault = TRUE;
|
|
}
|
|
|
|
// Enumerate through the keys
|
|
for (i = 0; ; i++)
|
|
{
|
|
// Enumerate Friendly Names
|
|
cb = sizeof(szServer);
|
|
lResult = RegEnumKeyEx(hkeyNews, i, szServer, &cb, 0, NULL, NULL, NULL);
|
|
|
|
// No more items
|
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
|
break;
|
|
|
|
// Error, lets move onto the next account
|
|
if (lResult != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Lets open they server key
|
|
if (RegOpenKeyEx(hkeyNews, szServer, 0, KEY_ALL_ACCESS, &hkeyServer) != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Has this server been migrated yet ?
|
|
cb = sizeof(fMigrated);
|
|
if (RegQueryValueEx(hkeyServer, c_szMigrated, 0, NULL, (LPBYTE)&fMigrated, &cb) != ERROR_SUCCESS)
|
|
fMigrated = FALSE;
|
|
|
|
// If not migrated
|
|
if (!fMigrated)
|
|
{
|
|
fDefault = (fSetDefault && (0 == lstrcmpi(szServer, szDefNntpServer)));
|
|
|
|
hr = MigrateNewsAccountSettings(pAcctMan, hkeyNews, hkeyServer, szServer, fDefault);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fMigrated = TRUE;
|
|
RegSetValueEx(hkeyServer, c_szMigrated, 0, REG_DWORD, (LPBYTE)&fMigrated, sizeof(fMigrated));
|
|
}
|
|
|
|
if (fDefault)
|
|
fSetDefault = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hkeyServer);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT MigrateBase64EncodedPassword(LPCSTR pszBase64, DWORD cch, DWORD dwPropId, IImnAccount *pAccount)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
IStream *pstmBase64=NULL;
|
|
IStream *pstmDecoded=NULL;
|
|
IMimeBody *pBody=NULL;
|
|
LPSTR pszPassword=NULL;
|
|
|
|
// Invalid Arg
|
|
Assert(pszBase64 && pAccount);
|
|
|
|
// Create a mime body
|
|
CHECKHR(hr = MimeOleCreateBody(&pBody));
|
|
|
|
// InitNew
|
|
CHECKHR(hr = pBody->InitNew());
|
|
|
|
// Create a pstmBase64 Stream
|
|
CHECKHR(hr = CreateStreamOnHGlobal(NULL, TRUE, &pstmBase64));
|
|
|
|
// Write the pszBase64 into this
|
|
CHECKHR(hr = pstmBase64->Write(pszBase64, cch * sizeof(*pszBase64), NULL));
|
|
|
|
// Commit
|
|
CHECKHR(hr = pstmBase64->Commit(STGC_DEFAULT));
|
|
|
|
// Rewind it
|
|
CHECKHR(hr = HrRewindStream(pstmBase64));
|
|
|
|
// Set it into IMimeBody
|
|
CHECKHR(hr = pBody->SetData(IET_BASE64, NULL, NULL, IID_IStream, (LPVOID)pstmBase64));
|
|
|
|
// Get the decoded stream
|
|
CHECKHR(hr = pBody->GetData(IET_DECODED, &pstmDecoded));
|
|
|
|
// Convert to string
|
|
CHECKALLOC(pszPassword = PszFromANSIStreamA(pstmDecoded));
|
|
|
|
// Store the property
|
|
CHECKHR(hr = pAccount->SetPropSz(dwPropId, pszPassword));
|
|
|
|
exit:
|
|
// Cleanup
|
|
if (pszPassword)
|
|
ZeroMemory(pszPassword, sizeof(pszPassword[0]) * lstrlenA(pszPassword)); // Done for security.
|
|
SafeRelease(pstmBase64);
|
|
SafeRelease(pstmDecoded);
|
|
SafeRelease(pBody);
|
|
SafeMemFree(pszPassword);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
static const char c_szAccessColors[] = "Always Use My Colors";
|
|
static const char c_szAccessFontFace[] = "Always Use My Font Face";
|
|
static const char c_szAccessFontSize[] = "Always Use My Font Size";
|
|
static const char c_szAccessSysCaret[] = "Move System Caret";
|
|
|
|
void MigrateAccessibilityKeys()
|
|
{
|
|
HKEY hkeyExplorer, hkeyAthena;
|
|
char szValue[MAX_PATH];
|
|
DWORD cbData, dw;
|
|
|
|
// Migrate keys from HKCU\SW\MS\InternetExplorer\Settings
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szIESettingsPath, 0, KEY_QUERY_VALUE, &hkeyExplorer) == ERROR_SUCCESS)
|
|
{
|
|
StrCpyN(szValue, c_szRegTriSettings, ARRAYSIZE(szValue));
|
|
if (RegCreateKeyEx(MU_GetCurrentUserHKey(), szValue, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAthena, &dw) == ERROR_SUCCESS)
|
|
{
|
|
cbData = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyExplorer, c_szAccessColors, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
|
|
RegSetValueEx (hkeyAthena, c_szAccessColors, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
|
|
|
|
cbData = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyExplorer, c_szAccessFontFace, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
|
|
RegSetValueEx (hkeyAthena, c_szAccessFontFace, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
|
|
|
|
cbData = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyExplorer, c_szAccessFontSize, NULL, NULL, (LPBYTE)&dw, &cbData) == ERROR_SUCCESS)
|
|
RegSetValueEx (hkeyAthena, c_szAccessFontSize, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
|
|
|
|
RegCloseKey(hkeyAthena);
|
|
}
|
|
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
|
|
// Migrate keys from HKCU\SW\MS\InternetExplorer\Main
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegKeyIEMain, 0, KEY_QUERY_VALUE, &hkeyExplorer) == ERROR_SUCCESS)
|
|
{
|
|
StrCpyN(szValue, c_szRegTriMain, ARRAYSIZE(szValue));
|
|
if (RegCreateKeyEx(MU_GetCurrentUserHKey(), szValue, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAthena, &dw) == ERROR_SUCCESS)
|
|
{
|
|
cbData = MAX_PATH;
|
|
if (RegQueryValueEx(hkeyExplorer, c_szAccessSysCaret, NULL, NULL, (LPBYTE)&szValue, &cbData) == ERROR_SUCCESS)
|
|
RegSetValueEx(hkeyAthena, c_szAccessSysCaret, 0, REG_SZ, (LPBYTE)szValue, cbData);
|
|
|
|
RegCloseKey(hkeyAthena);
|
|
}
|
|
|
|
RegCloseKey(hkeyExplorer);
|
|
}
|
|
}
|
|
|
|
ULONG UlBuildCritText(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
LPSTR pszReg = NULL;
|
|
LPSTR pszVal = NULL;
|
|
LPSTR pszTokens = NULL;
|
|
LPSTR pszWalk = NULL;
|
|
LPSTR pszString = NULL;
|
|
CRIT_ITEM critItem;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
|
|
// Get the key string from the registry
|
|
cbData = 0;
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((LPVOID *) &pszReg, cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszReg, &cbData);
|
|
|
|
// If it is empty, then we're done
|
|
if (FALSE != FIsEmptyA(pszReg))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// The strings are supposed to be in lowercase
|
|
CharLower(pszReg);
|
|
|
|
// Break up the strings into each search token
|
|
pszTokens = SzGetSearchTokens(pszReg);
|
|
if (NULL == pszTokens)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Count the space needed for the final string
|
|
cbData = 0;
|
|
for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Skip empty strings
|
|
if (FALSE == FIsEmptyA(pszWalk))
|
|
{
|
|
cbData += lstrlen(pszWalk) + 1;
|
|
}
|
|
}
|
|
|
|
// Nothing to add
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Add space to hold the string terminator
|
|
cbData += 2;
|
|
DWORD cchSizeString = cbData;
|
|
|
|
// Allocate space to hold the final string
|
|
if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Build up the string
|
|
pszString = pszVal;
|
|
for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Skip empty strings
|
|
if (FALSE == FIsEmptyA(pszWalk))
|
|
{
|
|
StrCpyNA(pszString, pszWalk, cchSizeString);
|
|
cchSizeString -= (lstrlen(pszString) + 1);
|
|
pszString += lstrlen(pszString) + 1;
|
|
}
|
|
}
|
|
|
|
// Terminate the string
|
|
pszString[0] = '\0';
|
|
pszString[1] = '\0';
|
|
|
|
// Build up the criteria
|
|
critItem.type = type;
|
|
critItem.logic = CRIT_LOGIC_NULL;
|
|
critItem.dwFlags = CRIT_FLAG_MULTIPLEAND;
|
|
critItem.propvar.vt = VT_BLOB;
|
|
critItem.propvar.blob.cbSize = cbData;
|
|
critItem.propvar.blob.pBlobData = (BYTE *) pszVal;
|
|
|
|
// Add it to the criteria object
|
|
if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
exit:
|
|
SafeMemFree(pszTokens);
|
|
SafeMemFree(pszVal);
|
|
SafeMemFree(pszReg);
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG UlBuildCritAcct(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
LPSTR pszVal = NULL;
|
|
CRIT_ITEM critItem;
|
|
IImnAccount * pAccount = NULL;
|
|
CHAR szAccount[CCHMAX_ACCOUNT_NAME];
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
|
|
// Get the key string from the registry
|
|
cbData = 0;
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
|
|
|
|
// If it is empty, then we're done
|
|
if (FALSE != FIsEmptyA(pszVal))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_NAME, pszVal, &pAccount)))
|
|
{
|
|
if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_ID, szAccount, sizeof(szAccount))))
|
|
{
|
|
SafeMemFree(pszVal);
|
|
pszVal = PszDupA(szAccount);
|
|
if (NULL == pszVal)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build up the criteria
|
|
critItem.type = type;
|
|
critItem.logic = CRIT_LOGIC_NULL;
|
|
critItem.dwFlags = CRIT_FLAG_DEFAULT;
|
|
critItem.propvar.vt = VT_LPSTR;
|
|
critItem.propvar.pszVal = pszVal;
|
|
|
|
// Add it to the criteria object
|
|
if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszVal);
|
|
SafeRelease(pAccount);
|
|
return ulRet;
|
|
}
|
|
ULONG UlBuildCritAddr(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
CRIT_ITEM critItem;
|
|
LPSTR pszReg = NULL;
|
|
LPSTR pszVal = NULL;
|
|
LPSTR pszTokens = NULL;
|
|
LPSTR pszWalk = NULL;
|
|
LPSTR pszString = NULL;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
|
|
// Get the key string from the registry
|
|
cbData = 0;
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((LPVOID *) &(pszReg), cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszReg, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// If it is empty, then we're done
|
|
if (FALSE != FIsEmptyA(pszReg))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// The strings are supposed to be in lowercase
|
|
CharLower(pszReg);
|
|
|
|
// Break up the strings into each search token
|
|
pszTokens = SzGetSearchTokens(pszReg);
|
|
if (NULL == pszTokens)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Count the space needed for the final string
|
|
cbData = 0;
|
|
for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Skip empty addresses
|
|
if (FALSE == FIsEmptyA(pszWalk))
|
|
{
|
|
cbData += lstrlen(pszWalk) + 1;
|
|
}
|
|
}
|
|
|
|
// Nothing to add
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Add space to hold the string terminator
|
|
cbData += 2;
|
|
DWORD cchSizeString = cbData;
|
|
|
|
// Allocate space to hold the final string
|
|
if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Build up the string
|
|
pszString = pszVal;
|
|
for (pszWalk = pszTokens; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Skip empty strings
|
|
if (FALSE == FIsEmptyA(pszWalk))
|
|
{
|
|
StrCpyN(pszString, pszWalk, cchSizeString);
|
|
cchSizeString -= (lstrlen(pszString) + 1);
|
|
pszString += lstrlen(pszString) + 1;
|
|
}
|
|
}
|
|
|
|
// Terminate the string
|
|
pszString[0] = '\0';
|
|
pszString[1] = '\0';
|
|
|
|
|
|
// Build up the criteria
|
|
critItem.type = type;
|
|
critItem.logic = CRIT_LOGIC_NULL;
|
|
critItem.dwFlags = CRIT_FLAG_MULTIPLEAND;
|
|
critItem.propvar.vt = VT_BLOB;
|
|
critItem.propvar.blob.cbSize = cbData;
|
|
critItem.propvar.blob.pBlobData = (BYTE *) pszVal;
|
|
|
|
// Add it to the criteria object
|
|
if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszVal);
|
|
SafeMemFree(pszTokens);
|
|
SafeMemFree(pszReg);
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG UlBuildCritKB(HKEY hKeyRoot, LPCSTR szKeyName, CRIT_TYPE type, IOECriteria * pICrit)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
ULONG ulVal = NULL;
|
|
CRIT_ITEM critItem;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
|
|
// Get the key long from the registry
|
|
cbData = sizeof(ulVal);
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) &ulVal, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Build up the criteria
|
|
critItem.type = type;
|
|
critItem.logic = CRIT_LOGIC_NULL;
|
|
critItem.dwFlags = CRIT_FLAG_DEFAULT;
|
|
critItem.propvar.vt = VT_UI4;
|
|
critItem.propvar.ulVal = ulVal;
|
|
|
|
// Add it to the criteria object
|
|
if (FAILED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG UlBuildActFolder(HKEY hKeyRoot, IMessageStore * pStore, BYTE * pbFldIdMap, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
ULONG ulVal = NULL;
|
|
ACT_ITEM actItem;
|
|
FOLDERID idFolder = FOLDERID_INVALID;
|
|
STOREUSERDATA UserData = {0};
|
|
RULEFOLDERDATA * prfdData = NULL;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
|
|
// Get the key long from the registry
|
|
cbData = sizeof(ulVal);
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) &ulVal, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Convert to V5 folder id
|
|
if ((NULL == pbFldIdMap) || (FAILED(RuleUtil_HrMapFldId(0, pbFldIdMap, (FOLDERID)((ULONG_PTR)ulVal), &idFolder))))
|
|
{
|
|
idFolder = (FOLDERID)((ULONG_PTR)ulVal);
|
|
}
|
|
|
|
// Create space for the data structure
|
|
if (FAILED(HrAlloc((VOID **) &prfdData, sizeof(*prfdData))))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the data struct
|
|
ZeroMemory(prfdData, sizeof(*prfdData));
|
|
|
|
// Get the timestamp for the store
|
|
if (FAILED(pStore->GetUserData(&UserData, sizeof(STOREUSERDATA))))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Set up the rule folder data
|
|
prfdData->ftStamp = UserData.ftCreated;
|
|
prfdData->idFolder = idFolder;
|
|
|
|
// Build up the actions
|
|
actItem.type = type;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_BLOB;
|
|
actItem.propvar.blob.cbSize = sizeof(*prfdData);
|
|
actItem.propvar.blob.pBlobData = (BYTE *) prfdData;
|
|
|
|
// Add it to the actions object
|
|
if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(prfdData);
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG UlBuildActFwd(HKEY hKeyRoot, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0,
|
|
cchCount = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
LPSTR pszVal = NULL,
|
|
pszTokens = NULL;
|
|
LPWSTR pwszVal = NULL,
|
|
pwszTokens = NULL;
|
|
ACT_ITEM actItem;
|
|
ULONG ulIndex = 0;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
|
|
// Get the key string from the registry
|
|
cbData = 0;
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cbData)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
|
|
Assert(*pszVal);
|
|
|
|
// Convert the string to our format
|
|
for (ulIndex = 0; ulIndex < cbData; ulIndex++)
|
|
{
|
|
if (',' == pszVal[ulIndex])
|
|
{
|
|
pszVal[ulIndex] = ';';
|
|
}
|
|
}
|
|
|
|
pwszVal = PszToUnicode(CP_ACP, pszVal);
|
|
if (!pwszVal)
|
|
goto exit;
|
|
|
|
if (FAILED(RuleUtil_HrBuildEmailString(pwszVal, 0, &pwszTokens, &cchCount)))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
Assert(pwszTokens);
|
|
pszTokens = PszToANSI(CP_ACP, pwszTokens);
|
|
if (!pszTokens)
|
|
goto exit;
|
|
|
|
// Build up the actions
|
|
actItem.type = type;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_LPSTR;
|
|
actItem.propvar.pszVal = pszTokens;
|
|
|
|
// Add it to the actions object
|
|
if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
exit:
|
|
MemFree(pszVal);
|
|
MemFree(pwszVal);
|
|
MemFree(pszTokens);
|
|
MemFree(pwszTokens);
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG UlBuildActFile(HKEY hKeyRoot, LPCSTR szKeyName, ACT_TYPE type, IOEActions * pIAct)
|
|
{
|
|
ULONG ulRet = 0;
|
|
DWORD cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
LPSTR pszVal = NULL;
|
|
ACT_ITEM actItem;
|
|
|
|
// Initialize out local vars
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
|
|
// Get the key string from the registry
|
|
cbData = 0;
|
|
lErr = SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cbData)
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((LPVOID *) &pszVal, cbData)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
SHQueryValueEx(hKeyRoot, szKeyName, NULL, NULL, (LPVOID) pszVal, &cbData);
|
|
|
|
// If it is empty, then we're done
|
|
if (FALSE != FIsEmptyA(pszVal))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
// Build up the actions
|
|
actItem.type = type;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_LPSTR;
|
|
actItem.propvar.pszVal = pszVal;
|
|
|
|
// Add it to the actions object
|
|
if (FAILED(pIAct->AppendActions(0, &actItem, 1, &ulRet)))
|
|
{
|
|
ulRet = 0;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
exit:
|
|
SafeMemFree(pszVal);
|
|
return ulRet;
|
|
}
|
|
|
|
// The maximum possible size of the Athena V1 actions string
|
|
const int CCH_V1_ACTION_MAX = 255;
|
|
|
|
BOOL FConvertV1ActionsToV4(HKEY hkeyRule, IMessageStore * pStore, IOEActions * pIAct)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
ULONG cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
TCHAR szAction[CCH_V1_ACTION_MAX];
|
|
LPSTR pszFolderName = NULL;
|
|
FOLDERID idFolder = FOLDERID_INVALID;
|
|
ACT_ITEM actItem;
|
|
RULEFOLDERDATA rfdData = {0};
|
|
STOREUSERDATA UserData = {0};
|
|
|
|
Assert(NULL != hkeyRule);
|
|
Assert(NULL != pStore);
|
|
Assert(NULL != pIAct);
|
|
|
|
// Is there anything to do?
|
|
cbData = sizeof(szAction);
|
|
lErr = RegQueryValueEx(hkeyRule, c_szActionV1, NULL, NULL, (BYTE *) szAction, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
Assert(0 == lstrcmpi(szAction, (LPTSTR) c_szMoveV1));
|
|
|
|
// Convert from old move to a V4 move
|
|
|
|
// Get the size of the folder name
|
|
lErr = RegQueryValueEx(hkeyRule, c_szFolderV1, NULL, NULL, NULL, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Allocate space to hold the folder name
|
|
if (FAILED(HrAlloc( (VOID **) &pszFolderName, cbData)))
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Get the old folder name
|
|
lErr = RegQueryValueEx(hkeyRule, c_szFolderV1, NULL, NULL, (BYTE *) pszFolderName, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Find the folder id from the folder name in the store
|
|
if (FAILED(GetFolderIdFromName(pStore, pszFolderName, FOLDERID_LOCAL_STORE, &idFolder)))
|
|
{
|
|
idFolder = FOLDERID_INVALID;
|
|
}
|
|
|
|
// Get the timestamp for the store
|
|
pStore->GetUserData(&UserData, sizeof(STOREUSERDATA));
|
|
|
|
// Set the timestamp and folder id
|
|
rfdData.ftStamp = UserData.ftCreated;
|
|
rfdData.idFolder = idFolder;
|
|
|
|
// Build up the actions
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
actItem.type = ACT_TYPE_MOVE;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_BLOB;
|
|
actItem.propvar.blob.cbSize = sizeof(rfdData);
|
|
actItem.propvar.blob.pBlobData = (BYTE *) &rfdData;
|
|
|
|
// Add it to the actions object
|
|
if (FAILED(pIAct->AppendActions(0, &actItem, 1, NULL)))
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the return value
|
|
fRet = TRUE;
|
|
|
|
exit:
|
|
SafeMemFree(pszFolderName);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void MigrateMailRulesSettings(void)
|
|
{
|
|
IImnAccountManager *pAcctMan = NULL;
|
|
HKEY hkeyOldRoot = NULL;
|
|
LONG lErr = 0;
|
|
ULONG cSubKeys = 0;
|
|
HKEY hkeyNewRoot = NULL;
|
|
DWORD dwDisp = 0;
|
|
DWORD cbData = 0;
|
|
BYTE * pbFldIdMap = NULL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
TCHAR szNameOld[16];
|
|
HKEY hKeyOld = NULL;
|
|
IOERule * pIRule = NULL;
|
|
PROPVARIANT propvar = {0};
|
|
BOOL boolVal = FALSE;
|
|
IOECriteria * pICrit = NULL;
|
|
CRIT_ITEM critItem;
|
|
ULONG ccritItem = 0;
|
|
CRIT_ITEM * pCrit = NULL;
|
|
ULONG ccritItemAlloc = 0;
|
|
IOEActions * pIAct = NULL;
|
|
DWORD dwActs = 0;
|
|
ACT_ITEM actItem;
|
|
ULONG cactItem = 0;
|
|
ACT_ITEM * pAct = NULL;
|
|
ULONG cactItemAlloc = 0;
|
|
ULONG ulName = 0;
|
|
TCHAR szRes[CCHMAX_STRINGRES + 5];
|
|
TCHAR szName[CCHMAX_STRINGRES + 5];
|
|
IOERule * pIRuleFind = NULL;
|
|
RULEINFO infoRule = {0};
|
|
CHAR szStoreDir[MAX_PATH + MAX_PATH];
|
|
IMessageStore * pStore = NULL;
|
|
|
|
// Initialize the local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
|
|
// Get the old key
|
|
lErr = AthUserOpenKey(c_szRegPathInboxRules, KEY_READ, &hkeyOldRoot);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Is there anything to do?
|
|
lErr = RegQueryInfoKey(hkeyOldRoot, NULL, NULL, NULL,
|
|
&cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
if ((lErr != ERROR_SUCCESS) || (0 == cSubKeys))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// To make sure we don't get any sample rule created
|
|
// set up the registry to look like we've already been set-up
|
|
|
|
// Get the new rules key
|
|
lErr = AthUserCreateKey(c_szRulesMail, KEY_ALL_ACCESS, &hkeyNewRoot, &dwDisp);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Save out the rules version
|
|
cbData = RULESMGR_VERSION;
|
|
lErr = RegSetValueEx(hkeyNewRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &cbData, sizeof(cbData));
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Figure out the size of the folderid map
|
|
lErr = AthUserGetValue(NULL, c_szFolderIdChange, NULL, NULL, &cbData);
|
|
if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// If the map exists, then grab it
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
// Allocate the space to hold the folderid map
|
|
if (FAILED(HrAlloc((void **) &pbFldIdMap, cbData)))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the folderid map from the registry
|
|
lErr = AthUserGetValue(NULL, c_szFolderIdChange, NULL, pbFldIdMap, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// CoIncrementInit Global Options Manager
|
|
if (FALSE == InitGlobalOptions(NULL, NULL))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the Rules Manager
|
|
Assert(NULL == g_pRulesMan);
|
|
hr = HrCreateRulesManager(NULL, (IUnknown **)&g_pRulesMan);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the rules manager
|
|
hr = g_pRulesMan->Initialize(0);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the Account Manager
|
|
Assert(g_pAcctMan == NULL);
|
|
hr = HrCreateAccountManager(&pAcctMan);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
hr = pAcctMan->QueryInterface(IID_IImnAccountManager2, (LPVOID *)&g_pAcctMan);
|
|
pAcctMan->Release();
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the account manager
|
|
hr = g_pAcctMan->Init(NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the store directory
|
|
hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the store object
|
|
pStore = new CMessageStore(FALSE);
|
|
if (NULL == pStore)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the store
|
|
hr = pStore->Initialize(szStoreDir);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
ulIndex = 0;
|
|
wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
|
|
|
|
if (0 == LoadString(g_hLocRes, idsRuleDefaultName, szRes, ARRAYSIZE(szRes)))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// For each entry in the old rules key
|
|
for (;RegOpenKeyEx(hkeyOldRoot, szNameOld, 0, KEY_READ, &hKeyOld) == ERROR_SUCCESS; RegCloseKey(hKeyOld))
|
|
{
|
|
// Create the new Rule
|
|
SafeRelease(pIRule);
|
|
hr = HrCreateRule(&pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Set the name on the rule
|
|
ulName = 1;
|
|
wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
|
|
|
|
Assert(NULL != g_pRulesMan);
|
|
while (S_OK == g_pRulesMan->FindRule(szName, RULE_TYPE_MAIL, &pIRuleFind))
|
|
{
|
|
SafeRelease(pIRuleFind);
|
|
ulName++;
|
|
wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
|
|
}
|
|
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_LPSTR;
|
|
propvar.pszVal = szName;
|
|
pIRule->SetProp(RULE_PROP_NAME, 0, &propvar);
|
|
|
|
// Set the enabled state on the rule
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szDisabled, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_BOOL;
|
|
propvar.boolVal = !!boolVal;
|
|
pIRule->SetProp(RULE_PROP_DISABLED, 0, &propvar);
|
|
|
|
// Copy over the criteria
|
|
SafeRelease(pICrit);
|
|
hr = HrCreateCriteria(&pICrit);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ccritItem = 0;
|
|
|
|
// Check for All Messages
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szFilterAllMessages, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
if (FALSE != boolVal)
|
|
{
|
|
critItem.type = CRIT_TYPE_ALL;
|
|
critItem.propvar.vt = VT_EMPTY;
|
|
critItem.logic = CRIT_LOGIC_NULL;
|
|
critItem.dwFlags = CRIT_FLAG_DEFAULT;
|
|
if (SUCCEEDED(pICrit->AppendCriteria(0, CRIT_LOGIC_AND, &critItem, 1, NULL)))
|
|
{
|
|
ccritItem++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check for account
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szFilterByAccount, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
if (FALSE != boolVal)
|
|
{
|
|
ccritItem += UlBuildCritAcct(hKeyOld, c_szAccount, CRIT_TYPE_ACCOUNT, pICrit);
|
|
}
|
|
|
|
// Check for size
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szFilterOnSize, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
if (FALSE != boolVal)
|
|
{
|
|
ccritItem += UlBuildCritKB(hKeyOld, c_szFilterSize, CRIT_TYPE_SIZE, pICrit);
|
|
}
|
|
|
|
// Check for subject
|
|
ccritItem += UlBuildCritText(hKeyOld, c_szSubject, CRIT_TYPE_SUBJECT, pICrit);
|
|
|
|
// Check for subject
|
|
ccritItem += UlBuildCritAddr(hKeyOld, c_szFrom, CRIT_TYPE_FROM, pICrit);
|
|
|
|
// Check for subject
|
|
ccritItem += UlBuildCritAddr(hKeyOld, c_szTo, CRIT_TYPE_TO, pICrit);
|
|
|
|
// Check for subject
|
|
ccritItem += UlBuildCritAddr(hKeyOld, c_szCC, CRIT_TYPE_CC, pICrit);
|
|
}
|
|
|
|
if (0 != ccritItem)
|
|
{
|
|
// Get the criteria from the criteria object and set it on the rule
|
|
RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
|
|
SafeMemFree(pCrit);
|
|
if (SUCCEEDED(pICrit->GetCriteria(0, &pCrit, &ccritItemAlloc)))
|
|
{
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_BLOB;
|
|
propvar.blob.cbSize = ccritItem * sizeof(CRIT_ITEM);
|
|
propvar.blob.pBlobData = (BYTE *) pCrit;
|
|
if (FAILED(pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar)))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copy over the actions
|
|
SafeRelease(pIAct);
|
|
hr = HrCreateActions(&pIAct);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
cactItem = 0;
|
|
|
|
// Convert any old V1 actions to V4
|
|
if (FALSE != FConvertV1ActionsToV4(hKeyOld, pStore, pIAct))
|
|
{
|
|
cactItem = 1;
|
|
}
|
|
else
|
|
{
|
|
// Get list of actions
|
|
cbData = sizeof(dwActs);
|
|
SHQueryValueEx(hKeyOld, c_szActions, NULL, NULL, (LPVOID) (&dwActs), &cbData);
|
|
|
|
// Check for don't download
|
|
if (0 != (dwActs & ACT_DONTDOWNLOAD))
|
|
{
|
|
actItem.type = ACT_TYPE_DONTDOWNLOAD;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_EMPTY;
|
|
if (SUCCEEDED(pIAct->AppendActions(0, &actItem, 1, NULL)))
|
|
{
|
|
cactItem++;
|
|
}
|
|
}
|
|
// Check for delete from server
|
|
else if (0 != (dwActs & ACT_DELETEOFFSERVER))
|
|
{
|
|
actItem.type = ACT_TYPE_DELETESERVER;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_EMPTY;
|
|
if (SUCCEEDED(pIAct->AppendActions(0, &actItem, 1, NULL)))
|
|
{
|
|
cactItem++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check for move to
|
|
if (0 != (dwActs & ACT_MOVETO))
|
|
{
|
|
cactItem += UlBuildActFolder(hKeyOld, pStore, pbFldIdMap, c_szMoveToHfolder, ACT_TYPE_MOVE, pIAct);
|
|
}
|
|
|
|
// Check for copy to
|
|
if (0 != (dwActs & ACT_COPYTO))
|
|
{
|
|
cactItem += UlBuildActFolder(hKeyOld, pStore, pbFldIdMap, c_szCopyToHfolder, ACT_TYPE_COPY, pIAct);
|
|
}
|
|
|
|
// Check for forward to
|
|
if (0 != (dwActs & ACT_FORWARDTO))
|
|
{
|
|
cactItem += UlBuildActFwd(hKeyOld, c_szForwardTo, ACT_TYPE_FWD, pIAct);
|
|
}
|
|
|
|
// Check for reply with
|
|
if (0 != (dwActs & ACT_REPLYWITH))
|
|
{
|
|
cactItem += UlBuildActFile(hKeyOld, c_szReplyWithFile, ACT_TYPE_REPLY, pIAct);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != cactItem)
|
|
{
|
|
// Get the actions from the action object and set it on the rule
|
|
RuleUtil_HrFreeActionsItem(pAct, cactItemAlloc);
|
|
SafeMemFree(pAct);
|
|
if (SUCCEEDED(pIAct->GetActions(0, &pAct, &cactItemAlloc)))
|
|
{
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_BLOB;
|
|
propvar.blob.cbSize = cactItem * sizeof(ACT_ITEM);
|
|
propvar.blob.pBlobData = (BYTE *) pAct;
|
|
if (FAILED(pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar)))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize the rule info
|
|
infoRule.ridRule = RULEID_INVALID;
|
|
infoRule.pIRule = pIRule;
|
|
|
|
// Add it to the rules
|
|
g_pRulesMan->SetRules(SETF_APPEND, RULE_TYPE_MAIL, &infoRule, 1);
|
|
|
|
ulIndex++;
|
|
wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
|
|
}
|
|
|
|
exit:
|
|
RuleUtil_HrFreeActionsItem(pAct, cactItemAlloc);
|
|
SafeMemFree(pAct);
|
|
RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
|
|
SafeMemFree(pCrit);
|
|
SafeRelease(pIAct);
|
|
SafeRelease(pICrit);
|
|
SafeRelease(pIRule);
|
|
if (NULL != hKeyOld)
|
|
{
|
|
RegCloseKey(hKeyOld);
|
|
}
|
|
SafeRelease(pStore);
|
|
SafeRelease(g_pAcctMan);
|
|
SafeRelease(g_pRulesMan);
|
|
DeInitGlobalOptions();
|
|
SafeMemFree(pbFldIdMap);
|
|
if (NULL != hkeyNewRoot)
|
|
{
|
|
RegCloseKey(hkeyNewRoot);
|
|
}
|
|
if (NULL != hkeyOldRoot)
|
|
{
|
|
RegCloseKey(hkeyOldRoot);
|
|
}
|
|
}
|
|
|
|
void CopyBeta2RulesToRTM(VOID)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hKeyMail = NULL;
|
|
HKEY hkeyRTM = NULL;
|
|
DWORD dwDisp = 0;
|
|
|
|
// Get the Beta 2 hkey for rules
|
|
lErr = AthUserOpenKey(c_szMail, KEY_READ, &hKeyMail);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the RTM hkey for rules
|
|
lErr = AthUserCreateKey(c_szRulesMail, KEY_ALL_ACCESS, &hkeyRTM, &dwDisp);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Copy the Beta 2 rules to the new location
|
|
SHCopyKey(hKeyMail, c_szRules, hkeyRTM, NULL);
|
|
|
|
exit:
|
|
if (NULL != hkeyRTM)
|
|
{
|
|
RegCloseKey(hkeyRTM);
|
|
}
|
|
if (NULL != hKeyMail)
|
|
{
|
|
RegCloseKey(hKeyMail);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2String(HKEY hkeyItem, LPCSTR pszSep, DWORD dwItemType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszData = NULL;
|
|
ULONG cbData = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
DWORD dwData = 0;
|
|
|
|
Assert(NULL != hkeyItem);
|
|
|
|
// Get the new data
|
|
hr = RuleUtil_HrGetOldFormatString(hkeyItem, c_szCriteriaValue, g_szComma, &pszData, &cbData);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the new data
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaValue, 0, REG_BINARY, (BYTE *) pszData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the proper value type
|
|
dwData = VT_BLOB;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the proper flags
|
|
dwData = CRIT_FLAG_MULTIPLEAND;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write the new type
|
|
cbData = sizeof(dwItemType);
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaType, 0, REG_DWORD, (BYTE *) &dwItemType, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszData);
|
|
return;
|
|
}
|
|
|
|
static IMessageStore * g_pStoreRulesMig = NULL;
|
|
|
|
VOID WriteOldOrderFormat(HKEY hkeyItem, LPSTR pszOrder)
|
|
{
|
|
ULONG cbData = 0;
|
|
LPSTR pszWalk = NULL;
|
|
ULONG cchWalk = 0;
|
|
|
|
// Convert the order string back to our old format
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += cchWalk + 1)
|
|
{
|
|
cchWalk = lstrlen(pszWalk);
|
|
*(pszWalk + cchWalk) = ' ';
|
|
cbData += cchWalk + 1;
|
|
}
|
|
|
|
// Make sure we terminate the order string
|
|
pszOrder[cbData - 1] = '\0';
|
|
|
|
// Save it
|
|
RegSetValueEx(hkeyItem, c_szRulesOrder, 0, REG_SZ, (BYTE *) pszOrder, cbData);
|
|
|
|
return;
|
|
}
|
|
|
|
static CRIT_TYPE g_rgtypeCritMerge[] =
|
|
{
|
|
CRIT_TYPE_FROM,
|
|
CRIT_TYPE_TO,
|
|
CRIT_TYPE_CC,
|
|
CRIT_TYPE_TOORCC
|
|
};
|
|
|
|
static const int g_ctypeCritMerge = sizeof(g_rgtypeCritMerge) / sizeof(g_rgtypeCritMerge[0]);
|
|
|
|
BOOL FMergeRuleData(HKEY hkeyItem, LPSTR pszSubKey, LPSTR * ppszData, ULONG * pcbData)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
DWORD dwType = 0;
|
|
ULONG cbString = 0;
|
|
LPSTR pszData = NULL;
|
|
ULONG cbData = 0;
|
|
|
|
// Get the size of the original string
|
|
lErr = SHGetValue(hkeyItem, pszSubKey, c_szCriteriaValue, &dwType, NULL, &cbString);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Figure out the space for the final string
|
|
cbData = *pcbData + cbString - 2;
|
|
if (cbData < *pcbData)
|
|
cbData = *pcbData;
|
|
|
|
// Allocate space for the final data
|
|
if (FAILED(HrAlloc((VOID **) &pszData, cbData * sizeof(*pszData))))
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Copy over the original string
|
|
CopyMemory(pszData, *ppszData, *pcbData * sizeof(*pszData));
|
|
|
|
// Copy over the new data
|
|
lErr = SHGetValue(hkeyItem, pszSubKey, c_szCriteriaValue, &dwType, (BYTE *) (pszData + *pcbData - 2), &cbString);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
fRet = FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Free the old data
|
|
SafeMemFree(*ppszData);
|
|
|
|
// Set the return values
|
|
*ppszData = pszData;
|
|
pszData = NULL;
|
|
*pcbData = cbData;
|
|
|
|
fRet = TRUE;
|
|
|
|
exit:
|
|
SafeMemFree(pszData);
|
|
return fRet;
|
|
}
|
|
|
|
void AddStopAction(HKEY hkeyItem, LPSTR * ppszOrder, ULONG * pcchOrder)
|
|
{
|
|
ULONG ulIndex = 0;
|
|
CHAR rgchTag[CCH_INDEX_MAX];
|
|
LPSTR pszWalk = NULL;
|
|
HKEY hkeyAction = NULL;
|
|
DWORD dwDisp = 0;
|
|
ULONG cbData = 0;
|
|
LONG lErr = 0;
|
|
ACT_TYPE typeAct = ACT_TYPE_NULL;
|
|
DWORD dwData = 0;
|
|
ULONG cchOrder = 0;
|
|
LPSTR pszOrder = NULL;
|
|
|
|
// Check to see if we need to add the stop processing action
|
|
if ('\0' == (*ppszOrder + lstrlen(*ppszOrder) + 1)[0])
|
|
{
|
|
// Get the action type
|
|
cbData = sizeof(typeAct);
|
|
lErr = SHGetValue(hkeyItem, *ppszOrder, c_szActionsType, NULL, (BYTE *) &typeAct, &cbData);
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
if ((ACT_TYPE_DONTDOWNLOAD == typeAct) || (ACT_TYPE_DELETESERVER == typeAct))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Spin through the order item looking for an open entry
|
|
for (ulIndex = 0; ulIndex < DWORD_INDEX_MAX; ulIndex++)
|
|
{
|
|
// Create the tag
|
|
wnsprintf(rgchTag, ARRAYSIZE(rgchTag), "%03X", ulIndex);
|
|
|
|
// Search for the tag in the list
|
|
for (pszWalk = *ppszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
if (0 == lstrcmp(pszWalk, rgchTag))
|
|
{
|
|
// Found it
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we didn't find it
|
|
if ('\0' == pszWalk[0])
|
|
{
|
|
// Use this one
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Did we find anything?
|
|
if (ulIndex >= DWORD_INDEX_MAX)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the new entry
|
|
lErr = RegCreateKeyEx(hkeyItem, rgchTag, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAction, &dwDisp);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Set the action type
|
|
cbData = sizeof(typeAct);
|
|
typeAct = ACT_TYPE_STOP;
|
|
lErr = RegSetValueEx(hkeyAction, c_szActionsType, 0, REG_DWORD, (BYTE *) &typeAct, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Set the action flags
|
|
dwData = ACT_FLAG_DEFAULT;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyAction, c_szActionsFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Allocate space to hold the new order string
|
|
cchOrder= *pcchOrder + CCH_INDEX_MAX;
|
|
if (FAILED(HrAlloc((VOID **) &pszOrder, cchOrder * sizeof (*pszOrder))))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Copy over the old values
|
|
CopyMemory(pszOrder, *ppszOrder, (*pcchOrder) * sizeof(*pszOrder));
|
|
|
|
// Add it to the new order string
|
|
StrCpyN(pszOrder + *pcchOrder - 2, rgchTag, (cchOrder - *pcchOrder + 2));
|
|
|
|
// Terminate the new string
|
|
pszOrder[cchOrder - 2] = '\0';
|
|
pszOrder[cchOrder - 1] = '\0';
|
|
|
|
// Release the old string
|
|
SafeMemFree(*ppszOrder);
|
|
|
|
// Save the new string
|
|
*ppszOrder = pszOrder;
|
|
pszOrder = NULL;
|
|
*pcchOrder = cchOrder;
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeyAction)
|
|
{
|
|
RegCloseKey(hkeyAction);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void MergeRTMCriteria(HKEY hkeyItem, CRIT_TYPE typeCrit, LPSTR pszOrder, ULONG cchOrder)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
LPSTR pszWalk = NULL;
|
|
CRIT_TYPE typeCritNew = CRIT_TYPE_NULL;
|
|
ULONG cbData = 0;
|
|
LPSTR pszFirst = NULL;
|
|
DWORD dwType = 0;
|
|
ULONG cbString = 0;
|
|
LPSTR pszString = NULL;
|
|
LPSTR pszSrc = NULL;
|
|
|
|
// Look through each item
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
cbData = sizeof(typeCritNew);
|
|
lErr = SHGetValue(hkeyItem, pszWalk, c_szCriteriaType, &dwType, (BYTE *) &typeCritNew, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (typeCritNew == typeCrit)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we couldn't find it we're done
|
|
if ('\0' == pszWalk[0])
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the size of the original string
|
|
pszFirst = pszWalk;
|
|
lErr = SHGetValue(hkeyItem, pszFirst, c_szCriteriaValue, &dwType, NULL, &cbString);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(HrAlloc((VOID **) &pszString, cbString * sizeof(*pszString))))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the original string
|
|
lErr = SHGetValue(hkeyItem, pszFirst, c_szCriteriaValue, &dwType, (BYTE *) pszString, &cbString);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Search for more entries of this type
|
|
for (pszWalk = pszFirst + lstrlen(pszFirst) + 1; '\0' != pszWalk[0]; )
|
|
{
|
|
cbData = sizeof(typeCritNew);
|
|
lErr = SHGetValue(hkeyItem, pszWalk, c_szCriteriaType, &dwType, (BYTE *) &typeCritNew, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (typeCritNew == typeCrit)
|
|
{
|
|
if (FALSE == FMergeRuleData(hkeyItem, pszWalk, &pszString, &cbString))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Remove the old key
|
|
SHDeleteKey(hkeyItem, pszWalk);
|
|
|
|
// Remove the item from the order string
|
|
pszSrc = pszWalk + lstrlen(pszWalk) + 1;
|
|
MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
|
|
cchOrder -= (ULONG) (pszSrc - pszWalk);
|
|
}
|
|
else
|
|
{
|
|
pszWalk += lstrlen(pszWalk) + 1;
|
|
}
|
|
}
|
|
|
|
// Save out the final string
|
|
lErr = SHSetValue(hkeyItem, pszFirst, c_szCriteriaValue, REG_BINARY, (BYTE *) pszString, cbString);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszString);
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2Folder(HKEY hkeyItem)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
DWORD dwType = 0;
|
|
FOLDERID idFolder = FOLDERID_INVALID;
|
|
ULONG cbData = 0;
|
|
STOREUSERDATA UserData = {0};
|
|
RULEFOLDERDATA rfdData = {0};
|
|
DWORD dwData = 0;
|
|
|
|
Assert(NULL != hkeyItem);
|
|
|
|
// Get the old folder id
|
|
cbData = sizeof(idFolder);
|
|
lErr = RegQueryValueEx(hkeyItem, c_szCriteriaValue, 0, &dwType, (BYTE *) &idFolder, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the timestamp for the store
|
|
Assert(NULL != g_pStoreRulesMig);
|
|
if (FAILED(g_pStoreRulesMig->GetUserData(&UserData, sizeof(STOREUSERDATA))))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Set up the new data
|
|
rfdData.idFolder = idFolder;
|
|
rfdData.ftStamp = UserData.ftCreated;
|
|
|
|
// Write out the new data
|
|
cbData = sizeof(rfdData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaValue, 0, REG_BINARY, (BYTE *) &rfdData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the proper value type
|
|
dwData = VT_BLOB;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szCriteriaValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2Show(HKEY hkeyItem)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
DWORD dwType = 0;
|
|
DWORD dwData = 0;
|
|
ULONG cbData = 0;
|
|
|
|
Assert(NULL != hkeyItem);
|
|
|
|
// Get the old flags
|
|
cbData = sizeof(dwData);
|
|
lErr = RegQueryValueEx(hkeyItem, c_szActionsFlags, 0, &dwType, (BYTE *) &dwData, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (0 != (dwData & ACT_FLAG_INVERT))
|
|
{
|
|
dwData = ACT_DATA_HIDE;
|
|
}
|
|
else
|
|
{
|
|
dwData = ACT_DATA_SHOW;
|
|
}
|
|
|
|
// Write out the new data
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szActionsValue, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the proper value type
|
|
dwData = VT_UI4;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szActionsValueType, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Write out the proper flags
|
|
dwData = ACT_FLAG_DEFAULT;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyItem, c_szActionsFlags, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2Criteria(HKEY hkeyItem, LPCSTR pszSubKey)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeyAtom = NULL;
|
|
CRIT_TYPE typeCrit = CRIT_TYPE_NULL;
|
|
DWORD dwType = 0;
|
|
ULONG cbData = 0;
|
|
|
|
lErr = RegOpenKeyEx(hkeyItem, pszSubKey, 0, KEY_ALL_ACCESS, &hkeyAtom);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the type of criteria
|
|
cbData = sizeof(typeCrit);
|
|
lErr = RegQueryValueEx(hkeyAtom, c_szCriteriaType, NULL, &dwType, (BYTE *) &typeCrit, &cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// For each criteria type
|
|
switch (typeCrit)
|
|
{
|
|
case CRIT_TYPE_FROM:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_FROM);
|
|
break;
|
|
|
|
case CRIT_TYPE_FROMADDR:
|
|
UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_FROM);
|
|
break;
|
|
|
|
case CRIT_TYPE_TO:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_TO);
|
|
break;
|
|
|
|
case CRIT_TYPE_TOADDR:
|
|
UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_TO);
|
|
break;
|
|
|
|
case CRIT_TYPE_CC:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_CC);
|
|
break;
|
|
|
|
case CRIT_TYPE_CCADDR:
|
|
UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_CC);
|
|
break;
|
|
|
|
case CRIT_TYPE_TOORCC:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_TOORCC);
|
|
break;
|
|
|
|
case CRIT_TYPE_TOORCCADDR:
|
|
UpdateBeta2String(hkeyAtom, g_szComma, (DWORD) CRIT_TYPE_TOORCC);
|
|
break;
|
|
|
|
case CRIT_TYPE_SUBJECT:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_SUBJECT);
|
|
break;
|
|
|
|
case CRIT_TYPE_BODY:
|
|
UpdateBeta2String(hkeyAtom, g_szSpace, (DWORD) CRIT_TYPE_BODY);
|
|
break;
|
|
|
|
case CRIT_TYPE_NEWSGROUP:
|
|
UpdateBeta2Folder(hkeyAtom);
|
|
break;
|
|
}
|
|
|
|
exit:
|
|
if (NULL != hkeyAtom)
|
|
{
|
|
RegCloseKey(hkeyAtom);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2Actions(HKEY hkeyItem, LPCSTR pszSubKey)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeyAtom = NULL;
|
|
ACT_TYPE typeAct = ACT_TYPE_NULL;
|
|
DWORD dwType = 0;
|
|
ULONG cbData = 0;
|
|
|
|
lErr = RegOpenKeyEx(hkeyItem, pszSubKey, 0, KEY_ALL_ACCESS, &hkeyAtom);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the type of actions
|
|
cbData = sizeof(typeAct);
|
|
lErr = RegQueryValueEx(hkeyAtom, c_szActionsType, NULL, &dwType, (BYTE *) &typeAct, &cbData);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// For each actions type
|
|
switch (typeAct)
|
|
{
|
|
case ACT_TYPE_MOVE:
|
|
case ACT_TYPE_COPY:
|
|
UpdateBeta2Folder(hkeyAtom);
|
|
break;
|
|
|
|
case ACT_TYPE_SHOW:
|
|
UpdateBeta2Show(hkeyAtom);
|
|
}
|
|
|
|
exit:
|
|
if (NULL != hkeyAtom)
|
|
{
|
|
RegCloseKey(hkeyAtom);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void MigrateBeta2RuleItems(HKEY hkeyRule, LPCSTR pszSubkey, BOOL fActions, RULE_TYPE typeRule)
|
|
{
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeySubkey = NULL;
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszOrder = NULL;
|
|
LPSTR pszWalk = NULL;
|
|
ULONG ulIndex = 0;
|
|
ULONG cbData = 0;
|
|
ULONG cchWalk = 0;
|
|
|
|
lErr = RegOpenKeyEx(hkeyRule, pszSubkey, 0, KEY_ALL_ACCESS, &hkeySubkey);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the order string
|
|
hr = RuleUtil_HrGetOldFormatString(hkeySubkey, c_szRulesOrder, g_szSpace, &pszOrder, &cbData);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// For each item in the order string
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Update actions
|
|
if (FALSE != fActions)
|
|
{
|
|
UpdateBeta2Actions(hkeySubkey, pszWalk);
|
|
}
|
|
else
|
|
{
|
|
UpdateBeta2Criteria(hkeySubkey, pszWalk);
|
|
}
|
|
}
|
|
|
|
if (FALSE == fActions)
|
|
{
|
|
// For each item type
|
|
for (ulIndex = 0; ulIndex < g_ctypeCritMerge; ulIndex++)
|
|
{
|
|
MergeRTMCriteria(hkeySubkey, g_rgtypeCritMerge[ulIndex], pszOrder, cbData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (typeRule != RULE_TYPE_FILTER)
|
|
{
|
|
AddStopAction(hkeySubkey, &pszOrder, &cbData);
|
|
}
|
|
}
|
|
|
|
// Write out the order string
|
|
WriteOldOrderFormat(hkeySubkey, pszOrder);
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeySubkey)
|
|
{
|
|
RegCloseKey(hkeySubkey);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void UpdateBeta2Rule(HKEY hkeyRoot, LPCSTR pszRule, RULE_TYPE typeRule)
|
|
{
|
|
HKEY hkeyRule = NULL;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
|
|
// Open up the rule
|
|
lErr = RegOpenKeyEx(hkeyRoot, pszRule, 0, KEY_ALL_ACCESS, &hkeyRule);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Migrate the criteria
|
|
MigrateBeta2RuleItems(hkeyRule, c_szRuleCriteria, FALSE, typeRule);
|
|
|
|
// Migrate the actions
|
|
MigrateBeta2RuleItems(hkeyRule, c_szRuleActions, TRUE, typeRule);
|
|
|
|
exit:
|
|
if (NULL != hkeyRule)
|
|
{
|
|
RegCloseKey(hkeyRule);
|
|
}
|
|
return;
|
|
}
|
|
|
|
typedef struct _RULEREGKEY
|
|
{
|
|
LPCSTR pszRegKey;
|
|
RULE_TYPE typeRule;
|
|
} RULEREGKEY, * PRULEREGKEY;
|
|
|
|
static RULEREGKEY g_rgpszRuleRegKeys[] =
|
|
{
|
|
{c_szRulesMail, RULE_TYPE_MAIL},
|
|
{c_szRulesNews, RULE_TYPE_NEWS},
|
|
{c_szRulesFilter, RULE_TYPE_FILTER}
|
|
};
|
|
|
|
static const int g_cpszRuleRegKeys = sizeof(g_rgpszRuleRegKeys) / sizeof(g_rgpszRuleRegKeys[0]);
|
|
|
|
void UpdateBeta2RuleFormats(VOID)
|
|
{
|
|
ULONG ulIndex = 0;
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeyRoot = NULL;
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszOrder = NULL;
|
|
LPSTR pszWalk = NULL;
|
|
CHAR szStoreDir[MAX_PATH + MAX_PATH];
|
|
|
|
// Set up the global objects
|
|
|
|
// Get the store directory
|
|
hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the store object
|
|
g_pStoreRulesMig = new CMessageStore(FALSE);
|
|
if (NULL == g_pStoreRulesMig)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the store
|
|
hr = g_pStoreRulesMig->Initialize(szStoreDir);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// For each type of rule
|
|
for (ulIndex = 0; ulIndex < g_cpszRuleRegKeys; ulIndex++)
|
|
{
|
|
// Open up the rule type reg key
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
lErr = AthUserOpenKey(g_rgpszRuleRegKeys[ulIndex].pszRegKey, KEY_ALL_ACCESS, &hkeyRoot);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Get the order string
|
|
SafeMemFree(pszOrder);
|
|
hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// For each item in the order string
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
// Update rule
|
|
UpdateBeta2Rule(hkeyRoot, pszWalk, g_rgpszRuleRegKeys[ulIndex].typeRule);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
SafeRelease(g_pStoreRulesMig);
|
|
return;
|
|
}
|
|
|
|
void MigrateBeta2Rules(VOID)
|
|
{
|
|
// Copy over all the items from the mail\rules area
|
|
|
|
// Get the new rules key
|
|
CopyBeta2RulesToRTM();
|
|
|
|
// Go through each rule type updating the formats
|
|
UpdateBeta2RuleFormats();
|
|
|
|
// Merge the items if neccessary
|
|
|
|
return;
|
|
}
|
|
|
|
void MigrateGroupFilterSettings(void)
|
|
{
|
|
IImnAccountManager *pAcctMan = NULL;
|
|
HKEY hkeyOldRoot = NULL;
|
|
LONG lErr = 0;
|
|
ULONG cSubKeys = 0;
|
|
HKEY hkeyNewRoot = NULL;
|
|
DWORD dwDisp = 0;
|
|
DWORD cbData = 0;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
TCHAR szNameOld[16];
|
|
HKEY hKeyOld = NULL;
|
|
IOERule * pIRule = NULL;
|
|
PROPVARIANT propvar = {0};
|
|
BOOL boolVal = FALSE;
|
|
IOECriteria * pICrit = NULL;
|
|
CRIT_ITEM critItem;
|
|
ULONG ccritItem = 0;
|
|
CRIT_ITEM * pCrit = NULL;
|
|
ULONG ccritItemAlloc = 0;
|
|
DWORD dwActs = 0;
|
|
ACT_ITEM actItem;
|
|
ULONG cactItemAlloc = 0;
|
|
ULONG ulName = 0;
|
|
TCHAR szRes[CCHMAX_STRINGRES + 5];
|
|
TCHAR szName[CCHMAX_STRINGRES + 5];
|
|
IOERule * pIRuleFind = NULL;
|
|
RULEINFO infoRule = {0};
|
|
CHAR szStoreDir[MAX_PATH + MAX_PATH];
|
|
IMessageStore * pStore = NULL;
|
|
|
|
// Initialize the local vars
|
|
ZeroMemory(&critItem, sizeof(critItem));
|
|
ZeroMemory(&actItem, sizeof(actItem));
|
|
|
|
// Get the old key
|
|
lErr = AthUserOpenKey(c_szRegPathGroupFilters, KEY_READ, &hkeyOldRoot);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Is there anything to do?
|
|
lErr = RegQueryInfoKey(hkeyOldRoot, NULL, NULL, NULL,
|
|
&cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
if ((lErr != ERROR_SUCCESS) || (0 == cSubKeys))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// To make sure we don't get any sample rule created
|
|
// set up the registry to look like we've already been set-up
|
|
|
|
// CoIncrementInit Global Options Manager
|
|
if (FALSE == InitGlobalOptions(NULL, NULL))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the Rules Manager
|
|
Assert(NULL == g_pRulesMan);
|
|
hr = HrCreateRulesManager(NULL, (IUnknown **)&g_pRulesMan);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the rules manager
|
|
hr = g_pRulesMan->Initialize(0);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the Account Manager
|
|
Assert(g_pAcctMan == NULL);
|
|
hr = HrCreateAccountManager(&pAcctMan);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
hr = pAcctMan->QueryInterface(IID_IImnAccountManager2, (LPVOID *)&g_pAcctMan);
|
|
pAcctMan->Release();
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the account manager
|
|
hr = g_pAcctMan->Init(NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the store directory
|
|
hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the store object
|
|
pStore = new CMessageStore(FALSE);
|
|
if (NULL == pStore)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the store
|
|
hr = pStore->Initialize(szStoreDir);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
ulIndex = 0;
|
|
wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
|
|
|
|
// Initialize the action
|
|
actItem.type = ACT_TYPE_SHOW;
|
|
actItem.dwFlags = ACT_FLAG_DEFAULT;
|
|
actItem.propvar.vt = VT_UI4;
|
|
actItem.propvar.ulVal = ACT_DATA_HIDE;
|
|
|
|
if (0 == LoadString(g_hLocRes, idsNewsFilterDefaultName, szRes, ARRAYSIZE(szRes)))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// For each entry in the old rules key
|
|
for (;RegOpenKeyEx(hkeyOldRoot, szNameOld, 0, KEY_READ, &hKeyOld) == ERROR_SUCCESS; RegCloseKey(hKeyOld))
|
|
{
|
|
// Create the new Rule
|
|
SafeRelease(pIRule);
|
|
hr = HrCreateRule(&pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Set the name on the rule
|
|
ulName = 1;
|
|
wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
|
|
|
|
Assert(NULL != g_pRulesMan);
|
|
while (S_OK == g_pRulesMan->FindRule(szName, RULE_TYPE_FILTER, &pIRuleFind))
|
|
{
|
|
SafeRelease(pIRuleFind);
|
|
ulName++;
|
|
wnsprintf(szName, ARRAYSIZE(szName), szRes, ulName);
|
|
}
|
|
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_LPSTR;
|
|
propvar.pszVal = szName;
|
|
pIRule->SetProp(RULE_PROP_NAME, 0, &propvar);
|
|
|
|
// Copy over the criteria
|
|
SafeRelease(pICrit);
|
|
hr = HrCreateCriteria(&pICrit);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ccritItem = 0;
|
|
|
|
// Check for age
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szFilterOnDate, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
if (FALSE != boolVal)
|
|
{
|
|
ccritItem += UlBuildCritKB(hKeyOld, c_szFilterDays, CRIT_TYPE_AGE, pICrit);
|
|
}
|
|
|
|
// Check for lines
|
|
cbData = sizeof(boolVal);
|
|
SHQueryValueEx(hKeyOld, c_szFilterOnSize, NULL, NULL, (LPVOID) (&boolVal), &cbData);
|
|
if (FALSE != boolVal)
|
|
{
|
|
ccritItem += UlBuildCritKB(hKeyOld, c_szFilterSize, CRIT_TYPE_LINES, pICrit);
|
|
}
|
|
|
|
// Check for subject
|
|
ccritItem += UlBuildCritText(hKeyOld, c_szSubject, CRIT_TYPE_SUBJECT, pICrit);
|
|
|
|
// Check for From
|
|
ccritItem += UlBuildCritAddr(hKeyOld, c_szFrom, CRIT_TYPE_FROM, pICrit);
|
|
|
|
if (0 != ccritItem)
|
|
{
|
|
// Get the criteria from the criteria object and set it on the rule
|
|
RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
|
|
SafeMemFree(pCrit);
|
|
if (SUCCEEDED(pICrit->GetCriteria(0, &pCrit, &ccritItemAlloc)))
|
|
{
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_BLOB;
|
|
propvar.blob.cbSize = ccritItem * sizeof(CRIT_ITEM);
|
|
propvar.blob.pBlobData = (BYTE *) pCrit;
|
|
if (FAILED(pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar)))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
propvar.vt = VT_BLOB;
|
|
propvar.blob.cbSize = sizeof(actItem);
|
|
propvar.blob.pBlobData = (BYTE *) &actItem;
|
|
if (FAILED(pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Initialize the rule info
|
|
infoRule.ridRule = RULEID_INVALID;
|
|
infoRule.pIRule = pIRule;
|
|
|
|
// Add it to the rules
|
|
g_pRulesMan->SetRules(SETF_APPEND, RULE_TYPE_FILTER, &infoRule, 1);
|
|
|
|
ulIndex++;
|
|
wnsprintf(szNameOld, ARRAYSIZE(szNameOld), "Rule%05d", ulIndex);
|
|
}
|
|
|
|
exit:
|
|
RuleUtil_HrFreeCriteriaItem(pCrit, ccritItemAlloc);
|
|
SafeMemFree(pCrit);
|
|
SafeRelease(pICrit);
|
|
SafeRelease(pIRule);
|
|
if (NULL != hKeyOld)
|
|
{
|
|
RegCloseKey(hKeyOld);
|
|
}
|
|
SafeRelease(pStore);
|
|
SafeRelease(g_pAcctMan);
|
|
SafeRelease(g_pRulesMan);
|
|
DeInitGlobalOptions();
|
|
if (NULL != hkeyNewRoot)
|
|
{
|
|
RegCloseKey(hkeyNewRoot);
|
|
}
|
|
if (NULL != hkeyOldRoot)
|
|
{
|
|
RegCloseKey(hkeyOldRoot);
|
|
}
|
|
}
|
|
|
|
void RemoveDeletedFromFilters(VOID)
|
|
{
|
|
CHAR szDeleted[CCH_INDEX_MAX];
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeyRoot = NULL;
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszOrder = NULL;
|
|
ULONG cchOrder = 0;
|
|
LPSTR pszWalk = NULL;
|
|
LPSTR pszSrc = NULL;
|
|
|
|
// Create the DELETED key
|
|
wnsprintf(szDeleted, ARRAYSIZE(szDeleted), "%03X", RULEID_VIEW_DELETED);
|
|
|
|
// Open the filter key
|
|
lErr = AthUserOpenKey(c_szRulesFilter, KEY_ALL_ACCESS, &hkeyRoot);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the order string
|
|
hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, &cchOrder);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Search for RULEID_VIEW_DELETED
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
if (0 == lstrcmpi(szDeleted, pszWalk))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we found it, then remove it
|
|
if ('\0' != pszWalk[0])
|
|
{
|
|
// Delete the view
|
|
SHDeleteKey(hkeyRoot, szDeleted);
|
|
|
|
// Remove it from the order string
|
|
pszSrc = pszWalk + lstrlen(pszWalk) + 1;
|
|
MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
|
|
|
|
// Save the order string
|
|
WriteOldOrderFormat(hkeyRoot, pszOrder);
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Stage5RulesMigration(VOID)
|
|
{
|
|
// Remove CRIT_TYPE_DELETED from views
|
|
RemoveDeletedFromFilters();
|
|
|
|
// Migrate the newsgroup filters
|
|
MigrateGroupFilterSettings();
|
|
|
|
return;
|
|
}
|
|
|
|
void RemoveRepliesFromFilters(VOID)
|
|
{
|
|
CHAR szDeleted[CCH_INDEX_MAX];
|
|
LONG lErr = ERROR_SUCCESS;
|
|
HKEY hkeyRoot = NULL;
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszOrder = NULL;
|
|
ULONG cchOrder = 0;
|
|
LPSTR pszWalk = NULL;
|
|
LPSTR pszSrc = NULL;
|
|
|
|
// Create the DELETED key
|
|
wnsprintf(szDeleted, ARRAYSIZE(szDeleted), "%03X", RULEID_VIEW_REPLIES);
|
|
|
|
// Open the filter key
|
|
lErr = AthUserOpenKey(c_szRulesFilter, KEY_ALL_ACCESS, &hkeyRoot);
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the order string
|
|
hr = RuleUtil_HrGetOldFormatString(hkeyRoot, c_szRulesOrder, g_szSpace, &pszOrder, &cchOrder);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Search for RULEID_VIEW_REPLIES
|
|
for (pszWalk = pszOrder; '\0' != pszWalk[0]; pszWalk += lstrlen(pszWalk) + 1)
|
|
{
|
|
if (0 == lstrcmpi(szDeleted, pszWalk))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we found it, then remove it
|
|
if ('\0' != pszWalk[0])
|
|
{
|
|
// Delete the view
|
|
SHDeleteKey(hkeyRoot, szDeleted);
|
|
|
|
// Remove it from the order string
|
|
pszSrc = pszWalk + lstrlen(pszWalk) + 1;
|
|
MoveMemory(pszWalk, pszSrc, cchOrder - (ULONG)(pszSrc - pszOrder));
|
|
|
|
// Save the order string
|
|
WriteOldOrderFormat(hkeyRoot, pszOrder);
|
|
}
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void Stage6RulesMigration(VOID)
|
|
{
|
|
// Remove RULEID_VIEW_REPLIES from views
|
|
RemoveRepliesFromFilters();
|
|
|
|
return;
|
|
}
|
|
|
|
|