www.pudn.com > MailCheck_src.zip > Wakeme.cpp
/***************************************************************************
* Copyright (c) 1996, Microsoft Corporation
*
* Sample extended MAPI app with new mail notifications
*
* History:
* 1 Oct 1996 Vajira Weerasekera
*
* This is a quick sample application that demonstrates Extended MAPI mail
* notifications.
*
* Once the app is launched it will logon to MAPI and register for new mail
* notifications, and when new mail arrives it will simply display a dialog with
* the originator and the subject.
*
\***************************************************************************/
// Wakeme.cpp : Defines the class behaviors for the application.
//
#include "Wakeme.h"
#include "Utils.h"
#define USES_IID_IUnknown
#define INITGUID
#include "mkguids.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CWinApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CWakemeApp
/////////////////////////////////////////////////////////////////////////////
// CWakemeApp construction
CWakemeApp::CWakemeApp()
{
m_fMAPIInitialized = FALSE;
m_pSession = NULL;
m_lpDefaultStore = NULL;
m_lpInboxFolder = NULL;
m_lpIPMFolder = NULL;
m_lpOutboxFolder = NULL;
m_lpRootHierarchyTable = NULL;
m_lpRootFolder = NULL;
// Initialise a MAPI Session
HRESULT hr = MAPIInitialize(NULL);
if (SUCCEEDED(hr)) {
m_fMAPIInitialized = TRUE;
ULONG ulFlags = MAPI_ALLOW_OTHERS | MAPI_USE_DEFAULT | MAPI_EXTENDED;
hr = (HRESULT) MAPILogonEx(NULL,
NULL,
NULL,
ulFlags,
&m_pSession );
}
if (FAILED(hr)) {
SCODE sc = GetScode(hr);
if (sc != MAPI_E_USER_CANCEL)
MessageBox(NULL,"Cannot establish a messaging session","Error",MB_APPLMODAL);
return;
}
hr = OpenMsgStore();
if (FAILED(hr))
return;
// Register for new mail
RegisterForNewMail();
}
// Logoff from MAPI when the application is closing down
CWakemeApp::~CWakemeApp()
{
MessageBox(NULL,"Disconnecting...","Information",MB_APPLMODAL);
// Unregister from new mail
if (m_bNewMailNotify)
UnregisterForNewMail();
if (m_lpInboxFolder)
m_lpInboxFolder->Release();
if (m_lpIPMFolder)
m_lpIPMFolder->Release();
if (m_lpOutboxFolder)
m_lpOutboxFolder->Release();
if (m_lpRootHierarchyTable)
m_lpRootHierarchyTable->Release();
if (m_lpRootFolder)
m_lpRootFolder->Release();
if (m_lpDefaultStore)
m_lpDefaultStore->Release();
if (m_pSession) {
// End the MAPI session
HRESULT hResult = m_pSession->Logoff(0,MAPI_LOGOFF_UI,0);
// Release the MAPI session object
m_pSession->Release();
if (FAILED(hResult))
MessageBox(NULL,"MAPI Logoff failed !","Error",MB_APPLMODAL);
}
// If we have initialized MAPI then Uninitialize it now
if (m_fMAPIInitialized) {
MAPIUninitialize();// Decrement MAPI reference count
m_fMAPIInitialized = FALSE;
}
}
// Open the message store object if it's not open already, and return the
// object pointer to the caller
//
HRESULT CWakemeApp::OpenMsgStore()
{
ASSERT(m_pSession != NULL);
if (m_lpDefaultStore)
return ResultFromScode(SUCCESS_SUCCESS);
// Open the default message store
ULONG cbEntryID;
LPENTRYID pEntryID;
HRESULT hr = QueryDefaultMsgStore(&cbEntryID,&pEntryID);
if (FAILED(hr))
return hr;
// Now that we have the entry ID for the default message store, we can
// open it.
hr = m_pSession->OpenMsgStore( NULL,
cbEntryID,
pEntryID,
NULL,
MDB_WRITE,
&m_lpDefaultStore );
if (FAILED(hr)){
m_lpDefaultStore = NULL;
return hr;
}
// Check for the existence of an IPM_SUBTREE in this store.
// If one does not exist, then make one with the standard name.
static SPropTagArray pta = { 1, {PR_IPM_SUBTREE_ENTRYID}};
ULONG cValues;
LPSPropValue pPropArray;
hr = m_lpDefaultStore->GetProps(&pta,0,&cValues,&pPropArray);
if (FAILED(hr) || pPropArray->ulPropTag != PR_IPM_SUBTREE_ENTRYID) {
if (SUCCEEDED(hr))
MAPIFreeBuffer(pPropArray);
// Open the root folder
LPMAPIFOLDER pfldrRoot;
ULONG ulObjType;
hr = m_lpDefaultStore->OpenEntry(0,NULL,NULL,MAPI_MODIFY,&ulObjType,(LPUNKNOWN FAR *) &pfldrRoot);
if (FAILED(hr)){
m_lpDefaultStore->Release();
m_lpDefaultStore = NULL;
return hr;
}
// Create a sub-folder called 'IPM_SUBTREE'
LPMAPIFOLDER pfldr;
hr = pfldrRoot->CreateFolder(FOLDER_GENERIC,"IPM_SUBTREE",NULL,NULL,OPEN_IF_EXISTS,&pfldr);
if (FAILED(hr)) {
pfldrRoot->Release();
m_lpDefaultStore->Release();
m_lpDefaultStore = NULL;
return hr;
}
pfldrRoot->Release();
hr = pfldr->SaveChanges(KEEP_OPEN_READONLY);
if (FAILED(hr)) {
pfldr->Release();
m_lpDefaultStore->Release();
m_lpDefaultStore = NULL;
return hr;
}
// Set PR_IPM_SUBTREE_ENTRYID to the entryid of this folder
static SPropTagArray pta = { 1, {PR_ENTRYID}};
ULONG cValues;
LPSPropValue pPropArray;
hr = pfldr->GetProps(&pta,0,&cValues,&pPropArray);
if (FAILED(hr)) {
pfldr->Release();
m_lpDefaultStore->Release();
m_lpDefaultStore = NULL;
return hr;
}
// Release the newly created folder
pfldr->Release();
if (pPropArray->ulPropTag == PR_ENTRYID) {
pPropArray->ulPropTag = PR_IPM_SUBTREE_ENTRYID;
hr = m_lpDefaultStore->SetProps(1,pPropArray,NULL);
if (FAILED(hr)) {
MAPIFreeBuffer(pPropArray);
pfldr->Release();
m_lpDefaultStore->Release();
m_lpDefaultStore = NULL;
return hr;
}
}
MAPIFreeBuffer(pPropArray);
} else {
MAPIFreeBuffer(pPropArray);
}
return hr;
}
//
// Figure out the default message store. Scans the MsgStoresTable for the
// first one with the PR_DEFAULT_STORE set to TRUE. If none found, then use
// the first store in the table.
//
HRESULT CWakemeApp::QueryDefaultMsgStore(ULONG FAR *pcbEntryID,LPENTRYID FAR *ppEntryID)
{
ASSERT(m_pSession != NULL);
// Get the message store table
LPMAPITABLE ptbl;
HRESULT hr = m_pSession->GetMsgStoresTable(0,&ptbl);
if (FAILED(hr))
return hr;
ULONG cRows = 0;
hr = ptbl->GetRowCount(0,&cRows);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
if (cRows == 0) {
ptbl->Release();
return ResultFromScode(MAPI_E_CALL_FAILED);
}
// Look for the default message store row and return it's entry ID
ULONG iRowDefault = 0xFFFF;
for (ULONG iRow=0;iRowSetColumns(&pta,0);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
hr = ptbl->SeekRow(BOOKMARK_BEGINNING,iRow,NULL);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
LPSRowSet prs;
hr = ptbl->QueryRows(1,0,&prs);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
if (prs->cRows == 1 &&
prs->aRow[0].lpProps->ulPropTag == PR_DEFAULT_STORE &&
prs->aRow[0].lpProps->Value.b) {
iRowDefault = iRow;
FreeRowSet(MAPIFreeBuffer, prs);
break;
}
FreeRowSet(MAPIFreeBuffer, prs);
}
if (iRowDefault == 0xFFFF)
return ResultFromScode(MAPI_E_CALL_FAILED);
static SPropTagArray pta = {1, {PR_ENTRYID}};
hr = ptbl->SetColumns(&pta,0);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
hr = ptbl->SeekRow(BOOKMARK_BEGINNING,iRowDefault,NULL);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
LPSRowSet prs;
hr = ptbl->QueryRows(1,0,&prs);
if (FAILED(hr)) {
ptbl->Release();
return hr;
}
ptbl->Release();
if (prs->cRows == 1 && prs->aRow[0].lpProps->ulPropTag == PR_ENTRYID) {
ULONG cb = prs->aRow[0].lpProps->Value.bin.cb;
LPENTRYID pEntryID;
SCODE sc = MAPIAllocateBuffer(cb,(LPVOID FAR *) &pEntryID);
if (FAILED(sc)) {
FreeRowSet(MAPIFreeBuffer, prs);
return ResultFromScode(sc);
}
memcpy(pEntryID,prs->aRow[0].lpProps->Value.bin.lpb,(size_t) cb);
FreeRowSet(MAPIFreeBuffer, prs);
*pcbEntryID = cb;
*ppEntryID = pEntryID;
return hrSuccess;
}
FreeRowSet(MAPIFreeBuffer, prs);
return ResultFromScode(MAPI_E_CALL_FAILED);
}
// Registers an AdviseSink for New Mail notification
//
HRESULT CWakemeApp::RegisterForNewMail()
{
ULONG cbEntryID;
LPENTRYID pEntryID;
LPSTR szActualClass;
ULONG ulRowCount = 0;
ULONG ulObjType;
m_bNewMailNotify = FALSE;
// Get the inbox folder object
HRESULT hr = m_lpDefaultStore->GetReceiveFolder("IPM", 0, &cbEntryID,
&pEntryID,&szActualClass );
if (FAILED(hr) || szActualClass == NULL || strcmp(szActualClass,"IPM")) {
if (SUCCEEDED(hr)) {
MAPIFreeBuffer( pEntryID );
MAPIFreeBuffer( szActualClass );
}
return ResultFromScode(E_FAIL);
}
// Get the root folder of the default message store
hr = m_lpDefaultStore->OpenEntry((ULONG)0,
NULL,
NULL,
MAPI_MODIFY|MAPI_DEFERRED_ERRORS,
&ulObjType,
(LPUNKNOWN FAR *) &m_lpRootFolder);
if (FAILED( hr))
return ResultFromScode(E_FAIL);
m_pNewMailSink = new CNewMailAdviseSink(this);
//Register for notification (fnevNewMail)
hr = m_lpDefaultStore->Advise( cbEntryID,
pEntryID,
fnevNewMail,
m_pNewMailSink,
&m_ulNewMailConnection );
MAPIFreeBuffer( pEntryID );
MAPIFreeBuffer( szActualClass );
if (FAILED( hr )) {
m_pNewMailSink->Release();
m_pNewMailSink = NULL;
return( hr );
}
// need to force an RPC call to the server..
// without this force, the notification will NOT work.
// this will ensure that the Advice() call was actaully registered.
// Get the hierarchy table for the root folder of the message store
hr = m_lpRootFolder->GetHierarchyTable(MAPI_DEFERRED_ERRORS,
&m_lpRootHierarchyTable);
if( FAILED( hr))
return ResultFromScode(E_FAIL);
hr = m_lpRootHierarchyTable->GetRowCount(TBL_NOWAIT,&ulRowCount);
if( FAILED( hr))
return ResultFromScode(E_FAIL);
m_bNewMailNotify = TRUE;
return( hr );
}
// Unregisters the new mail advise sink
//
HRESULT CWakemeApp::UnregisterForNewMail()
{
if (!m_bNewMailNotify)
return( hrSuccess );
HRESULT hr = m_lpDefaultStore->Unadvise( m_ulNewMailConnection );
if (m_pNewMailSink)
m_pNewMailSink->Release();
m_bNewMailNotify = FALSE;
return hr;
}
// Implementation of IUnknown methods
//
HRESULT CNewMailAdviseSink::QueryInterface(REFIID riid,LPVOID FAR* ppvObj)
{
if( riid == IID_IUnknown){
*ppvObj = this;
AddRef();
return hrSuccess;
}
return ResultFromScode(E_NOINTERFACE);
}
ULONG CNewMailAdviseSink::AddRef()
{
return ++m_cRef;
}
ULONG CNewMailAdviseSink::Release()
{
if (--m_cRef == 0) {
delete this;
return 0;
}
return m_cRef;
}
// Ha! a new mail msg just came in...
//
ULONG CNewMailAdviseSink::OnNotify(ULONG cNotif,LPNOTIFICATION lpNotify)
{
static SizedSPropTagArray(2, pta) = {2, {PR_SENDER_NAME,
PR_SUBJECT}};
HRESULT hr;
ULONG ulObjType;
LPMESSAGE lpNewMessage;
ULONG cValues;
LPSPropValue pPropArray;
// Quick sanity chek to see if we got really called back for newmail ?
if (lpNotify) {
if (lpNotify->ulEventType == fnevNewMail){
// Open the new message
hr = m_pParent->m_lpDefaultStore->OpenEntry(
lpNotify->info.newmail.cbEntryID,
lpNotify->info.newmail.lpEntryID,
NULL,
MAPI_MODIFY|MAPI_DEFERRED_ERRORS,
&ulObjType,
(LPUNKNOWN FAR *) &lpNewMessage);
if (FAILED( hr))
return 1;
// Get the message details
hr = lpNewMessage->GetProps((LPSPropTagArray)&pta,0,&cValues,&pPropArray);
// release the new message
lpNewMessage->Release();
if (FAILED( hr))
return 1;
CString s;
s.LoadString(IDS_MAIL);
m_pParent->dlg.m_from = pPropArray[0].Value.lpszA;
m_pParent->dlg.m_subject = pPropArray[1].Value.lpszA;
m_pParent->dlg.m_legend = s;
m_pParent->dlg.UpdateData(FALSE);
m_pParent->dlg.TraySetToolTip((LPCTSTR)s);
m_pParent->dlg.TraySetIcon(IDI_MAIL);
m_pParent->dlg.TrayUpdate();
Beep(440, 200);
return 0;
} // if
} // if
MessageBox(NULL,"Who is waking me up ?","Error",MB_APPLMODAL);
return 0;
}