Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1394 lines
41 KiB

/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
//
// MODULE: menuutil.cpp
//
// PURPOSE: Reusable menu & menu command handling code
//
#include "pch.hxx"
#include "resource.h"
#include "menuutil.h"
#include "imnact.h"
#include "strconst.h"
#include "fldrprop.h"
#include "mailutil.h"
#include "mimeutil.h"
#include "inetcfg.h"
#include "newfldr.h"
#include "browser.h"
#include "instance.h"
#include "statbar.h"
#include "storutil.h"
#include "subscr.h"
#include "demand.h"
#include "menures.h"
#include "statnery.h"
#include "store.h"
#include <storecb.h>
#include <range.h>
#include <newsdlgs.h>
#include "acctutil.h"
static const UINT c_rgidNewsNoShow[] =
{ ID_NEW_FOLDER, ID_RENAME, ID_DELETE_FOLDER, SEP_MAILFOLDER };
static const UINT c_rgidSubNoShow[] =
{ ID_SUBSCRIBE, ID_UNSUBSCRIBE, SEP_SUBSCRIBE };
static const UINT c_rgidSyncNoShow[] =
{ ID_POPUP_SYNCHRONIZE, SEP_SYNCHRONIZE };
static const UINT c_rgidCatchUpNoShow[] =
{ ID_CATCH_UP, SEP_CATCH_UP };
void DeleteMenuItems(HMENU hMenu, const UINT *rgid, UINT cid)
{
Assert(rgid != NULL);
Assert(cid != 0);
for ( ; cid > 0; cid--, rgid++)
DeleteMenu(hMenu, *rgid, MF_BYCOMMAND);
}
//
// FUNCTION: MenuUtil_GetContextMenu()
//
// PURPOSE: Returns a handle to the context menu that is appropriate for
// the folder type passed in pidl. The correct menu items will
// be enabled, disabled, bolded, etc.
//
// PARAMETERS:
// <in> pidl - PIDL that points to the folder that the caller needs a
// context menu for.
// <out> phMenu - Returns the handle to a popup menu.
//
// RETURN VALUE:
// S_OK - phMenu contains a valid hMenu for the folder
// E_UNEXPECTED - Either there was a problem loading the menu or the
// folder type was unrecognized.
// E_FAIL - The folder type doesn't support a menu.
//
HRESULT MenuUtil_GetContextMenu(FOLDERID idFolder, IOleCommandTarget *pTarget, HMENU *phMenu)
{
HRESULT hr;
TCHAR sz[CCHMAX_STRINGRES];
FOLDERINFO Folder;
HMENU hMenu;
int idMenu;
// Get folder INfo
hr = g_pStore->GetFolderInfo(idFolder, &Folder);
if (FAILED(hr))
return hr;
// Root ?
if (FOLDERID_ROOT == idFolder || ISFLAGSET(Folder.dwFlags, FOLDER_SERVER))
idMenu = IDR_SERVER_POPUP;
else
idMenu = IDR_FOLDER_POPUP;
if (0 == (hMenu = LoadPopupMenu(idMenu)))
{
g_pStore->FreeRecord(&Folder);
return (E_OUTOFMEMORY);
}
// Bold the default menu items
MENUITEMINFO mii;
if (!(MF_GRAYED & GetMenuState(hMenu, ID_OPEN_FOLDER, MF_BYCOMMAND)))
{
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
mii.fState = MFS_DEFAULT;
SetMenuItemInfo(hMenu, ID_OPEN_FOLDER, FALSE, &mii);
}
if (idMenu == IDR_SERVER_POPUP)
{
if (Folder.tyFolder != FOLDER_IMAP)
DeleteMenu(hMenu, ID_IMAP_FOLDERS, MF_BYCOMMAND);
if (Folder.tyFolder != FOLDER_NEWS)
DeleteMenu(hMenu, ID_NEWSGROUPS, MF_BYCOMMAND);
}
else
{
if (Folder.tyFolder == FOLDER_IMAP)
{
AthLoadString(idsShowFolderCmd, sz, ARRAYSIZE(sz));
ModifyMenu(hMenu, ID_SUBSCRIBE, MF_BYCOMMAND | MF_STRING, ID_SUBSCRIBE, sz);
AthLoadString(idsHideFolderCmd, sz, ARRAYSIZE(sz));
ModifyMenu(hMenu, ID_UNSUBSCRIBE, MF_BYCOMMAND | MF_STRING, ID_UNSUBSCRIBE, sz);
}
if (FOLDER_DELETED != Folder.tySpecial)
DeleteMenu(hMenu, ID_EMPTY_WASTEBASKET, MF_BYCOMMAND);
if (FOLDER_JUNK != Folder.tySpecial)
DeleteMenu(hMenu, ID_EMPTY_JUNKMAIL, MF_BYCOMMAND);
if (Folder.tyFolder == FOLDER_NEWS)
DeleteMenuItems(hMenu, c_rgidNewsNoShow, ARRAYSIZE(c_rgidNewsNoShow));
if (Folder.tyFolder != FOLDER_NEWS &&
Folder.tyFolder != FOLDER_IMAP)
DeleteMenuItems(hMenu, c_rgidSubNoShow, ARRAYSIZE(c_rgidSubNoShow));
if (Folder.tyFolder == FOLDER_LOCAL)
DeleteMenuItems(hMenu, c_rgidSyncNoShow, ARRAYSIZE(c_rgidSyncNoShow));
if (Folder.tyFolder != FOLDER_NEWS)
DeleteMenuItems(hMenu, c_rgidCatchUpNoShow, ARRAYSIZE(c_rgidCatchUpNoShow));
}
// Enable / disable
MenuUtil_EnablePopupMenu(hMenu, pTarget);
// Return
*phMenu = hMenu;
g_pStore->FreeRecord(&Folder);
return (S_OK);
}
void MenuUtil_OnSubscribeGroups(HWND hwnd, FOLDERID *pidFolder, DWORD cFolder, BOOL fSubscribe)
{
CStoreCB *pCB;
HRESULT hr;
DWORD iFolder;
char szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
FOLDERINFO info;
Assert(hwnd != NULL);
Assert(pidFolder != NULL);
Assert(cFolder > 0);
ZeroMemory(&info, sizeof(FOLDERINFO));
pCB = NULL;
for (iFolder = 0; iFolder < cFolder; iFolder++, pidFolder++)
{
hr = g_pStore->GetFolderInfo(*pidFolder, &info);
if (FAILED(hr))
break;
if (iFolder == 0)
{
if (!fSubscribe)
{
if (cFolder == 1)
{
AthLoadString(info.tyFolder == FOLDER_NEWS ? idsWantToUnSubscribe : idsWantToHideFolder, szRes, ARRAYSIZE(szRes));
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, info.pszName);
}
else
{
AthLoadString(info.tyFolder == FOLDER_NEWS ? idsWantToUnSubscribeN : idsWantToHideFolderN, szBuf, ARRAYSIZE(szBuf));
}
if (IDOK != DoDontShowMeAgainDlg(hwnd,
info.tyFolder == FOLDER_NEWS ? c_szRegUnsubscribe : c_szRegHide,
MAKEINTRESOURCE(idsAthena), szBuf, MB_OKCANCEL))
{
break;
}
}
if (info.tyFolder == FOLDER_IMAP)
{
pCB = new CStoreCB;
if (pCB == NULL)
break;
hr = pCB->Initialize(hwnd,
fSubscribe ? MAKEINTRESOURCE(idsShowingFolders) : MAKEINTRESOURCE(idsHidingFolders),
FALSE);
if (FAILED(hr))
break;
}
}
if (info.tySpecial == FOLDER_NOTSPECIAL &&
ISFLAGSET(info.dwFlags, FOLDER_SUBSCRIBED) ^ fSubscribe)
{
if (pCB != NULL)
pCB->Reset();
hr = g_pStore->SubscribeToFolder(*pidFolder, fSubscribe, (IStoreCallback *)pCB);
if (hr == E_PENDING)
{
Assert(info.tyFolder == FOLDER_IMAP);
Assert(pCB != NULL);
hr = pCB->Block();
}
if (FAILED(hr))
break;
}
g_pStore->FreeRecord(&info);
}
g_pStore->FreeRecord(&info);
if (pCB != NULL)
{
pCB->Close();
pCB->Release();
}
}
void MenuUtil_DeleteFolders(HWND hwnd, FOLDERID *pidFolder, DWORD cFolder, BOOL fNoTrash)
{
CStoreCB *pCB;
HRESULT hr;
DWORD iFolder, dwFlags;
FOLDERID idDeleted, idServer;
char szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES], szFolder[CCHMAX_FOLDER_NAME];
FOLDERID *pidFolderT;
FOLDERINFO info;
BOOL fPermDelete, fCallback;
Assert(hwnd != NULL);
Assert(pidFolder != NULL);
Assert(cFolder > 0);
pCB = NULL;
fCallback = FALSE;
*szFolder = 0;
if (fNoTrash)
{
dwFlags = DELETE_FOLDER_RECURSIVE | DELETE_FOLDER_NOTRASHCAN;
fPermDelete = TRUE;
}
else
{
dwFlags = DELETE_FOLDER_RECURSIVE;
fPermDelete = FALSE;
for (iFolder = 0, pidFolderT = pidFolder; iFolder < cFolder; iFolder++, pidFolderT++)
{
hr = g_pStore->GetFolderInfo(*pidFolderT, &info);
if (FAILED(hr))
return;
// Skip deletion of any special folders
if (info.tySpecial == FOLDER_NOTSPECIAL)
{
if (iFolder == 0 && cFolder == 1)
StrCpyN(szFolder, info.pszName, ARRAYSIZE(szFolder));
if (info.tyFolder == FOLDER_IMAP ||
info.tyFolder == FOLDER_HTTPMAIL)
{
fPermDelete = TRUE;
fCallback = TRUE;
}
else if (S_OK == IsParentDeletedItems(*pidFolderT, &idDeleted, &idServer))
{
fPermDelete = TRUE;
}
}
g_pStore->FreeRecord(&info);
if (fPermDelete)
break;
}
}
if (fPermDelete)
{
if (cFolder == 1 && *szFolder != 0)
{
AthLoadString(idsWarnDeleteFolder, szRes, ARRAYSIZE(szRes));
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, szFolder);
}
else
{
AthLoadString(idsWarnDeleteFolderN, szBuf, ARRAYSIZE(szBuf));
}
}
else
{
if (cFolder == 1 && *szFolder != 0)
{
AthLoadString(idsPromptDeleteFolder, szRes, ARRAYSIZE(szRes));
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, szFolder);
}
else
{
AthLoadString(idsPromptDeleteFolderN, szBuf, ARRAYSIZE(szBuf));
}
}
if (IDYES != AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf, 0, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2))
return;
if (fCallback)
{
pCB = new CStoreCB;
if (pCB == NULL)
return;
hr = pCB->Initialize(hwnd, MAKEINTRESOURCE(idsDeletingFolder), FALSE);
if (FAILED(hr))
{
pCB->Release();
return;
}
}
for (iFolder = 0, pidFolderT = pidFolder; iFolder < cFolder; iFolder++, pidFolderT++)
{
hr = g_pStore->GetFolderInfo(*pidFolderT, &info);
if (FAILED(hr))
break;
// Skip deletion of any special folders
if (info.tySpecial == FOLDER_NOTSPECIAL)
{
if (pCB != NULL)
pCB->Reset();
hr = g_pStore->DeleteFolder(*pidFolderT, dwFlags, (IStoreCallback *)pCB);
if (hr == E_PENDING)
{
Assert(info.tyFolder == FOLDER_IMAP || info.tyFolder == FOLDER_HTTPMAIL);
Assert(pCB != NULL);
hr = pCB->Block();
}
}
g_pStore->FreeRecord(&info);
if (FAILED(hr))
break;
}
if (pCB != NULL)
{
pCB->Close();
pCB->Release();
}
}
void MenuUtil_SyncThisNow(HWND hwnd, FOLDERID idFolder)
{
UPDATENEWSGROUPINFO uni;
HRESULT hr;
DWORD dwFlags;
FOLDERINFO info;
char szAcctId[CCHMAX_ACCOUNT_NAME];
BOOL fNews, fMarked;
if (g_pSpooler)
{
hr = g_pStore->GetFolderInfo(idFolder, &info);
if (SUCCEEDED(hr))
{
Assert(info.tyFolder == FOLDER_NEWS || info.tyFolder == FOLDER_IMAP || info.tyFolder == FOLDER_HTTPMAIL);
if((info.tyFolder == FOLDER_NEWS) ||
(!g_pConMan->IsAccountDisabled((LPSTR)info.pszAccountId)))
{
fNews = (info.tyFolder == FOLDER_NEWS);
dwFlags = fNews ? DELIVER_NEWS_TYPE : DELIVER_IMAP_TYPE;
//Tells the spooler that this is a sync operation and not Send&Receive
dwFlags |= DELIVER_OFFLINE_SYNC | DELIVER_WATCH | DELIVER_NOSKIP;
if (!!(info.dwFlags & FOLDER_SERVER))
{
// TODO: review these flags to make sure they are correct
//dwFlags |= DELIVER_POLL | DELIVER_NEWS_SEND | DELIVER_NEWSIMAP_NOSKIP | DELIVER_NEWSIMAP_OFFLINE;
dwFlags |= DELIVER_POLL | DELIVER_SEND | DELIVER_OFFLINE_FLAGS;
g_pSpooler->StartDelivery(hwnd, info.pszAccountId, FOLDERID_INVALID, dwFlags);
}
else
{
hr = GetFolderAccountId(&info, szAcctId, ARRAYSIZE(szAcctId));
if (SUCCEEDED(hr))
{
hr = HasMarkedMsgs(idFolder, &fMarked);
if (SUCCEEDED(hr))
{
uni.fNews = fNews;
uni.dwGroupFlags = info.dwFlags;
uni.cMarked = fMarked;
uni.idCmd = dwFlags;
// Display the dialog to find what get thing to get
DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddUpdateNewsgroup), hwnd, UpdateNewsgroup, (LPARAM)&uni);
// Check to see if the user canceled
if (uni.idCmd != -1)
g_pSpooler->StartDelivery(hwnd, szAcctId, idFolder, uni.idCmd);
}
}
}
}
g_pStore->FreeRecord(&info);
}
}
}
//
// FUNCTION: MenuUtil_OnDelete()
//
// PURPOSE: Deletes the folder designated by the pidl.
//
// PARAMETERS:
// <in> hwnd - Handle of the window to display UI over
// <in> pidl - PIDL of the folder to browse to
// <in> pStore - Pointer to the store to delete folders from
//
void MenuUtil_OnDelete(HWND hwnd, FOLDERID idFolder, BOOL fNoTrash)
{
TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
FOLDERINFO Folder;
IImnAccount *pAcct;
// Get Folder Info
if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder)))
return;
// Is a server
if (ISFLAGSET(Folder.dwFlags, FOLDER_SERVER))
{
Assert(g_pAcctMan);
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct)))
{
AthLoadString(idsWarnDeleteAccount, szRes, ARRAYSIZE(szRes));
wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, Folder.pszName);
if (IDYES == AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf,
0, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2))
{
pAcct->Delete();
}
pAcct->Release();
}
}
else
{
if (Folder.tyFolder == FOLDER_NEWS)
{
MenuUtil_OnSubscribeGroups(hwnd, &idFolder, 1, FALSE);
}
else
{
MenuUtil_DeleteFolders(hwnd, &idFolder, 1, fNoTrash);
}
}
g_pStore->FreeRecord(&Folder);
}
//
// FUNCTION: MenuUtil_OnProperties()
//
// PURPOSE: Displays properties for the folder designated by the pidl
//
// PARAMETERS:
// <in> hwnd - Handle of the window to parent the properties
// <in> pidl - PIDL of the folder to browse to
//
void MenuUtil_OnProperties(HWND hwnd, FOLDERID idFolder)
{
IImnAccount *pAcct;
FOLDERINFO Folder;
if (SUCCEEDED(g_pStore->GetFolderInfo(idFolder, &Folder)))
{
if (ISFLAGSET(Folder.dwFlags, FOLDER_SERVER))
{
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct)))
{
HRESULT hr;
Assert(pAcct != NULL);
DWORD dwFlags = ACCTDLG_SHOWIMAPSPECIAL | ACCTDLG_INTERNETCONNECTION | ACCTDLG_OE;
if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline())
dwFlags |= ACCTDLG_REVOCATION;
//We want to use the new dialog for the properties, hence the new flag internetconnection
hr = pAcct->ShowProperties(hwnd, dwFlags);
if (S_OK == hr)
// User hit "OK" to exit, not "Cancel"
CheckIMAPDirty(Folder.pszAccountId, hwnd, idFolder, NOFLAGS);
pAcct->Release();
}
}
else if (FOLDER_NEWS == Folder.tyFolder)
{
GroupProp_Create(hwnd, idFolder);
}
else
{
FolderProp_Create(hwnd, idFolder);
}
g_pStore->FreeRecord(&Folder);
}
}
void MenuUtil_OnSetDefaultServer(FOLDERID idFolder)
{
TCHAR *sz;
IImnAccount *pAcct = 0;
FOLDERINFO Folder;
if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder)))
return;
Assert(ISFLAGSET(Folder.dwFlags, FOLDER_SERVER));
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct)))
{
pAcct->SetAsDefault();
pAcct->Release();
}
g_pStore->FreeRecord(&Folder);
}
void MenuUtil_OnMarkNewsgroups(HWND hwnd, int id, FOLDERID idFolder)
{
FOLDERINFO Folder;
if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder)))
return;
Folder.dwFlags &= ~(FOLDER_DOWNLOADHEADERS | FOLDER_DOWNLOADNEW | FOLDER_DOWNLOADALL);
if (id == ID_MARK_RETRIEVE_FLD_NEW_HDRS)
Folder.dwFlags |= FOLDER_DOWNLOADHEADERS;
else if (id == ID_MARK_RETRIEVE_FLD_ALL_MSGS)
Folder.dwFlags |= FOLDER_DOWNLOADALL;
else if (id == ID_MARK_RETRIEVE_FLD_NEW_MSGS)
Folder.dwFlags |= FOLDER_DOWNLOADNEW;
g_pStore->UpdateRecord(&Folder);
g_pStore->FreeRecord(&Folder);
}
// BUG #41686 Catchup Implementation
void MenuUtil_OnCatchUp(FOLDERID idFolder)
{
FOLDERINFO Folder;
BOOL fFreeRange;
CRangeList *pRange;
IMessageFolder *pFolder;
ADJUSTFLAGS flags;
HCURSOR hcur;
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
if (SUCCEEDED(g_pStore->OpenFolder(idFolder, NULL, NOFLAGS, &pFolder)))
{
flags.dwAdd = ARF_READ;
flags.dwRemove = ARF_DOWNLOAD;
pFolder->SetMessageFlags(NULL, &flags, NULL, NULL);
pFolder->Release();
}
if (SUCCEEDED(g_pStore->GetFolderInfo(idFolder, &Folder)))
{
fFreeRange = FALSE;
if (Folder.dwServerHigh > 0)
{
Folder.dwClientHigh = Folder.dwServerHigh;
pRange = new CRangeList;
if (pRange != NULL)
{
if (Folder.Requested.cbSize > 0)
pRange->Load(Folder.Requested.pBlobData, Folder.Requested.cbSize);
pRange->AddRange(0, Folder.dwServerHigh);
fFreeRange = pRange->Save(&Folder.Requested.pBlobData, &Folder.Requested.cbSize);
pRange->Release();
}
}
else
{
Folder.dwServerLow = 0;
Folder.dwServerHigh = 0;
Folder.dwServerCount = 0;
}
Folder.dwNotDownloaded = 0;
g_pStore->UpdateRecord(&Folder);
if (fFreeRange)
MemFree(Folder.Requested.pBlobData);
g_pStore->FreeRecord(&Folder);
}
SetCursor(hcur);
}
UINT GetMenuItemPos(HMENU hmenu, UINT cmd)
{
MENUITEMINFO mii;
UINT cItem, ipos;
cItem = GetMenuItemCount(hmenu);
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID;
for (ipos = 0; ipos < cItem; ipos++)
{
SideAssert(GetMenuItemInfo(hmenu, ipos, TRUE, &mii));
if (mii.wID == cmd)
break;
}
Assert(ipos != cItem);
return(ipos);
}
BOOL MergeMenus(HMENU hmenuSrc, HMENU hmenuDst, int iPos, UINT uFlags)
{
MENUITEMINFO mii;
UINT uState, i, cMerge;
int cItem;
BOOL fSepPre, fSepPost, fPopup, fCommand;
BYTE rgch[CCHMAX_STRINGRES];
HMENU hmenuPopup;
cMerge = GetMenuItemCount(hmenuSrc);
if (cMerge == 0)
return(TRUE);
cItem = GetMenuItemCount(hmenuDst);
if (iPos == MMPOS_REPLACE)
{
// destroy all menus
while (RemoveMenu(hmenuDst, 0, MF_BYPOSITION));
cItem = 0;
iPos = 0;
}
if (iPos == MMPOS_APPEND)
iPos = cItem;
fCommand = ((uFlags & MMF_BYCOMMAND) != 0);
if (fCommand)
iPos = GetMenuItemPos(hmenuDst, (UINT)iPos);
if (iPos > cItem)
iPos = cItem;
fSepPre = FALSE;
fSepPost = FALSE;
if (uFlags & MMF_SEPARATOR)
{
if (iPos == 0)
{
// prepending, so stick in a separator after all the items
// ASSUMES: never a separator as the last item in a menu
if (cItem > 0)
fSepPost = TRUE;
}
else if (iPos == cItem)
{
// appending, so stick in a separator before all the items
// ASSUMES: never a separator as the first item in a menu
fSepPre = TRUE;
}
else
{
// merging stuff into the middle of the menu, so need to check before and after
uState = GetMenuState(hmenuDst, iPos - 1, MF_BYPOSITION);
if (!(uState & MF_SEPARATOR))
fSepPre = TRUE;
uState = GetMenuState(hmenuDst, iPos, MF_BYPOSITION);
if (!(uState & MF_SEPARATOR))
fSepPost = TRUE;
}
}
if (fSepPre)
{
InsertMenu(hmenuDst, (UINT)iPos, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
iPos++;
}
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
for (i = 0; i < cMerge; i++)
{
mii.dwTypeData = (LPSTR)rgch;
mii.cch = sizeof(rgch);
mii.fType = 0;
GetMenuItemInfo(hmenuSrc, i, TRUE, &mii);
fPopup = (mii.hSubMenu != NULL);
if (!fPopup && (mii.fType & MFT_SEPARATOR))
{
InsertMenuItem(hmenuDst, (UINT)iPos, TRUE, &mii);
}
else
{
if (fPopup)
{
// its a popup submenu item
hmenuPopup = CreateMenu();
MergeMenus(mii.hSubMenu, hmenuPopup, 0, 0);
mii.hSubMenu = hmenuPopup;
}
InsertMenuItem(hmenuDst, (UINT)iPos, TRUE, &mii);
}
iPos++;
}
if (fSepPost)
{
InsertMenu(hmenuDst, (UINT)iPos, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
iPos++;
}
return(TRUE);
}
//
// REVIEW: We need this function because current version of USER.EXE does
// not support pop-up only menu.
//
HMENU LoadPopupMenu(UINT id)
{
HMENU hmenuParent = LoadMenu(g_hLocRes, MAKEINTRESOURCE(id));
if (hmenuParent) {
HMENU hpopup = GetSubMenu(hmenuParent, 0);
RemoveMenu(hmenuParent, 0, MF_BYPOSITION);
DestroyMenu(hmenuParent);
return hpopup;
}
return NULL;
}
// walks a menu recursively, calling pfn for each item that isn't a separator
void WalkMenu(HMENU hMenu, WALKMENUFN pfn, LPVOID lpv)
{
MENUITEMINFO mii;
int i, cItems;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU;
cItems = GetMenuItemCount(hMenu);
for (i=0; i<cItems; i++)
{
mii.dwTypeData = 0;
mii.cch = 0;
if (GetMenuItemInfo(hMenu, i, TRUE, &mii))
{
if (!(mii.fType & MFT_SEPARATOR))
(*pfn)(hMenu, mii.wID, lpv);
if (mii.hSubMenu)
WalkMenu(mii.hSubMenu, pfn, lpv);
}
}
}
void MenuUtil_BuildMenuIDList(HMENU hMenu, OLECMD **prgCmds, ULONG *pcStart, ULONG *pcCmds)
{
ULONG cItems = 0;
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(mii));
if(!IsMenu(hMenu))
return;
// Start by getting the count of items on this menu
cItems = GetMenuItemCount(hMenu);
if (!cItems)
return;
// Realloc the array to be cItems elements bigger
if (!MemRealloc((LPVOID *) prgCmds, sizeof(OLECMD) * (cItems + (*pcCmds))))
return;
*pcCmds += cItems;
// Walk this menu and add our items to it
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_SUBMENU;
for (ULONG i = 0; i < cItems; i++)
{
if (GetMenuItemInfo(hMenu, i, TRUE, &mii))
{
// Make sure this isn't a separator
if (mii.wID != -1 && mii.wID != 0)
{
// Add the ID to our array
(*prgCmds)[*pcStart].cmdID = mii.wID;
(*prgCmds)[*pcStart].cmdf = 0;
(*pcStart)++;
// See if we need to recurse
if (mii.hSubMenu)
{
MenuUtil_BuildMenuIDList(mii.hSubMenu, prgCmds, pcStart, pcCmds);
}
}
}
}
return;
}
//
// FUNCTION: MenuUtil_EnablePopupMenu()
//
// PURPOSE: Walks the given menu and takes care of enabling and
// disabling each item via the provided commnand target.
//
// PARAMETERS:
// [in] hPopup
// [in] *pTarget
//
HRESULT MenuUtil_EnablePopupMenu(HMENU hPopup, IOleCommandTarget *pTarget)
{
HRESULT hr = S_OK;
int i;
int cItems;
OLECMD *rgCmds = NULL;
ULONG cStart = 0;
ULONG cCmds = 0;
MENUITEMINFO mii = {0};
Assert(hPopup && pTarget);
// Build the array of menu ids
MenuUtil_BuildMenuIDList(hPopup, &rgCmds, &cCmds, &cStart);
// Ask our parent for the state of the commands
if (SUCCEEDED(hr = pTarget->QueryStatus(&CMDSETID_OutlookExpress, cCmds, rgCmds, NULL)))
{
mii.cbSize = sizeof(MENUITEMINFO);
// Now loop through the menu and apply the state
for (i = 0; i < (int) cCmds; i++)
{
// The default thing we're going to update is the state
mii.fMask = MIIM_STATE;
// Enabled or Disabled
if (rgCmds[i].cmdf & OLECMDF_ENABLED)
mii.fState = MFS_ENABLED;
else
mii.fState = MFS_GRAYED;
// Checked?
if (rgCmds[i].cmdf & OLECMDF_LATCHED)
mii.fState |= MFS_CHECKED;
// Set the item state
BOOL f;
f = SetMenuItemInfo(hPopup, rgCmds[i].cmdID, FALSE, &mii);
// Radio Check?
if ((rgCmds[i].cmdf & OLECMDF_NINCHED) && rgCmds[i].cmdID != (-1))
{
CheckMenuRadioItem(hPopup, rgCmds[i].cmdID, rgCmds[i].cmdID, rgCmds[i].cmdID, MF_BYCOMMAND);
// mii.fMask |= MIIM_TYPE;
// mii.fType = MFT_RADIOCHECK;
// mii.fState |= MFS_CHECKED;
}
// Assert(f);
}
}
SafeMemFree(rgCmds);
return (hr);
}
void HandleMenuSelect(CStatusBar *pStatus, WPARAM wParam, LPARAM lParam)
{
UINT fuFlags, uItem;
HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
if (!pStatus)
return;
uItem = (UINT) LOWORD(wParam);
fuFlags = (UINT) HIWORD(wParam);
if (fuFlags & MF_POPUP)
{
MENUITEMINFO mii = { sizeof(MENUITEMINFO), MIIM_ID, 0 };
if (hmenu && IsMenu(hmenu))
{
// Windows 98 seems to pass the command ID for popup items instead
// of the documented position. So, if uItem is less than 40000 then
// we can assume this is a menu position otherwise we assume it's
// a command ID.
if (GetMenuItemInfo(hmenu, uItem, (uItem < ID_FIRST), &mii))
{
// change the parameters to simulate a normal menu item
uItem = mii.wID;
fuFlags = 0;
}
}
}
if (0 == (fuFlags & (MF_SYSMENU | MF_POPUP)))
{
TCHAR szMenu[256], szRes[CCHMAX_STRINGRES], szTemp[CCHMAX_STRINGRES + 256];
if (uItem >= ID_SORT_MENU_FIRST && uItem <= ID_SORT_MENU_LAST)
{
MENUITEMINFO mii = {0};
*szMenu = '\0';
*szRes = '\0';
*szTemp = '\0';
// must be a sort menu command! pull the menu name from the menu
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE;
mii.dwTypeData = (LPSTR)szMenu;
mii.cch = ARRAYSIZE(szMenu);
if (GetMenuItemInfo((HMENU)lParam, uItem, FALSE, &mii))
{
AthLoadString(idsSortMenuHelpControl, szRes, sizeof(szRes));
wnsprintf(szTemp, ARRAYSIZE(szTemp), szRes, szMenu);
pStatus->ShowSimpleText(szTemp);
}
}
else if (uItem >= ID_FIRST && uItem <= ID_LAST)
{
uItem = uItem - ID_FIRST;
pStatus->ShowSimpleText(MAKEINTRESOURCE(uItem));
}
else if ((uItem >= ID_VIEW_FILTER_FIRST) && (uItem <= ID_VIEW_FILTER_LAST))
{
if ((uItem >= ID_VIEW_CURRENT) && (uItem <= ID_VIEW_RECENT_4))
{
MENUITEMINFO mii = {0};
*szMenu = '\0';
*szRes = '\0';
*szTemp = '\0';
// must be a sort menu command! pull the menu name from the menu
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE;
mii.dwTypeData = (LPSTR)szMenu;
mii.cch = ARRAYSIZE(szMenu);
if (GetMenuItemInfo((HMENU)lParam, uItem, FALSE, &mii))
{
AthLoadString(idsViewMenuHelpControl, szRes, sizeof(szRes));
wnsprintf(szTemp, ARRAYSIZE(szTemp), szRes, szMenu);
pStatus->ShowSimpleText(szTemp);
}
}
else
{
uItem = uItem - ID_FIRST;
pStatus->ShowSimpleText(MAKEINTRESOURCE(uItem));
}
}
else if ((uItem >= ID_MESSENGER_FIRST) && (uItem<= ID_MESSENGER_LAST))
{
TCHAR szBuf[CCHMAX_STRINGRES] = "";
AthLoadString(uItem - ID_FIRST, szBuf, ARRAYSIZE(szBuf));
MenuUtil_BuildMessengerString(szBuf, ARRAYSIZE(szBuf));
pStatus->ShowSimpleText(szBuf);
}
else
{
if (uItem >= ID_ACCOUNT_FIRST && uItem <= ID_ACCOUNT_LAST)
pStatus->ShowSimpleText(MAKEINTRESOURCE(idsSRAccountMenuHelp));
else
pStatus->ShowSimpleText(0);
}
}
else if (fuFlags == 0xffff && ((HMENU)lParam) == NULL)
{
pStatus->HideSimpleText();
}
}
//
// FUNCTION: MenuUtil_SetPopupDefault()
//
// PURPOSE: Bolds the default item in a context menu
//
// PARAMETERS:
//
// RETURN VALUE:
//
void MenuUtil_SetPopupDefault(HMENU hPopup, UINT idDefault)
{
MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
if (GetMenuItemInfo(hPopup, idDefault, FALSE, &mii))
{
mii.fState |= MFS_DEFAULT;
SetMenuItemInfo(hPopup, idDefault, FALSE , &mii);
}
}
//
// FUNCTION: MenuUtil_ReplaceHelpMenu
//
// PURPOSE: Populates the ID_POPUP_HELP menu
//
void MenuUtil_ReplaceHelpMenu(HMENU hMenu)
{
MENUITEMINFO mii;
if (mii.hSubMenu = LoadPopupMenu(IDR_HELP_POPUP))
{
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_SUBMENU;
SetMenuItemInfo(hMenu, ID_POPUP_HELP, FALSE, &mii);
}
}
//
// FUNCTION: MenuUtil_ReplaceNewMsgMenu
//
// PURPOSE: Populates the ID_POPUP_HELP menu
//
void MenuUtil_ReplaceNewMsgMenus(HMENU hMenu)
{
MENUITEMINFO mii;
if (mii.hSubMenu = LoadPopupMenu(IDR_NEW_MSG_POPUP))
{
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_SUBMENU;
SetMenuItemInfo(hMenu, ID_POPUP_NEW_MSG, FALSE, &mii);
}
}
//
// FUNCTION: MenuUtil_ReplaceMessengerMenus
//
// PURPOSE: Customizes the Messenger menus with IEAK Messenger names...
//
void MenuUtil_ReplaceMessengerMenus(HMENU hMenu)
{
ULONG ulMenuItem;
MENUITEMINFO mii;
TCHAR szName[CCHMAX_STRINGRES];
for(ulMenuItem=ID_MESSENGER_FIRST;ulMenuItem<ID_MESSENGER_LAST;ulMenuItem++)
{
ZeroMemory(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE;
mii.dwTypeData = szName;
mii.cch = CCHMAX_STRINGRES;
if(GetMenuItemInfo(hMenu, ulMenuItem, FALSE, &mii))
{
if(MenuUtil_BuildMessengerString(szName, ARRAYSIZE(szName)))
{
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE;
mii.fType = MFT_STRING;
mii.dwTypeData = szName;
SetMenuItemInfo(hMenu, ulMenuItem, FALSE, &mii);
}
}
}
}
BOOL MenuUtil_BuildMessengerString(LPTSTR szMesStr, DWORD cchMesStr)
{
static TCHAR s_szCustName[51] = ""; //We know the name is less than 50 chars
TCHAR szNewMesStr[CCHMAX_STRINGRES];
HKEY hkey = NULL;
DWORD cb;
BOOL fReplaced=FALSE;
Assert(szMesStr);
if(s_szCustName[0] == 0)
{
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\MessengerService", 0, KEY_READ, &hkey))
{
cb = sizeof(s_szCustName);
RegQueryValueEx(hkey, "", NULL, NULL, (LPBYTE)s_szCustName, &cb);
RegCloseKey(hkey);
}
if(s_szCustName[0] == 0)
AthLoadString(idsServiceName, s_szCustName, ARRAYSIZE(s_szCustName));
}
fReplaced = (NULL != StrStr(szMesStr, "%s"));
//HACK! For strings needing multiple replacement...
if (fReplaced)
{
wnsprintf(szNewMesStr, ARRAYSIZE(szNewMesStr), szMesStr, s_szCustName, s_szCustName, s_szCustName, s_szCustName);
StrCpyN(szMesStr, szNewMesStr, cchMesStr);
}
return fReplaced;
}
void GetDefaultFolderID(BOOL fMail, FOLDERID *pFolderID)
{
IImnAccount *pAcct = NULL;
CHAR szAccountId[CCHMAX_ACCOUNT_NAME];
IEnumerateFolders *pEnumFolders = NULL;
FOLDERINFO rFolder;
BOOL fFound = FALSE;
ACCTTYPE acctType = ACCT_NEWS;
DWORD dwServerTypes = 0;
*pFolderID = FOLDERID_INVALID;
if (FAILED(g_pAcctMan->GetDefaultAccount(fMail?ACCT_MAIL:ACCT_NEWS, &pAcct)))
goto Exit;
if (FAILED(pAcct->GetAccountType(&acctType)))
goto Exit;
if ((ACCT_NEWS != acctType) && SUCCEEDED(pAcct->GetServerTypes(&dwServerTypes)) && (dwServerTypes & SRV_POP3))
{
*pFolderID = FOLDERID_LOCAL_STORE;
goto Exit;
}
*szAccountId = 0;
if (FAILED(pAcct->GetPropSz(AP_ACCOUNT_ID, szAccountId, ARRAYSIZE(szAccountId))))
goto Exit;
if (FAILED(g_pStore->EnumChildren(FOLDERID_ROOT, TRUE, &pEnumFolders)))
goto Exit;
AssertSz(pAcct, "How did we succeed and not get a pAcct?");
AssertSz(pEnumFolders, "How did we succeed and not get a pEnumFolders?");
while (!fFound && (S_OK == pEnumFolders->Next(1, &rFolder, NULL)))
{
fFound = (0 == lstrcmp(szAccountId, rFolder.pszAccountId));
if (fFound)
*pFolderID = rFolder.idFolder;
g_pStore->FreeRecord(&rFolder);
}
Exit:
ReleaseObj(pAcct);
ReleaseObj(pEnumFolders);
}
//
// FUNCTION: MenuUtil_HandleNewMessageIDs
//
// PURPOSE: Handles creation of notes from an ID
//
// RETURN VALUE: Returns TRUE if event was handled
//
BOOL MenuUtil_HandleNewMessageIDs(DWORD id, HWND hwnd, FOLDERID folderID, BOOL fMail, BOOL fModal, IUnknown *pUnkPump)
{
switch (id)
{
case ID_NEW_NEWS_MESSAGE:
case ID_NEW_MAIL_MESSAGE:
case ID_NEW_MSG_DEFAULT:
{
FOLDERINFO rInfo = {0};
if (id != ID_NEW_MSG_DEFAULT)
fMail = (id == ID_NEW_MAIL_MESSAGE);
if (SUCCEEDED(g_pStore->GetFolderInfo(folderID, &rInfo)))
{
BOOL fFolderIsMail = (rInfo.tyFolder != FOLDER_NEWS);
if (fFolderIsMail != fMail)
GetDefaultFolderID(fMail, &folderID);
g_pStore->FreeRecord(&rInfo);
}
if (DwGetOption(fMail ? OPT_MAIL_USESTATIONERY : OPT_NEWS_USESTATIONERY))
{
WCHAR wszFile[MAX_PATH];
if (SUCCEEDED(GetDefaultStationeryName(fMail, wszFile)) &&
SUCCEEDED(HrNewStationery(hwnd, 0, wszFile, fModal, fMail, folderID, FALSE, NSS_DEFAULT, pUnkPump, NULL)))
{
return TRUE;
}
// If HrNewStationery fails, go ahead and try opening a blank note without stationery.
}
FNewMessage(hwnd, fModal, !DwGetOption(fMail ? OPT_MAIL_SEND_HTML : OPT_NEWS_SEND_HTML), !fMail, folderID, pUnkPump);
return TRUE;
}
case ID_STATIONERY_RECENT_0:
case ID_STATIONERY_RECENT_1:
case ID_STATIONERY_RECENT_2:
case ID_STATIONERY_RECENT_3:
case ID_STATIONERY_RECENT_4:
case ID_STATIONERY_RECENT_5:
case ID_STATIONERY_RECENT_6:
case ID_STATIONERY_RECENT_7:
case ID_STATIONERY_RECENT_8:
case ID_STATIONERY_RECENT_9:
HrNewStationery(hwnd, id, NULL, fModal, fMail, folderID, TRUE, NSS_MRU, pUnkPump, NULL);
return TRUE;
case ID_STATIONERY_MORE:
HrMoreStationery(hwnd, fModal, fMail, folderID, pUnkPump);
return TRUE;
case ID_STATIONERY_NONE:
FNewMessage(hwnd, fModal, TRUE, !fMail, folderID, pUnkPump);
return TRUE;
case ID_WEB_PAGE:
HrSendWebPage(hwnd, fModal, fMail, folderID, pUnkPump);
return TRUE;
}
return FALSE;
}
HRESULT MenuUtil_NewMessageIDsQueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText, BOOL fMail)
{
DWORD cMailServer = 0;
DWORD cNewsServer = 0;
DWORD cDefServer = 0;
DWORD dwDefFlags;
// For right now, NULL is acceptable.
if (pguidCmdGroup && !IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
return S_OK;
g_pAcctMan->GetAccountCount(ACCT_NEWS, &cMailServer);
g_pAcctMan->GetAccountCount(ACCT_MAIL, &cNewsServer);
cDefServer = fMail ? cMailServer : cNewsServer;
// If there is at least one server and we are not mail in news only mode
if (!fMail || (0 == (g_dwAthenaMode & MODE_NEWSONLY)))
dwDefFlags = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
else
dwDefFlags = OLECMDF_SUPPORTED;
for (UINT i = 0; i < cCmds; i++)
{
if (prgCmds[i].cmdf == 0)
{
switch (prgCmds[i].cmdID)
{
case ID_POPUP_NEW_MSG:
case ID_NEW_MSG_DEFAULT:
case ID_STATIONERY_RECENT_0:
case ID_STATIONERY_RECENT_1:
case ID_STATIONERY_RECENT_2:
case ID_STATIONERY_RECENT_3:
case ID_STATIONERY_RECENT_4:
case ID_STATIONERY_RECENT_5:
case ID_STATIONERY_RECENT_6:
case ID_STATIONERY_RECENT_7:
case ID_STATIONERY_RECENT_8:
case ID_STATIONERY_RECENT_9:
case ID_STATIONERY_MORE:
case ID_STATIONERY_NONE:
prgCmds[i].cmdf = dwDefFlags;
break;
case ID_WEB_PAGE:
// If is enabled, then better make sure that we are on line.
if ((dwDefFlags & OLECMDF_ENABLED) && g_pConMan->IsGlobalOffline())
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
else
prgCmds[i].cmdf = dwDefFlags;
break;
case ID_NEW_MAIL_MESSAGE:
if (!(g_dwAthenaMode & MODE_NEWSONLY))
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
else
prgCmds[i].cmdf = OLECMDF_SUPPORTED;
break;
case ID_NEW_NEWS_MESSAGE:
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
break;
}
}
}
return S_OK;
}
HRESULT MenuUtil_EnableMenu(HMENU hMenu, IOleCommandTarget *pTarget)
{
int Count;
HMENU hMenuSub;
HRESULT hr = S_OK;
Count = GetMenuItemCount(hMenu);
if (Count != -1)
{
while (--Count >= 0)
{
hMenuSub = GetSubMenu(hMenu, Count);
hr = MenuUtil_EnablePopupMenu(hMenuSub, pTarget);
}
}
else
hr = E_FAIL;
return hr;
}