12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890 |
- #include <kopano/zcdefs.h>
- #include <kopano/platform.h>
- #include <exception>
- #include <cwctype>
- #include <mapidefs.h>
- #include <mapiutil.h>
- #include <mapispi.h>
- #include <memory>
- #include <new>
- #include <string>
- #include <stack>
- #include <set>
- #include <map>
- #include <cstring>
- #include <edkmdb.h>
- #include <kopano/Util.h>
- #include <kopano/ECIConv.h>
- #include <kopano/CommonUtil.h>
- #include <kopano/memory.hpp>
- #include <kopano/stringutil.h>
- #include <kopano/charset/convert.h>
- #include "ECMemStream.h"
- #include <kopano/IECSingleInstance.h>
- #include <kopano/ECGuid.h>
- #include <kopano/codepage.h>
- #include "rtfutil.h"
- #include <kopano/mapiext.h>
- #include <kopano/ustringutil.h>
- #include <kopano/mapi_ptr.h>
- #include "HtmlToTextParser.h"
- #include <kopano/ECLogger.h>
- #include "HtmlEntity.h"
- using namespace std;
- using namespace KCHL;
- #include <kopano/ECGetText.h>
- namespace KC {
- class iconv_HACK _kc_final {
- public:
- iconv_HACK(const char** ptr) : m_ptr(ptr) { }
-
- operator const char **(void) const { return m_ptr; }
- operator char**() { return const_cast <char**>(m_ptr); }
- private:
- const char** m_ptr;
- };
- class PropTagCompare _kc_final {
- public:
- bool operator()(ULONG lhs, ULONG rhs) const {
- if (PROP_TYPE(lhs) == PT_UNSPECIFIED || PROP_TYPE(rhs) == PT_UNSPECIFIED)
- return PROP_ID(lhs) < PROP_ID(rhs);
- return lhs < rhs;
- }
- };
- typedef std::set<ULONG,PropTagCompare> PropTagSet;
- HRESULT Util::HrAddToPropertyArray(const SPropValue *lpSrc, ULONG cValues,
- const SPropValue *lpToAdd, SPropValue **lppDest, ULONG *cDestValues)
- {
- LPSPropValue lpDest = NULL;
- unsigned int i = 0;
- unsigned int n = 0;
- HRESULT hr = MAPIAllocateBuffer(sizeof(SPropValue) * (cValues + 1),
- reinterpret_cast<void **>(&lpDest));
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < cValues; ++i) {
- hr = HrCopyProperty(&lpDest[n], &lpSrc[i], lpDest);
- if(hr == hrSuccess)
- ++n;
- hr = hrSuccess;
- }
- auto lpFind = PpropFindProp(lpDest, n, lpToAdd->ulPropTag);
- if (lpFind != nullptr)
- hr = HrCopyProperty(lpFind, lpToAdd, lpDest);
- else
- hr = HrCopyProperty(&lpDest[n++], lpToAdd, lpDest);
- if(hr != hrSuccess)
- return hr;
- *lppDest = lpDest;
- *cDestValues = n;
- return hrSuccess;
- }
- #ifndef STORE_HTML_OK
- #define STORE_HTML_OK 0x00010000
- #endif
- bool Util::FHasHTML(IMAPIProp *lpProp)
- {
- HRESULT hr = hrSuccess;
- memory_ptr<SPropValue> lpPropSupport = NULL;
- hr = HrGetOneProp(lpProp, PR_STORE_SUPPORT_MASK, &~lpPropSupport);
- if(hr != hrSuccess)
- return false;
- if((lpPropSupport->Value.ul & STORE_HTML_OK) == 0)
- return false;
- return true;
- }
- HRESULT Util::HrMergePropertyArrays(const SPropValue *lpSrc, ULONG cValues,
- const SPropValue *lpAdds, ULONG cAddValues, SPropValue **lppDest,
- ULONG *cDestValues)
- {
- HRESULT hr = hrSuccess;
- map<ULONG, const SPropValue *> mapPropSource;
- ULONG i = 0;
- memory_ptr<SPropValue> lpProps;
- for (i = 0; i < cValues; ++i)
- mapPropSource[lpSrc[i].ulPropTag] = &lpSrc[i];
- for (i = 0; i < cAddValues; ++i)
- mapPropSource[lpAdds[i].ulPropTag] = &lpAdds[i];
- hr = MAPIAllocateBuffer(sizeof(SPropValue)*mapPropSource.size(), &~lpProps);
- if (hr != hrSuccess)
- return hr;
- i = 0;
- for (const auto &ips : mapPropSource) {
- hr = Util::HrCopyProperty(&lpProps[i], ips.second, lpProps);
- if (hr != hrSuccess)
- return hr;
- ++i;
- }
- *cDestValues = i;
- *lppDest = lpProps.release();
- return hrSuccess;
- }
- HRESULT Util::HrCopyPropertyArrayByRef(const SPropValue *lpSrc, ULONG cValues,
- LPSPropValue *lppDest, ULONG *cDestValues, bool bExcludeErrors)
- {
- memory_ptr<SPropValue> lpDest;
- unsigned int i = 0;
- unsigned int n = 0;
-
- HRESULT hr = MAPIAllocateBuffer(sizeof(SPropValue) * cValues, &~lpDest);
- if (hr != hrSuccess)
- return hr;
-
- for (i = 0; i < cValues; ++i) {
- if (bExcludeErrors && PROP_TYPE(lpSrc[i].ulPropTag) == PT_ERROR)
- continue;
- hr = HrCopyPropertyByRef(&lpDest[n], &lpSrc[i]);
- if (hr == hrSuccess)
- ++n;
- }
- *lppDest = lpDest.release();
- *cDestValues = n;
- return hrSuccess;
- }
- HRESULT Util::HrCopyPropertyArray(const SPropValue *lpSrc, ULONG cValues,
- LPSPropValue *lppDest, ULONG *cDestValues, bool bExcludeErrors)
- {
- memory_ptr<SPropValue> lpDest;
- unsigned int i = 0;
- unsigned int n = 0;
- HRESULT hr = MAPIAllocateBuffer(sizeof(SPropValue) * cValues, &~lpDest);
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < cValues; ++i) {
- if (bExcludeErrors && PROP_TYPE(lpSrc[i].ulPropTag) == PT_ERROR)
- continue;
- hr = HrCopyProperty(&lpDest[n], &lpSrc[i], lpDest);
- if (hr == MAPI_E_INVALID_PARAMETER)
-
- continue;
- else if (hr != hrSuccess)
- return hr;
- ++n;
- }
- *lppDest = lpDest.release();
- *cDestValues = n;
- return hrSuccess;
- }
- HRESULT Util::HrCopyPropertyArray(const SPropValue *lpSrc, ULONG cValues,
- LPSPropValue lpDest, void *lpBase)
- {
- unsigned int i;
- for (i = 0; i < cValues; ++i) {
- HRESULT hr = HrCopyProperty(&lpDest[i], &lpSrc[i], lpBase);
- if(hr != hrSuccess)
- return hr;
- }
- return hrSuccess;
- }
- HRESULT Util::HrCopyPropertyArrayByRef(const SPropValue *lpSrc, ULONG cValues,
- LPSPropValue lpDest)
- {
- unsigned int i;
- for (i = 0; i < cValues; ++i) {
- HRESULT hr = HrCopyPropertyByRef(&lpDest[i], &lpSrc[i]);
- if(hr != hrSuccess)
- return hr;
- }
- return hrSuccess;
- }
- HRESULT Util::HrCopyPropertyByRef(LPSPropValue lpDest, const SPropValue *lpSrc)
- {
-
- memcpy(lpDest, lpSrc, sizeof(SPropValue));
-
- return hrSuccess;
- }
- HRESULT Util::HrCopyProperty(LPSPropValue lpDest, const SPropValue *lpSrc,
- void *lpBase, ALLOCATEMORE *lpfAllocMore)
- {
- HRESULT hr = hrSuccess;
- if(lpfAllocMore == NULL)
- lpfAllocMore = MAPIAllocateMore;
- switch(PROP_TYPE(lpSrc->ulPropTag)) {
- case PT_I2:
- lpDest->Value.i = lpSrc->Value.i;
- break;
- case PT_LONG:
- lpDest->Value.ul = lpSrc->Value.ul;
- break;
- case PT_BOOLEAN:
- lpDest->Value.b = lpSrc->Value.b;
- break;
- case PT_R4:
- lpDest->Value.flt = lpSrc->Value.flt;
- break;
- case PT_DOUBLE:
- lpDest->Value.dbl = lpSrc->Value.dbl;
- break;
- case PT_APPTIME:
- lpDest->Value.at = lpSrc->Value.at;
- break;
- case PT_CURRENCY:
- lpDest->Value.cur = lpSrc->Value.cur;
- break;
- case PT_SYSTIME:
- lpDest->Value.ft = lpSrc->Value.ft;
- break;
- case PT_I8:
- lpDest->Value.li = lpSrc->Value.li;
- break;
- case PT_UNICODE:
- if (lpSrc->Value.lpszW == NULL)
- return MAPI_E_INVALID_PARAMETER;
- hr = lpfAllocMore(wcslen(lpSrc->Value.lpszW)*sizeof(wchar_t)+sizeof(wchar_t), lpBase, (void**)&lpDest->Value.lpszW);
- if (hr != hrSuccess)
- return hr;
- wcscpy(lpDest->Value.lpszW, lpSrc->Value.lpszW);
- break;
- case PT_STRING8:
- if (lpSrc->Value.lpszA == NULL)
- return MAPI_E_INVALID_PARAMETER;
- hr = lpfAllocMore(strlen(lpSrc->Value.lpszA) + 1, lpBase, (void**)&lpDest->Value.lpszA);
- if (hr != hrSuccess)
- return hr;
- strcpy(lpDest->Value.lpszA, lpSrc->Value.lpszA);
- break;
- case PT_BINARY:
- if(lpSrc->Value.bin.cb > 0) {
- hr = lpfAllocMore(lpSrc->Value.bin.cb, lpBase, (void **) &lpDest->Value.bin.lpb);
- if (hr != hrSuccess)
- return hr;
- }
- lpDest->Value.bin.cb = lpSrc->Value.bin.cb;
-
- if(lpSrc->Value.bin.cb > 0)
- memcpy(lpDest->Value.bin.lpb, lpSrc->Value.bin.lpb, lpSrc->Value.bin.cb);
- else
- lpDest->Value.bin.lpb = NULL;
- break;
- case PT_CLSID:
- hr = lpfAllocMore(sizeof(GUID), lpBase, (void **)&lpDest->Value.lpguid);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.lpguid, lpSrc->Value.lpguid, sizeof(GUID));
- break;
- case PT_ERROR:
- lpDest->Value.err = lpSrc->Value.err;
- break;
- case PT_SRESTRICTION:
- if (lpSrc->Value.lpszA == NULL)
- return MAPI_E_INVALID_PARAMETER;
-
- hr = lpfAllocMore(sizeof(SRestriction), lpBase, (void **)&lpDest->Value.lpszA);
- if (hr != hrSuccess)
- return hr;
- hr = Util::HrCopySRestriction((LPSRestriction)lpDest->Value.lpszA, (LPSRestriction)lpSrc->Value.lpszA, lpBase);
- break;
- case PT_ACTIONS:
- if (lpSrc->Value.lpszA == NULL)
- return MAPI_E_INVALID_PARAMETER;
-
- hr = lpfAllocMore(sizeof(ACTIONS), lpBase, (void **)&lpDest->Value.lpszA);
- if (hr != hrSuccess)
- return hr;
- hr = Util::HrCopyActions((ACTIONS *)lpDest->Value.lpszA, (ACTIONS *)lpSrc->Value.lpszA, lpBase);
- break;
- case PT_NULL:
- break;
- case PT_OBJECT:
- lpDest->Value.x = 0;
- break;
-
- case PT_MV_I2:
- hr = lpfAllocMore(sizeof(short int) * lpSrc->Value.MVi.cValues, lpBase, (void **)&lpDest->Value.MVi.lpi);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVi.lpi, lpSrc->Value.MVi.lpi, sizeof(short int) * lpSrc->Value.MVi.cValues);
- lpDest->Value.MVi.cValues = lpSrc->Value.MVi.cValues;
- break;
- case PT_MV_LONG:
- hr = lpfAllocMore(sizeof(LONG) * lpSrc->Value.MVl.cValues, lpBase, (void **)&lpDest->Value.MVl.lpl);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVl.lpl, lpSrc->Value.MVl.lpl, sizeof(LONG) * lpSrc->Value.MVl.cValues);
- lpDest->Value.MVl.cValues = lpSrc->Value.MVl.cValues;
- break;
- case PT_MV_FLOAT:
- hr = lpfAllocMore(sizeof(float) * lpSrc->Value.MVflt.cValues, lpBase, (void **)&lpDest->Value.MVflt.lpflt);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVflt.lpflt, lpSrc->Value.MVflt.lpflt, sizeof(float) * lpSrc->Value.MVflt.cValues);
- lpDest->Value.MVflt.cValues = lpSrc->Value.MVflt.cValues;
- break;
- case PT_MV_DOUBLE:
- case PT_MV_APPTIME:
- hr = lpfAllocMore(sizeof(double) * lpSrc->Value.MVdbl.cValues, lpBase, (void **)&lpDest->Value.MVdbl.lpdbl);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVdbl.lpdbl, lpSrc->Value.MVdbl.lpdbl, sizeof(double) * lpSrc->Value.MVdbl.cValues);
- lpDest->Value.MVdbl.cValues = lpSrc->Value.MVdbl.cValues;
- break;
- case PT_MV_I8:
- hr = lpfAllocMore(sizeof(LONGLONG) * lpSrc->Value.MVli.cValues, lpBase, (void **)&lpDest->Value.MVli.lpli);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVli.lpli, lpSrc->Value.MVli.lpli, sizeof(LONGLONG) * lpSrc->Value.MVli.cValues);
- lpDest->Value.MVli.cValues = lpSrc->Value.MVli.cValues;
- break;
- case PT_MV_CURRENCY:
- hr = lpfAllocMore(sizeof(CURRENCY) * lpSrc->Value.MVcur.cValues, lpBase, (void **)&lpDest->Value.MVcur.lpcur);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVcur.lpcur, lpSrc->Value.MVcur.lpcur, sizeof(CURRENCY) * lpSrc->Value.MVcur.cValues);
- lpDest->Value.MVcur.cValues = lpSrc->Value.MVcur.cValues;
- break;
- case PT_MV_SYSTIME:
- hr = lpfAllocMore(sizeof(FILETIME) * lpSrc->Value.MVft.cValues, lpBase, (void **)&lpDest->Value.MVft.lpft);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVft.lpft, lpSrc->Value.MVft.lpft, sizeof(FILETIME) * lpSrc->Value.MVft.cValues);
- lpDest->Value.MVft.cValues = lpSrc->Value.MVft.cValues;
- break;
- case PT_MV_STRING8:
- hr = lpfAllocMore(sizeof(LPSTR *) * lpSrc->Value.MVszA.cValues, lpBase, (void **)&lpDest->Value.MVszA.lppszA);
- if (hr != hrSuccess)
- return hr;
- for (ULONG i = 0; i < lpSrc->Value.MVszA.cValues; ++i) {
- int datalength = strlen(lpSrc->Value.MVszA.lppszA[i]) + 1;
- hr = lpfAllocMore(datalength, lpBase, (void **)&lpDest->Value.MVszA.lppszA[i]);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVszA.lppszA[i], lpSrc->Value.MVszA.lppszA[i], datalength);
- }
- lpDest->Value.MVszA.cValues = lpSrc->Value.MVszA.cValues;
- break;
- case PT_MV_UNICODE:
- hr = lpfAllocMore(sizeof(LPWSTR *) * lpSrc->Value.MVszW.cValues, lpBase, (void **)&lpDest->Value.MVszW.lppszW);
- if (hr != hrSuccess)
- return hr;
- for (ULONG i = 0; i < lpSrc->Value.MVszW.cValues; ++i) {
- hr = lpfAllocMore(wcslen(lpSrc->Value.MVszW.lppszW[i]) * sizeof(WCHAR) + sizeof(WCHAR), lpBase, (void**)&lpDest->Value.MVszW.lppszW[i]);
- if (hr != hrSuccess)
- return hr;
- wcscpy(lpDest->Value.MVszW.lppszW[i], lpSrc->Value.MVszW.lppszW[i]);
- }
- lpDest->Value.MVszW.cValues = lpSrc->Value.MVszW.cValues;
- break;
- case PT_MV_BINARY:
- hr = lpfAllocMore(sizeof(SBinary) * lpSrc->Value.MVbin.cValues, lpBase, (void **)&lpDest->Value.MVbin.lpbin);
- if (hr != hrSuccess)
- return hr;
- for (ULONG i = 0; i < lpSrc->Value.MVbin.cValues; ++i) {
- hr = lpfAllocMore(lpSrc->Value.MVbin.lpbin[i].cb, lpBase, (void **)&lpDest->Value.MVbin.lpbin[i].lpb);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVbin.lpbin[i].lpb, lpSrc->Value.MVbin.lpbin[i].lpb, lpSrc->Value.MVbin.lpbin[i].cb);
- lpDest->Value.MVbin.lpbin[i].cb = lpSrc->Value.MVbin.lpbin[i].cb;
- }
- lpDest->Value.MVbin.cValues = lpSrc->Value.MVbin.cValues;
- break;
- case PT_MV_CLSID:
- hr = lpfAllocMore(sizeof(GUID) * lpSrc->Value.MVguid.cValues, lpBase, (void **)&lpDest->Value.MVguid.lpguid);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->Value.MVguid.lpguid, lpSrc->Value.MVguid.lpguid, sizeof(GUID) * lpSrc->Value.MVguid.cValues);
- lpDest->Value.MVguid.cValues = lpSrc->Value.MVguid.cValues;
- break;
- default:
- return MAPI_E_INVALID_PARAMETER;
- }
- lpDest->ulPropTag = lpSrc->ulPropTag;
- return hr;
- }
- HRESULT Util::HrCopySRestriction(LPSRestriction *lppDest,
- const SRestriction *lpSrc)
- {
- LPSRestriction lpDest = NULL;
- HRESULT hr = MAPIAllocateBuffer(sizeof(SRestriction),
- reinterpret_cast<void **>(&lpDest));
- if (hr != hrSuccess)
- return hr;
- hr = HrCopySRestriction(lpDest, lpSrc, lpDest);
- if(hr != hrSuccess)
- return hr;
- *lppDest = lpDest;
- return hrSuccess;
- }
- HRESULT Util::HrCopySRestriction(LPSRestriction lpDest,
- const SRestriction *lpSrc, void *lpBase)
- {
- HRESULT hr = hrSuccess;
- unsigned int i;
- if (lpDest == NULL || lpSrc == NULL || lpBase == NULL)
- return MAPI_E_INVALID_PARAMETER;
- lpDest->rt = lpSrc->rt;
- switch(lpSrc->rt) {
- case RES_AND:
- lpDest->res.resAnd.cRes = lpSrc->res.resAnd.cRes;
- hr = MAPIAllocateMore(sizeof(SRestriction) * lpSrc->res.resAnd.cRes, lpBase, (void **)&lpDest->res.resAnd.lpRes);
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < lpSrc->res.resAnd.cRes; ++i) {
- hr = HrCopySRestriction(&lpDest->res.resAnd.lpRes[i], &lpSrc->res.resAnd.lpRes[i], lpBase);
- if(hr != hrSuccess)
- return hr;
- }
- break;
- case RES_OR:
- lpDest->res.resOr.cRes = lpSrc->res.resOr.cRes;
- hr = MAPIAllocateMore(sizeof(SRestriction) * lpSrc->res.resOr.cRes, lpBase, (void **)&lpDest->res.resOr.lpRes);
- if (hr != hrSuccess)
- return hr;
- for (i = 0; i < lpSrc->res.resOr.cRes; ++i) {
- hr = HrCopySRestriction(&lpDest->res.resOr.lpRes[i], &lpSrc->res.resOr.lpRes[i], lpBase);
- if(hr != hrSuccess)
- return hr;
- }
- break;
- case RES_NOT:
- hr = MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **) &lpDest->res.resNot.lpRes);
- if (hr != hrSuccess)
- return hr;
- return HrCopySRestriction(lpDest->res.resNot.lpRes, lpSrc->res.resNot.lpRes, lpBase);
- case RES_CONTENT:
- lpDest->res.resContent.ulFuzzyLevel = lpSrc->res.resContent.ulFuzzyLevel;
- lpDest->res.resContent.ulPropTag = lpSrc->res.resContent.ulPropTag;
- hr = MAPIAllocateMore(sizeof(SPropValue), lpBase, (void **) &lpDest->res.resContent.lpProp);
- if (hr != hrSuccess)
- return hr;
- return HrCopyProperty(lpDest->res.resContent.lpProp, lpSrc->res.resContent.lpProp, lpBase);
- case RES_PROPERTY:
- lpDest->res.resProperty.relop = lpSrc->res.resProperty.relop;
- lpDest->res.resProperty.ulPropTag = lpSrc->res.resProperty.ulPropTag;
- hr = MAPIAllocateMore(sizeof(SPropValue), lpBase, (void **) &lpDest->res.resProperty.lpProp);
- if (hr != hrSuccess)
- return hr;
- return HrCopyProperty(lpDest->res.resProperty.lpProp, lpSrc->res.resProperty.lpProp, lpBase);
- case RES_COMPAREPROPS:
- lpDest->res.resCompareProps.relop = lpSrc->res.resCompareProps.relop;
- lpDest->res.resCompareProps.ulPropTag1 = lpSrc->res.resCompareProps.ulPropTag1;
- lpDest->res.resCompareProps.ulPropTag2 = lpSrc->res.resCompareProps.ulPropTag2;
- break;
- case RES_BITMASK:
- lpDest->res.resBitMask.relBMR = lpSrc->res.resBitMask.relBMR;
- lpDest->res.resBitMask.ulMask = lpSrc->res.resBitMask.ulMask;
- lpDest->res.resBitMask.ulPropTag = lpSrc->res.resBitMask.ulPropTag;
- break;
- case RES_SIZE:
- lpDest->res.resSize.cb = lpSrc->res.resSize.cb;
- lpDest->res.resSize.relop = lpSrc->res.resSize.relop;
- lpDest->res.resSize.ulPropTag = lpSrc->res.resSize.ulPropTag;
- break;
- case RES_EXIST:
- lpDest->res.resExist.ulPropTag = lpSrc->res.resExist.ulPropTag;
- break;
- case RES_SUBRESTRICTION:
- lpDest->res.resSub.ulSubObject = lpSrc->res.resSub.ulSubObject;
- hr = MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **)&lpDest->res.resSub.lpRes);
- if (hr != hrSuccess)
- return hr;
- return HrCopySRestriction(lpDest->res.resSub.lpRes, lpSrc->res.resSub.lpRes, lpBase);
- case RES_COMMENT:
- lpDest->res.resComment.cValues = lpSrc->res.resComment.cValues;
- lpDest->res.resComment.lpRes = NULL;
- if (lpSrc->res.resComment.cValues > 0)
- {
- hr = MAPIAllocateMore(sizeof(SPropValue) * lpSrc->res.resComment.cValues, lpBase, (void **) &lpDest->res.resComment.lpProp);
- if (hr != hrSuccess)
- return hr;
- hr = HrCopyPropertyArray(lpSrc->res.resComment.lpProp, lpSrc->res.resComment.cValues, lpDest->res.resComment.lpProp, lpBase);
- if (hr != hrSuccess)
- return hr;
- }
- if (lpSrc->res.resComment.lpRes) {
- hr = MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **) &lpDest->res.resComment.lpRes);
- if (hr != hrSuccess)
- return hr;
- hr = HrCopySRestriction(lpDest->res.resComment.lpRes, lpSrc->res.resComment.lpRes, lpBase);
- }
- break;
- }
- return hr;
- }
- HRESULT Util::HrCopyActions(ACTIONS *lpDest, const ACTIONS *lpSrc,
- void *lpBase)
- {
- unsigned int i;
- lpDest->cActions = lpSrc->cActions;
- lpDest->ulVersion = lpSrc->ulVersion;
- HRESULT hr = MAPIAllocateMore(sizeof(ACTION) * lpSrc->cActions, lpBase,
- reinterpret_cast<void **>(&lpDest->lpAction));
- if (hr != hrSuccess)
- return hr;
- memset(lpDest->lpAction, 0, sizeof(ACTION) * lpSrc->cActions);
- for (i = 0; i < lpSrc->cActions; ++i) {
- hr = HrCopyAction(&lpDest->lpAction[i], &lpSrc->lpAction[i], lpBase);
- if(hr != hrSuccess)
- return hr;
- }
- return hrSuccess;
- }
- HRESULT Util::HrCopyAction(ACTION *lpDest, const ACTION *lpSrc, void *lpBase)
- {
- HRESULT hr = hrSuccess;
- lpDest->acttype = lpSrc->acttype;
- lpDest->ulActionFlavor = lpSrc->ulActionFlavor;
- lpDest->lpRes = NULL;
- lpDest->lpPropTagArray = NULL;
- lpDest->ulFlags = lpSrc->ulFlags;
- switch(lpSrc->acttype) {
- case OP_MOVE:
- case OP_COPY:
- lpDest->actMoveCopy.cbStoreEntryId = lpSrc->actMoveCopy.cbStoreEntryId;
- hr = MAPIAllocateMore(lpSrc->actMoveCopy.cbStoreEntryId, lpBase, (void **) &lpDest->actMoveCopy.lpStoreEntryId);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->actMoveCopy.lpStoreEntryId, lpSrc->actMoveCopy.lpStoreEntryId, lpSrc->actMoveCopy.cbStoreEntryId);
- lpDest->actMoveCopy.cbFldEntryId = lpSrc->actMoveCopy.cbFldEntryId;
- hr = MAPIAllocateMore(lpSrc->actMoveCopy.cbFldEntryId, lpBase, (void **) &lpDest->actMoveCopy.lpFldEntryId);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->actMoveCopy.lpFldEntryId, lpSrc->actMoveCopy.lpFldEntryId, lpSrc->actMoveCopy.cbFldEntryId);
- break;
- case OP_REPLY:
- case OP_OOF_REPLY:
- lpDest->actReply.cbEntryId = lpSrc->actReply.cbEntryId;
- hr = MAPIAllocateMore(lpSrc->actReply.cbEntryId, lpBase, (void **) &lpDest->actReply.lpEntryId);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->actReply.lpEntryId, lpSrc->actReply.lpEntryId, lpSrc->actReply.cbEntryId);
- lpDest->actReply.guidReplyTemplate = lpSrc->actReply.guidReplyTemplate;
- break;
- case OP_DEFER_ACTION:
- lpDest->actDeferAction.cbData = lpSrc->actDeferAction.cbData;
- hr = MAPIAllocateMore(lpSrc->actDeferAction.cbData, lpBase, (void **)&lpDest->actDeferAction.pbData);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest->actDeferAction.pbData, lpSrc->actDeferAction.pbData, lpSrc->actDeferAction.cbData);
- break;
- case OP_BOUNCE:
- lpDest->scBounceCode = lpSrc->scBounceCode;
- break;
- case OP_FORWARD:
- case OP_DELEGATE:
- hr = MAPIAllocateMore(CbNewSRowSet(lpSrc->lpadrlist->cEntries), lpBase, reinterpret_cast<void **>(&lpDest->lpadrlist));
- if (hr != hrSuccess)
- return hr;
- return HrCopySRowSet((LPSRowSet)lpDest->lpadrlist, (LPSRowSet)lpSrc->lpadrlist, lpBase);
- case OP_TAG:
- return HrCopyProperty(&lpDest->propTag, &lpSrc->propTag, lpBase);
- case OP_DELETE:
- case OP_MARK_AS_READ:
- break;
- default:
- break;
- }
- return hr;
- }
- HRESULT Util::HrCopySRowSet(LPSRowSet lpDest, const SRowSet *lpSrc,
- void *lpBase)
- {
- unsigned int i;
- lpDest->cRows = 0;
- for (i = 0; i < lpSrc->cRows; ++i) {
- HRESULT hr = HrCopySRow(&lpDest->aRow[i], &lpSrc->aRow[i], lpBase);
- if (hr != hrSuccess)
- return hr;
- ++lpDest->cRows;
- }
- return hrSuccess;
- }
- HRESULT Util::HrCopySRow(LPSRow lpDest, const SRow *lpSrc, void *lpBase)
- {
- HRESULT hr;
- lpDest->cValues = lpSrc->cValues;
- if (lpBase)
- hr = MAPIAllocateMore(sizeof(SPropValue) * lpSrc->cValues, lpBase, (void **) &lpDest->lpProps);
- else
- hr = MAPIAllocateBuffer(sizeof(SPropValue) * lpSrc->cValues, (void **) &lpDest->lpProps);
- if (hr != hrSuccess)
- return hr;
- return HrCopyPropertyArray(lpSrc->lpProps, lpSrc->cValues, lpDest->lpProps, lpBase ? lpBase : lpDest->lpProps);
- }
- HRESULT Util::HrCopyPropTagArray(const SPropTagArray *lpSrc,
- LPSPropTagArray *lppDest)
- {
- SPropTagArrayPtr ptrPropTagArray;
- HRESULT hr = MAPIAllocateBuffer(CbNewSPropTagArray(lpSrc->cValues), &~ptrPropTagArray);
- if (hr != hrSuccess)
- return hr;
- memcpy(ptrPropTagArray->aulPropTag, lpSrc->aulPropTag, lpSrc->cValues * sizeof *lpSrc->aulPropTag);
- ptrPropTagArray->cValues = lpSrc->cValues;
- *lppDest = ptrPropTagArray.release();
- return hrSuccess;
- }
- HRESULT Util::HrCopyUnicodePropTagArray(ULONG ulFlags,
- const SPropTagArray *lpSrc, LPSPropTagArray *lppDest)
- {
- LPSPropTagArray lpPropTagArray = NULL;
- HRESULT hr = MAPIAllocateBuffer(CbNewSPropTagArray(lpSrc->cValues),
- reinterpret_cast<void **>(&lpPropTagArray));
- if (hr != hrSuccess)
- return hr;
- for (ULONG n = 0; n < lpSrc->cValues; ++n) {
- if (PROP_TYPE(lpSrc->aulPropTag[n]) == PT_STRING8 || PROP_TYPE(lpSrc->aulPropTag[n]) == PT_UNICODE)
- lpPropTagArray->aulPropTag[n] = CHANGE_PROP_TYPE(lpSrc->aulPropTag[n], ((ulFlags & MAPI_UNICODE) ? PT_UNICODE : PT_STRING8));
- else
- lpPropTagArray->aulPropTag[n] = lpSrc->aulPropTag[n];
- }
- lpPropTagArray->cValues = lpSrc->cValues;
- *lppDest = lpPropTagArray;
- return hrSuccess;
- }
- HRESULT Util::HrCopyBinary(ULONG ulSize, const BYTE *lpSrc,
- ULONG *lpulDestSize, LPBYTE *lppDest, LPVOID lpBase)
- {
- HRESULT hr;
- LPBYTE lpDest = NULL;
- if (ulSize == 0) {
- *lpulDestSize = 0;
- *lppDest = NULL;
- return hrSuccess;
- }
- if (lpBase)
- hr = MAPIAllocateMore(ulSize, lpBase, (void **)&lpDest);
- else
- hr = MAPIAllocateBuffer(ulSize, (void **) &lpDest);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpDest, lpSrc, ulSize);
- *lppDest = lpDest;
- *lpulDestSize = ulSize;
- return hrSuccess;
- }
- HRESULT Util::HrCopyEntryId(ULONG ulSize, const ENTRYID *lpSrc,
- ULONG *lpulDestSize, LPENTRYID* lppDest, LPVOID lpBase)
- {
- return HrCopyBinary(ulSize, (const BYTE *)lpSrc, lpulDestSize,
- (LPBYTE *)lppDest, lpBase);
- }
- template<typename T> static int twcmp(T a, T b)
- {
- return (a < b) ? -1 : (a == b) ? 0 : 1;
- }
- int Util::CompareSBinary(const SBinary &sbin1, const SBinary &sbin2)
- {
- if (sbin1.lpb && sbin2.lpb && sbin1.cb > 0 && sbin1.cb == sbin2.cb)
- return memcmp(sbin1.lpb, sbin2.lpb, sbin1.cb);
- else
- return twcmp(sbin1.cb, sbin2.cb);
- }
- HRESULT Util::CompareProp(const SPropValue *lpProp1, const SPropValue *lpProp2,
- const ECLocale &locale, int *lpCompareResult)
- {
- HRESULT hr = hrSuccess;
- int nCompareResult = 0;
- unsigned int i;
- if (lpProp1 == NULL || lpProp2 == NULL || lpCompareResult == NULL)
- return MAPI_E_INVALID_PARAMETER;
- if (PROP_TYPE(lpProp1->ulPropTag) != PROP_TYPE(lpProp2->ulPropTag))
- return MAPI_E_INVALID_PARAMETER;
- switch(PROP_TYPE(lpProp1->ulPropTag)) {
- case PT_I2:
- nCompareResult = twcmp(lpProp1->Value.i, lpProp2->Value.i);
- break;
- case PT_LONG:
- nCompareResult = twcmp(lpProp1->Value.ul, lpProp2->Value.ul);
- break;
- case PT_R4:
- nCompareResult = twcmp(lpProp1->Value.flt, lpProp2->Value.flt);
- break;
- case PT_BOOLEAN:
- nCompareResult = twcmp(lpProp1->Value.b, lpProp2->Value.b);
- break;
- case PT_DOUBLE:
- case PT_APPTIME:
- nCompareResult = twcmp(lpProp1->Value.dbl, lpProp2->Value.dbl);
- break;
- case PT_I8:
- nCompareResult = twcmp(lpProp1->Value.li.QuadPart, lpProp2->Value.li.QuadPart);
- break;
- case PT_UNICODE:
- if (lpProp1->Value.lpszW && lpProp2->Value.lpszW)
- if (lpProp2->ulPropTag == PR_ANR)
- nCompareResult = wcs_icontains(lpProp1->Value.lpszW, lpProp2->Value.lpszW, locale);
- else
- nCompareResult = wcs_icompare(lpProp1->Value.lpszW, lpProp2->Value.lpszW, locale);
- else
- nCompareResult = lpProp1->Value.lpszW != lpProp2->Value.lpszW;
- break;
- case PT_STRING8:
- if (lpProp1->Value.lpszA && lpProp2->Value.lpszA)
- if(lpProp2->ulPropTag == PR_ANR) {
- nCompareResult = str_icontains(lpProp1->Value.lpszA, lpProp2->Value.lpszA, locale);
- } else
- nCompareResult = str_icompare(lpProp1->Value.lpszA, lpProp2->Value.lpszA, locale);
- else
- nCompareResult = lpProp1->Value.lpszA != lpProp2->Value.lpszA;
- break;
- case PT_SYSTIME:
- case PT_CURRENCY:
- if (lpProp1->Value.cur.Hi == lpProp2->Value.cur.Hi)
- nCompareResult = twcmp(lpProp1->Value.cur.Lo, lpProp2->Value.cur.Lo);
- else
- nCompareResult = twcmp(lpProp1->Value.cur.Hi, lpProp2->Value.cur.Hi);
- break;
- case PT_BINARY:
- nCompareResult = CompareSBinary(lpProp1->Value.bin, lpProp2->Value.bin);
- break;
- case PT_CLSID:
- nCompareResult = memcmp(lpProp1->Value.lpguid, lpProp2->Value.lpguid, sizeof(GUID));
- break;
-
- case PT_MV_I2:
- if (lpProp1->Value.MVi.cValues == lpProp2->Value.MVi.cValues) {
- for (i = 0; i < lpProp1->Value.MVi.cValues; ++i) {
- nCompareResult = twcmp(lpProp1->Value.MVi.lpi[i], lpProp2->Value.MVi.lpi[i]);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVi.cValues, lpProp2->Value.MVi.cValues);
- break;
- case PT_MV_LONG:
- if (lpProp1->Value.MVl.cValues == lpProp2->Value.MVl.cValues) {
- for (i = 0; i < lpProp1->Value.MVl.cValues; ++i) {
- nCompareResult = twcmp(lpProp1->Value.MVl.lpl[i], lpProp2->Value.MVl.lpl[i]);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVl.cValues, lpProp2->Value.MVl.cValues);
- break;
- case PT_MV_R4:
- if (lpProp1->Value.MVflt.cValues == lpProp2->Value.MVflt.cValues) {
- for (i = 0; i < lpProp1->Value.MVflt.cValues; ++i) {
- nCompareResult = twcmp(lpProp1->Value.MVflt.lpflt[i], lpProp2->Value.MVflt.lpflt[i]);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVflt.cValues, lpProp2->Value.MVflt.cValues);
- break;
- case PT_MV_DOUBLE:
- case PT_MV_APPTIME:
- if (lpProp1->Value.MVdbl.cValues == lpProp2->Value.MVdbl.cValues) {
- for (i = 0; i < lpProp1->Value.MVdbl.cValues; ++i) {
- nCompareResult = twcmp(lpProp1->Value.MVdbl.lpdbl[i], lpProp2->Value.MVdbl.lpdbl[i]);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVdbl.cValues, lpProp2->Value.MVdbl.cValues);
- break;
- case PT_MV_I8:
- if (lpProp1->Value.MVli.cValues == lpProp2->Value.MVli.cValues) {
- for (i = 0; i < lpProp1->Value.MVli.cValues; ++i) {
- nCompareResult = twcmp(lpProp1->Value.MVli.lpli[i].QuadPart, lpProp2->Value.MVli.lpli[i].QuadPart);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVli.cValues, lpProp2->Value.MVli.cValues);
- break;
- case PT_MV_SYSTIME:
- case PT_MV_CURRENCY:
- if (lpProp1->Value.MVcur.cValues == lpProp2->Value.MVcur.cValues) {
- for (i = 0; i < lpProp1->Value.MVcur.cValues; ++i) {
- if(lpProp1->Value.MVcur.lpcur[i].Hi == lpProp2->Value.MVcur.lpcur[i].Hi)
- nCompareResult = twcmp(lpProp1->Value.MVcur.lpcur[i].Lo, lpProp2->Value.MVcur.lpcur[i].Lo);
- else
- nCompareResult = twcmp(lpProp1->Value.MVcur.lpcur[i].Hi, lpProp2->Value.MVcur.lpcur[i].Hi);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = lpProp1->Value.MVcur.cValues == lpProp2->Value.MVcur.cValues;
- break;
- case PT_MV_CLSID:
- if (lpProp1->Value.MVguid.cValues == lpProp2->Value.MVguid.cValues)
- nCompareResult = memcmp(lpProp1->Value.MVguid.lpguid, lpProp2->Value.MVguid.lpguid, sizeof(GUID)*lpProp1->Value.MVguid.cValues);
- else
- nCompareResult = twcmp(lpProp1->Value.MVguid.cValues, lpProp2->Value.MVguid.cValues);
- break;
- case PT_MV_BINARY:
- if (lpProp1->Value.MVbin.cValues == lpProp2->Value.MVbin.cValues) {
- for (i = 0; i < lpProp1->Value.MVbin.cValues; ++i) {
- nCompareResult = CompareSBinary(lpProp1->Value.MVbin.lpbin[i], lpProp2->Value.MVbin.lpbin[i]);
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVbin.cValues, lpProp2->Value.MVbin.cValues);
- break;
- case PT_MV_UNICODE:
- if (lpProp1->Value.MVszW.cValues == lpProp2->Value.MVszW.cValues) {
- for (i = 0; i < lpProp1->Value.MVszW.cValues; ++i) {
- if (lpProp1->Value.MVszW.lppszW[i] && lpProp2->Value.MVszW.lppszW[i])
- nCompareResult = wcscasecmp(lpProp1->Value.MVszW.lppszW[i], lpProp2->Value.MVszW.lppszW[i]);
- else
- nCompareResult = lpProp1->Value.MVszW.lppszW[i] != lpProp2->Value.MVszW.lppszW[i];
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVszA.cValues, lpProp2->Value.MVszA.cValues);
- break;
- case PT_MV_STRING8:
- if (lpProp1->Value.MVszA.cValues == lpProp2->Value.MVszA.cValues) {
- for (i = 0; i < lpProp1->Value.MVszA.cValues; ++i) {
- if (lpProp1->Value.MVszA.lppszA[i] && lpProp2->Value.MVszA.lppszA[i])
- nCompareResult = strcasecmp(lpProp1->Value.MVszA.lppszA[i], lpProp2->Value.MVszA.lppszA[i]);
- else
- nCompareResult = lpProp1->Value.MVszA.lppszA[i] != lpProp2->Value.MVszA.lppszA[i];
- if(nCompareResult != 0)
- break;
- }
- } else
- nCompareResult = twcmp(lpProp1->Value.MVszA.cValues, lpProp2->Value.MVszA.cValues);
- break;
- default:
- return MAPI_E_INVALID_TYPE;
- }
- *lpCompareResult = nCompareResult;
- return hr;
- }
- unsigned int Util::PropSize(const SPropValue *lpProp)
- {
- unsigned int ulSize, i;
- if(lpProp == NULL)
- return 0;
- switch(PROP_TYPE(lpProp->ulPropTag)) {
- case PT_I2:
- return 2;
- case PT_BOOLEAN:
- case PT_R4:
- case PT_LONG:
- return 4;
- case PT_APPTIME:
- case PT_DOUBLE:
- case PT_I8:
- return 8;
- case PT_UNICODE:
- return lpProp->Value.lpszW ? wcslen(lpProp->Value.lpszW) : 0;
- case PT_STRING8:
- return lpProp->Value.lpszA ? strlen(lpProp->Value.lpszA) : 0;
- case PT_SYSTIME:
- case PT_CURRENCY:
- return 8;
- case PT_BINARY:
- return lpProp->Value.bin.cb;
- case PT_CLSID:
- return sizeof(GUID);
- case PT_MV_I2:
- return 2 * lpProp->Value.MVi.cValues;
- case PT_MV_R4:
- return 4 * lpProp->Value.MVflt.cValues;
- case PT_MV_LONG:
- return 4 * lpProp->Value.MVl.cValues;
- case PT_MV_APPTIME:
- case PT_MV_DOUBLE:
- return 8 * lpProp->Value.MVdbl.cValues;
- case PT_MV_I8:
- return 8 * lpProp->Value.MVli.cValues;
- case PT_MV_UNICODE:
- ulSize = 0;
- for (i = 0; i < lpProp->Value.MVszW.cValues; ++i)
- ulSize += (lpProp->Value.MVszW.lppszW[i]) ? wcslen(lpProp->Value.MVszW.lppszW[i]) : 0;
- return ulSize;
- case PT_MV_STRING8:
- ulSize = 0;
- for (i = 0; i < lpProp->Value.MVszA.cValues; ++i)
- ulSize += (lpProp->Value.MVszA.lppszA[i]) ? strlen(lpProp->Value.MVszA.lppszA[i]) : 0;
- return ulSize;
- case PT_MV_SYSTIME:
- case PT_MV_CURRENCY:
- return 8 * lpProp->Value.MVcur.cValues;
- case PT_MV_BINARY:
- ulSize = 0;
- for (i = 0; i < lpProp->Value.MVbin.cValues; ++i)
- ulSize+= lpProp->Value.MVbin.lpbin[i].cb;
- return ulSize;
- case PT_MV_CLSID:
- return sizeof(GUID) * lpProp->Value.MVguid.cValues;
- default:
- return 0;
- }
- }
- #define BUFSIZE 65536
- HRESULT Util::HrTextToHtml(IStream *text, IStream *html, ULONG ulCodepage)
- {
- HRESULT hr = hrSuccess;
- ULONG cRead;
- std::wstring strHtml;
- WCHAR lpBuffer[BUFSIZE];
- static const char header1[] = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n" \
- "<HTML>\n" \
- "<HEAD>\n" \
- "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=";
-
- static const char header2[] = "\">\n" \
- "<META NAME=\"Generator\" CONTENT=\"Kopano HTML builder 1.0\">\n" \
- "<TITLE></TITLE>\n" \
- "</HEAD>\n" \
- "<BODY>\n" \
- "<!-- Converted from text/plain format -->\n" \
- "\n" \
- "<P><FONT STYLE=\"font-family: courier\" SIZE=2>\n";
-
- static const char footer[] = "</FONT>\n" \
- "</P>\n" \
- "\n" \
- "</BODY>" \
- "</HTML>";
- ULONG i = 0;
- size_t stRead = 0;
- size_t stWrite = 0;
- size_t stWritten;
- size_t err;
- const char *readBuffer = NULL;
- std::unique_ptr<char[]> writeBuffer;
- char *wPtr = NULL;
- iconv_t cd = (iconv_t)-1;
- const char *lpszCharset;
- hr = HrGetCharsetByCP(ulCodepage, &lpszCharset);
- if (hr != hrSuccess) {
-
- lpszCharset = "us-ascii";
- hr = hrSuccess;
- }
- cd = iconv_open(lpszCharset, CHARSET_WCHAR);
- if (cd == (iconv_t)-1) {
- hr = MAPI_E_BAD_CHARWIDTH;
- goto exit;
- }
- writeBuffer.reset(new(std::nothrow) char[BUFSIZE * 2]);
- if (writeBuffer == nullptr) {
- hr = MAPI_E_NOT_ENOUGH_MEMORY;
- goto exit;
- }
-
- hr = html->Write(header1, strlen(header1), NULL);
- if (hr != hrSuccess)
- goto exit;
- hr = html->Write(lpszCharset, strlen(lpszCharset), NULL);
- if (hr != hrSuccess)
- goto exit;
- hr = html->Write(header2, strlen(header2), NULL);
- if (hr != hrSuccess)
- goto exit;
- while (1) {
- strHtml.clear();
- hr = text->Read(lpBuffer, BUFSIZE*sizeof(WCHAR), &cRead);
- if (hr != hrSuccess)
- goto exit;
- if (cRead == 0)
- break;
- cRead /= sizeof(WCHAR);
-
- for (i = 0; i < cRead; ++i) {
- if (lpBuffer[i] != ' ') {
- std::wstring str;
- CHtmlEntity::CharToHtmlEntity(lpBuffer[i], str);
- strHtml += str;
- continue;
- }
- if ((i + 1) < cRead && lpBuffer[i+1] == ' ')
- strHtml += L" ";
- else
- strHtml += L" ";
- }
-
- readBuffer = (const char*)strHtml.c_str();
- stRead = strHtml.size() * sizeof(WCHAR);
- while (stRead > 0) {
- wPtr = writeBuffer.get();
- stWrite = BUFSIZE * 2;
- err = iconv(cd, iconv_HACK(&readBuffer), &stRead, &wPtr, &stWrite);
- stWritten = (BUFSIZE * 2) - stWrite;
-
- hr = html->Write(writeBuffer.get(), stWritten, NULL);
- if (hr != hrSuccess)
- goto exit;
- if (err != static_cast<size_t>(-1))
- continue;
-
- std::string strHTMLUnicode = "&#";
- strHTMLUnicode += stringify(*(WCHAR*)readBuffer);
- strHTMLUnicode += ";";
- hr = html->Write(strHTMLUnicode.c_str(), strHTMLUnicode.length(), NULL);
- if (hr != hrSuccess)
- goto exit;
-
- readBuffer += sizeof(WCHAR);
- stRead -= sizeof(WCHAR);
- }
- }
-
- hr = html->Write(footer, strlen(footer), NULL);
- exit:
- if (cd != (iconv_t)-1)
- iconv_close(cd);
- return hr;
- }
- HRESULT Util::HrTextToHtml(const WCHAR *text, std::string &strHTML, ULONG ulCodepage)
- {
- HRESULT hr = hrSuccess;
- const char *lpszCharset;
- wstring wHTML;
- hr = HrGetCharsetByCP(ulCodepage, &lpszCharset);
- if (hr != hrSuccess) {
-
- lpszCharset = "us-ascii";
- hr = hrSuccess;
- }
-
- for (ULONG i = 0; text[i] != '\0'; ++i) {
- if (text[i] != ' ') {
- std::wstring str;
- CHtmlEntity::CharToHtmlEntity(text[i], str);
- wHTML += str;
- continue;
- }
- if (text[i+1] == ' ')
- wHTML += L" ";
- else
- wHTML += L" ";
- }
- try {
- strHTML += convert_to<string>(lpszCharset, wHTML, rawsize(wHTML), CHARSET_WCHAR);
- } catch (const convert_exception &) {
- }
- return hr;
- }
- static const struct _rtfcodepages {
- int id;
- ULONG ulCodepage;
- } RTFCODEPAGES[] = {
- {437, 437},
- {708, 0},
- {709, 0},
- {710, 0},
- {711, 0},
- {720, 0},
- {819, 0},
- {850, 1252},
- {852, 1251},
- {860, 0},
- {862, 0},
- {863, 0},
- {864, 0},
- {865, 0},
- {866, 0},
- {874, 0},
- {932, 50220},
- {936, 936},
- {949, 0},
- {950, 0},
- {1250, 0},
- {1251, 0},
- {1252, 0},
- {1253, 0},
- {1254, 0},
- {1255, 0},
- {1256, 0},
- {1257, 0},
- {1258, 0},
- {1361, 0},
- };
- HRESULT Util::HrTextToRtf(IStream *text, IStream *rtf)
- {
- ULONG cRead;
- WCHAR c[BUFSIZE];
- static const char header[] = "{\\rtf1\\ansi\\ansicpg1252\\fromtext \\deff0{\\fonttbl\n" \
- "{\\f0\\fswiss Arial;}\n" \
- "{\\f1\\fmodern Courier New;}\n" \
- "{\\f2\\fnil\\fcharset2 Symbol;}\n" \
- "{\\f3\\fmodern\\fcharset0 Courier New;}}\n" \
- "{\\colortbl\\red0\\green0\\blue0;\\red0\\green0\\blue255;}\n" \
- "\\uc1\\pard\\plain\\deftab360 \\f0\\fs20 ";
- static const char footer[] = "}";
- ULONG i = 0;
- rtf->Write(header, strlen(header), NULL);
- while(1) {
- text->Read(c, BUFSIZE * sizeof(WCHAR), &cRead);
- if(cRead == 0)
- break;
- cRead /= sizeof(WCHAR);
- for (i = 0; i < cRead; ++i) {
- switch (c[i]) {
- case 0:
- break;
- case '\r':
- break;
- case '\n':
- rtf->Write("\\line\n", 6, nullptr);
- break;
- case '\\':
- rtf->Write("\\\\",2,NULL);
- break;
- case '{':
- rtf->Write("\\{",2,NULL);
- break;
- case '}':
- rtf->Write("\\}",2,NULL);
- break;
- case '\t':
- rtf->Write("\\tab ",5,NULL);
- break;
- case '\f':
- rtf->Write("\\page\n",6,NULL);
- break;
- default:
- if (c[i] < ' ' || (c[i] > 127 && c[i] <= 255)) {
- char hex[16];
- snprintf(hex, 16, "\\'%X", c[i]);
- rtf->Write(hex, strlen(hex), NULL);
- } else if (c[i] > 255) {
-
- char hex[16];
- snprintf(hex, 16, "\\u%hd ?", (signed short)c[i]);
- rtf->Write(hex, strlen(hex), NULL);
- } else {
- rtf->Write(&c[i], 1, NULL);
- }
- }
- }
- }
- rtf->Write(footer, strlen(footer), NULL);
- return hrSuccess;
- }
- LONG Util::FindPropInArray(const SPropTagArray *lpPropTags, ULONG ulPropTag)
- {
- unsigned int i = 0;
- if (!lpPropTags)
- return -1;
- for (i = 0; i < lpPropTags->cValues; ++i) {
- if(lpPropTags->aulPropTag[i] == ulPropTag)
- break;
- if(PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && PROP_ID(lpPropTags->aulPropTag[i]) == PROP_ID(ulPropTag))
- break;
- }
- if(i != lpPropTags->cValues)
- return i;
- return -1;
- }
- HRESULT Util::HrMAPIErrorToText(HRESULT hr, LPTSTR *lppszError, void *lpBase)
- {
- tstring strError;
- LPCTSTR lpszError = NULL;
- if (lppszError == NULL)
- return MAPI_E_INVALID_PARAMETER;
- switch(hr)
- {
- case MAPI_E_END_OF_SESSION:
- lpszError = _("End of Session");
- break;
- case MAPI_E_NETWORK_ERROR:
- lpszError = _("Connection lost");
- break;
- case MAPI_E_NO_ACCESS:
- lpszError = _("Access denied");
- break;
- case MAPI_E_FOLDER_CYCLE:
- lpszError = _("Unable to move or copy folders. Can't copy folder. A top-level can't be copied to one of its subfolders. Or, you may not have appropriate permissions for the folder. To check your permissions for the folder, right-click the folder, and then click Properties on the shortcut menu.");
- break;
- case MAPI_E_STORE_FULL:
- lpszError = _("The message store has reached its maximum size. To reduce the amount of data in this message store, select some items that you no longer need, and permanently (SHIFT + DEL) delete them.");
- break;
- case MAPI_E_USER_CANCEL:
- lpszError = _("The user canceled the operation, typically by clicking the Cancel button in a dialog box.");
- break;
- case MAPI_E_LOGON_FAILED:
- lpszError = _("A logon session could not be established.");
- break;
- case MAPI_E_COLLISION:
- lpszError = _("The name of the folder being moved or copied is the same as that of a subfolder in the destination folder. The message store provider requires that folder names be unique. The operation stops without completing.");
- break;
- case MAPI_W_PARTIAL_COMPLETION:
- lpszError = _("The operation succeeded, but not all entries were successfully processed, copied, deleted or moved");
- break;
- case MAPI_E_UNCONFIGURED:
- lpszError = _("The provider does not have enough information to complete the logon. Or, the service provider has not been configured.");
- break;
- case MAPI_E_FAILONEPROVIDER:
- lpszError = _("One of the providers cannot log on, but this error should not disable the other services.");
- break;
- case MAPI_E_DISK_ERROR:
- lpszError = _("A database error or I/O error has occurred.");
- break;
- case MAPI_E_HAS_FOLDERS:
- lpszError = _("The subfolder being deleted contains subfolders.");
- break;
- case MAPI_E_HAS_MESSAGES:
- lpszError = _("The subfolder being deleted contains messages.");
- break;
- default: {
- strError = _("No description available.");
- strError.append(1, ' ');
- strError.append(_("MAPI error code:"));
- strError.append(1, ' ');
- strError.append(tstringify(hr, true));
- lpszError = strError.c_str();
- }
- break;
- }
- if (lpBase == NULL)
- hr = MAPIAllocateBuffer((_tcslen(lpszError) + 1) * sizeof *lpszError, (void**)lppszError);
- else
- hr = MAPIAllocateMore((_tcslen(lpszError) + 1) * sizeof *lpszError, lpBase, (void**)lppszError);
- if (hr != hrSuccess)
- return hr;
- _tcscpy(*lppszError, lpszError);
- return hrSuccess;
- }
- bool Util::ValidatePropTagArray(const SPropTagArray *lpPropTagArray)
- {
- bool bResult = false;
- unsigned int i;
- if (lpPropTagArray == NULL)
- return true;
- for (i = 0; i < lpPropTagArray->cValues; ++i) {
- switch (PROP_TYPE(lpPropTagArray->aulPropTag[i]))
- {
- case PT_UNSPECIFIED:
- case PT_NULL:
- case PT_I2:
- case PT_I4:
- case PT_R4:
- case PT_R8:
- case PT_BOOLEAN:
- case PT_CURRENCY:
- case PT_APPTIME:
- case PT_SYSTIME:
- case PT_I8:
- case PT_STRING8:
- case PT_BINARY:
- case PT_UNICODE:
- case PT_CLSID:
- case PT_OBJECT:
- case PT_MV_I2:
- case PT_MV_LONG:
- case PT_MV_R4:
- case PT_MV_DOUBLE:
- case PT_MV_CURRENCY:
- case PT_MV_APPTIME:
- case PT_MV_SYSTIME:
- case PT_MV_BINARY:
- case PT_MV_STRING8:
- case PT_MV_UNICODE:
- case PT_MV_CLSID:
- case PT_MV_I8:
- case PT_ERROR:
- bResult = true;
- break;
- default:
- return false;
- }
- }
- return bResult;
- }
- HRESULT Util::HrStreamToString(IStream *sInput, std::string &strOutput) {
- HRESULT hr = hrSuccess;
- object_ptr<ECMemStream> lpMemStream;
- ULONG ulRead = 0;
- char buffer[BUFSIZE];
- LARGE_INTEGER zero = {{0,0}};
- if (sInput->QueryInterface(IID_ECMemStream, &~lpMemStream) == hrSuccess) {
-
- strOutput.append(lpMemStream->GetBuffer(), lpMemStream->GetSize());
- return hr;
- }
-
- hr = sInput->Seek(zero, SEEK_SET, NULL);
- if (hr != hrSuccess)
- return hr;
- while (1) {
- hr = sInput->Read(buffer, BUFSIZE, &ulRead);
- if (hr != hrSuccess || ulRead == 0)
- break;
- strOutput.append(buffer, ulRead);
- }
- return hr;
- }
- HRESULT Util::HrStreamToString(IStream *sInput, std::wstring &strOutput) {
- HRESULT hr = hrSuccess;
- object_ptr<ECMemStream> lpMemStream;
- ULONG ulRead = 0;
- char buffer[BUFSIZE];
- LARGE_INTEGER zero = {{0,0}};
- if (sInput->QueryInterface(IID_ECMemStream, &~lpMemStream) == hrSuccess) {
-
- strOutput.append((WCHAR*)lpMemStream->GetBuffer(), lpMemStream->GetSize() / sizeof(WCHAR));
- return hr;
- }
-
- hr = sInput->Seek(zero, SEEK_SET, NULL);
- if (hr != hrSuccess)
- return hr;
- while (1) {
- hr = sInput->Read(buffer, BUFSIZE, &ulRead);
- if (hr != hrSuccess || ulRead == 0)
- break;
- strOutput.append((WCHAR*)buffer, ulRead / sizeof(WCHAR));
- }
- return hr;
- }
- HRESULT Util::HrConvertStreamToWString(IStream *sInput, ULONG ulCodepage, std::wstring *wstrOutput)
- {
- const char *lpszCharset;
- convert_context converter;
- string data;
- HRESULT hr = HrGetCharsetByCP(ulCodepage, &lpszCharset);
- if (hr != hrSuccess) {
- lpszCharset = "us-ascii";
- hr = hrSuccess;
- }
- hr = HrStreamToString(sInput, data);
- if (hr != hrSuccess)
- return hr;
- try {
- wstrOutput->assign(converter.convert_to<wstring>(CHARSET_WCHAR"//IGNORE", data, rawsize(data), lpszCharset));
- } catch (std::exception &) {
- return MAPI_E_INVALID_PARAMETER;
- }
- return hrSuccess;
- }
- HRESULT Util::HrHtmlToText(IStream *html, IStream *text, ULONG ulCodepage)
- {
- std::wstring wstrHTML;
- CHtmlToTextParser parser;
- HRESULT hr = HrConvertStreamToWString(html, ulCodepage, &wstrHTML);
- if(hr != hrSuccess)
- return hr;
- if (!parser.Parse(string_strip_nuls(wstrHTML).c_str()))
- return MAPI_E_CORRUPT_DATA;
- std::wstring &strText = parser.GetText();
- return text->Write(strText.data(), (strText.size()+1)*sizeof(WCHAR), NULL);
- }
- HRESULT Util::HrHtmlToRtf(const WCHAR *lpwHTML, std::string &strRTF)
- {
- int tag = 0, type = 0;
- stack<unsigned int> stackTag;
- size_t pos = 0;
- bool inTag = false;
- int ulCommentMode = 0;
- int ulStyleMode = 0;
- int ulParMode = 0;
- bool bFirstText = true;
- bool bPlainCRLF = false;
- if (lpwHTML == NULL)
- return MAPI_E_INVALID_PARAMETER;
-
- strRTF = "{\\rtf1\\ansi\\ansicpg1252\\fromhtml1 \\deff0{\\fonttbl\r\n"
- "{\\f0\\fswiss\\fcharset0 Arial;}\r\n"
- "{\\f1\\fmodern Courier New;}\r\n"
- "{\\f2\\fnil\\fcharset2 Symbol;}\r\n"
- "{\\f3\\fmodern\\fcharset0 Courier New;}\r\n"
- "{\\f4\\fswiss\\fcharset0 Arial;}\r\n"
- "{\\f5\\fswiss Tahoma;}\r\n"
- "{\\f6\\fswiss\\fcharset0 Times New Roman;}}\r\n"
- "{\\colortbl\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green0\\blue255;}\r\n"
- "\\uc1\\pard\\plain\\deftab360 \\f0\\fs24 ";
-
- stackTag.push(RTF_OUTHTML);
-
-
-
- while (lpwHTML[pos]) {
- type = RTF_TAG_TYPE_UNK;
-
- if(lpwHTML[pos] == '<') {
- bPlainCRLF = false;
-
-
- if(StrCaseCompare(lpwHTML, L"<HTML", pos)) {
- type = RTF_TAG_TYPE_HTML;
- } else if(StrCaseCompare(lpwHTML, L"</HTML", pos)) {
- type = RTF_TAG_TYPE_HTML;
- } else if(StrCaseCompare(lpwHTML, L"<HEAD", pos)) {
- type = RTF_TAG_TYPE_HEAD;
- } else if(StrCaseCompare(lpwHTML, L"</HEAD", pos)) {
- type = RTF_TAG_TYPE_HEAD;
- } else if(StrCaseCompare(lpwHTML, L"<BODY", pos)) {
- type = RTF_TAG_TYPE_BODY;
- } else if(StrCaseCompare(lpwHTML, L"</BODY", pos)) {
- type = RTF_TAG_TYPE_BODY;
- } else if(StrCaseCompare(lpwHTML, L"<P", pos)) {
- type = RTF_TAG_TYPE_P;
- bPlainCRLF = true;
- } else if(StrCaseCompare(lpwHTML, L"</P", pos)) {
- type = RTF_TAG_TYPE_P;
- bPlainCRLF = true;
- } else if(StrCaseCompare(lpwHTML, L"<DIV", pos)) {
- type = RTF_TAG_TYPE_ENDP;
- } else if(StrCaseCompare(lpwHTML, L"</DIV", pos)) {
- type = RTF_TAG_TYPE_ENDP;
- bPlainCRLF = true;
- } else if(StrCaseCompare(lpwHTML, L"<SPAN", pos)) {
- type = RTF_TAG_TYPE_STARTP;
- } else if(StrCaseCompare(lpwHTML, L"</SPAN", pos)) {
- type = RTF_TAG_TYPE_STARTP;
- } else if(StrCaseCompare(lpwHTML, L"<A", pos)) {
- type = RTF_TAG_TYPE_STARTP;
- } else if(StrCaseCompare(lpwHTML, L"</A", pos)) {
- type = RTF_TAG_TYPE_STARTP;
- } else if(StrCaseCompare(lpwHTML, L"<BR", pos)) {
- type = RTF_TAG_TYPE_BR;
- bPlainCRLF = true;
- } else if(StrCaseCompare(lpwHTML, L"<PRE", pos)) {
- type = RTF_TAG_TYPE_PRE;
- } else if(StrCaseCompare(lpwHTML, L"</PRE", pos)) {
- type = RTF_TAG_TYPE_PRE;
- } else if(StrCaseCompare(lpwHTML, L"<FONT", pos)) {
- type = RTF_TAG_TYPE_FONT;
- } else if(StrCaseCompare(lpwHTML, L"</FONT", pos)) {
- type = RTF_TAG_TYPE_FONT;
- } else if(StrCaseCompare(lpwHTML, L"<META", pos)) {
- type = RTF_TAG_TYPE_HEADER;
- } else if(StrCaseCompare(lpwHTML, L"<LINK", pos)) {
- type = RTF_TAG_TYPE_HEADER;
- } else if (StrCaseCompare(lpwHTML, L"<H", pos) && iswdigit(lpwHTML[pos+2])) {
- type = RTF_TAG_TYPE_HEADER;
- } else if (StrCaseCompare(lpwHTML, L"</H", pos) && iswdigit(lpwHTML[pos+3])) {
- type = RTF_TAG_TYPE_HEADER;
- } else if(StrCaseCompare(lpwHTML, L"<TITLE", pos)) {
- type = RTF_TAG_TYPE_TITLE;
- } else if(StrCaseCompare(lpwHTML, L"</TITLE", pos)) {
- type = RTF_TAG_TYPE_TITLE;
- } else if(StrCaseCompare(lpwHTML, L"<PLAIN", pos)) {
- type = RTF_TAG_TYPE_FONT;
- } else if(StrCaseCompare(lpwHTML, L"</PLAIN", pos)) {
- type = RTF_TAG_TYPE_FONT;
- }
- if (StrCaseCompare(lpwHTML, L"</", pos))
- type |= RTF_FLAG_CLOSE;
- }
-
- if(type & RTF_FLAG_CLOSE) {
- switch(type & 0xF0) {
- case RTF_TAG_TYPE_HEAD:
- if(!stackTag.empty() && stackTag.top() == RTF_INHEAD)
- stackTag.pop();
- break;
- case RTF_TAG_TYPE_BODY:
- if(!stackTag.empty() && stackTag.top() == RTF_INBODY)
- stackTag.pop();
- break;
- case RTF_TAG_TYPE_HTML:
- if(!stackTag.empty() && stackTag.top() == RTF_INHTML)
- stackTag.pop();
- break;
- default:
- break;
- }
- }
-
-
- if(lpwHTML[pos] == '<' && !inTag) {
- if(StrCaseCompare(lpwHTML, L"<!--", pos))
- ++ulCommentMode;
-
- if(ulCommentMode == 0) {
- if(StrCaseCompare(lpwHTML, L"<STYLE", pos))
- ulStyleMode = 1;
- else if(StrCaseCompare(lpwHTML, L"</STYLE", pos)) {
- if(ulStyleMode == 3) {
-
- strRTF += "}";
- }
- ulStyleMode = 0;
- } else if(StrCaseCompare(lpwHTML, L"<DIV", pos) || StrCaseCompare(lpwHTML, L"<P", pos)) {
- ulParMode = 1;
- } else if(StrCaseCompare(lpwHTML, L"</DIV", pos) || StrCaseCompare(lpwHTML, L"</P", pos)) {
- ulParMode = 0;
- }
- }
-
- if(ulCommentMode < 2 && ulStyleMode < 2) {
- strRTF += "\r\n{\\*\\htmltag" + stringify((ulParMode == 2 ? RTF_FLAG_INPAR : 0) | tag | type | stackTag.top()) + " ";
- inTag = true;
- bFirstText = true;
-
- if(ulCommentMode)
-
- ++ulCommentMode;
- }
- }
-
-
- if(lpwHTML[pos] == '\r') {
-
- } else if(lpwHTML[pos] == '\n') {
- if(inTag || ulCommentMode || ulStyleMode)
- strRTF += " ";
- else
- strRTF += "\r\n{\\*\\htmltag" + stringify((ulParMode == 2 ? RTF_FLAG_INPAR : 0) | stackTag.top()) + " \\par }";
- } else if(lpwHTML[pos] == '\t') {
- if(inTag || ulCommentMode || ulStyleMode)
- strRTF += "\\tab ";
- else
- strRTF += "\r\n{\\*\\htmltag" + stringify((ulParMode == 2 ? RTF_FLAG_INPAR : 0) | stackTag.top()) + " \\tab }";
- } else if(lpwHTML[pos] == '{') {
- strRTF += "\\{";
- } else if(lpwHTML[pos] == '}') {
- strRTF += "\\}";
- } else if(lpwHTML[pos] == '\\') {
- strRTF += "\\\\";
- } else if(lpwHTML[pos] > 127) {
-
- char hex[12];
- snprintf(hex, 12, "\\u%hd ?", (signed short)lpwHTML[pos]);
- strRTF += hex;
- } else if(StrCaseCompare(lpwHTML, L" ", pos)) {
- if(inTag || ulCommentMode || ulStyleMode)
- strRTF += " ";
- else
- strRTF += "\r\n{\\*\\htmltag64}{\\*\\htmltag" + stringify((ulParMode == 2 ? RTF_FLAG_INPAR : 0) | RTF_TAG_TYPE_STARTP | stackTag.top()) + " }";
-
- pos+=5;
- } else if(!inTag && !ulCommentMode && !ulStyleMode && lpwHTML[pos] == '&' && CHtmlEntity::validateHtmlEntity(std::wstring(lpwHTML + pos, 10)) ) {
- size_t semicolon = pos;
- while (lpwHTML[semicolon] && lpwHTML[semicolon] != ';')
- ++semicolon;
- if (lpwHTML[semicolon]) {
- std::wstring strEntity;
- WCHAR c;
- std::string strChar;
- strEntity.assign(lpwHTML + pos+1, semicolon-pos-1);
- c = CHtmlEntity::HtmlEntityToChar(strEntity);
- if (c > 32 && c < 128)
- strChar = c;
- else {
-
- char hex[12];
- snprintf(hex, 12, "\\u%hd ?", (signed short)c);
- strChar = hex;
- }
-
- strRTF += std::string("\\htmlrtf ") + strChar + "\\htmlrtf0{\\*\\htmltag" +
- stringify((ulParMode == 2 ? RTF_FLAG_INPAR : 0) | RTF_TAG_TYPE_STARTP | stackTag.top()) +
- "&" + convert_to<string>(strEntity) + ";}";
- pos += strEntity.size() + 2;
- continue;
- }
- } else {
- if (!inTag && bFirstText)
- bFirstText = false;
- strRTF += lpwHTML[pos];
- }
-
- if(lpwHTML[pos] == '>' && (inTag || ulCommentMode)) {
- if(!ulCommentMode && ulStyleMode < 2)
- strRTF += "}";
-
- if(pos > 2 && StrCaseCompare(lpwHTML, L"-->", pos-2) && ulCommentMode) {
- --ulCommentMode;
-
- if(ulCommentMode == 1) {
- ulCommentMode = 0;
- strRTF += "}";
- }
- }
- if(pos > 6 && StrCaseCompare(lpwHTML, L"/STYLE>", pos-6) && ulStyleMode) {
- ulStyleMode = 0;
- strRTF += "}";
- }
- if(ulStyleMode == 1)
- ++ulStyleMode;
-
- if(ulParMode == 1)
- ++ulParMode;
-
- if(ulStyleMode == 2) {
-
- ulStyleMode = 3;
- strRTF += "\r\n{\\*\\htmltag" + stringify(RTF_TAG_TYPE_UNK | stackTag.top()) + " ";
- }
-
- if (!ulStyleMode && !ulCommentMode)
-
- strRTF += "{\\*\\htmltag64}";
- inTag = false;
- if (bPlainCRLF && !ulCommentMode && !ulStyleMode)
-
- strRTF += "\\htmlrtf \\line \\htmlrtf0 ";
- }
-
-
-
- ++pos;
-
- if(!(type & RTF_FLAG_CLOSE)) {
- switch(type & 0xF0) {
- case RTF_TAG_TYPE_HTML:
- stackTag.push(RTF_INHTML);
- break;
- case RTF_TAG_TYPE_BODY:
- stackTag.push(RTF_INBODY);
- break;
- case RTF_TAG_TYPE_HEAD:
- stackTag.push(RTF_INHEAD);
- break;
- default:
- break;
- }
- }
- }
-
- strRTF +="}\r\n";
- return hrSuccess;
- }
- HRESULT Util::HrHtmlToRtf(IStream *html, IStream *rtf, unsigned int ulCodepage)
- {
- wstring wstrHTML;
- std::string strRTF;
- HRESULT hr = HrConvertStreamToWString(html, ulCodepage, &wstrHTML);
- if(hr != hrSuccess)
- return hr;
- hr = HrHtmlToRtf(wstrHTML.c_str(), strRTF);
- if(hr != hrSuccess)
- return hr;
- return rtf->Write(strRTF.c_str(), strRTF.size(), NULL);
- }
- HRESULT Util::bin2hex(ULONG inLength, const BYTE *input, char **output,
- void *parent)
- {
- static const char digits[] = "0123456789ABCDEF";
- char *buffer = NULL;
- HRESULT hr;
- ULONG i, j;
- if (parent)
- hr = MAPIAllocateMore(inLength*2+1, parent, (void**)&buffer);
- else
- hr = MAPIAllocateBuffer(inLength*2+1, (void**)&buffer);
- if (hr != hrSuccess)
- return hr;
- for (i = 0, j = 0; i < inLength; ++i) {
- buffer[j++] = digits[input[i]>>4];
- buffer[j++] = digits[input[i]&0x0F];
- }
- buffer[j] = '\0';
- *output = buffer;
- return hrSuccess;
- }
- HRESULT Util::hex2bin(const char *input, size_t len, ULONG *outLength, LPBYTE *output, void *parent)
- {
- HRESULT hr;
- LPBYTE buffer = NULL;
- if (len % 2 != 0)
- return MAPI_E_INVALID_PARAMETER;
- if (parent)
- hr = MAPIAllocateMore(len/2+1, parent, (void**)&buffer);
- else
- hr = MAPIAllocateBuffer(len/2+1, (void**)&buffer);
- if (hr != hrSuccess)
- goto exit;
- hr = hex2bin(input, len, buffer);
- if(hr != hrSuccess)
- goto exit;
- buffer[len/2] = '\0';
- *outLength = len/2;
- *output = buffer;
- exit:
- if (hr != hrSuccess && parent == nullptr)
- MAPIFreeBuffer(buffer);
- return hr;
- }
- HRESULT Util::hex2bin(const char *input, size_t len, LPBYTE output)
- {
- ULONG i, j;
- if (len % 2 != 0)
- return MAPI_E_INVALID_PARAMETER;
- for (i = 0, j = 0; i < len; ++j) {
- output[j] = x2b(input[i++]) << 4;
- output[j] |= x2b(input[i++]);
- }
- return hrSuccess;
- }
- ULONG Util::GetBestBody(const SPropValue *lpBody, const SPropValue *lpHtml,
- const SPropValue *lpRtfCompressed, const SPropValue *lpRtfInSync,
- ULONG ulFlags)
- {
-
- const ULONG ulBodyTag = ((ulFlags & MAPI_UNICODE) ? PR_BODY_W : PR_BODY_A);
- if (lpRtfInSync->ulPropTag != PR_RTF_IN_SYNC)
- return PR_NULL;
- if ((lpBody->ulPropTag == ulBodyTag || (PROP_TYPE(lpBody->ulPropTag) == PT_ERROR && lpBody->Value.err == MAPI_E_NOT_ENOUGH_MEMORY)) &&
- (PROP_TYPE(lpHtml->ulPropTag) == PT_ERROR && lpHtml->Value.err == MAPI_E_NOT_FOUND) &&
- (PROP_TYPE(lpRtfCompressed->ulPropTag) == PT_ERROR && lpRtfCompressed->Value.err == MAPI_E_NOT_FOUND))
- return ulBodyTag;
- if ((lpHtml->ulPropTag == PR_HTML || (PROP_TYPE(lpHtml->ulPropTag) == PT_ERROR && lpHtml->Value.err == MAPI_E_NOT_ENOUGH_MEMORY)) &&
- (PROP_TYPE(lpBody->ulPropTag) == PT_ERROR && lpBody->Value.err == MAPI_E_NOT_ENOUGH_MEMORY) &&
- (PROP_TYPE(lpRtfCompressed->ulPropTag) == PT_ERROR && lpRtfCompressed->Value.err == MAPI_E_NOT_ENOUGH_MEMORY) &&
- lpRtfInSync->Value.b == FALSE)
- return PR_HTML;
- if ((lpRtfCompressed->ulPropTag == PR_RTF_COMPRESSED || (PROP_TYPE(lpRtfCompressed->ulPropTag) == PT_ERROR && lpRtfCompressed->Value.err == MAPI_E_NOT_ENOUGH_MEMORY)) &&
- (PROP_TYPE(lpBody->ulPropTag) == PT_ERROR && lpBody->Value.err == MAPI_E_NOT_ENOUGH_MEMORY) &&
- (PROP_TYPE(lpHtml->ulPropTag) == PT_ERROR && lpHtml->Value.err == MAPI_E_NOT_FOUND) &&
- lpRtfInSync->Value.b == TRUE)
- return PR_RTF_COMPRESSED;
- return PR_NULL;
- }
- ULONG Util::GetBestBody(IMAPIProp* lpPropObj, ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- SPropArrayPtr ptrBodies;
- const ULONG ulBodyTag = ((ulFlags & MAPI_UNICODE) ? PR_BODY_W : PR_BODY_A);
- SizedSPropTagArray (4, sBodyTags) = { 4, {
- ulBodyTag,
- PR_HTML,
- PR_RTF_COMPRESSED,
- PR_RTF_IN_SYNC
- } };
- ULONG cValues = 0;
- hr = lpPropObj->GetProps(sBodyTags, 0, &cValues, &~ptrBodies);
- if (FAILED(hr))
- return PR_NULL;
- return GetBestBody(&ptrBodies[0], &ptrBodies[1], &ptrBodies[2], &ptrBodies[3], ulFlags);
- }
- ULONG Util::GetBestBody(LPSPropValue lpPropArray, ULONG cValues, ULONG ulFlags)
- {
- auto lpBody = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_BODY, PT_UNSPECIFIED));
- if (!lpBody)
- return PR_NULL;
- auto lpHtml = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_HTML, PT_UNSPECIFIED));
- if (!lpHtml)
- return PR_NULL;
- auto lpRtfCompressed = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_RTF_COMPRESSED, PT_UNSPECIFIED));
- if (!lpRtfCompressed)
- return PR_NULL;
- auto lpRtfInSync = PCpropFindProp(lpPropArray, cValues, CHANGE_PROP_TYPE(PR_RTF_IN_SYNC, PT_UNSPECIFIED));
- if (!lpRtfInSync)
- return PR_NULL;
- return GetBestBody(lpBody, lpHtml, lpRtfCompressed, lpRtfInSync, ulFlags);
- }
- bool Util::IsBodyProp(ULONG ulPropTag)
- {
- switch (PROP_ID(ulPropTag)) {
- case PROP_ID(PR_BODY):
- case PROP_ID(PR_HTML):
- case PROP_ID(PR_RTF_COMPRESSED):
- return true;
- default:
- return false;
- }
- }
- HRESULT Util::FindInterface(LPCIID lpIID, ULONG ulIIDs, LPCIID lpIIDs) {
- HRESULT hr = MAPI_E_NOT_FOUND;
- ULONG i;
- if (!lpIIDs || !lpIID)
- return MAPI_E_NOT_FOUND;
- for (i = 0; i < ulIIDs; ++i) {
- if (*lpIID == lpIIDs[i]) {
- hr = hrSuccess;
- break;
- }
- }
- return hr;
- }
- HRESULT Util::CopyStream(LPSTREAM lpSrc, LPSTREAM lpDest) {
- ULARGE_INTEGER liRead = {{0}}, liWritten = {{0}};
- STATSTG stStatus;
- HRESULT hr = lpSrc->Stat(&stStatus, 0);
- if (FAILED(hr))
- return hr;
- hr = lpSrc->CopyTo(lpDest, stStatus.cbSize, &liRead, &liWritten);
- if (FAILED(hr))
- return hr;
- if (liRead.QuadPart != liWritten.QuadPart)
- return MAPI_W_PARTIAL_COMPLETION;
- return lpDest->Commit(0);
- }
- HRESULT Util::CopyRecipients(LPMESSAGE lpSrc, LPMESSAGE lpDest) {
- HRESULT hr;
- object_ptr<IMAPITable> lpTable;
- rowset_ptr lpRows;
- memory_ptr<SPropTagArray> lpTableColumns;
- ULONG ulRows = 0;
- hr = lpSrc->GetRecipientTable(MAPI_UNICODE, &~lpTable);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->QueryColumns(TBL_ALL_COLUMNS, &~lpTableColumns);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->SetColumns(lpTableColumns, 0);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->GetRowCount(0, &ulRows);
- if (hr != hrSuccess)
- return hr;
- if (ulRows == 0)
- return hrSuccess;
- hr = lpTable->QueryRows(ulRows, 0, &~lpRows);
- if (hr != hrSuccess)
- return hr;
-
- return lpDest->ModifyRecipients(MODRECIP_ADD,
- reinterpret_cast<ADRLIST *>(lpRows.get()));
- }
- HRESULT Util::CopyInstanceIds(LPMAPIPROP lpSrc, LPMAPIPROP lpDst)
- {
- object_ptr<IECSingleInstance> lpSrcInstance, lpDstInstance;
- ULONG cbInstanceID = 0;
- memory_ptr<ENTRYID> lpInstanceID;
-
- if (lpSrc->QueryInterface(IID_IECSingleInstance, &~lpSrcInstance) != hrSuccess)
- return hrSuccess;
- if (lpDst->QueryInterface(IID_IECSingleInstance, &~lpDstInstance) != hrSuccess)
- return hrSuccess;
-
- if (lpSrcInstance->GetSingleInstanceId(&cbInstanceID, &~lpInstanceID) != hrSuccess)
- return hrSuccess;
- if (lpDstInstance->SetSingleInstanceId(cbInstanceID, lpInstanceID) != hrSuccess)
- return hrSuccess;
- return hrSuccess;
- }
- HRESULT Util::CopyAttachmentProps(LPATTACH lpSrcAttach, LPATTACH lpDstAttach, LPSPropTagArray lpExcludeProps)
- {
- return Util::DoCopyTo(&IID_IAttachment, lpSrcAttach, 0, NULL,
- lpExcludeProps, 0, NULL, &IID_IAttachment, lpDstAttach, 0, NULL);
- }
- HRESULT Util::CopyAttachments(LPMESSAGE lpSrc, LPMESSAGE lpDest, LPSRestriction lpRestriction) {
- HRESULT hr;
- bool bPartial = false;
-
- object_ptr<IMAPITable> lpTable;
- rowset_ptr lpRows;
- memory_ptr<SPropTagArray> lpTableColumns;
- ULONG ulRows = 0;
-
- memory_ptr<SPropValue> lpHasAttach;
- ULONG ulAttachNr = 0;
- hr = HrGetOneProp(lpSrc, PR_HASATTACH, &~lpHasAttach);
- if (hr != hrSuccess)
- return hrSuccess;
- if (lpHasAttach->Value.b == FALSE)
- return hrSuccess;
- hr = lpSrc->GetAttachmentTable(MAPI_UNICODE, &~lpTable);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->QueryColumns(TBL_ALL_COLUMNS, &~lpTableColumns);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->SetColumns(lpTableColumns, 0);
- if (hr != hrSuccess)
- return hr;
- if (lpRestriction) {
- hr = lpTable->Restrict(lpRestriction, 0);
- if (hr != hrSuccess)
- return hr;
- }
- hr = lpTable->GetRowCount(0, &ulRows);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->QueryRows(ulRows, 0, &~lpRows);
- if (hr != hrSuccess)
- return hr;
- for (ULONG i = 0; i < lpRows->cRows; ++i) {
- object_ptr<IAttach> lpDestAttach, lpSrcAttach;
- auto lpAttachNum = PCpropFindProp(lpRows->aRow[i].lpProps, lpRows->aRow[i].cValues, PR_ATTACH_NUM);
- if (!lpAttachNum) {
- bPartial = true;
- goto next_attach;
- }
- hr = lpSrc->OpenAttach(lpAttachNum->Value.ul, NULL, 0, &~lpSrcAttach);
- if (hr != hrSuccess) {
- bPartial = true;
- goto next_attach;
- }
- hr = lpDest->CreateAttach(NULL, 0, &ulAttachNr, &~lpDestAttach);
- if (hr != hrSuccess) {
- bPartial = true;
- goto next_attach;
- }
- hr = CopyAttachmentProps(lpSrcAttach, lpDestAttach);
- if (hr != hrSuccess) {
- bPartial = true;
- goto next_attach;
- }
-
- CopyInstanceIds(lpSrcAttach, lpDestAttach);
- hr = lpDestAttach->SaveChanges(0);
- if (hr != hrSuccess)
- return hr;
- next_attach:
- ;
- }
- if (bPartial)
- hr = MAPI_W_PARTIAL_COMPLETION;
- return hr;
- }
- HRESULT Util::CopyHierarchy(LPMAPIFOLDER lpSrc, LPMAPIFOLDER lpDest, ULONG ulFlags, ULONG ulUIParam, LPMAPIPROGRESS lpProgress) {
- HRESULT hr;
- bool bPartial = false;
- object_ptr<IMAPITable> lpTable;
- static constexpr const SizedSPropTagArray(2, sptaName) =
- {2, {PR_DISPLAY_NAME_W, PR_ENTRYID}};
- object_ptr<IMAPIFolder> lpSrcParam, lpDestParam;
- ULONG ulObj;
-
- if (lpSrc == nullptr || lpDest == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- hr = lpSrc->QueryInterface(IID_IMAPIFolder, &~lpSrcParam);
- if (hr != hrSuccess)
- return hr;
- hr = lpDest->QueryInterface(IID_IMAPIFolder, &~lpDestParam);
- if (hr != hrSuccess)
- return hr;
- hr = lpSrc->GetHierarchyTable(MAPI_UNICODE, &~lpTable);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->SetColumns(sptaName, 0);
- if (hr != hrSuccess)
- return hr;
- while (true) {
- object_ptr<IMAPIFolder> lpSrcFolder, lpDestFolder;
- rowset_ptr lpRowSet;
- hr = lpTable->QueryRows(1, 0, &~lpRowSet);
- if (hr != hrSuccess)
- return hr;
- if (lpRowSet->cRows == 0)
- break;
- hr = lpSrc->OpenEntry(lpRowSet->aRow[0].lpProps[1].Value.bin.cb, reinterpret_cast<ENTRYID *>(lpRowSet->aRow[0].lpProps[1].Value.bin.lpb), &IID_IMAPIFolder, 0, &ulObj, &~lpSrcFolder);
- if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- hr = lpDest->CreateFolder(FOLDER_GENERIC, (LPTSTR)lpRowSet->aRow[0].lpProps[0].Value.lpszW, NULL, &IID_IMAPIFolder,
- MAPI_UNICODE | (ulFlags & MAPI_NOREPLACE ? 0 : OPEN_IF_EXISTS), &~lpDestFolder);
- if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- hr = Util::DoCopyTo(&IID_IMAPIFolder, lpSrcFolder, 0, NULL, NULL, ulUIParam, lpProgress, &IID_IMAPIFolder, lpDestFolder, ulFlags, NULL);
- if (FAILED(hr))
- return hr;
- else if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- if (ulFlags & MAPI_MOVE)
- lpSrc->DeleteFolder(lpRowSet->aRow[0].lpProps[1].Value.bin.cb, (LPENTRYID)lpRowSet->aRow[0].lpProps[1].Value.bin.lpb, 0, NULL, 0);
- }
- if (bPartial)
- hr = MAPI_W_PARTIAL_COMPLETION;
- return hr;
- }
- #define MAX_ROWS 50
- HRESULT Util::CopyContents(ULONG ulWhat, LPMAPIFOLDER lpSrc, LPMAPIFOLDER lpDest, ULONG ulFlags, ULONG ulUIParam, LPMAPIPROGRESS lpProgress) {
- HRESULT hr;
- bool bPartial = false;
- object_ptr<IMAPITable> lpTable;
- static constexpr const SizedSPropTagArray(1, sptaEntryID) = {1, {PR_ENTRYID}};
- ULONG ulObj;
- memory_ptr<ENTRYLIST> lpDeleteEntries;
- hr = lpSrc->GetContentsTable(MAPI_UNICODE | ulWhat, &~lpTable);
- if (hr != hrSuccess)
- return hr;
- hr = lpTable->SetColumns(sptaEntryID, 0);
- if (hr != hrSuccess)
- return hr;
- hr = MAPIAllocateBuffer(sizeof(ENTRYLIST), &~lpDeleteEntries);
- if (hr != hrSuccess)
- return hr;
- hr = MAPIAllocateMore(sizeof(SBinary)*MAX_ROWS, lpDeleteEntries, (void**)&lpDeleteEntries->lpbin);
- if (hr != hrSuccess)
- return hr;
- while (true) {
- rowset_ptr lpRowSet;
- hr = lpTable->QueryRows(MAX_ROWS, 0, &~lpRowSet);
- if (hr != hrSuccess)
- return hr;
- if (lpRowSet->cRows == 0)
- break;
- lpDeleteEntries->cValues = 0;
- for (ULONG i = 0; i < lpRowSet->cRows; ++i) {
- object_ptr<IMessage> lpSrcMessage, lpDestMessage;
- hr = lpSrc->OpenEntry(lpRowSet->aRow[i].lpProps[0].Value.bin.cb, reinterpret_cast<ENTRYID *>(lpRowSet->aRow[i].lpProps[0].Value.bin.lpb), &IID_IMessage, 0, &ulObj, &~lpSrcMessage);
- if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- hr = lpDest->CreateMessage(&IID_IMessage, ulWhat | MAPI_MODIFY, &~lpDestMessage);
- if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- hr = Util::DoCopyTo(&IID_IMessage, lpSrcMessage, 0, NULL, NULL, ulUIParam, lpProgress, &IID_IMessage, lpDestMessage, ulFlags, NULL);
- if (FAILED(hr))
- return hr;
- else if (hr != hrSuccess) {
- bPartial = true;
- continue;
- }
- hr = lpDestMessage->SaveChanges(0);
- if (hr != hrSuccess) {
- bPartial = true;
- } else if (ulFlags & MAPI_MOVE) {
- lpDeleteEntries->lpbin[lpDeleteEntries->cValues].cb = lpRowSet->aRow[i].lpProps[0].Value.bin.cb;
- lpDeleteEntries->lpbin[lpDeleteEntries->cValues].lpb = lpRowSet->aRow[i].lpProps[0].Value.bin.lpb;
- ++lpDeleteEntries->cValues;
- }
- }
- if (ulFlags & MAPI_MOVE && lpDeleteEntries->cValues > 0 &&
- lpSrc->DeleteMessages(lpDeleteEntries, 0, NULL, 0) != hrSuccess)
- bPartial = true;
- }
- if (bPartial)
- hr = MAPI_W_PARTIAL_COMPLETION;
- return hr;
- }
- HRESULT Util::TryOpenProperty(ULONG ulPropType, ULONG ulSrcPropTag, LPMAPIPROP lpPropSrc, ULONG ulDestPropTag, LPMAPIPROP lpPropDest, LPSTREAM *lppSrcStream, LPSTREAM *lppDestStream) {
- HRESULT hr;
- object_ptr<IStream> lpSrc, lpDest;
- hr = lpPropSrc->OpenProperty(PROP_TAG(ulPropType, PROP_ID(ulSrcPropTag)), &IID_IStream, 0, 0, &~lpSrc);
- if (hr != hrSuccess)
- return hr;
-
- hr = lpPropDest->OpenProperty(PROP_TAG(ulPropType, PROP_ID(ulDestPropTag)), &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~lpDest);
- if (hr != hrSuccess)
- hr = lpPropDest->OpenProperty(PROP_TAG(ulPropType, PROP_ID(ulDestPropTag)), &IID_IStream, STGM_WRITE, MAPI_CREATE | MAPI_MODIFY, &~lpDest);
- if (hr != hrSuccess)
- return hr;
- *lppSrcStream = lpSrc.release();
- *lppDestStream = lpDest.release();
- return hrSuccess;
- }
- HRESULT Util::AddProblemToArray(const SPropProblem *lpProblem,
- SPropProblemArray **lppProblems)
- {
- HRESULT hr;
- LPSPropProblemArray lpNewProblems = NULL;
- LPSPropProblemArray lpOrigProblems = *lppProblems;
- if (!lpOrigProblems) {
- hr = MAPIAllocateBuffer(CbNewSPropProblemArray(1), (void**)&lpNewProblems);
- if (hr != hrSuccess)
- return hr;
- lpNewProblems->cProblem = 1;
- } else {
- hr = MAPIAllocateBuffer(CbNewSPropProblemArray(lpOrigProblems->cProblem+1), (void**)&lpNewProblems);
- if (hr != hrSuccess)
- return hr;
- lpNewProblems->cProblem = lpOrigProblems->cProblem +1;
- memcpy(lpNewProblems->aProblem, lpOrigProblems->aProblem, sizeof(SPropProblem) * lpOrigProblems->cProblem);
- MAPIFreeBuffer(lpOrigProblems);
- }
- memcpy(&lpNewProblems->aProblem[lpNewProblems->cProblem -1], lpProblem, sizeof(SPropProblem));
- *lppProblems = lpNewProblems;
- return hrSuccess;
- }
- HRESULT Util::DoCopyTo(LPCIID lpSrcInterface, LPVOID lpSrcObj,
- ULONG ciidExclude, LPCIID rgiidExclude, const SPropTagArray *lpExcludeProps,
- ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpDestInterface,
- void *lpDestObj, ULONG ulFlags, SPropProblemArray **lppProblems)
- {
- HRESULT hr = hrSuccess;
- LPUNKNOWN lpUnkSrc = (LPUNKNOWN)lpSrcObj, lpUnkDest = (LPUNKNOWN)lpDestObj;
- bool bPartial = false;
-
- SizedSPropTagArray(23, sExtraExcludes) = { 19, { PR_STORE_ENTRYID, PR_STORE_RECORD_KEY, PR_STORE_SUPPORT_MASK, PR_MAPPING_SIGNATURE,
- PR_MDB_PROVIDER, PR_ACCESS_LEVEL, PR_RECORD_KEY, PR_HASATTACH, PR_NORMALIZED_SUBJECT,
- PR_MESSAGE_SIZE, PR_DISPLAY_TO, PR_DISPLAY_CC, PR_DISPLAY_BCC, PR_ACCESS, PR_SUBJECT_PREFIX,
- PR_OBJECT_TYPE, PR_ENTRYID, PR_PARENT_ENTRYID, PR_INTERNET_CONTENT,
- PR_NULL, PR_NULL, PR_NULL, PR_NULL }};
- object_ptr<IMAPIProp> lpPropSrc, lpPropDest;
- memory_ptr<SPropTagArray> lpSPropTagArray;
- if (!lpSrcInterface || !lpSrcObj || !lpDestInterface || !lpDestObj) {
- hr = MAPI_E_INVALID_PARAMETER;
- goto exit;
- }
-
- hr = FindInterface(lpSrcInterface, ciidExclude, rgiidExclude);
- if (hr == hrSuccess) {
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
- hr = FindInterface(lpDestInterface, ciidExclude, rgiidExclude);
- if (hr == hrSuccess) {
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
-
- if (*lpSrcInterface == IID_IStream) {
- hr = FindInterface(&IID_IStream, ciidExclude, rgiidExclude);
- if (hr == hrSuccess) {
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
- if (*lpDestInterface != IID_IStream) {
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
- hr = CopyStream((LPSTREAM)lpSrcObj, (LPSTREAM)lpDestObj);
- goto exit;
- }
- hr = FindInterface(&IID_IMAPIProp, ciidExclude, rgiidExclude);
- if (hr == hrSuccess) {
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
-
-
- if (*lpSrcInterface == IID_IMAPIFolder) {
-
- if (*lpDestInterface != IID_IMAPIFolder) {
-
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
- if (!lpExcludeProps || Util::FindPropInArray(lpExcludeProps, PR_CONTAINER_CONTENTS) == -1) {
- sExtraExcludes.aulPropTag[sExtraExcludes.cValues++] = PR_CONTAINER_CONTENTS;
- hr = CopyContents(0, (LPMAPIFOLDER)lpSrcObj, (LPMAPIFOLDER)lpDestObj, ulFlags, ulUIParam, lpProgress);
- if (hr != hrSuccess)
- bPartial = true;
- }
- if (!lpExcludeProps || Util::FindPropInArray(lpExcludeProps, PR_FOLDER_ASSOCIATED_CONTENTS) == -1) {
- sExtraExcludes.aulPropTag[sExtraExcludes.cValues++] = PR_FOLDER_ASSOCIATED_CONTENTS;
- hr = CopyContents(MAPI_ASSOCIATED, (LPMAPIFOLDER)lpSrcObj, (LPMAPIFOLDER)lpDestObj, ulFlags, ulUIParam, lpProgress);
- if (hr != hrSuccess)
- bPartial = true;
- }
- if (!lpExcludeProps || Util::FindPropInArray(lpExcludeProps, PR_CONTAINER_HIERARCHY) == -1) {
-
- sExtraExcludes.aulPropTag[sExtraExcludes.cValues++] = PR_CONTAINER_HIERARCHY;
- hr = CopyHierarchy((LPMAPIFOLDER)lpSrcObj, (LPMAPIFOLDER)lpDestObj, ulFlags, ulUIParam, lpProgress);
- if (hr != hrSuccess)
- bPartial = true;
- }
- } else if (*lpSrcInterface == IID_IMessage) {
-
-
- } else if (*lpSrcInterface == IID_IAttachment) {
-
-
- } else if (*lpSrcInterface == IID_IMAPIContainer || *lpSrcInterface == IID_IMAPIProp) {
-
-
- } else if (*lpSrcInterface == IID_IMailUser || *lpSrcInterface == IID_IDistList) {
-
-
-
- } else {
-
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- goto exit;
- }
-
- hr = QueryInterfaceMapiPropOrValidFallback(lpUnkSrc, lpSrcInterface, &~lpPropSrc);
- if (hr != hrSuccess)
- goto exit;
- hr = QueryInterfaceMapiPropOrValidFallback(lpUnkDest, lpDestInterface, &~lpPropDest);
- if (hr != hrSuccess)
- goto exit;
- if (!FHasHTML(lpPropDest))
- sExtraExcludes.aulPropTag[sExtraExcludes.cValues++] = PR_HTML;
- hr = lpPropSrc->GetPropList(MAPI_UNICODE, &~lpSPropTagArray);
- if (FAILED(hr))
- goto exit;
-
- if (lpExcludeProps || sExtraExcludes.cValues != 0) {
- for (ULONG i = 0; i < lpSPropTagArray->cValues; ++i) {
- if (lpExcludeProps && Util::FindPropInArray(lpExcludeProps, CHANGE_PROP_TYPE(lpSPropTagArray->aulPropTag[i], PT_UNSPECIFIED)) != -1)
- lpSPropTagArray->aulPropTag[i] = PR_NULL;
- else if (Util::FindPropInArray(sExtraExcludes, CHANGE_PROP_TYPE(lpSPropTagArray->aulPropTag[i], PT_UNSPECIFIED)) != -1)
- lpSPropTagArray->aulPropTag[i] = PR_NULL;
- }
- }
-
-
- if (*lpSrcInterface == IID_IMessage) {
- bool bAddAttach = false;
- bool bAddRecip = false;
- if (Util::FindPropInArray(lpExcludeProps, PR_MESSAGE_ATTACHMENTS) == -1 &&
- Util::FindPropInArray(lpSPropTagArray, PR_MESSAGE_ATTACHMENTS) == -1)
- bAddAttach = true;
- if (Util::FindPropInArray(lpExcludeProps, PR_MESSAGE_RECIPIENTS) == -1 &&
- Util::FindPropInArray(lpSPropTagArray, PR_MESSAGE_RECIPIENTS) == -1)
- bAddRecip = true;
- if (bAddAttach || bAddRecip) {
- memory_ptr<SPropTagArray> lpTempSPropTagArray;
- ULONG ulNewPropCount = lpSPropTagArray->cValues + (bAddAttach ? (bAddRecip ? 2 : 1) : 1);
-
- hr = MAPIAllocateBuffer(CbNewSPropTagArray(ulNewPropCount), &~lpTempSPropTagArray);
- if (hr != hrSuccess)
- goto exit;
- memcpy(lpTempSPropTagArray->aulPropTag, lpSPropTagArray->aulPropTag, lpSPropTagArray->cValues * sizeof *lpSPropTagArray->aulPropTag);
- if (bAddAttach)
- lpTempSPropTagArray->aulPropTag[ulNewPropCount - (bAddRecip ? 2 : 1)] = PR_MESSAGE_ATTACHMENTS;
- if (bAddRecip)
- lpTempSPropTagArray->aulPropTag[ulNewPropCount - 1] = PR_MESSAGE_RECIPIENTS;
- lpTempSPropTagArray->cValues = ulNewPropCount;
- std::swap(lpTempSPropTagArray, lpSPropTagArray);
- }
- }
-
- hr = Util::DoCopyProps(lpSrcInterface, lpSrcObj, lpSPropTagArray, ulUIParam, lpProgress, lpDestInterface, lpDestObj, 0, lppProblems);
- if (hr != hrSuccess)
- goto exit;
-
- exit:
-
- if (bPartial)
- hr = MAPI_W_PARTIAL_COMPLETION;
- return hr;
- }
- HRESULT Util::ValidMapiPropInterface(LPCIID lpInterface)
- {
- if (!lpInterface)
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- if (*lpInterface == IID_IAttachment ||
- *lpInterface == IID_IMAPIProp ||
- *lpInterface == IID_IProfSect ||
- *lpInterface == IID_IMsgStore ||
- *lpInterface == IID_IMessage ||
- *lpInterface == IID_IAddrBook ||
- *lpInterface == IID_IMailUser ||
- *lpInterface == IID_IMAPIContainer ||
- *lpInterface == IID_IMAPIFolder ||
- *lpInterface == IID_IABContainer ||
- *lpInterface == IID_IDistList)
- return S_OK;
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- HRESULT Util::QueryInterfaceMapiPropOrValidFallback(LPUNKNOWN lpInObj, LPCIID lpInterface, LPUNKNOWN *lppOutObj)
- {
- if (lpInObj == NULL || lppOutObj == NULL)
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- HRESULT hr = lpInObj->QueryInterface(IID_IMAPIProp,
- reinterpret_cast<void **>(lppOutObj));
- if (hr == hrSuccess)
- return hr;
- hr = ValidMapiPropInterface(lpInterface);
- if (hr != hrSuccess)
- return hr;
- return lpInObj->QueryInterface(*lpInterface, reinterpret_cast<void **>(lppOutObj));
- }
- HRESULT Util::DoCopyProps(LPCIID lpSrcInterface, void *lpSrcObj,
- const SPropTagArray *inclprop, ULONG ulUIParam, LPMAPIPROGRESS lpProgress,
- LPCIID lpDestInterface, void *lpDestObj, ULONG ulFlags,
- SPropProblemArray **lppProblems)
- {
- HRESULT hr = hrSuccess;
- LPUNKNOWN lpUnkSrc = (LPUNKNOWN)lpSrcObj, lpUnkDest = (LPUNKNOWN)lpDestObj;
- object_ptr<IECUnknown> lpKopano;
- memory_ptr<SPropValue> lpZObj, lpProps;
- bool bPartial = false;
- object_ptr<IMAPIProp> lpSrcProp, lpDestProp;
- ULONG cValues = 0;
- memory_ptr<SPropTagArray> lpsDestPropArray;
- memory_ptr<SPropProblemArray> lpProblems;
-
- ULONG cNames = 0;
- memory_ptr<SPropTagArray> lpIncludeProps;
- memory_ptr<SPropTagArray> lpsSrcNameTagArray, lpsDestNameTagArray;
- memory_ptr<SPropTagArray> lpsDestTagArray;
- memory_ptr<MAPINAMEID *> lppNames;
-
- memory_ptr<SPropValue> lpAttachMethod;
- LONG ulIdCPID;
- LONG ulIdRTF;
- LONG ulIdHTML;
- LONG ulIdBODY;
- ULONG ulBodyProp = PR_BODY;
- if (lpSrcInterface == nullptr || lpDestInterface == nullptr ||
- lpSrcObj == nullptr || lpDestObj == nullptr ||
- inclprop == nullptr) {
- hr = MAPI_E_INVALID_PARAMETER;
- goto exit;
- }
-
- hr = QueryInterfaceMapiPropOrValidFallback(lpUnkSrc, lpSrcInterface, &~lpSrcProp);
- if (hr != hrSuccess)
- goto exit;
- hr = QueryInterfaceMapiPropOrValidFallback(lpUnkDest, lpDestInterface, &~lpDestProp);
- if (hr != hrSuccess)
- goto exit;
-
- if (HrGetOneProp(lpDestProp, PR_EC_OBJECT, &~lpZObj) == hrSuccess &&
- lpZObj->Value.lpszA != NULL)
- reinterpret_cast<IECUnknown *>(lpZObj->Value.lpszA)->QueryInterface(IID_ECMessage, &~lpKopano);
-
- hr = MAPIAllocateBuffer(CbNewSPropTagArray(inclprop->cValues), &~lpIncludeProps);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpIncludeProps, inclprop, CbNewSPropTagArray(inclprop->cValues));
- if (ulFlags & MAPI_NOREPLACE) {
- hr = lpDestProp->GetPropList(MAPI_UNICODE, &~lpsDestPropArray);
- if (hr != hrSuccess)
- goto exit;
- for (ULONG i = 0; i < lpIncludeProps->cValues; ++i) {
- if (Util::FindPropInArray(lpsDestPropArray, lpIncludeProps->aulPropTag[i]) == -1)
- continue;
-
-
-
- lpIncludeProps->aulPropTag[i] = PR_NULL;
- }
- }
- if (lpKopano) {
-
- ulIdRTF = Util::FindPropInArray(lpIncludeProps, PR_RTF_COMPRESSED);
- ulIdHTML = Util::FindPropInArray(lpIncludeProps, PR_HTML);
- ulIdBODY = Util::FindPropInArray(lpIncludeProps, PR_BODY_W);
-
- ulBodyProp = GetBestBody(lpSrcProp, fMapiUnicode);
- if (ulBodyProp == PR_BODY && ulIdBODY != -1) {
-
- if(ulIdHTML != -1)
- lpIncludeProps->aulPropTag[ulIdHTML] = PR_NULL;
- if(ulIdRTF != -1)
- lpIncludeProps->aulPropTag[ulIdRTF] = PR_NULL;
- } else if (ulBodyProp == PR_HTML && ulIdHTML != -1) {
-
- if(ulIdBODY != -1)
- lpIncludeProps->aulPropTag[ulIdBODY] = PR_NULL;
- if(ulIdRTF != -1)
- lpIncludeProps->aulPropTag[ulIdRTF] = PR_NULL;
- } else if (ulBodyProp == PR_RTF_COMPRESSED && ulIdRTF != -1) {
-
- if(ulIdHTML != -1)
- lpIncludeProps->aulPropTag[ulIdHTML] = PR_NULL;
- if(ulIdBODY != -1)
- lpIncludeProps->aulPropTag[ulIdBODY] = PR_NULL;
- }
- }
- for (ULONG i = 0; i < lpIncludeProps->cValues; ++i) {
- bool isProblem = false;
-
-
-
- if (PROP_TYPE(lpIncludeProps->aulPropTag[i]) != PT_OBJECT &&
- PROP_ID(lpIncludeProps->aulPropTag[i]) != PROP_ID(PR_ATTACH_DATA_BIN))
- continue;
-
- if (*lpSrcInterface == IID_IMessage) {
- if (lpIncludeProps->aulPropTag[i] == PR_MESSAGE_RECIPIENTS)
-
- hr = Util::CopyRecipients((LPMESSAGE)lpSrcObj, (LPMESSAGE)lpDestObj);
- else if (lpIncludeProps->aulPropTag[i] == PR_MESSAGE_ATTACHMENTS)
-
- hr = Util::CopyAttachments((LPMESSAGE)lpSrcObj, (LPMESSAGE)lpDestObj, NULL);
- else
- hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- } else if (*lpSrcInterface == IID_IMAPIFolder) {
-
- if (lpIncludeProps->aulPropTag[i] == PR_CONTAINER_CONTENTS ||
- lpIncludeProps->aulPropTag[i] == PR_CONTAINER_HIERARCHY ||
- lpIncludeProps->aulPropTag[i] == PR_FOLDER_ASSOCIATED_CONTENTS) {
- lpIncludeProps->aulPropTag[i] = PR_NULL;
- } else {
- isProblem = true;
- }
- } else if (*lpSrcInterface == IID_IAttachment) {
- object_ptr<IStream> lpSrcStream, lpDestStream;
- object_ptr<IMessage> lpSrcMessage, lpDestMessage;
- ULONG ulAttachMethod;
-
-
- if (HrGetOneProp(lpSrcProp, PR_ATTACH_METHOD, &~lpAttachMethod) != hrSuccess)
- ulAttachMethod = ATTACH_BY_VALUE;
- else
- ulAttachMethod = lpAttachMethod->Value.ul;
- switch (ulAttachMethod) {
- case ATTACH_BY_VALUE:
- case ATTACH_OLE:
-
-
- if (((LPATTACH)lpSrcObj)->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, 0, &~lpSrcStream) == hrSuccess) {
-
-
-
- hr = ((LPATTACH)lpDestObj)->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~lpDestStream);
- if (hr != hrSuccess)
- hr = ((LPATTACH)lpDestObj)->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, STGM_WRITE, MAPI_CREATE | MAPI_MODIFY, &~lpDestStream);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- hr = Util::CopyStream(lpSrcStream, lpDestStream);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- } else if(lpAttachMethod->Value.ul == ATTACH_OLE &&
- ((LPATTACH)lpSrcObj)->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IStream, 0, 0, &~lpSrcStream) == hrSuccess) {
-
- hr = ((LPATTACH)lpDestObj)->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IStream, STGM_WRITE | STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY, &~lpDestStream);
- if (hr == E_FAIL)
- hr = ((LPATTACH)lpDestObj)->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IStream, STGM_WRITE, MAPI_CREATE | MAPI_MODIFY, &~lpDestStream);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- hr = Util::CopyStream(lpSrcStream, lpDestStream);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- }
- break;
- case ATTACH_EMBEDDED_MSG:
-
- if (((LPATTACH)lpSrcObj)->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IMessage, 0, 0, &~lpSrcMessage) == hrSuccess) {
-
- hr = ((LPATTACH)lpDestObj)->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY, &~lpDestMessage);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- hr = Util::DoCopyTo(&IID_IMessage, lpSrcMessage, 0, NULL, NULL, ulUIParam, lpProgress, &IID_IMessage, lpDestMessage, 0, NULL);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- hr = lpDestMessage->SaveChanges(0);
- if (hr != hrSuccess) {
- isProblem = true;
- goto next_include_check;
- }
- }
- break;
- default:
-
- isProblem = true;
- break;
- };
- } else {
- isProblem = true;
- }
-
- next_include_check:
- if (isProblem) {
- SPropProblem sProblem;
- bPartial = true;
- sProblem.ulIndex = i;
- sProblem.ulPropTag = lpIncludeProps->aulPropTag[i];
- sProblem.scode = MAPI_E_INTERFACE_NOT_SUPPORTED;
- hr = AddProblemToArray(&sProblem, &+lpProblems);
- if (hr != hrSuccess)
- goto exit;
- }
-
- lpIncludeProps->aulPropTag[i] = PR_NULL;
- }
- hr = lpSrcProp->GetProps(lpIncludeProps, 0, &cValues, &~lpProps);
- if (FAILED(hr))
- goto exit;
-
- hr = MAPIAllocateBuffer(CbNewSPropTagArray(cValues), &~lpsDestTagArray);
- if (hr != hrSuccess)
- goto exit;
-
- for (ULONG i = 0; i < cValues; ++i) {
- lpsDestTagArray->aulPropTag[i] = lpProps[i].ulPropTag;
- if (PROP_ID(lpProps[i].ulPropTag) >= 0x8000)
- ++cNames;
- }
- if (cNames) {
- hr = MAPIAllocateBuffer(CbNewSPropTagArray(cNames), &~lpsSrcNameTagArray);
- if (hr != hrSuccess)
- goto exit;
- lpsSrcNameTagArray->cValues = cNames;
- cNames = 0;
- for (ULONG i = 0; i < cValues; ++i)
- if (PROP_ID(lpProps[i].ulPropTag) >= 0x8000)
- lpsSrcNameTagArray->aulPropTag[cNames++] = lpProps[i].ulPropTag;
-
- hr = lpSrcProp->GetNamesFromIDs(&+lpsSrcNameTagArray, NULL, 0, &cNames, &~lppNames);
- if (FAILED(hr))
- goto exit;
- hr = lpDestProp->GetIDsFromNames(cNames, lppNames, MAPI_CREATE, &~lpsDestNameTagArray);
- if (FAILED(hr))
- goto exit;
-
- for (ULONG i = 0, j = 0; i < cValues && j < cNames; ++i) {
- if (PROP_ID(lpProps[i].ulPropTag) != PROP_ID(lpsSrcNameTagArray->aulPropTag[j]))
- continue;
- if (PROP_TYPE(lpsDestNameTagArray->aulPropTag[j]) != PT_ERROR)
-
- lpsDestTagArray->aulPropTag[i] = PROP_TAG(PROP_TYPE(lpProps[i].ulPropTag), PROP_ID(lpsDestNameTagArray->aulPropTag[j]));
- else
-
- lpsDestTagArray->aulPropTag[i] = PROP_TAG(PT_ERROR, PROP_ID(lpsDestNameTagArray->aulPropTag[j]));
-
- ++j;
- }
- }
-
- ulIdCPID = Util::FindPropInArray(lpIncludeProps, PR_INTERNET_CPID);
- if (ulIdCPID != -1) {
- hr = lpDestProp->SetProps(1, &lpProps[ulIdCPID], NULL);
- if (FAILED(hr))
- goto exit;
- }
-
- for (ULONG i = 0; i < cValues; ++i) {
- bool err = false;
- if(PROP_TYPE(lpProps[i].ulPropTag) == PT_ERROR)
- err = lpProps[i].Value.err == MAPI_E_NOT_ENOUGH_MEMORY ||
- PROP_ID(lpProps[i].ulPropTag) == PROP_ID(PR_BODY) ||
- PROP_ID(lpProps[i].ulPropTag) == PROP_ID(PR_HTML) ||
- PROP_ID(lpProps[i].ulPropTag) == PROP_ID(PR_RTF_COMPRESSED);
- if (!err)
- continue;
- assert(PROP_ID(lpIncludeProps->aulPropTag[i]) == PROP_ID(lpProps[i].ulPropTag));
- object_ptr<IStream> lpSrcStream, lpDestStream;
- hr = Util::TryOpenProperty(PROP_TYPE(lpIncludeProps->aulPropTag[i]), lpProps[i].ulPropTag, lpSrcProp, lpsDestTagArray->aulPropTag[i], lpDestProp, &~lpSrcStream, &~lpDestStream);
- if (hr != hrSuccess) {
-
-
- if (hr != MAPI_E_NOT_FOUND)
- bPartial = true;
- continue;
- }
- hr = Util::CopyStream(lpSrcStream, lpDestStream);
- if (hr != hrSuccess)
- bPartial = true;
- }
-
- for (ULONG i = 0; i < cValues; ++i) {
- lpProps[i].ulPropTag = lpsDestTagArray->aulPropTag[i];
-
- if (PROP_TYPE(lpProps[i].ulPropTag) == PT_ERROR)
- lpProps[i].ulPropTag = PR_NULL;
- }
- hr = lpDestProp->SetProps(cValues, lpProps, NULL);
- if (FAILED(hr))
- goto exit;
-
- if (ulFlags & MAPI_MOVE) {
-
- hr = lpSrcProp->DeleteProps(lpIncludeProps, NULL);
- if (FAILED(hr))
- goto exit;
- }
- exit:
- if (bPartial)
- hr = MAPI_W_PARTIAL_COMPLETION;
- if (hr == hrSuccess && lppProblems != nullptr)
-
- *lppProblems = lpProblems.release();
- return hr;
- }
- HRESULT Util::HrCopyIMAPData(LPMESSAGE lpSrcMsg, LPMESSAGE lpDstMsg)
- {
- HRESULT hr = hrSuccess;
- object_ptr<IStream> lpSrcStream, lpDestStream;
- static constexpr const SizedSPropTagArray(3, sptaIMAP) =
- {3, {PR_EC_IMAP_EMAIL_SIZE, PR_EC_IMAP_BODY,
- PR_EC_IMAP_BODYSTRUCTURE}};
- ULONG cValues = 0;
- memory_ptr<SPropValue> lpIMAPProps;
-
-
- if (Util::TryOpenProperty(PT_BINARY, PR_EC_IMAP_EMAIL, lpSrcMsg,
- PR_EC_IMAP_EMAIL, lpDstMsg, &~lpSrcStream, &~lpDestStream) != hrSuccess ||
- Util::CopyStream(lpSrcStream, lpDestStream) != hrSuccess)
- return hrSuccess;
-
- Util::CopyInstanceIds(lpSrcMsg, lpDstMsg);
-
- hr = lpSrcMsg->GetProps(sptaIMAP, 0, &cValues, &~lpIMAPProps);
- if (FAILED(hr))
- return hr;
- hr = lpDstMsg->SetProps(cValues, lpIMAPProps, NULL);
- if (FAILED(hr))
- return hr;
- return hrSuccess;
- }
- HRESULT Util::HrDeleteIMAPData(LPMESSAGE lpMsg)
- {
- static constexpr const SizedSPropTagArray(4, sptaIMAP) =
- {4, { PR_EC_IMAP_EMAIL_SIZE, PR_EC_IMAP_EMAIL,
- PR_EC_IMAP_BODY, PR_EC_IMAP_BODYSTRUCTURE}};
- return lpMsg->DeleteProps(sptaIMAP, NULL);
- }
- HRESULT Util::HrGetQuotaStatus(IMsgStore *lpMsgStore, ECQUOTA *lpsQuota,
- ECQUOTASTATUS **lppsQuotaStatus)
- {
- HRESULT hr = hrSuccess;
- memory_ptr<ECQUOTASTATUS> lpsQuotaStatus;
- memory_ptr<SPropValue> lpProps;
- static constexpr const SizedSPropTagArray(1, sptaProps) = {1, {PR_MESSAGE_SIZE_EXTENDED}};
- ULONG cValues = 0;
-
- if (lpMsgStore == nullptr || lppsQuotaStatus == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- hr = lpMsgStore->GetProps(sptaProps, 0, &cValues, &~lpProps);
- if (hr != hrSuccess)
- return hr;
- if (cValues != 1 || lpProps[0].ulPropTag != PR_MESSAGE_SIZE_EXTENDED)
- return MAPI_E_NOT_FOUND;
- hr = MAPIAllocateBuffer(sizeof *lpsQuotaStatus, &~lpsQuotaStatus);
- if (hr != hrSuccess)
- return hr;
- memset(lpsQuotaStatus, 0, sizeof *lpsQuotaStatus);
-
- lpsQuotaStatus->llStoreSize = lpProps[0].Value.li.QuadPart;
- lpsQuotaStatus->quotaStatus = QUOTA_OK;
- if (lpsQuota && lpsQuotaStatus->llStoreSize > 0) {
- if (lpsQuota->llHardSize > 0 && lpsQuotaStatus->llStoreSize > lpsQuota->llHardSize)
- lpsQuotaStatus->quotaStatus = QUOTA_HARDLIMIT;
- else if (lpsQuota->llSoftSize > 0 && lpsQuotaStatus->llStoreSize > lpsQuota->llSoftSize)
- lpsQuotaStatus->quotaStatus = QUOTA_SOFTLIMIT;
- else if (lpsQuota->llWarnSize > 0 && lpsQuotaStatus->llStoreSize > lpsQuota->llWarnSize)
- lpsQuotaStatus->quotaStatus = QUOTA_WARN;
- }
- *lppsQuotaStatus = lpsQuotaStatus.release();
- return hrSuccess;
- }
- HRESULT Util::HrDeleteResidualProps(LPMESSAGE lpDestMsg, LPMESSAGE lpSourceMsg, LPSPropTagArray lpsValidProps)
- {
- HRESULT hr = hrSuccess;
- memory_ptr<SPropTagArray> lpsPropArray, lpsNamedPropArray;
- memory_ptr<SPropTagArray> lpsMappedPropArray;
- ULONG cPropNames = 0;
- memory_ptr<MAPINAMEID *> lppPropNames;
- PropTagSet sPropTagSet;
- if (lpDestMsg == nullptr || lpSourceMsg == nullptr || lpsValidProps == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- hr = lpDestMsg->GetPropList(0, &~lpsPropArray);
- if (hr != hrSuccess || lpsPropArray->cValues == 0)
- return hr;
- hr = MAPIAllocateBuffer(CbNewSPropTagArray(lpsValidProps->cValues), &~lpsNamedPropArray);
- if (hr != hrSuccess)
- return hr;
- memset(lpsNamedPropArray, 0, CbNewSPropTagArray(lpsValidProps->cValues));
- for (unsigned i = 0; i < lpsValidProps->cValues; ++i)
- if (PROP_ID(lpsValidProps->aulPropTag[i]) >= 0x8000)
- lpsNamedPropArray->aulPropTag[lpsNamedPropArray->cValues++] = lpsValidProps->aulPropTag[i];
- if (lpsNamedPropArray->cValues > 0) {
- hr = lpSourceMsg->GetNamesFromIDs(&+lpsNamedPropArray, NULL, 0, &cPropNames, &~lppPropNames);
- if (FAILED(hr))
- return hr;
- hr = lpDestMsg->GetIDsFromNames(cPropNames, lppPropNames, MAPI_CREATE, &~lpsMappedPropArray);
- if (FAILED(hr))
- return hr;
- }
-
- for (unsigned i = 0; i < lpsPropArray->cValues; ++i)
- sPropTagSet.insert(lpsPropArray->aulPropTag[i]);
-
- for (unsigned i = 0; i < lpsValidProps->cValues; ++i)
- if (PROP_ID(lpsValidProps->aulPropTag[i]) < 0x8000)
- sPropTagSet.erase(lpsValidProps->aulPropTag[i]);
-
- for (unsigned i = 0; lpsMappedPropArray != NULL && i < lpsMappedPropArray->cValues; ++i)
- if (PROP_TYPE(lpsMappedPropArray->aulPropTag[i]) != PT_ERROR)
- sPropTagSet.erase(lpsMappedPropArray->aulPropTag[i]);
- if (sPropTagSet.empty())
- return hrSuccess;
-
- assert(lpsPropArray->cValues >= sPropTagSet.size());
- memset(lpsPropArray->aulPropTag, 0, lpsPropArray->cValues * sizeof *lpsPropArray->aulPropTag);
- lpsPropArray->cValues = 0;
- for (const auto &i : sPropTagSet)
- lpsPropArray->aulPropTag[lpsPropArray->cValues++] = i;
- hr = lpDestMsg->DeleteProps(lpsPropArray, NULL);
- if (hr != hrSuccess)
- return hr;
- return lpDestMsg->SaveChanges(KEEP_OPEN_READWRITE);
- }
- HRESULT Util::HrFindEntryIDs(ULONG cbEID, LPENTRYID lpEID, ULONG cbEntryIDs, LPSPropValue lpEntryIDs, BOOL *lpbFound, ULONG* lpPos)
- {
- BOOL bFound = FALSE;
- ULONG i;
- if (cbEID == 0 || lpEID == NULL || cbEntryIDs == 0 ||
- lpEntryIDs == NULL || lpbFound == NULL)
- return MAPI_E_INVALID_PARAMETER;
- for (i = 0; bFound == FALSE && i < cbEntryIDs; ++i) {
- if (PROP_TYPE(lpEntryIDs[i].ulPropTag) != PT_BINARY)
- continue;
- if (cbEID != lpEntryIDs[i].Value.bin.cb)
- continue;
- if (memcmp(lpEID, lpEntryIDs[i].Value.bin.lpb, cbEID) == 0) {
- bFound = TRUE;
- break;
- }
- }
- *lpbFound = bFound;
- if (bFound && lpPos)
- *lpPos = i;
- return hrSuccess;
- }
- HRESULT Util::HrDeleteAttachments(LPMESSAGE lpMsg)
- {
- MAPITablePtr ptrAttachTable;
- SRowSetPtr ptrRows;
- static constexpr const SizedSPropTagArray(1, sptaAttachNum) = {1, {PR_ATTACH_NUM}};
- if (lpMsg == NULL)
- return MAPI_E_INVALID_PARAMETER;
- HRESULT hr = lpMsg->GetAttachmentTable(0, &~ptrAttachTable);
- if (hr != hrSuccess)
- return hr;
- hr = HrQueryAllRows(ptrAttachTable, sptaAttachNum, NULL, NULL, 0, &ptrRows);
- if (hr != hrSuccess)
- return hr;
- for (SRowSetPtr::size_type i = 0; i < ptrRows.size(); ++i) {
- hr = lpMsg->DeleteAttach(ptrRows[i].lpProps[0].Value.l, 0, NULL, 0);
- if (hr != hrSuccess)
- return hr;
- }
- return hrSuccess;
- }
- HRESULT Util::HrDeleteRecipients(LPMESSAGE lpMsg)
- {
- MAPITablePtr ptrRecipTable;
- SRowSetPtr ptrRows;
- static constexpr const SizedSPropTagArray(1, sptaRowId) = {1, {PR_ROWID}};
- if (lpMsg == NULL)
- return MAPI_E_INVALID_PARAMETER;
- HRESULT hr = lpMsg->GetRecipientTable(0, &~ptrRecipTable);
- if (hr != hrSuccess)
- return hr;
- hr = HrQueryAllRows(ptrRecipTable, sptaRowId, NULL, NULL, 0, &ptrRows);
- if (hr != hrSuccess)
- return hr;
- return lpMsg->ModifyRecipients(MODRECIP_REMOVE, (LPADRLIST)ptrRows.get());
- }
- HRESULT Util::HrDeleteMessage(IMAPISession *lpSession, IMessage *lpMessage)
- {
- ULONG cMsgProps;
- SPropArrayPtr ptrMsgProps;
- MsgStorePtr ptrStore;
- ULONG ulType;
- MAPIFolderPtr ptrFolder;
- ENTRYLIST entryList = {1, NULL};
- static constexpr const SizedSPropTagArray(3, sptaMessageProps) =
- {3, {PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID}};
- enum {IDX_ENTRYID, IDX_STORE_ENTRYID, IDX_PARENT_ENTRYID};
- HRESULT hr = lpMessage->GetProps(sptaMessageProps, 0, &cMsgProps, &~ptrMsgProps);
- if (hr != hrSuccess)
- return hr;
- hr = lpSession->OpenMsgStore(0, ptrMsgProps[IDX_STORE_ENTRYID].Value.bin.cb, reinterpret_cast<ENTRYID *>(ptrMsgProps[IDX_STORE_ENTRYID].Value.bin.lpb), &ptrStore.iid(), MDB_WRITE, &~ptrStore);
- if (hr != hrSuccess)
- return hr;
- hr = ptrStore->OpenEntry(ptrMsgProps[IDX_PARENT_ENTRYID].Value.bin.cb, reinterpret_cast<ENTRYID *>(ptrMsgProps[IDX_PARENT_ENTRYID].Value.bin.lpb), &ptrFolder.iid(), MAPI_MODIFY, &ulType, &~ptrFolder);
- if (hr != hrSuccess)
- return hr;
- entryList.cValues = 1;
- entryList.lpbin = &ptrMsgProps[IDX_ENTRYID].Value.bin;
- return ptrFolder->DeleteMessages(&entryList, 0, NULL, DELETE_HARD_DELETE);
- }
- HRESULT Util::ReadProperty(IMAPIProp *lpProp, ULONG ulPropTag, std::string &strData)
- {
- HRESULT hr = hrSuccess;
- object_ptr<IStream> lpStream;
- hr = lpProp->OpenProperty(ulPropTag, &IID_IStream, 0, 0, &~lpStream);
- if(hr != hrSuccess)
- return hr;
- return HrStreamToString(lpStream, strData);
- }
- HRESULT Util::WriteProperty(IMAPIProp *lpProp, ULONG ulPropTag, const std::string &strData)
- {
- HRESULT hr = hrSuccess;
- object_ptr<IStream> lpStream;
- ULONG len = 0;
- hr = lpProp->OpenProperty(ulPropTag, &IID_IStream, STGM_DIRECT, MAPI_CREATE | MAPI_MODIFY, &~lpStream);
- if(hr != hrSuccess)
- return hr;
- hr = lpStream->Write(strData.data(), strData.size(), &len);
- if(hr != hrSuccess)
- return hr;
- return lpStream->Commit(0);
- }
- HRESULT Util::ExtractRSSEntryID(LPSPropValue lpPropBlob, ULONG *lpcbEntryID, LPENTRYID *lppEntryID)
- {
- return ExtractAdditionalRenEntryID(lpPropBlob, RSF_PID_RSS_SUBSCRIPTION, lpcbEntryID, lppEntryID);
- }
- HRESULT Util::ExtractSuggestedContactsEntryID(LPSPropValue lpPropBlob, ULONG *lpcbEntryID, LPENTRYID *lppEntryID)
- {
- return ExtractAdditionalRenEntryID(lpPropBlob, RSF_PID_SUGGESTED_CONTACTS , lpcbEntryID, lppEntryID);
- }
- HRESULT Util::ExtractAdditionalRenEntryID(LPSPropValue lpPropBlob, unsigned short usBlockType, ULONG *lpcbEntryID, LPENTRYID *lppEntryID)
- {
- HRESULT hr;
- LPBYTE lpPos = lpPropBlob->Value.bin.lpb;
- LPBYTE lpEnd = lpPropBlob->Value.bin.lpb + lpPropBlob->Value.bin.cb;
-
- while (true) {
- if (lpPos + 8 > lpEnd)
- return MAPI_E_NOT_FOUND;
- if (*reinterpret_cast<unsigned short *>(lpPos) == 0)
- return MAPI_E_NOT_FOUND;
- if (*(unsigned short *)lpPos != usBlockType) {
- unsigned short usLen = 0;
- lpPos += 2;
- usLen = *(unsigned short*)lpPos;
- lpPos += 2;
- if (lpPos + usLen > lpEnd)
- return MAPI_E_CORRUPT_DATA;
- lpPos += usLen;
- continue;
- }
- unsigned short usLen = 0;
- lpPos += 4;
- if (*reinterpret_cast<unsigned short *>(lpPos) != RSF_ELID_ENTRYID)
- return MAPI_E_CORRUPT_DATA;
- lpPos += 2;
- usLen = *(unsigned short *)lpPos;
- lpPos += 2;
- if (lpPos + usLen > lpEnd)
- return MAPI_E_CORRUPT_DATA;
- hr = MAPIAllocateBuffer(usLen, (LPVOID*)lppEntryID);
- if (hr != hrSuccess)
- return hr;
- memcpy(*lppEntryID, lpPos, usLen);
- *lpcbEntryID = usLen;
- return hrSuccess;
- }
- return hrSuccess;
- }
- }
|