diff --git a/bazaar/MAPIEx/MAPIAppointment.cpp b/bazaar/MAPIEx/MAPIAppointment.cpp index 561234013..3d7ad71df 100644 --- a/bazaar/MAPIEx/MAPIAppointment.cpp +++ b/bazaar/MAPIEx/MAPIAppointment.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // File: MAPIAppointment.cpp @@ -14,8 +16,8 @@ // Ported to U++ Framework by Koldo. See License.txt file -#include "MapiUtil.h" #include "MAPIEx.h" +#include "MapiUtil.h" ///////////////////////////////////////////////////////////// // MAPIAppointment @@ -132,3 +134,4 @@ String MAPIAppointment::GetMeetingUID() { } #endif +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIAttachment.cpp b/bazaar/MAPIEx/MAPIAttachment.cpp index 2df98b930..5ed4369b9 100644 --- a/bazaar/MAPIEx/MAPIAttachment.cpp +++ b/bazaar/MAPIEx/MAPIAttachment.cpp @@ -1,199 +1,203 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// File: MAPIAttachment.cpp -// Description: MAPI Attachment class wrapper -// -// 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/MAPIEx.asp -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Ported to U++ Framework by Koldo. See License.txt file - -//#include "MAPIExPCH.h" -#include "MAPIEx.h" - -///////////////////////////////////////////////////////////// -// MAPIAttachment - -MAPIAttachment::MAPIAttachment() { - m_pStream = NULL; - m_nBytesWritten = 0; -} - -MAPIAttachment::~MAPIAttachment() { - Close(); -} - -void MAPIAttachment::Attach(LPATTACH pAttachment) { - Close(); - m_pItem = pAttachment; -} - -LPATTACH MAPIAttachment::Detach() { - LPATTACH pAttachment = Attachment(); - m_pItem = NULL; - return pAttachment; -} - -bool MAPIAttachment::Create(LPMESSAGE pMessage) { - Close(); - - bool bResult = false; - if(pMessage) { - LPATTACH pAttachment; - ULONG ulAttachmentNum=0; - - if(pMessage->CreateAttach(NULL, 0, &ulAttachmentNum, &pAttachment) == S_OK) { - m_pItem=pAttachment; - - const int nProperties = 2; - SPropValue prop[nProperties]; - memset(prop, 0,sizeof(SPropValue)*nProperties); - prop[0].ulPropTag = PR_ATTACH_METHOD; - prop[0].Value.ul = ATTACH_BY_VALUE; - prop[1].ulPropTag = PR_RENDERING_POSITION; - prop[1].Value.l = 1; - if(pAttachment->SetProps(nProperties, prop, NULL) == S_OK) - bResult=true; - } - } - return bResult; -} - -bool MAPIAttachment::Open(LPMESSAGE pMessage, int nIndex) { - Close(); - - bool bResult = false; - LPMAPITABLE pAttachTable; - if(!(nIndex >= 0 && pMessage && pMessage->GetAttachmentTable(0, &pAttachTable) == S_OK)) - return 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) { - if(pAttachTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { - LPSRowSet pRows = NULL; - if(pAttachTable->QueryRows(1, 0, &pRows) == S_OK) { - if(pRows->cRows > 0) { - LPATTACH pAttachment; - if(pMessage->OpenAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.ul, - NULL, 0, &pAttachment) == S_OK) { - m_pItem=pAttachment; - bResult=true; - } - } - MAPIEx::FreeProws(pRows); - } - } - } - return bResult; -} - -void MAPIAttachment::Close() { - CloseStream(); - MAPIObject::Close(); -} - -String MAPIAttachment::GetDisplayName() { - return GetPropertyString(PR_DISPLAY_NAME); -} - -String MAPIAttachment::GetFileName() { - return GetPropertyString(PR_ATTACH_FILENAME); -} - -String MAPIAttachment::GetLongFileName() { - return GetPropertyString(PR_ATTACH_LONG_FILENAME); -} - -String MAPIAttachment::GetCID() { - return GetPropertyString(PR_ATTACH_CONTENT_ID); -} - -bool MAPIAttachment::SetDisplayName(const String &szDisplayName) { - return SetPropertyString(PR_DISPLAY_NAME, szDisplayName); -} - -bool MAPIAttachment::SetFileName(const String &szFileName) { - return SetPropertyString(PR_ATTACH_FILENAME, szFileName); -} - -bool MAPIAttachment::SetLongFileName(const String &szLongFileName) { - return SetPropertyString(PR_ATTACH_LONG_FILENAME, szLongFileName); -} - -bool MAPIAttachment::SetCID(const String &szCID) { - return SetPropertyString(PR_ATTACH_CONTENT_ID, szCID); -} - -bool MAPIAttachment::OpenStream(bool bCreate) { - if(m_pItem) { - ULONG ulInterfaceOptions = STGM_READ; - ULONG ulFlags = 0; - if(bCreate) { - ulInterfaceOptions = 0; - ulFlags = MAPI_MODIFY | MAPI_CREATE; - } - return (m_pItem->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, ulInterfaceOptions, ulFlags, (LPUNKNOWN*)&m_pStream)==S_OK); - } - return false; -} - -int MAPIAttachment::Read(BYTE* pData, int nCount) { - if(m_pStream) { - ULONG ulRead; - m_pStream->Read(pData, nCount, &ulRead); - return ulRead; - } - return -1; -} - -int MAPIAttachment::Write(BYTE* pData, int nCount) { - if(m_pStream) { - ULONG ulWritten; - m_pStream->Write(pData, nCount, &ulWritten); - m_nBytesWritten += ulWritten; - return ulWritten; - } - return -1; -} - -void MAPIAttachment::CloseStream() { - if(m_pStream) { - m_pStream->Commit(STGC_DEFAULT); - RELEASE(m_pStream); - SetPropertyValue(PR_ATTACH_SIZE, m_nBytesWritten); - m_nBytesWritten = 0; - } -} - -bool MAPIAttachment::LoadAttachment(const String &szPath) { - String file = LoadFile(szPath); - - if(file.IsEmpty() || !OpenStream(true)) - return false; - - Write((BYTE *)file.Begin(), file.GetLength()); - return true; -} - -bool MAPIAttachment::SaveAttachment(const String &szPath) { - if (!OpenStream(false)) - return false; - String file; - const int BUF_SIZE = 4096; - BYTE pData[BUF_SIZE]; - ULONG ulRead; - - do { - ulRead = Read(pData, BUF_SIZE); - if(ulRead >= 0) - file.Cat(pData, ulRead); - } while(ulRead >= BUF_SIZE); - return SaveFile(szPath, file); -} +#ifdef _WIN32 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// File: MAPIAttachment.cpp +// Description: MAPI Attachment class wrapper +// +// 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/MAPIEx.asp +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Ported to U++ Framework by Koldo. See License.txt file + +//#include "MAPIExPCH.h" +#include "MAPIEx.h" + +///////////////////////////////////////////////////////////// +// MAPIAttachment + +MAPIAttachment::MAPIAttachment() { + m_pStream = NULL; + m_nBytesWritten = 0; +} + +MAPIAttachment::~MAPIAttachment() { + Close(); +} + +void MAPIAttachment::Attach(LPATTACH pAttachment) { + Close(); + m_pItem = pAttachment; +} + +LPATTACH MAPIAttachment::Detach() { + LPATTACH pAttachment = Attachment(); + m_pItem = NULL; + return pAttachment; +} + +bool MAPIAttachment::Create(LPMESSAGE pMessage) { + Close(); + + bool bResult = false; + if(pMessage) { + LPATTACH pAttachment; + ULONG ulAttachmentNum=0; + + if(pMessage->CreateAttach(NULL, 0, &ulAttachmentNum, &pAttachment) == S_OK) { + m_pItem=pAttachment; + + const int nProperties = 2; + SPropValue prop[nProperties]; + memset(prop, 0,sizeof(SPropValue)*nProperties); + prop[0].ulPropTag = PR_ATTACH_METHOD; + prop[0].Value.ul = ATTACH_BY_VALUE; + prop[1].ulPropTag = PR_RENDERING_POSITION; + prop[1].Value.l = 1; + if(pAttachment->SetProps(nProperties, prop, NULL) == S_OK) + bResult=true; + } + } + return bResult; +} + +bool MAPIAttachment::Open(LPMESSAGE pMessage, int nIndex) { + Close(); + + bool bResult = false; + LPMAPITABLE pAttachTable; + if(!(nIndex >= 0 && pMessage && pMessage->GetAttachmentTable(0, &pAttachTable) == S_OK)) + return 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) { + if(pAttachTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { + LPSRowSet pRows = NULL; + if(pAttachTable->QueryRows(1, 0, &pRows) == S_OK) { + if(pRows->cRows > 0) { + LPATTACH pAttachment; + if(pMessage->OpenAttach(pRows->aRow[0].lpProps[PROP_ATTACH_NUM].Value.ul, + NULL, 0, &pAttachment) == S_OK) { + m_pItem=pAttachment; + bResult=true; + } + } + MAPIEx::FreeProws(pRows); + } + } + } + return bResult; +} + +void MAPIAttachment::Close() { + CloseStream(); + MAPIObject::Close(); +} + +String MAPIAttachment::GetDisplayName() { + return GetPropertyString(PR_DISPLAY_NAME); +} + +String MAPIAttachment::GetFileName() { + return GetPropertyString(PR_ATTACH_FILENAME); +} + +String MAPIAttachment::GetLongFileName() { + return GetPropertyString(PR_ATTACH_LONG_FILENAME); +} + +String MAPIAttachment::GetCID() { + return GetPropertyString(PR_ATTACH_CONTENT_ID); +} + +bool MAPIAttachment::SetDisplayName(const String &szDisplayName) { + return SetPropertyString(PR_DISPLAY_NAME, szDisplayName); +} + +bool MAPIAttachment::SetFileName(const String &szFileName) { + return SetPropertyString(PR_ATTACH_FILENAME, szFileName); +} + +bool MAPIAttachment::SetLongFileName(const String &szLongFileName) { + return SetPropertyString(PR_ATTACH_LONG_FILENAME, szLongFileName); +} + +bool MAPIAttachment::SetCID(const String &szCID) { + return SetPropertyString(PR_ATTACH_CONTENT_ID, szCID); +} + +bool MAPIAttachment::OpenStream(bool bCreate) { + if(m_pItem) { + ULONG ulInterfaceOptions = STGM_READ; + ULONG ulFlags = 0; + if(bCreate) { + ulInterfaceOptions = 0; + ulFlags = MAPI_MODIFY | MAPI_CREATE; + } + return (m_pItem->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, ulInterfaceOptions, ulFlags, (LPUNKNOWN*)&m_pStream)==S_OK); + } + return false; +} + +int MAPIAttachment::Read(BYTE* pData, int nCount) { + if(m_pStream) { + ULONG ulRead; + m_pStream->Read(pData, nCount, &ulRead); + return ulRead; + } + return -1; +} + +int MAPIAttachment::Write(BYTE* pData, int nCount) { + if(m_pStream) { + ULONG ulWritten; + m_pStream->Write(pData, nCount, &ulWritten); + m_nBytesWritten += ulWritten; + return ulWritten; + } + return -1; +} + +void MAPIAttachment::CloseStream() { + if(m_pStream) { + m_pStream->Commit(STGC_DEFAULT); + RELEASE(m_pStream); + SetPropertyValue(PR_ATTACH_SIZE, m_nBytesWritten); + m_nBytesWritten = 0; + } +} + +bool MAPIAttachment::LoadAttachment(const String &szPath) { + String file = LoadFile(szPath); + + if(file.IsEmpty() || !OpenStream(true)) + return false; + + Write((BYTE *)file.Begin(), file.GetLength()); + return true; +} + +bool MAPIAttachment::SaveAttachment(const String &szPath) { + if (!OpenStream(false)) + return false; + String file; + const int BUF_SIZE = 4096; + BYTE pData[BUF_SIZE]; + ULONG ulRead; + + do { + ulRead = Read(pData, BUF_SIZE); + if(ulRead >= 0) + file.Cat(pData, ulRead); + } while(ulRead >= BUF_SIZE); + return SaveFile(szPath, file); +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIContact.cpp b/bazaar/MAPIEx/MAPIContact.cpp index 397e4c278..0a3dd07b5 100644 --- a/bazaar/MAPIEx/MAPIContact.cpp +++ b/bazaar/MAPIEx/MAPIContact.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // File: MAPIContact.cpp @@ -14,9 +16,11 @@ // Ported to U++ Framework by Koldo. See License.txt file -#include #include "MAPIEx.h" -String Tokenize(const String &str, const String &token, int &pos); +#include "MapiUtil.h" + +#include + #define CATEGORIES_PROPERTY "Keywords" @@ -659,14 +663,14 @@ bool MAPIContact::SetCategories(const String &szCategories) { nCount = 0; nIndex = 0; int nLen = 0; - strCategory=Tokenize(strCategories, ";", nIndex); + strCategory = Tokenize(strCategories, ";", nIndex); do { nLen = strCategory.GetLength(); if(nLen > 0) { arCategories[nCount] = new TCHAR[nLen+1]; memcpy(arCategories[nCount], (LPCTSTR)strCategory, nLen*sizeof(TCHAR)); arCategories[nCount++][nLen] = (TCHAR)0; - strCategory=Tokenize(strCategories, ";", nIndex); + strCategory = Tokenize(strCategories, ";", nIndex); } } while(nLen); @@ -711,3 +715,5 @@ bool MAPIContact::SetPicture(const String &szPath) { return bPicture; #endif } + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIEx.cpp b/bazaar/MAPIEx/MAPIEx.cpp index 722319235..c76fd8bca 100644 --- a/bazaar/MAPIEx/MAPIEx.cpp +++ b/bazaar/MAPIEx/MAPIEx.cpp @@ -1,691 +1,694 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// File: MAPIEx.cpp -// Description: Windows Extended MAPI class -// -// Copyright (C) 2005-2010, 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 -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Ported to U++ Framework by Koldo. See License.txt file - -#include -#include "MAPIEx.h" -#include "MAPISink.h" - -#ifdef _WIN32_WCE -#include -#pragma comment(lib,"cemapi.lib") -#pragma comment(lib,"pimstore.lib") - -#else -#pragma comment (lib,"mapi32.lib") -#endif -#pragma comment(lib,"Ole32.lib") - -INITBLOCK { - MAPIEx::Init(); -} - -EXITBLOCK { - MAPIEx::Term(); -} - -void WINAPI MAPIEx::FreeProws(LPSRowSet pRows) { - if(pRows) { - for(ULONG i = 0; i < pRows->cRows; i++) - MAPIFreeBuffer(pRows->aRow[i].lpProps); - MAPIFreeBuffer(pRows); - } -} - -///////////////////////////////////////////////////////////// -// MAPIEx - -int MAPIEx::cm_bComInit = FALSE; -int MAPIEx::cm_nMAPICode = 0; - -MAPIEx::MAPIEx() { - m_pSession = NULL; - m_pMsgStore = NULL; - m_sink = 0; -} - -MAPIEx::~MAPIEx() { - Logout(); -} - -// flags are ignored on Windows CE -bool MAPIEx::Init(DWORD dwFlags, bool bInitAsService) { - if(CoInitializeEx(NULL, COINIT_MULTITHREADED) == S_OK) - cm_bComInit = true; -#ifdef _WIN32_WCE - // flags are ignored on Windows CE - if(MAPIInitialize(NULL) != S_OK) - return false; - CPOOM::Init(); -#else - if(!dwFlags) - dwFlags = MAPI_NO_COINIT | MAPI_MULTITHREAD_NOTIFICATIONS; - if(bInitAsService) - dwFlags |= MAPI_NT_SERVICE; - - MAPIINIT_0 MAPIInit = { MAPI_INIT_VERSION, dwFlags }; - if(MAPIInitialize(&MAPIInit) != S_OK) - return false; -#endif - return true; -} - -void MAPIEx::Term() { - MAPIUninitialize(); -#ifdef _WIN32_WCE - CPOOM::Term(); -#endif - if(cm_bComInit) - CoUninitialize(); -} - -// dwFlags set to defaults but added as a param here for special cases (ie MAPI_NO_MAIL) -bool MAPIEx::Login(const String szProfileName, DWORD dwFlags, bool bInitAsService) { - if(!dwFlags) - dwFlags = MAPI_EXTENDED | MAPI_USE_DEFAULT | MAPI_NEW_SESSION; - if(bInitAsService) - dwFlags |= MAPI_EXPLICIT_PROFILE | MAPI_NT_SERVICE; - return (MAPILogonEx(0, (LPTSTR)(szProfileName.Begin()), NULL, dwFlags, &m_pSession) == S_OK); -} - -void MAPIEx::Logout() { - if(m_sink) { - if(m_pMsgStore) - m_pMsgStore->Unadvise(m_sink); - m_sink = 0; - } - RELEASE(m_pMsgStore); - RELEASE(m_pSession); -} - -bool MAPIEx::CreateProfile(String szProfileName) { - LPPROFADMIN lpProfAdmin = NULL; - if(MAPIAdminProfiles(0, &lpProfAdmin) != S_OK) - return false; - HRESULT hr = lpProfAdmin->CreateProfile((LPTSTR)(szProfileName.Begin()), NULL, 0, 0); - RELEASE(lpProfAdmin); - return (hr == S_OK); -} - -bool MAPIEx::DeleteProfile(String szProfileName) { - LPPROFADMIN lpProfAdmin = NULL; - if(MAPIAdminProfiles(0, &lpProfAdmin) != S_OK) - return false; - HRESULT hr = lpProfAdmin->DeleteProfile((LPTSTR)(szProfileName.Begin()), 0); - RELEASE(lpProfAdmin); - return (hr == S_OK); -} - -bool MAPIEx::CreateMessageService(LPCTSTR szProfileName, LPCTSTR szService, LPCTSTR szDisplayName) { - bool bResult=FALSE; - LPPROFADMIN lpProfAdmin=NULL; - if(MAPIAdminProfiles(0, &lpProfAdmin) == S_OK) { - LPSERVICEADMIN lpMsgServiceAdmin=NULL; - if(lpProfAdmin->AdminServices((LPTSTR)szProfileName, NULL, 0, MAPI_DIALOG, - &lpMsgServiceAdmin) == S_OK) { - bResult = (lpMsgServiceAdmin->CreateMsgService((LPTSTR)szService, - (LPTSTR)szDisplayName, 0, SERVICE_UI_ALWAYS | SERVICE_UI_ALLOWED) == S_OK); - RELEASE(lpMsgServiceAdmin); - } - RELEASE(lpProfAdmin); - } - return bResult; -} - -String MAPIEx::GetProfileName() { - String strProfileName; -#ifndef _WIN32_WCE - if(!m_pSession) - return strProfileName; - - LPSRowSet pRows = NULL; - const int nProperties = 2; - SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME_A, PR_RESOURCE_TYPE}}; - - IMAPITable* pStatusTable; - if(m_pSession->GetStatusTable(0, &pStatusTable) == S_OK) { - if(pStatusTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { - while(pStatusTable->QueryRows(1, 0, &pRows) == S_OK) { - if(pRows->cRows != 1) - FreeProws(pRows); - else if(pRows->aRow[0].lpProps[1].Value.ul == MAPI_SUBSYSTEM) { - strProfileName = GetValidString(pRows->aRow[0].lpProps[0]); - FreeProws(pRows); - } else { - FreeProws(pRows); - continue; - } - break; - } - } - RELEASE(pStatusTable); - } -#endif - return FromSystemCharset(strProfileName); -} - -String MAPIEx::GetProfileEmail() { - String strProfileEmail; -#ifndef _WIN32_WCE - if(!m_pSession) - return strProfileEmail; - - SBinary entryID; - if(m_pSession->QueryIdentity(&entryID.cb, (LPENTRYID*)&entryID.lpb) == S_OK) { - GetExEmail(entryID, strProfileEmail); - return strProfileEmail; - } -#endif - return strProfileEmail; -} - -int MAPIEx::GetMessageStoreCount() { - IMAPITable* pMsgStoresTable; - if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { - ULONG ulCount; - HRESULT hr = pMsgStoresTable->GetRowCount(0, &ulCount); - RELEASE(pMsgStoresTable); - if(hr == S_OK) - return ulCount; - } - return -1; -} - -bool MAPIEx::GetMessageStoreProperties(int nIndex, String& strName, bool& bDefaultStore) { - bool bResult = FALSE; - IMAPITable *pMsgStoresTable; - if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { - LPSRowSet pRows = NULL; - const int nProperties = 3; - SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, - PR_DEFAULT_STORE}}; - - if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { - if(pMsgStoresTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { - if(pMsgStoresTable->QueryRows(1, 0, &pRows) == S_OK) { - if(pRows->cRows>0) { - strName = GetValidString(pRows->aRow[0].lpProps[0]); - bDefaultStore = pRows->aRow[0].lpProps[2].Value.b; - bResult = true; - } - FreeProws(pRows); - } - } - } - RELEASE(pMsgStoresTable); - } - return bResult; -} - -bool MAPIEx::OpenMessageStore(int nIndex, ULONG ulFlags) { - BOOL bResult = false; - IMAPITable* pMsgStoresTable; - if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { - LPSRowSet pRows = NULL; - const int nProperties = 3; - SizedSPropTagArray(nProperties, Columns)={nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, - PR_DEFAULT_STORE}}; - if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { - if(pMsgStoresTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { - if(pMsgStoresTable->QueryRows(1, 0, &pRows)==S_OK) { - if(pRows->cRows>0) { - m_ulMDBFlags=ulFlags; - RELEASE(m_pMsgStore); - bResult = (m_pSession->OpenMsgStore(0, - pRows->aRow[0].lpProps[1].Value.bin.cb, - (ENTRYID*)pRows->aRow[0].lpProps[1].Value.bin.lpb, NULL, - MDB_NO_DIALOG | MAPI_BEST_ACCESS, &m_pMsgStore) == S_OK); - } - FreeProws(pRows); - } - } - } - RELEASE(pMsgStoresTable); - } - return bResult; -} - -// do not set MAPI_NO_CACHE flag for Outlook 97 and 2000 -bool MAPIEx::OpenMessageStore(String szStore, ULONG ulFlags) { - bool bResult = false; - IMAPITable* pMsgStoresTable; - if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { - LPSRowSet pRows = NULL; - const int nProperties = 3; - SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, - PR_DEFAULT_STORE}}; - if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { - while(pMsgStoresTable->QueryRows(1, 0, &pRows) == S_OK) { - if(pRows->cRows != 1) - FreeProws(pRows); - else { - if(szStore.IsEmpty()) { - if(pRows->aRow[0].lpProps[2].Value.b) - bResult = true; - } else { - String strStore = GetValidString(pRows->aRow[0].lpProps[0]); - if(strStore.Find(szStore)!=-1) - bResult = true; - } - if(!bResult) { - FreeProws(pRows); - continue; - } - } - break; - } - if(bResult) { - m_ulMDBFlags = ulFlags; - RELEASE(m_pMsgStore); - bResult = (m_pSession->OpenMsgStore(0, pRows->aRow[0].lpProps[1].Value.bin.cb, - (ENTRYID*)pRows->aRow[0].lpProps[1].Value.bin.lpb, NULL, - MDB_NO_DIALOG | MAPI_BEST_ACCESS, &m_pMsgStore) == S_OK); - FreeProws(pRows); - } - } - RELEASE(pMsgStoresTable); - } - return bResult; -} - -ULONG MAPIEx::GetMessageStoreSupport() { - if(!m_pMsgStore) - return false; - - LPSPropValue props = NULL; - ULONG cValues = 0; - ULONG rgTags[] = {1, PR_STORE_SUPPORT_MASK}; - ULONG ulSupport = 0; - - if(m_pMsgStore->GetProps((LPSPropTagArray) rgTags, MAPIEx::cm_nMAPICode, &cValues, &props) - == S_OK) { - ulSupport = props->Value.ul; - MAPIFreeBuffer(props); - } - return ulSupport; -} - -#ifdef _WIN32_WCE -CPOOM* MAPIEx::GetPOOM() { - return m_pFolder ? m_pFolder->GetPOOM() : NULL; -} -#endif - -bool MAPIEx::OpenFolder(unsigned long ulFolderID, MAPIFolder& folder) { - if(!m_pMsgStore) - return NULL; - - LPSPropValue props = NULL; - ULONG cValues = 0; - DWORD dwObjType; - ULONG rgTags[] = { 1, ulFolderID }; - LPMAPIFOLDER pFolder; - - if(S_OK != m_pMsgStore->GetProps((LPSPropTagArray) rgTags, cm_nMAPICode, &cValues, &props)) - return false; - if(S_OK != m_pMsgStore->OpenEntry(props[0].Value.bin.cb, (LPENTRYID)props[0].Value.bin.lpb, - NULL, m_ulMDBFlags, &dwObjType, (LPUNKNOWN*)&pFolder)) - return false; - - MAPIFreeBuffer(props); - if(pFolder) { - folder.Attach(this, pFolder); - folder.GetHierarchy(); - folder.GetContents(); - return true; - } - return false; -} - -bool MAPIEx::OpenFolder(const String &folderName, MAPIFolder &folder, bool fullPath) { - MAPIFolder root; - if(!OpenRootFolder(root)) - return false; - if (!root.OpenSubFolder(folderName, folder, fullPath, "")) - return false; - folder.GetHierarchy(); - folder.GetContents(); - return true; -} - -bool MAPIEx::OpenSpecialFolder(unsigned long ulFolderID, MAPIFolder &folder) { -#ifdef _WIN32_WCE - if(pFolder->GetPOOM()->OpenFolder(ulFolderID, folder) != NULL) { - folder.GetContents(); - folder.GetHierarchy(); - return true; - } - return false; -#else - MAPIFolder inbox; - if(!OpenInbox(inbox) || !m_pMsgStore) - return false; - - LPSPropValue props = NULL; - ULONG cValues = 0; - DWORD dwObjType; - ULONG rgTags[] = { 1, ulFolderID }; - LPMAPIFOLDER pFolder; - - if(inbox.Folder()->GetProps((LPSPropTagArray) rgTags, cm_nMAPICode, &cValues, &props)!=S_OK) - return false; - HRESULT hr = m_pMsgStore->OpenEntry(props[0].Value.bin.cb, - (LPENTRYID)props[0].Value.bin.lpb, NULL, m_ulMDBFlags, &dwObjType, - (LPUNKNOWN*)&pFolder); - MAPIFreeBuffer(props); - if(hr != S_OK) - return false; - - if(pFolder) { - folder.Attach(this, pFolder); - folder.GetContents(); - folder.GetHierarchy(); - return true; - } - return false; -#endif -} - -bool MAPIEx::OpenRootFolder(MAPIFolder &folder) { - return OpenFolder(PR_IPM_SUBTREE_ENTRYID, folder); -} - -bool MAPIEx::OpenInbox(MAPIFolder &folder) { -#ifdef _WIN32_WCE - return OpenFolder(PR_CE_IPM_INBOX_ENTRYID, MAPIFolder folder); -#else - if(!m_pMsgStore) - return false; - - ULONG cbEntryID; - LPENTRYID pEntryID; - DWORD dwObjType; - LPMAPIFOLDER pFolder; - - if(m_pMsgStore->GetReceiveFolder(NULL, 0, &cbEntryID, &pEntryID, NULL) != S_OK) - return false; - HRESULT hr = m_pMsgStore->OpenEntry(cbEntryID, pEntryID, NULL, m_ulMDBFlags, &dwObjType, (LPUNKNOWN*)&pFolder); - MAPIFreeBuffer(pEntryID); - - if(hr == S_OK && pFolder) { - folder.Attach(this, pFolder); - folder.GetHierarchy(); - folder.GetContents(); - return true; - } - return false; -#endif -} - -bool MAPIEx::OpenOutbox(MAPIFolder &folder) { - return OpenFolder(PR_IPM_OUTBOX_ENTRYID, folder); -} - -bool MAPIEx::OpenSentItems(MAPIFolder &folder) { - return OpenFolder(PR_IPM_SENTMAIL_ENTRYID, folder); -} - -bool MAPIEx::OpenDeletedItems(MAPIFolder &folder) { - return OpenFolder(PR_IPM_WASTEBASKET_ENTRYID, folder); -} - -bool MAPIEx::OpenContacts(MAPIFolder &folder) { - return OpenSpecialFolder(PR_IPM_CONTACT_ENTRYID, folder); -} - -bool MAPIEx::OpenDrafts(MAPIFolder &folder) { -#ifdef _WIN32_WCE - return OpenFolder(PR_CE_IPM_DRAFTS_ENTRYID, folder); -#else - return OpenSpecialFolder(PR_IPM_DRAFTS_ENTRYID, folder); -#endif -} - -bool MAPIEx::OpenCalendar(MAPIFolder &folder) { - return OpenSpecialFolder(PR_IPM_APPOINTMENT_ENTRYID, folder); -} - -// call with ulEventMask set to ALL notifications ORed together, only one Advise Sink is used. -bool MAPIEx::Notify(LPNOTIFCALLBACK lpfnCallback, LPVOID lpvContext, ULONG ulEventMask) { - if(GetMessageStoreSupport()&STORE_NOTIFY_OK) { - if(m_sink) - m_pMsgStore->Unadvise(m_sink); - MAPISink* pAdviseSink = new MAPISink(lpfnCallback, lpvContext); - if(m_pMsgStore->Advise(0, NULL,ulEventMask, pAdviseSink, &m_sink) == S_OK) - return true; - delete pAdviseSink; - m_sink = 0; - } - return false; -} - -// pumps the message queue, use this when waiting for notifications -void MAPIEx::PumpMessages() { - MSG msg; - while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -// sometimes the string in prop is invalid, causing unexpected crashes -#ifndef _WIN32_WCE -String MAPIEx::ValidateString(LPCTSTR s) { - if(s && !::IsBadStringPtr(s, (UINT_PTR)-1)) - return FromSystemCharset(s); - return Null; -} -#else -// Windows Mobile does not have IsBadStringPtr so I use SEH -// I shut off optimization because the optimizer still had trouble with the try/catch -#pragma optimize("",off) -String MAPIEx::ValidateString(String s) { - try { - if(s) { - TCHAR ch = *s; - return s; - } - } - catch(...) { - } - return Null; -} -#pragma optimize("",on) -#endif - -String MAPIEx::GetValidString(SPropValue& prop) { - return ValidateString(prop.Value.LPSZ); -} - -// sometimes the string in prop is invalid, causing unexpected crashes -String MAPIEx::GetValidMVString(SPropValue& prop, int nIndex) { - return ValidateString(prop.Value.MVSZ.LPPSZ[nIndex]); -} - -// special case of GetValidString to take the narrow string in UNICODE -void MAPIEx::GetNarrowString(SPropValue& prop, String& strNarrow) { - String s = GetValidString(prop); - if(s.IsEmpty()) - strNarrow = ""; - else - strNarrow = s; -} - -bool MAPIEx::SelectContacts(Vector &emails, const String caption) { - emails.Clear(); - LPADRLIST pAddressList; - if(ShowAddressBook(pAddressList, caption) == IDOK) { - String strEmail; - for(ULONG i = 0; i < pAddressList->cEntries; i++) { - if(GetEmail(pAddressList->aEntries[i], strEmail)) - emails.Add(strEmail); - } - MAPIEx::ReleaseAddressList(pAddressList); - } - return emails.GetCount() > 0; -} - -// Shows the default Address Book dialog, return false on failure, IDOK or IDCANCEL on success -// I force narrow strings here because it for some reason doesn't work in UNICODE -int MAPIEx::ShowAddressBook(LPADRLIST& pAddressList, const String caption) { -#ifndef _WIN32_WCE - if(!m_pSession) - return false; - - LPADRBOOK pAddressBook; - if(m_pSession->OpenAddressBook(0, NULL, 0, &pAddressBook) == S_OK) { - pAddressList = NULL; - - const char* lppszDestTitles[]={ "To" }; - ULONG lpulDestComps[] = { MAPI_TO }; - - ADRPARM adrparm; - memset(&adrparm, 0, sizeof(ADRPARM)); - adrparm.ulFlags = DIALOG_MODAL | AB_RESOLVE; - - adrparm.lpszCaption = (LPTSTR)(caption.Begin()); - - adrparm.cDestFields = 1; - adrparm.lppszDestTitles=(LPTSTR*)lppszDestTitles; - adrparm.lpulDestComps=lpulDestComps; - - HWND hDesktop = ::GetDesktopWindow(); - HRESULT hr = pAddressBook->Address((ULONG_PTR*)&hDesktop, &adrparm, &pAddressList); - RELEASE(pAddressBook); - if(hr == S_OK) - return IDOK; - if(hr == MAPI_E_USER_CANCEL) - return IDCANCEL; - } -#endif - return false; -} - -// utility function to release ADRLIST entries -void MAPIEx::ReleaseAddressList(LPADRLIST pAddressList) { -#ifndef _WIN32_WCE - FreePadrlist(pAddressList); -#else - if(pAddressList) { - for(ULONG i = 0; i < pAddressList->cEntries; i++) - MAPIFreeBuffer(pAddressList->aEntries[i].rgPropVals); - MAPIFreeBuffer(pAddressList); - } -#endif -} - -bool MAPIEx::CompareEntryIDs(ULONG cb1, LPENTRYID lpb1, ULONG cb2, LPENTRYID lpb2) { - ULONG ulResult; - if(m_pSession && m_pSession->CompareEntryIDs(cb1, lpb1, cb2, lpb2, 0, &ulResult) == S_OK) - return ulResult; - return false; -} - -// ADDRENTRY objects from Address don't come in unicode so I check for _A and force narrow strings -bool MAPIEx::GetEmail(ADRENTRY& adrEntry, String& strEmail) { -#ifndef _WIN32_WCE - LPSPropValue pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE); - if(!pProp) - pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE_A); - if(pProp) { - String strAddrType; - GetNarrowString(*pProp, strAddrType); - if(strAddrType == "EX") { - pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ENTRYID); - - SBinary entryID; - entryID.cb = pProp->Value.bin.cb; - entryID.lpb = pProp->Value.bin.lpb; - - return GetExEmail(entryID, strEmail); - } - } - pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS); - if(!pProp) - pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS_A); - if(pProp) { - GetNarrowString(*pProp, strEmail); - return true; - } -#endif - return false; -} - -bool MAPIEx::GetExEmail(SBinary entryID, String& strEmail) { - bool bResult = false; -#ifndef _WIN32_WCE - if(!m_pSession) - return false; - - LPADRBOOK pAddressBook; - if(m_pSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook) != S_OK) - return false; - ULONG ulObjType; - IMAPIProp* pItem = NULL; - if(pAddressBook->OpenEntry(entryID.cb, (ENTRYID*)entryID.lpb, NULL,MAPI_BEST_ACCESS, - &ulObjType, (LPUNKNOWN*)&pItem) == S_OK) { - if(ulObjType == MAPI_MAILUSER) { - LPSPropValue pProp; - ULONG ulPropCount; - ULONG pSMTP[] = { 1, PR_SMTP_ADDRESS }; - ULONG pEmail[] = { 1, PR_EMAIL_ADDRESS }; - - if(pItem->GetProps((LPSPropTagArray)pSMTP, MAPIEx::cm_nMAPICode, &ulPropCount, - &pProp)==S_OK) { - strEmail=MAPIEx::GetValidString(*pProp); - MAPIFreeBuffer(pProp); - bResult = true; - } - if(!bResult && pItem->GetProps((LPSPropTagArray)pEmail, MAPIEx::cm_nMAPICode, - &ulPropCount, &pProp) == S_OK) { - strEmail=MAPIEx::GetValidString(*pProp); - MAPIFreeBuffer(pProp); - bResult = true; - } - } - RELEASE(pItem); - } - RELEASE(pAddressBook); -#endif - return bResult; -} - -void MAPIEx::SetSystemTime(SYSTEMTIME& tm, int wYear, int wMonth, int wDay, int wHour, - int wMinute, int wSecond, int wMilliSeconds) { - tm.wYear = (WORD)wYear; - tm.wMonth = (WORD)wMonth; - tm.wDay = (WORD)wDay; - tm.wHour = (WORD)wHour; - tm.wMinute = (WORD)wMinute; - tm.wSecond = (WORD)wSecond; - tm.wMilliseconds= (WORD)wMilliSeconds; - tm.wDayOfWeek = 0; -} - -void MAPIEx::SetSystemTime(SYSTEMTIME& tm, const Time &t) { - tm.wYear = t.year; - tm.wMonth = t.month; - tm.wDay = t.day; - tm.wHour = t.hour; - tm.wMinute = t.minute; - tm.wSecond = t.second; - tm.wMilliseconds = 0; - tm.wDayOfWeek = 0; -} - -Time MAPIEx::GetSystemTime(SYSTEMTIME& tm) { - return Time(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond); -} - \ No newline at end of file +#ifdef _WIN32 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// File: MAPIEx.cpp +// Description: Windows Extended MAPI class +// +// Copyright (C) 2005-2010, 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 +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Ported to U++ Framework by Koldo. See License.txt file + +#include "MAPIEx.h" +#include "MapiUtil.h" +#include "MAPISink.h" + +#ifdef _WIN32_WCE +#include +#pragma comment(lib,"cemapi.lib") +#pragma comment(lib,"pimstore.lib") + +#else +#pragma comment (lib,"mapi32.lib") +#endif +#pragma comment(lib,"Ole32.lib") + +INITBLOCK { + MAPIEx::Init(); +} + +EXITBLOCK { + MAPIEx::Term(); +} + +void WINAPI MAPIEx::FreeProws(LPSRowSet pRows) { + if(pRows) { + for(ULONG i = 0; i < pRows->cRows; i++) + MAPIFreeBuffer(pRows->aRow[i].lpProps); + MAPIFreeBuffer(pRows); + } +} + +///////////////////////////////////////////////////////////// +// MAPIEx + +int MAPIEx::cm_bComInit = FALSE; +int MAPIEx::cm_nMAPICode = 0; + +MAPIEx::MAPIEx() { + m_pSession = NULL; + m_pMsgStore = NULL; + m_sink = 0; +} + +MAPIEx::~MAPIEx() { + Logout(); +} + +// flags are ignored on Windows CE +bool MAPIEx::Init(DWORD dwFlags, bool bInitAsService) { + if(CoInitializeEx(NULL, COINIT_MULTITHREADED) == S_OK) + cm_bComInit = true; +#ifdef _WIN32_WCE + // flags are ignored on Windows CE + if(MAPIInitialize(NULL) != S_OK) + return false; + CPOOM::Init(); +#else + if(!dwFlags) + dwFlags = MAPI_NO_COINIT | MAPI_MULTITHREAD_NOTIFICATIONS; + if(bInitAsService) + dwFlags |= MAPI_NT_SERVICE; + + MAPIINIT_0 MAPIInit = { MAPI_INIT_VERSION, dwFlags }; + if(MAPIInitialize(&MAPIInit) != S_OK) + return false; +#endif + return true; +} + +void MAPIEx::Term() { + MAPIUninitialize(); +#ifdef _WIN32_WCE + CPOOM::Term(); +#endif + if(cm_bComInit) + CoUninitialize(); +} + +// dwFlags set to defaults but added as a param here for special cases (ie MAPI_NO_MAIL) +bool MAPIEx::Login(const String szProfileName, DWORD dwFlags, bool bInitAsService) { + if(!dwFlags) + dwFlags = MAPI_EXTENDED | MAPI_USE_DEFAULT | MAPI_NEW_SESSION; + if(bInitAsService) + dwFlags |= MAPI_EXPLICIT_PROFILE | MAPI_NT_SERVICE; + return (MAPILogonEx(0, (LPTSTR)(szProfileName.Begin()), NULL, dwFlags, &m_pSession) == S_OK); +} + +void MAPIEx::Logout() { + if(m_sink) { + if(m_pMsgStore) + m_pMsgStore->Unadvise(m_sink); + m_sink = 0; + } + RELEASE(m_pMsgStore); + RELEASE(m_pSession); +} + +bool MAPIEx::CreateProfile(String szProfileName) { + LPPROFADMIN lpProfAdmin = NULL; + if(MAPIAdminProfiles(0, &lpProfAdmin) != S_OK) + return false; + HRESULT hr = lpProfAdmin->CreateProfile((LPTSTR)(szProfileName.Begin()), NULL, 0, 0); + RELEASE(lpProfAdmin); + return (hr == S_OK); +} + +bool MAPIEx::DeleteProfile(String szProfileName) { + LPPROFADMIN lpProfAdmin = NULL; + if(MAPIAdminProfiles(0, &lpProfAdmin) != S_OK) + return false; + HRESULT hr = lpProfAdmin->DeleteProfile((LPTSTR)(szProfileName.Begin()), 0); + RELEASE(lpProfAdmin); + return (hr == S_OK); +} + +bool MAPIEx::CreateMessageService(LPCTSTR szProfileName, LPCTSTR szService, LPCTSTR szDisplayName) { + bool bResult=FALSE; + LPPROFADMIN lpProfAdmin=NULL; + if(MAPIAdminProfiles(0, &lpProfAdmin) == S_OK) { + LPSERVICEADMIN lpMsgServiceAdmin=NULL; + if(lpProfAdmin->AdminServices((LPTSTR)szProfileName, NULL, 0, MAPI_DIALOG, + &lpMsgServiceAdmin) == S_OK) { + bResult = (lpMsgServiceAdmin->CreateMsgService((LPTSTR)szService, + (LPTSTR)szDisplayName, 0, SERVICE_UI_ALWAYS | SERVICE_UI_ALLOWED) == S_OK); + RELEASE(lpMsgServiceAdmin); + } + RELEASE(lpProfAdmin); + } + return bResult; +} + +String MAPIEx::GetProfileName() { + String strProfileName; +#ifndef _WIN32_WCE + if(!m_pSession) + return strProfileName; + + LPSRowSet pRows = NULL; + const int nProperties = 2; + SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME_A, PR_RESOURCE_TYPE}}; + + IMAPITable* pStatusTable; + if(m_pSession->GetStatusTable(0, &pStatusTable) == S_OK) { + if(pStatusTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { + while(pStatusTable->QueryRows(1, 0, &pRows) == S_OK) { + if(pRows->cRows != 1) + FreeProws(pRows); + else if(pRows->aRow[0].lpProps[1].Value.ul == MAPI_SUBSYSTEM) { + strProfileName = GetValidString(pRows->aRow[0].lpProps[0]); + FreeProws(pRows); + } else { + FreeProws(pRows); + continue; + } + break; + } + } + RELEASE(pStatusTable); + } +#endif + return FromSystemCharset(strProfileName); +} + +String MAPIEx::GetProfileEmail() { + String strProfileEmail; +#ifndef _WIN32_WCE + if(!m_pSession) + return strProfileEmail; + + SBinary entryID; + if(m_pSession->QueryIdentity(&entryID.cb, (LPENTRYID*)&entryID.lpb) == S_OK) { + GetExEmail(entryID, strProfileEmail); + return strProfileEmail; + } +#endif + return strProfileEmail; +} + +int MAPIEx::GetMessageStoreCount() { + IMAPITable* pMsgStoresTable; + if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { + ULONG ulCount; + HRESULT hr = pMsgStoresTable->GetRowCount(0, &ulCount); + RELEASE(pMsgStoresTable); + if(hr == S_OK) + return ulCount; + } + return -1; +} + +bool MAPIEx::GetMessageStoreProperties(int nIndex, String& strName, bool& bDefaultStore) { + bool bResult = FALSE; + IMAPITable *pMsgStoresTable; + if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { + LPSRowSet pRows = NULL; + const int nProperties = 3; + SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, + PR_DEFAULT_STORE}}; + + if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { + if(pMsgStoresTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { + if(pMsgStoresTable->QueryRows(1, 0, &pRows) == S_OK) { + if(pRows->cRows>0) { + strName = GetValidString(pRows->aRow[0].lpProps[0]); + bDefaultStore = pRows->aRow[0].lpProps[2].Value.b; + bResult = true; + } + FreeProws(pRows); + } + } + } + RELEASE(pMsgStoresTable); + } + return bResult; +} + +bool MAPIEx::OpenMessageStore(int nIndex, ULONG ulFlags) { + BOOL bResult = false; + IMAPITable* pMsgStoresTable; + if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { + LPSRowSet pRows = NULL; + const int nProperties = 3; + SizedSPropTagArray(nProperties, Columns)={nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, + PR_DEFAULT_STORE}}; + if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { + if(pMsgStoresTable->SeekRow(BOOKMARK_BEGINNING, nIndex, NULL) == S_OK) { + if(pMsgStoresTable->QueryRows(1, 0, &pRows)==S_OK) { + if(pRows->cRows>0) { + m_ulMDBFlags=ulFlags; + RELEASE(m_pMsgStore); + bResult = (m_pSession->OpenMsgStore(0, + pRows->aRow[0].lpProps[1].Value.bin.cb, + (ENTRYID*)pRows->aRow[0].lpProps[1].Value.bin.lpb, NULL, + MDB_NO_DIALOG | MAPI_BEST_ACCESS, &m_pMsgStore) == S_OK); + } + FreeProws(pRows); + } + } + } + RELEASE(pMsgStoresTable); + } + return bResult; +} + +// do not set MAPI_NO_CACHE flag for Outlook 97 and 2000 +bool MAPIEx::OpenMessageStore(String szStore, ULONG ulFlags) { + bool bResult = false; + IMAPITable* pMsgStoresTable; + if(m_pSession && m_pSession->GetMsgStoresTable(0, &pMsgStoresTable) == S_OK) { + LPSRowSet pRows = NULL; + const int nProperties = 3; + SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, + PR_DEFAULT_STORE}}; + if(pMsgStoresTable->SetColumns((LPSPropTagArray)&Columns, 0) == S_OK) { + while(pMsgStoresTable->QueryRows(1, 0, &pRows) == S_OK) { + if(pRows->cRows != 1) + FreeProws(pRows); + else { + if(szStore.IsEmpty()) { + if(pRows->aRow[0].lpProps[2].Value.b) + bResult = true; + } else { + String strStore = GetValidString(pRows->aRow[0].lpProps[0]); + if(strStore.Find(szStore) != -1) + bResult = true; + } + if(!bResult) { + FreeProws(pRows); + continue; + } + } + break; + } + if(bResult) { + m_ulMDBFlags = ulFlags; + RELEASE(m_pMsgStore); + bResult = (m_pSession->OpenMsgStore(0, pRows->aRow[0].lpProps[1].Value.bin.cb, + (ENTRYID*)pRows->aRow[0].lpProps[1].Value.bin.lpb, NULL, + MDB_NO_DIALOG | MAPI_BEST_ACCESS, &m_pMsgStore) == S_OK); + FreeProws(pRows); + } + } + RELEASE(pMsgStoresTable); + } + return bResult; +} + +ULONG MAPIEx::GetMessageStoreSupport() { + if(!m_pMsgStore) + return false; + + LPSPropValue props = NULL; + ULONG cValues = 0; + ULONG rgTags[] = {1, PR_STORE_SUPPORT_MASK}; + ULONG ulSupport = 0; + + if(m_pMsgStore->GetProps((LPSPropTagArray) rgTags, MAPIEx::cm_nMAPICode, &cValues, &props) + == S_OK) { + ulSupport = props->Value.ul; + MAPIFreeBuffer(props); + } + return ulSupport; +} + +#ifdef _WIN32_WCE +CPOOM* MAPIEx::GetPOOM() { + return m_pFolder ? m_pFolder->GetPOOM() : NULL; +} +#endif + +bool MAPIEx::OpenFolder(unsigned long ulFolderID, MAPIFolder& folder) { + if(!m_pMsgStore) + return NULL; + + LPSPropValue props = NULL; + ULONG cValues = 0; + DWORD dwObjType; + ULONG rgTags[] = { 1, ulFolderID }; + LPMAPIFOLDER pFolder; + + if(S_OK != m_pMsgStore->GetProps((LPSPropTagArray) rgTags, cm_nMAPICode, &cValues, &props)) + return false; + if(S_OK != m_pMsgStore->OpenEntry(props[0].Value.bin.cb, (LPENTRYID)props[0].Value.bin.lpb, + NULL, m_ulMDBFlags, &dwObjType, (LPUNKNOWN*)&pFolder)) + return false; + + MAPIFreeBuffer(props); + if(pFolder) { + folder.Attach(this, pFolder); + folder.GetHierarchy(); + folder.GetContents(); + return true; + } + return false; +} + +bool MAPIEx::OpenFolder(const String &folderName, MAPIFolder &folder, bool fullPath) { + MAPIFolder root; + if(!OpenRootFolder(root)) + return false; + if (!root.OpenSubFolder(folderName, folder, fullPath, "")) + return false; + folder.GetHierarchy(); + folder.GetContents(); + return true; +} + +bool MAPIEx::OpenSpecialFolder(unsigned long ulFolderID, MAPIFolder &folder) { +#ifdef _WIN32_WCE + if(pFolder->GetPOOM()->OpenFolder(ulFolderID, folder) != NULL) { + folder.GetContents(); + folder.GetHierarchy(); + return true; + } + return false; +#else + MAPIFolder inbox; + if(!OpenInbox(inbox) || !m_pMsgStore) + return false; + + LPSPropValue props = NULL; + ULONG cValues = 0; + DWORD dwObjType; + ULONG rgTags[] = { 1, ulFolderID }; + LPMAPIFOLDER pFolder; + + if(inbox.Folder()->GetProps((LPSPropTagArray) rgTags, cm_nMAPICode, &cValues, &props)!=S_OK) + return false; + HRESULT hr = m_pMsgStore->OpenEntry(props[0].Value.bin.cb, + (LPENTRYID)props[0].Value.bin.lpb, NULL, m_ulMDBFlags, &dwObjType, + (LPUNKNOWN*)&pFolder); + MAPIFreeBuffer(props); + if(hr != S_OK) + return false; + + if(pFolder) { + folder.Attach(this, pFolder); + folder.GetContents(); + folder.GetHierarchy(); + return true; + } + return false; +#endif +} + +bool MAPIEx::OpenRootFolder(MAPIFolder &folder) { + return OpenFolder(PR_IPM_SUBTREE_ENTRYID, folder); +} + +bool MAPIEx::OpenInbox(MAPIFolder &folder) { +#ifdef _WIN32_WCE + return OpenFolder(PR_CE_IPM_INBOX_ENTRYID, MAPIFolder folder); +#else + if(!m_pMsgStore) + return false; + + ULONG cbEntryID; + LPENTRYID pEntryID; + DWORD dwObjType; + LPMAPIFOLDER pFolder; + + if(m_pMsgStore->GetReceiveFolder(NULL, 0, &cbEntryID, &pEntryID, NULL) != S_OK) + return false; + HRESULT hr = m_pMsgStore->OpenEntry(cbEntryID, pEntryID, NULL, m_ulMDBFlags, &dwObjType, (LPUNKNOWN*)&pFolder); + MAPIFreeBuffer(pEntryID); + + if(hr == S_OK && pFolder) { + folder.Attach(this, pFolder); + folder.GetHierarchy(); + folder.GetContents(); + return true; + } + return false; +#endif +} + +bool MAPIEx::OpenOutbox(MAPIFolder &folder) { + return OpenFolder(PR_IPM_OUTBOX_ENTRYID, folder); +} + +bool MAPIEx::OpenSentItems(MAPIFolder &folder) { + return OpenFolder(PR_IPM_SENTMAIL_ENTRYID, folder); +} + +bool MAPIEx::OpenDeletedItems(MAPIFolder &folder) { + return OpenFolder(PR_IPM_WASTEBASKET_ENTRYID, folder); +} + +bool MAPIEx::OpenContacts(MAPIFolder &folder) { + return OpenSpecialFolder(PR_IPM_CONTACT_ENTRYID, folder); +} + +bool MAPIEx::OpenDrafts(MAPIFolder &folder) { +#ifdef _WIN32_WCE + return OpenFolder(PR_CE_IPM_DRAFTS_ENTRYID, folder); +#else + return OpenSpecialFolder(PR_IPM_DRAFTS_ENTRYID, folder); +#endif +} + +bool MAPIEx::OpenCalendar(MAPIFolder &folder) { + return OpenSpecialFolder(PR_IPM_APPOINTMENT_ENTRYID, folder); +} + +// call with ulEventMask set to ALL notifications ORed together, only one Advise Sink is used. +bool MAPIEx::Notify(LPNOTIFCALLBACK lpfnCallback, LPVOID lpvContext, ULONG ulEventMask) { + if(GetMessageStoreSupport()&STORE_NOTIFY_OK) { + if(m_sink) + m_pMsgStore->Unadvise(m_sink); + MAPISink* pAdviseSink = new MAPISink(lpfnCallback, lpvContext); + if(m_pMsgStore->Advise(0, NULL,ulEventMask, pAdviseSink, &m_sink) == S_OK) + return true; + delete pAdviseSink; + m_sink = 0; + } + return false; +} + +// pumps the message queue, use this when waiting for notifications +void MAPIEx::PumpMessages() { + MSG msg; + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +// sometimes the string in prop is invalid, causing unexpected crashes +#ifndef _WIN32_WCE +String MAPIEx::ValidateString(LPCTSTR s) { + if(s && !::IsBadStringPtr(s, (UINT_PTR)-1)) + return FromSystemCharset(s); + return Null; +} +#else +// Windows Mobile does not have IsBadStringPtr so I use SEH +// I shut off optimization because the optimizer still had trouble with the try/catch +#pragma optimize("",off) +String MAPIEx::ValidateString(String s) { + try { + if(s) { + TCHAR ch = *s; + return s; + } + } + catch(...) { + } + return Null; +} +#pragma optimize("",on) +#endif + +String MAPIEx::GetValidString(SPropValue& prop) { + return ValidateString(prop.Value.LPSZ); +} + +// sometimes the string in prop is invalid, causing unexpected crashes +String MAPIEx::GetValidMVString(SPropValue& prop, int nIndex) { + return ValidateString(prop.Value.MVSZ.LPPSZ[nIndex]); +} + +// special case of GetValidString to take the narrow string in UNICODE +void MAPIEx::GetNarrowString(SPropValue& prop, String& strNarrow) { + String s = GetValidString(prop); + if(s.IsEmpty()) + strNarrow = ""; + else + strNarrow = s; +} + +bool MAPIEx::SelectContacts(Vector &emails, const String caption) { + emails.Clear(); + LPADRLIST pAddressList; + if(ShowAddressBook(pAddressList, caption) == IDOK) { + String strEmail; + for(ULONG i = 0; i < pAddressList->cEntries; i++) { + if(GetEmail(pAddressList->aEntries[i], strEmail)) + emails.Add(strEmail); + } + MAPIEx::ReleaseAddressList(pAddressList); + } + return emails.GetCount() > 0; +} + +// Shows the default Address Book dialog, return false on failure, IDOK or IDCANCEL on success +// I force narrow strings here because it for some reason doesn't work in UNICODE +int MAPIEx::ShowAddressBook(LPADRLIST& pAddressList, const String caption) { +#ifndef _WIN32_WCE + if(!m_pSession) + return false; + + LPADRBOOK pAddressBook; + if(m_pSession->OpenAddressBook(0, NULL, 0, &pAddressBook) == S_OK) { + pAddressList = NULL; + + const char* lppszDestTitles[]={ "To" }; + ULONG lpulDestComps[] = { MAPI_TO }; + + ADRPARM adrparm; + memset(&adrparm, 0, sizeof(ADRPARM)); + adrparm.ulFlags = DIALOG_MODAL | AB_RESOLVE; + + adrparm.lpszCaption = (LPTSTR)(caption.Begin()); + + adrparm.cDestFields = 1; + adrparm.lppszDestTitles=(LPTSTR*)lppszDestTitles; + adrparm.lpulDestComps=lpulDestComps; + + HWND hDesktop = ::GetDesktopWindow(); + HRESULT hr = pAddressBook->Address((ULONG_PTR*)&hDesktop, &adrparm, &pAddressList); + RELEASE(pAddressBook); + if(hr == S_OK) + return IDOK; + if(hr == MAPI_E_USER_CANCEL) + return IDCANCEL; + } +#endif + return false; +} + +// utility function to release ADRLIST entries +void MAPIEx::ReleaseAddressList(LPADRLIST pAddressList) { +#ifndef _WIN32_WCE + FreePadrlist(pAddressList); +#else + if(pAddressList) { + for(ULONG i = 0; i < pAddressList->cEntries; i++) + MAPIFreeBuffer(pAddressList->aEntries[i].rgPropVals); + MAPIFreeBuffer(pAddressList); + } +#endif +} + +bool MAPIEx::CompareEntryIDs(ULONG cb1, LPENTRYID lpb1, ULONG cb2, LPENTRYID lpb2) { + ULONG ulResult; + if(m_pSession && m_pSession->CompareEntryIDs(cb1, lpb1, cb2, lpb2, 0, &ulResult) == S_OK) + return ulResult; + return false; +} + +// ADDRENTRY objects from Address don't come in unicode so I check for _A and force narrow strings +bool MAPIEx::GetEmail(ADRENTRY& adrEntry, String& strEmail) { +#ifndef _WIN32_WCE + LPSPropValue pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE); + if(!pProp) + pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE_A); + if(pProp) { + String strAddrType; + GetNarrowString(*pProp, strAddrType); + if(strAddrType == "EX") { + pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ENTRYID); + + SBinary entryID; + entryID.cb = pProp->Value.bin.cb; + entryID.lpb = pProp->Value.bin.lpb; + + return GetExEmail(entryID, strEmail); + } + } + pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS); + if(!pProp) + pProp = PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS_A); + if(pProp) { + GetNarrowString(*pProp, strEmail); + return true; + } +#endif + return false; +} + +bool MAPIEx::GetExEmail(SBinary entryID, String& strEmail) { + bool bResult = false; +#ifndef _WIN32_WCE + if(!m_pSession) + return false; + + LPADRBOOK pAddressBook; + if(m_pSession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook) != S_OK) + return false; + ULONG ulObjType; + IMAPIProp* pItem = NULL; + if(pAddressBook->OpenEntry(entryID.cb, (ENTRYID*)entryID.lpb, NULL,MAPI_BEST_ACCESS, + &ulObjType, (LPUNKNOWN*)&pItem) == S_OK) { + if(ulObjType == MAPI_MAILUSER) { + LPSPropValue pProp; + ULONG ulPropCount; + ULONG pSMTP[] = { 1, PR_SMTP_ADDRESS }; + ULONG pEmail[] = { 1, PR_EMAIL_ADDRESS }; + + if(pItem->GetProps((LPSPropTagArray)pSMTP, MAPIEx::cm_nMAPICode, &ulPropCount, + &pProp)==S_OK) { + strEmail=MAPIEx::GetValidString(*pProp); + MAPIFreeBuffer(pProp); + bResult = true; + } + if(!bResult && pItem->GetProps((LPSPropTagArray)pEmail, MAPIEx::cm_nMAPICode, + &ulPropCount, &pProp) == S_OK) { + strEmail=MAPIEx::GetValidString(*pProp); + MAPIFreeBuffer(pProp); + bResult = true; + } + } + RELEASE(pItem); + } + RELEASE(pAddressBook); +#endif + return bResult; +} + +void MAPIEx::SetSystemTime(SYSTEMTIME& tm, int wYear, int wMonth, int wDay, int wHour, + int wMinute, int wSecond, int wMilliSeconds) { + tm.wYear = (WORD)wYear; + tm.wMonth = (WORD)wMonth; + tm.wDay = (WORD)wDay; + tm.wHour = (WORD)wHour; + tm.wMinute = (WORD)wMinute; + tm.wSecond = (WORD)wSecond; + tm.wMilliseconds= (WORD)wMilliSeconds; + tm.wDayOfWeek = 0; +} + +void MAPIEx::SetSystemTime(SYSTEMTIME& tm, const Time &t) { + tm.wYear = t.year; + tm.wMonth = t.month; + tm.wDay = t.day; + tm.wHour = t.hour; + tm.wMinute = t.minute; + tm.wSecond = t.second; + tm.wMilliseconds = 0; + tm.wDayOfWeek = 0; +} + +Time MAPIEx::GetSystemTime(SYSTEMTIME& tm) { + return Time(tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond); +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIEx.h b/bazaar/MAPIEx/MAPIEx.h index 77797918d..4d06cb0a0 100644 --- a/bazaar/MAPIEx/MAPIEx.h +++ b/bazaar/MAPIEx/MAPIEx.h @@ -4,7 +4,7 @@ #include using namespace Upp; - +#undef CY #define CY tagCY @@ -118,6 +118,7 @@ protected: ULONG GetMessageStoreSupport(); bool OpenFolder(unsigned long ulFolderID, MAPIFolder &folder); +public: //////// static String ValidateString(LPCTSTR s); IMAPISession* GetSession() {return m_pSession;} LPMDB GetMessageStore() {return m_pMsgStore;} diff --git a/bazaar/MAPIEx/MAPIEx.upp b/bazaar/MAPIEx/MAPIEx.upp index 8bff47c6e..ce8057e0b 100644 --- a/bazaar/MAPIEx/MAPIEx.upp +++ b/bazaar/MAPIEx/MAPIEx.upp @@ -4,7 +4,7 @@ uses Core, Functions4U; -library(GCC) "mapi32 kernel32"; +library(GCC WIN32) "mapi32 kernel32"; file MAPIAppointment.cpp, diff --git a/bazaar/MAPIEx/MAPIFolder.cpp b/bazaar/MAPIEx/MAPIFolder.cpp index 0ea512f6a..42ee68f33 100644 --- a/bazaar/MAPIEx/MAPIFolder.cpp +++ b/bazaar/MAPIEx/MAPIFolder.cpp @@ -1,321 +1,325 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// File: MAPIFolder.cpp -// Description: MAPI Folder class wrapper -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Ported to U++ Framework by Koldo. See License.txt file - -#include -#include "MAPIEx.h" - -///////////////////////////////////////////////////////////// -// MAPIFolder - -MAPIFolder::MAPIFolder() { - Init(); -} - -MAPIFolder::MAPIFolder(MAPIEx* pMAPI, LPMAPIFOLDER pFolder, String szName) { - Init(); - - m_entryID.cb=0; - Attach(pMAPI, pFolder, szName); -} - -MAPIFolder::~MAPIFolder() { - Close(); -} - -void MAPIFolder::Init() { - m_pHierarchy = NULL; - m_pContents = NULL; - m_nMaxRowsSize = DEFAULT_FOLDER_BUFFER_SIZE; - m_pRows = NULL; - ClearBuffer(); -} - -void MAPIFolder::Close() { - ClearBuffer(); - RELEASE(m_pHierarchy); - RELEASE(m_pContents); - MAPIObject::Close(); -} - -void MAPIFolder::SetBufferSize(int nSize) { - m_nMaxRowsSize = max(1, nSize); -} - -void MAPIFolder::ClearBuffer() { - if(m_pRows) { - FreeProws(m_pRows); - m_pRows = NULL; - } - m_nRowsIndex = 0; -} - -bool MAPIFolder::Attach(MAPIEx* pMAPI, LPMAPIFOLDER pFolder, String szName) { - Close(); - m_pMAPI = pMAPI; - m_pItem = pFolder; - m_strName = szName; - LPSPropValue pProp; - if(GetProperty(PR_ENTRYID, pProp) == S_OK) { - SetEntryID(&pProp->Value.bin); - MAPIFreeBuffer(pProp); - return true; - } else { - SetEntryID(NULL); - return false; - } -} - -LPMAPIFOLDER MAPIFolder::Detach() { - LPMAPIFOLDER pFolder = Folder(); - m_pItem = NULL; - return pFolder; -} - -String MAPIFolder::GetName() { - return m_strName; -} - -LPMAPITABLE MAPIFolder::GetHierarchy() { - RELEASE(m_pHierarchy); - if(Folder()->GetHierarchyTable(0, &m_pHierarchy) != S_OK) - return NULL; - - const int nProperties = 2; - SizedSPropTagArray(nProperties, Columns)={nProperties,{PR_DISPLAY_NAME, PR_ENTRYID}}; - if(m_pHierarchy->SetColumns((LPSPropTagArray)&Columns, 0) != S_OK) { - RELEASE(m_pHierarchy); - return NULL; - } - return m_pHierarchy; -} - -// High Level function to open a sub folder by iterating recursively (DFS) over all folders -bool MAPIFolder::OpenSubFolder(const String &subFolderName, MAPIFolder &subFolder, - bool fullPath, String path) { - if(!GetHierarchy()) - return NULL; - - String strFolder; - MAPIFolder folder; - MAPIFolder* pSubFolder = NULL; - while(GetNextSubFolder(folder, strFolder)) { - bool retSubFolder; - if (fullPath) - strFolder = path + "/" + strFolder; - if(!CompareNoCase(strFolder, subFolderName)) - retSubFolder = subFolder.Attach(m_pMAPI, folder.Detach()); - else - retSubFolder = folder.OpenSubFolder(subFolderName, subFolder, fullPath, strFolder); - if(retSubFolder) - return true; - } - return false; -} - -// Creates a sub-folder under pFolder, opens the folder if it already exists -bool MAPIFolder::CreateSubFolder(const String &subFolderName, MAPIFolder &subFolder) { - LPMAPIFOLDER pSubFolder = NULL; - ULONG ulFolderType=FOLDER_GENERIC; - ULONG ulFlags=OPEN_IF_EXISTS | MAPIEx::cm_nMAPICode; - - Folder()->CreateFolder(ulFolderType, (LPTSTR)(subFolderName.Begin()), NULL, NULL, ulFlags, - &pSubFolder); - subFolder.Attach(m_pMAPI, pSubFolder); - return pSubFolder; -} - -// Deletes a sub-folder and ALL sub folders/messages -bool MAPIFolder::DeleteSubFolder(const String &subFolderName) { - if(GetHierarchy()) { - String strFolder; - MAPIFolder folder; - while(GetNextSubFolder(folder, strFolder)) { - if(!CompareNoCase(strFolder, subFolderName)) - return DeleteSubFolder(folder); - } - } - return false; -} - -// Deletes a sub-folder and ALL sub folders/messages -bool MAPIFolder::DeleteSubFolder(MAPIFolder &subFolder) { - if(!subFolder.IsOpened()) - return false; - - LPSPropValue props = NULL; - ULONG cValues=0; - ULONG rgTags[]={ 1, PR_ENTRYID }; - - if(subFolder.Folder()->GetProps((LPSPropTagArray) rgTags, MAPIEx::cm_nMAPICode, - &cValues, &props) == S_OK) { - HRESULT hr = Folder()->DeleteFolder(props[0].Value.bin.cb, - (LPENTRYID)props[0].Value.bin.lpb, 0, NULL,DEL_FOLDERS|DEL_MESSAGES); - MAPIFreeBuffer(props); - return (hr == S_OK); - } - return false; -} - -LPMAPITABLE MAPIFolder::GetContents() { - RELEASE(m_pContents); - if(Folder()->GetContentsTable(MAPIEx::cm_nMAPICode, &m_pContents)!=S_OK) - return NULL; - - const int nProperties = MESSAGE_COLS; - SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_MESSAGE_FLAGS, PR_ENTRYID }}; - if(m_pContents->SetColumns((LPSPropTagArray)&Columns, 0)!=S_OK) { - RELEASE(m_pContents); - return NULL; - } - return m_pContents; -} - -int MAPIFolder::GetCount() { - ULONG ulCount; - if(!m_pContents || m_pContents->GetRowCount(0, &ulCount) != S_OK) - return -1; - return ulCount; -} - -bool MAPIFolder::SortContents(ULONG ulSortParam, ULONG ulSortField) { - if(!m_pContents) - return false; - - SizedSSortOrderSet(1, SortColums) = {1, 0, 0, {{ulSortField, ulSortParam}}}; - return (m_pContents->SortTable((LPSSortOrderSet)&SortColums, 0) == S_OK); -} - -bool MAPIFolder::SetUnreadOnly(bool bUnreadOnly) { - if(bUnreadOnly) { - SRestriction res; - res.rt = RES_BITMASK; - res.res.resBitMask.relBMR = BMR_EQZ; - res.res.resBitMask.ulPropTag = PR_MESSAGE_FLAGS; - res.res.resBitMask.ulMask = MSGFLAG_READ; - return SetRestriction(&res); - } - return SetRestriction(NULL); -} - -bool MAPIFolder::SetRestriction(SRestriction* pRestriction) { - return (m_pContents && m_pContents->Restrict(pRestriction, 0)==S_OK); -} - -bool MAPIFolder::QueryRows() { - ClearBuffer(); - if(m_pContents) { - if(m_pContents->QueryRows(m_nMaxRowsSize, 0, &m_pRows) == S_OK) { - return true; - } - m_pRows = NULL; - } - return false; -} - -SRow* MAPIFolder::GetNextRow() { - if(m_pRows == NULL || m_nRowsIndex >= m_pRows->cRows) { - if(!QueryRows()) - return NULL; - } - if(m_pRows->cRows==0) { - ClearBuffer(); - return NULL; - } - return &m_pRows->aRow[m_nRowsIndex++]; -} - -bool MAPIFolder::GetNextMessage(MAPIMessage& message) { - SRow* pRow = GetNextRow(); - return pRow ? message.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; -} - -bool MAPIFolder::GetNextContact(MAPIContact& contact) { -#ifdef _WIN32_WCE - return m_poom.GetNextContact(m_pMAPI, contact); -#else - SRow* pRow = GetNextRow(); - return pRow ? contact.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; -#endif -} - -bool MAPIFolder::GetNextAppointment(MAPIAppointment& appointment) { -#ifdef _WIN32_WCE - return m_poom.GetNextAppointment(m_pMAPI,appointment); -#else - SRow* pRow=GetNextRow(); - return pRow ? appointment.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; -#endif -} - -bool MAPIFolder::GetNextSubFolder(MAPIFolder& folder, String& strFolder) { - if(!m_pHierarchy) - return NULL; - folder.Close(); - - DWORD dwObjType; - LPSRowSet pRows = NULL; - - LPMAPIFOLDER pSubFolder = NULL; - if(m_pHierarchy->QueryRows(1, 0, &pRows) == S_OK) { - if(pRows->cRows) { - if(S_OK == Folder()->OpenEntry(pRows->aRow[0].lpProps[PROP_ENTRYID].Value.bin.cb, - (LPENTRYID)pRows->aRow[0].lpProps[PROP_ENTRYID].Value.bin.lpb, - NULL, MAPI_MODIFY, &dwObjType, (LPUNKNOWN*)&pSubFolder)) { - strFolder = MAPIEx::GetValidString(pRows->aRow[0].lpProps[0]); - folder.Attach(m_pMAPI, pSubFolder, strFolder); - } - } - FreeProws(pRows); - } - if (!pSubFolder) - return false; - folder.GetHierarchy(); - folder.GetContents(); - return true; -} - -bool MAPIFolder::DeleteMessage(MAPIMessage& message) { - return DeleteObject(message); -} - -bool MAPIFolder::CopyMessage(MAPIMessage& message, MAPIFolder &folderDest) { - ENTRYLIST entries = { 1, message.GetEntryID() }; - HRESULT hr = Folder()->CopyMessages(&entries, NULL, folderDest.Folder(), 0, NULL, 0); - return (hr == S_OK); -} - -bool MAPIFolder::MoveMessage(MAPIMessage& message, MAPIFolder &folderDest) { - if(!folderDest.IsOpened()) - return false; - - ENTRYLIST entries = { 1, message.GetEntryID() }; - HRESULT hr = Folder()->CopyMessages(&entries, NULL, folderDest.Folder(), 0, NULL,MESSAGE_MOVE); - return (hr == S_OK); -} - -bool MAPIFolder::DeleteContact(MAPIContact& contact) { - return DeleteObject(contact); -} - -bool MAPIFolder::DeleteAppointment(MAPIAppointment& appointment) { - return DeleteObject(appointment); -} - -bool MAPIFolder::DeleteObject(MAPIObject& object) { - ENTRYLIST entries={ 1, object.GetEntryID() }; - HRESULT hr = Folder()->DeleteMessages(&entries, 0, NULL, 0); - return (hr==S_OK); -} +#ifdef _WIN32 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// File: MAPIFolder.cpp +// Description: MAPI Folder class wrapper +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Ported to U++ Framework by Koldo. See License.txt file + +#include "MAPIEx.h" +#include "MapiUtil.h" + +///////////////////////////////////////////////////////////// +// MAPIFolder + +MAPIFolder::MAPIFolder() { + Init(); +} + +MAPIFolder::MAPIFolder(MAPIEx* pMAPI, LPMAPIFOLDER pFolder, String szName) { + Init(); + + m_entryID.cb=0; + Attach(pMAPI, pFolder, szName); +} + +MAPIFolder::~MAPIFolder() { + Close(); +} + +void MAPIFolder::Init() { + m_pHierarchy = NULL; + m_pContents = NULL; + m_nMaxRowsSize = DEFAULT_FOLDER_BUFFER_SIZE; + m_pRows = NULL; + ClearBuffer(); +} + +void MAPIFolder::Close() { + ClearBuffer(); + RELEASE(m_pHierarchy); + RELEASE(m_pContents); + MAPIObject::Close(); +} + +void MAPIFolder::SetBufferSize(int nSize) { + m_nMaxRowsSize = max(1, nSize); +} + +void MAPIFolder::ClearBuffer() { + if(m_pRows) { + FreeProws(m_pRows); + m_pRows = NULL; + } + m_nRowsIndex = 0; +} + +bool MAPIFolder::Attach(MAPIEx* pMAPI, LPMAPIFOLDER pFolder, String szName) { + Close(); + m_pMAPI = pMAPI; + m_pItem = pFolder; + m_strName = szName; + LPSPropValue pProp; + if(GetProperty(PR_ENTRYID, pProp) == S_OK) { + SetEntryID(&pProp->Value.bin); + MAPIFreeBuffer(pProp); + return true; + } else { + SetEntryID(NULL); + return false; + } +} + +LPMAPIFOLDER MAPIFolder::Detach() { + LPMAPIFOLDER pFolder = Folder(); + m_pItem = NULL; + return pFolder; +} + +String MAPIFolder::GetName() { + return m_strName; +} + +LPMAPITABLE MAPIFolder::GetHierarchy() { + RELEASE(m_pHierarchy); + if(Folder()->GetHierarchyTable(0, &m_pHierarchy) != S_OK) + return NULL; + + const int nProperties = 2; + SizedSPropTagArray(nProperties, Columns)={nProperties,{PR_DISPLAY_NAME, PR_ENTRYID}}; + if(m_pHierarchy->SetColumns((LPSPropTagArray)&Columns, 0) != S_OK) { + RELEASE(m_pHierarchy); + return NULL; + } + return m_pHierarchy; +} + +// High Level function to open a sub folder by iterating recursively (DFS) over all folders +bool MAPIFolder::OpenSubFolder(const String &subFolderName, MAPIFolder &subFolder, + bool fullPath, String path) { + if(!GetHierarchy()) + return NULL; + + String strFolder; + MAPIFolder folder; + MAPIFolder* pSubFolder = NULL; + while(GetNextSubFolder(folder, strFolder)) { + bool retSubFolder; + if (fullPath) + strFolder = path + "/" + strFolder; + if(!CompareNoCase(strFolder, subFolderName)) + retSubFolder = subFolder.Attach(m_pMAPI, folder.Detach()); + else + retSubFolder = folder.OpenSubFolder(subFolderName, subFolder, fullPath, strFolder); + if(retSubFolder) + return true; + } + return false; +} + +// Creates a sub-folder under pFolder, opens the folder if it already exists +bool MAPIFolder::CreateSubFolder(const String &subFolderName, MAPIFolder &subFolder) { + LPMAPIFOLDER pSubFolder = NULL; + ULONG ulFolderType=FOLDER_GENERIC; + ULONG ulFlags=OPEN_IF_EXISTS | MAPIEx::cm_nMAPICode; + + Folder()->CreateFolder(ulFolderType, (LPTSTR)(subFolderName.Begin()), NULL, NULL, ulFlags, + &pSubFolder); + subFolder.Attach(m_pMAPI, pSubFolder); + return pSubFolder; +} + +// Deletes a sub-folder and ALL sub folders/messages +bool MAPIFolder::DeleteSubFolder(const String &subFolderName) { + if(GetHierarchy()) { + String strFolder; + MAPIFolder folder; + while(GetNextSubFolder(folder, strFolder)) { + if(!CompareNoCase(strFolder, subFolderName)) + return DeleteSubFolder(folder); + } + } + return false; +} + +// Deletes a sub-folder and ALL sub folders/messages +bool MAPIFolder::DeleteSubFolder(MAPIFolder &subFolder) { + if(!subFolder.IsOpened()) + return false; + + LPSPropValue props = NULL; + ULONG cValues=0; + ULONG rgTags[]={ 1, PR_ENTRYID }; + + if(subFolder.Folder()->GetProps((LPSPropTagArray) rgTags, MAPIEx::cm_nMAPICode, + &cValues, &props) == S_OK) { + HRESULT hr = Folder()->DeleteFolder(props[0].Value.bin.cb, + (LPENTRYID)props[0].Value.bin.lpb, 0, NULL,DEL_FOLDERS|DEL_MESSAGES); + MAPIFreeBuffer(props); + return (hr == S_OK); + } + return false; +} + +LPMAPITABLE MAPIFolder::GetContents() { + RELEASE(m_pContents); + if(Folder()->GetContentsTable(MAPIEx::cm_nMAPICode, &m_pContents)!=S_OK) + return NULL; + + const int nProperties = MESSAGE_COLS; + SizedSPropTagArray(nProperties, Columns) = {nProperties,{PR_MESSAGE_FLAGS, PR_ENTRYID }}; + if(m_pContents->SetColumns((LPSPropTagArray)&Columns, 0)!=S_OK) { + RELEASE(m_pContents); + return NULL; + } + return m_pContents; +} + +int MAPIFolder::GetCount() { + ULONG ulCount; + if(!m_pContents || m_pContents->GetRowCount(0, &ulCount) != S_OK) + return -1; + return ulCount; +} + +bool MAPIFolder::SortContents(ULONG ulSortParam, ULONG ulSortField) { + if(!m_pContents) + return false; + + SizedSSortOrderSet(1, SortColums) = {1, 0, 0, {{ulSortField, ulSortParam}}}; + return (m_pContents->SortTable((LPSSortOrderSet)&SortColums, 0) == S_OK); +} + +bool MAPIFolder::SetUnreadOnly(bool bUnreadOnly) { + if(bUnreadOnly) { + SRestriction res; + res.rt = RES_BITMASK; + res.res.resBitMask.relBMR = BMR_EQZ; + res.res.resBitMask.ulPropTag = PR_MESSAGE_FLAGS; + res.res.resBitMask.ulMask = MSGFLAG_READ; + return SetRestriction(&res); + } + return SetRestriction(NULL); +} + +bool MAPIFolder::SetRestriction(SRestriction* pRestriction) { + return (m_pContents && m_pContents->Restrict(pRestriction, 0)==S_OK); +} + +bool MAPIFolder::QueryRows() { + ClearBuffer(); + if(m_pContents) { + if(m_pContents->QueryRows(m_nMaxRowsSize, 0, &m_pRows) == S_OK) { + return true; + } + m_pRows = NULL; + } + return false; +} + +SRow* MAPIFolder::GetNextRow() { + if(m_pRows == NULL || m_nRowsIndex >= m_pRows->cRows) { + if(!QueryRows()) + return NULL; + } + if(m_pRows->cRows==0) { + ClearBuffer(); + return NULL; + } + return &m_pRows->aRow[m_nRowsIndex++]; +} + +bool MAPIFolder::GetNextMessage(MAPIMessage& message) { + SRow* pRow = GetNextRow(); + return pRow ? message.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; +} + +bool MAPIFolder::GetNextContact(MAPIContact& contact) { +#ifdef _WIN32_WCE + return m_poom.GetNextContact(m_pMAPI, contact); +#else + SRow* pRow = GetNextRow(); + return pRow ? contact.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; +#endif +} + +bool MAPIFolder::GetNextAppointment(MAPIAppointment& appointment) { +#ifdef _WIN32_WCE + return m_poom.GetNextAppointment(m_pMAPI,appointment); +#else + SRow* pRow = GetNextRow(); + return pRow ? appointment.Open(m_pMAPI, pRow->lpProps[PROP_ENTRYID].Value.bin) : false; +#endif +} + +bool MAPIFolder::GetNextSubFolder(MAPIFolder& folder, String& strFolder) { + if(!m_pHierarchy) + return NULL; + folder.Close(); + + DWORD dwObjType; + LPSRowSet pRows = NULL; + + LPMAPIFOLDER pSubFolder = NULL; + if(m_pHierarchy->QueryRows(1, 0, &pRows) == S_OK) { + if(pRows->cRows) { + if(S_OK == Folder()->OpenEntry(pRows->aRow[0].lpProps[PROP_ENTRYID].Value.bin.cb, + (LPENTRYID)pRows->aRow[0].lpProps[PROP_ENTRYID].Value.bin.lpb, + NULL, MAPI_MODIFY, &dwObjType, (LPUNKNOWN*)&pSubFolder)) { + strFolder = MAPIEx::GetValidString(pRows->aRow[0].lpProps[0]); + folder.Attach(m_pMAPI, pSubFolder, strFolder); + } + } + FreeProws(pRows); + } + if (!pSubFolder) + return false; + folder.GetHierarchy(); + folder.GetContents(); + return true; +} + +bool MAPIFolder::DeleteMessage(MAPIMessage& message) { + return DeleteObject(message); +} + +bool MAPIFolder::CopyMessage(MAPIMessage& message, MAPIFolder &folderDest) { + ENTRYLIST entries = { 1, message.GetEntryID() }; + HRESULT hr = Folder()->CopyMessages(&entries, NULL, folderDest.Folder(), 0, NULL, 0); + return (hr == S_OK); +} + +bool MAPIFolder::MoveMessage(MAPIMessage& message, MAPIFolder &folderDest) { + if(!folderDest.IsOpened()) + return false; + + ENTRYLIST entries = { 1, message.GetEntryID() }; + HRESULT hr = Folder()->CopyMessages(&entries, NULL, folderDest.Folder(), 0, NULL,MESSAGE_MOVE); + return (hr == S_OK); +} + +bool MAPIFolder::DeleteContact(MAPIContact& contact) { + return DeleteObject(contact); +} + +bool MAPIFolder::DeleteAppointment(MAPIAppointment& appointment) { + return DeleteObject(appointment); +} + +bool MAPIFolder::DeleteObject(MAPIObject& object) { + ENTRYLIST entries={ 1, object.GetEntryID() }; + HRESULT hr = Folder()->DeleteMessages(&entries, 0, NULL, 0); + return (hr==S_OK); +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIMessage.cpp b/bazaar/MAPIEx/MAPIMessage.cpp index 9e430582e..b28cf71d3 100644 --- a/bazaar/MAPIEx/MAPIMessage.cpp +++ b/bazaar/MAPIEx/MAPIMessage.cpp @@ -1,3 +1,5 @@ +#ifdef _WIN32 + //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // File: MAPIMessage.cpp @@ -12,8 +14,10 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include +// Ported to U++ Framework by Koldo. See License.txt file + #include "MAPIEx.h" +#include "MapiUtil.h" #include const GUID CLSID_MailMessage={ 0x00020D0B, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; @@ -25,8 +29,10 @@ const GUID CLSID_MailMessage={ 0x00020D0B, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x0 #include #endif +extern "C" { + STDAPI_(void) CloseIMsgSession(LPMSGSESS lpMsgSess); +} -// Ported to U++ Framework by Koldo. See License.txt file ///////////////////////////////////////////////////////////// // MAPIMessage @@ -486,4 +492,6 @@ bool MAPIMessage::SaveToFile(const String &fileName) { RELEASE(pStorage); return true; #endif -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPIObject.cpp b/bazaar/MAPIEx/MAPIObject.cpp index 7560d9f3b..1bf3254f2 100644 --- a/bazaar/MAPIEx/MAPIObject.cpp +++ b/bazaar/MAPIEx/MAPIObject.cpp @@ -1,743 +1,748 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Ported to U++ Framework by Koldo. See License.txt file - -#include -#include "MAPIEx.h" - -///////////////////////////////////////////////////////////// -// MAPIObject - -MAPIObject::MAPIObject() { - m_pMAPI = NULL; - m_pItem = NULL; - m_entryID.cb = 0; - SetEntryID(NULL); -} - -MAPIObject::~MAPIObject() { -} - -String MAPIObject::GetHexString(SBinary bin) { - String strHex; - if(bin.cb) { - for(ULONG i = 0; i < bin.cb; i++) - strHex += Format("%02X", bin.lpb[i]); - return strHex; - } - return String(); -} - -String MAPIObject::GetEntryIDString() { - return GetHexString(m_entryID); -} - -void MAPIObject::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 MAPIObject::Open(MAPIEx* pMAPI, SBinary entryID) { - Close(); - m_pMAPI = pMAPI; - ULONG ulObjType; - if(S_OK != m_pMAPI->GetSession()->OpenEntry(entryID.cb, (LPENTRYID)entryID.lpb, NULL, - MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN*)&m_pItem)) - return false; - SetEntryID(&entryID); - return true; -} - -void MAPIObject::Close() { - SetEntryID(NULL); - RELEASE(m_pItem); - m_pMAPI = NULL; -} - -bool MAPIObject::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 MAPIObject::GetMessageFlags() { - return GetPropertyValue(PR_MESSAGE_FLAGS, 0); -} - -bool MAPIObject::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 MAPIObject::GetSensitivity() { - return GetPropertyValue(PR_SENSITIVITY, -1); -} - -bool MAPIObject::SetSensitivity(int nSensitivity) { - SPropValue prop; - prop.ulPropTag = PR_SENSITIVITY; - prop.Value.l = nSensitivity; - return (Message()->SetProps(1, &prop, NULL) == S_OK); -} - -int MAPIObject::GetImportance() { - return GetPropertyValue(PR_IMPORTANCE, IMPORTANCE_NORMAL); -} - -bool MAPIObject::SetImportance(int nImportance) { - SPropValue prop; - prop.ulPropTag = PR_IMPORTANCE; - prop.Value.l = nImportance; - return (Message()->SetProps(1, &prop, NULL) == S_OK); -} - -String MAPIObject::GetMessageClass() { - return GetPropertyString(PR_MESSAGE_CLASS); -} - -bool MAPIObject::SetMessageClass(String szMessageClass) { - SPropValue prop; - prop.ulPropTag = PR_MESSAGE_CLASS; - prop.Value.LPSZ = (LPSTR)szMessageClass.Begin(); - return (Message()->SetProps(1, &prop, NULL) == S_OK); -} - -int MAPIObject::GetMessageEditorFormat() { - return GetPropertyValue(PR_MSG_EDITOR_FORMAT, EDITOR_FORMAT_DONTKNOW); -} - -bool MAPIObject::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 MAPIObject::Create(MAPIEx &mapi, MAPIFolder &folder) { - if(!folder.IsOpened()) - return false; - Close(); - m_pMAPI = &mapi; - if(folder.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 MAPIObject::GetProperty(ULONG ulProperty, LPSPropValue& pProp) { - if(!m_pItem) - return E_INVALIDARG; - ULONG ulPropCount; - ULONG p[2] = {1, ulProperty}; - return m_pItem->GetProps((LPSPropTagArray)p, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); -} - -String MAPIObject::GetPropertyString(ULONG ulProperty, bool bStream) { - String strProperty; - if(bStream) { - IStream* pStream; - if(Message()->OpenProperty(ulProperty, &IID_IStream,STGM_READ, 0, (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 strProperty; - } - } else { - if (ulProperty == PR_ENTRYID) - return GetEntryIDString(); - LPSPropValue pProp; - if(GetProperty(ulProperty, pProp) == S_OK) { - strProperty = MAPIEx::GetValidString(*pProp); - MAPIFreeBuffer(pProp); - return strProperty; - } - } - return String(); -} - -int MAPIObject::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 MAPIObject::GetPropTagArray(LPCTSTR szFieldName, LPSPropTagArray& lppPropTags, int& nFieldType, bool bCreate) { - if(!m_pItem) - return false; - - MAPINAMEID nameID; - nameID.lpguid = (GUID*)&GUIDPublicStrings; - nameID.ulKind = MNID_STRING; - - nFieldType = PT_STRING8; - WCHAR wszFieldName[256]; - MultiByteToWideChar(CP_ACP, 0, szFieldName,-1,wszFieldName,255); - nameID.Kind.lpwstrName = wszFieldName; - - LPMAPINAMEID lpNameID[1] = {&nameID}; - - HRESULT hr = m_pItem->GetIDsFromNames(1, lpNameID, bCreate ? MAPI_CREATE : 0, &lppPropTags); - return (hr == S_OK); -} - -bool MAPIObject::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, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); - MAPIFreeBuffer(lppPropTags); - return (hr == S_OK); -} - -bool MAPIObject::GetNamedProperty(LPCTSTR szFieldName, String& strField) { - LPSPropValue pProp; - if(GetNamedProperty(szFieldName, pProp)) { - strField = MAPIEx::GetValidString(*pProp); - MAPIFreeBuffer(pProp); - return true; - } - return false; -} - -bool MAPIObject::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; - - nFieldType = PT_STRING8; - - 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 MAPIObject::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, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); - MAPIFreeBuffer(lppPropTags); - return (hr == S_OK); -} - -// gets a custom outlook property value -bool MAPIObject::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 MAPIObject::GetOutlookPropertyString(ULONG ulData, ULONG ulProperty, String& strProperty) { - LPSPropValue pProp; - if(GetOutlookProperty(ulData, ulProperty, pProp)) { - strProperty = MAPIEx::GetValidString(*pProp); - MAPIFreeBuffer(pProp); - return true; - } - return false; -} - -bool MAPIObject::SetPropertyString(ULONG ulProperty, String szProperty, bool bStream) { - if(m_pItem && !IsNull(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, (szProperty.ToWString().GetCount()+1)*sizeof(wchar), - NULL); - RELEASE(pStream); - return true; - } - } else { - SPropValue prop; - prop.ulPropTag = ulProperty; - prop.Value.LPSZ = (LPTSTR)szProperty.Begin(); - return (m_pItem->SetProps(1, &prop, NULL) == S_OK); - } - } - return false; -} - -bool MAPIObject::SetPropertyValue(ULONG ulProperty, int nValue) { - if(!m_pItem) - return false; - SPropValue prop; - prop.ulPropTag = ulProperty; - prop.Value.l = nValue; - return (m_pItem->SetProps(1, &prop, NULL) == S_OK); -} - -// if bCreate is true, the property will be created if necessary otherwise if not present will return false -bool MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::GetAttachmentCount() { - ULONG ulCount = 0; - LPSPropValue pProp; - if(GetProperty(PR_HASATTACH, pProp) == S_OK) { - if(pProp->Value.b) { - LPMAPITABLE pAttachTable=NULL; - 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); - } - } - MAPIFreeBuffer(pProp); - } - return ulCount; -} - -bool MAPIObject::GetAttachment(MAPIAttachment& attachment, int nIndex) { - return attachment.Open(Message(), nIndex); -} - -bool MAPIObject::AddAttachment(MAPIAttachment& attachment) { - return attachment.Create(Message()); -} - -// use nIndex of -1 to save all attachments to szFolder -bool MAPIObject::SaveAttachment(LPCTSTR szFolder, int nIndex, LPCTSTR szFileName) { - LPMAPITABLE pAttachTable = NULL; - if(Message()->GetAttachmentTable(0, &pAttachTable) != S_OK) - return false; - - String 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; - MAPIAttachment attachment; - while(true) { - strPath = ""; - 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("%s\\%s", szFolder, szFileName); - else { - if(!IsNull(MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME]))) - strPath += Format("%s\\%s", szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME].Value.LPSZ); - else if(!IsNull(MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME]))) - strPath += Format("%s\\%s", szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME].Value.LPSZ); - else - strPath += Format("%s\\Attachment.dat", szFolder); - } - strPath = FromSystemCharset(strPath); - attachment.Attach(pAttachment); - //attachment.SaveAttachment(strPath); - bResult = attachment.SaveAttachment(strPath); - } - } - FreeProws(pRows); - if(nIndex >= 0) - break; - } - } - RELEASE(pAttachTable); - return bResult; -} - -// use nIndex of -1 to delete all attachments -bool MAPIObject::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; -} - -bool MAPIObject::AddAttachment(const String &szPath, String szName, String szCID) { - if (!FileExists(szPath)) - return false; - - String szFileName = szName; - if(IsNull(szFileName)) { - szFileName = szPath; - for(int i = szPath.GetCount() - 1; i >= 0; i--) - if(szPath[i] == '\\' || szPath[i] == '/') { - szFileName = szPath.Mid(i+1); - break; - } - } - - MAPIAttachment attachment; - if(attachment.Create(Message())) { - if(IsNull(szCID) || szCID != CONTACT_PICTURE) { - attachment.SetFileName(szFileName); - attachment.SetLongFileName(szFileName); - if(!IsNull(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; -} - -// Gets the body of the item, if bAutoDetect is set, uses the MessageEditorFormat to try to determine which property to return -String MAPIObject::GetBody(bool bAutoDetect) { - String strBody; - if(bAutoDetect) { - int nFormat = GetMessageEditorFormat(); - if(nFormat == EDITOR_FORMAT_DONTKNOW || nFormat == EDITOR_FORMAT_RTF) - return GetRTF(); - else if(nFormat == EDITOR_FORMAT_HTML) - return GetHTML(); - } - return GetPropertyString(PR_BODY, true); -} - -bool MAPIObject::SetBody(const String& strBody) { - if(SetPropertyString(PR_BODY, strBody, true)) { - SetMessageEditorFormat(EDITOR_FORMAT_PLAINTEXT); - return true; - } - return false; -} - -String MAPIObject::GetHTML() { - return GetPropertyString(PR_BODY_HTML, true); -} - -bool MAPIObject::SetHTML(const String &strHTML) { - // 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, strHTML, true)) { - SetMessageEditorFormat(EDITOR_FORMAT_HTML); - return true; - } - } else { - // otherwise lets encode it into RTF - const char *szCodePage = "1252"; // default codepage is ANSI - Latin I - GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, (CHAR*)szCodePage, strlen(szCodePage)); - - String strRTF; - strRTF = Format("{\\rtf1\\ansi\\ansicpg%s\\fromhtml1 {\\*\\htmltag1 ", szCodePage); - strRTF += strHTML; - strRTF += " }}"; - - return SetRTF(strRTF); - } - return false; -} - -String MAPIObject::GetRTF() { - String strRTF; - 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 Null; - - if(nMessageStatus & MSGSTATUS_HAS_PR_BODY_HTML) { - if(Message()->OpenProperty(PR_BODY_HTML_A, &IID_IStream, STGM_READ, NULL, (LPUNKNOWN*)&pStream)!=S_OK) - return Null; - - 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 Null; - 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 Null; - - 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? If so decode it - // code taken from Lucian Wischik's example at http://www.wischik.com/lu/programmer/mapi_utils.html - if(strRTF.Find("\\fromhtml") != -1) - return GetHTML(); - else if(strRTF.Find("\\fromtext") != -1) - return GetBody(false); - - return strRTF; -} - -bool MAPIObject::SetRTF(const String &strRTF) { - 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(strRTF.ToWString(), strRTF.ToWString().GetCount()*sizeof(wchar), 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; -} - -Time MAPIObject::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 MAPIEx::GetSystemTime(tm); - } - return Null; -} - -bool MAPIObject::SetLastModified(const Time &tm) { - SPropValue prop; - prop.ulPropTag = PR_LAST_MODIFICATION_TIME; - SYSTEMTIME st; - MAPIEx::SetSystemTime(st, tm); - SystemTimeToFileTime(&st, &prop.Value.ft); - return (m_pItem && m_pItem->SetProps(1, &prop, NULL) == S_OK); -} \ No newline at end of file +#ifdef _WIN32 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Ported to U++ Framework by Koldo. See License.txt file + +#include "MAPIEx.h" +#include "MapiUtil.h" +#include + +///////////////////////////////////////////////////////////// +// MAPIObject + +MAPIObject::MAPIObject() { + m_pMAPI = NULL; + m_pItem = NULL; + m_entryID.cb = 0; + SetEntryID(NULL); +} + +MAPIObject::~MAPIObject() { +} + +String MAPIObject::GetHexString(SBinary bin) { + String strHex; + if(bin.cb) { + for(ULONG i = 0; i < bin.cb; i++) + strHex += Format("%02X", bin.lpb[i]); + return strHex; + } + return String(); +} + +String MAPIObject::GetEntryIDString() { + return GetHexString(m_entryID); +} + +void MAPIObject::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 MAPIObject::Open(MAPIEx* pMAPI, SBinary entryID) { + Close(); + m_pMAPI = pMAPI; + ULONG ulObjType; + if(S_OK != m_pMAPI->GetSession()->OpenEntry(entryID.cb, (LPENTRYID)entryID.lpb, NULL, + MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN*)&m_pItem)) + return false; + SetEntryID(&entryID); + return true; +} + +void MAPIObject::Close() { + SetEntryID(NULL); + RELEASE(m_pItem); + m_pMAPI = NULL; +} + +bool MAPIObject::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 MAPIObject::GetMessageFlags() { + return GetPropertyValue(PR_MESSAGE_FLAGS, 0); +} + +bool MAPIObject::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 MAPIObject::GetSensitivity() { + return GetPropertyValue(PR_SENSITIVITY, -1); +} + +bool MAPIObject::SetSensitivity(int nSensitivity) { + SPropValue prop; + prop.ulPropTag = PR_SENSITIVITY; + prop.Value.l = nSensitivity; + return (Message()->SetProps(1, &prop, NULL) == S_OK); +} + +int MAPIObject::GetImportance() { + return GetPropertyValue(PR_IMPORTANCE, IMPORTANCE_NORMAL); +} + +bool MAPIObject::SetImportance(int nImportance) { + SPropValue prop; + prop.ulPropTag = PR_IMPORTANCE; + prop.Value.l = nImportance; + return (Message()->SetProps(1, &prop, NULL) == S_OK); +} + +String MAPIObject::GetMessageClass() { + return GetPropertyString(PR_MESSAGE_CLASS); +} + +bool MAPIObject::SetMessageClass(String szMessageClass) { + SPropValue prop; + prop.ulPropTag = PR_MESSAGE_CLASS; + prop.Value.LPSZ = (LPSTR)szMessageClass.Begin(); + return (Message()->SetProps(1, &prop, NULL) == S_OK); +} + +int MAPIObject::GetMessageEditorFormat() { + return GetPropertyValue(PR_MSG_EDITOR_FORMAT, EDITOR_FORMAT_DONTKNOW); +} + +bool MAPIObject::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 MAPIObject::Create(MAPIEx &mapi, MAPIFolder &folder) { + if(!folder.IsOpened()) + return false; + Close(); + m_pMAPI = &mapi; + if(folder.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 MAPIObject::GetProperty(ULONG ulProperty, LPSPropValue& pProp) { + if(!m_pItem) + return E_INVALIDARG; + ULONG ulPropCount; + ULONG p[2] = {1, ulProperty}; + return m_pItem->GetProps((LPSPropTagArray)p, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); +} + +String MAPIObject::GetPropertyString(ULONG ulProperty, bool bStream) { + String strProperty; + if(bStream) { + IStream* pStream; + if(Message()->OpenProperty(ulProperty, &IID_IStream,STGM_READ, 0, (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 strProperty; + } + } else { + if (ulProperty == PR_ENTRYID) + return GetEntryIDString(); + LPSPropValue pProp; + if(GetProperty(ulProperty, pProp) == S_OK) { + strProperty = MAPIEx::GetValidString(*pProp); + MAPIFreeBuffer(pProp); + return strProperty; + } + } + return String(); +} + +int MAPIObject::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 MAPIObject::GetPropTagArray(LPCTSTR szFieldName, LPSPropTagArray& lppPropTags, int& nFieldType, bool bCreate) { + if(!m_pItem) + return false; + + MAPINAMEID nameID; + nameID.lpguid = (GUID*)&GUIDPublicStrings; + nameID.ulKind = MNID_STRING; + + nFieldType = PT_STRING8; + WCHAR wszFieldName[256]; + MultiByteToWideChar(CP_ACP, 0, szFieldName,-1,wszFieldName,255); + nameID.Kind.lpwstrName = wszFieldName; + + LPMAPINAMEID lpNameID[1] = {&nameID}; + + HRESULT hr = m_pItem->GetIDsFromNames(1, lpNameID, bCreate ? MAPI_CREATE : 0, &lppPropTags); + return (hr == S_OK); +} + +bool MAPIObject::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, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); + MAPIFreeBuffer(lppPropTags); + return (hr == S_OK); +} + +bool MAPIObject::GetNamedProperty(LPCTSTR szFieldName, String& strField) { + LPSPropValue pProp; + if(GetNamedProperty(szFieldName, pProp)) { + strField = MAPIEx::GetValidString(*pProp); + MAPIFreeBuffer(pProp); + return true; + } + return false; +} + +bool MAPIObject::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; + + nFieldType = PT_STRING8; + + 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 MAPIObject::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, MAPIEx::cm_nMAPICode, &ulPropCount, &pProp); + MAPIFreeBuffer(lppPropTags); + return (hr == S_OK); +} + +// gets a custom outlook property value +bool MAPIObject::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 MAPIObject::GetOutlookPropertyString(ULONG ulData, ULONG ulProperty, String& strProperty) { + LPSPropValue pProp; + if(GetOutlookProperty(ulData, ulProperty, pProp)) { + strProperty = MAPIEx::GetValidString(*pProp); + MAPIFreeBuffer(pProp); + return true; + } + return false; +} + +bool MAPIObject::SetPropertyString(ULONG ulProperty, String szProperty, bool bStream) { + if(m_pItem && !IsNull(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, (szProperty.ToWString().GetCount()+1)*sizeof(wchar), + NULL); + RELEASE(pStream); + return true; + } + } else { + SPropValue prop; + prop.ulPropTag = ulProperty; + prop.Value.LPSZ = (LPTSTR)szProperty.Begin(); + return (m_pItem->SetProps(1, &prop, NULL) == S_OK); + } + } + return false; +} + +bool MAPIObject::SetPropertyValue(ULONG ulProperty, int nValue) { + if(!m_pItem) + return false; + SPropValue prop; + prop.ulPropTag = ulProperty; + prop.Value.l = nValue; + return (m_pItem->SetProps(1, &prop, NULL) == S_OK); +} + +// if bCreate is true, the property will be created if necessary otherwise if not present will return false +bool MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::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 MAPIObject::GetAttachmentCount() { + ULONG ulCount = 0; + LPSPropValue pProp; + if(GetProperty(PR_HASATTACH, pProp) == S_OK) { + if(pProp->Value.b) { + LPMAPITABLE pAttachTable=NULL; + 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); + } + } + MAPIFreeBuffer(pProp); + } + return ulCount; +} + +bool MAPIObject::GetAttachment(MAPIAttachment& attachment, int nIndex) { + return attachment.Open(Message(), nIndex); +} + +bool MAPIObject::AddAttachment(MAPIAttachment& attachment) { + return attachment.Create(Message()); +} + +// use nIndex of -1 to save all attachments to szFolder +bool MAPIObject::SaveAttachment(LPCTSTR szFolder, int nIndex, LPCTSTR szFileName) { + LPMAPITABLE pAttachTable = NULL; + if(Message()->GetAttachmentTable(0, &pAttachTable) != S_OK) + return false; + + String 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; + MAPIAttachment attachment; + while(true) { + strPath = ""; + 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("%s\\%s", szFolder, szFileName); + else { + if(!IsNull(MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME]))) + strPath += Format("%s\\%s", szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_LONG_FILENAME].Value.LPSZ); + else if(!IsNull(MAPIEx::GetValidString(pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME]))) + strPath += Format("%s\\%s", szFolder, pRows->aRow[0].lpProps[PROP_ATTACH_FILENAME].Value.LPSZ); + else + strPath += Format("%s\\Attachment.dat", szFolder); + } + strPath = FromSystemCharset(strPath); + attachment.Attach(pAttachment); + //attachment.SaveAttachment(strPath); + bResult = attachment.SaveAttachment(strPath); + } + } + FreeProws(pRows); + if(nIndex >= 0) + break; + } + } + RELEASE(pAttachTable); + return bResult; +} + +// use nIndex of -1 to delete all attachments +bool MAPIObject::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; +} + +bool MAPIObject::AddAttachment(const String &szPath, String szName, String szCID) { + if (!FileExists(szPath)) + return false; + + String szFileName = szName; + if(IsNull(szFileName)) { + szFileName = szPath; + for(int i = szPath.GetCount() - 1; i >= 0; i--) + if(szPath[i] == '\\' || szPath[i] == '/') { + szFileName = szPath.Mid(i+1); + break; + } + } + + MAPIAttachment attachment; + if(attachment.Create(Message())) { + if(IsNull(szCID) || szCID != CONTACT_PICTURE) { + attachment.SetFileName(szFileName); + attachment.SetLongFileName(szFileName); + if(!IsNull(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; +} + +// Gets the body of the item, if bAutoDetect is set, uses the MessageEditorFormat to try to determine which property to return +String MAPIObject::GetBody(bool bAutoDetect) { + String strBody; + if(bAutoDetect) { + int nFormat = GetMessageEditorFormat(); + if(nFormat == EDITOR_FORMAT_DONTKNOW || nFormat == EDITOR_FORMAT_RTF) + return GetRTF(); + else if(nFormat == EDITOR_FORMAT_HTML) + return GetHTML(); + } + return GetPropertyString(PR_BODY, true); +} + +bool MAPIObject::SetBody(const String& strBody) { + if(SetPropertyString(PR_BODY, strBody, true)) { + SetMessageEditorFormat(EDITOR_FORMAT_PLAINTEXT); + return true; + } + return false; +} + +String MAPIObject::GetHTML() { + return GetPropertyString(PR_BODY_HTML, true); +} + +bool MAPIObject::SetHTML(const String &strHTML) { + // 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, strHTML, true)) { + SetMessageEditorFormat(EDITOR_FORMAT_HTML); + return true; + } + } else { + // otherwise lets encode it into RTF + const char *szCodePage = "1252"; // default codepage is ANSI - Latin I + GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, (CHAR*)szCodePage, strlen(szCodePage)); + + String strRTF; + strRTF = Format("{\\rtf1\\ansi\\ansicpg%s\\fromhtml1 {\\*\\htmltag1 ", szCodePage); + strRTF += strHTML; + strRTF += " }}"; + + return SetRTF(strRTF); + } + return false; +} + +String MAPIObject::GetRTF() { + String strRTF; + 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 Null; + + if(nMessageStatus & MSGSTATUS_HAS_PR_BODY_HTML) { + if(Message()->OpenProperty(PR_BODY_HTML_A, &IID_IStream, STGM_READ, NULL, (LPUNKNOWN*)&pStream)!=S_OK) + return Null; + + 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 Null; + 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 Null; + + 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? If so decode it + // code taken from Lucian Wischik's example at http://www.wischik.com/lu/programmer/mapi_utils.html + if(strRTF.Find("\\fromhtml") != -1) + return GetHTML(); + else if(strRTF.Find("\\fromtext") != -1) + return GetBody(false); + + return strRTF; +} + +bool MAPIObject::SetRTF(const String &strRTF) { + 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(strRTF.ToWString(), strRTF.ToWString().GetCount()*sizeof(wchar), 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; +} + +Time MAPIObject::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 MAPIEx::GetSystemTime(tm); + } + return Null; +} + +bool MAPIObject::SetLastModified(const Time &tm) { + SPropValue prop; + prop.ulPropTag = PR_LAST_MODIFICATION_TIME; + SYSTEMTIME st; + MAPIEx::SetSystemTime(st, tm); + SystemTimeToFileTime(&st, &prop.Value.ft); + return (m_pItem && m_pItem->SetProps(1, &prop, NULL) == S_OK); +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/MAPISink.cpp b/bazaar/MAPIEx/MAPISink.cpp index 8d5d3fe2b..1a0c5376d 100644 --- a/bazaar/MAPIEx/MAPISink.cpp +++ b/bazaar/MAPIEx/MAPISink.cpp @@ -1,54 +1,57 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// File: MAPISink.cpp -// Description: MAPI Advise Sink Wrapper -// -// 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 -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Ported to U++ Framework by Koldo. See License.txt file - -#include "MAPIEx.h" -#include "MAPISink.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// MAPISink - -MAPISink::MAPISink(LPNOTIFCALLBACK lpfnCallback, LPVOID lpvContext) { - m_lpfnCallback = lpfnCallback; - m_lpvContext = lpvContext; - m_nRef = 0; -} - -HRESULT MAPISink::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { - if(riid == IID_IUnknown) { - *ppvObj = this; - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG MAPISink::AddRef() { - return InterlockedIncrement(&m_nRef); -} - -ULONG MAPISink::Release() { - ULONG ul = InterlockedDecrement(&m_nRef); - if(!ul) - delete this; - return ul; -} - -ULONG MAPISink::OnNotify(ULONG cNotification, LPNOTIFICATION lpNotifications) { - if(m_lpfnCallback) - m_lpfnCallback(m_lpvContext, cNotification, lpNotifications); - return 0; -} - +#ifdef _WIN32 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// File: MAPISink.cpp +// Description: MAPI Advise Sink Wrapper +// +// 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 +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Ported to U++ Framework by Koldo. See License.txt file + +#include "MAPIEx.h" +#include "MAPISink.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MAPISink + +MAPISink::MAPISink(LPNOTIFCALLBACK lpfnCallback, LPVOID lpvContext) { + m_lpfnCallback = lpfnCallback; + m_lpvContext = lpvContext; + m_nRef = 0; +} + +HRESULT MAPISink::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { + if(riid == IID_IUnknown) { + *ppvObj = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +ULONG MAPISink::AddRef() { + return InterlockedIncrement(&m_nRef); +} + +ULONG MAPISink::Release() { + ULONG ul = InterlockedDecrement(&m_nRef); + if(!ul) + delete this; + return ul; +} + +ULONG MAPISink::OnNotify(ULONG cNotification, LPNOTIFICATION lpNotifications) { + if(m_lpfnCallback) + m_lpfnCallback(m_lpvContext, cNotification, lpNotifications); + return 0; +} + +#endif \ No newline at end of file diff --git a/bazaar/MAPIEx/plugin/MAPIEx.cpp b/bazaar/MAPIEx/plugin/MAPIEx.cpp index 9aa8c8a59..0a919c2dd 100644 --- a/bazaar/MAPIEx/plugin/MAPIEx.cpp +++ b/bazaar/MAPIEx/plugin/MAPIEx.cpp @@ -682,15 +682,17 @@ int CMAPIEx::ShowAddressBook(LPADRLIST& pAddressList, LPCTSTR szCaption) adrparm.lpszCaption=(LPTSTR)szNarrowCaption; } #endif - adrparm.cDestFields=1; - adrparm.lppszDestTitles=(LPTSTR*)lppszDestTitles; - adrparm.lpulDestComps=lpulDestComps; + adrparm.cDestFields = 1; + adrparm.lppszDestTitles = (LPTSTR*)lppszDestTitles; + adrparm.lpulDestComps = lpulDestComps; - HWND hDesktop=::GetDesktopWindow(); - HRESULT hr=pAddressBook->Address((ULONG_PTR*)&hDesktop, &adrparm, &pAddressList); + HWND hDesktop = ::GetDesktopWindow(); + HRESULT hr = pAddressBook->Address((ULONG_PTR*)&hDesktop, &adrparm, &pAddressList); RELEASE(pAddressBook); - if(hr==S_OK) return IDOK; - if(hr==MAPI_E_USER_CANCEL) return IDCANCEL; + if(hr == S_OK) + return IDOK; + if(hr == MAPI_E_USER_CANCEL) + return IDCANCEL; } #endif return FALSE; diff --git a/bazaar/MAPIEx/plugin/MAPIMessage.cpp b/bazaar/MAPIEx/plugin/MAPIMessage.cpp index 1303a1656..c379761f4 100644 --- a/bazaar/MAPIEx/plugin/MAPIMessage.cpp +++ b/bazaar/MAPIEx/plugin/MAPIMessage.cpp @@ -510,7 +510,7 @@ BOOL CMAPIMessage::SaveAsMsg(LPCTSTR szPath) CString strPath=szPath; if(strPath.GetLength()<4 || strPath.Right(4).CompareNoCase(".msg")) strPath+=".msg"; #ifdef _WIN32_WCE - return FALSE; + return FALSE; #else LPSTORAGE pStorage; DWORD dwFlags=STGM_READWRITE | STGM_TRANSACTED | STGM_CREATE; @@ -524,14 +524,11 @@ BOOL CMAPIMessage::SaveAsMsg(LPCTSTR szPath) { LPMSGSESS pMsgSession; LPMALLOC pMalloc = MAPIGetDefaultMalloc(); - if(OpenIMsgSession(pMalloc, 0, &pMsgSession) == S_OK) - { + if(OpenIMsgSession(pMalloc, 0, &pMsgSession) == S_OK) { LPMESSAGE pIMsg; - if(OpenIMsgOnIStg(pMsgSession, MAPIAllocateBuffer, MAPIAllocateMore, MAPIFreeBuffer, pMalloc, NULL, pStorage, NULL, 0, 0, &pIMsg) == S_OK) - { + if(OpenIMsgOnIStg(pMsgSession, MAPIAllocateBuffer, MAPIAllocateMore, MAPIFreeBuffer, pMalloc, NULL, pStorage, NULL, 0, 0, &pIMsg) == S_OK) { // client must support CLSID_MailMessage as the compound document - if(WriteClassStg(pStorage, CLSID_MailMessage) == S_OK) - { + if(WriteClassStg(pStorage, CLSID_MailMessage) == S_OK) { // exclude these properties from the copy operation to speed things up SizedSPropTagArray ( 7, excludeTags ); excludeTags.cValues=7; @@ -543,8 +540,7 @@ BOOL CMAPIMessage::SaveAsMsg(LPCTSTR szPath) excludeTags.aulPropTag[5]=PR_RTF_SYNC_PREFIX_COUNT; excludeTags.aulPropTag[6]=PR_RTF_SYNC_TRAILING_COUNT; - if(Message()->CopyTo(0, NULL, (LPSPropTagArray)&excludeTags, NULL, NULL, (LPIID)&IID_IMessage, pIMsg, 0, NULL ) == S_OK) - { + if(Message()->CopyTo(0, NULL, (LPSPropTagArray)&excludeTags, NULL, NULL, (LPIID)&IID_IMessage, pIMsg, 0, NULL ) == S_OK) { pIMsg->SaveChanges(KEEP_OPEN_READWRITE); pStorage->Commit(STGC_DEFAULT); } @@ -553,7 +549,6 @@ BOOL CMAPIMessage::SaveAsMsg(LPCTSTR szPath) } CloseIMsgSession(pMsgSession); } - RELEASE(pStorage); return TRUE; } diff --git a/bazaar/MAPIEx/src.tpp/all.i b/bazaar/MAPIEx/src.tpp/all.i index d773369f7..1bf30a76d 100644 --- a/bazaar/MAPIEx/src.tpp/all.i +++ b/bazaar/MAPIEx/src.tpp/all.i @@ -1,7 +1,3 @@ -TOPIC("aa$en-us") -#include "aa$en-us.tppi" -END_TOPIC - TOPIC("MAPIAppointment$en-us") #include "MAPIAppointment$en-us.tppi" END_TOPIC @@ -26,3 +22,7 @@ TOPIC("MAPIMessage$en-us") #include "MAPIMessage$en-us.tppi" END_TOPIC +TOPIC("aa$en-us") +#include "aa$en-us.tppi" +END_TOPIC + diff --git a/bazaar/MAPIEx/srcdoc.tpp/ChangesLog$en-us.tpp b/bazaar/MAPIEx/srcdoc.tpp/ChangesLog$en-us.tpp deleted file mode 100644 index 6027b2657..000000000 --- a/bazaar/MAPIEx/srcdoc.tpp/ChangesLog$en-us.tpp +++ /dev/null @@ -1,9 +0,0 @@ -topic "News and changes Log"; -[ $$0,0#00000000000000000000000000000000:Default] -[a83;*R6 $$1,0#31310162474203024125188417583966:caption] -[{_}%EN-US -[s0; [*R+184 MAPIEx. News and changes log]&] -[s0;%- &] -[ {{1441:8559f0;g0;^t/25b/25 [s0;# [2 2011/04/20]] -:: [s0;# [2 Package created.]]}}&] -[s0; ] \ No newline at end of file diff --git a/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tpp b/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tpp index daa3ec11c..fdfa5f036 100644 --- a/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tpp +++ b/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tpp @@ -27,4 +27,4 @@ ucian Wischik MAPI Utils][2 . Its license is:]&] [s0; [C+75 This code (c) 2002`-2006 Lucian Wischik.]&] [s0;C+75 &] [s0; [C+75 The code is free and anyone can do with it whatever they -like, including incorporating it in commercial products.]] \ No newline at end of file +like, including incorporating it in commercial products.]]] \ No newline at end of file diff --git a/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tppi b/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tppi index 0c7dc33f3..ca6a84890 100644 --- a/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tppi +++ b/bazaar/MAPIEx/srcdoc.tpp/License$en-us.tppi @@ -1,6 +1,6 @@ TITLE("MAPIEx License") COMPRESSED -120,156,149,147,107,79,219,48,20,134,255,202,145,96,19,163,144,91,175,43,154,166,209,49,9,13,16,2,170,125,168,10,54,142,155,120,56,118,100,59,52,101,218,127,223,113,82,208,214,21,77,235,151,186,245,185,188,239,57,143,103,176,187,27,29,68,59,209,63,62,227,207,124,65,43,233,230,51,58,234,30,237,95,13,48,47,198,188,110,220,141,163,120,144,244,134,189,36,234,70,73,47,78,250,241,104,212,139,135,253,81,247,253,96,48,102,180,116,66,171,249,236,199,221,207,55,39,23,135,211,107,152,217,232,8,102,251,87,157,120,212,131,243,79,151,167,39,53,156,9,198,149,229,243,183,115,127,155,64,251,13,179,228,57,96,74,58,164,3,199,244,137,82,3,37,101,15,52,227,32,44,44,42,41,87,112,79,45,79,65,40,152,207,110,115,231,74,50,38,33,9,151,203,37,9,138,42,37,1,163,36,108,11,145,224,73,148,183,9,92,104,46,225,179,144,146,222,235,42,203,97,210,94,207,177,99,0,167,206,130,108,21,97,143,241,95,170,38,157,97,31,38,186,92,25,145, -229,14,246,38,239,32,137,162,62,57,76,162,56,58,216,172,189,78,111,146,254,168,112,147,163,1,171,43,195,56,48,157,182,126,12,231,224,52,84,216,154,170,20,10,157,138,197,10,74,163,31,69,138,30,157,207,81,218,161,58,48,188,160,66,89,244,237,40,115,77,184,203,169,63,172,128,171,156,42,198,11,174,208,139,54,112,95,101,176,16,53,183,64,13,135,82,91,231,139,105,76,224,232,36,229,151,70,127,231,88,164,244,115,205,241,90,168,172,109,198,36,181,168,11,107,248,88,166,139,162,82,194,173,124,242,61,87,124,33,92,240,170,195,169,197,114,99,176,222,211,70,35,106,208,131,68,147,14,252,198,198,161,95,87,224,199,80,182,17,120,46,66,180,198,141,226,46,156,156,211,82,156,212,1,181,229,22,72,190,104,41,245,242,69,242,243,238,168,148,192,112,14,25,218,206,233,35,71,193,92,225,216,74,109,214,246,217,203,18,115,45,83,110,130,45,4,253,166,201,255,40,72,248,245,152,132,167,151,228,89,20,241,170,106,242,177,176,25,249,208,29,13,7,81,47,38, -59,117,189,62,214,53,242,118,221,140,0,181,249,209,55,148,109,177,177,134,16,85,225,70,253,102,27,42,22,70,23,91,100,45,133,101,185,120,88,75,146,21,9,81,100,102,104,81,112,67,194,2,149,145,187,202,9,105,73,144,187,66,162,134,179,138,9,170,224,91,155,216,188,44,152,250,136,255,160,190,97,182,145,181,199,26,234,19,79,125,52,216,40,254,58,18,55,249,6,236,30,91,36,86,43,252,31,11,164,26,150,194,229,32,28,44,17,102,254,200,27,240,86,40,237,129,31,32,235,76,86,169,223,52,158,180,193,77,210,6,85,12,199,231,239,233,228,6,133,72,255,98,210,138,57,27,204,231,191,0,77,128,153,55, +120,156,149,147,107,79,219,48,20,134,255,202,145,96,19,163,144,91,175,43,154,166,209,49,9,13,16,2,170,125,168,2,54,142,219,120,56,118,100,59,52,101,218,127,223,113,82,208,214,21,77,235,151,186,245,185,188,239,57,143,103,176,187,27,29,68,59,209,63,62,227,207,124,78,43,233,210,25,29,117,143,246,175,6,152,23,99,94,55,238,198,81,60,72,122,195,94,18,117,163,164,23,39,253,120,52,234,197,195,254,168,251,126,48,24,51,90,58,161,85,58,251,113,247,243,205,201,197,225,244,26,102,54,58,130,217,254,85,39,30,245,224,252,211,229,233,73,13,103,130,113,101,121,250,54,245,183,9,180,223,48,75,158,3,166,164,67,58,112,76,159,40,53,80,82,246,64,23,28,132,133,121,37,229,10,238,169,229,25,8,5,233,236,54,119,174,36,99,18,146,112,185,92,146,160,168,50,18,48,74,194,182,16,9,158,68,121,155,192,133,230,18,62,11,41,233,189,174,22,57,76,218,235,20,59,6,112,234,44,200,86,17,246,24,255,165,106,210,25,246,97,162,203,149,17,139, +220,193,222,228,29,36,81,212,39,135,73,20,71,7,155,181,215,233,77,210,31,21,110,114,52,96,117,101,24,7,166,179,214,143,225,28,156,134,10,91,83,149,65,161,51,49,95,65,105,244,163,200,208,163,243,57,74,59,84,7,134,23,84,40,139,190,29,101,174,9,119,57,245,135,21,112,149,83,197,120,193,21,122,209,6,238,171,5,204,69,205,45,80,195,161,212,214,249,98,26,19,56,58,201,248,165,209,223,57,22,41,253,92,115,188,22,106,209,54,99,146,90,212,133,53,124,44,211,69,81,41,225,86,62,249,158,43,62,23,46,120,213,225,212,98,185,49,88,239,105,163,17,53,232,65,162,73,7,126,99,227,208,175,43,240,99,40,219,8,60,23,33,90,227,70,113,23,78,206,105,41,78,234,128,218,114,11,36,95,180,148,122,249,34,249,121,119,84,74,96,56,135,5,218,206,233,35,71,193,92,225,216,74,109,214,246,217,203,18,115,45,51,110,130,45,4,253,166,201,255,40,72,248,245,152,132,167,151,228,89,20,241,170,106,242,177,176,11,242,161,59,26,14,162,94,76, +118,234,122,125,172,107,228,237,186,25,1,106,243,163,111,40,219,98,99,13,33,170,194,141,250,205,54,84,204,141,46,182,200,90,10,203,114,241,176,150,36,43,18,162,200,133,161,69,193,13,9,11,84,70,238,42,39,164,37,65,238,10,137,26,206,42,38,168,130,111,109,98,243,178,96,234,35,254,131,250,134,217,70,214,30,107,168,79,60,245,209,96,163,248,235,72,220,228,27,176,123,108,145,88,173,240,127,44,144,105,88,10,151,131,112,176,68,152,249,35,111,192,91,161,180,7,126,128,172,51,89,101,126,211,120,210,6,55,73,27,84,49,28,159,191,167,147,27,20,34,253,139,201,42,230,108,144,166,233,47,231,20,153,148, diff --git a/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tpp b/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tpp index e184d59ed..45c20f730 100644 --- a/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tpp +++ b/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tpp @@ -3,4 +3,4 @@ topic "ToDo list"; [{_}%EN-US [s0; [*R+184 MAPIEx. ToDo list]&] [s0;2 &] -[s0;i150;O0;~~~608; [2 MinGW compatibility.]] \ No newline at end of file +[s0;i150;O0;~~~608; [2 MinGW compatibility.]]] \ No newline at end of file diff --git a/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tppi b/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tppi index 9fc37dc5f..1407dd07c 100644 --- a/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tppi +++ b/bazaar/MAPIEx/srcdoc.tpp/ToDo$en-us.tppi @@ -1,4 +1,4 @@ TITLE("ToDo list") COMPRESSED -120,156,139,86,80,81,49,208,49,80,54,32,0,172,92,82,211,18,75,115,74,98,163,171,227,107,85,93,253,116,67,131,21,162,139,13,172,21,162,181,130,180,13,45,76,20,124,29,3,60,93,43,244,20,66,242,93,242,21,114,50,139,75,98,213,98,65,10,140,20,32,116,166,161,169,129,181,191,129,117,93,93,157,153,129,5,80,159,145,130,111,102,158,123,184,66,114,126,110,65,98,73,102,82,102,78,102,73,165,94,108,44,0,103,174,40,73, +120,156,139,86,80,81,49,208,49,80,54,32,0,172,92,82,211,18,75,115,74,98,163,171,227,107,85,93,253,116,67,131,21,162,139,13,172,21,162,181,130,180,13,45,76,20,124,29,3,60,93,43,244,20,66,242,93,242,21,114,50,139,75,98,213,98,65,10,140,20,32,116,166,161,169,129,181,191,129,117,93,93,157,153,129,5,80,159,145,130,111,102,158,123,184,66,114,126,110,65,98,73,102,82,102,78,102,73,165,94,108,108,44,0,144,84,40,166,