WSUtil.cpp 93 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <sys/un.h>
  19. #include "WSUtil.h"
  20. #include <kopano/ECIConv.h>
  21. #include <kopano/ECGuid.h>
  22. #include <kopano/Trace.h>
  23. #include <kopano/memory.hpp>
  24. #include "Mem.h"
  25. #include <kopano/mapiext.h>
  26. // For the static row getprop functions
  27. #include "ECMAPIProp.h"
  28. #include "ECMAPIFolder.h"
  29. #include "ECMessage.h"
  30. #include "ECMailUser.h"
  31. #include "ECDistList.h"
  32. #include "ECABContainer.h"
  33. #include "SOAPUtils.h"
  34. #include <kopano/CommonUtil.h>
  35. #include <kopano/charset/convert.h>
  36. #include <kopano/charset/utf8string.h>
  37. #include "EntryPoint.h"
  38. #include <kopano/ECGetText.h>
  39. #include "SOAPSock.h"
  40. using namespace std;
  41. using namespace KCHL;
  42. #define CONVERT_TO(_context, _charset, ...) ((_context) ? (_context)->convert_to<_charset>(__VA_ARGS__) : convert_to<_charset>(__VA_ARGS__))
  43. HRESULT CopyMAPIPropValToSOAPPropVal(propVal *lpPropValDst,
  44. const SPropValue *lpPropValSrc, convert_context *lpConverter)
  45. {
  46. TRACE_MAPI(TRACE_ENTRY, (char*)__FUNCTION__, " Prop: 0x%X", lpPropValSrc->ulPropTag);
  47. HRESULT hr = hrSuccess;
  48. lpPropValDst->ulPropTag = lpPropValSrc->ulPropTag;
  49. memset(&lpPropValDst->Value, 0, sizeof(propValData));
  50. switch(PROP_TYPE(lpPropValSrc->ulPropTag)) {
  51. case PT_I2:
  52. lpPropValDst->__union = SOAP_UNION_propValData_i;
  53. lpPropValDst->Value.i = lpPropValSrc->Value.i;
  54. break;
  55. case PT_LONG: // or PT_ULONG
  56. lpPropValDst->__union = SOAP_UNION_propValData_ul;
  57. lpPropValDst->Value.ul = lpPropValSrc->Value.ul;
  58. break;
  59. case PT_R4:
  60. lpPropValDst->__union = SOAP_UNION_propValData_flt;
  61. lpPropValDst->Value.flt = lpPropValSrc->Value.flt;
  62. break;
  63. case PT_DOUBLE:
  64. lpPropValDst->__union = SOAP_UNION_propValData_dbl;
  65. lpPropValDst->Value.dbl = lpPropValSrc->Value.dbl;
  66. break;
  67. case PT_CURRENCY:
  68. lpPropValDst->__union = SOAP_UNION_propValData_hilo;
  69. lpPropValDst->Value.hilo = s_alloc<hiloLong>(nullptr);
  70. lpPropValDst->Value.hilo->hi = lpPropValSrc->Value.cur.Hi;
  71. lpPropValDst->Value.hilo->lo = lpPropValSrc->Value.cur.Lo;
  72. break;
  73. case PT_APPTIME:
  74. lpPropValDst->__union = SOAP_UNION_propValData_dbl;
  75. lpPropValDst->Value.dbl = lpPropValSrc->Value.at;
  76. break;
  77. case PT_ERROR:
  78. lpPropValDst->__union = SOAP_UNION_propValData_ul;
  79. lpPropValDst->Value.ul = lpPropValSrc->Value.err;
  80. break;
  81. case PT_BOOLEAN:
  82. lpPropValDst->__union = SOAP_UNION_propValData_b;
  83. lpPropValDst->Value.b = lpPropValSrc->Value.b == 0 ? false : true;
  84. break;
  85. case PT_OBJECT:
  86. // can never be transmitted over the wire!
  87. hr = MAPI_E_INVALID_TYPE;
  88. break;
  89. case PT_I8:
  90. lpPropValDst->__union = SOAP_UNION_propValData_li;
  91. lpPropValDst->Value.li = lpPropValSrc->Value.li.QuadPart;
  92. break;
  93. case PT_STRING8:
  94. {
  95. utf8string u8 = CONVERT_TO(lpConverter, utf8string, lpPropValSrc->Value.lpszA); // SOAP lpszA = UTF-8, MAPI lpszA = current locale charset
  96. lpPropValDst->__union = SOAP_UNION_propValData_lpszA;
  97. lpPropValDst->Value.lpszA = s_alloc<char>(nullptr, u8.size() + 1);
  98. strcpy(lpPropValDst->Value.lpszA, u8.c_str());
  99. }
  100. break;
  101. case PT_UNICODE:
  102. {
  103. utf8string u8 = CONVERT_TO(lpConverter, utf8string, lpPropValSrc->Value.lpszW);
  104. lpPropValDst->__union = SOAP_UNION_propValData_lpszA;
  105. lpPropValDst->Value.lpszA = s_alloc<char>(nullptr, u8.size() + 1);
  106. strcpy(lpPropValDst->Value.lpszA, u8.c_str());
  107. }
  108. break;
  109. case PT_SYSTIME:
  110. lpPropValDst->__union = SOAP_UNION_propValData_hilo;
  111. lpPropValDst->Value.hilo = s_alloc<hiloLong>(nullptr);
  112. lpPropValDst->Value.hilo->hi = lpPropValSrc->Value.ft.dwHighDateTime;
  113. lpPropValDst->Value.hilo->lo = lpPropValSrc->Value.ft.dwLowDateTime;
  114. break;
  115. case PT_CLSID:
  116. lpPropValDst->__union = SOAP_UNION_propValData_bin;
  117. lpPropValDst->Value.bin = s_alloc<xsd__base64Binary>(nullptr);
  118. lpPropValDst->Value.bin->__ptr = s_alloc<unsigned char>(nullptr, sizeof(GUID));
  119. lpPropValDst->Value.bin->__size = sizeof(GUID);
  120. memcpy(lpPropValDst->Value.bin->__ptr, lpPropValSrc->Value.lpguid, sizeof(GUID));
  121. break;
  122. case PT_BINARY:
  123. lpPropValDst->__union = SOAP_UNION_propValData_bin;
  124. lpPropValDst->Value.bin = s_alloc<xsd__base64Binary>(nullptr);
  125. lpPropValDst->Value.bin->__ptr = s_alloc<unsigned char>(nullptr, lpPropValSrc->Value.bin.cb);
  126. lpPropValDst->Value.bin->__size = lpPropValSrc->Value.bin.cb;
  127. memcpy(lpPropValDst->Value.bin->__ptr, lpPropValSrc->Value.bin.lpb, lpPropValSrc->Value.bin.cb);
  128. break;
  129. case PT_MV_I2:
  130. lpPropValDst->__union = SOAP_UNION_propValData_mvi;
  131. lpPropValDst->Value.mvi.__size = lpPropValSrc->Value.MVi.cValues;
  132. lpPropValDst->Value.mvi.__ptr = s_alloc<short int>(nullptr, lpPropValDst->Value.mvi.__size);
  133. memcpy(lpPropValDst->Value.mvi.__ptr, lpPropValSrc->Value.MVi.lpi, sizeof(short int) * lpPropValDst->Value.mvi.__size);
  134. break;
  135. case PT_MV_LONG:
  136. lpPropValDst->__union = SOAP_UNION_propValData_mvl;
  137. lpPropValDst->Value.mvl.__size = lpPropValSrc->Value.MVl.cValues;
  138. lpPropValDst->Value.mvl.__ptr = s_alloc<unsigned int>(nullptr, lpPropValDst->Value.mvl.__size);
  139. memcpy(lpPropValDst->Value.mvl.__ptr, lpPropValSrc->Value.MVl.lpl, sizeof(unsigned int) * lpPropValDst->Value.mvl.__size);
  140. break;
  141. case PT_MV_R4:
  142. lpPropValDst->__union = SOAP_UNION_propValData_mvflt;
  143. lpPropValDst->Value.mvflt.__size = lpPropValSrc->Value.MVflt.cValues;
  144. lpPropValDst->Value.mvflt.__ptr = s_alloc<float>(nullptr, lpPropValDst->Value.mvflt.__size);
  145. memcpy(lpPropValDst->Value.mvflt.__ptr, lpPropValSrc->Value.MVflt.lpflt, sizeof(float) * lpPropValDst->Value.mvflt.__size);
  146. break;
  147. case PT_MV_DOUBLE:
  148. lpPropValDst->__union = SOAP_UNION_propValData_mvdbl;
  149. lpPropValDst->Value.mvdbl.__size = lpPropValSrc->Value.MVdbl.cValues;
  150. lpPropValDst->Value.mvdbl.__ptr = s_alloc<double>(nullptr, lpPropValDst->Value.mvdbl.__size);
  151. memcpy(lpPropValDst->Value.mvdbl.__ptr, lpPropValSrc->Value.MVdbl.lpdbl, sizeof(double) * lpPropValDst->Value.mvdbl.__size);
  152. break;
  153. case PT_MV_CURRENCY:
  154. lpPropValDst->__union = SOAP_UNION_propValData_mvhilo;
  155. lpPropValDst->Value.mvhilo.__size = lpPropValSrc->Value.MVcur.cValues;
  156. lpPropValDst->Value.mvhilo.__ptr = s_alloc<hiloLong>(nullptr, lpPropValDst->Value.mvhilo.__size);
  157. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvhilo.__size; ++i) {
  158. lpPropValDst->Value.mvhilo.__ptr[i].hi = lpPropValSrc->Value.MVcur.lpcur[i].Hi;
  159. lpPropValDst->Value.mvhilo.__ptr[i].lo = lpPropValSrc->Value.MVcur.lpcur[i].Lo;
  160. }
  161. break;
  162. case PT_MV_APPTIME:
  163. lpPropValDst->__union = SOAP_UNION_propValData_mvdbl;
  164. lpPropValDst->Value.mvdbl.__size = lpPropValSrc->Value.MVat.cValues;
  165. lpPropValDst->Value.mvdbl.__ptr = s_alloc<double>(nullptr, lpPropValDst->Value.mvdbl.__size);
  166. memcpy(lpPropValDst->Value.mvdbl.__ptr, lpPropValSrc->Value.MVat.lpat, sizeof(double) * lpPropValDst->Value.mvdbl.__size);
  167. break;
  168. case PT_MV_SYSTIME:
  169. lpPropValDst->__union = SOAP_UNION_propValData_mvhilo;
  170. lpPropValDst->Value.mvhilo.__size = lpPropValSrc->Value.MVft.cValues;
  171. lpPropValDst->Value.mvhilo.__ptr = s_alloc<hiloLong>(nullptr, lpPropValDst->Value.mvhilo.__size);
  172. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvhilo.__size; ++i) {
  173. lpPropValDst->Value.mvhilo.__ptr[i].hi = lpPropValSrc->Value.MVft.lpft[i].dwHighDateTime;
  174. lpPropValDst->Value.mvhilo.__ptr[i].lo = lpPropValSrc->Value.MVft.lpft[i].dwLowDateTime;
  175. }
  176. break;
  177. case PT_MV_BINARY:
  178. lpPropValDst->__union = SOAP_UNION_propValData_mvbin;
  179. lpPropValDst->Value.mvbin.__size = lpPropValSrc->Value.MVbin.cValues;
  180. lpPropValDst->Value.mvbin.__ptr = s_alloc<xsd__base64Binary>(nullptr, lpPropValDst->Value.mvbin.__size);
  181. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvbin.__size; ++i) {
  182. lpPropValDst->Value.mvbin.__ptr[i].__size = lpPropValSrc->Value.MVbin.lpbin[i].cb;
  183. lpPropValDst->Value.mvbin.__ptr[i].__ptr = s_alloc<unsigned char>(nullptr, lpPropValDst->Value.mvbin.__ptr[i].__size);
  184. memcpy(lpPropValDst->Value.mvbin.__ptr[i].__ptr, lpPropValSrc->Value.MVbin.lpbin[i].lpb, lpPropValDst->Value.mvbin.__ptr[i].__size);
  185. }
  186. break;
  187. case PT_MV_STRING8:
  188. if (lpConverter == NULL) {
  189. convert_context converter;
  190. CopyMAPIPropValToSOAPPropVal(lpPropValDst, lpPropValSrc, &converter);
  191. } else {
  192. lpPropValDst->__union = SOAP_UNION_propValData_mvszA;
  193. lpPropValDst->Value.mvszA.__size = lpPropValSrc->Value.MVszA.cValues;
  194. lpPropValDst->Value.mvszA.__ptr = s_alloc<char *>(nullptr, lpPropValDst->Value.mvszA.__size);
  195. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvszA.__size; ++i) {
  196. utf8string u8 = lpConverter->convert_to<utf8string>(lpPropValSrc->Value.MVszA.lppszA[i]);
  197. lpPropValDst->Value.mvszA.__ptr[i] = s_alloc<char>(nullptr, u8.size() + 1);
  198. strcpy(lpPropValDst->Value.mvszA.__ptr[i], u8.c_str());
  199. }
  200. }
  201. break;
  202. case PT_MV_UNICODE:
  203. if (lpConverter == NULL) {
  204. convert_context converter;
  205. CopyMAPIPropValToSOAPPropVal(lpPropValDst, lpPropValSrc, &converter);
  206. } else {
  207. lpPropValDst->__union = SOAP_UNION_propValData_mvszA;
  208. lpPropValDst->Value.mvszA.__size = lpPropValSrc->Value.MVszA.cValues;
  209. lpPropValDst->Value.mvszA.__ptr = s_alloc<char *>(nullptr, lpPropValDst->Value.mvszA.__size);
  210. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvszA.__size; ++i) {
  211. utf8string u8 = lpConverter->convert_to<utf8string>(lpPropValSrc->Value.MVszW.lppszW[i]);
  212. lpPropValDst->Value.mvszA.__ptr[i] = s_alloc<char>(nullptr, u8.size() + 1);
  213. strcpy(lpPropValDst->Value.mvszA.__ptr[i], u8.c_str());
  214. }
  215. }
  216. break;
  217. case PT_MV_CLSID:
  218. lpPropValDst->__union = SOAP_UNION_propValData_mvbin;
  219. lpPropValDst->Value.mvbin.__size = lpPropValSrc->Value.MVguid.cValues;
  220. lpPropValDst->Value.mvbin.__ptr = s_alloc<xsd__base64Binary>(nullptr, lpPropValDst->Value.mvbin.__size);
  221. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvbin.__size; ++i) {
  222. lpPropValDst->Value.mvbin.__ptr[i].__size = sizeof(GUID);
  223. lpPropValDst->Value.mvbin.__ptr[i].__ptr = s_alloc<unsigned char>(nullptr, lpPropValDst->Value.mvbin.__ptr[i].__size);
  224. memcpy(lpPropValDst->Value.mvbin.__ptr[i].__ptr, &lpPropValSrc->Value.MVguid.lpguid[i], lpPropValDst->Value.mvbin.__ptr[i].__size);
  225. }
  226. break;
  227. case PT_MV_I8:
  228. lpPropValDst->__union = SOAP_UNION_propValData_mvli;
  229. lpPropValDst->Value.mvli.__size = lpPropValSrc->Value.MVli.cValues;
  230. lpPropValDst->Value.mvli.__ptr = s_alloc<LONG64>(nullptr, lpPropValDst->Value.mvli.__size);
  231. for (gsoap_size_t i = 0; i < lpPropValDst->Value.mvli.__size; ++i)
  232. lpPropValDst->Value.mvli.__ptr[i] = lpPropValSrc->Value.MVli.lpli[i].QuadPart;
  233. break;
  234. case PT_SRESTRICTION:
  235. lpPropValDst->__union = SOAP_UNION_propValData_res;
  236. // NOTE: we placed the object pointer in lpszA to make sure it is on the same offset as Value.x on 32-bit and 64-bit machines
  237. hr = CopyMAPIRestrictionToSOAPRestriction(&lpPropValDst->Value.res, (LPSRestriction)lpPropValSrc->Value.lpszA, lpConverter);
  238. break;
  239. case PT_ACTIONS: {
  240. // NOTE: we placed the object pointer in lpszA to make sure it is on the same offset as Value.x on 32-bit and 64-bit machines
  241. auto lpSrcActions = reinterpret_cast<ACTIONS *>(lpPropValSrc->Value.lpszA);
  242. lpPropValDst->__union = SOAP_UNION_propValData_actions;
  243. lpPropValDst->Value.actions = s_alloc<actions>(nullptr);
  244. lpPropValDst->Value.actions->__ptr = s_alloc<action>(nullptr, lpSrcActions->cActions);
  245. lpPropValDst->Value.actions->__size = lpSrcActions->cActions;
  246. for (unsigned int i = 0; i < lpSrcActions->cActions; ++i) {
  247. ACTION *lpSrcAction = &lpSrcActions->lpAction[i];
  248. struct action *lpDstAction = &lpPropValDst->Value.actions->__ptr[i];
  249. lpDstAction->acttype = lpSrcAction->acttype;
  250. lpDstAction->flavor = lpSrcAction->ulActionFlavor;
  251. lpDstAction->flags = lpSrcAction->ulFlags;
  252. switch(lpSrcActions->lpAction[i].acttype) {
  253. case OP_MOVE:
  254. case OP_COPY:
  255. lpDstAction->__union = SOAP_UNION__act_moveCopy;
  256. lpDstAction->act.moveCopy.store.__ptr = s_alloc<unsigned char>(nullptr, lpSrcAction->actMoveCopy.cbStoreEntryId);
  257. memcpy(lpDstAction->act.moveCopy.store.__ptr, lpSrcAction->actMoveCopy.lpStoreEntryId, lpSrcAction->actMoveCopy.cbStoreEntryId);
  258. lpDstAction->act.moveCopy.store.__size = lpSrcAction->actMoveCopy.cbStoreEntryId;
  259. lpDstAction->act.moveCopy.folder.__ptr = s_alloc<unsigned char>(nullptr, lpSrcAction->actMoveCopy.cbFldEntryId);
  260. memcpy(lpDstAction->act.moveCopy.folder.__ptr, lpSrcAction->actMoveCopy.lpFldEntryId, lpSrcAction->actMoveCopy.cbFldEntryId);
  261. lpDstAction->act.moveCopy.folder.__size = lpSrcAction->actMoveCopy.cbFldEntryId;
  262. break;
  263. case OP_REPLY:
  264. case OP_OOF_REPLY:
  265. lpDstAction->__union = SOAP_UNION__act_reply;
  266. lpDstAction->act.reply.message.__ptr = s_alloc<unsigned char>(nullptr, lpSrcAction->actReply.cbEntryId);
  267. memcpy(lpDstAction->act.reply.message.__ptr, lpSrcAction->actReply.lpEntryId, lpSrcAction->actReply.cbEntryId);
  268. lpDstAction->act.reply.message.__size = lpSrcAction->actReply.cbEntryId;
  269. lpDstAction->act.reply.guid.__size = sizeof(GUID);
  270. lpDstAction->act.reply.guid.__ptr = s_alloc<unsigned char>(nullptr, sizeof(GUID));
  271. memcpy(lpDstAction->act.reply.guid.__ptr, &lpSrcAction->actReply.guidReplyTemplate, sizeof(GUID));
  272. break;
  273. case OP_DEFER_ACTION:
  274. lpDstAction->__union = SOAP_UNION__act_defer;
  275. lpDstAction->act.defer.bin.__ptr = s_alloc<unsigned char>(nullptr, lpSrcAction->actDeferAction.cbData);
  276. lpDstAction->act.defer.bin.__size = lpSrcAction->actDeferAction.cbData;
  277. memcpy(lpDstAction->act.defer.bin.__ptr,lpSrcAction->actDeferAction.pbData, lpSrcAction->actDeferAction.cbData);
  278. break;
  279. case OP_BOUNCE:
  280. lpDstAction->__union = SOAP_UNION__act_bouncecode;
  281. lpDstAction->act.bouncecode = lpSrcAction->scBounceCode;
  282. break;
  283. case OP_FORWARD:
  284. case OP_DELEGATE:
  285. lpDstAction->__union = SOAP_UNION__act_adrlist;
  286. hr = CopyMAPIRowSetToSOAPRowSet((LPSRowSet)lpSrcAction->lpadrlist, &lpDstAction->act.adrlist, lpConverter);
  287. if(hr != hrSuccess)
  288. return hr;
  289. break;
  290. case OP_TAG:
  291. lpDstAction->__union = SOAP_UNION__act_prop;
  292. lpDstAction->act.prop = s_alloc<propVal>(nullptr);
  293. hr = CopyMAPIPropValToSOAPPropVal(lpDstAction->act.prop, &lpSrcAction->propTag, lpConverter);
  294. break;
  295. case OP_DELETE:
  296. case OP_MARK_AS_READ:
  297. // no other data needed
  298. break;
  299. }
  300. }
  301. break;
  302. }
  303. default:
  304. hr = MAPI_E_INVALID_TYPE;
  305. break;
  306. }
  307. return hr;
  308. }
  309. HRESULT CopySOAPPropValToMAPIPropVal(LPSPropValue lpPropValDst,
  310. const struct propVal *lpPropValSrc, void *lpBase,
  311. convert_context *lpConverter)
  312. {
  313. HRESULT hr = hrSuccess;
  314. lpPropValDst->ulPropTag = lpPropValSrc->ulPropTag;
  315. lpPropValDst->dwAlignPad = 0;
  316. // FIXME check pointer is OK before using in (lpPropValSrc->Value.hilo may be NULL!)
  317. switch(PROP_TYPE(lpPropValSrc->ulPropTag)) {
  318. case PT_I2:
  319. lpPropValDst->Value.i = lpPropValSrc->Value.i;
  320. break;
  321. case PT_LONG:
  322. lpPropValDst->Value.ul = lpPropValSrc->Value.ul;
  323. break;
  324. case PT_R4:
  325. lpPropValDst->Value.flt = lpPropValSrc->Value.flt;
  326. break;
  327. case PT_DOUBLE:
  328. lpPropValDst->Value.dbl = lpPropValSrc->Value.dbl;
  329. break;
  330. case PT_CURRENCY:
  331. if(lpPropValSrc->__union && lpPropValSrc->Value.hilo) {
  332. lpPropValDst->Value.cur.Hi = lpPropValSrc->Value.hilo->hi;
  333. lpPropValDst->Value.cur.Lo = lpPropValSrc->Value.hilo->lo;
  334. } else {
  335. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  336. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  337. }
  338. break;
  339. case PT_APPTIME:
  340. lpPropValDst->Value.at = lpPropValSrc->Value.dbl;
  341. break;
  342. case PT_ERROR:
  343. lpPropValDst->Value.err = kcerr_to_mapierr(lpPropValSrc->Value.ul);
  344. break;
  345. case PT_BOOLEAN:
  346. lpPropValDst->Value.b = lpPropValSrc->Value.b;
  347. break;
  348. case PT_OBJECT:
  349. // can never be transmitted over the wire!
  350. hr = MAPI_E_INVALID_TYPE;
  351. break;
  352. case PT_I8:
  353. lpPropValDst->Value.li.QuadPart = lpPropValSrc->Value.li;
  354. break;
  355. case PT_STRING8:
  356. if(lpPropValSrc->__union && lpPropValSrc->Value.lpszA) {
  357. string s = CONVERT_TO(lpConverter, string, lpPropValSrc->Value.lpszA, rawsize(lpPropValSrc->Value.lpszA), "UTF-8");
  358. hr = ECAllocateMore(s.length() + 1, lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.lpszA));
  359. if (hr != hrSuccess)
  360. return hr;
  361. strcpy(lpPropValDst->Value.lpszA, s.c_str());
  362. } else {
  363. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  364. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  365. }
  366. break;
  367. case PT_UNICODE:
  368. if(lpPropValSrc->__union && lpPropValSrc->Value.lpszA) {
  369. wstring ws = CONVERT_TO(lpConverter, wstring, lpPropValSrc->Value.lpszA, rawsize(lpPropValSrc->Value.lpszA), "UTF-8");
  370. hr = ECAllocateMore(sizeof(wstring::value_type) * (ws.length() + 1), lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.lpszW));
  371. if (hr != hrSuccess)
  372. return hr;
  373. wcscpy(lpPropValDst->Value.lpszW, ws.c_str());
  374. } else {
  375. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  376. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  377. }
  378. break;
  379. case PT_SYSTIME:
  380. if(lpPropValSrc->__union && lpPropValSrc->Value.hilo) {
  381. lpPropValDst->Value.ft.dwHighDateTime = lpPropValSrc->Value.hilo->hi;
  382. lpPropValDst->Value.ft.dwLowDateTime = lpPropValSrc->Value.hilo->lo;
  383. } else {
  384. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  385. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  386. }
  387. break;
  388. case PT_CLSID:
  389. if(lpPropValSrc->__union && lpPropValSrc->Value.bin && lpPropValSrc->Value.bin->__size == sizeof(MAPIUID)) {
  390. hr = ECAllocateMore(lpPropValSrc->Value.bin->__size, lpBase,
  391. reinterpret_cast<void **>(&lpPropValDst->Value.lpguid));
  392. if (hr != hrSuccess)
  393. return hr;
  394. memcpy(lpPropValDst->Value.lpguid, lpPropValSrc->Value.bin->__ptr, lpPropValSrc->Value.bin->__size);
  395. } else {
  396. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  397. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  398. }
  399. break;
  400. case PT_BINARY:
  401. if(lpPropValSrc->__union && lpPropValSrc->Value.bin) {
  402. hr = ECAllocateMore(lpPropValSrc->Value.bin->__size, lpBase,
  403. reinterpret_cast<void **>(&lpPropValDst->Value.bin.lpb));
  404. if (hr != hrSuccess)
  405. return hr;
  406. memcpy(lpPropValDst->Value.bin.lpb, lpPropValSrc->Value.bin->__ptr, lpPropValSrc->Value.bin->__size);
  407. lpPropValDst->Value.bin.cb = lpPropValSrc->Value.bin->__size;
  408. }else if(lpPropValSrc->__union == 0) {
  409. lpPropValDst->Value.bin.lpb = NULL;
  410. lpPropValDst->Value.bin.cb = 0;
  411. }else {
  412. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  413. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  414. }
  415. break;
  416. case PT_MV_I2:
  417. if(lpPropValSrc->__union && lpPropValSrc->Value.mvi.__ptr) {
  418. lpPropValDst->Value.MVi.cValues = lpPropValSrc->Value.mvi.__size;
  419. hr = ECAllocateMore(sizeof(short int) * lpPropValDst->Value.MVi.cValues, lpBase,
  420. reinterpret_cast<void **>(&lpPropValDst->Value.MVi.lpi));
  421. if (hr != hrSuccess)
  422. return hr;
  423. memcpy(lpPropValDst->Value.MVi.lpi, lpPropValSrc->Value.mvi.__ptr, sizeof(short int)*lpPropValDst->Value.MVi.cValues);
  424. }else {
  425. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  426. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  427. }
  428. break;
  429. case PT_MV_LONG:
  430. if(lpPropValSrc->__union && lpPropValSrc->Value.mvl.__ptr) {
  431. lpPropValDst->Value.MVl.cValues = lpPropValSrc->Value.mvl.__size;
  432. hr = ECAllocateMore(sizeof(unsigned int) * lpPropValDst->Value.MVl.cValues, lpBase,
  433. reinterpret_cast<void **>(&lpPropValDst->Value.MVl.lpl));
  434. if (hr != hrSuccess)
  435. return hr;
  436. memcpy(lpPropValDst->Value.MVl.lpl, lpPropValSrc->Value.mvl.__ptr, sizeof(unsigned int)*lpPropValDst->Value.MVl.cValues);
  437. }else {
  438. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  439. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  440. }
  441. break;
  442. case PT_MV_R4:
  443. if(lpPropValSrc->__union && lpPropValSrc->Value.mvflt.__ptr) {
  444. lpPropValDst->Value.MVflt.cValues = lpPropValSrc->Value.mvflt.__size;
  445. hr = ECAllocateMore(sizeof(float) * lpPropValDst->Value.MVflt.cValues, lpBase,
  446. reinterpret_cast<void **>(&lpPropValDst->Value.MVflt.lpflt));
  447. if (hr != hrSuccess)
  448. return hr;
  449. memcpy(lpPropValDst->Value.MVflt.lpflt, lpPropValSrc->Value.mvflt.__ptr, sizeof(float)*lpPropValDst->Value.MVflt.cValues);
  450. }else {
  451. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  452. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  453. }
  454. break;
  455. case PT_MV_DOUBLE:
  456. if(lpPropValSrc->__union && lpPropValSrc->Value.mvdbl.__ptr) {
  457. lpPropValDst->Value.MVdbl.cValues = lpPropValSrc->Value.mvdbl.__size;
  458. hr = ECAllocateMore(sizeof(double) * lpPropValDst->Value.MVdbl.cValues, lpBase,
  459. reinterpret_cast<void **>(&lpPropValDst->Value.MVdbl.lpdbl));
  460. if (hr != hrSuccess)
  461. return hr;
  462. memcpy(lpPropValDst->Value.MVdbl.lpdbl, lpPropValSrc->Value.mvdbl.__ptr, sizeof(double)*lpPropValDst->Value.MVdbl.cValues);
  463. }else {
  464. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  465. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  466. }
  467. break;
  468. case PT_MV_CURRENCY:
  469. if(lpPropValSrc->__union && lpPropValSrc->Value.mvhilo.__ptr) {
  470. lpPropValDst->Value.MVcur.cValues = lpPropValSrc->Value.mvhilo.__size;
  471. hr = ECAllocateMore(sizeof(hiloLong) * lpPropValDst->Value.MVcur.cValues, lpBase,
  472. reinterpret_cast<void **>(&lpPropValDst->Value.MVcur.lpcur));
  473. if (hr != hrSuccess)
  474. return hr;
  475. for (unsigned int i = 0; i < lpPropValDst->Value.MVcur.cValues; ++i) {
  476. lpPropValDst->Value.MVcur.lpcur[i].Hi = lpPropValSrc->Value.mvhilo.__ptr[i].hi;
  477. lpPropValDst->Value.MVcur.lpcur[i].Lo = lpPropValSrc->Value.mvhilo.__ptr[i].lo;
  478. }
  479. }else {
  480. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  481. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  482. }
  483. break;
  484. case PT_MV_APPTIME:
  485. if(lpPropValSrc->__union && lpPropValSrc->Value.mvdbl.__ptr) {
  486. lpPropValDst->Value.MVat.cValues = lpPropValSrc->Value.mvdbl.__size;
  487. hr = ECAllocateMore(sizeof(double) * lpPropValDst->Value.MVat.cValues, lpBase,
  488. reinterpret_cast<void **>(&lpPropValDst->Value.MVat.lpat));
  489. if (hr != hrSuccess)
  490. return hr;
  491. memcpy(lpPropValDst->Value.MVat.lpat, lpPropValSrc->Value.mvdbl.__ptr, sizeof(double)*lpPropValDst->Value.MVat.cValues);
  492. }else {
  493. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  494. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  495. }
  496. break;
  497. case PT_MV_SYSTIME:
  498. if(lpPropValSrc->__union && lpPropValSrc->Value.mvhilo.__ptr) {
  499. lpPropValDst->Value.MVft.cValues = lpPropValSrc->Value.mvhilo.__size;
  500. hr = ECAllocateMore(sizeof(hiloLong) * lpPropValDst->Value.MVft.cValues, lpBase,
  501. reinterpret_cast<void **>(&lpPropValDst->Value.MVft.lpft));
  502. if (hr != hrSuccess)
  503. return hr;
  504. for (unsigned int i = 0; i < lpPropValDst->Value.MVft.cValues; ++i) {
  505. lpPropValDst->Value.MVft.lpft[i].dwHighDateTime = lpPropValSrc->Value.mvhilo.__ptr[i].hi;
  506. lpPropValDst->Value.MVft.lpft[i].dwLowDateTime = lpPropValSrc->Value.mvhilo.__ptr[i].lo;
  507. }
  508. }else {
  509. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  510. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  511. }
  512. break;
  513. case PT_MV_BINARY:
  514. if(lpPropValSrc->__union && lpPropValSrc->Value.mvbin.__ptr) {
  515. lpPropValDst->Value.MVbin.cValues = lpPropValSrc->Value.mvbin.__size;
  516. hr = ECAllocateMore(sizeof(SBinary) * lpPropValDst->Value.MVbin.cValues, lpBase,
  517. reinterpret_cast<void **>(&lpPropValDst->Value.MVbin.lpbin));
  518. if (hr != hrSuccess)
  519. return hr;
  520. for (unsigned int i = 0; i < lpPropValDst->Value.MVbin.cValues; ++i) {
  521. lpPropValDst->Value.MVbin.lpbin[i].cb = lpPropValSrc->Value.mvbin.__ptr[i].__size;
  522. if(lpPropValDst->Value.MVbin.lpbin[i].cb > 0) {
  523. hr = ECAllocateMore(sizeof(unsigned char) * lpPropValDst->Value.MVbin.lpbin[i].cb,
  524. lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.MVbin.lpbin[i].lpb));
  525. if (hr != hrSuccess)
  526. return hr;
  527. memcpy(lpPropValDst->Value.MVbin.lpbin[i].lpb, lpPropValSrc->Value.mvbin.__ptr[i].__ptr, sizeof(unsigned char)*lpPropValDst->Value.MVbin.lpbin[i].cb);
  528. }
  529. else
  530. lpPropValDst->Value.MVbin.lpbin[i].lpb = NULL;
  531. }
  532. }else {
  533. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  534. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  535. }
  536. break;
  537. case PT_MV_STRING8:
  538. if(lpPropValSrc->__union && lpPropValSrc->Value.mvszA.__ptr) {
  539. if (lpConverter == NULL) {
  540. convert_context converter;
  541. CopySOAPPropValToMAPIPropVal(lpPropValDst, lpPropValSrc, lpBase, &converter);
  542. } else {
  543. lpPropValDst->Value.MVszA.cValues = lpPropValSrc->Value.mvszA.__size;
  544. hr = ECAllocateMore(sizeof(LPSTR)*lpPropValDst->Value.MVszA.cValues, lpBase, (void**)&lpPropValDst->Value.MVszA.lppszA);
  545. for (unsigned int i = 0; i < lpPropValDst->Value.MVszA.cValues; ++i) {
  546. if (lpPropValSrc->Value.mvszA.__ptr[i] != NULL) {
  547. string s = lpConverter->convert_to<string>(lpPropValSrc->Value.mvszA.__ptr[i], rawsize(lpPropValSrc->Value.mvszA.__ptr[i]), "UTF-8");
  548. hr = ECAllocateMore(s.size() + 1, lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.MVszA.lppszA[i]));
  549. if (hr != hrSuccess)
  550. return hr;
  551. strcpy(lpPropValDst->Value.MVszA.lppszA[i], s.c_str());
  552. } else {
  553. hr = ECAllocateMore(1, lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.MVszA.lppszA[i]));
  554. if (hr != hrSuccess)
  555. return hr;
  556. lpPropValDst->Value.MVszA.lppszA[i][0] = '\0';
  557. }
  558. }
  559. }
  560. }else {
  561. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  562. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  563. }
  564. break;
  565. case PT_MV_UNICODE:
  566. if(lpPropValSrc->__union && lpPropValSrc->Value.mvszA.__ptr) {
  567. if (lpConverter == NULL) {
  568. convert_context converter;
  569. CopySOAPPropValToMAPIPropVal(lpPropValDst, lpPropValSrc, lpBase, &converter);
  570. } else {
  571. lpPropValDst->Value.MVszW.cValues = lpPropValSrc->Value.mvszA.__size;
  572. hr = ECAllocateMore(sizeof(LPWSTR) * lpPropValDst->Value.MVszW.cValues, lpBase,
  573. reinterpret_cast<void **>(&lpPropValDst->Value.MVszW.lppszW));
  574. if (hr != hrSuccess)
  575. return hr;
  576. for (unsigned int i = 0; i < lpPropValDst->Value.MVszW.cValues; ++i) {
  577. if (lpPropValSrc->Value.mvszA.__ptr[i] != NULL) {
  578. wstring ws = lpConverter->convert_to<wstring>(lpPropValSrc->Value.mvszA.__ptr[i], rawsize(lpPropValSrc->Value.mvszA.__ptr[i]), "UTF-8");
  579. hr = ECAllocateMore(sizeof(wstring::value_type) * (ws.length() + 1), lpBase,
  580. reinterpret_cast<void **>(&lpPropValDst->Value.MVszW.lppszW[i]));
  581. if (hr != hrSuccess)
  582. return hr;
  583. wcscpy(lpPropValDst->Value.MVszW.lppszW[i], ws.c_str());
  584. } else {
  585. hr = ECAllocateMore(1, lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.MVszW.lppszW[i]));
  586. if (hr != hrSuccess)
  587. return hr;
  588. lpPropValDst->Value.MVszW.lppszW[i][0] = '\0';
  589. }
  590. }
  591. }
  592. }else {
  593. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  594. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  595. }
  596. break;
  597. case PT_MV_CLSID:
  598. if(lpPropValSrc->__union && lpPropValSrc->Value.mvbin.__ptr) {
  599. lpPropValDst->Value.MVguid.cValues = lpPropValSrc->Value.mvbin.__size;
  600. hr = ECAllocateMore(sizeof(GUID) * lpPropValDst->Value.MVguid.cValues, lpBase,
  601. reinterpret_cast<void **>(&lpPropValDst->Value.MVguid.lpguid));
  602. if (hr != hrSuccess)
  603. return hr;
  604. for (unsigned int i = 0; i < lpPropValDst->Value.MVguid.cValues; ++i)
  605. memcpy(&lpPropValDst->Value.MVguid.lpguid[i], lpPropValSrc->Value.mvbin.__ptr[i].__ptr, sizeof(GUID));
  606. }else {
  607. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  608. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  609. }
  610. break;
  611. case PT_MV_I8:
  612. if(lpPropValSrc->__union && lpPropValSrc->Value.mvli.__ptr) {
  613. lpPropValDst->Value.MVli.cValues = lpPropValSrc->Value.mvli.__size;
  614. hr = ECAllocateMore(sizeof(LARGE_INTEGER) * lpPropValDst->Value.MVli.cValues, lpBase,
  615. reinterpret_cast<void **>(&lpPropValDst->Value.MVli.lpli));
  616. if (hr != hrSuccess)
  617. return hr;
  618. for (unsigned int i = 0; i < lpPropValDst->Value.MVli.cValues; ++i)
  619. lpPropValDst->Value.MVli.lpli[i].QuadPart = lpPropValSrc->Value.mvli.__ptr[i];
  620. }else {
  621. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  622. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  623. }
  624. break;
  625. case PT_SRESTRICTION:
  626. if(lpPropValSrc->__union && lpPropValSrc->Value.res) {
  627. // NOTE: we place the object pointer in lpszA to make sure it's on the same offset as Value.x on 32-bit and 64-bit machines
  628. hr = ECAllocateMore(sizeof(SRestriction), lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.lpszA));
  629. if (hr != hrSuccess)
  630. return hr;
  631. hr = CopySOAPRestrictionToMAPIRestriction((LPSRestriction)lpPropValDst->Value.lpszA, lpPropValSrc->Value.res, lpBase, lpConverter);
  632. }else {
  633. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  634. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  635. }
  636. break;
  637. case PT_ACTIONS: {
  638. if(lpPropValSrc->__union && lpPropValSrc->Value.actions) {
  639. // NOTE: we place the object pointer in lpszA to make sure it is on the same offset as Value.x on 32-bit and 64-bit machines
  640. ACTIONS *lpDstActions;
  641. hr = ECAllocateMore(sizeof(ACTIONS), lpBase, reinterpret_cast<void **>(&lpPropValDst->Value.lpszA));
  642. if (hr != hrSuccess)
  643. return hr;
  644. lpDstActions = (ACTIONS *)lpPropValDst->Value.lpszA;
  645. lpDstActions->cActions = lpPropValSrc->Value.actions->__size;
  646. hr = ECAllocateMore(sizeof(ACTION) * lpPropValSrc->Value.actions->__size, lpBase,
  647. reinterpret_cast<void **>(&lpDstActions->lpAction));
  648. if (hr != hrSuccess)
  649. return hr;
  650. lpDstActions->ulVersion = EDK_RULES_VERSION;
  651. for (gsoap_size_t i = 0; i < lpPropValSrc->Value.actions->__size; ++i) {
  652. ACTION *lpDstAction = &lpDstActions->lpAction[i];
  653. struct action *lpSrcAction = &lpPropValSrc->Value.actions->__ptr[i];
  654. lpDstAction->acttype = (ACTTYPE)lpSrcAction->acttype;
  655. lpDstAction->ulActionFlavor = lpSrcAction->flavor;
  656. lpDstAction->ulFlags = lpSrcAction->flags;
  657. lpDstAction->lpRes = NULL;
  658. lpDstAction->lpPropTagArray = NULL;
  659. switch(lpSrcAction->acttype) {
  660. case OP_MOVE:
  661. case OP_COPY:
  662. lpDstAction->actMoveCopy.cbStoreEntryId = lpSrcAction->act.moveCopy.store.__size;
  663. hr = ECAllocateMore(lpSrcAction->act.moveCopy.store.__size, lpBase, reinterpret_cast<void **>(&lpDstAction->actMoveCopy.lpStoreEntryId));
  664. if (hr != hrSuccess)
  665. return hr;
  666. memcpy(lpDstAction->actMoveCopy.lpStoreEntryId, lpSrcAction->act.moveCopy.store.__ptr, lpSrcAction->act.moveCopy.store.__size);
  667. lpDstAction->actMoveCopy.cbFldEntryId = lpSrcAction->act.moveCopy.folder.__size;
  668. hr = ECAllocateMore(lpSrcAction->act.moveCopy.folder.__size, lpBase, reinterpret_cast<void **>(&lpDstAction->actMoveCopy.lpFldEntryId));
  669. if (hr != hrSuccess)
  670. return hr;
  671. memcpy(lpDstAction->actMoveCopy.lpFldEntryId, lpSrcAction->act.moveCopy.folder.__ptr, lpSrcAction->act.moveCopy.folder.__size);
  672. break;
  673. case OP_REPLY:
  674. case OP_OOF_REPLY:
  675. lpDstAction->actReply.cbEntryId = lpSrcAction->act.reply.message.__size;
  676. hr = ECAllocateMore(lpSrcAction->act.reply.message.__size, lpBase, reinterpret_cast<void **>(&lpDstAction->actReply.lpEntryId));
  677. if (hr != hrSuccess)
  678. return hr;
  679. memcpy(lpDstAction->actReply.lpEntryId, lpSrcAction->act.reply.message.__ptr, lpSrcAction->act.reply.message.__size);
  680. if (lpSrcAction->act.reply.guid.__size != sizeof(GUID))
  681. return MAPI_E_CORRUPT_DATA;
  682. memcpy(&lpDstAction->actReply.guidReplyTemplate, lpSrcAction->act.reply.guid.__ptr, lpSrcAction->act.reply.guid.__size);
  683. break;
  684. case OP_DEFER_ACTION:
  685. hr = ECAllocateMore(lpSrcAction->act.defer.bin.__size, lpBase, reinterpret_cast<void **>(&lpDstAction->actDeferAction.pbData));
  686. if (hr != hrSuccess)
  687. return hr;
  688. lpDstAction->actDeferAction.cbData = lpSrcAction->act.defer.bin.__size;
  689. memcpy(lpDstAction->actDeferAction.pbData, lpSrcAction->act.defer.bin.__ptr,lpSrcAction->act.defer.bin.__size);
  690. break;
  691. case OP_BOUNCE:
  692. lpDstAction->scBounceCode = lpSrcAction->act.bouncecode;
  693. break;
  694. case OP_FORWARD:
  695. case OP_DELEGATE:
  696. if (lpSrcAction->act.adrlist == NULL)
  697. return MAPI_E_CORRUPT_DATA;
  698. hr = ECAllocateMore(CbNewADRLIST(lpSrcAction->act.adrlist->__size), lpBase, reinterpret_cast<void **>(&lpDstAction->lpadrlist));
  699. if (hr != hrSuccess)
  700. return hr;
  701. lpDstAction->lpadrlist->cEntries = lpSrcAction->act.adrlist->__size;
  702. for (gsoap_size_t j = 0; j < lpSrcAction->act.adrlist->__size; ++j) {
  703. lpDstAction->lpadrlist->aEntries[j].ulReserved1 = 0;
  704. lpDstAction->lpadrlist->aEntries[j].cValues = lpSrcAction->act.adrlist->__ptr[j].__size;
  705. // new rowset allocate more on old rowset, so we can just call FreeProws once
  706. hr = ECAllocateMore(sizeof(SPropValue) * lpSrcAction->act.adrlist->__ptr[j].__size, lpBase,
  707. reinterpret_cast<void **>(&lpDstAction->lpadrlist->aEntries[j].rgPropVals));
  708. if (hr != hrSuccess)
  709. return hr;
  710. hr = CopySOAPRowToMAPIRow(&lpSrcAction->act.adrlist->__ptr[j], lpDstAction->lpadrlist->aEntries[j].rgPropVals, lpBase, lpConverter);
  711. if (hr != hrSuccess)
  712. return hr;
  713. }
  714. // FIXME rowset is not coupled to action -> leaks!
  715. break;
  716. case OP_TAG:
  717. hr = CopySOAPPropValToMAPIPropVal(&lpDstAction->propTag, lpSrcAction->act.prop, lpBase, lpConverter);
  718. break;
  719. }
  720. }
  721. }else {
  722. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  723. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  724. }
  725. break;
  726. }
  727. default:
  728. lpPropValDst->ulPropTag = PROP_TAG(PT_ERROR, PROP_ID(lpPropValSrc->ulPropTag));
  729. lpPropValDst->Value.err = MAPI_E_NOT_FOUND;
  730. break;
  731. }
  732. return hr;
  733. }
  734. HRESULT CopySOAPRowToMAPIRow(void *lpProvider,
  735. const struct propValArray *lpsRowSrc, LPSPropValue lpsRowDst,
  736. void **lpBase, ULONG ulType, convert_context *lpConverter)
  737. {
  738. if (lpConverter == NULL && lpsRowSrc->__size > 1) {
  739. // Try again with a converter to reuse the iconv instances
  740. convert_context converter;
  741. return CopySOAPRowToMAPIRow(lpProvider, lpsRowSrc, lpsRowDst, lpBase, ulType, &converter);
  742. }
  743. for (gsoap_size_t j = 0; j < lpsRowSrc->__size; ++j) {
  744. // First, try the default TableRowGetProp from ECMAPIProp
  745. if((ulType == MAPI_STORE || ulType == MAPI_FOLDER || ulType == MAPI_MESSAGE || ulType == MAPI_ATTACH) &&
  746. ECMAPIProp::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  747. continue;
  748. else if((ulType == MAPI_MAILUSER || ulType == MAPI_ABCONT || ulType == MAPI_DISTLIST)&&
  749. ECABProp::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  750. continue;
  751. switch(ulType) {
  752. case MAPI_FOLDER:
  753. // Then, try the specialized TableRowGetProp for the type of table we're handling
  754. if (ECMAPIFolder::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  755. continue;
  756. break;
  757. case MAPI_MESSAGE:
  758. if (ECMessage::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  759. continue;
  760. break;
  761. case MAPI_MAILUSER:
  762. if (ECMailUser::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  763. continue;
  764. break;
  765. case MAPI_DISTLIST:
  766. if (ECDistList::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  767. continue;
  768. break;
  769. case MAPI_ABCONT:
  770. if (ECABContainer::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  771. continue;
  772. break;
  773. case MAPI_STORE:
  774. if (ECMsgStore::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  775. continue;
  776. break;
  777. }
  778. if (ECGenericProp::TableRowGetProp(lpProvider, &lpsRowSrc->__ptr[j], &lpsRowDst[j], lpBase, ulType) == erSuccess)
  779. continue;
  780. // If all fails, get the actual data from the server
  781. CopySOAPPropValToMAPIPropVal(&lpsRowDst[j], &lpsRowSrc->__ptr[j], lpBase, lpConverter);
  782. }
  783. return hrSuccess;
  784. }
  785. HRESULT CopySOAPEntryId(const entryId *lpSrc, entryId *lpDst)
  786. {
  787. if (lpSrc == NULL || lpDst == NULL)
  788. return MAPI_E_INVALID_PARAMETER;
  789. lpDst->__size = lpSrc->__size;
  790. lpDst->__ptr = s_alloc<unsigned char>(nullptr, lpDst->__size);
  791. memcpy(lpDst->__ptr, lpSrc->__ptr, lpDst->__size);
  792. return hrSuccess;
  793. }
  794. HRESULT CopyMAPIEntryIdToSOAPEntryId(ULONG cbEntryIdSrc,
  795. const ENTRYID *lpEntryIdSrc, entryId **lppDest)
  796. {
  797. HRESULT hr = hrSuccess;
  798. auto lpDest = s_alloc<entryId>(nullptr);
  799. hr = CopyMAPIEntryIdToSOAPEntryId(cbEntryIdSrc, lpEntryIdSrc, lpDest, false);
  800. if(hr != hrSuccess)
  801. goto exit;
  802. *lppDest = lpDest;
  803. exit:
  804. if(hr != hrSuccess)
  805. s_free(nullptr, lpDest);
  806. return hr;
  807. }
  808. HRESULT CopyMAPIEntryIdToSOAPEntryId(ULONG cbEntryIdSrc,
  809. const ENTRYID *lpEntryIdSrc, entryId *lpDest, bool bCheapCopy)
  810. {
  811. if ((cbEntryIdSrc > 0 && lpEntryIdSrc == NULL) || lpDest == NULL)
  812. return MAPI_E_INVALID_PARAMETER;
  813. if(cbEntryIdSrc == 0) {
  814. lpDest->__ptr = NULL;
  815. lpDest->__size = 0;
  816. return hrSuccess;
  817. }
  818. if(bCheapCopy == false) {
  819. lpDest->__ptr = s_alloc<unsigned char>(nullptr, cbEntryIdSrc);
  820. memcpy(lpDest->__ptr, lpEntryIdSrc, cbEntryIdSrc);
  821. }else{
  822. lpDest->__ptr = (LPBYTE)lpEntryIdSrc;
  823. }
  824. lpDest->__size = cbEntryIdSrc;
  825. return hrSuccess;
  826. }
  827. HRESULT CopySOAPEntryIdToMAPIEntryId(const entryId *lpSrc, ULONG *lpcbDest,
  828. LPENTRYID *lppEntryIdDest, void *lpBase)
  829. {
  830. HRESULT hr;
  831. LPENTRYID lpEntryId = NULL;
  832. if (lpSrc == NULL || lpcbDest == NULL || lppEntryIdDest == NULL)
  833. return MAPI_E_INVALID_PARAMETER;
  834. if (lpSrc->__size == 0)
  835. return MAPI_E_INVALID_ENTRYID;
  836. if(lpBase)
  837. hr = ECAllocateMore(lpSrc->__size, lpBase, (void**)&lpEntryId);
  838. else
  839. hr = ECAllocateBuffer(lpSrc->__size, (void**)&lpEntryId);
  840. if(hr != hrSuccess)
  841. return hr;
  842. memcpy(lpEntryId, lpSrc->__ptr, lpSrc->__size);
  843. *lppEntryIdDest = lpEntryId;
  844. *lpcbDest = lpSrc->__size;
  845. return hrSuccess;
  846. }
  847. HRESULT CopySOAPEntryIdToMAPIEntryId(const entryId *lpSrc, ULONG ulObjId,
  848. ULONG ulType, ULONG *lpcbDest, LPENTRYID *lppEntryIdDest, void *lpBase)
  849. {
  850. HRESULT hr;
  851. ULONG cbEntryId = 0;
  852. LPENTRYID lpEntryId = NULL;
  853. if (lpSrc == NULL || lpcbDest == NULL || lppEntryIdDest == NULL)
  854. return MAPI_E_INVALID_PARAMETER;
  855. if((unsigned int)lpSrc->__size < CbNewABEID("") || lpSrc->__ptr == NULL)
  856. return MAPI_E_INVALID_ENTRYID;
  857. if (lpBase != NULL)
  858. hr = MAPIAllocateMore(lpSrc->__size, lpBase, (void**)&lpEntryId);
  859. else
  860. hr = MAPIAllocateBuffer(lpSrc->__size, (void**)&lpEntryId);
  861. if (hr != hrSuccess)
  862. return hr;
  863. memcpy(lpEntryId, lpSrc->__ptr, lpSrc->__size);
  864. cbEntryId = lpSrc->__size;
  865. *lppEntryIdDest = lpEntryId;
  866. *lpcbDest = cbEntryId;
  867. return hrSuccess;
  868. }
  869. HRESULT CopySOAPEntryIdToMAPIEntryId(const entryId *lpSrc, ULONG ulObjId,
  870. ULONG *lpcbDest, LPENTRYID *lppEntryIdDest, void *lpBase)
  871. {
  872. return CopySOAPEntryIdToMAPIEntryId(lpSrc, ulObjId, MAPI_MAILUSER, lpcbDest, lppEntryIdDest, lpBase);
  873. }
  874. HRESULT CopyMAPIEntryListToSOAPEntryList(const ENTRYLIST *lpMsgList,
  875. struct entryList *lpsEntryList)
  876. {
  877. unsigned int i = 0;
  878. if (lpMsgList == NULL || lpsEntryList == NULL)
  879. return MAPI_E_INVALID_PARAMETER;
  880. if(lpMsgList->cValues == 0 || lpMsgList->lpbin == NULL) {
  881. lpsEntryList->__ptr = NULL;
  882. lpsEntryList->__size = 0;
  883. return hrSuccess;
  884. }
  885. lpsEntryList->__ptr = s_alloc<entryId>(nullptr, lpMsgList->cValues);
  886. for (i = 0; i < lpMsgList->cValues; ++i) {
  887. lpsEntryList->__ptr[i].__ptr = s_alloc<unsigned char>(nullptr, lpMsgList->lpbin[i].cb);
  888. memcpy(lpsEntryList->__ptr[i].__ptr, lpMsgList->lpbin[i].lpb, lpMsgList->lpbin[i].cb);
  889. lpsEntryList->__ptr[i].__size = lpMsgList->lpbin[i].cb;
  890. }
  891. lpsEntryList->__size = i;
  892. return hrSuccess;
  893. }
  894. HRESULT CopySOAPEntryListToMAPIEntryList(const struct entryList *lpsEntryList,
  895. LPENTRYLIST *lppMsgList)
  896. {
  897. HRESULT hr = hrSuccess;
  898. unsigned int i = 0;
  899. ecmem_ptr<ENTRYLIST> lpMsgList;
  900. if (lpsEntryList == nullptr || lppMsgList == nullptr)
  901. return MAPI_E_INVALID_PARAMETER;
  902. hr = ECAllocateBuffer(sizeof(ENTRYLIST), &~lpMsgList);
  903. if(hr != hrSuccess)
  904. return hr;
  905. if(lpsEntryList->__size == 0) {
  906. lpMsgList->cValues = 0;
  907. lpMsgList->lpbin = NULL;
  908. } else {
  909. hr = ECAllocateMore(lpsEntryList->__size * sizeof(SBinary), lpMsgList, (void**)&lpMsgList->lpbin);
  910. if(hr != hrSuccess)
  911. return hr;
  912. }
  913. for (i = 0; i < lpsEntryList->__size; ++i) {
  914. hr = ECAllocateMore(lpsEntryList->__ptr[i].__size, lpMsgList, (void**)&lpMsgList->lpbin[i].lpb);
  915. if(hr != hrSuccess)
  916. return hr;
  917. memcpy(lpMsgList->lpbin[i].lpb, lpsEntryList->__ptr[i].__ptr, lpsEntryList->__ptr[i].__size);
  918. lpMsgList->lpbin[i].cb = lpsEntryList->__ptr[i].__size;
  919. }
  920. lpMsgList->cValues = i;
  921. *lppMsgList = lpMsgList.release();
  922. return hrSuccess;
  923. }
  924. HRESULT CopySOAPRowToMAPIRow(const struct propValArray *lpsRowSrc,
  925. LPSPropValue lpsRowDst, void *lpBase, convert_context *lpConverter)
  926. {
  927. HRESULT hr;
  928. if (lpConverter == NULL && lpsRowSrc->__size > 1) {
  929. convert_context converter;
  930. return CopySOAPRowToMAPIRow(lpsRowSrc, lpsRowDst, lpBase, &converter);
  931. }
  932. for (gsoap_size_t j = 0; j < lpsRowSrc->__size; ++j) {
  933. // If all fails, get the actual data from the server
  934. hr = CopySOAPPropValToMAPIPropVal(&lpsRowDst[j], &lpsRowSrc->__ptr[j], lpBase, lpConverter);
  935. if(hr != hrSuccess)
  936. return hr;
  937. }
  938. return hrSuccess;
  939. }
  940. HRESULT CopyMAPIRowToSOAPRow(const SRow *lpRowSrc,
  941. struct propValArray *lpsRowDst, convert_context *lpConverter)
  942. {
  943. HRESULT hr = hrSuccess;
  944. struct propVal* lpPropVal = NULL;
  945. if (lpConverter == NULL && lpRowSrc->cValues > 1) {
  946. convert_context converter;
  947. return CopyMAPIRowToSOAPRow(lpRowSrc, lpsRowDst, &converter);
  948. }
  949. lpPropVal = s_alloc<propVal>(nullptr, lpRowSrc->cValues);
  950. memset(lpPropVal, 0, sizeof(struct propVal) *lpRowSrc->cValues);
  951. lpsRowDst->__ptr = lpPropVal;
  952. lpsRowDst->__size = 0;
  953. for (unsigned int i = 0; i < lpRowSrc->cValues; ++i) {
  954. hr = CopyMAPIPropValToSOAPPropVal(&lpPropVal[i], &lpRowSrc->lpProps[i], lpConverter);
  955. if (hr != hrSuccess) {
  956. FreePropValArray(lpsRowDst, false);
  957. lpsRowDst->__ptr = nullptr;
  958. return hr;
  959. }
  960. ++lpsRowDst->__size;
  961. }
  962. return hrSuccess;
  963. }
  964. HRESULT CopyMAPIRowSetToSOAPRowSet(const SRowSet *lpRowSetSrc,
  965. struct rowSet **lppsRowSetDst, convert_context *lpConverter)
  966. {
  967. HRESULT hr = hrSuccess;
  968. struct rowSet *lpsRowSetDst = NULL;
  969. if (lpConverter == NULL && lpRowSetSrc->cRows > 1) {
  970. convert_context converter;
  971. return CopyMAPIRowSetToSOAPRowSet(lpRowSetSrc, lppsRowSetDst, &converter);
  972. }
  973. lpsRowSetDst = s_alloc<rowSet>(nullptr);
  974. lpsRowSetDst->__ptr = NULL;
  975. lpsRowSetDst->__size = 0;
  976. if (lpRowSetSrc->cRows > 0) {
  977. lpsRowSetDst->__ptr = s_alloc<propValArray>(nullptr, lpRowSetSrc->cRows);
  978. lpsRowSetDst->__size = 0;
  979. for (unsigned int i = 0; i < lpRowSetSrc->cRows; ++i) {
  980. hr = CopyMAPIRowToSOAPRow(&lpRowSetSrc->aRow[i], &lpsRowSetDst->__ptr[i], lpConverter);
  981. if (hr != hrSuccess) {
  982. FreeRowSet(lpsRowSetDst, false);
  983. return hr;
  984. }
  985. ++lpsRowSetDst->__size;
  986. }
  987. }
  988. *lppsRowSetDst = lpsRowSetDst;
  989. return hrSuccess;
  990. }
  991. // Copies a row set, filling in client-side generated values on the fly
  992. HRESULT CopySOAPRowSetToMAPIRowSet(void *lpProvider,
  993. const struct rowSet *lpsRowSetSrc, LPSRowSet *lppRowSetDst, ULONG ulType)
  994. {
  995. HRESULT hr = hrSuccess;
  996. ULONG ulRows = 0;
  997. LPSRowSet lpRowSet = NULL;
  998. convert_context converter;
  999. ulRows = lpsRowSetSrc->__size;
  1000. // Allocate space for the rowset
  1001. hr = ECAllocateBuffer(CbNewSRowSet(ulRows), reinterpret_cast<void **>(&lpRowSet));
  1002. if (hr != hrSuccess)
  1003. return hr;
  1004. // Loop through all the rows and values, fill in any client-side generated values, or translate
  1005. // some serverside values through TableRowGetProps
  1006. for (lpRowSet->cRows = 0; lpRowSet->cRows < ulRows; ++lpRowSet->cRows) {
  1007. auto i = lpRowSet->cRows;
  1008. lpRowSet->aRow[i].ulAdrEntryPad = 0;
  1009. lpRowSet->aRow[i].cValues = lpsRowSetSrc->__ptr[i].__size;
  1010. hr = ECAllocateBuffer(sizeof(SPropValue) * lpsRowSetSrc->__ptr[i].__size, reinterpret_cast<void **>(&lpRowSet->aRow[i].lpProps));
  1011. if (hr != hrSuccess)
  1012. goto exit;
  1013. CopySOAPRowToMAPIRow(lpProvider, &lpsRowSetSrc->__ptr[i], lpRowSet->aRow[i].lpProps, (void **)lpRowSet->aRow[i].lpProps, ulType, &converter);
  1014. }
  1015. *lppRowSetDst = lpRowSet;
  1016. exit:
  1017. if (hr != hrSuccess)
  1018. FreeProws(lpRowSet);
  1019. return hr;
  1020. }
  1021. HRESULT CopySOAPRestrictionToMAPIRestriction(LPSRestriction lpDst,
  1022. const struct restrictTable *lpSrc, void *lpBase,
  1023. convert_context *lpConverter)
  1024. {
  1025. HRESULT hr = hrSuccess;
  1026. if (lpSrc == NULL)
  1027. return MAPI_E_INVALID_PARAMETER;
  1028. if (lpConverter == NULL) {
  1029. convert_context converter;
  1030. CopySOAPRestrictionToMAPIRestriction(lpDst, lpSrc, lpBase, &converter);
  1031. return hrSuccess;
  1032. }
  1033. memset(lpDst, 0, sizeof(SRestriction));
  1034. lpDst->rt = lpSrc->ulType;
  1035. switch(lpSrc->ulType) {
  1036. case RES_OR:
  1037. if (lpSrc->lpOr == NULL)
  1038. return MAPI_E_INVALID_PARAMETER;
  1039. lpDst->res.resOr.cRes = lpSrc->lpOr->__size;
  1040. hr = ECAllocateMore(sizeof(SRestriction) * lpSrc->lpOr->__size, lpBase,
  1041. reinterpret_cast<void **>(&lpDst->res.resOr.lpRes));
  1042. if (hr != hrSuccess)
  1043. return hr;
  1044. for (gsoap_size_t i = 0; i < lpSrc->lpOr->__size; ++i) {
  1045. hr = CopySOAPRestrictionToMAPIRestriction(&lpDst->res.resOr.lpRes[i], lpSrc->lpOr->__ptr[i], lpBase, lpConverter);
  1046. if(hr != hrSuccess)
  1047. return hr;
  1048. }
  1049. break;
  1050. case RES_AND:
  1051. if (lpSrc->lpAnd == NULL)
  1052. return MAPI_E_INVALID_PARAMETER;
  1053. lpDst->res.resAnd.cRes = lpSrc->lpAnd->__size;
  1054. hr = ECAllocateMore(sizeof(SRestriction) * lpSrc->lpAnd->__size, lpBase,
  1055. reinterpret_cast<void **>(&lpDst->res.resAnd.lpRes));
  1056. if (hr != hrSuccess)
  1057. return hr;
  1058. for (gsoap_size_t i = 0; i < lpSrc->lpAnd->__size; ++i) {
  1059. hr = CopySOAPRestrictionToMAPIRestriction(&lpDst->res.resAnd.lpRes[i], lpSrc->lpAnd->__ptr[i], lpBase, lpConverter);
  1060. if(hr != hrSuccess)
  1061. return hr;
  1062. }
  1063. break;
  1064. case RES_BITMASK:
  1065. if (lpSrc->lpBitmask == NULL)
  1066. return MAPI_E_INVALID_PARAMETER;
  1067. lpDst->res.resBitMask.relBMR = lpSrc->lpBitmask->ulType;
  1068. lpDst->res.resBitMask.ulMask = lpSrc->lpBitmask->ulMask;
  1069. lpDst->res.resBitMask.ulPropTag = lpSrc->lpBitmask->ulPropTag;
  1070. break;
  1071. case RES_COMMENT:
  1072. if (lpSrc->lpComment == NULL)
  1073. return MAPI_E_INVALID_PARAMETER;
  1074. hr = ECAllocateMore(sizeof(SRestriction), lpBase, (void **) &lpDst->res.resComment.lpRes);
  1075. if (hr != hrSuccess)
  1076. return hr;
  1077. hr = CopySOAPRestrictionToMAPIRestriction(lpDst->res.resComment.lpRes, lpSrc->lpComment->lpResTable, lpBase, lpConverter);
  1078. if (hr != hrSuccess)
  1079. return hr;
  1080. lpDst->res.resComment.cValues = lpSrc->lpComment->sProps.__size;
  1081. hr = ECAllocateMore(sizeof(SPropValue) * lpSrc->lpComment->sProps.__size, lpBase, (void **)&lpDst->res.resComment.lpProp);
  1082. if (hr != hrSuccess)
  1083. return hr;
  1084. for (gsoap_size_t i = 0; i < lpSrc->lpComment->sProps.__size; ++i) {
  1085. hr = CopySOAPPropValToMAPIPropVal(&lpDst->res.resComment.lpProp[i], &lpSrc->lpComment->sProps.__ptr[i], lpBase, lpConverter);
  1086. if (hr != hrSuccess)
  1087. return hr;
  1088. }
  1089. break;
  1090. case RES_COMPAREPROPS:
  1091. if (lpSrc->lpCompare == NULL)
  1092. return MAPI_E_INVALID_PARAMETER;
  1093. lpDst->res.resCompareProps.relop = lpSrc->lpCompare->ulType;
  1094. lpDst->res.resCompareProps.ulPropTag1 = lpSrc->lpCompare->ulPropTag1;
  1095. lpDst->res.resCompareProps.ulPropTag2 = lpSrc->lpCompare->ulPropTag2;
  1096. break;
  1097. case RES_CONTENT:
  1098. if (lpSrc->lpContent == NULL || lpSrc->lpContent->lpProp == NULL)
  1099. return MAPI_E_INVALID_PARAMETER;
  1100. lpDst->res.resContent.ulFuzzyLevel = lpSrc->lpContent->ulFuzzyLevel;
  1101. lpDst->res.resContent.ulPropTag = lpSrc->lpContent->ulPropTag;
  1102. hr = ECAllocateMore(sizeof(SPropValue), lpBase, (void **) &lpDst->res.resContent.lpProp);
  1103. if(hr != hrSuccess)
  1104. return hr;
  1105. hr = CopySOAPPropValToMAPIPropVal(lpDst->res.resContent.lpProp, lpSrc->lpContent->lpProp, lpBase, lpConverter);
  1106. if(hr != hrSuccess)
  1107. return hr;
  1108. break;
  1109. case RES_EXIST:
  1110. if (lpSrc->lpExist == NULL)
  1111. return MAPI_E_INVALID_PARAMETER;
  1112. lpDst->res.resExist.ulPropTag = lpSrc->lpExist->ulPropTag;
  1113. break;
  1114. case RES_NOT:
  1115. if (lpSrc->lpNot == NULL || lpSrc->lpNot->lpNot == NULL)
  1116. return MAPI_E_INVALID_PARAMETER;
  1117. hr = ECAllocateMore(sizeof(SRestriction), lpBase, reinterpret_cast<void **>(&lpDst->res.resNot.lpRes));
  1118. if (hr != hrSuccess)
  1119. return hr;
  1120. hr = CopySOAPRestrictionToMAPIRestriction(lpDst->res.resNot.lpRes, lpSrc->lpNot->lpNot, lpBase, lpConverter);
  1121. break;
  1122. case RES_PROPERTY:
  1123. if (lpSrc->lpProp == NULL || lpSrc->lpProp->lpProp == NULL)
  1124. return MAPI_E_INVALID_PARAMETER;
  1125. hr = ECAllocateMore(sizeof(SPropValue), lpBase, reinterpret_cast<void **>(&lpDst->res.resProperty.lpProp));
  1126. if (hr != hrSuccess)
  1127. return hr;
  1128. lpDst->res.resProperty.relop = lpSrc->lpProp->ulType;
  1129. lpDst->res.resProperty.ulPropTag = lpSrc->lpProp->ulPropTag;
  1130. hr = CopySOAPPropValToMAPIPropVal(lpDst->res.resProperty.lpProp, lpSrc->lpProp->lpProp, lpBase, lpConverter);
  1131. break;
  1132. case RES_SIZE:
  1133. if (lpSrc->lpSize == NULL)
  1134. return MAPI_E_INVALID_PARAMETER;
  1135. lpDst->res.resSize.cb = lpSrc->lpSize->cb;
  1136. lpDst->res.resSize.relop = lpSrc->lpSize->ulType;
  1137. lpDst->res.resSize.ulPropTag = lpSrc->lpSize->ulPropTag;
  1138. break;
  1139. case RES_SUBRESTRICTION:
  1140. if (lpSrc->lpSub == NULL || lpSrc->lpSub->lpSubObject == NULL)
  1141. return MAPI_E_INVALID_PARAMETER;
  1142. lpDst->res.resSub.ulSubObject = lpSrc->lpSub->ulSubObject;
  1143. hr = ECAllocateMore(sizeof(SRestriction), lpBase, reinterpret_cast<void **>(&lpDst->res.resSub.lpRes));
  1144. if (hr != hrSuccess)
  1145. return hr;
  1146. hr = CopySOAPRestrictionToMAPIRestriction(lpDst->res.resSub.lpRes, lpSrc->lpSub->lpSubObject, lpBase, lpConverter);
  1147. break;
  1148. default:
  1149. hr = MAPI_E_INVALID_PARAMETER;
  1150. break;
  1151. }
  1152. return hr;
  1153. }
  1154. HRESULT CopyMAPIRestrictionToSOAPRestriction(struct restrictTable **lppDst,
  1155. const SRestriction *lpSrc, convert_context *lpConverter)
  1156. {
  1157. HRESULT hr = hrSuccess;
  1158. struct restrictTable *lpDst = NULL;
  1159. unsigned int i=0;
  1160. if (lpConverter == NULL) {
  1161. convert_context converter;
  1162. hr = CopyMAPIRestrictionToSOAPRestriction(lppDst, lpSrc, &converter);
  1163. goto exit;
  1164. }
  1165. lpDst = s_alloc<restrictTable>(nullptr);
  1166. memset(lpDst, 0, sizeof(restrictTable));
  1167. lpDst->ulType = lpSrc->rt;
  1168. switch(lpSrc->rt) {
  1169. case RES_OR:
  1170. lpDst->lpOr = s_alloc<restrictOr>(nullptr);
  1171. memset(lpDst->lpOr,0,sizeof(restrictOr));
  1172. lpDst->lpOr->__ptr = s_alloc<restrictTable *>(nullptr, lpSrc->res.resOr.cRes);
  1173. memset(lpDst->lpOr->__ptr, 0, sizeof(restrictTable*) * lpSrc->res.resOr.cRes);
  1174. lpDst->lpOr->__size = lpSrc->res.resOr.cRes;
  1175. for (i = 0; i < lpSrc->res.resOr.cRes; ++i) {
  1176. hr = CopyMAPIRestrictionToSOAPRestriction(&(lpDst->lpOr->__ptr[i]), &lpSrc->res.resOr.lpRes[i], lpConverter);
  1177. if(hr != hrSuccess)
  1178. goto exit;
  1179. }
  1180. break;
  1181. case RES_AND:
  1182. lpDst->lpAnd = s_alloc<restrictAnd>(nullptr);
  1183. memset(lpDst->lpAnd,0,sizeof(restrictAnd));
  1184. lpDst->lpAnd->__ptr = s_alloc<restrictTable *>(nullptr, lpSrc->res.resAnd.cRes);
  1185. memset(lpDst->lpAnd->__ptr, 0, sizeof(restrictTable*) * lpSrc->res.resAnd.cRes);
  1186. lpDst->lpAnd->__size = lpSrc->res.resAnd.cRes;
  1187. for (i = 0; i < lpSrc->res.resAnd.cRes; ++i) {
  1188. hr = CopyMAPIRestrictionToSOAPRestriction(&lpDst->lpAnd->__ptr[i], &lpSrc->res.resAnd.lpRes[i], lpConverter);
  1189. if(hr != hrSuccess)
  1190. goto exit;
  1191. }
  1192. break;
  1193. case RES_BITMASK:
  1194. lpDst->lpBitmask = s_alloc<restrictBitmask>(nullptr);
  1195. memset(lpDst->lpBitmask, 0, sizeof(restrictBitmask));
  1196. lpDst->lpBitmask->ulMask = lpSrc->res.resBitMask.ulMask;
  1197. lpDst->lpBitmask->ulPropTag = lpSrc->res.resBitMask.ulPropTag;
  1198. lpDst->lpBitmask->ulType = lpSrc->res.resBitMask.relBMR;
  1199. break;
  1200. case RES_COMMENT:
  1201. lpDst->lpComment = s_alloc<restrictComment>(nullptr);
  1202. memset(lpDst->lpComment, 0, sizeof(restrictComment));
  1203. lpDst->lpComment->sProps.__ptr = s_alloc<propVal>(nullptr, lpSrc->res.resComment.cValues);
  1204. lpDst->lpComment->sProps.__size = lpSrc->res.resComment.cValues;
  1205. for (unsigned int i = 0; i < lpSrc->res.resComment.cValues; ++i) {
  1206. hr = CopyMAPIPropValToSOAPPropVal(&lpDst->lpComment->sProps.__ptr[i], &lpSrc->res.resComment.lpProp[i], lpConverter);
  1207. if(hr != hrSuccess)
  1208. goto exit;
  1209. }
  1210. hr = CopyMAPIRestrictionToSOAPRestriction(&lpDst->lpComment->lpResTable, lpSrc->res.resComment.lpRes, lpConverter);
  1211. if (hr != hrSuccess)
  1212. goto exit;
  1213. break;
  1214. case RES_COMPAREPROPS:
  1215. lpDst->lpCompare = s_alloc<restrictCompare>(nullptr);
  1216. memset(lpDst->lpCompare, 0, sizeof(restrictCompare));
  1217. lpDst->lpCompare->ulPropTag1 = lpSrc->res.resCompareProps.ulPropTag1;
  1218. lpDst->lpCompare->ulPropTag2 = lpSrc->res.resCompareProps.ulPropTag2;
  1219. lpDst->lpCompare->ulType = lpSrc->res.resCompareProps.relop;
  1220. break;
  1221. case RES_CONTENT:
  1222. lpDst->lpContent = s_alloc<restrictContent>(nullptr);
  1223. memset(lpDst->lpContent, 0, sizeof(restrictContent));
  1224. if( (PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_BINARY &&
  1225. PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_MV_BINARY &&
  1226. PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_STRING8 &&
  1227. PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_MV_STRING8 &&
  1228. PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_UNICODE &&
  1229. PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) != PT_MV_UNICODE) ||
  1230. (PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) == PT_BINARY && lpSrc->res.resContent.lpProp->Value.bin.cb >0 && lpSrc->res.resContent.lpProp->Value.bin.lpb == NULL) ||
  1231. (PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) == PT_STRING8 && lpSrc->res.resContent.lpProp->Value.lpszA == NULL) ||
  1232. (PROP_TYPE(lpSrc->res.resContent.lpProp->ulPropTag) == PT_UNICODE && lpSrc->res.resContent.lpProp->Value.lpszW == NULL)) {
  1233. hr = MAPI_E_INVALID_PARAMETER;
  1234. goto exit;
  1235. }
  1236. lpDst->lpContent->ulFuzzyLevel = lpSrc->res.resContent.ulFuzzyLevel;
  1237. lpDst->lpContent->ulPropTag = lpSrc->res.resContent.ulPropTag;
  1238. lpDst->lpContent->lpProp = s_alloc<propVal>(nullptr);
  1239. memset(lpDst->lpContent->lpProp, 0, sizeof(propVal));
  1240. hr = CopyMAPIPropValToSOAPPropVal(lpDst->lpContent->lpProp, lpSrc->res.resContent.lpProp, lpConverter);
  1241. if(hr != hrSuccess)
  1242. goto exit;
  1243. break;
  1244. case RES_EXIST:
  1245. lpDst->lpExist = s_alloc<restrictExist>(nullptr);
  1246. memset(lpDst->lpExist, 0, sizeof(restrictExist));
  1247. lpDst->lpExist->ulPropTag = lpSrc->res.resExist.ulPropTag;
  1248. break;
  1249. case RES_NOT:
  1250. lpDst->lpNot = s_alloc<restrictNot>(nullptr);
  1251. memset(lpDst->lpNot, 0, sizeof(restrictNot));
  1252. hr = CopyMAPIRestrictionToSOAPRestriction(&lpDst->lpNot->lpNot, lpSrc->res.resNot.lpRes, lpConverter);
  1253. if(hr != hrSuccess)
  1254. goto exit;
  1255. break;
  1256. case RES_PROPERTY:
  1257. lpDst->lpProp = s_alloc<restrictProp>(nullptr);
  1258. memset(lpDst->lpProp, 0, sizeof(restrictProp));
  1259. lpDst->lpProp->ulType = lpSrc->res.resProperty.relop;
  1260. lpDst->lpProp->lpProp = s_alloc<propVal>(nullptr);
  1261. memset(lpDst->lpProp->lpProp, 0, sizeof(propVal));
  1262. lpDst->lpProp->ulPropTag = lpSrc->res.resProperty.ulPropTag;
  1263. hr = CopyMAPIPropValToSOAPPropVal(lpDst->lpProp->lpProp, lpSrc->res.resProperty.lpProp, lpConverter);
  1264. if(hr != hrSuccess)
  1265. goto exit;
  1266. break;
  1267. case RES_SIZE:
  1268. lpDst->lpSize = s_alloc<restrictSize>(nullptr);
  1269. memset(lpDst->lpSize, 0, sizeof(restrictSize));
  1270. lpDst->lpSize->cb = lpSrc->res.resSize.cb;
  1271. lpDst->lpSize->ulPropTag = lpSrc->res.resSize.ulPropTag;
  1272. lpDst->lpSize->ulType = lpSrc->res.resSize.relop;
  1273. break;
  1274. case RES_SUBRESTRICTION:
  1275. lpDst->lpSub = s_alloc<restrictSub>(nullptr);
  1276. memset(lpDst->lpSub, 0, sizeof(restrictSub));
  1277. lpDst->lpSub->ulSubObject = lpSrc->res.resSub.ulSubObject;
  1278. hr = CopyMAPIRestrictionToSOAPRestriction(&lpDst->lpSub->lpSubObject, lpSrc->res.resSub.lpRes, lpConverter);
  1279. if(hr != hrSuccess)
  1280. goto exit;
  1281. break;
  1282. default:
  1283. hr = MAPI_E_INVALID_PARAMETER;
  1284. goto exit;
  1285. }
  1286. *lppDst = lpDst;
  1287. exit:
  1288. if(hr != hrSuccess && lpDst != NULL)
  1289. FreeRestrictTable(lpDst);
  1290. return hr;
  1291. }
  1292. static HRESULT CopySOAPPropTagArrayToMAPIPropTagArray(
  1293. const struct propTagArray *lpsPropTagArray,
  1294. LPSPropTagArray *lppPropTagArray, void *lpBase)
  1295. {
  1296. HRESULT hr;
  1297. LPSPropTagArray lpPropTagArray = NULL;
  1298. if (lpsPropTagArray == NULL || lppPropTagArray == NULL)
  1299. return MAPI_E_INVALID_PARAMETER;
  1300. if(lpBase)
  1301. hr = ECAllocateMore(CbNewSPropTagArray(lpsPropTagArray->__size), lpBase, (void**)&lpPropTagArray);
  1302. else
  1303. hr = ECAllocateBuffer(CbNewSPropTagArray(lpsPropTagArray->__size), (void**)&lpPropTagArray);
  1304. if(hr != hrSuccess)
  1305. return hr;
  1306. lpPropTagArray->cValues = lpsPropTagArray->__size;
  1307. if(lpsPropTagArray->__size > 0)
  1308. memcpy(lpPropTagArray->aulPropTag, lpsPropTagArray->__ptr, sizeof(unsigned int)*lpsPropTagArray->__size);
  1309. *lppPropTagArray = lpPropTagArray;
  1310. return hr;
  1311. }
  1312. HRESULT Utf8ToTString(LPCSTR lpszUtf8, ULONG ulFlags, LPVOID lpBase, convert_context *lpConverter, LPTSTR *lppszTString)
  1313. {
  1314. HRESULT hr;
  1315. std::string strDest;
  1316. size_t cbDest;
  1317. if (lpszUtf8 == NULL || lppszTString == NULL)
  1318. return MAPI_E_INVALID_PARAMETER;
  1319. strDest = CONVERT_TO(lpConverter, std::string, ((ulFlags & MAPI_UNICODE) ? CHARSET_WCHAR : CHARSET_CHAR), lpszUtf8, rawsize(lpszUtf8), "UTF-8");
  1320. cbDest = strDest.length() + ((ulFlags & MAPI_UNICODE) ? sizeof(WCHAR) : sizeof(CHAR));
  1321. if (lpBase)
  1322. hr = ECAllocateMore(cbDest, lpBase, (LPVOID*)lppszTString);
  1323. else
  1324. hr = ECAllocateBuffer(cbDest, (LPVOID*)lppszTString);
  1325. if (hr != hrSuccess)
  1326. return hr;
  1327. memset(*lppszTString, 0, cbDest);
  1328. memcpy(*lppszTString, strDest.c_str(), strDest.length());
  1329. return hrSuccess;
  1330. }
  1331. static HRESULT TStringToUtf8(const TCHAR *lpszTstring, ULONG ulFlags,
  1332. void *lpBase, convert_context *lpConverter, char **lppszUtf8)
  1333. {
  1334. HRESULT hr;
  1335. std::string strDest;
  1336. size_t cbDest;
  1337. if (lpszTstring == NULL || lppszUtf8 == NULL)
  1338. return MAPI_E_INVALID_PARAMETER;
  1339. if (ulFlags & MAPI_UNICODE)
  1340. strDest = CONVERT_TO(lpConverter, std::string, "UTF-8", (wchar_t*)lpszTstring, rawsize((wchar_t*)lpszTstring), CHARSET_WCHAR);
  1341. else
  1342. strDest = CONVERT_TO(lpConverter, std::string, "UTF-8", (char*)lpszTstring, rawsize((char*)lpszTstring), CHARSET_CHAR);
  1343. cbDest = strDest.length() + 1;
  1344. if (lpBase)
  1345. hr = ECAllocateMore(cbDest, lpBase, (LPVOID*)lppszUtf8);
  1346. else
  1347. hr = ECAllocateBuffer(cbDest, (LPVOID*)lppszUtf8);
  1348. if (hr != hrSuccess)
  1349. return hr;
  1350. memcpy(*lppszUtf8, strDest.c_str(), cbDest);
  1351. return hrSuccess;
  1352. }
  1353. HRESULT CopyABPropsFromSoap(const struct propmapPairArray *lpsoapPropmap,
  1354. const struct propmapMVPairArray *lpsoapMVPropmap, SPROPMAP *lpPropmap,
  1355. MVPROPMAP *lpMVPropmap, void *lpBase, ULONG ulFlags)
  1356. {
  1357. HRESULT hr;
  1358. unsigned int nLen = 0;
  1359. convert_context converter;
  1360. ULONG ulConvFlags;
  1361. if (lpsoapPropmap != NULL) {
  1362. lpPropmap->cEntries = lpsoapPropmap->__size;
  1363. nLen = sizeof(*lpPropmap->lpEntries) * lpPropmap->cEntries;
  1364. hr = ECAllocateMore(nLen, lpBase, (void**)&lpPropmap->lpEntries);
  1365. if (hr != hrSuccess)
  1366. return hr;
  1367. for (gsoap_size_t i = 0; i < lpsoapPropmap->__size; ++i) {
  1368. if (PROP_TYPE(lpsoapPropmap->__ptr[i].ulPropId) != PT_BINARY) {
  1369. lpPropmap->lpEntries[i].ulPropId = CHANGE_PROP_TYPE(lpsoapPropmap->__ptr[i].ulPropId, ((ulFlags & MAPI_UNICODE) ? PT_UNICODE : PT_STRING8));
  1370. ulConvFlags = ulFlags;
  1371. } else {
  1372. lpPropmap->lpEntries[i].ulPropId = lpsoapPropmap->__ptr[i].ulPropId;
  1373. ulConvFlags = 0;
  1374. }
  1375. hr = Utf8ToTString(lpsoapPropmap->__ptr[i].lpszValue, ulConvFlags, lpBase, &converter, &lpPropmap->lpEntries[i].lpszValue);
  1376. if (hr != hrSuccess)
  1377. return hr;
  1378. }
  1379. }
  1380. if (lpsoapMVPropmap != NULL) {
  1381. lpMVPropmap->cEntries = lpsoapMVPropmap->__size;
  1382. hr = ECAllocateMore(sizeof(*lpMVPropmap->lpEntries) * lpMVPropmap->cEntries, lpBase, (void**)&lpMVPropmap->lpEntries);
  1383. if (hr != hrSuccess)
  1384. return hr;
  1385. for (gsoap_size_t i = 0; i < lpsoapMVPropmap->__size; ++i) {
  1386. if (PROP_TYPE(lpsoapMVPropmap->__ptr[i].ulPropId) != PT_MV_BINARY) {
  1387. lpMVPropmap->lpEntries[i].ulPropId = CHANGE_PROP_TYPE(lpsoapMVPropmap->__ptr[i].ulPropId, ((ulFlags & MAPI_UNICODE) ? PT_MV_UNICODE : PT_MV_STRING8));
  1388. ulConvFlags = ulFlags;
  1389. } else {
  1390. lpMVPropmap->lpEntries[i].ulPropId = lpsoapMVPropmap->__ptr[i].ulPropId;
  1391. ulConvFlags = 0;
  1392. }
  1393. lpMVPropmap->lpEntries[i].cValues = lpsoapMVPropmap->__ptr[i].sValues.__size;
  1394. nLen = sizeof(*lpMVPropmap->lpEntries[i].lpszValues) * lpMVPropmap->lpEntries[i].cValues;
  1395. hr = ECAllocateMore(nLen, lpBase, (void**)&lpMVPropmap->lpEntries[i].lpszValues);
  1396. if (hr != hrSuccess)
  1397. return hr;
  1398. for (gsoap_size_t j = 0; j < lpsoapMVPropmap->__ptr[i].sValues.__size; ++j) {
  1399. hr = Utf8ToTString(lpsoapMVPropmap->__ptr[i].sValues.__ptr[j], ulConvFlags, lpBase, &converter, &lpMVPropmap->lpEntries[i].lpszValues[j]);
  1400. if (hr != hrSuccess)
  1401. return hr;
  1402. }
  1403. }
  1404. }
  1405. return hrSuccess;
  1406. }
  1407. HRESULT CopyABPropsToSoap(const SPROPMAP *lpPropmap,
  1408. const MVPROPMAP *lpMVPropmap, ULONG ulFlags,
  1409. struct propmapPairArray **lppsoapPropmap,
  1410. struct propmapMVPairArray **lppsoapMVPropmap)
  1411. {
  1412. HRESULT hr = hrSuccess;
  1413. ecmem_ptr<struct propmapPairArray> soapPropmap;
  1414. ecmem_ptr<struct propmapMVPairArray> soapMVPropmap;
  1415. convert_context converter;
  1416. ULONG ulConvFlags;
  1417. if (lpPropmap && lpPropmap->cEntries) {
  1418. hr = ECAllocateBuffer(sizeof *soapPropmap, &~soapPropmap);
  1419. if (hr != hrSuccess)
  1420. return hr;
  1421. soapPropmap->__size = lpPropmap->cEntries;
  1422. hr = ECAllocateMore(soapPropmap->__size * sizeof *soapPropmap->__ptr, soapPropmap, (void**)&soapPropmap->__ptr);
  1423. if (hr != hrSuccess)
  1424. return hr;
  1425. for (gsoap_size_t i = 0; i < soapPropmap->__size; ++i) {
  1426. if (PROP_TYPE(lpPropmap->lpEntries[i].ulPropId) != PT_BINARY) {
  1427. soapPropmap->__ptr[i].ulPropId = CHANGE_PROP_TYPE(lpPropmap->lpEntries[i].ulPropId, PT_STRING8);
  1428. ulConvFlags = ulFlags;
  1429. } else {
  1430. soapPropmap->__ptr[i].ulPropId = lpPropmap->lpEntries[i].ulPropId;
  1431. ulConvFlags = 0;
  1432. }
  1433. hr = TStringToUtf8(lpPropmap->lpEntries[i].lpszValue, ulConvFlags, soapPropmap, &converter, &soapPropmap->__ptr[i].lpszValue);
  1434. if (hr != hrSuccess)
  1435. return hr;
  1436. }
  1437. }
  1438. if (lpMVPropmap && lpMVPropmap->cEntries) {
  1439. hr = ECAllocateBuffer(sizeof *soapMVPropmap, &~soapMVPropmap);
  1440. if (hr != hrSuccess)
  1441. return hr;
  1442. soapMVPropmap->__size = lpMVPropmap->cEntries;
  1443. hr = ECAllocateMore(soapMVPropmap->__size * sizeof *soapMVPropmap->__ptr, soapMVPropmap, (void**)&soapMVPropmap->__ptr);
  1444. if (hr != hrSuccess)
  1445. return hr;
  1446. for (gsoap_size_t i = 0; i < soapMVPropmap->__size; ++i) {
  1447. if (PROP_TYPE(lpMVPropmap->lpEntries[i].ulPropId) != PT_MV_BINARY) {
  1448. soapMVPropmap->__ptr[i].ulPropId = CHANGE_PROP_TYPE(lpMVPropmap->lpEntries[i].ulPropId, PT_MV_STRING8);
  1449. ulConvFlags = ulFlags;
  1450. } else {
  1451. soapMVPropmap->__ptr[i].ulPropId = lpMVPropmap->lpEntries[i].ulPropId;
  1452. ulConvFlags = 0;
  1453. }
  1454. soapMVPropmap->__ptr[i].sValues.__size = lpMVPropmap->lpEntries[i].cValues;
  1455. hr = ECAllocateMore(soapMVPropmap->__ptr[i].sValues.__size * sizeof * soapMVPropmap->__ptr[i].sValues.__ptr, soapMVPropmap, (void**)&soapMVPropmap->__ptr[i].sValues.__ptr);
  1456. if (hr != hrSuccess)
  1457. return hr;
  1458. for (gsoap_size_t j = 0; j < soapMVPropmap->__ptr[i].sValues.__size; ++j) {
  1459. hr = TStringToUtf8(lpMVPropmap->lpEntries[i].lpszValues[j], ulConvFlags, soapMVPropmap, &converter, &soapMVPropmap->__ptr[i].sValues.__ptr[j]);
  1460. if (hr != hrSuccess)
  1461. return hr;
  1462. }
  1463. }
  1464. }
  1465. if (lppsoapPropmap != nullptr)
  1466. *lppsoapPropmap = soapPropmap.release();
  1467. if (lppsoapMVPropmap != nullptr)
  1468. *lppsoapMVPropmap = soapMVPropmap.release();
  1469. return hrSuccess;
  1470. }
  1471. HRESULT FreeABProps(struct propmapPairArray *lpsoapPropmap, struct propmapMVPairArray *lpsoapMVPropmap)
  1472. {
  1473. if (lpsoapPropmap)
  1474. ECFreeBuffer(lpsoapPropmap);
  1475. if (lpsoapMVPropmap)
  1476. ECFreeBuffer(lpsoapMVPropmap);
  1477. return hrSuccess;
  1478. }
  1479. static HRESULT SoapUserToUser(const struct user *lpUser, ECUSER *lpsUser,
  1480. ULONG ulFlags, void *lpBase, convert_context &converter)
  1481. {
  1482. HRESULT hr;
  1483. if (lpUser == NULL || lpsUser == NULL)
  1484. return MAPI_E_INVALID_PARAMETER;
  1485. if (lpBase == NULL)
  1486. lpBase = lpsUser;
  1487. memset(lpsUser, 0, sizeof(*lpsUser));
  1488. hr = Utf8ToTString(lpUser->lpszUsername, ulFlags, lpBase, &converter, &lpsUser->lpszUsername);
  1489. if (hr == hrSuccess && lpUser->lpszFullName != NULL)
  1490. hr = Utf8ToTString(lpUser->lpszFullName, ulFlags, lpBase, &converter, &lpsUser->lpszFullName);
  1491. if (hr == hrSuccess && lpUser->lpszMailAddress != NULL)
  1492. hr = Utf8ToTString(lpUser->lpszMailAddress, ulFlags, lpBase, &converter, &lpsUser->lpszMailAddress);
  1493. if (hr == hrSuccess && lpUser->lpszServername != NULL)
  1494. hr = Utf8ToTString(lpUser->lpszServername, ulFlags, lpBase, &converter, &lpsUser->lpszServername);
  1495. if (hr != hrSuccess)
  1496. return hr;
  1497. hr = CopyABPropsFromSoap(lpUser->lpsPropmap, lpUser->lpsMVPropmap,
  1498. &lpsUser->sPropmap, &lpsUser->sMVPropmap, lpBase, ulFlags);
  1499. if (hr != hrSuccess)
  1500. return hr;
  1501. hr = CopySOAPEntryIdToMAPIEntryId(&lpUser->sUserId, lpUser->ulUserId, (ULONG*)&lpsUser->sUserId.cb, (LPENTRYID*)&lpsUser->sUserId.lpb, lpBase);
  1502. if (hr != hrSuccess)
  1503. return hr;
  1504. lpsUser->ulIsAdmin = lpUser->ulIsAdmin;
  1505. lpsUser->ulIsABHidden = lpUser->ulIsABHidden;
  1506. lpsUser->ulCapacity = lpUser->ulCapacity;
  1507. /**
  1508. * If we're talking to a pre 6.40 server we won't get a object class,
  1509. * only an is-non-active flag. Luckily we don't have to support that.
  1510. * However, a 6.40.0 server will put the object class information in
  1511. * that is-non-active field. We (6.40.1 and up) expect the object class
  1512. * information in a dedicated object class field, and reverted the
  1513. * is-non-active field to its original usage.
  1514. *
  1515. * We can easily determine what's the case here:
  1516. * If ulClass is missing (value == 0), we're dealing with a pre 6.40.1
  1517. * server. In that case the ulIsNonActive either contains is-non-active
  1518. * information or an object class. We can distinguish this since an
  1519. * object class has data in the high 16-bit of its value, the
  1520. * is-non-active field is either 0 or 1.
  1521. * If we detect a class, we put the class in the ulClass field.
  1522. * If we detect a is-non-active, we'll simply return an error since we're
  1523. * not required to be able to communicate with a pre 6.40.
  1524. * We could guess things here, but why bother?
  1525. */
  1526. if (lpUser->ulObjClass == 0) {
  1527. if (OBJECTCLASS_TYPE(lpUser->ulIsNonActive) != 0)
  1528. lpsUser->ulObjClass = (objectclass_t)lpUser->ulIsNonActive; // ulIsNonActive itself will be ignored by the offline server.
  1529. else
  1530. return MAPI_E_UNABLE_TO_COMPLETE;
  1531. } else
  1532. lpsUser->ulObjClass = (objectclass_t)lpUser->ulObjClass;
  1533. return hrSuccess;
  1534. }
  1535. HRESULT SoapUserArrayToUserArray(const struct userArray *lpUserArray,
  1536. ULONG ulFlags, ULONG *lpcUsers, ECUSER **lppsUsers)
  1537. {
  1538. HRESULT hr;
  1539. ECUSER *lpECUsers = NULL;
  1540. convert_context converter;
  1541. if (lpUserArray == NULL || lpcUsers == NULL || lppsUsers == NULL)
  1542. return MAPI_E_INVALID_PARAMETER;
  1543. hr = ECAllocateBuffer(sizeof(ECUSER) * lpUserArray->__size, reinterpret_cast<void **>(&lpECUsers));
  1544. if (hr != hrSuccess)
  1545. return hr;
  1546. memset(lpECUsers, 0, sizeof(ECUSER) * lpUserArray->__size);
  1547. for (gsoap_size_t i = 0; i < lpUserArray->__size; ++i) {
  1548. hr = SoapUserToUser(lpUserArray->__ptr + i, lpECUsers + i, ulFlags, lpECUsers, converter);
  1549. if (hr != hrSuccess)
  1550. return hr;
  1551. }
  1552. *lppsUsers = lpECUsers;
  1553. *lpcUsers = lpUserArray->__size;
  1554. return hrSuccess;
  1555. }
  1556. HRESULT SoapUserToUser(const struct user *lpUser, ULONG ulFlags,
  1557. ECUSER **lppsUser)
  1558. {
  1559. HRESULT hr = hrSuccess;
  1560. ecmem_ptr<ECUSER> lpsUser;
  1561. convert_context converter;
  1562. if (lpUser == nullptr || lppsUser == nullptr)
  1563. return MAPI_E_INVALID_PARAMETER;
  1564. hr = ECAllocateBuffer(sizeof *lpsUser, &~lpsUser);
  1565. if (hr != hrSuccess)
  1566. return hr;
  1567. hr = SoapUserToUser(lpUser, lpsUser, ulFlags, NULL, converter);
  1568. if (hr != hrSuccess)
  1569. return hr;
  1570. *lppsUser = lpsUser.release();
  1571. return hrSuccess;
  1572. }
  1573. static HRESULT SoapGroupToGroup(const struct group *lpGroup,
  1574. ECGROUP *lpsGroup, ULONG ulFlags, void *lpBase, convert_context &converter)
  1575. {
  1576. HRESULT hr;
  1577. if (lpGroup == NULL || lpsGroup == NULL)
  1578. return MAPI_E_INVALID_PARAMETER;
  1579. if (lpBase == NULL)
  1580. lpBase = lpsGroup;
  1581. memset(lpsGroup, 0, sizeof(*lpsGroup));
  1582. if (lpGroup->lpszGroupname == NULL)
  1583. return MAPI_E_INVALID_OBJECT;
  1584. hr = Utf8ToTString(lpGroup->lpszGroupname, ulFlags, lpBase, &converter, &lpsGroup->lpszGroupname);
  1585. if (hr == hrSuccess && lpGroup->lpszFullname)
  1586. hr = Utf8ToTString(lpGroup->lpszFullname, ulFlags, lpBase, &converter, &lpsGroup->lpszFullname);
  1587. if (hr == hrSuccess && lpGroup->lpszFullEmail)
  1588. hr = Utf8ToTString(lpGroup->lpszFullEmail, ulFlags, lpBase, &converter, &lpsGroup->lpszFullEmail);
  1589. if (hr != hrSuccess)
  1590. return hr;
  1591. hr = CopyABPropsFromSoap(lpGroup->lpsPropmap, lpGroup->lpsMVPropmap,
  1592. &lpsGroup->sPropmap, &lpsGroup->sMVPropmap, lpBase, ulFlags);
  1593. if (hr != hrSuccess)
  1594. return hr;
  1595. hr = CopySOAPEntryIdToMAPIEntryId(&lpGroup->sGroupId, lpGroup->ulGroupId,
  1596. reinterpret_cast<ULONG *>(&lpsGroup->sGroupId.cb),
  1597. reinterpret_cast<ENTRYID **>(&lpsGroup->sGroupId.lpb), lpBase);
  1598. if (hr != hrSuccess)
  1599. return hr;
  1600. lpsGroup->ulIsABHidden = lpGroup->ulIsABHidden;
  1601. return hrSuccess;
  1602. }
  1603. HRESULT SoapGroupArrayToGroupArray(const struct groupArray *lpGroupArray,
  1604. ULONG ulFlags, ULONG *lpcGroups, ECGROUP **lppsGroups)
  1605. {
  1606. HRESULT hr = hrSuccess;
  1607. ecmem_ptr<ECGROUP> lpECGroups;
  1608. convert_context converter;
  1609. if (lpGroupArray == nullptr || lpcGroups == nullptr || lppsGroups == nullptr)
  1610. return MAPI_E_INVALID_PARAMETER;
  1611. hr = ECAllocateBuffer(sizeof(ECGROUP) * lpGroupArray->__size, &~lpECGroups);
  1612. if (hr != hrSuccess)
  1613. return hr;
  1614. memset(lpECGroups, 0, sizeof(ECGROUP) * lpGroupArray->__size);
  1615. for (gsoap_size_t i = 0; i < lpGroupArray->__size; ++i) {
  1616. hr = SoapGroupToGroup(lpGroupArray->__ptr + i, lpECGroups + i, ulFlags, lpECGroups, converter);
  1617. if (hr != hrSuccess)
  1618. return hr;
  1619. }
  1620. *lppsGroups = lpECGroups.release();
  1621. *lpcGroups = lpGroupArray->__size;
  1622. return hrSuccess;
  1623. }
  1624. HRESULT SoapGroupToGroup(const struct group *lpGroup, ULONG ulFlags,
  1625. ECGROUP **lppsGroup)
  1626. {
  1627. HRESULT hr = hrSuccess;
  1628. ecmem_ptr<ECGROUP> lpsGroup;
  1629. convert_context converter;
  1630. if (lpGroup == nullptr || lppsGroup == nullptr)
  1631. return MAPI_E_INVALID_PARAMETER;
  1632. hr = ECAllocateBuffer(sizeof *lpsGroup, &~lpsGroup);
  1633. if (hr != hrSuccess)
  1634. return hr;
  1635. hr = SoapGroupToGroup(lpGroup, lpsGroup, ulFlags, NULL, converter);
  1636. if (hr != hrSuccess)
  1637. return hr;
  1638. *lppsGroup = lpsGroup.release();
  1639. return hrSuccess;
  1640. }
  1641. static HRESULT SoapCompanyToCompany(const struct company *lpCompany,
  1642. ECCOMPANY *lpsCompany, ULONG ulFlags, void *lpBase,
  1643. convert_context &converter)
  1644. {
  1645. HRESULT hr;
  1646. if (lpCompany == NULL || lpsCompany == NULL)
  1647. return MAPI_E_INVALID_PARAMETER;
  1648. if (lpBase == NULL)
  1649. lpBase = lpsCompany;
  1650. memset(lpsCompany, 0, sizeof(*lpsCompany));
  1651. hr = Utf8ToTString(lpCompany->lpszCompanyname, ulFlags, lpBase, &converter, &lpsCompany->lpszCompanyname);
  1652. if (hr == hrSuccess && lpCompany->lpszServername != NULL)
  1653. hr = Utf8ToTString(lpCompany->lpszServername, ulFlags, lpBase, &converter, &lpsCompany->lpszServername);
  1654. if (hr != hrSuccess)
  1655. return hr;
  1656. hr = CopyABPropsFromSoap(lpCompany->lpsPropmap, lpCompany->lpsMVPropmap,
  1657. &lpsCompany->sPropmap, &lpsCompany->sMVPropmap, lpBase, ulFlags);
  1658. if (hr != hrSuccess)
  1659. return hr;
  1660. hr = CopySOAPEntryIdToMAPIEntryId(&lpCompany->sAdministrator, lpCompany->ulAdministrator, (ULONG*)&lpsCompany->sAdministrator.cb, (LPENTRYID*)&lpsCompany->sAdministrator.lpb, lpBase);
  1661. if (hr != hrSuccess)
  1662. return hr;
  1663. hr = CopySOAPEntryIdToMAPIEntryId(&lpCompany->sCompanyId, lpCompany->ulCompanyId, (ULONG*)&lpsCompany->sCompanyId.cb, (LPENTRYID*)&lpsCompany->sCompanyId.lpb, lpBase);
  1664. if (hr != hrSuccess)
  1665. return hr;
  1666. lpsCompany->ulIsABHidden = lpCompany->ulIsABHidden;
  1667. return hrSuccess;
  1668. }
  1669. HRESULT SoapCompanyArrayToCompanyArray(
  1670. const struct companyArray *lpCompanyArray, ULONG ulFlags,
  1671. ULONG *lpcCompanies, ECCOMPANY **lppsCompanies)
  1672. {
  1673. HRESULT hr = hrSuccess;
  1674. ecmem_ptr<ECCOMPANY> lpECCompanies;
  1675. convert_context converter;
  1676. if (lpCompanyArray == nullptr || lpcCompanies == nullptr ||
  1677. lppsCompanies == nullptr)
  1678. return MAPI_E_INVALID_PARAMETER;
  1679. hr = ECAllocateBuffer(sizeof(ECCOMPANY) * lpCompanyArray->__size, &~lpECCompanies);
  1680. if (hr != hrSuccess)
  1681. return hr;
  1682. memset(lpECCompanies, 0, sizeof(ECCOMPANY) * lpCompanyArray->__size);
  1683. for (gsoap_size_t i = 0; i < lpCompanyArray->__size; ++i) {
  1684. hr = SoapCompanyToCompany(&lpCompanyArray->__ptr[i], lpECCompanies + i, ulFlags, lpECCompanies, converter);
  1685. if (hr != hrSuccess)
  1686. return hr;
  1687. }
  1688. *lppsCompanies = lpECCompanies.release();
  1689. *lpcCompanies = lpCompanyArray->__size;
  1690. return hrSuccess;
  1691. }
  1692. HRESULT SoapCompanyToCompany(const struct company *lpCompany, ULONG ulFlags,
  1693. ECCOMPANY **lppsCompany)
  1694. {
  1695. HRESULT hr = hrSuccess;
  1696. ecmem_ptr<ECCOMPANY> lpsCompany;
  1697. convert_context converter;
  1698. if (lpCompany == nullptr || lppsCompany == nullptr)
  1699. return MAPI_E_INVALID_PARAMETER;
  1700. hr = ECAllocateBuffer(sizeof *lpsCompany, &~lpsCompany);
  1701. if (hr != hrSuccess)
  1702. return hr;
  1703. hr = SoapCompanyToCompany(lpCompany, lpsCompany, ulFlags, NULL, converter);
  1704. if (hr != hrSuccess)
  1705. return hr;
  1706. *lppsCompany = lpsCompany.release();
  1707. return hrSuccess;
  1708. }
  1709. HRESULT SvrNameListToSoapMvString8(ECSVRNAMELIST *lpSvrNameList,
  1710. ULONG ulFlags, struct mv_string8 **lppsSvrNameList)
  1711. {
  1712. HRESULT hr = hrSuccess;
  1713. ecmem_ptr<struct mv_string8> lpsSvrNameList;
  1714. convert_context converter;
  1715. if (lpSvrNameList == nullptr || lppsSvrNameList == nullptr)
  1716. return MAPI_E_INVALID_PARAMETER;
  1717. hr = ECAllocateBuffer(sizeof(*lpsSvrNameList), &~lpsSvrNameList);
  1718. if (hr != hrSuccess)
  1719. return hr;
  1720. memset(lpsSvrNameList, 0, sizeof *lpsSvrNameList);
  1721. if (lpSvrNameList->cServers > 0) {
  1722. lpsSvrNameList->__size = lpSvrNameList->cServers;
  1723. hr = ECAllocateMore(lpSvrNameList->cServers * sizeof *lpsSvrNameList->__ptr, lpsSvrNameList, (void**)&lpsSvrNameList->__ptr);
  1724. if (hr != hrSuccess)
  1725. return hr;
  1726. memset(lpsSvrNameList->__ptr, 0, lpSvrNameList->cServers * sizeof *lpsSvrNameList->__ptr);
  1727. for (unsigned i = 0; i < lpSvrNameList->cServers; ++i) {
  1728. hr = TStringToUtf8(lpSvrNameList->lpszaServer[i], ulFlags, lpSvrNameList, &converter, &lpsSvrNameList->__ptr[i]);
  1729. if (hr != hrSuccess)
  1730. return hr;
  1731. }
  1732. }
  1733. *lppsSvrNameList = lpsSvrNameList.release();
  1734. return hrSuccess;
  1735. }
  1736. HRESULT SoapServerListToServerList(const struct serverList *lpsServerList,
  1737. ULONG ulFLags, ECSERVERLIST **lppServerList)
  1738. {
  1739. HRESULT hr = hrSuccess;
  1740. ecmem_ptr<ECSERVERLIST> lpServerList;
  1741. convert_context converter;
  1742. if (lpsServerList == nullptr || lppServerList == nullptr)
  1743. return MAPI_E_INVALID_PARAMETER;
  1744. hr = ECAllocateBuffer(sizeof(*lpServerList), &~lpServerList);
  1745. if (hr != hrSuccess)
  1746. return hr;
  1747. memset(lpServerList, 0, sizeof *lpServerList);
  1748. if (lpsServerList->__size > 0 && lpsServerList->__ptr != NULL) {
  1749. lpServerList->cServers = lpsServerList->__size;
  1750. hr = ECAllocateMore(lpsServerList->__size * sizeof *lpServerList->lpsaServer, lpServerList, (void**)&lpServerList->lpsaServer);
  1751. if (hr != hrSuccess)
  1752. return hr;
  1753. memset(lpServerList->lpsaServer, 0, lpsServerList->__size * sizeof *lpServerList->lpsaServer);
  1754. for (gsoap_size_t i = 0; i < lpsServerList->__size; ++i) {
  1755. // Flags
  1756. lpServerList->lpsaServer[i].ulFlags = lpsServerList->__ptr[i].ulFlags;
  1757. // Name
  1758. if (lpsServerList->__ptr[i].lpszName != NULL) {
  1759. hr = Utf8ToTString(lpsServerList->__ptr[i].lpszName, ulFLags, lpServerList, &converter, &lpServerList->lpsaServer[i].lpszName);
  1760. if (hr != hrSuccess)
  1761. return hr;
  1762. }
  1763. // FilePath
  1764. if (lpsServerList->__ptr[i].lpszFilePath != NULL) {
  1765. hr = Utf8ToTString(lpsServerList->__ptr[i].lpszFilePath, ulFLags, lpServerList, &converter, &lpServerList->lpsaServer[i].lpszFilePath);
  1766. if (hr != hrSuccess)
  1767. return hr;
  1768. }
  1769. // HttpPath
  1770. if (lpsServerList->__ptr[i].lpszHttpPath != NULL) {
  1771. hr = Utf8ToTString(lpsServerList->__ptr[i].lpszHttpPath, ulFLags, lpServerList, &converter, &lpServerList->lpsaServer[i].lpszHttpPath);
  1772. if (hr != hrSuccess)
  1773. return hr;
  1774. }
  1775. // SslPath
  1776. if (lpsServerList->__ptr[i].lpszSslPath != NULL) {
  1777. hr = Utf8ToTString(lpsServerList->__ptr[i].lpszSslPath, ulFLags, lpServerList, &converter, &lpServerList->lpsaServer[i].lpszSslPath);
  1778. if (hr != hrSuccess)
  1779. return hr;
  1780. }
  1781. // PreferedPath
  1782. if (lpsServerList->__ptr[i].lpszPreferedPath != NULL) {
  1783. hr = Utf8ToTString(lpsServerList->__ptr[i].lpszPreferedPath, ulFLags, lpServerList, &converter, &lpServerList->lpsaServer[i].lpszPreferedPath);
  1784. if (hr != hrSuccess)
  1785. return hr;
  1786. }
  1787. }
  1788. }
  1789. *lppServerList = lpServerList.release();
  1790. return hrSuccess;
  1791. }
  1792. HRESULT CreateSoapTransport(ULONG ulUIFlags, const sGlobalProfileProps
  1793. &sProfileProps, KCmd **const lppCmd)
  1794. {
  1795. return CreateSoapTransport(ulUIFlags,
  1796. sProfileProps.strServerPath.c_str(),
  1797. sProfileProps.strSSLKeyFile.c_str(),
  1798. sProfileProps.strSSLKeyPass.c_str(),
  1799. sProfileProps.ulConnectionTimeOut,
  1800. sProfileProps.strProxyHost.c_str(),
  1801. sProfileProps.ulProxyPort,
  1802. sProfileProps.strProxyUserName.c_str(),
  1803. sProfileProps.strProxyPassword.c_str(),
  1804. sProfileProps.ulProxyFlags,
  1805. SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING,
  1806. SOAP_IO_KEEPALIVE | SOAP_XML_TREE | SOAP_C_UTFSTRING,
  1807. lppCmd);
  1808. }
  1809. // Wrap the server store entryid to client store entry. (Add a servername)
  1810. HRESULT WrapServerClientStoreEntry(const char* lpszServerName, entryId* lpsStoreId, ULONG* lpcbStoreID, LPENTRYID* lppStoreID)
  1811. {
  1812. HRESULT hr;
  1813. LPENTRYID lpStoreID = NULL;
  1814. ULONG ulSize;
  1815. if (lpsStoreId == NULL || lpszServerName == NULL)
  1816. return MAPI_E_INVALID_PARAMETER;
  1817. // The new entryid size is, current size + servername size + 1 byte term 0 - 4 bytes padding
  1818. ulSize = lpsStoreId->__size+strlen(lpszServerName)+1-4;
  1819. hr = ECAllocateBuffer(ulSize, (void**)&lpStoreID);
  1820. if(hr != hrSuccess)
  1821. return hr;
  1822. memset(lpStoreID, 0, ulSize );
  1823. //Copy the entryid without servername
  1824. memcpy(lpStoreID, lpsStoreId->__ptr, lpsStoreId->__size);
  1825. // Add the server name
  1826. strcpy((char*)lpStoreID+(lpsStoreId->__size-4), lpszServerName);
  1827. *lpcbStoreID = ulSize;
  1828. *lppStoreID = lpStoreID;
  1829. return hrSuccess;
  1830. }
  1831. // Un wrap the client store entryid to server store entry. (remove a servername)
  1832. HRESULT UnWrapServerClientStoreEntry(ULONG cbWrapStoreID, LPENTRYID lpWrapStoreID, ULONG* lpcbUnWrapStoreID, LPENTRYID* lppUnWrapStoreID)
  1833. {
  1834. HRESULT hr;
  1835. LPENTRYID lpUnWrapStoreID = NULL;
  1836. PEID peid = NULL;
  1837. ULONG ulSize = 0;
  1838. if (lpWrapStoreID == NULL || lppUnWrapStoreID == NULL)
  1839. return MAPI_E_INVALID_PARAMETER;
  1840. peid = (PEID)lpWrapStoreID;
  1841. if (peid->ulVersion == 0)
  1842. ulSize = sizeof(EID_V0);
  1843. else if (peid->ulVersion == 1)
  1844. ulSize = sizeof(EID);
  1845. else
  1846. return MAPI_E_INVALID_ENTRYID;
  1847. if (cbWrapStoreID < ulSize)
  1848. return MAPI_E_INVALID_ENTRYID;
  1849. hr = ECAllocateBuffer(ulSize, (void**)&lpUnWrapStoreID);
  1850. if(hr != hrSuccess)
  1851. return hr;
  1852. memset(lpUnWrapStoreID, 0, ulSize);
  1853. // Remove servername
  1854. memcpy(lpUnWrapStoreID, lpWrapStoreID, ulSize-4);
  1855. *lppUnWrapStoreID = lpUnWrapStoreID;
  1856. *lpcbUnWrapStoreID = ulSize;
  1857. return hrSuccess;
  1858. }
  1859. HRESULT UnWrapServerClientABEntry(ULONG cbWrapABID, LPENTRYID lpWrapABID, ULONG* lpcbUnWrapABID, LPENTRYID* lppUnWrapABID)
  1860. {
  1861. HRESULT hr;
  1862. LPENTRYID lpUnWrapABID = NULL;
  1863. ULONG ulSize = 0;
  1864. if (lpWrapABID == NULL || lppUnWrapABID == NULL)
  1865. return MAPI_E_INVALID_PARAMETER;
  1866. // Check minimum size of EntryID
  1867. if (cbWrapABID < sizeof(ABEID))
  1868. return MAPI_E_INVALID_ENTRYID;
  1869. // FIXME: Check whether it is a Zarafa entry?
  1870. auto pabeid = reinterpret_cast<const ABEID *>(lpWrapABID);
  1871. if (pabeid->ulVersion == 0)
  1872. ulSize = sizeof(ABEID);
  1873. else if (pabeid->ulVersion == 1)
  1874. ulSize = CbABEID(pabeid);
  1875. else
  1876. return MAPI_E_INVALID_ENTRYID;
  1877. if (cbWrapABID < ulSize)
  1878. return MAPI_E_INVALID_ENTRYID;
  1879. hr = ECAllocateBuffer(ulSize, reinterpret_cast<void **>(&lpUnWrapABID));
  1880. if(hr != hrSuccess)
  1881. return hr;
  1882. memset(lpUnWrapABID, 0, ulSize);
  1883. // Remove servername
  1884. memcpy(lpUnWrapABID, lpWrapABID, ulSize-4);
  1885. *lppUnWrapABID = lpUnWrapABID;
  1886. *lpcbUnWrapABID = ulSize;
  1887. return hrSuccess;
  1888. }
  1889. HRESULT CopySOAPNotificationToMAPINotification(void *lpProvider, struct notification *lpSrc, LPNOTIFICATION *lppDst, convert_context *lpConverter) {
  1890. HRESULT hr = hrSuccess;
  1891. ecmem_ptr<NOTIFICATION> lpNotification;
  1892. int nLen;
  1893. hr = ECAllocateBuffer(sizeof(NOTIFICATION), &~lpNotification);
  1894. if (hr != hrSuccess)
  1895. return hr;
  1896. memset(lpNotification, 0, sizeof(NOTIFICATION));
  1897. lpNotification->ulEventType = lpSrc->ulEventType;
  1898. switch(lpSrc->ulEventType){
  1899. case fnevCriticalError:// ERROR_NOTIFICATION
  1900. hr = MAPI_E_INVALID_PARAMETER;
  1901. break;
  1902. case fnevNewMail://NEWMAIL_NOTIFICATION
  1903. if (lpSrc->newmail->pEntryId != nullptr)
  1904. // Ignore error now
  1905. // FIXME: This must exist, so maybe give an error or skip them
  1906. CopySOAPEntryIdToMAPIEntryId(lpSrc->newmail->pEntryId, &lpNotification->info.newmail.cbEntryID, &lpNotification->info.newmail.lpEntryID, lpNotification);
  1907. if (lpSrc->newmail->pParentId != nullptr)
  1908. // Ignore error
  1909. CopySOAPEntryIdToMAPIEntryId(lpSrc->newmail->pParentId, &lpNotification->info.newmail.cbParentID, &lpNotification->info.newmail.lpParentID, lpNotification);
  1910. if(lpSrc->newmail->lpszMessageClass != NULL) {
  1911. nLen = strlen(lpSrc->newmail->lpszMessageClass)+1;
  1912. hr = ECAllocateMore(nLen, lpNotification, reinterpret_cast<void **>(&lpNotification->info.newmail.lpszMessageClass));
  1913. if (hr != hrSuccess)
  1914. break;
  1915. memcpy(lpNotification->info.newmail.lpszMessageClass, lpSrc->newmail->lpszMessageClass, nLen);
  1916. }
  1917. lpNotification->info.newmail.ulFlags = 0;
  1918. lpNotification->info.newmail.ulMessageFlags = lpSrc->newmail->ulMessageFlags;
  1919. break;
  1920. case fnevObjectCreated:// OBJECT_NOTIFICATION
  1921. case fnevObjectDeleted:
  1922. case fnevObjectModified:
  1923. case fnevObjectCopied:
  1924. case fnevObjectMoved:
  1925. case fnevSearchComplete:
  1926. // FIXME for each if statement below, check the ELSE .. we can't send a TABLE_ROW_ADDED without lpProps for example ..
  1927. lpNotification->info.obj.ulObjType = lpSrc->obj->ulObjType;
  1928. // All errors of CopySOAPEntryIdToMAPIEntryId are ignored
  1929. if (lpSrc->obj->pEntryId != NULL)
  1930. CopySOAPEntryIdToMAPIEntryId(lpSrc->obj->pEntryId, &lpNotification->info.obj.cbEntryID, &lpNotification->info.obj.lpEntryID, lpNotification);
  1931. if (lpSrc->obj->pParentId != NULL)
  1932. CopySOAPEntryIdToMAPIEntryId(lpSrc->obj->pParentId, &lpNotification->info.obj.cbParentID, &lpNotification->info.obj.lpParentID, lpNotification);
  1933. if (lpSrc->obj->pOldId != NULL)
  1934. CopySOAPEntryIdToMAPIEntryId(lpSrc->obj->pOldId, &lpNotification->info.obj.cbOldID, &lpNotification->info.obj.lpOldID, lpNotification);
  1935. if (lpSrc->obj->pOldParentId != NULL)
  1936. CopySOAPEntryIdToMAPIEntryId(lpSrc->obj->pOldParentId, &lpNotification->info.obj.cbOldParentID, &lpNotification->info.obj.lpOldParentID, lpNotification);
  1937. if (lpSrc->obj->pPropTagArray != nullptr)
  1938. // ignore errors
  1939. CopySOAPPropTagArrayToMAPIPropTagArray(lpSrc->obj->pPropTagArray, &lpNotification->info.obj.lpPropTagArray, lpNotification);
  1940. break;
  1941. case fnevTableModified:// TABLE_NOTIFICATION
  1942. lpNotification->info.tab.ulTableEvent = lpSrc->tab->ulTableEvent;
  1943. lpNotification->info.tab.propIndex.ulPropTag = lpSrc->tab->propIndex.ulPropTag;
  1944. if (lpSrc->tab->propIndex.Value.bin){
  1945. lpNotification->info.tab.propIndex.Value.bin.cb = lpSrc->tab->propIndex.Value.bin->__size;
  1946. hr = ECAllocateMore(lpNotification->info.tab.propIndex.Value.bin.cb, lpNotification,
  1947. reinterpret_cast<void **>(&lpNotification->info.tab.propIndex.Value.bin.lpb));
  1948. if (hr != hrSuccess)
  1949. break;
  1950. memcpy(lpNotification->info.tab.propIndex.Value.bin.lpb, lpSrc->tab->propIndex.Value.bin->__ptr, lpSrc->tab->propIndex.Value.bin->__size);
  1951. }
  1952. lpNotification->info.tab.propPrior.ulPropTag = lpSrc->tab->propPrior.ulPropTag;
  1953. if (lpSrc->tab->propPrior.Value.bin){
  1954. lpNotification->info.tab.propPrior.Value.bin.cb = lpSrc->tab->propPrior.Value.bin->__size;
  1955. hr = ECAllocateMore(lpNotification->info.tab.propPrior.Value.bin.cb, lpNotification,
  1956. reinterpret_cast<void **>(&lpNotification->info.tab.propPrior.Value.bin.lpb));
  1957. if (hr != hrSuccess)
  1958. break;
  1959. memcpy(lpNotification->info.tab.propPrior.Value.bin.lpb, lpSrc->tab->propPrior.Value.bin->__ptr, lpSrc->tab->propPrior.Value.bin->__size);
  1960. }
  1961. if(lpSrc->tab->pRow)
  1962. {
  1963. lpNotification->info.tab.row.cValues = lpSrc->tab->pRow->__size;
  1964. hr = ECAllocateMore(sizeof(SPropValue)*lpNotification->info.tab.row.cValues, lpNotification,
  1965. reinterpret_cast<void **>(&lpNotification->info.tab.row.lpProps));
  1966. if (hr != hrSuccess)
  1967. break;
  1968. CopySOAPRowToMAPIRow(lpProvider, lpSrc->tab->pRow,
  1969. lpNotification->info.tab.row.lpProps,
  1970. reinterpret_cast<void **>(lpNotification.get()),
  1971. lpSrc->tab->ulObjType, lpConverter);
  1972. }
  1973. break;
  1974. case fnevStatusObjectModified: // STATUS_OBJECT_NOTIFICATION
  1975. hr = MAPI_E_INVALID_PARAMETER;
  1976. break;
  1977. case fnevExtended: // EXTENDED_NOTIFICATION
  1978. hr = MAPI_E_INVALID_PARAMETER;
  1979. break;
  1980. default:
  1981. hr = MAPI_E_INVALID_PARAMETER;
  1982. break;
  1983. }
  1984. if(hr != hrSuccess)
  1985. return hr;
  1986. *lppDst = lpNotification.release();
  1987. return hrSuccess;
  1988. }
  1989. HRESULT CopySOAPChangeNotificationToSyncState(struct notification *lpSrc, LPSBinary *lppDst, void *lpBase)
  1990. {
  1991. HRESULT hr = hrSuccess;
  1992. LPSBinary lpSBinary = NULL;
  1993. if (lpSrc->ulEventType != fnevKopanoIcsChange) {
  1994. hr = MAPI_E_INVALID_PARAMETER;
  1995. goto exit;
  1996. }
  1997. if (lpBase == NULL)
  1998. hr = ECAllocateBuffer(sizeof(*lpSBinary), reinterpret_cast<void **>(&lpSBinary));
  1999. else
  2000. hr = ECAllocateMore(sizeof(*lpSBinary), lpBase, reinterpret_cast<void **>(&lpSBinary));
  2001. if (hr != hrSuccess)
  2002. return hr;
  2003. memset(lpSBinary, 0, sizeof *lpSBinary);
  2004. lpSBinary->cb = lpSrc->ics->pSyncState->__size;
  2005. if (lpBase == NULL)
  2006. hr = ECAllocateMore(lpSBinary->cb, lpSBinary, reinterpret_cast<void **>(&lpSBinary->lpb));
  2007. else
  2008. hr = ECAllocateMore(lpSBinary->cb, lpBase, reinterpret_cast<void **>(&lpSBinary->lpb));
  2009. if (hr != hrSuccess)
  2010. goto exit;
  2011. memcpy(lpSBinary->lpb, lpSrc->ics->pSyncState->__ptr, lpSBinary->cb);
  2012. *lppDst = lpSBinary;
  2013. lpSBinary = NULL;
  2014. exit:
  2015. MAPIFreeBuffer(lpSBinary);
  2016. return hr;
  2017. }
  2018. static HRESULT CopyMAPISourceKeyToSoapSourceKey(const SBinary *lpsMAPISourceKey,
  2019. struct xsd__base64Binary *lpsSoapSourceKey, void *lpBase)
  2020. {
  2021. HRESULT hr;
  2022. struct xsd__base64Binary sSoapSourceKey = {0};
  2023. if (lpsMAPISourceKey == NULL || lpsSoapSourceKey == NULL)
  2024. return MAPI_E_INVALID_PARAMETER;
  2025. sSoapSourceKey.__size = (int)lpsMAPISourceKey->cb;
  2026. if (lpBase)
  2027. hr = MAPIAllocateMore(lpsMAPISourceKey->cb, lpBase, (void**)&sSoapSourceKey.__ptr);
  2028. else
  2029. hr = MAPIAllocateBuffer(lpsMAPISourceKey->cb, (void**)&sSoapSourceKey.__ptr);
  2030. if (hr != hrSuccess)
  2031. return hr;
  2032. memcpy(sSoapSourceKey.__ptr, lpsMAPISourceKey->lpb, lpsMAPISourceKey->cb);
  2033. *lpsSoapSourceKey = sSoapSourceKey;
  2034. return hrSuccess;
  2035. }
  2036. HRESULT CopyICSChangeToSOAPSourceKeys(ULONG cbChanges,
  2037. const ICSCHANGE *lpsChanges, sourceKeyPairArray **lppsSKPA)
  2038. {
  2039. HRESULT hr = hrSuccess;
  2040. memory_ptr<sourceKeyPairArray> lpsSKPA;
  2041. if (lpsChanges == nullptr || lppsSKPA == nullptr)
  2042. return MAPI_E_INVALID_PARAMETER;
  2043. hr = MAPIAllocateBuffer(sizeof *lpsSKPA, &~lpsSKPA);
  2044. if (hr != hrSuccess)
  2045. return hr;
  2046. memset(lpsSKPA, 0, sizeof *lpsSKPA);
  2047. if (cbChanges > 0) {
  2048. lpsSKPA->__size = cbChanges;
  2049. hr = MAPIAllocateMore(cbChanges * sizeof *lpsSKPA->__ptr, lpsSKPA, (void**)&lpsSKPA->__ptr);
  2050. if (hr != hrSuccess)
  2051. return hr;
  2052. memset(lpsSKPA->__ptr, 0, cbChanges * sizeof *lpsSKPA->__ptr);
  2053. for (unsigned i = 0; i < cbChanges; ++i) {
  2054. hr = CopyMAPISourceKeyToSoapSourceKey(&lpsChanges[i].sSourceKey, &lpsSKPA->__ptr[i].sObjectKey, lpsSKPA);
  2055. if (hr != hrSuccess)
  2056. return hr;
  2057. hr = CopyMAPISourceKeyToSoapSourceKey(&lpsChanges[i].sParentSourceKey, &lpsSKPA->__ptr[i].sParentKey, lpsSKPA);
  2058. if (hr != hrSuccess)
  2059. return hr;
  2060. }
  2061. }
  2062. *lppsSKPA = lpsSKPA.release();
  2063. return hrSuccess;
  2064. }
  2065. HRESULT CopyUserClientUpdateStatusFromSOAP(struct userClientUpdateStatusResponse &sUCUS,
  2066. ULONG ulFlags, ECUSERCLIENTUPDATESTATUS **lppECUCUS)
  2067. {
  2068. HRESULT hr = hrSuccess;
  2069. memory_ptr<ECUSERCLIENTUPDATESTATUS> lpECUCUS;
  2070. convert_context converter;
  2071. hr = MAPIAllocateBuffer(sizeof(ECUSERCLIENTUPDATESTATUS), &~lpECUCUS);
  2072. if (hr != hrSuccess)
  2073. return hr;
  2074. memset(lpECUCUS, 0, sizeof(ECUSERCLIENTUPDATESTATUS));
  2075. lpECUCUS->ulTrackId = sUCUS.ulTrackId;
  2076. lpECUCUS->tUpdatetime = sUCUS.tUpdatetime;
  2077. lpECUCUS->ulStatus = sUCUS.ulStatus;
  2078. if (sUCUS.lpszCurrentversion)
  2079. hr = Utf8ToTString(sUCUS.lpszCurrentversion, ulFlags, lpECUCUS, &converter, &lpECUCUS->lpszCurrentversion);
  2080. if (hr == hrSuccess && sUCUS.lpszLatestversion)
  2081. hr = Utf8ToTString(sUCUS.lpszLatestversion, ulFlags, lpECUCUS, &converter, &lpECUCUS->lpszLatestversion);
  2082. if (hr == hrSuccess && sUCUS.lpszComputername)
  2083. hr = Utf8ToTString(sUCUS.lpszComputername, ulFlags, lpECUCUS, &converter, &lpECUCUS->lpszComputername);
  2084. if (hr != hrSuccess)
  2085. return hr;
  2086. *lppECUCUS = lpECUCUS.release();
  2087. return hrSuccess;
  2088. }
  2089. static HRESULT ConvertString8ToUnicode(const char *lpszA, WCHAR **lppszW,
  2090. void *base, convert_context &converter)
  2091. {
  2092. HRESULT hr;
  2093. wstring wide;
  2094. WCHAR *lpszW = NULL;
  2095. if (lpszA == NULL || lppszW == NULL)
  2096. return MAPI_E_INVALID_PARAMETER;
  2097. TryConvert(lpszA, wide);
  2098. hr = ECAllocateMore((wide.length() +1) * sizeof(wstring::value_type), base, (void**)&lpszW);
  2099. if (hr != hrSuccess)
  2100. return hr;
  2101. wcscpy(lpszW, wide.c_str());
  2102. *lppszW = lpszW;
  2103. return hrSuccess;
  2104. }
  2105. static HRESULT ConvertString8ToUnicode(LPSRestriction lpRestriction,
  2106. void *base, convert_context &converter)
  2107. {
  2108. HRESULT hr;
  2109. ULONG i;
  2110. if (lpRestriction == NULL)
  2111. return hrSuccess;
  2112. switch (lpRestriction->rt) {
  2113. case RES_OR:
  2114. for (i = 0; i < lpRestriction->res.resOr.cRes; ++i) {
  2115. hr = ConvertString8ToUnicode(&lpRestriction->res.resOr.lpRes[i], base, converter);
  2116. if (hr != hrSuccess)
  2117. return hr;
  2118. }
  2119. break;
  2120. case RES_AND:
  2121. for (i = 0; i < lpRestriction->res.resAnd.cRes; ++i) {
  2122. hr = ConvertString8ToUnicode(&lpRestriction->res.resAnd.lpRes[i], base, converter);
  2123. if (hr != hrSuccess)
  2124. return hr;
  2125. }
  2126. break;
  2127. case RES_NOT:
  2128. hr = ConvertString8ToUnicode(lpRestriction->res.resNot.lpRes, base, converter);
  2129. if (hr != hrSuccess)
  2130. return hr;
  2131. break;
  2132. case RES_COMMENT:
  2133. if (lpRestriction->res.resComment.lpRes) {
  2134. hr = ConvertString8ToUnicode(lpRestriction->res.resComment.lpRes, base, converter);
  2135. if (hr != hrSuccess)
  2136. return hr;
  2137. }
  2138. for (i = 0; i < lpRestriction->res.resComment.cValues; ++i) {
  2139. if (PROP_TYPE(lpRestriction->res.resComment.lpProp[i].ulPropTag) == PT_STRING8) {
  2140. hr = ConvertString8ToUnicode(lpRestriction->res.resComment.lpProp[i].Value.lpszA, &lpRestriction->res.resComment.lpProp[i].Value.lpszW, base, converter);
  2141. if (hr != hrSuccess)
  2142. return hr;
  2143. lpRestriction->res.resComment.lpProp[i].ulPropTag = CHANGE_PROP_TYPE(lpRestriction->res.resComment.lpProp[i].ulPropTag, PT_UNICODE);
  2144. }
  2145. }
  2146. break;
  2147. case RES_COMPAREPROPS:
  2148. break;
  2149. case RES_CONTENT:
  2150. if (PROP_TYPE(lpRestriction->res.resContent.ulPropTag) == PT_STRING8) {
  2151. hr = ConvertString8ToUnicode(lpRestriction->res.resContent.lpProp->Value.lpszA, &lpRestriction->res.resContent.lpProp->Value.lpszW, base, converter);
  2152. if (hr != hrSuccess)
  2153. return hr;
  2154. lpRestriction->res.resContent.lpProp->ulPropTag = CHANGE_PROP_TYPE(lpRestriction->res.resContent.lpProp->ulPropTag, PT_UNICODE);
  2155. lpRestriction->res.resContent.ulPropTag = CHANGE_PROP_TYPE(lpRestriction->res.resContent.ulPropTag, PT_UNICODE);
  2156. }
  2157. break;
  2158. case RES_PROPERTY:
  2159. if (PROP_TYPE(lpRestriction->res.resProperty.ulPropTag) == PT_STRING8) {
  2160. hr = ConvertString8ToUnicode(lpRestriction->res.resProperty.lpProp->Value.lpszA, &lpRestriction->res.resProperty.lpProp->Value.lpszW, base, converter);
  2161. if (hr != hrSuccess)
  2162. return hr;
  2163. lpRestriction->res.resProperty.lpProp->ulPropTag = CHANGE_PROP_TYPE(lpRestriction->res.resProperty.lpProp->ulPropTag, PT_UNICODE);
  2164. lpRestriction->res.resProperty.ulPropTag = CHANGE_PROP_TYPE(lpRestriction->res.resProperty.ulPropTag, PT_UNICODE);
  2165. }
  2166. break;
  2167. case RES_SUBRESTRICTION:
  2168. hr = ConvertString8ToUnicode(lpRestriction->res.resSub.lpRes, base, converter);
  2169. if (hr != hrSuccess)
  2170. return hr;
  2171. break;
  2172. };
  2173. return hrSuccess;
  2174. }
  2175. static HRESULT ConvertString8ToUnicode(const ADRLIST *lpAdrList, void *base,
  2176. convert_context &converter)
  2177. {
  2178. HRESULT hr;
  2179. if (lpAdrList == NULL)
  2180. return hrSuccess;
  2181. for (ULONG c = 0; c < lpAdrList->cEntries; ++c) {
  2182. // treat as row
  2183. hr = ConvertString8ToUnicode((LPSRow)&lpAdrList->aEntries[c], base, converter);
  2184. if (hr != hrSuccess)
  2185. return hr;
  2186. }
  2187. return hrSuccess;
  2188. }
  2189. static HRESULT ConvertString8ToUnicode(const ACTIONS *lpActions, void *base,
  2190. convert_context &converter)
  2191. {
  2192. HRESULT hr;
  2193. if (lpActions == NULL)
  2194. return hrSuccess;
  2195. for (ULONG c = 0; c < lpActions->cActions; ++c) {
  2196. if (lpActions->lpAction[c].acttype == OP_FORWARD || lpActions->lpAction[c].acttype == OP_DELEGATE) {
  2197. hr = ConvertString8ToUnicode(lpActions->lpAction[c].lpadrlist, base, converter);
  2198. if (hr != hrSuccess)
  2199. return hr;
  2200. }
  2201. }
  2202. return hrSuccess;
  2203. }
  2204. HRESULT ConvertString8ToUnicode(LPSRow lpRow, void *base, convert_context &converter)
  2205. {
  2206. HRESULT hr = hrSuccess;
  2207. if (lpRow == NULL)
  2208. return hrSuccess;
  2209. for (ULONG c = 0; c < lpRow->cValues; ++c) {
  2210. if (PROP_TYPE(lpRow->lpProps[c].ulPropTag) == PT_SRESTRICTION) {
  2211. hr = ConvertString8ToUnicode((LPSRestriction)lpRow->lpProps[c].Value.lpszA, base ? base : lpRow->lpProps, converter);
  2212. } else if (PROP_TYPE(lpRow->lpProps[c].ulPropTag) == PT_ACTIONS) {
  2213. hr = ConvertString8ToUnicode((ACTIONS*)lpRow->lpProps[c].Value.lpszA, base ? base : lpRow->lpProps, converter);
  2214. } else if (base && PROP_TYPE(lpRow->lpProps[c].ulPropTag) == PT_STRING8) {
  2215. // only for "base" items: eg. the lpadrlist data, not the PR_RULE_NAME from the top-level
  2216. hr = ConvertString8ToUnicode(lpRow->lpProps[c].Value.lpszA, &lpRow->lpProps[c].Value.lpszW, base, converter);
  2217. if (hr != hrSuccess)
  2218. return hr;
  2219. lpRow->lpProps[c].ulPropTag = CHANGE_PROP_TYPE(lpRow->lpProps[c].ulPropTag, PT_UNICODE);
  2220. }
  2221. if (hr != hrSuccess)
  2222. return hr;
  2223. }
  2224. return hrSuccess;
  2225. }
  2226. /**
  2227. * Converts PT_STRING8 to PT_UNICODE inside PT_SRESTRICTION and
  2228. * PT_ACTION properties inside the rows
  2229. *
  2230. * @param[in,out] lpRowSet Rowset to modify
  2231. *
  2232. * @return MAPI Error code
  2233. */
  2234. HRESULT ConvertString8ToUnicode(LPSRowSet lpRowSet)
  2235. {
  2236. HRESULT hr;
  2237. convert_context converter;
  2238. if (lpRowSet == NULL)
  2239. return hrSuccess;
  2240. for (ULONG c = 0; c < lpRowSet->cRows; ++c) {
  2241. hr = ConvertString8ToUnicode(&lpRowSet->aRow[c], NULL, converter);
  2242. if (hr != hrSuccess)
  2243. return hr;
  2244. }
  2245. return hrSuccess;
  2246. }