123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715 |
- #include <new>
- #include <kopano/platform.h>
- #include <kopano/lockhelper.hpp>
- #include <kopano/mapi_ptr.h>
- #include <kopano/memory.hpp>
- #include <kopano/ECInterfaceDefs.h>
- #include <mapidefs.h>
- #include <mapiutil.h>
- #include <mapitags.h>
- #include <kopano/mapiext.h>
- #include "ECMessage.h"
- #include "ECAttach.h"
- #include <kopano/ECMemTable.h>
- #include <kopano/codepage.h>
- #include "rtfutil.h"
- #include <kopano/Util.h>
- #include "Mem.h"
- #include <kopano/mapi_ptr.h>
- #include <kopano/ECGuid.h>
- #include <edkguid.h>
- #include <kopano/ECDebug.h>
- #include "WSUtil.h"
- #include "ClientUtil.h"
- #include "ECMemStream.h"
- #include <kopano/charset/convert.h>
- #include <librosie.h>
- #include "config.h"
- using namespace std;
- using namespace KCHL;
- #define MAX_TABLE_PROPSIZE 8192
- static constexpr const SizedSPropTagArray(15, sPropRecipColumns) =
- {15, {PR_7BIT_DISPLAY_NAME_W, PR_EMAIL_ADDRESS_W, PR_INSTANCE_KEY,
- PR_RECORD_KEY, PR_SEARCH_KEY, PR_SEND_RICH_INFO, PR_DISPLAY_NAME_W,
- PR_RECIPIENT_TYPE, PR_ROWID, PR_DISPLAY_TYPE, PR_ENTRYID,
- PR_SPOOLER_STATUS, PR_OBJECT_TYPE, PR_ADDRTYPE_W, PR_RESPONSIBILITY}};
- static constexpr const SizedSPropTagArray(8, sPropAttachColumns) =
- {8, {PR_ATTACH_NUM, PR_INSTANCE_KEY, PR_RECORD_KEY,
- PR_RENDERING_POSITION, PR_ATTACH_FILENAME_W, PR_ATTACH_METHOD,
- PR_DISPLAY_NAME_W, PR_ATTACH_LONG_FILENAME_W}};
- HRESULT ECMessageFactory::Create(ECMsgStore *lpMsgStore, BOOL fNew, BOOL fModify, ULONG ulFlags, BOOL bEmbedded, ECMAPIProp *lpRoot, ECMessage **lpMessage) const
- {
- return ECMessage::Create(lpMsgStore, fNew, fModify, ulFlags, bEmbedded, lpRoot, lpMessage);
- }
- ECMessage::ECMessage(ECMsgStore *lpMsgStore, BOOL fNew, BOOL fModify,
- ULONG ulFlags, BOOL bEmbedded, ECMAPIProp *lpRoot) :
- ECMAPIProp(lpMsgStore, MAPI_MESSAGE, fModify, lpRoot, "IMessage"),
- m_bEmbedded(bEmbedded)
- {
- this->ulObjFlags = ulFlags & MAPI_ASSOCIATED;
- this->fNew = fNew;
- this->m_bEmbedded = bEmbedded;
-
- this->HrAddPropHandlers(PR_RTF_IN_SYNC, GetPropHandler ,DefaultSetPropIgnore, (void*) this, TRUE, FALSE);
- this->HrAddPropHandlers(PR_HASATTACH, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_NORMALIZED_SUBJECT, GetPropHandler ,DefaultSetPropIgnore, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_PARENT_ENTRYID, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_MESSAGE_SIZE, GetPropHandler ,SetPropHandler, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_DISPLAY_TO, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_DISPLAY_CC, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_DISPLAY_BCC, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_ACCESS, GetPropHandler ,DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_MESSAGE_ATTACHMENTS, GetPropHandler ,DefaultSetPropIgnore, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_MESSAGE_RECIPIENTS, GetPropHandler ,DefaultSetPropIgnore, (void*) this, FALSE, FALSE);
-
- this->HrAddPropHandlers(PR_BODY, GetPropHandler ,DefaultSetPropSetReal, (void*) this, TRUE, FALSE);
- this->HrAddPropHandlers(PR_RTF_COMPRESSED, GetPropHandler ,DefaultSetPropSetReal, (void*) this, FALSE, FALSE);
-
- this->HrAddPropHandlers(PR_HTML, GetPropHandler ,SetPropHandler, (void*) this, FALSE, FALSE);
- this->HrAddPropHandlers(PR_EC_BODY_FILTERED, GetPropHandler, SetPropHandler, static_cast<void *>(this), false, false);
-
-
-
-
-
- this->HrAddPropHandlers(0x10970003, DefaultGetPropGetReal,DefaultSetPropSetReal, (void*) this, TRUE, TRUE);
-
-
- this->HrAddPropHandlers(PR_EC_IMAP_ID, DefaultGetPropGetReal,DefaultSetPropComputed, (void*) this, TRUE, TRUE);
-
- this->HrAddPropHandlers(PR_MESSAGE_FLAGS, GetPropHandler ,SetPropHandler, (void*) this, FALSE, FALSE);
-
- this->HrAddPropHandlers(PR_SOURCE_KEY, GetPropHandler ,SetPropHandler, (void*) this, TRUE, FALSE);
-
- this->HrAddPropHandlers(PR_EC_IMAP_EMAIL, DefaultGetPropGetReal ,DefaultSetPropSetReal, (void*) this, TRUE, TRUE);
- this->HrAddPropHandlers(PR_EC_IMAP_EMAIL_SIZE, DefaultGetPropGetReal ,DefaultSetPropSetReal, (void*) this, TRUE, TRUE);
- this->HrAddPropHandlers(CHANGE_PROP_TYPE(PR_EC_IMAP_BODY, PT_UNICODE), DefaultGetPropGetReal ,DefaultSetPropSetReal, (void*) this, TRUE, TRUE);
- this->HrAddPropHandlers(CHANGE_PROP_TYPE(PR_EC_IMAP_BODYSTRUCTURE, PT_UNICODE), DefaultGetPropGetReal ,DefaultSetPropSetReal, (void*) this, TRUE, TRUE);
- this->HrAddPropHandlers(PR_ASSOCIATED, GetPropHandler, DefaultSetPropComputed, (void *)this, TRUE, TRUE);
- }
- ECMessage::~ECMessage()
- {
- MAPIFreeBuffer(m_lpParentID);
- if(lpRecips)
- lpRecips->Release();
- if(lpAttachments)
- lpAttachments->Release();
- }
- HRESULT ECMessage::Create(ECMsgStore *lpMsgStore, BOOL fNew, BOOL fModify, ULONG ulFlags, BOOL bEmbedded, ECMAPIProp *lpRoot, ECMessage **lppMessage)
- {
- return alloc_wrap<ECMessage>(lpMsgStore, fNew, fModify, ulFlags,
- bEmbedded, lpRoot).as(IID_ECMessage, lppMessage);
- }
- HRESULT ECMessage::QueryInterface(REFIID refiid, void **lppInterface)
- {
- REGISTER_INTERFACE2(ECMessage, this);
- REGISTER_INTERFACE2(ECMAPIProp, this);
- REGISTER_INTERFACE2(ECUnknown, this);
- REGISTER_INTERFACE2(IMessage, &this->m_xMessage);
- REGISTER_INTERFACE2(IMAPIProp, &this->m_xMessage);
- REGISTER_INTERFACE2(IUnknown, &this->m_xMessage);
- REGISTER_INTERFACE3(ISelectUnicode, IUnknown, &this->m_xUnknown);
- REGISTER_INTERFACE2(IECSingleInstance, &this->m_xECSingleInstance);
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- HRESULT ECMessage::GetProps(const SPropTagArray *lpPropTagArray, ULONG ulFlags,
- ULONG *lpcValues, SPropValue **lppPropArray)
- {
- HRESULT hr = hrSuccess;
- ULONG cValues = 0;
- SPropArrayPtr ptrPropArray;
- LONG lBodyIdx = 0;
- LONG lRtfIdx = 0;
- LONG lHtmlIdx = 0;
- if (lpPropTagArray) {
- lBodyIdx = Util::FindPropInArray(lpPropTagArray, CHANGE_PROP_TYPE(PR_BODY_W, PT_UNSPECIFIED));
- lRtfIdx = Util::FindPropInArray(lpPropTagArray, CHANGE_PROP_TYPE(PR_RTF_COMPRESSED, PT_UNSPECIFIED));
- lHtmlIdx = Util::FindPropInArray(lpPropTagArray, CHANGE_PROP_TYPE(PR_HTML, PT_UNSPECIFIED));
- }
- if (lstProps == NULL && (!lpPropTagArray || lBodyIdx >= 0 || lRtfIdx >=0 || lHtmlIdx >= 0)) {
-
- m_ulBodyType = bodyTypeUnknown;
- hr = HrLoadProps();
- if (hr != hrSuccess)
- return hr;
- }
- if (m_ulBodyType != bodyTypeUnknown) {
- const ULONG ulBestMatchTable[4][3] = {
- { PR_BODY_W, PR_RTF_COMPRESSED, PR_HTML },
- { PR_BODY_W, PR_RTF_COMPRESSED, PR_HTML },
- { PR_RTF_COMPRESSED, PR_HTML, PR_BODY_W },
- { PR_HTML, PR_RTF_COMPRESSED, PR_BODY_W }};
- SPropTagArrayPtr ptrPropTagArray;
- ULONG ulBestMatch = 0;
- if (lpPropTagArray) {
-
- hr = Util::HrCopyPropTagArray(lpPropTagArray, &~ptrPropTagArray);
- if (hr != hrSuccess)
- return hr;
- } else {
-
- hr = GetPropList(ulFlags, &~ptrPropTagArray);
- if (hr != hrSuccess)
- return hr;
- lBodyIdx = Util::FindPropInArray(ptrPropTagArray, CHANGE_PROP_TYPE(PR_BODY_W, PT_UNSPECIFIED));
- lRtfIdx = Util::FindPropInArray(ptrPropTagArray, CHANGE_PROP_TYPE(PR_RTF_COMPRESSED, PT_UNSPECIFIED));
- lHtmlIdx = Util::FindPropInArray(ptrPropTagArray, CHANGE_PROP_TYPE(PR_HTML, PT_UNSPECIFIED));
- }
- if (!lpPropTagArray || lBodyIdx >= 0 || lRtfIdx >= 0 || lHtmlIdx >= 0) {
-
-
- if (lpPropTagArray == NULL)
-
- ulBestMatch = ulBestMatchTable[m_ulBodyType][0];
- else {
-
- for (int i = 0; i < 3; ++i)
- if (Util::FindPropInArray(ptrPropTagArray, PROP_TAG(PT_UNSPECIFIED, PROP_ID(ulBestMatchTable[m_ulBodyType][i]))) >= 0) {
- ulBestMatch = ulBestMatchTable[m_ulBodyType][i];
- break;
- }
- }
-
- if (lBodyIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_BODY))
- ptrPropTagArray->aulPropTag[lBodyIdx] = PR_NULL;
- if (lRtfIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_RTF_COMPRESSED))
- ptrPropTagArray->aulPropTag[lRtfIdx] = PR_NULL;
- if (lHtmlIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_HTML))
- ptrPropTagArray->aulPropTag[lHtmlIdx] = PR_NULL;
- hr = ECMAPIProp::GetProps(ptrPropTagArray, ulFlags, &cValues, &~ptrPropArray);
- if (HR_FAILED(hr))
- return hr;
-
- if (lBodyIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_BODY)) {
- ptrPropArray[lBodyIdx].ulPropTag = CHANGE_PROP_TYPE(PR_BODY, PT_ERROR);
- ptrPropArray[lBodyIdx].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- hr = MAPI_W_ERRORS_RETURNED;
- }
- if (lRtfIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_RTF_COMPRESSED)) {
- ptrPropArray[lRtfIdx].ulPropTag = CHANGE_PROP_TYPE(PR_RTF_COMPRESSED, PT_ERROR);
- if (!lpPropTagArray)
- ptrPropArray[lRtfIdx].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- else
- ptrPropArray[lRtfIdx].Value.err = PROP_ID(PR_RTF_COMPRESSED) < PROP_ID(ulBestMatch) ? MAPI_E_NOT_ENOUGH_MEMORY : MAPI_E_NOT_FOUND;
- hr = MAPI_W_ERRORS_RETURNED;
- }
- if (lHtmlIdx >= 0 && PROP_ID(ulBestMatch) != PROP_ID(PR_HTML)) {
- ptrPropArray[lHtmlIdx].ulPropTag = CHANGE_PROP_TYPE(PR_HTML, PT_ERROR);
- ptrPropArray[lHtmlIdx].Value.err = lpPropTagArray ? MAPI_E_NOT_FOUND : MAPI_E_NOT_ENOUGH_MEMORY;
- hr = MAPI_W_ERRORS_RETURNED;
- }
-
-
-
- if (lHtmlIdx >= 0 && lRtfIdx >= 0 && m_ulBodyType == bodyTypeHTML) {
- LONG lSyncIdx = Util::FindPropInArray(ptrPropTagArray, CHANGE_PROP_TYPE(PR_RTF_IN_SYNC, PT_UNSPECIFIED));
- if (lSyncIdx >= 0) {
- ptrPropArray[lSyncIdx].ulPropTag = PR_RTF_IN_SYNC;
- ptrPropArray[lSyncIdx].Value.b = false;
- }
- }
- } else {
-
- hr = ECMAPIProp::GetProps(lpPropTagArray, ulFlags, &cValues, &~ptrPropArray);
- if (HR_FAILED(hr))
- return hr;
- }
- } else {
-
- hr = ECMAPIProp::GetProps(lpPropTagArray, ulFlags, &cValues, &~ptrPropArray);
- if (HR_FAILED(hr))
- return hr;
- }
- *lpcValues = cValues;
- *lppPropArray = ptrPropArray.release();
- return hr;
- }
- HRESULT ECMessage::GetSyncedBodyProp(ULONG ulPropTag, ULONG ulFlags, void *lpBase, LPSPropValue lpsPropValue)
- {
- HRESULT hr;
- if (ulPropTag == PR_BODY_HTML)
- ulPropTag = PR_HTML;
- hr = HrGetRealProp(ulPropTag, ulFlags, lpBase, lpsPropValue);
- if (HR_FAILED(hr))
- return hr;
- if (PROP_TYPE(lpsPropValue->ulPropTag) == PT_ERROR &&
- lpsPropValue->Value.err == MAPI_E_NOT_FOUND &&
- m_ulBodyType != bodyTypeUnknown)
- {
-
- if ((m_ulBodyType == bodyTypePlain && PROP_ID(ulPropTag) == PROP_ID(PR_BODY)) ||
- (m_ulBodyType == bodyTypeRTF && PROP_ID(ulPropTag) == PROP_ID(PR_RTF_COMPRESSED)) ||
- (m_ulBodyType == bodyTypeHTML && PROP_ID(ulPropTag) == PROP_ID(PR_HTML)))
-
- return hr;
- hr = SyncBody(ulPropTag);
- if (hr != hrSuccess)
- return hr;
-
- hr = HrGetRealProp(ulPropTag, ulFlags, lpBase, lpsPropValue);
- }
- return hr;
- }
- HRESULT ECMessage::SyncBody(ULONG ulPropTag)
- {
- HRESULT hr = hrSuccess;
- const BOOL fModifyOld = fModify;
- if (m_ulBodyType == bodyTypeUnknown) {
-
- hr = MAPI_E_NO_SUPPORT;
- goto exit;
- }
- if (!Util::IsBodyProp(ulPropTag)) {
- hr = MAPI_E_INVALID_PARAMETER;
- goto exit;
- }
-
- fModify = TRUE;
- if (m_ulBodyType == bodyTypePlain) {
- if (PROP_ID(ulPropTag) == PROP_ID(PR_RTF_COMPRESSED))
- hr = SyncPlainToRtf();
- else if (PROP_ID(ulPropTag) == PROP_ID(PR_HTML))
- hr = SyncPlainToHtml();
- } else if (m_ulBodyType == bodyTypeRTF) {
- if (PROP_ID(ulPropTag) == PROP_ID(PR_BODY) || PROP_ID(ulPropTag) == PROP_ID(PR_HTML))
- hr = SyncRtf();
- } else if (m_ulBodyType == bodyTypeHTML) {
- if (PROP_ID(ulPropTag) == PROP_ID(PR_BODY))
- hr = SyncHtmlToPlain();
- else if (PROP_ID(ulPropTag) == PROP_ID(PR_RTF_COMPRESSED))
- hr = SyncHtmlToRtf();
- }
- exit:
- fModify = fModifyOld;
- return hr;
- }
- HRESULT ECMessage::SyncPlainToRtf()
- {
- HRESULT hr = hrSuccess;
- StreamPtr ptrBodyStream;
- StreamPtr ptrCompressedRtfStream;
- StreamPtr ptrUncompressedRtfStream;
- ULARGE_INTEGER emptySize = {{0,0}};
- assert(m_bInhibitSync == false);
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::OpenProperty(PR_BODY_W, &IID_IStream, 0, 0, &~ptrBodyStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~ptrCompressedRtfStream);
- if (hr != hrSuccess)
- goto exit;
-
- hr = ptrCompressedRtfStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = WrapCompressedRTFStream(ptrCompressedRtfStream, MAPI_MODIFY, &~ptrUncompressedRtfStream);
- if (hr != hrSuccess)
- goto exit;
-
- hr = Util::HrTextToRtf(ptrBodyStream, ptrUncompressedRtfStream);
- if (hr != hrSuccess)
- goto exit;
-
- hr = ptrUncompressedRtfStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
-
- hr = ptrCompressedRtfStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
-
- HrSetCleanProperty(PR_RTF_COMPRESSED);
-
- m_setDeletedProps.insert(PR_RTF_COMPRESSED);
- exit:
- m_bInhibitSync = FALSE;
- return hr;
- }
- HRESULT ECMessage::SyncPlainToHtml()
- {
- HRESULT hr = hrSuccess;
- StreamPtr ptrBodyStream;
- unsigned int ulCodePage = 0;
- StreamPtr ptrHtmlStream;
- ULARGE_INTEGER emptySize = {{0,0}};
- assert(m_bInhibitSync == false);
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::OpenProperty(PR_BODY_W, &IID_IStream, 0, 0, &~ptrBodyStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_HTML, &IID_IStream, STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~ptrHtmlStream);
- if (hr != hrSuccess)
- goto exit;
- hr = GetCodePage(&ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHtmlStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = Util::HrTextToHtml(ptrBodyStream, ptrHtmlStream, ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHtmlStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
-
- HrSetCleanProperty(PR_HTML);
-
- m_setDeletedProps.insert(PR_HTML);
- exit:
- m_bInhibitSync = FALSE;
- return hr;
- }
- HRESULT ECMessage::SyncRtf()
- {
- enum eRTFType { RTFTypeOther, RTFTypeFromText, RTFTypeFromHTML};
- HRESULT hr = hrSuccess;
- string strRTF;
- bool bDone = false;
- unsigned int ulCodePage = 0;
- StreamPtr ptrHTMLStream;
- ULONG ulWritten = 0;
- eRTFType rtfType = RTFTypeOther;
- ULARGE_INTEGER emptySize = {{0,0}};
- LARGE_INTEGER moveBegin = {{0,0}};
- assert(m_bInhibitSync == false);
- m_bInhibitSync = TRUE;
- hr = GetRtfData(&strRTF);
- if (hr != hrSuccess)
- goto exit;
- hr = GetCodePage(&ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_HTML, &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~ptrHTMLStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
-
- if (isrtfhtml(strRTF.c_str(), strRTF.size()))
- rtfType = RTFTypeFromHTML;
- else if (isrtftext(strRTF.c_str(), strRTF.size()))
- rtfType = RTFTypeFromText;
- else
- rtfType = RTFTypeOther;
- if (rtfType == RTFTypeOther) {
- BOOL bUpdated;
- hr = RTFSync(&this->m_xMessage, RTF_SYNC_RTF_CHANGED, &bUpdated);
- if (hr == hrSuccess) {
- StreamPtr ptrBodyStream;
- hr = ECMAPIProp::OpenProperty(PR_BODY_W, &IID_IStream, 0, 0, &~ptrBodyStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = Util::HrTextToHtml(ptrBodyStream, ptrHTMLStream, ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
- bDone = true;
- }
- }
- if (!bDone) {
- string strHTML;
- StreamPtr ptrBodyStream;
- switch (rtfType) {
- case RTFTypeOther:
- hr = HrExtractHTMLFromRealRTF(strRTF, strHTML, ulCodePage);
- break;
- case RTFTypeFromText:
- hr = HrExtractHTMLFromTextRTF(strRTF, strHTML, ulCodePage);
- break;
- case RTFTypeFromHTML:
- hr = HrExtractHTMLFromRTF(strRTF, strHTML, ulCodePage);
- break;
- }
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->Write(strHTML.c_str(), strHTML.size(), &ulWritten);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrHTMLStream->Seek(moveBegin, STREAM_SEEK_SET, NULL);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_BODY_W, &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~ptrBodyStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrBodyStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = Util::HrHtmlToText(ptrHTMLStream, ptrBodyStream, ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrBodyStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
- }
- if (rtfType == RTFTypeOther) {
-
- HrSetCleanProperty(PR_HTML);
-
- m_setDeletedProps.insert(PR_HTML);
- } else if (rtfType == RTFTypeFromText) {
-
- HrSetCleanProperty(PR_RTF_COMPRESSED);
- HrSetCleanProperty(PR_HTML);
-
- m_setDeletedProps.insert(PR_RTF_COMPRESSED);
- m_setDeletedProps.insert(PR_HTML);
- } else if (rtfType == RTFTypeFromHTML) {
-
- HrSetCleanProperty(PR_RTF_COMPRESSED);
-
- m_setDeletedProps.insert(PR_RTF_COMPRESSED);
- }
- exit:
- m_bInhibitSync = FALSE;
- return hr;
- }
- HRESULT ECMessage::SyncHtmlToPlain()
- {
- HRESULT hr = hrSuccess;
- StreamPtr ptrHtmlStream;
- StreamPtr ptrBodyStream;
- unsigned int ulCodePage;
- ULARGE_INTEGER emptySize = {{0,0}};
- assert(m_bInhibitSync == FALSE);
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::OpenProperty(PR_HTML, &IID_IStream, 0, 0, &~ptrHtmlStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_BODY_W, &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~ptrBodyStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrBodyStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = GetCodePage(&ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = Util::HrHtmlToText(ptrHtmlStream, ptrBodyStream, ulCodePage);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrBodyStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
- exit:
- m_bInhibitSync = FALSE;
- return hr;
- }
- HRESULT ECMessage::SyncHtmlToRtf()
- {
- HRESULT hr = hrSuccess;
- StreamPtr ptrHtmlStream;
- StreamPtr ptrRtfCompressedStream;
- StreamPtr ptrRtfUncompressedStream;
- unsigned int ulCodePage;
- ULARGE_INTEGER emptySize = {{0,0}};
- assert(!m_bInhibitSync);
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::OpenProperty(PR_HTML, &IID_IStream, 0, 0, &~ptrHtmlStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ECMAPIProp::OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, STGM_TRANSACTED, MAPI_CREATE|MAPI_MODIFY, &~ptrRtfCompressedStream);
- if (hr != hrSuccess)
- goto exit;
- hr = ptrRtfCompressedStream->SetSize(emptySize);
- if (hr != hrSuccess)
- goto exit;
- hr = WrapCompressedRTFStream(ptrRtfCompressedStream, MAPI_MODIFY, &~ptrRtfUncompressedStream);
- if (hr != hrSuccess)
- goto exit;
- hr = GetCodePage(&ulCodePage);
- if (hr != hrSuccess)
- goto exit;
-
- hr = Util::HrHtmlToRtf(ptrHtmlStream, ptrRtfUncompressedStream, ulCodePage);
- if (hr != hrSuccess)
- goto exit;
-
- hr = ptrRtfUncompressedStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
-
- hr = ptrRtfCompressedStream->Commit(0);
- if (hr != hrSuccess)
- goto exit;
-
- HrSetCleanProperty(PR_RTF_COMPRESSED);
-
- m_setDeletedProps.insert(PR_RTF_COMPRESSED);
- exit:
- m_bInhibitSync = FALSE;
- return hr;
- }
- HRESULT ECMessage::GetPropList(ULONG ulFlags, LPSPropTagArray *lppPropTagArray)
- {
- HRESULT hr = hrSuccess;
- const eBodyType ulBodyTypeSaved = m_ulBodyType;
- SPropTagArrayPtr ptrPropTagArray;
- SPropTagArrayPtr ptrPropTagArrayMod;
- bool bHaveBody;
- bool bHaveRtf;
- bool bHaveHtml;
- m_ulBodyType = bodyTypeUnknown;
- hr = ECMAPIProp::GetPropList(ulFlags, &~ptrPropTagArray);
- if (hr != hrSuccess)
- goto exit;
-
-
-
- bHaveBody = Util::FindPropInArray(ptrPropTagArray, CHANGE_PROP_TYPE(PR_BODY, PT_UNSPECIFIED)) >= 0;
- bHaveRtf = Util::FindPropInArray(ptrPropTagArray, PR_RTF_COMPRESSED) >= 0;
- bHaveHtml = Util::FindPropInArray(ptrPropTagArray, PR_HTML) >= 0;
- if ((bHaveBody && bHaveRtf && bHaveHtml) ||
- (!bHaveBody && !bHaveRtf && !bHaveHtml))
- {
-
- *lppPropTagArray = ptrPropTagArray.release();
- goto exit;
- }
-
- hr = ECAllocateBuffer(CbNewSPropTagArray(ptrPropTagArray->cValues + 2), &~ptrPropTagArrayMod);
- if (hr != hrSuccess)
- goto exit;
- ptrPropTagArrayMod->cValues = ptrPropTagArray->cValues;
- memcpy(ptrPropTagArrayMod->aulPropTag, ptrPropTagArray->aulPropTag, sizeof(*ptrPropTagArrayMod->aulPropTag) * ptrPropTagArrayMod->cValues);
-
- if (!bHaveBody)
- ptrPropTagArrayMod->aulPropTag[ptrPropTagArrayMod->cValues++] = (ulFlags & MAPI_UNICODE ? PR_BODY_W : PR_BODY_A);
- if (!bHaveRtf)
- ptrPropTagArrayMod->aulPropTag[ptrPropTagArrayMod->cValues++] = PR_RTF_COMPRESSED;
- if (!bHaveHtml)
- ptrPropTagArrayMod->aulPropTag[ptrPropTagArrayMod->cValues++] = PR_HTML;
- *lppPropTagArray = ptrPropTagArrayMod.release();
- exit:
- m_ulBodyType = ulBodyTypeSaved;
- return hr;
- }
- HRESULT ECMessage::OpenProperty(ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN *lppUnk)
- {
- HRESULT hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- if (lpiid == NULL)
- return MAPI_E_INVALID_PARAMETER;
- if(ulPropTag == PR_MESSAGE_ATTACHMENTS) {
- if(*lpiid == IID_IMAPITable)
- hr = GetAttachmentTable(ulInterfaceOptions, (LPMAPITABLE*)lppUnk);
- } else if(ulPropTag == PR_MESSAGE_RECIPIENTS) {
- if (*lpiid == IID_IMAPITable)
- hr = GetRecipientTable(ulInterfaceOptions, (LPMAPITABLE*)lppUnk);
- } else {
-
- if(ulPropTag == PR_BODY_HTML)
- ulPropTag = PR_HTML;
- hr = ECMAPIProp::OpenProperty(ulPropTag, lpiid, ulInterfaceOptions, ulFlags, lppUnk);
- if (hr == MAPI_E_NOT_FOUND && m_ulBodyType != bodyTypeUnknown && Util::IsBodyProp(ulPropTag)) {
- hr = SyncBody(ulPropTag);
- if (hr != hrSuccess)
- return hr;
-
- hr = ECMAPIProp::OpenProperty(ulPropTag, lpiid, ulInterfaceOptions, ulFlags, lppUnk);
- }
- }
- return hr;
- }
- HRESULT ECMessage::GetAttachmentTable(ULONG ulFlags, LPMAPITABLE *lppTable)
- {
- HRESULT hr = hrSuccess;
- LPSPropValue lpPropID = NULL;
- LPSPropValue lpPropType = NULL;
- memory_ptr<SPropTagArray> lpPropTagArray;
- scoped_rlock lock(m_hMutexMAPIObject);
- if(lstProps == NULL) {
- hr = HrLoadProps();
- if (hr != hrSuccess)
- return hr;
- if (lstProps == nullptr)
- return MAPI_E_CALL_FAILED;
- }
- if (this->lpAttachments == NULL) {
- hr = Util::HrCopyUnicodePropTagArray(ulFlags,
- sPropAttachColumns, &~lpPropTagArray);
- if(hr != hrSuccess)
- return hr;
- hr = ECMemTable::Create(lpPropTagArray, PR_ATTACH_NUM, &this->lpAttachments);
- if(hr != hrSuccess)
- return hr;
-
-
-
- if (!fNew) {
-
- for (const auto &obj : m_sMapiObject->lstChildren) {
- if (obj->ulObjType != MAPI_ATTACH)
- continue;
- if (obj->bDelete)
- continue;
- this->ulNextAttUniqueId = obj->ulUniqueId > this->ulNextAttUniqueId ? obj->ulUniqueId : this->ulNextAttUniqueId;
- ++this->ulNextAttUniqueId;
- ULONG ulProps = obj->lstProperties.size();
- ecmem_ptr<SPropValue> lpProps;
- SPropValue sKeyProp;
- ULONG i;
-
-
- hr = ECAllocateBuffer(sizeof(SPropValue) * (ulProps + 2), &~lpProps);
- if (hr != hrSuccess)
- return hr;
- lpPropID = NULL;
- lpPropType = NULL;
- i = 0;
- for (const auto &pv : obj->lstProperties) {
- pv.CopyToByRef(&lpProps[i]);
- if (lpProps[i].ulPropTag == PR_ATTACH_NUM) {
- lpPropID = &lpProps[i];
- } else if (lpProps[i].ulPropTag == PR_OBJECT_TYPE) {
- lpPropType = &lpProps[i];
- } else if (PROP_ID(lpProps[i].ulPropTag) == PROP_ID(PR_ATTACH_DATA_OBJ)) {
- lpProps[i].ulPropTag = CHANGE_PROP_TYPE(lpProps[i].ulPropTag, PT_ERROR);
- lpProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- } else if (PROP_TYPE(lpProps[i].ulPropTag) == PT_BINARY && lpProps[i].Value.bin.cb > MAX_TABLE_PROPSIZE) {
- lpProps[i].ulPropTag = CHANGE_PROP_TYPE(lpProps[i].ulPropTag, PT_ERROR);
- lpProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- }
- ++i;
- }
- if (lpPropID == NULL) {
- ++ulProps;
- lpPropID = &lpProps[i++];
- }
- lpPropID->ulPropTag = PR_ATTACH_NUM;
- lpPropID->Value.ul = obj->ulUniqueId;
- if (lpPropType == NULL) {
- ++ulProps;
- lpPropType = &lpProps[i++];
- }
- lpPropType->ulPropTag = PR_OBJECT_TYPE;
- lpPropType->Value.ul = MAPI_ATTACH;
- sKeyProp.ulPropTag = PR_EC_HIERARCHYID;
- sKeyProp.Value.ul = obj->ulObjId;
- hr = lpAttachments->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpProps, i);
- if (hr != hrSuccess)
- return hr;
- }
-
- hr = lpAttachments->HrSetClean();
- if (hr != hrSuccess)
- return hr;
- }
- }
- if (this->lpAttachments == nullptr)
- return MAPI_E_CALL_FAILED;
- object_ptr<ECMemTableView> lpView;
- hr = lpAttachments->HrGetView(createLocaleFromName(""),
- ulFlags & MAPI_UNICODE, &~lpView);
- if(hr != hrSuccess)
- return hr;
- return lpView->QueryInterface(IID_IMAPITable,
- reinterpret_cast<void **>(lppTable));
- }
- HRESULT ECMessage::OpenAttach(ULONG ulAttachmentNum, LPCIID lpInterface, ULONG ulFlags, LPATTACH *lppAttach)
- {
- HRESULT hr = hrSuccess;
- object_ptr<ECAttach> lpAttach;
- object_ptr<IECPropStorage> lpParentStorage;
- SPropValue sID;
- ecmem_ptr<SPropValue> lpObjId;
- ULONG ulObjId;
- if(this->lpAttachments == NULL) {
- object_ptr<IMAPITable> lpTable;
- hr = this->GetAttachmentTable(fMapiUnicode, &~lpTable);
- if(hr != hrSuccess)
- return hr;
- }
- if (this->lpAttachments == nullptr)
- return MAPI_E_CALL_FAILED;
- hr = ECAttach::Create(this->GetMsgStore(), MAPI_ATTACH, TRUE, ulAttachmentNum, m_lpRoot, &~lpAttach);
- if(hr != hrSuccess)
- return hr;
- sID.ulPropTag = PR_ATTACH_NUM;
- sID.Value.ul = ulAttachmentNum;
- if (lpAttachments->HrGetRowID(&sID, &~lpObjId) == hrSuccess)
- ulObjId = lpObjId->Value.ul;
- else
- ulObjId = 0;
- hr = this->GetMsgStore()->lpTransport->HrOpenParentStorage(this, ulAttachmentNum, ulObjId, this->lpStorage->GetServerStorage(), &~lpParentStorage);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->HrSetPropStorage(lpParentStorage, TRUE);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->QueryInterface(IID_IAttachment, (void **)lppAttach);
-
- AddChild(lpAttach);
- return hr;
- }
- HRESULT ECMessage::CreateAttach(LPCIID lpInterface, ULONG ulFlags, ULONG *lpulAttachmentNum, LPATTACH *lppAttach)
- {
- return CreateAttach(lpInterface, ulFlags, ECAttachFactory(), lpulAttachmentNum, lppAttach);
- }
- HRESULT ECMessage::CreateAttach(LPCIID lpInterface, ULONG ulFlags, const IAttachFactory &refFactory, ULONG *lpulAttachmentNum, LPATTACH *lppAttach)
- {
- HRESULT hr = hrSuccess;
- SPropValue sID;
- object_ptr<IECPropStorage> lpStorage;
- if(this->lpAttachments == NULL) {
- object_ptr<IMAPITable> lpTable;
- hr = this->GetAttachmentTable(fMapiUnicode, &~lpTable);
- if(hr != hrSuccess)
- return hr;
- }
- if (this->lpAttachments == nullptr)
- return MAPI_E_CALL_FAILED;
- object_ptr<ECAttach> lpAttach;
- hr = refFactory.Create(this->GetMsgStore(), MAPI_ATTACH, TRUE,
- this->ulNextAttUniqueId, m_lpRoot, &~lpAttach);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->HrLoadEmptyProps();
- if(hr != hrSuccess)
- return hr;
- sID.ulPropTag = PR_ATTACH_NUM;
- sID.Value.ul = this->ulNextAttUniqueId;
- hr = this->GetMsgStore()->lpTransport->HrOpenParentStorage(this, this->ulNextAttUniqueId, 0, NULL, &~lpStorage);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->HrSetPropStorage(lpStorage, FALSE);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->SetProps(1, &sID, NULL);
- if(hr != hrSuccess)
- return hr;
- hr = lpAttach->QueryInterface(IID_IAttachment, (void **)lppAttach);
- AddChild(lpAttach);
- *lpulAttachmentNum = sID.Value.ul;
-
- ++this->ulNextAttUniqueId;
- return hr;
- }
- HRESULT ECMessage::DeleteAttach(ULONG ulAttachmentNum, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
- {
- HRESULT hr;
- SPropValue sPropID;
- if(this->lpAttachments == NULL) {
- object_ptr<IMAPITable> lpTable;
- hr = this->GetAttachmentTable(fMapiUnicode, &~lpTable);
- if(hr != hrSuccess)
- return hr;
- }
- if (this->lpAttachments == NULL)
- return MAPI_E_CALL_FAILED;
- sPropID.ulPropTag = PR_ATTACH_NUM;
- sPropID.Value.ul = ulAttachmentNum;
- hr = this->lpAttachments->HrModifyRow(ECKeyTable::TABLE_ROW_DELETE, NULL, &sPropID, 1);
- if (hr !=hrSuccess)
- return hr;
-
- return hrSuccess;
- }
- HRESULT ECMessage::GetRecipientTable(ULONG ulFlags, LPMAPITABLE *lppTable)
- {
- HRESULT hr = hrSuccess;
- memory_ptr<SPropTagArray> lpPropTagArray;
- scoped_rlock lock(m_hMutexMAPIObject);
- if(lstProps == NULL) {
- hr = HrLoadProps();
- if (hr != hrSuccess)
- return hr;
- if (lstProps == nullptr)
- return MAPI_E_CALL_FAILED;
- }
- if (this->lpRecips == NULL) {
- hr = Util::HrCopyUnicodePropTagArray(ulFlags,
- sPropRecipColumns, &~lpPropTagArray);
- if(hr != hrSuccess)
- return hr;
- hr = ECMemTable::Create(lpPropTagArray, PR_ROWID, &lpRecips);
- if(hr != hrSuccess)
- return hr;
-
-
-
-
-
-
- if (!fNew) {
-
- for (const auto &obj : m_sMapiObject->lstChildren) {
-
-
-
-
- if (obj->ulObjType == MAPI_ATTACH)
- continue;
- if (obj->bDelete)
- continue;
- this->ulNextRecipUniqueId = obj->ulUniqueId > this->ulNextRecipUniqueId ? obj->ulUniqueId : this->ulNextRecipUniqueId;
- ++this->ulNextRecipUniqueId;
- ULONG ulProps = obj->lstProperties.size();
- ecmem_ptr<SPropValue> lpProps;
- SPropValue sKeyProp;
- ULONG i = 0;
- LPSPropValue lpPropID = NULL;
- LPSPropValue lpPropObjType = NULL;
-
-
- hr = ECAllocateBuffer(sizeof(SPropValue) * (ulProps + 2), &~lpProps);
- if (hr != hrSuccess)
- return hr;
- for (const auto &pv : obj->lstProperties) {
- pv.CopyToByRef(&lpProps[i]);
- if (lpProps[i].ulPropTag == PR_ROWID)
- lpPropID = &lpProps[i];
- else if (lpProps[i].ulPropTag == PR_OBJECT_TYPE)
- lpPropObjType = &lpProps[i];
- else if (lpProps[i].ulPropTag == PR_EC_CONTACT_ENTRYID)
-
- lpProps[i].ulPropTag = PR_ENTRYID;
- ++i;
- }
- if (lpPropID == NULL) {
- ++ulProps;
- lpPropID = &lpProps[i++];
- }
- lpPropID->ulPropTag = PR_ROWID;
- lpPropID->Value.ul = obj->ulUniqueId;
- if (lpPropObjType == NULL) {
- ++ulProps;
- lpPropObjType = &lpProps[i++];
- }
- lpPropObjType->ulPropTag = PR_OBJECT_TYPE;
- lpPropObjType->Value.ul = obj->ulObjType;
- sKeyProp.ulPropTag = PR_EC_HIERARCHYID;
- sKeyProp.Value.ul = obj->ulObjId;
- hr = lpRecips->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpProps, i);
- if (hr != hrSuccess)
- return hr;
- }
-
- hr = lpRecips->HrSetClean();
- if (hr != hrSuccess)
- return hr;
- }
- }
- object_ptr<ECMemTableView> lpView;
- hr = lpRecips->HrGetView(createLocaleFromName(""),
- ulFlags & MAPI_UNICODE, &~lpView);
- if(hr != hrSuccess)
- return hr;
- return lpView->QueryInterface(IID_IMAPITable,
- reinterpret_cast<void **>(lppTable));
- }
- HRESULT ECMessage::ModifyRecipients(ULONG ulFlags, const ADRLIST *lpMods)
- {
- HRESULT hr = hrSuccess;
- ecmem_ptr<SPropValue> lpRecipProps;
- ULONG cValuesRecipProps = 0;
- SPropValue sPropAdd[2];
- SPropValue sKeyProp;
- unsigned int i = 0;
- if (lpMods == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- if (!fModify)
- return MAPI_E_NO_ACCESS;
-
- if(lpRecips == NULL) {
- object_ptr<IMAPITable> lpTable;
- hr = GetRecipientTable(fMapiUnicode, &~lpTable);
- if(hr != hrSuccess)
- return hr;
- }
- if (lpRecips == nullptr)
- return MAPI_E_CALL_FAILED;
- if(ulFlags == 0) {
- hr = lpRecips->HrDeleteAll();
- if(hr != hrSuccess)
- return hr;
- ulNextRecipUniqueId = 0;
- }
- for (i = 0; i < lpMods->cEntries; ++i) {
- if(ulFlags & MODRECIP_ADD || ulFlags == 0) {
-
- sPropAdd[0].ulPropTag = PR_ROWID;
- sPropAdd[0].Value.ul = this->ulNextRecipUniqueId++;
-
- sPropAdd[1].ulPropTag = PR_INSTANCE_KEY;
- sPropAdd[1].Value.bin.cb = sizeof(ULONG);
- sPropAdd[1].Value.bin.lpb = (unsigned char *)&sPropAdd[0].Value.ul;
- hr = Util::HrMergePropertyArrays(lpMods->aEntries[i].rgPropVals, lpMods->aEntries[i].cValues, sPropAdd, 2, &+lpRecipProps, &cValuesRecipProps);
- if (hr != hrSuccess)
- continue;
- sKeyProp.ulPropTag = PR_EC_HIERARCHYID;
- sKeyProp.Value.ul = 0;
-
- hr = lpRecips->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpRecipProps, cValuesRecipProps);
- lpRecipProps.reset();
- } else if(ulFlags & MODRECIP_MODIFY) {
-
- hr = lpRecips->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, NULL, lpMods->aEntries[i].rgPropVals, lpMods->aEntries[i].cValues);
- } else if(ulFlags & MODRECIP_REMOVE) {
- hr = lpRecips->HrModifyRow(ECKeyTable::TABLE_ROW_DELETE, NULL, lpMods->aEntries[i].rgPropVals, lpMods->aEntries[i].cValues);
- }
- if(hr != hrSuccess)
- return hr;
- }
- m_bRecipsDirty = TRUE;
- return hrSuccess;
- }
- HRESULT ECMessage::SubmitMessage(ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- SizedSPropTagArray(1, sPropTagArray);
- ULONG cValue = 0;
- ULONG ulRepCount = 0;
- ULONG ulPreprocessFlags = 0;
- ULONG ulSubmitFlag = 0;
- ecmem_ptr<SPropValue> lpsPropArray;
- object_ptr<IMAPITable> lpRecipientTable;
- ecmem_ptr<SPropValue> lpRecip;
- ULONG cRecip = 0;
- SizedADRLIST(1, sRowSetRecip);
- SPropValue sPropResponsibility;
- FILETIME ft;
-
- sPropTagArray.cValues = 1;
- sPropTagArray.aulPropTag[0] = PR_MESSAGE_FLAGS;
- hr = ECMAPIProp::GetProps(sPropTagArray, 0, &cValue, &~lpsPropArray);
- if(HR_FAILED(hr))
- return hr;
- if(lpsPropArray->ulPropTag == PR_MESSAGE_FLAGS) {
-
-
- lpsPropArray->Value.ul |= MSGFLAG_UNSENT;
- hr = this->SetProps(1, lpsPropArray, NULL);
- if(hr != hrSuccess)
- return hr;
- }
-
- hr = this->GetRecipientTable(fMapiUnicode, &~lpRecipientTable);
- if(hr != hrSuccess)
- return hr;
-
- hr = lpRecipientTable->GetRowCount(0, &ulRepCount);
- if(hr != hrSuccess)
- return hr;
- if (ulRepCount == 0)
- return MAPI_E_NO_RECIPIENTS;
-
- while(TRUE){
- rowset_ptr lpsRow;
- hr = lpRecipientTable->QueryRows(1, 0, &~lpsRow);
- if (hr != hrSuccess)
- return hr;
- if (lpsRow->cRows == 0)
- break;
- sPropResponsibility.ulPropTag = PR_RESPONSIBILITY;
- sPropResponsibility.Value.b = FALSE;
-
- hr = Util::HrAddToPropertyArray(lpsRow->aRow[0].lpProps,
- lpsRow->aRow[0].cValues, &sPropResponsibility, &+lpRecip, &cRecip);
- if(hr != hrSuccess)
- return hr;
- sRowSetRecip.cEntries = 1;
- sRowSetRecip.aEntries[0].rgPropVals = lpRecip;
- sRowSetRecip.aEntries[0].cValues = cRecip;
- if(lpsRow->aRow[0].cValues > 1){
- hr = this->ModifyRecipients(MODRECIP_MODIFY, sRowSetRecip);
- if (hr != hrSuccess)
- return hr;
- }
- lpRecip.reset();
- }
-
- GetSystemTimeAsFileTime(&ft);
- hr = ECAllocateBuffer(sizeof(SPropValue) * 2, &~lpsPropArray);
- if (hr != hrSuccess)
- return hr;
- lpsPropArray[0].ulPropTag = PR_CLIENT_SUBMIT_TIME;
- lpsPropArray[0].Value.ft = ft;
- lpsPropArray[1].ulPropTag = PR_MESSAGE_DELIVERY_TIME;
- lpsPropArray[1].Value.ft = ft;
- hr = SetProps(2, lpsPropArray, NULL);
- if (hr != hrSuccess)
- return hr;
-
- hr = this->GetMsgStore()->lpSupport->ExpandRecips(&this->m_xMessage, &ulPreprocessFlags);
- if (hr != hrSuccess)
- return hr;
- if (this->GetMsgStore()->IsOfflineStore())
- ulPreprocessFlags |= NEEDS_SPOOLER;
-
- if (ulPreprocessFlags & NEEDS_PREPROCESSING)
- ulSubmitFlag = SUBMITFLAG_PREPROCESS;
- if (ulPreprocessFlags & NEEDS_SPOOLER)
- ulSubmitFlag = 0L;
- hr = ECAllocateBuffer(sizeof(SPropValue), &~lpsPropArray);
- if (hr != hrSuccess)
- return hr;
- lpsPropArray[0].ulPropTag = PR_SUBMIT_FLAGS;
- lpsPropArray[0].Value.l = ulSubmitFlag;
- hr = SetProps(1, lpsPropArray, NULL);
- if (hr != hrSuccess)
- return hr;
-
- hr = SaveChanges(KEEP_OPEN_READWRITE);
- if(hr != hrSuccess)
- return hr;
-
-
- if(ulPreprocessFlags & NEEDS_SPOOLER) {
- TRACE_MAPI(TRACE_ENTRY, "Submitting through local queue, flags", "%d", ulPreprocessFlags);
-
- hr = this->GetMsgStore()->lpTransport->HrSubmitMessage(this->m_cbEntryId, this->m_lpEntryId, EC_SUBMIT_LOCAL);
- } else {
- TRACE_MAPI(TRACE_ENTRY, "Submitting through master queue, flags", "%d", ulPreprocessFlags);
-
- hr = this->GetMsgStore()->lpTransport->HrSubmitMessage(this->m_cbEntryId, this->m_lpEntryId, EC_SUBMIT_MASTER | EC_SUBMIT_DOSENTMAIL);
- }
- return hr;
- }
- HRESULT ECMessage::SetReadFlag(ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- ecmem_ptr<SPropValue> lpReadReceiptRequest;
- memory_ptr<SPropValue> lpPropFlags;
- memory_ptr<SPropValue> lpsPropUserName;
- SPropValue sProp;
- object_ptr<IMAPIFolder> lpRootFolder;
- object_ptr<IMessage> lpNewMessage, lpThisMessage;
- ULONG ulObjType = 0;
- ULONG cValues = 0;
- ULONG cbStoreID = 0;
- memory_ptr<ENTRYID> lpStoreID;
- object_ptr<IMsgStore> lpDefMsgStore;
- if((ulFlags &~ (CLEAR_READ_FLAG | CLEAR_NRN_PENDING | CLEAR_RN_PENDING | GENERATE_RECEIPT_ONLY | MAPI_DEFERRED_ERRORS | SUPPRESS_RECEIPT)) != 0 ||
- (ulFlags & (SUPPRESS_RECEIPT | CLEAR_READ_FLAG)) == (SUPPRESS_RECEIPT | CLEAR_READ_FLAG)||
- (ulFlags & (SUPPRESS_RECEIPT | CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY)) == (SUPPRESS_RECEIPT | CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY) ||
- (ulFlags & (CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY)) == (CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY) )
- return MAPI_E_INVALID_PARAMETER;
- if (m_lpParentID != nullptr)
-
- return hrSuccess;
-
- static constexpr const SizedSPropTagArray(2, proptags) =
- {2, {PR_MESSAGE_FLAGS, PR_READ_RECEIPT_REQUESTED}};
- hr = ECMAPIProp::GetProps(proptags, 0, &cValues, &~lpReadReceiptRequest);
- if(hr == hrSuccess && (!(ulFlags&(SUPPRESS_RECEIPT|CLEAR_READ_FLAG | CLEAR_NRN_PENDING | CLEAR_RN_PENDING)) || (ulFlags&GENERATE_RECEIPT_ONLY )) &&
- lpReadReceiptRequest[1].Value.b == TRUE && ((lpReadReceiptRequest[0].Value.ul & MSGFLAG_RN_PENDING) || (lpReadReceiptRequest[0].Value.ul & MSGFLAG_NRN_PENDING)))
- {
- hr = QueryInterface(IID_IMessage, &~lpThisMessage);
- if (hr != hrSuccess)
- return hr;
- if((ulFlags & (GENERATE_RECEIPT_ONLY | SUPPRESS_RECEIPT)) == (GENERATE_RECEIPT_ONLY | SUPPRESS_RECEIPT) )
- {
- sProp.ulPropTag = PR_READ_RECEIPT_REQUESTED;
- sProp.Value.b = FALSE;
- hr = HrSetOneProp(lpThisMessage, &sProp);
- if (hr != hrSuccess)
- return hr;
- hr = lpThisMessage->SaveChanges(KEEP_OPEN_READWRITE);
- if (hr != hrSuccess)
- return hr;
- }else {
-
- hr = HrGetOneProp(&GetMsgStore()->m_xMsgStore, PR_USER_NAME, &~lpsPropUserName);
- if (hr != hrSuccess)
- return hr;
- hr = GetMsgStore()->CreateStoreEntryID(nullptr, lpsPropUserName->Value.LPSZ, fMapiUnicode, &cbStoreID, &~lpStoreID);
- if (hr != hrSuccess)
- return hr;
- hr = GetMsgStore()->lpSupport->OpenEntry(cbStoreID, lpStoreID, nullptr, MAPI_MODIFY, &ulObjType, &~lpDefMsgStore);
- if (hr != hrSuccess)
- return hr;
-
- hr = lpDefMsgStore->OpenEntry(0, nullptr, nullptr, MAPI_MODIFY, &ulObjType, &~lpRootFolder);
- if (hr != hrSuccess)
- return hr;
- hr = lpRootFolder->CreateMessage(nullptr, 0, &~lpNewMessage);
- if (hr != hrSuccess)
- return hr;
- hr = ClientUtil::ReadReceipt(0, lpThisMessage, &+lpNewMessage);
- if(hr != hrSuccess)
- return hr;
- hr = lpNewMessage->SubmitMessage(FORCE_SUBMIT);
- if(hr != hrSuccess)
- return hr;
-
-
- ulFlags |= CLEAR_NRN_PENDING | CLEAR_RN_PENDING;
- }
- }
- hr = this->GetMsgStore()->lpTransport->HrSetReadFlag(this->m_cbEntryId, this->m_lpEntryId, ulFlags, 0);
- if(hr != hrSuccess)
- return hr;
-
- hr = MAPIAllocateBuffer(sizeof(SPropValue), &~lpPropFlags);
- if (hr != hrSuccess)
- return hr;
- hr = HrGetRealProp(PR_MESSAGE_FLAGS, ulFlags, lpPropFlags, lpPropFlags);
- if(hr != hrSuccess)
- return hr;
- if (ulFlags & CLEAR_READ_FLAG)
- lpPropFlags->Value.ul &= ~MSGFLAG_READ;
- else
- lpPropFlags->Value.ul |= MSGFLAG_READ;
- return HrSetRealProp(lpPropFlags);
- }
- HRESULT ECMessage::SyncRecips()
- {
- HRESULT hr = hrSuccess;
- std::wstring wstrTo;
- std::wstring wstrCc;
- std::wstring wstrBcc;
- SPropValue sPropRecip;
- object_ptr<IMAPITable> lpTable;
- static constexpr const SizedSPropTagArray(2, sPropDisplay) =
- {2, {PR_RECIPIENT_TYPE, PR_DISPLAY_NAME_W}};
- if (this->lpRecips) {
- hr = GetRecipientTable(fMapiUnicode, &~lpTable);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->SetColumns(sPropDisplay, 0);
- while (TRUE) {
- rowset_ptr lpRows;
- hr = lpTable->QueryRows(1, 0, &~lpRows);
- if (hr != hrSuccess || lpRows->cRows != 1)
- break;
- if (lpRows->aRow[0].lpProps[0].ulPropTag == PR_RECIPIENT_TYPE && lpRows->aRow[0].lpProps[0].Value.ul == MAPI_TO) {
- if (lpRows->aRow[0].lpProps[1].ulPropTag == PR_DISPLAY_NAME_W) {
- if (wstrTo.length() > 0)
- wstrTo += L"; ";
- wstrTo += lpRows->aRow[0].lpProps[1].Value.lpszW;
- }
- }
- else if (lpRows->aRow[0].lpProps[0].ulPropTag == PR_RECIPIENT_TYPE && lpRows->aRow[0].lpProps[0].Value.ul == MAPI_CC) {
- if (lpRows->aRow[0].lpProps[1].ulPropTag == PR_DISPLAY_NAME_W) {
- if (wstrCc.length() > 0)
- wstrCc += L"; ";
- wstrCc += lpRows->aRow[0].lpProps[1].Value.lpszW;
- }
- }
- else if (lpRows->aRow[0].lpProps[0].ulPropTag == PR_RECIPIENT_TYPE && lpRows->aRow[0].lpProps[0].Value.ul == MAPI_BCC) {
- if (lpRows->aRow[0].lpProps[1].ulPropTag == PR_DISPLAY_NAME_W) {
- if (wstrBcc.length() > 0)
- wstrBcc += L"; ";
- wstrBcc += lpRows->aRow[0].lpProps[1].Value.lpszW;
- }
- }
- }
- sPropRecip.ulPropTag = PR_DISPLAY_TO_W;
- sPropRecip.Value.lpszW = (WCHAR *)wstrTo.c_str();
- HrSetRealProp(&sPropRecip);
- sPropRecip.ulPropTag = PR_DISPLAY_CC_W;
- sPropRecip.Value.lpszW = (WCHAR *)wstrCc.c_str();
- HrSetRealProp(&sPropRecip);
- sPropRecip.ulPropTag = PR_DISPLAY_BCC_W;
- sPropRecip.Value.lpszW = (WCHAR *)wstrBcc.c_str();
- HrSetRealProp(&sPropRecip);
- }
- m_bRecipsDirty = FALSE;
- return hr;
- }
- HRESULT ECMessage::SaveRecips()
- {
- HRESULT hr = hrSuccess;
- rowset_ptr lpRowSet;
- ecmem_ptr<SPropValue> lpObjIDs;
- ecmem_ptr<ULONG> lpulStatus;
- unsigned int i = 0,
- j = 0;
- ULONG ulRealObjType;
- scoped_rlock lock(m_hMutexMAPIObject);
-
- hr = lpRecips->HrGetAllWithStatus(&~lpRowSet, &~lpObjIDs, &~lpulStatus);
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < lpRowSet->cRows; ++i) {
- MAPIOBJECT *mo = NULL;
-
- auto lpObjType = PCpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_OBJECT_TYPE);
- if(lpObjType != NULL)
- ulRealObjType = lpObjType->Value.ul;
- else
- ulRealObjType = MAPI_MAILUSER;
- auto lpRowId = PCpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_ROWID);
- if (!lpRowId) {
- assert(lpRowId != NULL);
- continue;
- }
- AllocNewMapiObject(lpRowId->Value.ul, lpObjIDs[i].Value.ul, ulRealObjType, &mo);
-
- auto lpEntryID = PpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_ENTRYID);
- if(lpEntryID)
- lpEntryID->ulPropTag = PR_EC_CONTACT_ENTRYID;
- if (lpulStatus[i] == ECROW_MODIFIED || lpulStatus[i] == ECROW_ADDED) {
- mo->bChanged = true;
- for (j = 0; j < lpRowSet->aRow[i].cValues; ++j)
- if(PROP_TYPE(lpRowSet->aRow[i].lpProps[j].ulPropTag) != PT_NULL) {
- mo->lstModified.push_back(ECProperty(&lpRowSet->aRow[i].lpProps[j]));
-
-
- mo->lstProperties.push_back(ECProperty(&lpRowSet->aRow[i].lpProps[j]));
- }
- } else if (lpulStatus[i] == ECROW_DELETED) {
- mo->bDelete = true;
- } else {
-
- for (j = 0; j < lpRowSet->aRow[i].cValues; ++j)
- if(PROP_TYPE(lpRowSet->aRow[i].lpProps[j].ulPropTag) != PT_NULL)
- mo->lstProperties.push_back(ECProperty(&lpRowSet->aRow[i].lpProps[j]));
- }
-
- auto iterSObj = m_sMapiObject->lstChildren.find(mo);
- if (iterSObj != m_sMapiObject->lstChildren.cend()) {
- FreeMapiObject(*iterSObj);
- m_sMapiObject->lstChildren.erase(iterSObj);
- }
- m_sMapiObject->lstChildren.insert(mo);
- }
- return lpRecips->HrSetClean();
- }
- void ECMessage::RecursiveMarkDelete(MAPIOBJECT *lpObj) {
- lpObj->bDelete = true;
- lpObj->lstDeleted.clear();
- lpObj->lstAvailable.clear();
- lpObj->lstModified.clear();
- lpObj->lstProperties.clear();
- for (const auto &obj : lpObj->lstChildren)
- RecursiveMarkDelete(obj);
- }
- BOOL ECMessage::HasAttachment()
- {
- HRESULT hr = hrSuccess;
- BOOL bRet = TRUE;
- ECMapiObjects::const_iterator iterObjects;
- scoped_rlock lock(m_hMutexMAPIObject);
- if(lstProps == NULL) {
- hr = HrLoadProps();
- if (hr != hrSuccess)
- goto exit;
- if(lstProps == NULL) {
- hr = MAPI_E_CALL_FAILED;
- goto exit;
- }
- }
- for (iterObjects = m_sMapiObject->lstChildren.cbegin();
- iterObjects != m_sMapiObject->lstChildren.cend(); ++iterObjects)
- if ((*iterObjects)->ulObjType == MAPI_ATTACH)
- break;
- bRet = iterObjects != m_sMapiObject->lstChildren.cend();
- exit:
- if(hr != hrSuccess)
- bRet = FALSE;
- return bRet;
- }
- HRESULT ECMessage::SyncAttachments()
- {
- HRESULT hr = hrSuccess;
- rowset_ptr lpRowSet;
- ecmem_ptr<SPropValue> lpObjIDs;
- ecmem_ptr<ULONG> lpulStatus;
- unsigned int i = 0;
- scoped_rlock lock(m_hMutexMAPIObject);
-
-
- hr = lpAttachments->HrGetAllWithStatus(&~lpRowSet, &~lpObjIDs, &~lpulStatus);
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < lpRowSet->cRows; ++i) {
- if (lpulStatus[i] != ECROW_DELETED)
- continue;
- auto lpObjType = PCpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_OBJECT_TYPE);
- if(lpObjType == NULL || lpObjType->Value.ul != MAPI_ATTACH)
- continue;
- auto lpAttachNum = PCpropFindProp(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues, PR_ATTACH_NUM);
- if (!lpAttachNum) {
- assert(lpAttachNum != NULL);
- continue;
- }
-
- MAPIOBJECT find(lpObjType->Value.ul, lpAttachNum->Value.ul);
- auto iterSObj = m_sMapiObject->lstChildren.find(&find);
- if (iterSObj != m_sMapiObject->lstChildren.cend())
- RecursiveMarkDelete(*iterSObj);
- }
- return lpAttachments->HrSetClean();
- }
- HRESULT ECMessage::UpdateTable(ECMemTable *lpTable, ULONG ulObjType, ULONG ulObjKeyProp) {
- HRESULT hr = hrSuccess;
- SPropValue sKeyProp;
- SPropValue sUniqueProp;
- ULONG cAllValues = 0;
- ULONG cValues = 0;
- ULONG ulProps = 0;
- ULONG i = 0;
- scoped_rlock lock(m_hMutexMAPIObject);
- if (m_sMapiObject == nullptr)
- return MAPI_E_INVALID_PARAMETER;
-
- for (const auto &obj : m_sMapiObject->lstChildren) {
- memory_ptr<SPropValue> lpProps, lpNewProps, lpAllProps;
- if (obj->ulObjType != ulObjType)
- continue;
- sUniqueProp.ulPropTag = ulObjKeyProp;
- sUniqueProp.Value.ul = obj->ulUniqueId;
- sKeyProp.ulPropTag = PR_EC_HIERARCHYID;
- sKeyProp.Value.ul = obj->ulObjId;
- hr = lpTable->HrUpdateRowID(&sKeyProp, &sUniqueProp, 1);
- if (hr != hrSuccess)
- return hr;
-
- ulProps = obj->lstProperties.size();
- if (ulProps == 0)
- continue;
-
- hr = lpTable->HrGetRowData(&sUniqueProp, &cValues, &~lpProps);
- if (hr != hrSuccess)
- return hr;
-
- hr = MAPIAllocateBuffer(sizeof(SPropValue) * ulProps, &~lpNewProps);
- if (hr != hrSuccess)
- return hr;
- i = 0;
- for (const auto &pv : obj->lstProperties) {
- pv.CopyToByRef(&lpNewProps[i]);
- if (PROP_ID(lpNewProps[i].ulPropTag) == PROP_ID(PR_ATTACH_DATA_OBJ)) {
- lpNewProps[i].ulPropTag = CHANGE_PROP_TYPE(lpNewProps[i].ulPropTag, PT_ERROR);
- lpNewProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- } else if (PROP_TYPE(lpNewProps[i].ulPropTag) == PT_BINARY && lpNewProps[i].Value.bin.cb > MAX_TABLE_PROPSIZE) {
- lpNewProps[i].ulPropTag = CHANGE_PROP_TYPE(lpNewProps[i].ulPropTag, PT_ERROR);
- lpNewProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- }
- ++i;
- }
- hr = Util::HrMergePropertyArrays(lpProps, cValues, lpNewProps, ulProps, &~lpAllProps, &cAllValues);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->HrModifyRow(ECKeyTable::TABLE_ROW_MODIFY, &sKeyProp, lpAllProps, cAllValues);
- if (hr != hrSuccess)
- return hr;
- }
- return lpTable->HrSetClean();
- }
- HRESULT ECMessage::SaveChanges(ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- ecmem_ptr<SPropValue> lpsPropMessageFlags;
- ULONG cValues = 0;
- scoped_rlock lock(m_hMutexMAPIObject);
-
- if (!fModify)
- return MAPI_E_NO_ACCESS;
-
- if (this->lstProps == NULL)
- return hr;
- assert(m_sMapiObject != NULL);
- if (this->lpRecips) {
- hr = SaveRecips();
- if (hr != hrSuccess)
- return hr;
-
- SyncRecips();
- }
- if (this->lpAttachments) {
-
- hr = SyncAttachments();
- if (hr != hrSuccess)
- return hr;
- }
-
- if (fNew && this->GetMsgStore()->IsSpooler() == TRUE) {
- static constexpr const SizedSPropTagArray(1, proptag) = {1, {PR_MESSAGE_FLAGS}};
- hr = ECMAPIProp::GetProps(proptag, 0, &cValues, &~lpsPropMessageFlags);
- if(hr != hrSuccess)
- return hr;
- lpsPropMessageFlags->ulPropTag = PR_MESSAGE_FLAGS;
- lpsPropMessageFlags->Value.l &= ~(MSGFLAG_READ|MSGFLAG_UNSENT);
- lpsPropMessageFlags->Value.l |= MSGFLAG_UNMODIFIED;
- hr = SetProps(1, lpsPropMessageFlags, NULL);
- if(hr != hrSuccess)
- return hr;
- }
-
- assert(!m_bInhibitSync);
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::SaveChanges(ulFlags);
- m_bInhibitSync = FALSE;
- m_bExplicitSubjectPrefix = FALSE;
- if(hr != hrSuccess)
- return hr;
-
- if (m_sMapiObject && m_bEmbedded == false) {
- if (lpRecips) {
- hr = UpdateTable(lpRecips, MAPI_MAILUSER, PR_ROWID);
- if(hr != hrSuccess)
- return hr;
- hr = UpdateTable(lpRecips, MAPI_DISTLIST, PR_ROWID);
- if(hr != hrSuccess)
- return hr;
- }
- if (lpAttachments) {
- hr = UpdateTable(lpAttachments, MAPI_ATTACH, PR_ATTACH_NUM);
- if(hr != hrSuccess)
- return hr;
- }
- }
- return hrSuccess;
- }
- HRESULT ECMessage::SyncSubject()
- {
- HRESULT hr = hrSuccess;
- HRESULT hr1 = hrSuccess;
- HRESULT hr2 = hrSuccess;
- BOOL bDirtySubject = FALSE;
- BOOL bDirtySubjectPrefix = FALSE;
- ecmem_ptr<SPropValue> lpPropArray;
- ULONG cValues = 0;
- WCHAR* lpszColon = NULL;
- WCHAR* lpszEnd = NULL;
- int sizePrefix1 = 0;
- static constexpr const SizedSPropTagArray(2, sPropSubjects) =
- {2, {PR_SUBJECT_W, PR_SUBJECT_PREFIX_W}};
- hr1 = IsPropDirty(CHANGE_PROP_TYPE(PR_SUBJECT, PT_UNSPECIFIED), &bDirtySubject);
- hr2 = IsPropDirty(CHANGE_PROP_TYPE(PR_SUBJECT_PREFIX, PT_UNSPECIFIED), &bDirtySubjectPrefix);
-
- if( (hr1 != hrSuccess && hr2 != hrSuccess) || (hr1 == hr2 && bDirtySubject == FALSE && bDirtySubjectPrefix == FALSE) )
- return hr;
-
- if(hr1 != hrSuccess && hr2 == hrSuccess)
- return HrDeleteRealProp(CHANGE_PROP_TYPE(PR_SUBJECT_PREFIX, PT_UNSPECIFIED), FALSE);
-
- hr = ECMAPIProp::GetProps(sPropSubjects, 0, &cValues, &~lpPropArray);
- if(HR_FAILED(hr))
- return hr;
- if(lpPropArray[0].ulPropTag == PR_SUBJECT_W)
- lpszColon = wcschr(lpPropArray[0].Value.lpszW, L':');
- if(lpszColon == NULL) {
- //Set emtpy PR_SUBJECT_PREFIX
- lpPropArray[1].ulPropTag = PR_SUBJECT_PREFIX_W;
- lpPropArray[1].Value.lpszW = const_cast<wchar_t *>(L"");
- hr = HrSetRealProp(&lpPropArray[1]);
- } else {
- sizePrefix1 = lpszColon - lpPropArray[0].Value.lpszW + 1;
- // synchronized PR_SUBJECT_PREFIX
- lpPropArray[1].ulPropTag = PR_SUBJECT_PREFIX_W; // If PROP_TYPE(lpPropArray[1].ulPropTag) == PT_ERROR, we lose that info here.
- if (sizePrefix1 > 1 && sizePrefix1 <= 4)
- {
- if (lpPropArray[0].Value.lpszW[sizePrefix1] == L' ')
- lpPropArray[0].Value.lpszW[sizePrefix1+1] = 0; // with space "fwd: "
- else
- lpPropArray[0].Value.lpszW[sizePrefix1] = 0; // "fwd:"
- assert(lpPropArray[0].Value.lpszW[sizePrefix1-1] == L':');
- lpPropArray[1].Value.lpszW = lpPropArray[0].Value.lpszW;
- wcstol(lpPropArray[1].Value.lpszW, &lpszEnd, 10);
- if (lpszEnd == lpszColon)
- lpPropArray[1].Value.lpszW = const_cast<wchar_t *>(L""); // skip a numeric prefix
- } else
- lpPropArray[1].Value.lpszW = const_cast<wchar_t *>(L""); // emtpy PR_SUBJECT_PREFIX
- hr = HrSetRealProp(&lpPropArray[1]);
- // PR_SUBJECT_PREFIX and PR_SUBJECT are synchronized
- }
- return hr;
- }
- // Override IMAPIProp::SetProps
- HRESULT ECMessage::SetProps(ULONG cValues, const SPropValue *lpPropArray,
- SPropProblemArray **lppProblems)
- {
- HRESULT hr = hrSuccess;
- const SPropValue *pvalSubject, *pvalSubjectPrefix;
- const SPropValue *pvalRtf, *pvalHtml, *pvalBody;
- const BOOL bInhibitSyncOld = m_bInhibitSync;
- m_bInhibitSync = TRUE; // We want to override the logic in ECMessage::HrSetRealProp.
- // Send to IMAPIProp first
- hr = ECMAPIProp::SetProps(cValues, lpPropArray, lppProblems);
- if (hr != hrSuccess)
- goto exit;
- m_bInhibitSync = bInhibitSyncOld;
- /* We only sync the subject (like a PST does) in the following conditions:
- * 1) PR_SUBJECT is modified, and PR_SUBJECT_PREFIX was not set
- * 2) PR_SUBJECT is modified, and PR_SUBJECT_PREFIX was modified by a previous SyncSubject() call
- * If the caller ever does a SetProps on the PR_SUBJECT_PREFIX itself, we must never touch it ourselves again, until SaveChanges().
- */
- pvalSubject = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_SUBJECT, PT_UNSPECIFIED));
- pvalSubjectPrefix = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_SUBJECT_PREFIX, PT_UNSPECIFIED));
- if (pvalSubjectPrefix)
- m_bExplicitSubjectPrefix = TRUE;
- if (pvalSubject && m_bExplicitSubjectPrefix == FALSE)
- SyncSubject();
- // Now, sync RTF
- pvalRtf = PCpropFindProp(lpPropArray, cValues, PR_RTF_COMPRESSED);
- pvalHtml = PCpropFindProp(lpPropArray, cValues, PROP_TAG(PT_UNSPECIFIED, PROP_ID(PR_BODY_HTML)) );
- pvalBody = PCpropFindProp(lpPropArray, cValues, PROP_TAG(PT_UNSPECIFIED, PROP_ID(PR_BODY)) );
- // IF the user sets both the body and the RTF, assume RTF overrides
- if (pvalRtf) {
- m_ulBodyType = bodyTypeUnknown; // Make sure GetBodyType doesn't use the cached value
- GetBodyType(&m_ulBodyType);
- SyncRtf();
- } else if (pvalHtml) {
- m_ulBodyType = bodyTypeHTML;
- SyncHtmlToPlain();
- HrDeleteRealProp(PR_RTF_COMPRESSED, FALSE);
- } else if(pvalBody) {
- m_ulBodyType = bodyTypePlain;
- HrDeleteRealProp(PR_RTF_COMPRESSED, FALSE);
- HrDeleteRealProp(PR_HTML, FALSE);
- }
- exit:
- m_bInhibitSync = bInhibitSyncOld;
- return hr;
- }
- HRESULT ECMessage::DeleteProps(const SPropTagArray *lpPropTagArray,
- SPropProblemArray **lppProblems)
- {
- HRESULT hr;
- SizedSPropTagArray(1, sSubjectPrefix) =
- {1, {CHANGE_PROP_TYPE(PR_SUBJECT_PREFIX, PT_UNSPECIFIED)}};
-
- hr = ECMAPIProp::DeleteProps(lpPropTagArray, lppProblems);
- if (FAILED(hr))
- return hr;
-
- if (m_bExplicitSubjectPrefix == FALSE && Util::FindPropInArray(lpPropTagArray, CHANGE_PROP_TYPE(PR_SUBJECT, PT_UNSPECIFIED)) >= 0)
- ECMAPIProp::DeleteProps(sSubjectPrefix, NULL);
-
- if (m_bExplicitSubjectPrefix == TRUE && Util::FindPropInArray(lpPropTagArray, CHANGE_PROP_TYPE(PR_SUBJECT_PREFIX, PT_UNSPECIFIED)) >= 0)
- m_bExplicitSubjectPrefix = FALSE;
- return hrSuccess;
- }
- HRESULT ECMessage::TableRowGetProp(void* lpProvider, struct propVal *lpsPropValSrc, LPSPropValue lpsPropValDst, void **lpBase, ULONG ulType)
- {
- HRESULT hr = hrSuccess;
- auto lpMsgStore = static_cast<ECMsgStore *>(lpProvider);
- if (lpsPropValSrc->ulPropTag != PR_SOURCE_KEY)
- return MAPI_E_NOT_FOUND;
- if ((lpMsgStore->m_ulProfileFlags & EC_PROFILE_FLAGS_TRUNCATE_SOURCEKEY) &&
- lpsPropValSrc->Value.bin->__size > 22) {
- lpsPropValSrc->Value.bin->__size = 22;
- lpsPropValSrc->Value.bin->__ptr[lpsPropValSrc->Value.bin->__size-1] |= 0x80;
- hr = CopySOAPPropValToMAPIPropVal(lpsPropValDst, lpsPropValSrc, lpBase);
- } else {
- hr = MAPI_E_NOT_FOUND;
- }
- return hr;
- }
- HRESULT ECMessage::GetPropHandler(ULONG ulPropTag, void* lpProvider, ULONG ulFlags, LPSPropValue lpsPropValue, void *lpParam, void *lpBase)
- {
- HRESULT hr = hrSuccess;
- unsigned int ulSize = 0;
- LPBYTE lpData = NULL;
- auto lpMessage = static_cast<ECMessage *>(lpParam);
- switch(PROP_ID(ulPropTag)) {
- case PROP_ID(PR_RTF_IN_SYNC):
- lpsPropValue->ulPropTag = PR_RTF_IN_SYNC;
- lpsPropValue->Value.ul = TRUE;
- break;
- case PROP_ID(PR_HASATTACH):
- lpsPropValue->ulPropTag = PR_HASATTACH;
- lpsPropValue->Value.b = lpMessage->HasAttachment();
- break;
- case PROP_ID(PR_ASSOCIATED):
- hr = lpMessage->HrGetRealProp(PR_MESSAGE_FLAGS, ulFlags, lpBase, lpsPropValue);
- if(hr != hrSuccess) {
- hr = hrSuccess;
- lpsPropValue->ulPropTag = PR_ASSOCIATED;
- lpsPropValue->Value.b = false;
- } else {
- lpsPropValue->ulPropTag = PR_ASSOCIATED;
- lpsPropValue->Value.b = !!(lpsPropValue->Value.ul & MSGFLAG_ASSOCIATED);
- }
- break;
- case PROP_ID(PR_MESSAGE_FLAGS):
- {
- hr = lpMessage->HrGetRealProp(PR_MESSAGE_FLAGS, ulFlags, lpBase, lpsPropValue);
- if(hr != hrSuccess) {
- hr = hrSuccess;
- lpsPropValue->ulPropTag = PR_MESSAGE_FLAGS;
- lpsPropValue->Value.ul = MSGFLAG_READ;
- }
-
- lpsPropValue->Value.ul = (lpsPropValue->Value.ul & ~MSGFLAG_HASATTACH) | (lpMessage->HasAttachment() ? MSGFLAG_HASATTACH : 0);
- break;
- }
- case PROP_ID(PR_NORMALIZED_SUBJECT):
- hr = lpMessage->HrGetRealProp(CHANGE_PROP_TYPE(PR_SUBJECT, PROP_TYPE(ulPropTag)), ulFlags, lpBase, lpsPropValue);
- if (hr != hrSuccess) {
-
- lpsPropValue->ulPropTag = CHANGE_PROP_TYPE(PR_NORMALIZED_SUBJECT, PT_ERROR);
- break;
- }
- if (PROP_TYPE(ulPropTag) == PT_UNICODE) {
- lpsPropValue->ulPropTag = PR_NORMALIZED_SUBJECT_W;
- WCHAR *lpszColon = wcschr(lpsPropValue->Value.lpszW, ':');
- if (lpszColon && (lpszColon - lpsPropValue->Value.lpszW) > 1 && (lpszColon - lpsPropValue->Value.lpszW) < 4) {
- WCHAR *c = lpsPropValue->Value.lpszW;
- while (c < lpszColon && iswdigit(*c))
- ++c;
- if (c != lpszColon) {
- ++lpszColon;
- if (*lpszColon == ' ')
- ++lpszColon;
- lpsPropValue->Value.lpszW = lpszColon;
- }
- }
- } else {
- lpsPropValue->ulPropTag = PR_NORMALIZED_SUBJECT_A;
- char *lpszColon = strchr(lpsPropValue->Value.lpszA, ':');
- if (lpszColon && (lpszColon - lpsPropValue->Value.lpszA) > 1 && (lpszColon - lpsPropValue->Value.lpszA) < 4) {
- char *c = lpsPropValue->Value.lpszA;
- while (c < lpszColon && isdigit(*c))
- ++c;
- if (c != lpszColon) {
- ++lpszColon;
- if (*lpszColon == ' ')
- ++lpszColon;
- lpsPropValue->Value.lpszA = lpszColon;
- }
- }
- }
- break;
- case PROP_ID(PR_PARENT_ENTRYID):
- if(!lpMessage->m_lpParentID)
- hr = lpMessage->HrGetRealProp(PR_PARENT_ENTRYID, ulFlags, lpBase, lpsPropValue);
- else{
- lpsPropValue->ulPropTag = PR_PARENT_ENTRYID;
- lpsPropValue->Value.bin.cb = lpMessage->m_cbParentID;
- hr = ECAllocateMore(lpsPropValue->Value.bin.cb, lpBase, reinterpret_cast<void **>(&lpsPropValue->Value.bin.lpb));
- if (hr != hrSuccess)
- break;
- memcpy(lpsPropValue->Value.bin.lpb, lpMessage->m_lpParentID, lpsPropValue->Value.bin.cb);
- }
- break;
- case PROP_ID(PR_MESSAGE_SIZE):
- lpsPropValue->ulPropTag = PR_MESSAGE_SIZE;
- if(lpMessage->m_lpEntryId == NULL)
- lpsPropValue->Value.l = 1024;
- else
- hr = lpMessage->HrGetRealProp(PR_MESSAGE_SIZE, ulFlags, lpBase, lpsPropValue);
- break;
- case PROP_ID(PR_DISPLAY_TO):
- case PROP_ID(PR_DISPLAY_CC):
- case PROP_ID(PR_DISPLAY_BCC):
- if((lpMessage->m_bRecipsDirty && lpMessage->SyncRecips() != erSuccess) || lpMessage->HrGetRealProp(ulPropTag, ulFlags, lpBase, lpsPropValue) != erSuccess) {
- lpsPropValue->ulPropTag = ulPropTag;
- if(PROP_TYPE(ulPropTag) == PT_UNICODE)
- lpsPropValue->Value.lpszW = const_cast<wchar_t *>(L"");
- else
- lpsPropValue->Value.lpszA = const_cast<char *>("");
- }
- break;
- case PROP_ID(PR_ACCESS):
- if(lpMessage->HrGetRealProp(PR_ACCESS, ulFlags, lpBase, lpsPropValue) != hrSuccess)
- {
- lpsPropValue->ulPropTag = PR_ACCESS;
- lpsPropValue->Value.l = MAPI_ACCESS_READ | MAPI_ACCESS_MODIFY | MAPI_ACCESS_DELETE;
- }
- break;
- case PROP_ID(PR_MESSAGE_ATTACHMENTS):
- lpsPropValue->ulPropTag = PR_MESSAGE_ATTACHMENTS;
- lpsPropValue->Value.x = 1;
- break;
- case PROP_ID(PR_MESSAGE_RECIPIENTS):
- lpsPropValue->ulPropTag = PR_MESSAGE_RECIPIENTS;
- lpsPropValue->Value.x = 1;
- break;
- #ifdef HAVE_TIDY_H
- case PROP_ID(PR_EC_BODY_FILTERED): {
-
- hr = lpMessage->GetSyncedBodyProp(PR_EC_BODY_FILTERED, ulFlags, lpBase, lpsPropValue);
- if (hr == hrSuccess)
- break;
-
- memory_ptr<SPropValue> tprop;
- hr = MAPIAllocateBuffer(sizeof(SPropValue), &~tprop);
- if (hr != hrSuccess)
- break;
- hr = lpMessage->GetSyncedBodyProp(PR_HTML, ulFlags, tprop, tprop);
- if (hr != hrSuccess) {
- hr = MAPI_E_NOT_FOUND;
- break;
- }
- std::string fltblk, memblk(reinterpret_cast<const char *>(tprop->Value.bin.lpb), tprop->Value.bin.cb);
- std::copy_if(fltblk.cbegin(), fltblk.cend(), std::back_inserter(fltblk), [](char x) { return x != '\0'; });
- std::string result;
- std::vector<std::string> errors;
- bool rc = rosie_clean_html(fltblk, &result, &errors);
-
- if (rc) {
- ULONG ulSize = result.size();
- hr = ECAllocateMore(ulSize + 1, lpBase, reinterpret_cast<void **>(&lpsPropValue->Value.lpszA));
- if (hr == hrSuccess) {
- memcpy(lpsPropValue->Value.lpszA, result.c_str(), ulSize);
- lpsPropValue->Value.lpszA[ulSize] = '\0';
-
- } else {
- ulSize = 0;
- }
- lpsPropValue->Value.bin.cb = ulSize;
- }
- if (rc == 0 || hr != hrSuccess) {
- hr = MAPI_E_NOT_FOUND;
- break;
- }
- break;
- }
- #endif
- case PROP_ID(PR_BODY):
- case PROP_ID(PR_RTF_COMPRESSED):
- case PROP_ID(PR_HTML):
- hr = lpMessage->GetSyncedBodyProp(ulPropTag, ulFlags, lpBase, lpsPropValue);
- if (hr != hrSuccess)
- break;
- if (ulPropTag == PR_BODY_HTML) {
-
- if (lpsPropValue->ulPropTag != PR_HTML){
- hr = MAPI_E_NOT_FOUND;
- break;
- }
- lpsPropValue->ulPropTag = PR_BODY_HTML;
- ulSize = lpsPropValue->Value.bin.cb;
- lpData = lpsPropValue->Value.bin.lpb;
- hr = ECAllocateMore(ulSize + 1, lpBase, (void**)&lpsPropValue->Value.lpszA);
- if(hr != hrSuccess)
- break;
- if(ulSize>0 && lpData){
- memcpy(lpsPropValue->Value.lpszA, lpData, ulSize);
- }else
- ulSize = 0;
- lpsPropValue->Value.lpszA[ulSize] = 0;
- }
- break;
- case PROP_ID(PR_SOURCE_KEY): {
- std::string strServerGUID;
- std::string strID;
- std::string strSourceKey;
- if(ECMAPIProp::DefaultMAPIGetProp(PR_SOURCE_KEY, lpProvider, ulFlags, lpsPropValue, lpParam, lpBase) == hrSuccess)
- return hr;
-
- strServerGUID.assign((char*)&lpMessage->GetMsgStore()->GetStoreGuid(), sizeof(GUID));
- if(lpMessage->m_sMapiObject)
- strID.assign((char *)&lpMessage->m_sMapiObject->ulObjId, sizeof(lpMessage->m_sMapiObject->ulObjId));
-
-
- strID.resize(6,0);
- strSourceKey = strServerGUID + strID;
- hr = MAPIAllocateMore(strSourceKey.size(), lpBase, (void **)&lpsPropValue->Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- lpsPropValue->ulPropTag = PR_SOURCE_KEY;
- lpsPropValue->Value.bin.cb = strSourceKey.size();
- memcpy(lpsPropValue->Value.bin.lpb, strSourceKey.c_str(), strSourceKey.size());
- break;
- }
- default:
- hr = MAPI_E_NOT_FOUND;
- break;
- }
- return hr;
- }
- HRESULT ECMessage::SetPropHandler(ULONG ulPropTag, void *lpProvider,
- const SPropValue *lpsPropValue, void *lpParam)
- {
- auto lpMessage = static_cast<ECMessage *>(lpParam);
- HRESULT hr = hrSuccess;
- switch(ulPropTag) {
- case PR_MESSAGE_SIZE:
-
- if (lpMessage->fNew)
- hr = lpMessage->HrSetRealProp(lpsPropValue);
- else
- hr = MAPI_E_COMPUTED;
- break;
- case PR_HTML:
- hr = lpMessage->HrSetRealProp(lpsPropValue);
- break;
- case PR_BODY_HTML: {
-
- SPropValue copy;
- copy.ulPropTag = PR_HTML;
- auto lpData = copy.Value.lpszA;
- if(lpData) {
- copy.Value.bin.cb = strlen(lpData);
- copy.Value.bin.lpb = (LPBYTE)lpData;
- }
- else {
- copy.Value.bin.cb = 0;
- }
- hr = lpMessage->HrSetRealProp(©);
- break;
- }
- case PR_MESSAGE_FLAGS:
- if (lpMessage->m_sMapiObject == NULL || lpMessage->m_sMapiObject->ulObjId == 0) {
-
- SPropValue copy = *lpsPropValue;
- copy.Value.l &= 0x03FF;
- if (lpMessage->HasAttachment())
- copy.Value.l |= MSGFLAG_HASATTACH;
- hr = lpMessage->HrSetRealProp(©);
- }
- break;
- case PR_SOURCE_KEY:
- hr = ECMAPIProp::SetPropHandler(ulPropTag, lpProvider, lpsPropValue, lpParam);
- break;
- default:
- hr = MAPI_E_NOT_FOUND;
- break;
- }
- return hr;
- }
- HRESULT ECMessage::CopyTo(ULONG ciidExclude, LPCIID rgiidExclude,
- const SPropTagArray *lpExcludeProps, ULONG ulUIParam,
- LPMAPIPROGRESS lpProgress, LPCIID lpInterface, void *lpDestObj,
- ULONG ulFlags, SPropProblemArray **lppProblems)
- {
- HRESULT hr = hrSuccess;
- object_ptr<IECUnknown> lpECUnknown;
- memory_ptr<SPropValue> lpECObject;
- object_ptr<ECMAPIProp> lpECMAPIProp;
- ECMAPIProp *lpDestTop = NULL;
- ECMAPIProp *lpSourceTop = NULL;
- GUID sDestServerGuid = {0};
- GUID sSourceServerGuid = {0};
- if (lpDestObj == nullptr)
- return MAPI_E_INVALID_PARAMETER;
-
- if (HrGetOneProp((LPMAPIPROP)lpDestObj, PR_EC_OBJECT, &~lpECObject) == hrSuccess)
- lpECUnknown.reset(reinterpret_cast<IECUnknown *>(lpECObject->Value.lpszA));
-
-
- if(lpECUnknown && lpECUnknown->QueryInterface(IID_ECMAPIProp, &~lpECMAPIProp) == hrSuccess) {
-
- lpDestTop = lpECMAPIProp->m_lpRoot;
- lpSourceTop = this->m_lpRoot;
-
- if (!this->IsChildOf(lpDestTop)) {
-
-
- hr = lpDestTop->GetMsgStore()->lpTransport->GetServerGUID(&sDestServerGuid);
- if (hr != hrSuccess)
- return hr;
- hr = lpSourceTop->GetMsgStore()->lpTransport->GetServerGUID(&sSourceServerGuid);
- if (hr != hrSuccess)
- return hr;
- if(lpDestTop->m_lpEntryId && lpSourceTop->m_lpEntryId &&
- lpDestTop->m_cbEntryId == lpSourceTop->m_cbEntryId &&
- memcmp(lpDestTop->m_lpEntryId, lpSourceTop->m_lpEntryId, lpDestTop->m_cbEntryId) == 0 &&
- sDestServerGuid == sSourceServerGuid)
-
- return MAPI_E_NO_ACCESS;
- }
- }
- return Util::DoCopyTo(&IID_IMessage, &this->m_xMessage, ciidExclude,
- rgiidExclude, lpExcludeProps, ulUIParam, lpProgress,
- lpInterface, lpDestObj, ulFlags, lppProblems);
- }
- HRESULT ECMessage::HrLoadProps()
- {
- HRESULT hr = hrSuccess;
- ecmem_ptr<SPropValue> lpsBodyProps;
- static constexpr const SizedSPropTagArray(3, sPropBodyTags) =
- {3, {PR_BODY_W, PR_RTF_COMPRESSED, PR_HTML}};
- ULONG cValues = 0;
- BOOL fBodyOK = FALSE;
- BOOL fRTFOK = FALSE;
- BOOL fHTMLOK = FALSE;
- m_bInhibitSync = TRUE;
- hr = ECMAPIProp::HrLoadProps();
- m_bInhibitSync = FALSE;
- if (hr != hrSuccess)
- return hr;
-
- hr = ECMAPIProp::GetProps(sPropBodyTags, 0, &cValues, &~lpsBodyProps);
- if (HR_FAILED(hr))
- return hr;
- hr = hrSuccess;
- if (lpsBodyProps[0].ulPropTag == PR_BODY_W || (lpsBodyProps[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY)) && lpsBodyProps[0].Value.err == MAPI_E_NOT_ENOUGH_MEMORY))
- fBodyOK = TRUE;
- if (lpsBodyProps[1].ulPropTag == PR_RTF_COMPRESSED || (lpsBodyProps[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED)) && lpsBodyProps[1].Value.err == MAPI_E_NOT_ENOUGH_MEMORY))
- fRTFOK = TRUE;
- if (lpsBodyProps[2].ulPropTag == PR_HTML || (lpsBodyProps[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML)) && lpsBodyProps[2].Value.err == MAPI_E_NOT_ENOUGH_MEMORY))
- fHTMLOK = TRUE;
- if (fRTFOK) {
- HRESULT hrTmp = hrSuccess;
- hrTmp = GetBodyType(&m_ulBodyType);
- if (FAILED(hrTmp)) {
-
- TRACE_MAPI(TRACE_WARNING, "GetBestBody", "Unable to determine body type based on RTF data, hr=0x%08x", hrTmp);
- } else if ((m_ulBodyType == bodyTypePlain && !fBodyOK) ||
- (m_ulBodyType == bodyTypeHTML && !fHTMLOK)) {
- hr = SyncRtf();
- if (hr != hrSuccess)
- return hr;
- }
- }
- if (m_ulBodyType == bodyTypeUnknown) {
-
-
- if (fHTMLOK)
- m_ulBodyType = bodyTypeHTML;
- else if (fBodyOK)
- m_ulBodyType = bodyTypePlain;
- }
- return hr;
- }
- HRESULT ECMessage::HrSetRealProp(const SPropValue *lpsPropValue)
- {
- HRESULT hr;
- hr = ECMAPIProp::HrSetRealProp(lpsPropValue);
- if(hr != hrSuccess)
- return hr;
-
- if (m_bInhibitSync)
- return hrSuccess;
- if (lpsPropValue->ulPropTag == PR_RTF_COMPRESSED) {
- m_ulBodyType = bodyTypeUnknown;
- GetBodyType(&m_ulBodyType);
- SyncRtf();
- } else if (lpsPropValue->ulPropTag == PR_HTML) {
- m_ulBodyType = bodyTypeHTML;
- SyncHtmlToPlain();
- HrDeleteRealProp(PR_RTF_COMPRESSED, FALSE);
- } else if (lpsPropValue->ulPropTag == PR_BODY_W || lpsPropValue->ulPropTag == PR_BODY_A) {
- m_ulBodyType = bodyTypePlain;
- HrDeleteRealProp(PR_RTF_COMPRESSED, FALSE);
- HrDeleteRealProp(PR_HTML, FALSE);
- }
- return hrSuccess;
- }
- struct findobject_if {
- unsigned int m_ulUniqueId;
- unsigned int m_ulObjType;
- findobject_if(unsigned int ulObjType, unsigned int ulUniqueId) : m_ulUniqueId(ulUniqueId), m_ulObjType(ulObjType) {}
- bool operator()(const MAPIOBJECT *entry)
- {
- return entry->ulUniqueId == m_ulUniqueId && entry->ulObjType == m_ulObjType;
- }
- };
- static HRESULT HrCopyObjIDs(MAPIOBJECT *lpDest, const MAPIOBJECT *lpSrc)
- {
- HRESULT hr;
- lpDest->ulObjId = lpSrc->ulObjId;
- for (const auto &src : lpSrc->lstChildren) {
- auto iterDest = lpDest->lstChildren.find(src);
- if (iterDest != lpDest->lstChildren.cend()) {
- hr = HrCopyObjIDs(*iterDest, src);
- if(hr != hrSuccess)
- return hr;
- }
- }
- return hrSuccess;
- }
- HRESULT ECMessage::HrSaveChild(ULONG ulFlags, MAPIOBJECT *lpsMapiObject) {
- HRESULT hr = hrSuccess;
- ECMapiObjects::const_iterator iterSObj;
- SPropValue sKeyProp;
- ecmem_ptr<SPropValue> lpProps;
- ULONG ulProps = 0;
- LPSPropValue lpPropID = NULL;
- LPSPropValue lpPropObjType = NULL;
- ULONG i;
- scoped_rlock lock(m_hMutexMAPIObject);
- if (lpsMapiObject->ulObjType != MAPI_ATTACH)
-
-
- return MAPI_E_INVALID_OBJECT;
- if(this->lpAttachments == NULL) {
- object_ptr<IMAPITable> lpTable;
- hr = this->GetAttachmentTable(fMapiUnicode, &~lpTable);
- if(hr != hrSuccess)
- return hr;
- }
- if (this->lpAttachments == nullptr)
- return MAPI_E_CALL_FAILED;
- if (!m_sMapiObject) {
-
- assert(m_sMapiObject != NULL);
- return MAPI_E_NOT_FOUND;
- }
-
-
- iterSObj = m_sMapiObject->lstChildren.find(lpsMapiObject);
- if (iterSObj != m_sMapiObject->lstChildren.cend()) {
-
- hr = HrCopyObjIDs(lpsMapiObject, (*iterSObj));
- if(hr != hrSuccess)
- return hr;
-
- FreeMapiObject(*iterSObj);
- m_sMapiObject->lstChildren.erase(iterSObj);
- }
- m_sMapiObject->lstChildren.insert(new MAPIOBJECT(lpsMapiObject));
-
- ulProps = lpsMapiObject->lstProperties.size();
-
- hr = ECAllocateBuffer(sizeof(SPropValue) * (ulProps + 2), &~lpProps);
- if (hr != hrSuccess)
- return hr;
- lpPropID = NULL;
- i = 0;
- for (const auto &pv : lpsMapiObject->lstProperties) {
- pv.CopyToByRef(&lpProps[i]);
- if (lpProps[i].ulPropTag == PR_ATTACH_NUM) {
- lpPropID = &lpProps[i];
- } else if(lpProps[i].ulPropTag == PR_OBJECT_TYPE) {
- lpPropObjType = &lpProps[i];
- } else if (PROP_ID(lpProps[i].ulPropTag) == PROP_ID(PR_ATTACH_DATA_OBJ)) {
- lpProps[i].ulPropTag = CHANGE_PROP_TYPE(lpProps[i].ulPropTag, PT_ERROR);
- lpProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- } else if (PROP_TYPE(lpProps[i].ulPropTag) == PT_BINARY && lpProps[i].Value.bin.cb > MAX_TABLE_PROPSIZE) {
- lpProps[i].ulPropTag = CHANGE_PROP_TYPE(lpProps[i].ulPropTag, PT_ERROR);
- lpProps[i].Value.err = MAPI_E_NOT_ENOUGH_MEMORY;
- }
- ++i;
- }
- if (lpPropID == NULL) {
- ++ulProps;
- lpPropID = &lpProps[i++];
- }
- if (lpPropObjType == NULL) {
- ++ulProps;
- lpPropObjType = &lpProps[i++];
- }
- lpPropObjType->ulPropTag = PR_OBJECT_TYPE;
- lpPropObjType->Value.ul = MAPI_ATTACH;
- lpPropID->ulPropTag = PR_ATTACH_NUM;
- lpPropID->Value.ul = lpsMapiObject->ulUniqueId;
- sKeyProp.ulPropTag = PR_EC_HIERARCHYID;
- sKeyProp.Value.ul = lpsMapiObject->ulObjId;
- return lpAttachments->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpProps, ulProps);
- }
- HRESULT ECMessage::GetBodyType(eBodyType *lpulBodyType)
- {
- HRESULT hr = hrSuccess;
- object_ptr<IStream> lpRTFCompressedStream, lpRTFUncompressedStream;
- char szRtfBuf[64] = {0};
- ULONG cbRtfBuf = 0;
- if (m_ulBodyType == bodyTypeUnknown) {
- hr = OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, 0, 0, &~lpRTFCompressedStream);
- if (hr != hrSuccess)
- return hr;
- hr = WrapCompressedRTFStream(lpRTFCompressedStream, 0, &~lpRTFUncompressedStream);
- if (hr != hrSuccess)
- return hr;
- hr = lpRTFUncompressedStream->Read(szRtfBuf, sizeof(szRtfBuf), &cbRtfBuf);
- if (hr != hrSuccess)
- return hr;
- if (isrtftext(szRtfBuf, cbRtfBuf))
- m_ulBodyType = bodyTypePlain;
- else if (isrtfhtml(szRtfBuf, cbRtfBuf))
- m_ulBodyType = bodyTypeHTML;
- else
- m_ulBodyType = bodyTypeRTF;
- }
- *lpulBodyType = m_ulBodyType;
- return hrSuccess;
- }
- HRESULT ECMessage::GetRtfData(std::string *lpstrRtfData)
- {
- HRESULT hr;
- StreamPtr ptrRtfCompressedStream;
- StreamPtr ptrRtfUncompressedStream;
- char lpBuf[4096];
- std::string strRtfData;
- hr = OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, 0, 0, &~ptrRtfCompressedStream);
- if (hr != hrSuccess)
- return hr;
-
- hr = WrapCompressedRTFStream(ptrRtfCompressedStream, 0, &~ptrRtfUncompressedStream);
- if(hr != hrSuccess)
- {
- KCHL::object_ptr<ECMemStream> ptrEmptyMemStream;
-
- hr = ECMemStream::Create(nullptr, 0, 0, nullptr, nullptr, nullptr, &~ptrEmptyMemStream);
- if (hr != hrSuccess)
- return hr;
- hr = ptrEmptyMemStream->QueryInterface(IID_IStream, &~ptrRtfUncompressedStream);
- if (hr != hrSuccess)
- return hr;
- }
-
- while (1) {
- ULONG ulRead;
- hr = ptrRtfUncompressedStream->Read(lpBuf, 4096, &ulRead);
- if (hr != hrSuccess)
- return hr;
- if (ulRead == 0)
- break;
- strRtfData.append(lpBuf, ulRead);
- }
- lpstrRtfData->swap(strRtfData);
- return hrSuccess;
- }
- HRESULT ECMessage::GetCodePage(unsigned int *lpulCodePage)
- {
- HRESULT hr;
- SPropValuePtr ptrPropValue;
- hr = ECAllocateBuffer(sizeof(SPropValue), &~ptrPropValue);
- if (hr != hrSuccess)
- return hr;
- if (HrGetRealProp(PR_INTERNET_CPID, 0, ptrPropValue, ptrPropValue) == hrSuccess &&
- ptrPropValue->ulPropTag == PR_INTERNET_CPID)
- *lpulCodePage = ptrPropValue->Value.ul;
- else
- *lpulCodePage = 0;
- return hrSuccess;
- }
- HRESULT ECMessage::CopyProps(const SPropTagArray *lpIncludeProps,
- ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface,
- void *lpDestObj, ULONG ulFlags, SPropProblemArray **lppProblems)
- {
- return Util::DoCopyProps(&IID_IMessage, &this->m_xMessage, lpIncludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
- }
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, QueryInterface, (REFIID, refiid), (void **, lppInterface))
- DEF_ULONGMETHOD1(TRACE_MAPI, ECMessage, Message, AddRef, (void))
- DEF_ULONGMETHOD1(TRACE_MAPI, ECMessage, Message, Release, (void))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetLastError, (HRESULT, hError), (ULONG, ulFlags), (LPMAPIERROR *, lppMapiError))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, SaveChanges, (ULONG, ulFlags))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetProps, (const SPropTagArray *, lpPropTagArray), (ULONG, ulFlags), (ULONG *, lpcValues), (SPropValue **, lppPropArray))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetPropList, (ULONG, ulFlags), (LPSPropTagArray *, lppPropTagArray))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, OpenProperty, (ULONG, ulPropTag), (LPCIID, lpiid), (ULONG, ulInterfaceOptions), (ULONG, ulFlags), (LPUNKNOWN *, lppUnk))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, SetProps, (ULONG, cValues), (const SPropValue *, lpPropArray), (SPropProblemArray **, lppProblems))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, DeleteProps, (const SPropTagArray *, lpPropTagArray), (SPropProblemArray **, lppProblems))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, CopyTo, (ULONG, ciidExclude), (LPCIID, rgiidExclude), (const SPropTagArray *, lpExcludeProps), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (LPCIID, lpInterface), (void *, lpDestObj), (ULONG, ulFlags), (SPropProblemArray **, lppProblems))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, CopyProps, (const SPropTagArray *, lpIncludeProps), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (LPCIID, lpInterface), (void *, lpDestObj), (ULONG, ulFlags), (SPropProblemArray **, lppProblems))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetNamesFromIDs, (LPSPropTagArray *, pptaga), (LPGUID, lpguid), (ULONG, ulFlags), (ULONG *, pcNames), (LPMAPINAMEID **, pppNames))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetIDsFromNames, (ULONG, cNames), (LPMAPINAMEID *, ppNames), (ULONG, ulFlags), (LPSPropTagArray *, pptaga))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetAttachmentTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, OpenAttach, (ULONG, ulAttachmentNum), (LPCIID, lpInterface), (ULONG, ulFlags), (LPATTACH *, lppAttach))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, CreateAttach, (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulAttachmentNum), (LPATTACH *, lppAttach))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, DeleteAttach, (ULONG, ulAttachmentNum), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, GetRecipientTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, ModifyRecipients, (ULONG, ulFlags), (const ADRLIST *, lpMods))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, SubmitMessage, (ULONG, ulFlags))
- DEF_HRMETHOD1(TRACE_MAPI, ECMessage, Message, SetReadFlag, (ULONG, ulFlags))
|