|
|
// --------------------------------------------------------------------------------
// Acctutil.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// Steven J. Bailey
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "goptions.h"
#include "imnact.h"
#include "acctutil.h"
#include "strconst.h"
#include "error.h"
#include "resource.h"
#include <storfldr.h>
#include <notify.h>
#include "conman.h"
#include "shlwapip.h"
#include "browser.h"
#include "instance.h"
#include "menures.h"
#include "subscr.h"
#include "msident.h"
#include "acctcach.h"
#include <demand.h> // must be last!
CNewAcctMonitor *g_pNewAcctMonitor = NULL;
HRESULT IsValidSendAccount(LPSTR pszAccount);
CImnAdviseAccount::CImnAdviseAccount(void) { m_cRef = 1; m_pNotify = NULL; }
CImnAdviseAccount::~CImnAdviseAccount(void) { if (m_pNotify != NULL) m_pNotify->Release(); }
HRESULT CImnAdviseAccount::Initialize() { HRESULT hr;
hr = CreateNotify(&m_pNotify); if (SUCCEEDED(hr)) hr = m_pNotify->Initialize((TCHAR *)c_szMailFolderNotify);
return(hr); }
STDMETHODIMP CImnAdviseAccount::QueryInterface(REFIID riid, LPVOID *ppv) { // Locals
HRESULT hr=S_OK;
// Bad param
if (ppv == NULL) { hr = TRAPHR(E_INVALIDARG); goto exit; }
// Init
*ppv=NULL;
// IID_IImnAccountManager
if (IID_IImnAdviseAccount == riid) *ppv = (IImnAdviseAccount *)this;
// IID_IUnknown
else if (IID_IUnknown == riid) *ppv = (IUnknown *)this;
// If not null, addref it and return
if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); goto exit; }
// No Interface
hr = TRAPHR(E_NOINTERFACE);
exit: // Done
return hr; }
STDMETHODIMP_(ULONG) CImnAdviseAccount::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CImnAdviseAccount::Release(void) { if (0 != --m_cRef) return m_cRef; delete this; return 0; }
STDMETHODIMP CImnAdviseAccount::AdviseAccount(DWORD dwAdviseType, ACTX *pactx) { Assert(pactx != NULL);
if (pactx->AcctType == ACCT_DIR_SERV) return(S_OK);
if (g_pBrowser) g_pBrowser->AccountsChanged();
if (dwAdviseType == AN_DEFAULT_CHANGED) return(S_OK);
HandleAccountChange(pactx->AcctType, dwAdviseType, pactx->pszAccountID, pactx->pszOldName, pactx->dwServerType); if (g_pNewAcctMonitor != NULL) g_pNewAcctMonitor->OnAdvise(pactx->AcctType, dwAdviseType, pactx->pszAccountID);
// No matter what the notification, we need to tell the connection manager
if (g_pConMan) g_pConMan->AdviseAccount(dwAdviseType, pactx);
return S_OK; }
void CImnAdviseAccount::HandleAccountChange(ACCTTYPE AcctType, DWORD dwAN, LPTSTR pszID, LPTSTR pszOldName, DWORD dwSrvTypesOld) { HRESULT hr; IImnAccount *pAccount; char szName[CCHMAX_ACCOUNT_NAME]; FOLDERID id;
Assert(pszID != NULL);
switch (dwAN) { case AN_ACCOUNT_DELETED: AccountCache_AccountDeleted(pszID); if (!!(dwSrvTypesOld & (SRV_IMAP | SRV_NNTP | SRV_HTTPMAIL))) { hr = g_pStore->FindServerId(pszID, &id); if (SUCCEEDED(hr)) { HCURSOR hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); hr = g_pStore->DeleteFolder(id, DELETE_FOLDER_RECURSIVE | DELETE_FOLDER_NOTRASHCAN, (IStoreCallback *)g_pBrowser); Assert(SUCCEEDED(hr)); SetCursor(hCursor); } }
if (g_pBrowser != NULL) g_pBrowser->UpdateToolbar(); break;
case AN_ACCOUNT_ADDED: if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszID, &pAccount))) { hr = g_pStore->CreateServer(pAccount, NOFLAGS, &id); Assert(SUCCEEDED(hr));
if (g_pBrowser != NULL) g_pBrowser->UpdateToolbar();
pAccount->Release(); } break;
case AN_ACCOUNT_CHANGED: AccountCache_AccountChanged(pszID); if (pszOldName != NULL) { hr = g_pStore->FindServerId(pszID, &id); if (SUCCEEDED(hr)) { if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszID, &pAccount))) { hr = pAccount->GetPropSz(AP_ACCOUNT_NAME, szName, ARRAYSIZE(szName)); Assert(SUCCEEDED(hr));
hr = g_pStore->RenameFolder(id, szName, NOFLAGS, NOSTORECALLBACK); Assert(SUCCEEDED(hr));
pAccount->Release(); } } } break; } }
// -----------------------------------------------------------------------------
// AcctUtil_HrCreateAccountMenu
// -----------------------------------------------------------------------------
#define CCHMAX_RES 255
HRESULT AcctUtil_HrCreateAccountMenu(ACCOUNTMENUTYPE type, HMENU hPopup, UINT uidmPopup, HMENU *phAccounts, LPACCTMENU *pprgAccount, ULONG *pcAccounts, LPSTR pszThisAccount, BOOL fMail) { // Locals
HRESULT hr=S_OK; ULONG cAccounts=0; IImnEnumAccounts *pEnum=NULL; IImnAccount *pAccount=NULL; CHAR szDefault[CCHMAX_ACCOUNT_NAME]; CHAR szAccount[CCHMAX_ACCOUNT_NAME]; CHAR szQuoted[CCHMAX_ACCOUNT_NAME + CCHMAX_ACCOUNT_NAME + CCHMAX_RES]; LPACCTMENU prgAccount=NULL; HMENU hAccounts=NULL; MENUITEMINFO mii; UINT uPos=0; ULONG iAccount=0; CHAR szRes[CCHMAX_RES]; CHAR szRes1[CCHMAX_RES]; CHAR szRes2[CCHMAX_RES]; UINT idmFirst; CHAR szTitle[CCHMAX_RES + CCHMAX_RES + CCHMAX_ACCOUNT_NAME]; BOOL fNeedUsingMenu = FALSE;
// Check Parameters
Assert(g_pAcctMan && phAccounts && pprgAccount && pcAccounts);
// Init
*szDefault = '\0'; *pprgAccount = NULL; *pcAccounts = 0; *phAccounts = NULL;
if (type == ACCTMENU_SENDLATER) idmFirst = ID_SEND_LATER_ACCOUNT_FIRST; else idmFirst = ID_SEND_NOW_ACCOUNT_FIRST;
// Verify Default SMTP Account
CHECKHR(hr = g_pAcctMan->ValidateDefaultSendAccount());
// Get the default
CHECKHR(hr = hr = g_pAcctMan->GetDefaultAccountName(ACCT_MAIL, szDefault, ARRAYSIZE(szDefault)));
// Enumerate through the server types
CHECKHR(hr = g_pAcctMan->Enumerate(((ACCTMENU_SEND == type || ACCTMENU_SENDLATER == type) ? SRV_SMTP : SRV_SMTP | SRV_POP3), &pEnum));
// sort the accoutns
CHECKHR(hr = pEnum->SortByAccountName());
// Get Count
CHECKHR(hr = pEnum->GetCount(&cAccounts));
// No Accounts
if (cAccounts == 0) goto exit;
// Exceeded menu ids...
Assert(cAccounts <= 50);
// Add one if ACCTMENU_SENDRECV
if (ACCTMENU_SENDRECV == type) cAccounts++;
// Allocate prgAccount
CHECKALLOC(prgAccount = (LPACCTMENU)g_pMalloc->Alloc(cAccounts * sizeof(ACCTMENU)));
// Zero Init
ZeroMemory(prgAccount, cAccounts * sizeof(ACCTMENU));
// Only one account
if (((ACCTMENU_SENDRECV == type) && (cAccounts == 2)) || (cAccounts == 1) || !fMail) { // Return default Account
prgAccount[iAccount].fDefault = TRUE; prgAccount[iAccount].fThisAccount = TRUE; StrCpyN(prgAccount[iAccount].szAccount, szDefault, ARRAYSIZE(prgAccount[iAccount].szAccount));
// Return Everything
*pprgAccount = prgAccount; prgAccount = NULL; *pcAccounts = cAccounts;
// Done
goto exit; }
// Create a Menu
CHECKALLOC(hAccounts = CreatePopupMenu());
// if not using a specific account or the account is illegal, then let's default to the default-account
if (pszThisAccount==NULL || *pszThisAccount == NULL || IsValidSendAccount(pszThisAccount)!=S_OK) pszThisAccount = szDefault;
// Lets insert the default item
if ((ACCTMENU_SENDLATER == type || ACCTMENU_SEND == type) && !FIsEmptyA(szDefault)) { // Load String
StrCpyN(szTitle, pszThisAccount, ARRAYSIZE(szTitle));
prgAccount[iAccount].fDefault = lstrcmpi(pszThisAccount, szDefault)==0;
// if this is the default, flag it.
if (prgAccount[iAccount].fDefault) { AthLoadString(idsDefaultAccount, szRes1, ARRAYSIZE(szRes1)); StrCatBuff(szTitle, " ", ARRAYSIZE(szTitle)); StrCatBuff(szTitle, szRes1, ARRAYSIZE(szTitle)); }
if (((ACCTMENU_SEND == type && DwGetOption(OPT_SENDIMMEDIATE) && !g_pConMan->IsGlobalOffline()) || (ACCTMENU_SENDLATER == type && (!DwGetOption(OPT_SENDIMMEDIATE) || g_pConMan->IsGlobalOffline())))) { // if this menu is the default action add the 'Alt+S' accelerator string
AthLoadString(idsSendMsgAccelTip, szRes, ARRAYSIZE(szRes)); StrCatBuff(szTitle, "\t", ARRAYSIZE(szTitle)); StrCatBuff(szTitle, szRes, ARRAYSIZE(szTitle)); }
// Get mii ready
ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID; mii.fType = MFT_STRING; mii.fState = MFS_DEFAULT; // first item is the default verb
mii.dwTypeData = PszEscapeMenuStringA(szTitle, szQuoted, sizeof(szQuoted) / sizeof(char)); mii.cch = lstrlen(szQuoted); mii.wID = idmFirst + uPos;
// Set acctmenu item
prgAccount[iAccount].fThisAccount= TRUE; prgAccount[iAccount].uidm = mii.wID; StrCpyN(prgAccount[iAccount].szAccount, pszThisAccount, ARRAYSIZE(prgAccount[iAccount].szAccount)); iAccount++;
// Insert the item
if (InsertMenuItem(hAccounts, uPos, TRUE, &mii)) { uPos++; mii.fMask = MIIM_TYPE; mii.fType = MFT_SEPARATOR; if (InsertMenuItem(hAccounts, uPos, TRUE, &mii)) uPos++; } }
// Otherwise Send & Receive
else if (ACCTMENU_SENDRECV == type) { // Setup Menu
ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID; mii.fType = MFT_STRING; mii.fState = MFS_DEFAULT; AthLoadString(idsPollAllAccounts, szRes, ARRAYSIZE(szRes)); mii.dwTypeData = szRes; mii.cch = lstrlen(szRes); mii.wID = idmFirst + uPos;
// Set acctmenu item
prgAccount[iAccount].fDefault = TRUE; prgAccount[iAccount].uidm = mii.wID; *prgAccount[iAccount].szAccount = '\0'; iAccount++;
// Insert the item
if (InsertMenuItem(hAccounts, uPos, TRUE, &mii)) { uPos++; mii.fMask = MIIM_TYPE; mii.fType = MFT_SEPARATOR; if (InsertMenuItem(hAccounts, uPos, TRUE, &mii)) uPos++; } }
// Standard
ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID; mii.fType = MFT_STRING;
// Loop accounts
while(SUCCEEDED(pEnum->GetNext(&pAccount))) { // Get Account Name
CHECKHR(hr = pAccount->GetPropSz(AP_ACCOUNT_NAME, szAccount, ARRAYSIZE(szAccount)));
// Skip the 'This' account. Note for the send & receive menu this will always be the default
if (lstrcmpi(pszThisAccount, szAccount) == 0) { // We've already added this account
if (ACCTMENU_SEND == type || ACCTMENU_SENDLATER == type) { SafeRelease(pAccount); continue; }
// Otherwise, Account (Default)
else { // for send a recieve menu pszThisAccount should == szDefault
Assert (pszThisAccount == szDefault); // Load String
AthLoadString(idsDefaultAccount, szRes, ARRAYSIZE(szRes));
// Make String - Saranac (Default)
wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s %s", szAccount, szRes);
// Setup the menu item name
mii.dwTypeData = PszEscapeMenuStringA(szTitle, szQuoted, sizeof(szQuoted) / sizeof(char)); mii.cch = lstrlen(szQuoted); prgAccount[iAccount].fDefault = TRUE; } }
else { *szTitle=0;
// this might be the default
prgAccount[iAccount].fDefault = lstrcmpi(szAccount, szDefault)==0;
// build the string on the fly as any one of these accounts might be the 'default'
PszEscapeMenuStringA(szAccount, szTitle, sizeof(szTitle) / sizeof(char));
// if this is the default, flag it.
if (prgAccount[iAccount].fDefault) { AthLoadString(idsDefaultAccount, szRes1, ARRAYSIZE(szRes1)); StrCatBuff(szTitle, " ", ARRAYSIZE(szTitle)); StrCatBuff(szTitle, szRes1, ARRAYSIZE(szTitle)); }
// Setup the menu item name
mii.dwTypeData = szTitle; mii.cch = lstrlen(szTitle); }
// Insert into menu
mii.wID = idmFirst + uPos; if (InsertMenuItem(hAccounts, uPos, TRUE, &mii)) uPos++;
// Set acctmenu item
Assert(iAccount < cAccounts); prgAccount[iAccount].uidm = mii.wID; StrCpyN(prgAccount[iAccount].szAccount, szAccount, ARRAYSIZE(prgAccount[iAccount].szAccount)); iAccount++;
// Release Account
SafeRelease(pAccount); }
// Return Everything
*phAccounts = hAccounts; hAccounts = NULL; *pprgAccount = prgAccount; prgAccount = NULL; *pcAccounts = cAccounts;
exit: // Lets Setup the Accounts Menu
ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(MENUITEMINFO); fNeedUsingMenu = (cAccounts <= 1) || !fMail; if (ACCTMENU_SEND == type) { mii.fMask = MIIM_SUBMENU | MIIM_TYPE;
if (fNeedUsingMenu) { AthLoadString(idsSendMsgOneAccount, szRes, ARRAYSIZE(szRes)); AthLoadString(idsSendMsgAccelTip, szRes1, ARRAYSIZE(szRes1)); // If send now is default, add the Alt + S at the end
if (DwGetOption(OPT_SENDIMMEDIATE) && !g_pConMan->IsGlobalOffline()) wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s\t%s", szRes, szRes1); else wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s", szRes); } else AthLoadString(idsSendMsgUsing, szTitle, ARRAYSIZE(szTitle));
mii.fType = MFT_STRING; mii.dwTypeData = szTitle; mii.cch = lstrlen(szTitle); mii.hSubMenu = fNeedUsingMenu ? NULL : *phAccounts; } else if (ACCTMENU_SENDLATER == type) { if (fNeedUsingMenu) { AthLoadString(idsSendLaterOneAccount, szRes, ARRAYSIZE(szRes)); AthLoadString(idsSendMsgAccelTip, szRes1, ARRAYSIZE(szRes1)); // If send now is default, add the Alt + S at the end
if (!DwGetOption(OPT_SENDIMMEDIATE) || g_pConMan->IsGlobalOffline()) wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s\t%s", szRes, szRes1); else wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s", szRes); } else AthLoadString(idsSendLaterUsing, szTitle, ARRAYSIZE(szTitle));
mii.fMask = MIIM_SUBMENU | MIIM_TYPE; mii.fType = MFT_STRING; mii.dwTypeData = szTitle; mii.cch = lstrlen(szTitle); mii.hSubMenu = fNeedUsingMenu ? NULL : *phAccounts; } else { mii.fMask = MIIM_SUBMENU | MIIM_TYPE; AthLoadString(fNeedUsingMenu ? idsSendRecvOneAccount : idsSendRecvUsing, szRes, ARRAYSIZE(szRes)); mii.fType = MFT_STRING; mii.dwTypeData = szRes; mii.cch = lstrlen(szRes); mii.hSubMenu = fNeedUsingMenu ? NULL : *phAccounts; }
// Set the menu item
SideAssert(SetMenuItemInfo(hPopup, uidmPopup, FALSE, &mii));
// Cleanup
SafeRelease(pEnum); SafeRelease(pAccount); SafeMemFree(prgAccount); if (hAccounts) DestroyMenu(hAccounts);
// Done
return hr; }
HRESULT AcctUtil_GetServerCount(DWORD dwSrvTypes, DWORD *pcSrv) { HRESULT hr; IImnEnumAccounts *pEnum;
Assert(dwSrvTypes != 0); Assert(pcSrv != NULL);
hr = g_pAcctMan->Enumerate(dwSrvTypes, &pEnum); if (SUCCEEDED(hr)) { hr = pEnum->GetCount(pcSrv); Assert(SUCCEEDED(hr));
pEnum->Release(); }
return(hr); }
/////////////////////////////////////////////////////////////////////////////
// CNewAcctMonitor
//
CNewAcctMonitor::CNewAcctMonitor() { m_cRef = 1; m_rgAccounts = NULL; m_cAlloc = 0; m_cAccounts = 0; m_fMonitor = FALSE; }
CNewAcctMonitor::~CNewAcctMonitor() { Assert(m_rgAccounts == NULL); }
ULONG CNewAcctMonitor::AddRef(void) { return (++m_cRef); }
ULONG CNewAcctMonitor::Release(void) { ULONG cRefT = --m_cRef;
if (0 == m_cRef) delete this;
return (cRefT); }
void CNewAcctMonitor::OnAdvise(ACCTTYPE atType, DWORD dwNotify, LPCSTR pszAcctId) { UINT i; IImnAccount *pAccount; DWORD dwSrvTypes; HRESULT hr; FOLDERTYPE type;
if (atType == ACCT_DIR_SERV) return;
switch (dwNotify) { case AN_ACCOUNT_ADDED: if (atType == ACCT_MAIL) { if (FAILED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAcctId, &pAccount))) break;
hr = pAccount->GetServerTypes(&dwSrvTypes); Assert(SUCCEEDED(hr));
pAccount->Release();
if (!!(dwSrvTypes & SRV_IMAP)) type = FOLDER_IMAP; else if (!!(dwSrvTypes & SRV_HTTPMAIL)) type = FOLDER_HTTPMAIL; else break; } else { Assert(atType == ACCT_NEWS); type = FOLDER_NEWS; }
// Check to see if we need to grow our array
if ((1 + m_cAccounts) >= m_cAlloc) { if (!MemRealloc((LPVOID *)&m_rgAccounts, sizeof(NEWACCTINFO) * (10 + m_cAlloc))) break;
m_cAlloc += 10; }
m_rgAccounts[m_cAccounts].pszAcctId = PszDupA(pszAcctId); m_rgAccounts[m_cAccounts].type = type; m_cAccounts++; break;
case AN_ACCOUNT_DELETED: // Check to see if we've already added this to our list.
for (i = 0; i < m_cAccounts; i++) { if (0 == lstrcmpi(pszAcctId, m_rgAccounts[i].pszAcctId)) { // We found it. We need to remove it, and adjust our array
MemFree(m_rgAccounts[i].pszAcctId); m_cAccounts--; for (; i < m_cAccounts; i++) m_rgAccounts[i] = m_rgAccounts[i + 1]; break; } } break; } }
void CNewAcctMonitor::StartMonitor(void) { Assert(m_rgAccounts == NULL); Assert(m_cAccounts == NULL); Assert(m_fMonitor == FALSE);
m_fMonitor = TRUE; }
void CNewAcctMonitor::StopMonitor(HWND hwndParent) { FOLDERID id; HRESULT hr; UINT i;
Assert(m_fMonitor == TRUE);
// If we have any new newsgroups left, ask if the user want's to display
// the subscription dialog.
if (m_cAccounts != 0) { int ResId; BOOL fOffline = (g_pConMan && g_pConMan->IsGlobalOffline());
if (m_rgAccounts[0].type == FOLDER_NEWS) { ResId = fOffline ? idsDisplayNewsSubDlgOffline : idsDisplayNewsSubDlg; } else { ResId = fOffline ? idsDisplayImapSubDlgOffline : idsDisplayImapSubDlg; }
if (IDYES == AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(ResId), 0, MB_ICONEXCLAMATION | MB_YESNO)) { hr = g_pStore->FindServerId(m_rgAccounts[0].pszAcctId, &id); if (SUCCEEDED(hr)) { if (fOffline) g_pConMan->SetGlobalOffline(FALSE);
if (FOLDER_HTTPMAIL == m_rgAccounts[0].type) DownloadNewsgroupList(hwndParent, id); else DoSubscriptionDialog(hwndParent, m_rgAccounts[0].type == FOLDER_NEWS, id); } } }
for (i = 0; i < m_cAccounts; i++) { if (m_rgAccounts[i].pszAcctId != NULL) MemFree(m_rgAccounts[i].pszAcctId); } m_cAccounts = 0; m_cAlloc = 0;
SafeMemFree(m_rgAccounts); m_fMonitor = FALSE; }
void CheckIMAPDirty(LPSTR pszAccountID, HWND hwndParent, FOLDERID idServer, DWORD dwFlags) { HRESULT hr; IImnAccount *pAcct = NULL; DWORD dw;
TraceCall("CheckIMAPDirty");
hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccountID, &pAcct); if (FAILED(hr)) { TraceResult(hr); goto exit; }
hr = pAcct->GetPropDw(AP_IMAP_DIRTY, &dw); if (FAILED(hr) || 0 == dw) { TraceError(hr); goto exit; }
// IMAP is dirty, deal with each dirty flag
if ((dw & IMAP_OE4MIGRATE_DIRTY) && FOLDERID_INVALID != idServer && NULL != g_pStore) { IEnumerateFolders *pEnum; BOOL fSentItems = FALSE; BOOL fDrafts = FALSE; BOOL fInbox = FALSE;
Assert(0 == (dw & IMAP_OE4MIGRATE_DIRTY) || (dw & IMAP_FLDRLIST_DIRTY));
// We may or may not be dirty. Check if all IMAP special fldrs already present
hr = g_pStore->EnumChildren(idServer, FALSE, &pEnum); TraceError(hr); if (SUCCEEDED(hr)) { FOLDERINFO fiFolderInfo;
while (S_OK == pEnum->Next(1, &fiFolderInfo, NULL)) { switch (fiFolderInfo.tySpecial) { case FOLDER_INBOX: fInbox = TRUE; break;
case FOLDER_SENT: fSentItems = TRUE; break;
case FOLDER_DRAFT: fDrafts = TRUE; break; }
g_pStore->FreeRecord(&fiFolderInfo); }
pEnum->Release(); }
if (fInbox && fSentItems && fDrafts) { // All special folders present: remove dirty flags
dw &= ~(IMAP_FLDRLIST_DIRTY | IMAP_OE4MIGRATE_DIRTY); } }
if (dw & IMAP_FLDRLIST_DIRTY) { int iResult;
// Ask user if he would like to reset his folderlist
if (0 == (dwFlags & CID_NOPROMPT)) { UINT uiReasonStrID;
AssertSz(0 == (dwFlags & CID_RESETLISTOK), "If I have permission to reset, why prompt?");
// Figure out why we are asking to refresh the folderlist
if (dw & IMAP_OE4MIGRATE_DIRTY) uiReasonStrID = idsOE5IMAPSpecialFldrs; else uiReasonStrID = idsYouMadeChanges;
iResult = AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(uiReasonStrID), MAKEINTRESOURCEW(idsRefreshFolderListPrompt), MB_ICONEXCLAMATION | MB_YESNO); } else iResult = (dwFlags & CID_RESETLISTOK) ? IDYES : IDNO;
if (IDYES == iResult) { if (FOLDERID_INVALID == idServer) { hr = g_pStore->FindServerId(pszAccountID, &idServer); TraceError(hr); }
if (FOLDERID_INVALID != idServer) { //The user wants to download the list of newsgroups, so if we are offline, go online
if (g_pConMan) g_pConMan->SetGlobalOffline(FALSE);
hr = DownloadNewsgroupList(hwndParent, idServer); TraceError(hr); if (SUCCEEDED(hr)) { // The sent items and drafts folders should not be dirty any longer
dw &= ~(IMAP_SENTITEMS_DIRTY | IMAP_DRAFTS_DIRTY); } } }
// Regardless of yes or no, reset dirty flag
dw &= ~(IMAP_FLDRLIST_DIRTY | IMAP_OE4MIGRATE_DIRTY); }
if (dw & (IMAP_SENTITEMS_DIRTY | IMAP_DRAFTS_DIRTY)) { IEnumerateFolders *pEnum; char szSentItems[MAX_PATH]; char szDrafts[MAX_PATH]; DWORD dwIMAPSpecial = 0; BOOL fSetSentItems = FALSE; BOOL fSetDrafts = FALSE;
// Remove all affected special folder types from cache. If new path is
// found in folderlist, set its special folder type
szSentItems[0] = '\0'; szDrafts[0] = '\0'; hr = pAcct->GetPropDw(AP_IMAP_SVRSPECIALFLDRS, &dwIMAPSpecial); if (SUCCEEDED(hr) && dwIMAPSpecial) { if (dw & IMAP_SENTITEMS_DIRTY) { hr = pAcct->GetPropSz(AP_IMAP_SENTITEMSFLDR, szSentItems, ARRAYSIZE(szSentItems)); TraceError(hr); }
if (dw & IMAP_DRAFTS_DIRTY) { hr = pAcct->GetPropSz(AP_IMAP_DRAFTSFLDR, szDrafts, ARRAYSIZE(szDrafts)); TraceError(hr); } }
hr = g_pStore->EnumChildren(idServer, FALSE, &pEnum); TraceError(hr); if (SUCCEEDED(hr)) { FOLDERINFO fiFolderInfo;
while (S_OK == pEnum->Next(1, &fiFolderInfo, NULL)) { BOOL fUpdate = FALSE;
if (dw & IMAP_SENTITEMS_DIRTY) { if (0 == lstrcmp(szSentItems, fiFolderInfo.pszName)) { fiFolderInfo.tySpecial = FOLDER_SENT; fUpdate = TRUE; fSetSentItems = TRUE;
// IE5 Bug #62765: if new special folder is unsubscribed, we need to subscribe it
if (0 == (fiFolderInfo.dwFlags & FOLDER_SUBSCRIBED)) fiFolderInfo.dwFlags |= FOLDER_SUBSCRIBED | FOLDER_CREATEONDEMAND; } else if (FOLDER_SENT == fiFolderInfo.tySpecial) { // Ignore FOLDER_HIDDEN. I'm assuming it's no big deal to leave a tombstone
fiFolderInfo.tySpecial = FOLDER_NOTSPECIAL; fUpdate = TRUE; } }
if (dw & IMAP_DRAFTS_DIRTY) { if (0 == lstrcmp(szDrafts, fiFolderInfo.pszName)) { fiFolderInfo.tySpecial = FOLDER_DRAFT; fUpdate = TRUE; fSetDrafts = TRUE;
// IE5 Bug #62765: if new special folder exists and is unsubscribed, we must subscribe it
if (0 == (fiFolderInfo.dwFlags & FOLDER_SUBSCRIBED)) fiFolderInfo.dwFlags |= FOLDER_SUBSCRIBED | FOLDER_CREATEONDEMAND; } else if (FOLDER_DRAFT == fiFolderInfo.tySpecial) { // Ignore FOLDER_HIDDEN. I'm assuming it's no big deal to leave a tombstone
fiFolderInfo.tySpecial = FOLDER_NOTSPECIAL; fUpdate = TRUE; } }
if (fUpdate) { hr = g_pStore->UpdateRecord(&fiFolderInfo); TraceError(hr); }
g_pStore->FreeRecord(&fiFolderInfo); } // while
pEnum->Release(); } // if (SUCCEEDED(EnumChildren))
// If the new special folder path(s) not found in folderlist, need to create placeholder folder
if (dwIMAPSpecial && (dw & IMAP_SENTITEMS_DIRTY) && FALSE == fSetSentItems && '\0' != szSentItems[0]) { FOLDERINFO fiFolderInfo; BOOL bHierarchy = 0xFF; // Invalid hierarchy char
hr = g_pStore->GetFolderInfo(idServer, &fiFolderInfo); if (SUCCEEDED(hr)) { bHierarchy = fiFolderInfo.bHierarchy; g_pStore->FreeRecord(&fiFolderInfo); }
ZeroMemory(&fiFolderInfo, sizeof(fiFolderInfo)); fiFolderInfo.idParent = idServer; fiFolderInfo.pszName = szSentItems; fiFolderInfo.dwFlags = FOLDER_HIDDEN | FOLDER_SUBSCRIBED | FOLDER_CREATEONDEMAND; fiFolderInfo.tySpecial = FOLDER_SENT; fiFolderInfo.tyFolder = FOLDER_IMAP; fiFolderInfo.bHierarchy = (BYTE)bHierarchy;
hr = g_pStore->CreateFolder(CREATE_FOLDER_LOCALONLY, &fiFolderInfo, NULL); TraceError(hr); }
if (dwIMAPSpecial && (dw & IMAP_DRAFTS_DIRTY) && FALSE == fSetDrafts && '\0' != szDrafts[0]) { FOLDERINFO fiFolderInfo; BOOL bHierarchy = 0xFF; // Invalid hierarchy char
hr = g_pStore->GetFolderInfo(idServer, &fiFolderInfo); if (SUCCEEDED(hr)) { bHierarchy = fiFolderInfo.bHierarchy; g_pStore->FreeRecord(&fiFolderInfo); }
ZeroMemory(&fiFolderInfo, sizeof(fiFolderInfo)); fiFolderInfo.idParent = idServer; fiFolderInfo.pszName = szDrafts; fiFolderInfo.dwFlags = FOLDER_HIDDEN | FOLDER_SUBSCRIBED | FOLDER_CREATEONDEMAND; fiFolderInfo.tySpecial = FOLDER_DRAFT; fiFolderInfo.tyFolder = FOLDER_IMAP; fiFolderInfo.bHierarchy = (BYTE)bHierarchy;
hr = g_pStore->CreateFolder(CREATE_FOLDER_LOCALONLY, &fiFolderInfo, NULL); TraceError(hr); }
// Regardless of error, reset dirty flag
dw &= ~(IMAP_SENTITEMS_DIRTY | IMAP_DRAFTS_DIRTY);
} // if (dw & (IMAP_SENTITEMS_DIRTY | IMAP_DRAFTS_DIRTY))
AssertSz(0 == dw, "Unhandled IMAP dirty flag");
// Reset IMAP dirty property
hr = pAcct->SetPropDw(AP_IMAP_DIRTY, dw); if (FAILED(hr)) { TraceResult(hr); goto exit; }
// Save changes
hr = pAcct->SaveChanges(); if (FAILED(hr)) { TraceResult(hr); goto exit; }
exit: if (NULL != pAcct) pAcct->Release(); }
void CheckAllIMAPDirty(HWND hwndParent) { HRESULT hrResult; IImnEnumAccounts *pAcctEnum = NULL; IImnAccount *pAcct = NULL; BOOL fPromptedUser = FALSE; BOOL fPermissionToReset = FALSE;
TraceCall("CheckAllIMAPDirty");
if (NULL == g_pAcctMan) return;
hrResult = g_pAcctMan->Enumerate(SRV_IMAP, &pAcctEnum); if (FAILED(hrResult)) { TraceResult(hrResult); goto exit; }
// Enumerate through ALL IMAP accounts (even if user denied permission to reset list)
hrResult = pAcctEnum->GetNext(&pAcct); while(SUCCEEDED(hrResult)) { DWORD dwIMAPDirty;
// Is this IMAP account dirty?
hrResult = pAcct->GetPropDw(AP_IMAP_DIRTY, &dwIMAPDirty); if (FAILED(hrResult)) dwIMAPDirty = 0;
if (dwIMAPDirty & IMAP_FLDRLIST_DIRTY) { // Prompt user only once to see if he would like to refresh folder list
if (FALSE == fPromptedUser) { int iResult;
iResult = AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsYouMadeChangesOneOrMore), MAKEINTRESOURCEW(idsRefreshFolderListPrompt), MB_ICONEXCLAMATION | MB_YESNO); if (IDYES == iResult) fPermissionToReset = TRUE;
fPromptedUser = TRUE; } // if (FALSE == fPromptedUser)
}
if (dwIMAPDirty) { FOLDERID idServer; char szAccountID[CCHMAX_ACCOUNT_NAME];
hrResult = pAcct->GetPropSz(AP_ACCOUNT_ID, szAccountID, ARRAYSIZE(szAccountID)); TraceError(hrResult); if (SUCCEEDED(hrResult)) { hrResult = g_pStore->FindServerId(szAccountID, &idServer); TraceError(hrResult); if (SUCCEEDED(hrResult)) { CheckIMAPDirty(szAccountID, hwndParent, idServer, CID_NOPROMPT | (fPermissionToReset ? CID_RESETLISTOK : 0)); } } }
// Load in the next IMAP account
SafeRelease(pAcct); hrResult = pAcctEnum->GetNext(&pAcct);
} // while
exit: SafeRelease(pAcctEnum); SafeRelease(pAcct); }
void DoAccountListDialog(HWND hwnd, ACCTTYPE type) { ACCTLISTINFO ali;
// Create the monitor
if (NULL == g_pNewAcctMonitor) g_pNewAcctMonitor = new CNewAcctMonitor();
if (g_pNewAcctMonitor) g_pNewAcctMonitor->StartMonitor();
Assert(g_pAcctMan != NULL);
ali.cbSize = sizeof(ACCTLISTINFO); ali.AcctTypeInit = type;
if (g_dwAthenaMode & MODE_NEWSONLY) ali.dwAcctFlags = ACCT_FLAG_NEWS | ACCT_FLAG_DIR_SERV; else if (g_dwAthenaMode & MODE_MAILONLY) ali.dwAcctFlags = ACCT_FLAG_MAIL | ACCT_FLAG_DIR_SERV; else ali.dwAcctFlags = ACCT_FLAG_ALL;
ali.dwFlags = ACCTDLG_SHOWIMAPSPECIAL | ACCTDLG_OE;
//Account wizard uses this flag to distinguish between OE and outlook.
ali.dwFlags |= (ACCTDLG_INTERNETCONNECTION | ACCTDLG_HTTPMAIL);
// Revocation checking flag
if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline()) ali.dwFlags |= ACCTDLG_REVOCATION;
g_pAcctMan->AccountListDialog(hwnd, &ali);
if (g_pNewAcctMonitor) { g_pNewAcctMonitor->StopMonitor(hwnd); g_pNewAcctMonitor->Release(); g_pNewAcctMonitor = 0; }
// Look for any dirty IMAP accounts
CheckAllIMAPDirty(hwnd); }
HRESULT IsValidSendAccount(LPSTR pszAccount) { IImnAccount *pAccount; DWORD dwSrvTypes=0;
if (g_pAcctMan && g_pAcctMan->FindAccount(AP_ACCOUNT_NAME, pszAccount, &pAccount)==S_OK) { pAccount->GetServerTypes(&dwSrvTypes); pAccount->Release(); return dwSrvTypes & SRV_SMTP ? S_OK : S_FALSE; }
return S_FALSE; }
HRESULT AcctUtil_CreateSendReceieveMenu(HMENU hMenu, DWORD *pcItems) { IImnAccount *pAccount; TCHAR szDefaultAccount[CCHMAX_ACCOUNT_NAME]; HRESULT hr; IImnEnumAccounts *pEnum; DWORD cAccounts = 0; TCHAR szTitle[CCHMAX_ACCOUNT_NAME + 30]; TCHAR szAccountQuoted[CCHMAX_ACCOUNT_NAME + 60]; TCHAR szDefaultString[CCHMAX_STRINGRES]; TCHAR szAccount[CCHMAX_ACCOUNT_NAME]; TCHAR szTruncAcct[128]; MENUITEMINFO mii; DWORD iAccount = 0; LPTSTR pszAccount; LPSTR pszAcctID; // Get the default account's ID. If this fails we just go on.
if (SUCCEEDED(hr = g_pAcctMan->GetDefaultAccount(ACCT_MAIL, &pAccount))) { // Get the account ID from the default account
pAccount->GetPropSz(AP_ACCOUNT_NAME, szDefaultAccount, ARRAYSIZE(szDefaultAccount)); pAccount->Release(); }
if (!(g_dwAthenaMode & MODE_NEWSONLY)) { // Enumerate through the servers
if (SUCCEEDED(hr = g_pAcctMan->Enumerate(SRV_SMTP | SRV_POP3 | SRV_HTTPMAIL, &pEnum))) { // Sort the accounts. If this fails, we just go on.
pEnum->SortByAccountName();
// Get the number of accounts we'll be enumerating
if (SUCCEEDED(hr = pEnum->GetCount(&cAccounts))) { // If there are zero accounts, there's nothing to do.
if (0 != cAccounts) { // Make sure we have enough ID's reserved for this
Assert(cAccounts < ID_ACCOUNT_LAST - ID_ACCOUNT_FIRST);
// Set this struct up before we start
ZeroMemory(&mii, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE; mii.fType = MFT_STRING;
// Loop through the accounts
while (SUCCEEDED(pEnum->GetNext(&pAccount))) { if (MemAlloc((LPVOID *) &pszAcctID, sizeof(TCHAR) * CCHMAX_ACCOUNT_NAME)) { // Get the name of the account
pAccount->GetPropSz(AP_ACCOUNT_NAME, szAccount, CCHMAX_ACCOUNT_NAME); pAccount->GetPropSz(AP_ACCOUNT_ID, pszAcctID, CCHMAX_ACCOUNT_NAME);
// If this account is the default account, we need to append
// "(Default)" to the end. Limit the string to 80 since Win95 seems
// to have some problems with really really long menus.
if (0 == lstrcmp(szAccount, szDefaultAccount)) { AthLoadString(idsDefaultAccount, szDefaultString, ARRAYSIZE(szDefaultString)); StrCpyN(szTruncAcct, szAccount, 80); wnsprintf(szTitle, ARRAYSIZE(szTitle), "%s %s", szTruncAcct, szDefaultString); } else { StrCpyN(szTitle, szAccount, 80); }
// For account names with "&" characters like AT&T, we need to
// quote the "&".
PszEscapeMenuStringA(szTitle, szAccountQuoted, ARRAYSIZE(szAccountQuoted));
// Fill in the struct
mii.wID = ID_ACCOUNT_FIRST + iAccount; mii.dwItemData = (DWORD_PTR) pszAcctID; mii.dwTypeData = szAccountQuoted;
// Append the item
InsertMenuItem(hMenu, -1, TRUE, &mii);
// Increment the count
iAccount++; } // Release the account pointer
pAccount->Release(); } } }
// Release the enumerator
pEnum->Release();
Assert(iAccount == cAccounts); } } else { //Remove Seperator in NEWSONLY mode.
int ItemCount;
ItemCount = GetMenuItemCount(hMenu); if (ItemCount != -1) { DeleteMenu(hMenu, ItemCount - 1, MF_BYPOSITION); } }
//iAccount could be less than cAccounts if we are in news only mode.
if (pcItems) *pcItems = cAccounts;
return (S_OK); }
HRESULT AcctUtil_FreeSendReceieveMenu(HMENU hMenu, DWORD cItems) { DWORD i; MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA;
for (i = 0; i < cItems; i++) { mii.dwItemData = 0; if (GetMenuItemInfo(hMenu, ID_ACCOUNT_FIRST + i, FALSE, &mii)) { if (mii.dwItemData) MemFree((LPTSTR) mii.dwItemData);
DeleteMenu(hMenu, ID_ACCOUNT_FIRST + i, MF_BYCOMMAND); } }
return (S_OK); }
HRESULT AcctUtil_CreateAccountManagerForIdentity(GUID *puidIdentity, IImnAccountManager2 **ppAccountManager) { HRESULT hr; IImnAccountManager *pAccountManager = NULL; IImnAccountManager2 *pAccountManager2 = NULL;
*ppAccountManager = NULL;
if (FAILED(hr = HrCreateAccountManager(&pAccountManager))) goto exit; if (FAILED(hr = pAccountManager->QueryInterface(IID_IImnAccountManager2, (LPVOID *)&pAccountManager2))) goto exit;
// The *puidIdentity does not result in a new GUID object being created (formal param is by reference)
if (FAILED(hr = pAccountManager2->InitUser(NULL, *puidIdentity, 0))) goto exit;
*ppAccountManager = pAccountManager2; pAccountManager2 = NULL; exit: SafeRelease(pAccountManager); SafeRelease(pAccountManager2);
return hr; }
void InitNewAcctMenu(HMENU hmenu) { HKEY hkey, hkeyT; LONG lResult; DWORD cServices, cb, i, type, cItem, dwMsn; char szKey[MAX_PATH], sz[512], szQuoted[512]; HMENU hsubmenu; MENUITEMINFO mii; LPSTR pszKey; BOOL fHideHotmail = HideHotmail();
cItem = 0; hsubmenu = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szHTTPMailServiceRoot, 0, KEY_READ, &hkey)) { if (ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, 0, &cServices, NULL, NULL, NULL, NULL, NULL, NULL, NULL) && cServices > 0) { mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE; mii.fType = MFT_STRING; hsubmenu = CreatePopupMenu(); if (hsubmenu != NULL) { // Start Enumerating the keys
for (i = 0; i < cServices; i++) { // Enumerate Friendly Names
cb = sizeof(szKey); lResult = RegEnumKeyEx(hkey, i, szKey, &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) { Assert(FALSE); continue; } if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szKey, 0, KEY_QUERY_VALUE, &hkeyT)) {
cb = sizeof(dwMsn); if (!fHideHotmail || ERROR_SUCCESS != RegQueryValueEx(hkeyT, c_szHTTPMailDomainMSN, 0, NULL, (LPBYTE)&dwMsn, &cb) || dwMsn == 0)
{ cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hkeyT, c_szHTTPMailSignUp, NULL, &type, (LPBYTE)sz, &cb) && *sz != 0) { cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hkeyT, c_szHTTPMailServiceName, NULL, &type, (LPBYTE)sz, &cb) && *sz != 0) { pszKey = PszDup(szKey); if (pszKey != NULL) { PszEscapeMenuStringA(sz, szQuoted, ARRAYSIZE(szQuoted));
// Fill in the struct
mii.wID = ID_NEW_ACCT_FIRST + cItem; mii.dwItemData = (DWORD_PTR)pszKey; mii.dwTypeData = szQuoted; // Append the item
InsertMenuItem(hsubmenu, -1, TRUE, &mii);
cItem++; } } } }
RegCloseKey(hkeyT); } } } }
RegCloseKey(hkey); }
if (cItem == 0) { if (hsubmenu != NULL) DestroyMenu(hsubmenu);
DeleteMenu(hmenu, ID_POPUP_NEW_ACCT, MF_BYCOMMAND); } else { Assert(hsubmenu != NULL); mii.fMask = MIIM_SUBMENU; mii.hSubMenu = hsubmenu; SetMenuItemInfo(hmenu, ID_POPUP_NEW_ACCT, FALSE, &mii); } }
void FreeNewAcctMenu(HMENU hmenu) { int i, cItem; MENUITEMINFO mii; HMENU hsubmenu;
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; mii.hSubMenu = NULL;
if (GetMenuItemInfo(hmenu, ID_POPUP_NEW_ACCT, FALSE, &mii) && mii.hSubMenu != NULL) { hsubmenu = mii.hSubMenu; cItem = GetMenuItemCount(hsubmenu);
mii.fMask = MIIM_DATA;
for (i = 0; i < cItem; i++) { mii.dwItemData = 0; if (GetMenuItemInfo(hsubmenu, ID_NEW_ACCT_FIRST + i, FALSE, &mii)) { if (mii.dwItemData) MemFree((LPSTR)mii.dwItemData); } }
DestroyMenu(hsubmenu); } }
HRESULT HandleNewAcctMenu(HWND hwnd, HMENU hmenu, int id) { MENUITEMINFO mii; char szKey[MAX_PATH], szUrl[512]; HKEY hkey; DWORD type, cb, dwUseWizard; TCHAR rgch[MAX_PATH]; BOOL bFoundUrl = TRUE;
mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_DATA|MIIM_TYPE; mii.dwItemData = 0; mii.dwTypeData = rgch; mii.cch = ARRAYSIZE(rgch);
if (GetMenuItemInfo(hmenu, id, FALSE, &mii) && mii.dwItemData != 0) { wnsprintf(szKey, ARRAYSIZE(szKey), c_szPathFileFmt, c_szHTTPMailServiceRoot, (LPSTR)mii.dwItemData); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkey)) { // look for a config url
cb = sizeof(szUrl); if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szHTTPMailConfig, NULL, &type, (LPBYTE)szUrl, &cb)) { // config url wasn't found. fall back to sign up url
cb = sizeof(szUrl); if (ERROR_SUCCESS != RegQueryValueEx(hkey, c_szHTTPMailSignUp, NULL, &type, (LPBYTE)szUrl, &cb)) bFoundUrl = FALSE; }
if (bFoundUrl) { cb = sizeof(DWORD); if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szHTTPMailUseWizard, NULL, &type, (LPBYTE)&dwUseWizard, &cb) && dwUseWizard != 0) DoHotMailWizard(GetTopMostParent(hwnd), szUrl, rgch, NULL, NULL); else ShellExecute(hwnd, "open", szUrl, NULL, NULL, SW_SHOWNORMAL); } RegCloseKey(hkey); } }
return(S_OK); }
|