WSABPropStorage.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. #include <new>
  17. #include <kopano/platform.h>
  18. #include "WSABPropStorage.h"
  19. #include "Mem.h"
  20. #include <kopano/ECGuid.h>
  21. #include <kopano/ECInterfaceDefs.h>
  22. #include "SOAPUtils.h"
  23. #include "WSUtil.h"
  24. #include <kopano/charset/convert.h>
  25. #define START_SOAP_CALL retry:
  26. #define END_SOAP_CALL \
  27. if (er == KCERR_END_OF_SESSION && this->m_lpTransport->HrReLogon() == hrSuccess) \
  28. goto retry; \
  29. hr = kcerr_to_mapierr(er, MAPI_E_NOT_FOUND); \
  30. if(hr != hrSuccess) \
  31. goto exit;
  32. /*
  33. * This is a PropStorage object for use with the WebServices storage platform
  34. */
  35. WSABPropStorage::WSABPropStorage(ULONG cbEntryId, LPENTRYID lpEntryId,
  36. KCmd *lpCmd, std::recursive_mutex &data_lock, ECSESSIONID ecSessionId,
  37. WSTransport *lpTransport) :
  38. ECUnknown("WSABPropStorage"), lpDataLock(data_lock),
  39. m_lpTransport(lpTransport)
  40. {
  41. CopyMAPIEntryIdToSOAPEntryId(cbEntryId, lpEntryId, &m_sEntryId);
  42. this->lpCmd = lpCmd;
  43. this->ecSessionId = ecSessionId;
  44. lpTransport->AddSessionReloadCallback(this, Reload, &m_ulSessionReloadCallback);
  45. }
  46. WSABPropStorage::~WSABPropStorage()
  47. {
  48. m_lpTransport->RemoveSessionReloadCallback(m_ulSessionReloadCallback);
  49. FreeEntryId(&m_sEntryId, false);
  50. }
  51. HRESULT WSABPropStorage::QueryInterface(REFIID refiid, void **lppInterface)
  52. {
  53. REGISTER_INTERFACE2(WSABPropStorage, this);
  54. REGISTER_INTERFACE2(IECPropStorage, &this->m_xECPropStorage);
  55. return MAPI_E_INTERFACE_NOT_SUPPORTED;
  56. }
  57. HRESULT WSABPropStorage::Create(ULONG cbEntryId, LPENTRYID lpEntryId,
  58. KCmd *lpCmd, std::recursive_mutex &lpDataLock, ECSESSIONID ecSessionId,
  59. WSTransport *lpTransport, WSABPropStorage **lppPropStorage)
  60. {
  61. HRESULT hr = hrSuccess;
  62. auto lpStorage = new(std::nothrow) WSABPropStorage(cbEntryId, lpEntryId,
  63. lpCmd, lpDataLock, ecSessionId, lpTransport);
  64. if (lpStorage == nullptr)
  65. return MAPI_E_NOT_ENOUGH_MEMORY;
  66. hr = lpStorage->QueryInterface(IID_WSABPropStorage, (void **)lppPropStorage);
  67. if(hr != hrSuccess)
  68. delete lpStorage;
  69. return hr;
  70. }
  71. HRESULT WSABPropStorage::HrReadProps(LPSPropTagArray *lppPropTags,ULONG *cValues, LPSPropValue *ppValues)
  72. {
  73. HRESULT hr = hrSuccess;
  74. ECRESULT er = hrSuccess;
  75. convert_context converter;
  76. struct readPropsResponse sResponse;
  77. LockSoap();
  78. START_SOAP_CALL
  79. {
  80. // Read the properties from the server
  81. if(SOAP_OK != lpCmd->ns__readABProps(ecSessionId, m_sEntryId, &sResponse))
  82. er = KCERR_NETWORK_ERROR;
  83. else
  84. er = sResponse.er;
  85. }
  86. END_SOAP_CALL
  87. // Convert the property tags to a MAPI proptagarray
  88. hr = ECAllocateBuffer(CbNewSPropTagArray(sResponse.aPropTag.__size), (void **)lppPropTags);
  89. if(hr != hrSuccess)
  90. goto exit;
  91. (*lppPropTags)->cValues = sResponse.aPropTag.__size;
  92. for (gsoap_size_t i = 0; i < sResponse.aPropTag.__size; ++i)
  93. (*lppPropTags)->aulPropTag[i] = sResponse.aPropTag.__ptr[i];
  94. // Convert the property values to a MAPI propvalarray
  95. *cValues = sResponse.aPropVal.__size;
  96. if(sResponse.aPropTag.__size == 0) {
  97. *ppValues = NULL;
  98. } else {
  99. hr = ECAllocateBuffer(sizeof(SPropValue) * sResponse.aPropVal.__size, (void **)ppValues);
  100. if(hr != hrSuccess)
  101. goto exit;
  102. }
  103. for (gsoap_size_t i = 0; i < sResponse.aPropVal.__size; ++i) {
  104. hr = CopySOAPPropValToMAPIPropVal(&(*ppValues)[i],&sResponse.aPropVal.__ptr[i], *ppValues, &converter);
  105. if(hr != hrSuccess)
  106. goto exit;
  107. }
  108. exit:
  109. UnLockSoap();
  110. if(hr != hrSuccess) {
  111. if(*lppPropTags)
  112. ECFreeBuffer(*lppPropTags);
  113. if(*ppValues)
  114. ECFreeBuffer(*ppValues);
  115. }
  116. return hr;
  117. }
  118. HRESULT WSABPropStorage::HrLoadProp(ULONG ulObjId, ULONG ulPropTag, LPSPropValue *lppsPropValue)
  119. {
  120. ECRESULT er = erSuccess;
  121. HRESULT hr = hrSuccess;
  122. LPSPropValue lpsPropValDst = NULL;
  123. struct loadPropResponse sResponse;
  124. LockSoap();
  125. START_SOAP_CALL
  126. {
  127. if(SOAP_OK != lpCmd->ns__loadABProp(ecSessionId, m_sEntryId, ulPropTag, &sResponse))
  128. er = KCERR_NETWORK_ERROR;
  129. else
  130. er = sResponse.er;
  131. }
  132. END_SOAP_CALL
  133. hr = ECAllocateBuffer(sizeof(SPropValue), (void **)&lpsPropValDst);
  134. if(hr != hrSuccess)
  135. goto exit;
  136. if(sResponse.lpPropVal == NULL) {
  137. hr = MAPI_E_NOT_FOUND;
  138. goto exit;
  139. }
  140. hr = CopySOAPPropValToMAPIPropVal(lpsPropValDst, sResponse.lpPropVal, lpsPropValDst);
  141. *lppsPropValue = lpsPropValDst;
  142. exit:
  143. UnLockSoap();
  144. return hr;
  145. }
  146. HRESULT WSABPropStorage::HrWriteProps(ULONG cValues, LPSPropValue pValues, ULONG ulFlags)
  147. {
  148. HRESULT hr = hrSuccess;
  149. ECRESULT er = erSuccess;
  150. unsigned int i = 0;
  151. unsigned int j = 0;
  152. convert_context converter;
  153. struct propValArray sPropVals;
  154. sPropVals.__ptr = s_alloc<propVal>(nullptr, cValues);
  155. for (i = 0; i < cValues; ++i) {
  156. hr = CopyMAPIPropValToSOAPPropVal(&sPropVals.__ptr[j], &pValues[i], &converter);
  157. if(hr == hrSuccess)
  158. ++j;
  159. }
  160. hr = hrSuccess;
  161. sPropVals.__size = j;
  162. LockSoap();
  163. START_SOAP_CALL
  164. {
  165. if(SOAP_OK != lpCmd->ns__writeABProps(ecSessionId, m_sEntryId, &sPropVals, &er))
  166. er = KCERR_NETWORK_ERROR;
  167. }
  168. END_SOAP_CALL
  169. exit:
  170. UnLockSoap();
  171. if(sPropVals.__ptr)
  172. FreePropValArray(&sPropVals);
  173. return hr;
  174. }
  175. HRESULT WSABPropStorage::HrDeleteProps(const SPropTagArray *lpsPropTagArray)
  176. {
  177. ECRESULT er = erSuccess;
  178. HRESULT hr = hrSuccess;
  179. struct propTagArray sPropTags;
  180. sPropTags.__size = lpsPropTagArray->cValues;
  181. sPropTags.__ptr = (unsigned int *)lpsPropTagArray->aulPropTag;
  182. LockSoap();
  183. START_SOAP_CALL
  184. {
  185. if(SOAP_OK != lpCmd->ns__deleteABProps(ecSessionId, m_sEntryId, &sPropTags, &er))
  186. er = KCERR_NETWORK_ERROR;
  187. }
  188. END_SOAP_CALL
  189. exit:
  190. UnLockSoap();
  191. return hr;
  192. }
  193. HRESULT WSABPropStorage::HrSaveObject(ULONG ulFlags, MAPIOBJECT *lpsMapiObject)
  194. {
  195. return MAPI_E_NO_SUPPORT;
  196. // TODO: this should be supported eventually
  197. }
  198. HRESULT WSABPropStorage::HrLoadObject(MAPIOBJECT **lppsMapiObject)
  199. {
  200. HRESULT hr = hrSuccess;
  201. ECRESULT er = hrSuccess;
  202. MAPIOBJECT *mo = NULL;
  203. LPSPropValue lpProp = NULL;
  204. struct readPropsResponse sResponse;
  205. convert_context converter;
  206. LockSoap();
  207. START_SOAP_CALL
  208. {
  209. // Read the properties from the server
  210. if(SOAP_OK != lpCmd->ns__readABProps(ecSessionId, m_sEntryId, &sResponse))
  211. er = KCERR_NETWORK_ERROR;
  212. else
  213. er = sResponse.er;
  214. }
  215. END_SOAP_CALL
  216. // Convert the property tags to a MAPIOBJECT
  217. //(type,objectid)
  218. AllocNewMapiObject(0, 0, 0, &mo);
  219. hr = ECAllocateBuffer(sizeof(SPropValue) * sResponse.aPropVal.__size, (void **)&lpProp);
  220. if (hr != hrSuccess)
  221. goto exit;
  222. for (gsoap_size_t i = 0; i < sResponse.aPropTag.__size; ++i)
  223. mo->lstAvailable.push_back(sResponse.aPropTag.__ptr[i]);
  224. for (gsoap_size_t i = 0; i < sResponse.aPropVal.__size; ++i) {
  225. hr = CopySOAPPropValToMAPIPropVal(lpProp, &sResponse.aPropVal.__ptr[i], lpProp, &converter);
  226. if (hr != hrSuccess)
  227. goto exit;
  228. mo->lstProperties.push_back(lpProp);
  229. }
  230. *lppsMapiObject = mo;
  231. exit:
  232. UnLockSoap();
  233. if (hr != hrSuccess && mo)
  234. FreeMapiObject(mo);
  235. if (lpProp)
  236. ECFreeBuffer(lpProp);
  237. return hr;
  238. }
  239. IECPropStorage* WSABPropStorage::GetServerStorage()
  240. {
  241. return &this->m_xECPropStorage;
  242. }
  243. HRESULT WSABPropStorage::LockSoap()
  244. {
  245. lpDataLock.lock();
  246. return erSuccess;
  247. }
  248. HRESULT WSABPropStorage::UnLockSoap()
  249. {
  250. // Clean up data create with soap_malloc
  251. if(lpCmd->soap) {
  252. soap_destroy(lpCmd->soap);
  253. soap_end(lpCmd->soap);
  254. }
  255. lpDataLock.unlock();
  256. return erSuccess;
  257. }
  258. // Called when the session ID has changed
  259. HRESULT WSABPropStorage::Reload(void *lpParam, ECSESSIONID sessionId) {
  260. static_cast<WSABPropStorage *>(lpParam)->ecSessionId = sessionId;
  261. return hrSuccess;
  262. }
  263. // Interface IECPropStorage
  264. DEF_ULONGMETHOD0(WSABPropStorage, ECPropStorage, AddRef, (void))
  265. DEF_ULONGMETHOD0(WSABPropStorage, ECPropStorage, Release, (void))
  266. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, QueryInterface, (REFIID, refiid), (void**, lppInterface))
  267. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrReadProps, (LPSPropTagArray *, lppPropTags), (ULONG *, cValues), (LPSPropValue *, lppValues))
  268. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrLoadProp, (ULONG, ulObjId), (ULONG, ulPropTag), (LPSPropValue *, lppsPropValue))
  269. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrWriteProps, (ULONG, cValues), (LPSPropValue, lpValues), (ULONG, ulFlags))
  270. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrDeleteProps, (const SPropTagArray *, lpsPropTagArray))
  271. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrSaveObject, (ULONG, ulFlags), (MAPIOBJECT *, lpsMapiObject))
  272. DEF_HRMETHOD0(WSABPropStorage, ECPropStorage, HrLoadObject, (MAPIOBJECT **, lppsMapiObject))
  273. IECPropStorage* WSABPropStorage::xECPropStorage::GetServerStorage()
  274. {
  275. METHOD_PROLOGUE_(WSABPropStorage, ECPropStorage);
  276. return pThis->GetServerStorage();
  277. }