📄 inboxmenuext.cpp
字号:
// Check if we are currently in the Deleted Items folder
// If yes - THEN we will be permanently deleting
IsDeletedItems = (rgFolderProps[1].Value.ul & FOLDER_DELETED_ITEMS)? TRUE : FALSE;
if (IsDeletedItems)
{
// Warn user that they will be permanently deleting
int iResult = ::MessageBox(GetActiveWindow(),
TEXT("Are you sure you want to permanently delete all messages?"),
TEXT("Permanently Delete Items"), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2);
// If IDYES - then continue / else exit method now
hr = (iResult == IDYES) ? S_OK : E_FAIL;
CHR(hr);
}
else
{
// If we are not currently in the Deleted Items folder
// then get the Deleted Items folder
// since we will eventually be moving items there
hr = GetWastebasketForFolder(pFolder, &pWasteBasket);
CHR(hr);
CPR(pWasteBasket);
}
// Get contents of the folder
IMAPITable *pTable;
pFolder->GetContentsTable(MAPI_UNICODE, &pTable);
// We only care about the EntryID.
SizedSPropTagArray (1, spta) = {1, PR_ENTRYID};
pTable->SetColumns((SPropTagArray *)&spta, 0);
BOOL done = FALSE;
while(cMsgCount > 0)
{
// 10 is the max number of rows which QueryRows can return
int cCurrentQuery = 0;
if (cMsgCount > 10)
{
cCurrentQuery = 10;
}
else
{
cCurrentQuery = cMsgCount;
}
hr = pTable->QueryRows(cCurrentQuery, 0, &pRows);
CHR(hr);
// Did we hit the end of the table?
if (pRows->cRows == 0)
{
break;
}
// Since we are in a loop here and we are re-using lpmsgEntryList
// we may need to free the memory from the previous iteration first
// In the case of the last iteration or Error - this will be freed at Error:
MAPIFreeBuffer(lpmsgEntryList);
lpmsgEntryList = NULL;
// Otherwise - Get the List of EntryIDs from the RowSet as an EntryList
// Note: the resulting will EntryList be dependant on the RowSet so don't free until later
hr = CreateEntryList(pRows, &lpmsgEntryList);
CHR(hr);
if (IsDeletedItems)
{
// We are in the Deleted Items folder - so
// permanently delete the items
hr = pFolder->DeleteMessages(lpmsgEntryList, NULL, NULL, NULL);
}
else
{
// We are not in the Deleted Items folder - so
// *move* the messages into the to the deleted items folder.
hr = pFolder->CopyMessages(lpmsgEntryList, NULL, pWasteBasket, 0, NULL, MAPI_MOVE);
}
CHR(hr);
cMsgCount -= pRows->cRows;
}
}
Error:
// Make sure we do not leak memory
FreeProws(pRows);
MAPIFreeBuffer(rgFolderProps);
MAPIFreeBuffer(lpmsgEntryList);
RELEASE_OBJ(pProp);
RELEASE_OBJ(pFolder);
RELEASE_OBJ(pWasteBasket);
RELEASE_OBJ(m_pSession);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// MarkAllInFolderAsRead
//
// This method actually does the wok of marking all messaages in the current
// folder as read
//
// Since we have good logic to prevent the Mark All As Read menu item
// from being enabled when it should not - we should be able to trust that
// when this method is hit
// 1) the folder we are on is has mail in it.
//
// Notes: We KNOW that the FIRST item is in the ItemRefArray is always a FOLDER
// item if are a ListView Extension.
//
// Arguments:
// none
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::MarkAllInFolderAsRead()
{
HRESULT hr = E_FAIL;
ItemRefArray *pItemArray = NULL;
ItemRef *pRef = NULL;
IMAPIFolder *pFolder = NULL;
IMAPIProp *pProp = NULL;
IMessage *pMsg = NULL;
SPropValue *rgFolderProps= NULL;
SPropValue *rgMsgProps= NULL;
SRowSet *pRows = NULL;
hr = GetItemRefArray(&pItemArray);
CHR(hr);
if (pItemArray)
{
// Double check that the 1st item is indeed a Folder item
pRef = &pItemArray->rgRefs[0];
CBR(IsFolder(pRef));
ULONG cbEntry = 0;
ENTRYID *pEntryID = NULL;
ULONG cValues = 0;
ULONG rgFolderTags[] = {1, PR_CONTENT_COUNT};
ULONG rgMsgTags[] = {1, PR_MESSAGE_FLAGS};
ULONG cMsgCount = 0;
// Get the Entry Size - cbEntryID from the ItemRef
cbEntry = ((SBinary *)pRef->pRef)->cb;
CBR(cbEntry);
// Get the pointer to the EntryID from the ItemRef
pEntryID = (ENTRYID *) ((SBinary *)pRef->pRef)->lpb;
CPR(pEntryID);
// Logon to MAPI
hr = MAPILogonEx(0, NULL, NULL, 0, &m_pSession);
CHR(hr);
// Open the Folder
hr = m_pSession->OpenEntry(cbEntry, pEntryID, NULL, 0, NULL, (LPUNKNOWN *)&pFolder);
CHR(hr);
CPR(pFolder);
// Get an IMAPIProp Interface
hr = pFolder->QueryInterface(IID_IMAPIProp, (LPVOID *) &pProp);
CHR(hr);
CPR(pProp);
// Get the Folder PR_CONTENT_COUNT property
hr = pProp->GetProps((LPSPropTagArray)rgFolderTags, MAPI_UNICODE, &cValues, &rgFolderProps);
CHR(hr);
CBR(PR_CONTENT_COUNT == rgFolderProps[0].ulPropTag);
// Store the COUNT of messages in this folder
cMsgCount = rgFolderProps[0].Value.ul;
// Get contents of the folder
IMAPITable *pTable;
pFolder->GetContentsTable(MAPI_UNICODE, &pTable);
// We only care about the EntryID.
SizedSPropTagArray (1, spta) = {1, PR_ENTRYID};
pTable->SetColumns((SPropTagArray *)&spta, 0);
BOOL done = FALSE;
while(cMsgCount > 0)
{
// 10 is the max number of rows which QueryRows can return
int cCurrentQuery = 0;
if (cMsgCount > 10)
cCurrentQuery = 10;
else
cCurrentQuery = cMsgCount;
hr = pTable->QueryRows(cCurrentQuery, 0, &pRows);
CHR(hr);
// Did we hit the end of the table?
if (pRows->cRows == 0)
{
break;
}
// Otherwise - iterate through the message EntryIDS
// and get the messages. Then make sure that they are
// marked as read
for (int i = 0; i < (int)pRows->cRows; i++)
{
// Get the EntryID and count of bytes
cbEntry = pRows->aRow[i].lpProps[0].Value.bin.cb;
pEntryID = (ENTRYID *)pRows->aRow[i].lpProps[0].Value.bin.lpb;
// Get the Message
hr = pFolder->OpenEntry(cbEntry, pEntryID, NULL, 0, NULL, (LPUNKNOWN *)&pMsg);
CHR(hr);
CPR(pMsg);
// Get an IMAPIProp Interface
hr = pMsg->QueryInterface(IID_IMAPIProp, (LPVOID *) &pProp);
CHR(hr);
CPR(pProp);
// Get the Messages PR_FLAGS property
hr = pProp->GetProps((LPSPropTagArray)rgMsgTags, MAPI_UNICODE, &cValues, &rgMsgProps);
CHR(hr);
CBR(PR_MESSAGE_FLAGS == rgMsgProps[0].ulPropTag);
// If Not already marked Read
if (!(rgMsgProps[0].Value.ul & MSGFLAG_READ))
{
// OR in the READ flag - so you don't disturb other flags
rgMsgProps[0].Value.ul |= MSGFLAG_READ;
hr = pProp->SetProps(1, rgMsgProps, NULL);
}
}
cMsgCount -= pRows->cRows;
}
}
Error:
// Make sure we do not leak memory
FreeProws(pRows);
MAPIFreeBuffer(rgFolderProps);
MAPIFreeBuffer(rgMsgProps);
RELEASE_OBJ(pProp);
RELEASE_OBJ(pFolder);
RELEASE_OBJ(pMsg);
RELEASE_OBJ(m_pSession);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// GetWastebasketForFolder
//
// This method will find the appropriate wastebasket for the given folder. It
// does this by finding the message store for the folder and then gets the
// ENTRYID of the wastebasket and then gets the wastebasket folder
//
// This method assumes that the CALLER already logged on to a MAPISession and
// m_pSession is not NULL.
//
// Arguments:
// [IN] LPMAPIFOLDER pFolder - a pointer the current folder
// [OUT] LPMAPIFOLDER* ppfldrWastebasket - this is used to return the
// pointer to the appropraite "deleted items" folder for the current
// folder
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::GetWastebasketForFolder(LPMAPIFOLDER pFolder,
LPMAPIFOLDER* ppfldrWastebasket)
{
HRESULT hr = E_FAIL;
IMsgStore* pms = NULL;
ULONG cItems;
ULONG rgtagsFldr[] = { 1, PR_OWN_STORE_ENTRYID };
ULONG rgtagsMsgStore[] = { 1, PR_IPM_WASTEBASKET_ENTRYID };
LPSPropValue rgprops = NULL;
// This method assumes that the CALLER already logged on to a MAPISession
if (!m_pSession)
CHR(E_FAIL);
// Now request the PR_OWN_STORE_ENTRYID on the folder. This is the
// ENTRYID of the message store that owns the folder object.
hr = pFolder->GetProps((LPSPropTagArray)rgtagsFldr, MAPI_UNICODE, &cItems, &rgprops);
CHR(hr);
CBR(PR_OWN_STORE_ENTRYID == rgprops[0].ulPropTag);
// Now open the message store object.
hr = m_pSession->OpenEntry(rgprops[0].Value.bin.cb,
(LPENTRYID)rgprops[0].Value.bin.lpb,
NULL, 0, NULL, (LPUNKNOWN*)&pms);
CHR(hr);
MAPIFreeBuffer(rgprops);
rgprops = NULL;
// Get the ENTRYID of the wastebasket for the message store
hr = pms->GetProps((LPSPropTagArray)rgtagsMsgStore, MAPI_UNICODE, &cItems, &rgprops);
CHR(hr);
// Now open the correct wastebasket and return it to the caller.
CBR(PR_IPM_WASTEBASKET_ENTRYID == rgprops[0].ulPropTag);
hr = m_pSession->OpenEntry(rgprops[0].Value.bin.cb,
(LPENTRYID)rgprops[0].Value.bin.lpb,
NULL, 0, NULL, (LPUNKNOWN*)ppfldrWastebasket);
CHR(hr);
Error:
MAPIFreeBuffer(rgprops);
RELEASE_OBJ(pms);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// CreateEntryList
//
// This method will create an ENTRYLIST from an SRowSet which
//
// Arguments:
// [IN] SRowSet *pRows - a pointer the row set (obtained from an IMAPITable)
// [OUT] ENTRYLIST **ppList - the resulting new EntryList.
// NOTE: The caller is responsible for calling MAPIFreeBuffer
// on this returned list
//
// Return Values:
// HRESULT - S_OK on success
//
HRESULT MenuExtension::CreateEntryList(SRowSet *pRows, ENTRYLIST **ppList)
{
HRESULT hr;
ENTRYLIST* plist = NULL;
// How much space do we need to create this entry list??
ULONG cbNeeded = sizeof(SBinaryArray) + (pRows->cRows * (sizeof(SBinary)));
// Allocate one buffer to hold all the data for the list.
hr = MAPIAllocateBuffer(cbNeeded, (LPVOID*)&plist);
CHR(hr);
CPR(plist);
// Set the number of items in the EntryList
plist->cValues = pRows->cRows;
// Set plist->lpbin to the place in the buffer where the array items will be
// filled in
BYTE* pb;
pb = (BYTE*)plist;
pb += sizeof(SBinaryArray);
plist->lpbin = (SBinary*) pb;
// Loop through the list setting the contents of the EntryList to the contents
// of the incoming SRowSet
for (int cItems = 0; cItems < (int)plist->cValues; cItems++)
{
plist->lpbin[cItems].cb = pRows->aRow[cItems].lpProps[0].Value.bin.cb;
plist->lpbin[cItems].lpb = pRows->aRow[cItems].lpProps[0].Value.bin.lpb;
// Track our memory usage
pb += sizeof(SBinary);
}
// Make sure that we didn't write off the end of our buffer...
CBR(pb <= ((BYTE*)plist + cbNeeded));
Error:
if (FAILED(hr))
{
MAPIFreeBuffer(plist);
plist = NULL;
}
*ppList = plist;
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -