ECPropertyEntry.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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 <new>
  19. #include "ECPropertyEntry.h"
  20. #include "Mem.h"
  21. #include <kopano/charset/convert.h>
  22. //
  23. // ECPropertyEntry
  24. //
  25. DEF_INVARIANT_CHECK(ECPropertyEntry) {
  26. // There should always be a proptag set.
  27. assert(ulPropTag != 0);
  28. assert(PROP_ID(ulPropTag) != 0);
  29. // PT_STRING8 and PT_MV_STRING8 are never stored.
  30. assert(PROP_TYPE(ulPropTag) != PT_STRING8);
  31. assert(PROP_TYPE(ulPropTag) != PT_MV_STRING8);
  32. }
  33. ECPropertyEntry::ECPropertyEntry(ULONG ulPropTag) :
  34. lpProperty(nullptr)
  35. {
  36. this->ulPropTag = ulPropTag;
  37. DEBUG_CHECK_INVARIANT;
  38. }
  39. ECPropertyEntry::ECPropertyEntry(ECProperty *property)
  40. {
  41. this->ulPropTag = property->GetPropTag();
  42. this->lpProperty = property;
  43. DEBUG_CHECK_INVARIANT;
  44. }
  45. ECPropertyEntry::~ECPropertyEntry()
  46. {
  47. DEBUG_CHECK_INVARIANT;
  48. }
  49. // NOTE: lpsPropValue must be checked already
  50. HRESULT ECPropertyEntry::HrSetProp(const SPropValue *lpsPropValue)
  51. {
  52. DEBUG_GUARD;
  53. HRESULT hr = hrSuccess;
  54. assert(this->ulPropTag != 0);
  55. assert(this->ulPropTag == lpsPropValue->ulPropTag);
  56. if(this->lpProperty)
  57. this->lpProperty->CopyFrom(lpsPropValue);
  58. else
  59. this->lpProperty = new ECProperty(lpsPropValue);
  60. this->fDirty = TRUE;
  61. return hr;
  62. }
  63. HRESULT ECPropertyEntry::HrSetProp(ECProperty *property)
  64. {
  65. DEBUG_GUARD;
  66. HRESULT hr = hrSuccess;
  67. assert(property->GetPropTag() != 0);
  68. assert(this->lpProperty == NULL);
  69. this->lpProperty = property;
  70. this->fDirty = TRUE;
  71. return hr;
  72. }
  73. HRESULT ECPropertyEntry::HrSetClean()
  74. {
  75. DEBUG_GUARD;
  76. this->fDirty = FALSE;
  77. return hrSuccess;
  78. }
  79. void ECPropertyEntry::DeleteProperty()
  80. {
  81. delete this->lpProperty;
  82. this->lpProperty = NULL;
  83. }
  84. //
  85. //
  86. //
  87. // ECProperty
  88. //
  89. // C++ class representing a property
  90. //
  91. //
  92. //
  93. //
  94. DEF_INVARIANT_CHECK(ECProperty) {
  95. // There should always be a proptag set.
  96. assert(ulPropTag != 0);
  97. assert(PROP_ID(ulPropTag) != 0);
  98. // PT_STRING8 and PT_MV_STRING8 are never stored.
  99. assert(PROP_TYPE(ulPropTag) != PT_STRING8);
  100. assert(PROP_TYPE(ulPropTag) != PT_MV_STRING8);
  101. }
  102. ECProperty::ECProperty(const ECProperty &Property) {
  103. SPropValue sPropValue;
  104. assert(Property.ulPropTag != 0);
  105. sPropValue.ulPropTag = Property.ulPropTag;
  106. sPropValue.Value = Property.Value;
  107. memset(&this->Value, 0, sizeof(union __UPV));
  108. this->ulSize = 0;
  109. CopyFromInternal(&sPropValue);
  110. DEBUG_CHECK_INVARIANT;
  111. }
  112. ECProperty::ECProperty(const SPropValue *lpsProp)
  113. {
  114. memset(&this->Value, 0, sizeof(union __UPV));
  115. this->ulSize = 0;
  116. assert(lpsProp->ulPropTag != 0);
  117. CopyFromInternal(lpsProp);
  118. DEBUG_CHECK_INVARIANT;
  119. }
  120. HRESULT ECProperty::CopyFrom(const SPropValue *lpsProp)
  121. {
  122. DEBUG_GUARD;
  123. return CopyFromInternal(lpsProp);
  124. }
  125. HRESULT ECProperty::CopyFromInternal(const SPropValue *lpsProp)
  126. {
  127. ULONG ulNewSize = 0;
  128. unsigned int i;
  129. if (lpsProp == NULL)
  130. return dwLastError = MAPI_E_INVALID_PARAMETER;
  131. this->dwLastError = 0;
  132. this->ulPropTag = lpsProp->ulPropTag;
  133. assert(lpsProp->ulPropTag != 0);
  134. switch(PROP_TYPE(lpsProp->ulPropTag)) {
  135. case PT_I2:
  136. this->ulSize = 4;
  137. this->Value.i = lpsProp->Value.i;
  138. break;
  139. case PT_I4:
  140. this->ulSize = 4;
  141. this->Value.l = lpsProp->Value.l;
  142. break;
  143. case PT_R4:
  144. this->ulSize = 4;
  145. this->Value.flt = lpsProp->Value.flt;
  146. break;
  147. case PT_R8:
  148. this->ulSize = 4;
  149. this->Value.dbl = lpsProp->Value.dbl;
  150. break;
  151. case PT_BOOLEAN:
  152. this->ulSize = 4;
  153. this->Value.b = lpsProp->Value.b;
  154. break;
  155. case PT_CURRENCY:
  156. this->ulSize = 4;
  157. this->Value.cur = lpsProp->Value.cur;
  158. break;
  159. case PT_APPTIME:
  160. this->ulSize = 4;
  161. this->Value.at = lpsProp->Value.at;
  162. break;
  163. case PT_SYSTIME:
  164. this->ulSize = 4;
  165. this->Value.ft = lpsProp->Value.ft;
  166. break;
  167. case PT_STRING8: {
  168. std::wstring wstrTmp;
  169. if (lpsProp->Value.lpszA == NULL)
  170. return dwLastError = MAPI_E_INVALID_PARAMETER;
  171. if (TryConvert(lpsProp->Value.lpszA, wstrTmp) != hrSuccess)
  172. return dwLastError = MAPI_E_INVALID_PARAMETER;
  173. ulNewSize = wstrTmp.length() + 1;
  174. if(ulSize < ulNewSize) {
  175. delete[] this->Value.lpszW;
  176. this->Value.lpszW = new(std::nothrow) WCHAR[ulNewSize];
  177. if (this->Value.lpszW == NULL)
  178. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  179. }
  180. ulSize = ulNewSize;
  181. this->ulPropTag = CHANGE_PROP_TYPE(lpsProp->ulPropTag, PT_UNICODE);
  182. wcscpy(this->Value.lpszW, wstrTmp.c_str());
  183. break;
  184. }
  185. case PT_BINARY: {
  186. if (lpsProp->Value.bin.lpb == NULL && lpsProp->Value.bin.cb)
  187. return dwLastError = MAPI_E_INVALID_PARAMETER;
  188. ulNewSize = lpsProp->Value.bin.cb;
  189. if(ulNewSize == 0) {
  190. delete[] this->Value.bin.lpb;
  191. this->Value.bin.lpb = NULL;
  192. this->Value.bin.cb = 0;
  193. ulSize = 0;
  194. break;
  195. }
  196. if(ulSize < ulNewSize) {
  197. delete[] this->Value.bin.lpb;
  198. this->Value.bin.lpb = new(std::nothrow) BYTE[ulNewSize];
  199. if (this->Value.bin.lpb == NULL)
  200. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  201. }
  202. ulSize = ulNewSize;
  203. this->Value.bin.cb = lpsProp->Value.bin.cb;
  204. memcpy(this->Value.bin.lpb, lpsProp->Value.bin.lpb, lpsProp->Value.bin.cb);
  205. break;
  206. }
  207. case PT_UNICODE: {
  208. if (lpsProp->Value.lpszW == NULL)
  209. return dwLastError = MAPI_E_INVALID_PARAMETER;
  210. ulNewSize = wcslen(lpsProp->Value.lpszW)+1;
  211. if(ulSize < ulNewSize) {
  212. delete[] this->Value.lpszW;
  213. this->Value.lpszW = new(std::nothrow) WCHAR[ulNewSize];
  214. if (this->Value.lpszW == NULL)
  215. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  216. }
  217. ulSize = ulNewSize;
  218. wcscpy(this->Value.lpszW, lpsProp->Value.lpszW);
  219. break;
  220. }
  221. case PT_CLSID: {
  222. if (lpsProp->Value.lpguid == NULL)
  223. return dwLastError = MAPI_E_INVALID_PARAMETER;
  224. if(ulSize != sizeof(GUID)) {
  225. ulSize = sizeof(GUID);
  226. this->Value.lpguid = new(std::nothrow) GUID;
  227. if (this->Value.lpguid == NULL)
  228. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  229. }
  230. memcpy(this->Value.lpguid, lpsProp->Value.lpguid, sizeof(GUID));
  231. break;
  232. }
  233. case PT_I8:
  234. ulSize = 8;
  235. this->Value.li = lpsProp->Value.li;
  236. break;
  237. case PT_MV_I2: {
  238. if (lpsProp->Value.MVi.lpi == NULL)
  239. return dwLastError = MAPI_E_INVALID_PARAMETER;
  240. ulNewSize = sizeof(short int)*lpsProp->Value.MVi.cValues;
  241. if(ulSize < ulNewSize) {
  242. delete[] this->Value.MVi.lpi;
  243. this->Value.MVi.lpi = new(std::nothrow) short int[lpsProp->Value.MVi.cValues];
  244. if (this->Value.MVi.lpi == NULL)
  245. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  246. }
  247. ulSize = ulNewSize;
  248. this->Value.MVi.cValues = lpsProp->Value.MVi.cValues;
  249. memcpy(this->Value.MVi.lpi, lpsProp->Value.MVi.lpi, lpsProp->Value.MVi.cValues * sizeof(short int));
  250. break;
  251. }
  252. case PT_MV_LONG: {
  253. if (lpsProp->Value.MVl.lpl == NULL)
  254. return dwLastError = MAPI_E_INVALID_PARAMETER;
  255. ulNewSize = sizeof(LONG) * lpsProp->Value.MVl.cValues;
  256. if(ulSize < ulNewSize) {
  257. delete[] this->Value.MVl.lpl;
  258. this->Value.MVl.lpl = new(std::nothrow) LONG[lpsProp->Value.MVl.cValues];
  259. if (this->Value.MVl.lpl == NULL)
  260. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  261. }
  262. ulSize = ulNewSize;
  263. this->Value.MVl.cValues = lpsProp->Value.MVl.cValues;
  264. memcpy(this->Value.MVl.lpl, lpsProp->Value.MVl.lpl, lpsProp->Value.MVl.cValues * sizeof(int));
  265. break;
  266. }
  267. case PT_MV_R4: {
  268. if (lpsProp->Value.MVflt.lpflt == NULL)
  269. return dwLastError = MAPI_E_INVALID_PARAMETER;
  270. ulNewSize = sizeof(float) * lpsProp->Value.MVflt.cValues;
  271. if(ulSize < ulNewSize) {
  272. delete[] this->Value.MVflt.lpflt;
  273. this->Value.MVflt.lpflt = new(std::nothrow) float[lpsProp->Value.MVflt.cValues];
  274. if (this->Value.MVflt.lpflt == NULL)
  275. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  276. }
  277. ulSize = ulNewSize;
  278. this->Value.MVflt.cValues = lpsProp->Value.MVflt.cValues;
  279. memcpy(this->Value.MVflt.lpflt, lpsProp->Value.MVflt.lpflt, lpsProp->Value.MVflt.cValues * sizeof(float));
  280. break;
  281. }
  282. case PT_MV_DOUBLE: {
  283. if (lpsProp->Value.MVdbl.lpdbl == NULL)
  284. return dwLastError = MAPI_E_INVALID_PARAMETER;
  285. ulNewSize = sizeof(double) * lpsProp->Value.MVdbl.cValues;
  286. if(ulSize < ulNewSize) {
  287. delete[] this->Value.MVdbl.lpdbl;
  288. this->Value.MVdbl.lpdbl = new(std::nothrow) double[lpsProp->Value.MVdbl.cValues];
  289. if (this->Value.MVdbl.lpdbl == NULL)
  290. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  291. }
  292. ulSize = ulNewSize;
  293. this->Value.MVdbl.cValues = lpsProp->Value.MVdbl.cValues;
  294. memcpy(this->Value.MVdbl.lpdbl, lpsProp->Value.MVdbl.lpdbl, lpsProp->Value.MVdbl.cValues * sizeof(double));
  295. break;
  296. }
  297. case PT_MV_CURRENCY: {
  298. if (lpsProp->Value.MVcur.lpcur == NULL)
  299. return dwLastError = MAPI_E_INVALID_PARAMETER;
  300. ulNewSize = sizeof(CURRENCY) * lpsProp->Value.MVcur.cValues;
  301. if(ulSize < ulNewSize) {
  302. delete[] this->Value.MVcur.lpcur;
  303. this->Value.MVcur.lpcur = new(std::nothrow) CURRENCY[lpsProp->Value.MVcur.cValues];
  304. if (this->Value.MVcur.lpcur == NULL)
  305. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  306. }
  307. ulSize = ulNewSize;
  308. this->Value.MVcur.cValues = lpsProp->Value.MVcur.cValues;
  309. memcpy(this->Value.MVcur.lpcur, lpsProp->Value.MVcur.lpcur, lpsProp->Value.MVcur.cValues * sizeof(CURRENCY));
  310. break;
  311. }
  312. case PT_MV_APPTIME: {
  313. if (lpsProp->Value.MVat.lpat == NULL)
  314. return dwLastError = MAPI_E_INVALID_PARAMETER;
  315. ulNewSize = sizeof(double) * lpsProp->Value.MVat.cValues;
  316. if(ulSize < ulNewSize) {
  317. if(this->Value.MVat.lpat)
  318. delete[] this->Value.MVat.lpat;
  319. this->Value.MVat.lpat = new(std::nothrow) double[lpsProp->Value.MVat.cValues];
  320. if (this->Value.MVat.lpat == NULL)
  321. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  322. }
  323. ulSize = ulNewSize;
  324. this->Value.MVat.cValues = lpsProp->Value.MVat.cValues;
  325. memcpy(this->Value.MVat.lpat, lpsProp->Value.MVat.lpat, lpsProp->Value.MVat.cValues * sizeof(double));
  326. break;
  327. }
  328. case PT_MV_SYSTIME: {
  329. if (lpsProp->Value.MVft.lpft == NULL)
  330. return dwLastError = MAPI_E_INVALID_PARAMETER;
  331. ulNewSize = sizeof(FILETIME) * lpsProp->Value.MVft.cValues;
  332. if(ulSize < ulNewSize) {
  333. delete[] this->Value.MVft.lpft;
  334. this->Value.MVft.lpft = new(std::nothrow) FILETIME[lpsProp->Value.MVft.cValues];
  335. if (this->Value.MVft.lpft == NULL)
  336. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  337. }
  338. ulSize = ulNewSize;
  339. this->Value.MVft.cValues = lpsProp->Value.MVft.cValues;
  340. memcpy(this->Value.MVft.lpft, lpsProp->Value.MVft.lpft, lpsProp->Value.MVft.cValues * sizeof(FILETIME));
  341. break;
  342. }
  343. case PT_MV_BINARY: {
  344. if (lpsProp->Value.MVbin.lpbin == NULL)
  345. return dwLastError = MAPI_E_INVALID_PARAMETER;
  346. ulNewSize = sizeof(void *) * lpsProp->Value.MVbin.cValues;
  347. if(ulSize < ulNewSize) {
  348. if(this->Value.MVbin.lpbin){
  349. for (unsigned int i = 0; i < this->Value.MVbin.cValues; ++i)
  350. delete[] this->Value.MVbin.lpbin[i].lpb;
  351. delete[] this->Value.MVbin.lpbin;
  352. }
  353. this->Value.MVbin.lpbin = new(std::nothrow) SBinary[lpsProp->Value.MVbin.cValues];
  354. if (this->Value.MVbin.lpbin == NULL)
  355. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  356. memset(this->Value.MVbin.lpbin, 0, sizeof(SBinary) * lpsProp->Value.MVbin.cValues);
  357. }
  358. else {
  359. for(unsigned int i = lpsProp->Value.MVbin.cValues; i < this->Value.MVbin.cValues; ++i)
  360. delete[] this->Value.MVbin.lpbin[i].lpb;
  361. }
  362. ulSize = ulNewSize;
  363. this->Value.MVbin.cValues = lpsProp->Value.MVbin.cValues;
  364. for (unsigned int i = 0; i < lpsProp->Value.MVbin.cValues; ++i) {
  365. if(lpsProp->Value.MVbin.lpbin[i].cb > 0)
  366. {
  367. if (lpsProp->Value.MVbin.lpbin[i].lpb == NULL)
  368. return dwLastError = MAPI_E_INVALID_PARAMETER;
  369. if(this->Value.MVbin.lpbin[i].lpb == NULL || this->Value.MVbin.lpbin[i].cb < lpsProp->Value.MVbin.lpbin[i].cb) {
  370. delete[] this->Value.MVbin.lpbin[i].lpb;
  371. this->Value.MVbin.lpbin[i].lpb = new BYTE [lpsProp->Value.MVbin.lpbin[i].cb];
  372. }
  373. memcpy(this->Value.MVbin.lpbin[i].lpb, lpsProp->Value.MVbin.lpbin[i].lpb, lpsProp->Value.MVbin.lpbin[i].cb);
  374. }else {
  375. delete[] this->Value.MVbin.lpbin[i].lpb;
  376. this->Value.MVbin.lpbin[i].lpb = NULL;
  377. }
  378. this->Value.MVbin.lpbin[i].cb = lpsProp->Value.MVbin.lpbin[i].cb;
  379. }
  380. break;
  381. }
  382. case PT_MV_STRING8: {
  383. convert_context converter;
  384. if (lpsProp->Value.MVszA.lppszA == NULL)
  385. return dwLastError = MAPI_E_INVALID_PARAMETER;
  386. ulNewSize = sizeof(void *) * lpsProp->Value.MVszA.cValues;
  387. if(ulSize < ulNewSize) {
  388. if(this->Value.MVszW.lppszW) {
  389. for (i = 0; i < this->Value.MVszW.cValues; ++i)
  390. delete [] this->Value.MVszW.lppszW[i];
  391. delete [] this->Value.MVszW.lppszW;
  392. }
  393. this->Value.MVszW.lppszW = new(std::nothrow) wchar_t *[lpsProp->Value.MVszA.cValues];
  394. if (this->Value.MVszW.lppszW == NULL)
  395. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  396. memset(this->Value.MVszW.lppszW, 0, sizeof(wchar_t *) * lpsProp->Value.MVszA.cValues);
  397. }
  398. else {
  399. for(unsigned int i = lpsProp->Value.MVszW.cValues; i < this->Value.MVszW.cValues; ++i)
  400. delete[] this->Value.MVszW.lppszW[i];
  401. }
  402. ulSize = ulNewSize;
  403. this->Value.MVszW.cValues = lpsProp->Value.MVszA.cValues;
  404. for (unsigned int i = 0; i < lpsProp->Value.MVszA.cValues; ++i) {
  405. std::wstring wstrTmp;
  406. if (lpsProp->Value.MVszA.lppszA[i] == NULL)
  407. return dwLastError = MAPI_E_INVALID_PARAMETER;
  408. if (TryConvert(lpsProp->Value.MVszA.lppszA[i], wstrTmp) != hrSuccess)
  409. return dwLastError = MAPI_E_INVALID_PARAMETER;
  410. if(this->Value.MVszW.lppszW[i] == NULL || wcslen(this->Value.MVszW.lppszW[i]) < wstrTmp.length())
  411. {
  412. delete[] this->Value.MVszW.lppszW[i];
  413. this->Value.MVszW.lppszW[i] = new WCHAR [wstrTmp.length() + sizeof(wchar_t)];
  414. }
  415. wcscpy(this->Value.MVszW.lppszW[i], wstrTmp.c_str());
  416. }
  417. this->ulPropTag = CHANGE_PROP_TYPE(lpsProp->ulPropTag, PT_MV_UNICODE);
  418. break;
  419. }
  420. case PT_MV_UNICODE: {
  421. if (lpsProp->Value.MVszW.lppszW == NULL)
  422. return dwLastError = MAPI_E_INVALID_PARAMETER;
  423. ulNewSize = sizeof(void *) * lpsProp->Value.MVszW.cValues;
  424. if(ulSize < ulNewSize) {
  425. if(this->Value.MVszW.lppszW) {
  426. for (unsigned int i = 0; i < this->Value.MVszW.cValues; ++i)
  427. delete[] this->Value.MVszW.lppszW[i];
  428. delete[] this->Value.MVszW.lppszW;
  429. }
  430. this->Value.MVszW.lppszW = new(std::nothrow) wchar_t *[lpsProp->Value.MVszW.cValues];
  431. if (this->Value.MVszW.lppszW == NULL)
  432. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  433. memset(this->Value.MVszW.lppszW, 0, sizeof(WCHAR *) * lpsProp->Value.MVszW.cValues);
  434. }
  435. else {
  436. for(unsigned int i = lpsProp->Value.MVszW.cValues; i < this->Value.MVszW.cValues; ++i)
  437. delete[] this->Value.MVszW.lppszW[i];
  438. }
  439. ulSize = ulNewSize;
  440. this->Value.MVszW.cValues = lpsProp->Value.MVszW.cValues;
  441. for (unsigned int i = 0; i < lpsProp->Value.MVszW.cValues; ++i) {
  442. if (lpsProp->Value.MVszW.lppszW[i] == NULL)
  443. return dwLastError = MAPI_E_INVALID_PARAMETER;
  444. if(this->Value.MVszW.lppszW[i] == NULL || wcslen(this->Value.MVszW.lppszW[i]) < wcslen(lpsProp->Value.MVszW.lppszW[i])) {
  445. delete[] this->Value.MVszW.lppszW[i];
  446. this->Value.MVszW.lppszW[i] = new WCHAR [wcslen(lpsProp->Value.MVszW.lppszW[i])+sizeof(WCHAR)];
  447. }
  448. wcscpy(this->Value.MVszW.lppszW[i], lpsProp->Value.MVszW.lppszW[i]);
  449. }
  450. break;
  451. }
  452. case PT_MV_CLSID: {
  453. if (lpsProp->Value.MVguid.lpguid == NULL)
  454. return dwLastError = MAPI_E_INVALID_PARAMETER;
  455. ulNewSize = sizeof(GUID) * lpsProp->Value.MVguid.cValues;
  456. if(ulSize < ulNewSize) {
  457. delete[] this->Value.MVguid.lpguid;
  458. this->Value.MVguid.lpguid = new(std::nothrow) GUID[lpsProp->Value.MVguid.cValues];
  459. if (this->Value.MVguid.lpguid == NULL)
  460. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  461. }
  462. ulSize = ulNewSize;
  463. this->Value.MVguid.cValues = lpsProp->Value.MVguid.cValues;
  464. memcpy(this->Value.MVguid.lpguid, lpsProp->Value.MVguid.lpguid, sizeof(GUID) * lpsProp->Value.MVguid.cValues);
  465. break;
  466. }
  467. case PT_MV_I8: {
  468. if (lpsProp->Value.MVli.lpli == NULL)
  469. return dwLastError = MAPI_E_INVALID_PARAMETER;
  470. ulNewSize = sizeof(LARGE_INTEGER) * lpsProp->Value.MVli.cValues;
  471. if(ulSize < ulNewSize) {
  472. delete[] this->Value.MVli.lpli;
  473. this->Value.MVli.lpli = new(std::nothrow) LARGE_INTEGER[lpsProp->Value.MVli.cValues];
  474. if (this->Value.MVli.lpli == NULL)
  475. return dwLastError = MAPI_E_NOT_ENOUGH_MEMORY;
  476. }
  477. ulSize = ulNewSize;
  478. this->Value.MVli.cValues = lpsProp->Value.MVli.cValues;
  479. memcpy(this->Value.MVli.lpli, lpsProp->Value.MVli.lpli, lpsProp->Value.MVli.cValues * sizeof(LARGE_INTEGER));
  480. break;
  481. }
  482. case PT_ERROR:
  483. this->Value.err = lpsProp->Value.err;
  484. break;
  485. default:
  486. // Unknown type (PR_NULL not include)
  487. assert(false);
  488. dwLastError = MAPI_E_INVALID_PARAMETER;
  489. break;
  490. }
  491. return dwLastError;
  492. }
  493. ECProperty::~ECProperty()
  494. {
  495. DEBUG_GUARD;
  496. switch(PROP_TYPE(ulPropTag)) {
  497. case PT_I2:
  498. case PT_I4:
  499. case PT_R4:
  500. case PT_R8:
  501. case PT_BOOLEAN:
  502. case PT_CURRENCY:
  503. case PT_APPTIME:
  504. case PT_SYSTIME:
  505. case PT_I8:
  506. break;
  507. case PT_BINARY:
  508. delete[] this->Value.bin.lpb;
  509. break;
  510. case PT_STRING8:
  511. assert("We should never have PT_STRING8 storage" == nullptr);
  512. // Deliberate fallthrough
  513. case PT_UNICODE:
  514. delete [] this->Value.lpszW;
  515. break;
  516. case PT_CLSID:
  517. delete this->Value.lpguid;
  518. break;
  519. case PT_MV_I2:
  520. delete [] Value.MVi.lpi;
  521. break;
  522. case PT_MV_LONG:
  523. delete [] this->Value.MVl.lpl;
  524. break;
  525. case PT_MV_R4:
  526. delete [] this->Value.MVflt.lpflt;
  527. break;
  528. case PT_MV_DOUBLE:
  529. delete [] this->Value.MVdbl.lpdbl;
  530. break;
  531. case PT_MV_CURRENCY:
  532. delete [] this->Value.MVcur.lpcur;
  533. break;
  534. case PT_MV_APPTIME:
  535. delete [] this->Value.MVat.lpat;
  536. break;
  537. case PT_MV_SYSTIME:
  538. delete [] this->Value.MVft.lpft;
  539. break;
  540. case PT_MV_BINARY: {
  541. for (unsigned int i = 0; i <this->Value.MVbin.cValues; ++i)
  542. delete[] this->Value.MVbin.lpbin[i].lpb;
  543. delete [] this->Value.MVbin.lpbin;
  544. break;
  545. }
  546. case PT_MV_STRING8:
  547. assert("We should never have PT_MV_STRING8 storage" == nullptr);
  548. // Deliberate fallthrough
  549. case PT_MV_UNICODE: {
  550. for (unsigned int i = 0; i < this->Value.MVszW.cValues; ++i)
  551. delete [] this->Value.MVszW.lppszW[i];
  552. delete [] this->Value.MVszW.lppszW;
  553. break;
  554. }
  555. case PT_MV_CLSID: {
  556. delete [] this->Value.MVguid.lpguid;
  557. break;
  558. }
  559. case PT_MV_I8:
  560. delete [] this->Value.MVli.lpli;
  561. break;
  562. case PT_ERROR:
  563. break;
  564. default:
  565. break;
  566. }
  567. }
  568. HRESULT ECProperty::CopyToByRef(LPSPropValue lpsProp) const
  569. {
  570. DEBUG_GUARD;
  571. HRESULT hr = hrSuccess;
  572. lpsProp->ulPropTag = this->ulPropTag;
  573. memcpy(&lpsProp->Value, &this->Value, sizeof(union __UPV));
  574. return hr;
  575. }
  576. HRESULT ECProperty::CopyTo(LPSPropValue lpsProp, void *lpBase, ULONG ulRequestPropTag) {
  577. DEBUG_GUARD;
  578. HRESULT hr = hrSuccess;
  579. assert
  580. (
  581. PROP_TYPE(ulRequestPropTag) == PROP_TYPE(this->ulPropTag) ||
  582. ((PROP_TYPE(ulRequestPropTag) == PT_STRING8 || PROP_TYPE(ulRequestPropTag) == PT_UNICODE) && PROP_TYPE(this->ulPropTag) == PT_UNICODE) ||
  583. ((PROP_TYPE(ulRequestPropTag) == PT_MV_STRING8 || PROP_TYPE(ulRequestPropTag) == PT_MV_UNICODE) && PROP_TYPE(this->ulPropTag) == PT_MV_UNICODE)
  584. );
  585. lpsProp->ulPropTag = ulRequestPropTag;
  586. switch(PROP_TYPE(this->ulPropTag)) {
  587. case PT_I2:
  588. lpsProp->Value.i = this->Value.i;
  589. break;
  590. case PT_I4:
  591. lpsProp->Value.l = this->Value.l;
  592. break;
  593. case PT_R4:
  594. lpsProp->Value.flt = this->Value.flt;
  595. break;
  596. case PT_R8:
  597. lpsProp->Value.dbl = this->Value.dbl;
  598. break;
  599. case PT_BOOLEAN:
  600. lpsProp->Value.b = this->Value.b;
  601. break;
  602. case PT_CURRENCY:
  603. lpsProp->Value.cur = this->Value.cur;
  604. break;
  605. case PT_APPTIME:
  606. lpsProp->Value.at = this->Value.at;
  607. break;
  608. case PT_SYSTIME:
  609. lpsProp->Value.ft = this->Value.ft;
  610. break;
  611. case PT_BINARY: {
  612. if (this->Value.bin.cb == 0) {
  613. lpsProp->Value.bin.lpb = NULL;
  614. lpsProp->Value.bin.cb = this->Value.bin.cb;
  615. } else {
  616. BYTE *lpBin = NULL;
  617. hr = ECAllocateMore(this->Value.bin.cb, lpBase, (LPVOID *)&lpBin);
  618. if(hr != hrSuccess)
  619. dwLastError = hr;
  620. else {
  621. memcpy(lpBin, this->Value.bin.lpb, this->Value.bin.cb);
  622. lpsProp->Value.bin.lpb = lpBin;
  623. lpsProp->Value.bin.cb = this->Value.bin.cb;
  624. }
  625. }
  626. break;
  627. }
  628. case PT_STRING8:
  629. assert("We should never have PT_STRING8 storage" == nullptr);
  630. // Deliberate fallthrough
  631. case PT_UNICODE: {
  632. if (PROP_TYPE(ulRequestPropTag) == PT_UNICODE) {
  633. hr = ECAllocateMore(sizeof(WCHAR) * (wcslen(this->Value.lpszW) + 1), lpBase, (LPVOID*)&lpsProp->Value.lpszW);
  634. if (hr != hrSuccess)
  635. dwLastError = hr;
  636. else
  637. wcscpy(lpsProp->Value.lpszW, this->Value.lpszW);
  638. }
  639. else {
  640. std::string dst;
  641. if (TryConvert(this->Value.lpszW, dst) != hrSuccess) {
  642. dwLastError = MAPI_E_INVALID_PARAMETER;
  643. return hr;
  644. }
  645. hr = ECAllocateMore(dst.length() + 1, lpBase, (LPVOID*)&lpsProp->Value.lpszA);
  646. if (hr != hrSuccess)
  647. dwLastError = hr;
  648. else
  649. strcpy(lpsProp->Value.lpszA, dst.c_str());
  650. }
  651. break;
  652. }
  653. case PT_CLSID: {
  654. GUID *lpGUID;
  655. hr = ECAllocateMore(sizeof(GUID), lpBase, (LPVOID *)&lpGUID);
  656. if(hr != hrSuccess)
  657. dwLastError = hr;
  658. else {
  659. memcpy(lpGUID, this->Value.lpguid, sizeof(GUID));
  660. lpsProp->Value.lpguid = lpGUID;
  661. }
  662. break;
  663. }
  664. case PT_I8:
  665. lpsProp->Value.li = this->Value.li;
  666. break;
  667. case PT_MV_I2: {
  668. short int *lpShort;
  669. hr = ECAllocateMore(this->Value.MVi.cValues * sizeof(short int), lpBase, (LPVOID *)&lpShort);
  670. if(hr != hrSuccess)
  671. dwLastError = hr;
  672. else {
  673. lpsProp->Value.MVi.cValues = this->Value.MVi.cValues;
  674. memcpy(lpShort, this->Value.MVi.lpi, this->Value.MVi.cValues * sizeof(short int));
  675. lpsProp->Value.MVi.lpi = lpShort;
  676. }
  677. break;
  678. }
  679. case PT_MV_LONG: {
  680. LONG *lpLong;
  681. hr = ECAllocateMore(this->Value.MVl.cValues * sizeof(LONG), lpBase, (LPVOID *)&lpLong);
  682. if(hr != hrSuccess)
  683. dwLastError = hr;
  684. else {
  685. lpsProp->Value.MVl.cValues = this->Value.MVl.cValues;
  686. memcpy(lpLong, this->Value.MVl.lpl, this->Value.MVl.cValues * sizeof(LONG));
  687. lpsProp->Value.MVl.lpl = lpLong;
  688. }
  689. break;
  690. }
  691. case PT_MV_R4: {
  692. float *lpFloat;
  693. hr = ECAllocateMore(this->Value.MVflt.cValues * sizeof(float), lpBase, (LPVOID *)&lpFloat);
  694. if(hr != hrSuccess)
  695. dwLastError = hr;
  696. else {
  697. lpsProp->Value.MVflt.cValues = this->Value.MVflt.cValues;
  698. memcpy(lpFloat, this->Value.MVflt.lpflt, this->Value.MVflt.cValues * sizeof(float));
  699. lpsProp->Value.MVflt.lpflt = lpFloat;
  700. }
  701. break;
  702. }
  703. case PT_MV_DOUBLE: {
  704. double *lpDouble;
  705. hr = ECAllocateMore(this->Value.MVdbl.cValues * sizeof(double), lpBase, (LPVOID *)&lpDouble);
  706. if(hr != hrSuccess)
  707. dwLastError = hr;
  708. else {
  709. lpsProp->Value.MVdbl.cValues = this->Value.MVdbl.cValues;
  710. memcpy(lpDouble, this->Value.MVdbl.lpdbl, this->Value.MVdbl.cValues * sizeof(double));
  711. lpsProp->Value.MVdbl.lpdbl = lpDouble;
  712. }
  713. break;
  714. }
  715. case PT_MV_CURRENCY: {
  716. CURRENCY *lpCurrency;
  717. hr = ECAllocateMore(this->Value.MVcur.cValues * sizeof(CURRENCY), lpBase, (LPVOID *)&lpCurrency);
  718. if(hr != hrSuccess)
  719. dwLastError = hr;
  720. else {
  721. lpsProp->Value.MVcur.cValues = this->Value.MVcur.cValues;
  722. memcpy(lpCurrency, this->Value.MVcur.lpcur, this->Value.MVcur.cValues * sizeof(CURRENCY));
  723. lpsProp->Value.MVcur.lpcur = lpCurrency;
  724. }
  725. break;
  726. }
  727. case PT_MV_APPTIME: {
  728. double *lpApptime;
  729. hr = ECAllocateMore(this->Value.MVat.cValues * sizeof(double), lpBase, (LPVOID *)&lpApptime);
  730. if(hr != hrSuccess)
  731. dwLastError = hr;
  732. else {
  733. lpsProp->Value.MVat.cValues = this->Value.MVat.cValues;
  734. memcpy(lpApptime, this->Value.MVat.lpat, this->Value.MVat.cValues * sizeof(double));
  735. lpsProp->Value.MVat.lpat = lpApptime;
  736. }
  737. break;
  738. }
  739. case PT_MV_SYSTIME: {
  740. FILETIME *lpFiletime;
  741. hr = ECAllocateMore(this->Value.MVft.cValues * sizeof(FILETIME), lpBase, (LPVOID *)&lpFiletime);
  742. if(hr != hrSuccess)
  743. dwLastError = hr;
  744. else {
  745. lpsProp->Value.MVft.cValues = this->Value.MVft.cValues;
  746. memcpy(lpFiletime, this->Value.MVft.lpft, this->Value.MVft.cValues * sizeof(FILETIME));
  747. lpsProp->Value.MVft.lpft = lpFiletime;
  748. }
  749. break;
  750. }
  751. case PT_MV_BINARY: {
  752. SBinary *lpBin;
  753. hr = ECAllocateMore(this->Value.MVbin.cValues * sizeof(SBinary), lpBase, (LPVOID *)&lpBin);
  754. if(hr != hrSuccess)
  755. dwLastError = hr;
  756. else {
  757. lpsProp->Value.MVbin.cValues = this->Value.MVbin.cValues;
  758. lpsProp->Value.MVbin.lpbin = lpBin;
  759. for (unsigned int i = 0; i < this->Value.MVbin.cValues; ++i) {
  760. lpsProp->Value.MVbin.lpbin[i].cb = this->Value.MVbin.lpbin[i].cb;
  761. if(lpsProp->Value.MVbin.lpbin[i].cb > 0)
  762. {
  763. hr = ECAllocateMore(this->Value.MVbin.lpbin[i].cb, lpBase, reinterpret_cast<void **>(&lpsProp->Value.MVbin.lpbin[i].lpb));
  764. if (hr != hrSuccess)
  765. return hr;
  766. memcpy(lpsProp->Value.MVbin.lpbin[i].lpb, this->Value.MVbin.lpbin[i].lpb, lpsProp->Value.MVbin.lpbin[i].cb);
  767. }else
  768. lpsProp->Value.MVbin.lpbin[i].lpb = NULL;
  769. }
  770. }
  771. break;
  772. }
  773. case PT_MV_STRING8:
  774. assert("We should never have PT_MV_STRING8 storage" == nullptr);
  775. // Deliberate fallthrough
  776. case PT_MV_UNICODE: {
  777. if (PROP_TYPE(ulRequestPropTag) == PT_MV_STRING8) {
  778. lpsProp->Value.MVszA.cValues = this->Value.MVszW.cValues;
  779. hr = ECAllocateMore(this->Value.MVszW.cValues * sizeof(LPSTR), lpBase, (LPVOID*)&lpsProp->Value.MVszA.lppszA);
  780. if (hr != hrSuccess)
  781. dwLastError = hr;
  782. else {
  783. convert_context converter;
  784. for (ULONG i = 0; hr == hrSuccess && i < this->Value.MVszW.cValues; ++i) {
  785. std::string strDst;
  786. if (TryConvert(this->Value.MVszW.lppszW[i], strDst) != hrSuccess) {
  787. dwLastError = MAPI_E_INVALID_PARAMETER;
  788. return hr;
  789. }
  790. hr = ECAllocateMore(strDst.size() + 1, lpBase, (LPVOID*)&lpsProp->Value.MVszA.lppszA[i]);
  791. if (hr != hrSuccess)
  792. dwLastError = hr;
  793. else
  794. strcpy(lpsProp->Value.MVszA.lppszA[i], strDst.c_str());
  795. }
  796. }
  797. } else {
  798. lpsProp->Value.MVszW.cValues = this->Value.MVszW.cValues;
  799. hr = ECAllocateMore(this->Value.MVszW.cValues * sizeof(LPWSTR), lpBase, (LPVOID*)&lpsProp->Value.MVszW.lppszW);
  800. if (hr != hrSuccess)
  801. dwLastError = hr;
  802. else {
  803. for (ULONG i = 0; hr == hrSuccess && i < this->Value.MVszW.cValues; ++i) {
  804. hr = ECAllocateMore(sizeof(WCHAR) * (wcslen(this->Value.MVszW.lppszW[i]) + 1), lpBase, (LPVOID*)&lpsProp->Value.MVszW.lppszW[i]);
  805. if (hr != hrSuccess)
  806. dwLastError = hr;
  807. else
  808. wcscpy(lpsProp->Value.MVszW.lppszW[i], this->Value.MVszW.lppszW[i]);
  809. }
  810. }
  811. }
  812. break;
  813. }
  814. case PT_MV_CLSID: {
  815. GUID *lpGuid;
  816. hr = ECAllocateMore(this->Value.MVguid.cValues * sizeof(GUID), lpBase, (LPVOID *)&lpGuid);
  817. if(hr != hrSuccess)
  818. dwLastError = hr;
  819. else {
  820. memcpy(lpGuid, this->Value.MVguid.lpguid, sizeof(GUID) * this->Value.MVguid.cValues);
  821. lpsProp->Value.MVguid.cValues = this->Value.MVguid.cValues;
  822. lpsProp->Value.MVguid.lpguid = lpGuid;
  823. }
  824. break;
  825. }
  826. case PT_MV_I8: {
  827. LARGE_INTEGER *lpLarge;
  828. hr = ECAllocateMore(this->Value.MVli.cValues * sizeof(LARGE_INTEGER), lpBase, (LPVOID *)&lpLarge);
  829. if(hr != hrSuccess)
  830. dwLastError = hr;
  831. else {
  832. lpsProp->Value.MVli.cValues = this->Value.MVli.cValues;
  833. memcpy(lpLarge, this->Value.MVli.lpli, this->Value.MVli.cValues * sizeof(LARGE_INTEGER));
  834. lpsProp->Value.MVli.lpli = lpLarge;
  835. }
  836. break;
  837. }
  838. case PT_ERROR:
  839. lpsProp->Value.err = this->Value.err;
  840. break;
  841. default: // I hope there are no pointers involved here!
  842. assert(false);
  843. lpsProp->Value = this->Value;
  844. break;
  845. }
  846. return hr;
  847. }
  848. bool ECProperty::operator==(const ECProperty &property) const {
  849. DEBUG_GUARD;
  850. return property.ulPropTag == this->ulPropTag ||
  851. (
  852. PROP_ID(property.ulPropTag) == PROP_ID(this->ulPropTag) &&
  853. (
  854. (PROP_TYPE(property.ulPropTag) == PT_STRING8 && PROP_TYPE(this->ulPropTag) == PT_UNICODE) ||
  855. (PROP_TYPE(property.ulPropTag) == PT_MV_STRING8 && PROP_TYPE(this->ulPropTag) == PT_MV_UNICODE)
  856. )
  857. );
  858. }
  859. SPropValue ECProperty::GetMAPIPropValRef(void) const
  860. {
  861. DEBUG_GUARD;
  862. SPropValue ret;
  863. ret.ulPropTag = this->ulPropTag;
  864. ret.dwAlignPad = 0;
  865. ret.Value = this->Value;
  866. return ret;
  867. }