mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
845 lines
22 KiB
C++
845 lines
22 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// File: MAPIObject.cpp
|
|
// Description: Base class for code common to MAPI Items (messages, contacts etc)
|
|
//
|
|
// Copyright (C) 2005-2011, Noel Dillabough
|
|
//
|
|
// This source code is free to use and modify provided this notice remains intact and that any enhancements
|
|
// or bug fixes are posted to the CodeProject page hosting this class for the community to benefit.
|
|
//
|
|
// Usage: see the CodeProject article at http://www.codeproject.com/internet/CMapiEx.asp
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "MAPIExPCH.h"
|
|
#include "MAPIEx.h"
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CMAPIObject
|
|
|
|
CMAPIObject::CMAPIObject()
|
|
{
|
|
m_pMAPI=NULL;
|
|
m_pItem=NULL;
|
|
m_entryID.cb=0;
|
|
SetEntryID(NULL);
|
|
}
|
|
|
|
CMAPIObject::~CMAPIObject()
|
|
{
|
|
}
|
|
|
|
BOOL CMAPIObject::GetHexString(CString& strHex, SBinary bin)
|
|
{
|
|
strHex.Empty();
|
|
if(bin.cb)
|
|
{
|
|
TCHAR szBuffer[3];
|
|
for(ULONG i=0;i<bin.cb;i++)
|
|
{
|
|
_stprintf_s(szBuffer, 3, _T("%02X"), bin.lpb[i]);
|
|
strHex+=szBuffer;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetEntryIDString(CString& strEntryID)
|
|
{
|
|
return GetHexString(strEntryID, m_entryID);
|
|
}
|
|
|
|
void CMAPIObject::SetEntryID(SBinary* pEntryID)
|
|
{
|
|
if(m_entryID.cb) delete [] m_entryID.lpb;
|
|
m_entryID.lpb=NULL;
|
|
|
|
if(pEntryID)
|
|
{
|
|
m_entryID.cb=pEntryID->cb;
|
|
if(m_entryID.cb)
|
|
{
|
|
m_entryID.lpb=new BYTE[m_entryID.cb];
|
|
memcpy(m_entryID.lpb, pEntryID->lpb, m_entryID.cb);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_entryID.cb=0;
|
|
}
|
|
}
|
|
|
|
BOOL CMAPIObject::Open(CMAPIEx* pMAPI, SBinary entryID)
|
|
{
|
|
Close();
|
|
m_pMAPI=pMAPI;
|
|
ULONG ulObjType;
|
|
if(m_pMAPI->GetSession()->OpenEntry(entryID.cb, (LPENTRYID)entryID.lpb, NULL, MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN*)&m_pItem)!=S_OK) return FALSE;
|
|
SetEntryID(&entryID);
|
|
return TRUE;
|
|
}
|
|
|
|
void CMAPIObject::Close()
|
|
{
|
|
SetEntryID(NULL);
|
|
RELEASE(m_pItem);
|
|
m_pMAPI=NULL;
|
|
}
|
|
|
|
BOOL CMAPIObject::Save(BOOL bClose)
|
|
{
|
|
ULONG ulFlags=bClose ? 0 : KEEP_OPEN_READWRITE;
|
|
if(m_pItem && m_pItem->SaveChanges(ulFlags)==S_OK)
|
|
{
|
|
if(bClose) Close();
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int CMAPIObject::GetMessageFlags()
|
|
{
|
|
return GetPropertyValue(PR_MESSAGE_FLAGS, 0);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetMessageFlags(int nFlags)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_MESSAGE_FLAGS;
|
|
prop.Value.l=nFlags;
|
|
return (m_pItem && m_pItem->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
|
|
int CMAPIObject::GetSensitivity()
|
|
{
|
|
return GetPropertyValue(PR_SENSITIVITY, -1);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetSensitivity(int nSensitivity)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_SENSITIVITY;
|
|
prop.Value.l=nSensitivity;
|
|
return (Message()->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
|
|
int CMAPIObject::GetImportance()
|
|
{
|
|
return GetPropertyValue(PR_IMPORTANCE, IMPORTANCE_NORMAL);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetImportance(int nImportance)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_IMPORTANCE;
|
|
prop.Value.l=nImportance;
|
|
return (Message()->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::GetMessageClass(CString& strMessageClass)
|
|
{
|
|
return GetPropertyString(PR_MESSAGE_CLASS, strMessageClass);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetMessageClass(LPCTSTR szMessageClass)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_MESSAGE_CLASS;
|
|
prop.Value.LPSZ=(LPTSTR)szMessageClass;
|
|
return (Message()->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
|
|
int CMAPIObject::GetMessageEditorFormat()
|
|
{
|
|
return GetPropertyValue(PR_MSG_EDITOR_FORMAT, EDITOR_FORMAT_DONTKNOW);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetMessageEditorFormat(int nFormat)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_MSG_EDITOR_FORMAT;
|
|
prop.Value.l=nFormat;
|
|
return (m_pItem && m_pItem->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::Create(CMAPIEx* pMAPI, CMAPIFolder* pFolder)
|
|
{
|
|
if(!pMAPI) return FALSE;
|
|
if(!pFolder) pFolder=pMAPI->GetFolder();
|
|
if(!pFolder) return FALSE;
|
|
Close();
|
|
m_pMAPI=pMAPI;
|
|
if(pFolder->Folder()->CreateMessage(NULL, 0, (LPMESSAGE*)&m_pItem)==S_OK)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetProperty(PR_ENTRYID, pProp)==S_OK)
|
|
{
|
|
SetEntryID(&pProp->Value.bin);
|
|
MAPIFreeBuffer(pProp);
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CMAPIObject::GetProperty(ULONG ulProperty, LPSPropValue& pProp)
|
|
{
|
|
if(!m_pItem) return E_INVALIDARG;
|
|
ULONG ulPropCount;
|
|
ULONG p[2]={ 1, ulProperty };
|
|
return m_pItem->GetProps((LPSPropTagArray)p, CMAPIEx::cm_nMAPICode, &ulPropCount, &pProp);
|
|
}
|
|
|
|
BOOL CMAPIObject::GetPropertyString(ULONG ulProperty, CString& strProperty, BOOL bStream)
|
|
{
|
|
strProperty=_T("");
|
|
if(bStream)
|
|
{
|
|
IStream* pStream;
|
|
if(Message()->OpenProperty(ulProperty, &IID_IStream, STGM_READ, NULL, (LPUNKNOWN*)&pStream)==S_OK)
|
|
{
|
|
const int BUF_SIZE=16384;
|
|
TCHAR szBuf[BUF_SIZE+1];
|
|
ULONG ulNumChars;
|
|
|
|
do
|
|
{
|
|
pStream->Read(szBuf, BUF_SIZE*sizeof(TCHAR), &ulNumChars);
|
|
ulNumChars/=sizeof(TCHAR);
|
|
szBuf[min(BUF_SIZE,ulNumChars)]=0;
|
|
strProperty+=szBuf;
|
|
} while(ulNumChars>=BUF_SIZE);
|
|
|
|
RELEASE(pStream);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ulProperty==PR_ENTRYID)
|
|
{
|
|
return GetEntryIDString(strProperty);
|
|
}
|
|
|
|
LPSPropValue pProp;
|
|
if(GetProperty(ulProperty, pProp)==S_OK)
|
|
{
|
|
strProperty=CMAPIEx::GetValidString(*pProp);
|
|
MAPIFreeBuffer(pProp);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int CMAPIObject::GetPropertyValue(ULONG ulProperty, int nDefaultValue)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetProperty(ulProperty, pProp)==S_OK)
|
|
{
|
|
nDefaultValue=pProp->Value.l;
|
|
MAPIFreeBuffer(pProp);
|
|
}
|
|
return nDefaultValue;
|
|
}
|
|
|
|
const GUID GUIDPublicStrings={ 0x00020329, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
|
|
|
|
BOOL CMAPIObject::GetPropTagArray(LPCTSTR szFieldName, LPSPropTagArray& lppPropTags, int& nFieldType, BOOL bCreate)
|
|
{
|
|
if(!m_pItem) return FALSE;
|
|
|
|
MAPINAMEID nameID;
|
|
nameID.lpguid=(GUID*)&GUIDPublicStrings;
|
|
nameID.ulKind=MNID_STRING;
|
|
#ifdef UNICODE
|
|
nFieldType=PT_UNICODE;
|
|
nameID.Kind.lpwstrName=(LPWSTR)szFieldName;
|
|
#else
|
|
nFieldType=PT_STRING8;
|
|
WCHAR wszFieldName[256];
|
|
MultiByteToWideChar(CP_ACP, 0, szFieldName, -1, wszFieldName, 255);
|
|
nameID.Kind.lpwstrName=wszFieldName;
|
|
#endif
|
|
|
|
LPMAPINAMEID lpNameID[1]={ &nameID };
|
|
|
|
HRESULT hr=m_pItem->GetIDsFromNames(1, lpNameID, bCreate ? MAPI_CREATE : 0, &lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::GetNamedProperty(LPCTSTR szFieldName, LPSPropValue &pProp)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetPropTagArray(szFieldName, lppPropTags, nFieldType, FALSE)) return FALSE;
|
|
|
|
ULONG ulPropCount;
|
|
HRESULT hr=m_pItem->GetProps(lppPropTags, CMAPIEx::cm_nMAPICode, &ulPropCount, &pProp);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::GetNamedProperty(LPCTSTR szFieldName, CString& strField)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetNamedProperty(szFieldName, pProp))
|
|
{
|
|
strField=CMAPIEx::GetValidString(*pProp);
|
|
MAPIFreeBuffer(pProp);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetOutlookPropTagArray(ULONG ulData, ULONG ulProperty, LPSPropTagArray& lppPropTags, int& nFieldType, BOOL bCreate)
|
|
{
|
|
if(!m_pItem) return FALSE;
|
|
|
|
const GUID guidOutlookEmail1={ulData, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
|
|
|
|
MAPINAMEID nameID;
|
|
nameID.lpguid=(GUID*)&guidOutlookEmail1;
|
|
nameID.ulKind=MNID_ID;
|
|
nameID.Kind.lID=ulProperty;
|
|
|
|
#ifdef UNICODE
|
|
nFieldType=PT_UNICODE;
|
|
#else
|
|
nFieldType=PT_STRING8;
|
|
#endif
|
|
|
|
LPMAPINAMEID lpNameID[1]={ &nameID };
|
|
|
|
HRESULT hr=m_pItem->GetIDsFromNames(1, lpNameID, bCreate ? MAPI_CREATE : 0, &lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
// gets a custom outlook property (ie EmailAddress1 of a contact)
|
|
BOOL CMAPIObject::GetOutlookProperty(ULONG ulData, ULONG ulProperty, LPSPropValue& pProp)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetOutlookPropTagArray(ulData,ulProperty, lppPropTags, nFieldType, FALSE)) return FALSE;
|
|
|
|
ULONG ulPropCount;
|
|
HRESULT hr=m_pItem->GetProps(lppPropTags, CMAPIEx::cm_nMAPICode, &ulPropCount, &pProp);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
// gets a custom outlook property value
|
|
BOOL CMAPIObject::GetOutlookPropertyValue(ULONG ulData, ULONG ulProperty, int& nValue)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetOutlookProperty(ulData, ulProperty, pProp))
|
|
{
|
|
nValue=pProp->Value.i;
|
|
MAPIFreeBuffer(pProp);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// gets a custom outlook property string (ie EmailAddress1 of a contact)
|
|
BOOL CMAPIObject::GetOutlookPropertyString(ULONG ulData, ULONG ulProperty, CString& strProperty)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetOutlookProperty(ulData, ulProperty, pProp))
|
|
{
|
|
strProperty=CMAPIEx::GetValidString(*pProp);
|
|
MAPIFreeBuffer(pProp);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::SetPropertyString(ULONG ulProperty, LPCTSTR szProperty, BOOL bStream)
|
|
{
|
|
if(m_pItem && szProperty)
|
|
{
|
|
if(bStream)
|
|
{
|
|
LPSTREAM pStream=NULL;
|
|
if(m_pItem->OpenProperty(ulProperty, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK)
|
|
{
|
|
pStream->Write(szProperty, (ULONG)(_tcslen(szProperty)+1)*sizeof(TCHAR), NULL);
|
|
RELEASE(pStream);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=ulProperty;
|
|
prop.Value.LPSZ=(LPTSTR)szProperty;
|
|
return (m_pItem->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::SetPropertyValue(ULONG ulProperty, int nValue)
|
|
{
|
|
if(m_pItem)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=ulProperty;
|
|
prop.Value.l=nValue;
|
|
return (m_pItem->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// if bCreate is true, the property will be created if necessary otherwise if not present will return FALSE
|
|
BOOL CMAPIObject::SetNamedProperty(LPCTSTR szFieldName, LPCTSTR szField, BOOL bCreate)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetPropTagArray(szFieldName, lppPropTags, nFieldType, bCreate)) return FALSE;
|
|
|
|
SPropValue prop;
|
|
prop.ulPropTag=(lppPropTags->aulPropTag[0]|nFieldType);
|
|
prop.Value.LPSZ=(LPTSTR)szField;
|
|
HRESULT hr=m_pItem->SetProps(1, &prop, NULL);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetNamedMVProperty(LPCTSTR szFieldName, LPCTSTR* arCategories, int nCount, LPSPropValue &pProp, BOOL bCreate)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetPropTagArray(szFieldName, lppPropTags, nFieldType, bCreate)) return FALSE;
|
|
|
|
HRESULT hr=MAPIAllocateBuffer(sizeof(SPropValue), (LPVOID*)&pProp);
|
|
if(hr==S_OK)
|
|
{
|
|
pProp->ulPropTag=(lppPropTags->aulPropTag[0]|nFieldType|MV_FLAG);
|
|
pProp->Value.MVi.cValues=nCount;
|
|
if(PROP_TYPE(pProp->ulPropTag)==PT_MV_STRING8)
|
|
{
|
|
hr=MAPIAllocateMore(sizeof(LPSTR)*nCount, pProp, (LPVOID*)&pProp->Value.MVszA.lppszA);
|
|
}
|
|
else
|
|
{
|
|
// PT_MV_UNICODE
|
|
hr=MAPIAllocateMore(sizeof(LPSTR)*nCount, pProp, (LPVOID*)&pProp->Value.MVszW.lppszW);
|
|
}
|
|
if(hr==S_OK)
|
|
{
|
|
for(int i=0;i<nCount;i++) pProp->Value.MVSZ.LPPSZ[i]=(LPTSTR)arCategories[i];
|
|
hr=m_pItem->SetProps(1, pProp, NULL);
|
|
}
|
|
if(hr!=S_OK) MAPIFreeBuffer(pProp);
|
|
}
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetOutlookProperty(ULONG ulData, ULONG ulProperty, LPCTSTR szField)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetOutlookPropTagArray(ulData, ulProperty, lppPropTags, nFieldType, FALSE)) return FALSE;
|
|
|
|
SPropValue prop;
|
|
prop.ulPropTag=(lppPropTags->aulPropTag[0]|nFieldType);
|
|
prop.Value.LPSZ=(LPTSTR)szField;
|
|
HRESULT hr=m_pItem->SetProps(1, &prop, NULL);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetOutlookProperty(ULONG ulData, ULONG ulProperty, int nField, int nFieldType)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nIgnored;
|
|
if(!GetOutlookPropTagArray(ulData, ulProperty, lppPropTags, nIgnored, FALSE)) return FALSE;
|
|
|
|
SPropValue prop;
|
|
prop.ulPropTag=(lppPropTags->aulPropTag[0]|nFieldType);
|
|
prop.Value.l=nField;
|
|
HRESULT hr=m_pItem->SetProps(1, &prop, NULL);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetOutlookProperty(ULONG ulData, ULONG ulProperty, FILETIME ftField)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetOutlookPropTagArray(ulData,ulProperty, lppPropTags, nFieldType, FALSE)) return FALSE;
|
|
nFieldType=PT_SYSTIME;
|
|
|
|
SPropValue prop;
|
|
prop.ulPropTag=(lppPropTags->aulPropTag[0]|nFieldType);
|
|
prop.Value.ft=ftField;
|
|
HRESULT hr=m_pItem->SetProps(1, &prop, NULL);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
BOOL CMAPIObject::DeleteNamedProperty(LPCTSTR szFieldName)
|
|
{
|
|
LPSPropTagArray lppPropTags;
|
|
int nFieldType;
|
|
if(!GetPropTagArray(szFieldName, lppPropTags, nFieldType, FALSE)) return FALSE;
|
|
|
|
HRESULT hr=m_pItem->DeleteProps(lppPropTags, NULL);
|
|
MAPIFreeBuffer(lppPropTags);
|
|
return (hr==S_OK);
|
|
}
|
|
|
|
int CMAPIObject::GetAttachmentCount()
|
|
{
|
|
ULONG ulCount=0;
|
|
LPMAPITABLE pAttachTable;
|
|
if(Message()->GetAttachmentTable(0, &pAttachTable)==S_OK)
|
|
{
|
|
#ifndef _WIN32_WCE
|
|
if(pAttachTable->GetRowCount(0, &ulCount)!=S_OK) ulCount=0;
|
|
#else
|
|
enum { PROP_ATTACH_CONTENT_ID, ATTACH_COLS };
|
|
static SizedSPropTagArray(ATTACH_COLS, Columns)={ATTACH_COLS, PR_ATTACH_CONTENT_ID };
|
|
if(pAttachTable->SetColumns((LPSPropTagArray)&Columns, 0)==S_OK)
|
|
{
|
|
ULONG cRows;
|
|
do {
|
|
LPSRowSet pRows=NULL;
|
|
if(pAttachTable->QueryRows(1, 0, &pRows)!=S_OK)
|
|
{
|
|
MAPIFreeBuffer(pRows);
|
|
break;
|
|
}
|
|
cRows=pRows->cRows;
|
|
ulCount+=cRows;
|
|
FreeProws(pRows);
|
|
} while(cRows);
|
|
}
|
|
#endif
|
|
RELEASE(pAttachTable);
|
|
}
|
|
return ulCount;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetAttachment(CMAPIAttachment& attachment, int nIndex)
|
|
{
|
|
return attachment.Open(Message(), nIndex);
|
|
}
|
|
|
|
BOOL CMAPIObject::AddAttachment(CMAPIAttachment& attachment)
|
|
{
|
|
return attachment.Create(Message());
|
|
}
|
|
|
|
BOOL CMAPIObject::AddAttachment(LPCTSTR szPath, LPCTSTR szName, LPCTSTR szCID)
|
|
{
|
|
CFile file;
|
|
if(!file.Open(szPath, CFile::modeRead)) return FALSE;
|
|
file.Close();
|
|
|
|
LPTSTR szFileName=(LPTSTR)szName;
|
|
if(!szFileName)
|
|
{
|
|
szFileName=(LPTSTR)szPath;
|
|
for(int i=(int)_tcsclen(szPath)-1;i>=0;i--) if(szPath[i]=='\\' || szPath[i]=='/')
|
|
{
|
|
szFileName=(LPTSTR)&szPath[i+1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
CMAPIAttachment attachment;
|
|
if(attachment.Create(Message()))
|
|
{
|
|
if(!szCID || _tcscmp(szCID, CONTACT_PICTURE))
|
|
{
|
|
attachment.SetFileName(szFileName);
|
|
attachment.SetLongFileName(szFileName);
|
|
if(szCID) attachment.SetCID(szCID);
|
|
}
|
|
else
|
|
{
|
|
attachment.SetFileName(szCID);
|
|
attachment.SetLongFileName(szCID);
|
|
attachment.SetPropertyValue(PR_ATTACHMENT_UNKNOWN, TRUE);
|
|
}
|
|
if(attachment.LoadAttachment(szPath))
|
|
{
|
|
attachment.Save();
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// use nIndex of -1 to delete all attachments
|
|
BOOL CMAPIObject::DeleteAttachment(int nIndex)
|
|
{
|
|
LPMAPITABLE pAttachTable=NULL;
|
|
if(Message()->GetAttachmentTable(0, &pAttachTable)!=S_OK) return FALSE;
|
|
|
|
BOOL bResult=FALSE;
|
|
enum { PROP_ATTACH_NUM, ATTACH_COLS };
|
|
static SizedSPropTagArray(ATTACH_COLS, Columns)={ATTACH_COLS, PR_ATTACH_NUM };
|
|
if(pAttachTable->SetColumns((LPSPropTagArray)&Columns, 0)==S_OK)
|
|
{
|
|
int i=0;
|
|
LPSRowSet pRows=NULL;
|
|
while(TRUE)
|
|
{
|
|
if(pAttachTable->QueryRows(1, 0, &pRows)==S_OK)
|
|
{
|
|
if(!pRows->cRows) break;
|
|
else if(i<nIndex)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
bResult=(Message()->DeleteAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.ul, 0, NULL, 0)==S_OK);
|
|
}
|
|
FreeProws(pRows);
|
|
if(!bResult || nIndex==i) break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
RELEASE(pAttachTable);
|
|
return bResult;
|
|
}
|
|
|
|
// use nIndex of -1 to save all attachments to szFolder
|
|
BOOL CMAPIObject::SaveAttachment(LPCTSTR szFolder, int nIndex, LPCTSTR szFileName)
|
|
{
|
|
LPMAPITABLE pAttachTable=NULL;
|
|
if(Message()->GetAttachmentTable(0, &pAttachTable)!=S_OK) return FALSE;
|
|
|
|
CString strPath;
|
|
BOOL bResult=FALSE;
|
|
enum { PROP_ATTACH_NUM, PROP_ATTACH_LONG_FILENAME, PROP_ATTACH_FILENAME, ATTACH_COLS };
|
|
static SizedSPropTagArray(ATTACH_COLS, Columns)={ATTACH_COLS, PR_ATTACH_NUM, PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME };
|
|
if(pAttachTable->SetColumns((LPSPropTagArray)&Columns, 0)==S_OK)
|
|
{
|
|
LPSRowSet pRows=NULL;
|
|
CMAPIAttachment attachment;
|
|
while(TRUE)
|
|
{
|
|
if(nIndex>=0 && pAttachTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL)!=S_OK) break;
|
|
if(pAttachTable->QueryRows(1, 0, &pRows)==S_OK)
|
|
{
|
|
if(!pRows->cRows) break;
|
|
LPATTACH pAttachment;
|
|
if(Message()->OpenAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.bin.cb, NULL, 0, &pAttachment)==S_OK)
|
|
{
|
|
if (szFileName != NULL)
|
|
{
|
|
strPath.Format(_T("%s\\%s"), szFolder, szFileName);
|
|
}
|
|
else
|
|
{
|
|
if(CMAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME])) strPath.Format(_T("%s\\%s"), szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME].Value.LPSZ);
|
|
else if(CMAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME])) strPath.Format(_T("%s\\%s"), szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME].Value.LPSZ);
|
|
else strPath.Format(_T("%s\\Attachment.dat"), szFolder);
|
|
}
|
|
attachment.Attach(pAttachment);
|
|
attachment.SaveAttachment(strPath);
|
|
bResult=attachment.SaveAttachment(strPath);
|
|
}
|
|
}
|
|
FreeProws(pRows);
|
|
if(nIndex>=0) break;
|
|
}
|
|
}
|
|
RELEASE(pAttachTable);
|
|
return bResult;
|
|
}
|
|
|
|
// Gets the body of the item, if bAutoDetect is set, uses the MessageEditorFormat to try to determine which property to return
|
|
BOOL CMAPIObject::GetBody(CString& strBody, BOOL bAutoDetect)
|
|
{
|
|
if(bAutoDetect)
|
|
{
|
|
int nFormat=GetMessageEditorFormat();
|
|
if(nFormat==EDITOR_FORMAT_DONTKNOW || nFormat==EDITOR_FORMAT_RTF) return GetRTF(strBody);
|
|
else if(nFormat==EDITOR_FORMAT_HTML) return GetHTML(strBody);
|
|
}
|
|
return GetPropertyString(PR_BODY, strBody, TRUE);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetBody(LPCTSTR szBody)
|
|
{
|
|
if(SetPropertyString(PR_BODY, szBody, TRUE))
|
|
{
|
|
SetMessageEditorFormat(EDITOR_FORMAT_PLAINTEXT);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetHTML(CString& strHTML)
|
|
{
|
|
return GetPropertyString(PR_BODY_HTML, strHTML, TRUE);
|
|
}
|
|
|
|
BOOL CMAPIObject::SetHTML(LPCTSTR szHTML)
|
|
{
|
|
if(szHTML)
|
|
{
|
|
// does this Message Store support HTML directly?
|
|
ULONG ulSupport=m_pMAPI ? m_pMAPI->GetMessageStoreSupport() : 0;
|
|
if(ulSupport&STORE_HTML_OK)
|
|
{
|
|
if(SetPropertyString(PR_BODY_HTML, szHTML, TRUE))
|
|
{
|
|
SetMessageEditorFormat(EDITOR_FORMAT_HTML);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// otherwise lets encode it into RTF
|
|
TCHAR szCodePage[6]=_T("1252"); // default codepage is ANSI - Latin I
|
|
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, szCodePage, sizeof(szCodePage));
|
|
|
|
CString strRTF;
|
|
strRTF.Format(_T("{\\rtf1\\ansi\\ansicpg%s\\fromhtml1 {\\*\\htmltag1 "), szCodePage);
|
|
strRTF+=szHTML;
|
|
strRTF+=_T(" }}");
|
|
|
|
return SetRTF(strRTF);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetRTF(CString& strRTF)
|
|
{
|
|
strRTF=_T("");
|
|
IStream* pStream;
|
|
|
|
const int BUF_SIZE=16384;
|
|
char szBuf[BUF_SIZE+1];
|
|
ULONG ulNumChars;
|
|
|
|
#ifdef _WIN32_WCE
|
|
int nMessageStatus=GetMessageStatus();
|
|
if(nMessageStatus & MSGSTATUS_PARTIAL) return;
|
|
|
|
if(nMessageStatus & MSGSTATUS_HAS_PR_BODY_HTML)
|
|
{
|
|
if(Message()->OpenProperty(PR_BODY_HTML_A, &IID_IStream, STGM_READ, NULL, (LPUNKNOWN*)&pStream)!=S_OK) return FALSE;
|
|
|
|
do
|
|
{
|
|
pStream->Read(szBuf, BUF_SIZE, &ulNumChars);
|
|
szBuf[min(BUF_SIZE,ulNumChars)]=0;
|
|
strRTF+=szBuf;
|
|
} while(ulNumChars>=BUF_SIZE);
|
|
|
|
RELEASE(pStream);
|
|
}
|
|
else if(nMessageStatus & MSGSTATUS_HAS_PR_BODY)
|
|
{
|
|
if(Message()->OpenProperty(PR_BODY_A, &IID_IStream, STGM_READ, NULL, (LPUNKNOWN*)&pStream)!=S_OK) return FALSE;
|
|
|
|
do
|
|
{
|
|
pStream->Read(szBuf, BUF_SIZE, &ulNumChars);
|
|
szBuf[min(BUF_SIZE,ulNumChars)]=0;
|
|
strRTF+=szBuf;
|
|
} while(ulNumChars>=BUF_SIZE);
|
|
|
|
RELEASE(pStream);
|
|
}
|
|
#else
|
|
if(Message()->OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, STGM_READ, 0, (LPUNKNOWN*)&pStream)!=S_OK) return FALSE;
|
|
|
|
IStream *pUncompressed;
|
|
if(WrapCompressedRTFStream(pStream, 0, &pUncompressed)==S_OK)
|
|
{
|
|
do
|
|
{
|
|
pUncompressed->Read(szBuf, BUF_SIZE, &ulNumChars);
|
|
szBuf[min(BUF_SIZE,ulNumChars)]=0;
|
|
strRTF+=szBuf;
|
|
} while(ulNumChars>=BUF_SIZE);
|
|
RELEASE(pUncompressed);
|
|
}
|
|
|
|
RELEASE(pStream);
|
|
#endif
|
|
|
|
// does this RTF contain encoded HTML, or text?
|
|
if(strRTF.Find(_T("\\fromhtml"))!=-1)
|
|
{
|
|
return GetHTML(strRTF);
|
|
}
|
|
else if(strRTF.Find(_T("\\fromtext"))!=-1)
|
|
{
|
|
return GetBody(strRTF, FALSE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMAPIObject::SetRTF(LPCTSTR szRTF)
|
|
{
|
|
LPSTREAM pStream=NULL;
|
|
if(Message()->OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, STGM_CREATE | STGM_WRITE, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStream)==S_OK)
|
|
{
|
|
#ifndef _WIN32_WCE
|
|
IStream *pUncompressed;
|
|
if(WrapCompressedRTFStream(pStream,MAPI_MODIFY, &pUncompressed)==S_OK)
|
|
{
|
|
pUncompressed->Write(szRTF, (ULONG)_tcslen(szRTF)*sizeof(TCHAR), NULL);
|
|
if(pUncompressed->Commit(STGC_DEFAULT)==S_OK) pStream->Commit(STGC_DEFAULT);
|
|
RELEASE(pUncompressed);
|
|
}
|
|
#endif
|
|
RELEASE(pStream);
|
|
SetMessageEditorFormat(EDITOR_FORMAT_RTF);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetLastModified(SYSTEMTIME& tmLastModified)
|
|
{
|
|
LPSPropValue pProp;
|
|
if(GetProperty(PR_LAST_MODIFICATION_TIME, pProp)==S_OK)
|
|
{
|
|
SYSTEMTIME tm;
|
|
FileTimeToSystemTime(&pProp->Value.ft, &tm);
|
|
SystemTimeToTzSpecificLocalTime(NULL, &tm, &tmLastModified);
|
|
|
|
MAPIFreeBuffer(pProp);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::GetLastModified(CString& strLastModified, LPCTSTR szFormat)
|
|
{
|
|
SYSTEMTIME tm;
|
|
if(GetLastModified(tm))
|
|
{
|
|
TCHAR szDate[256];
|
|
if(!szFormat) szFormat=_T("MM/dd/yyyy");
|
|
GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &tm, szFormat, szDate, 256);
|
|
strLastModified=szDate;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMAPIObject::SetLastModified(SYSTEMTIME& tmLastModified)
|
|
{
|
|
SPropValue prop;
|
|
prop.ulPropTag=PR_LAST_MODIFICATION_TIME;
|
|
SystemTimeToFileTime(&tmLastModified, &prop.Value.ft);
|
|
return (m_pItem && m_pItem->SetProps(1, &prop, NULL)==S_OK);
|
|
}
|