//////////////////////////////////////////////////////////////////////////////////////////////////////////// // // 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;icb; 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;iValue.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(iDeleteAttach(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); }