WSTableView.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  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 "WSTableView.h"
  19. #include "Mem.h"
  20. #include <kopano/ECGuid.h>
  21. #include "SOAPUtils.h"
  22. #include "WSUtil.h"
  23. #include <kopano/charset/convert.h>
  24. /*
  25. * TableView operations for WS transport
  26. */
  27. #define START_SOAP_CALL retry:
  28. #define END_SOAP_CALL \
  29. if (er == KCERR_END_OF_SESSION && m_lpTransport->HrReLogon() == hrSuccess) \
  30. goto retry; \
  31. hr = kcerr_to_mapierr(er, MAPI_E_NOT_FOUND); \
  32. if(hr != hrSuccess) \
  33. goto exit;
  34. WSTableView::WSTableView(ULONG ulType, ULONG ulFlags, KCmd *lpCmd,
  35. std::recursive_mutex &data_lock, ECSESSIONID ecSessionId, ULONG cbEntryId,
  36. LPENTRYID lpEntryId, WSTransport *lpTransport, const char *szClassName) :
  37. ECUnknown(szClassName), lpDataLock(data_lock),
  38. m_lpTransport(lpTransport)
  39. {
  40. this->ulType = ulType;
  41. this->ulFlags = ulFlags;
  42. this->lpCmd = lpCmd;
  43. this->ecSessionId = ecSessionId;
  44. m_lpTransport->AddSessionReloadCallback(this, Reload, &m_ulSessionReloadCallback);
  45. CopyMAPIEntryIdToSOAPEntryId(cbEntryId, lpEntryId, &m_sEntryId);
  46. }
  47. WSTableView::~WSTableView()
  48. {
  49. m_lpTransport->RemoveSessionReloadCallback(m_ulSessionReloadCallback);
  50. // if the table was still open it will now be closed in the server too
  51. this->HrCloseTable();
  52. delete[] m_lpsPropTagArray;
  53. delete[] m_lpsSortOrderSet;
  54. FreeEntryId(&m_sEntryId, false);
  55. }
  56. HRESULT WSTableView::QueryInterface(REFIID refiid, void **lppInterface)
  57. {
  58. REGISTER_INTERFACE3(ECTableView, WSTableView, this);
  59. return MAPI_E_INTERFACE_NOT_SUPPORTED;
  60. }
  61. HRESULT WSTableView::HrQueryRows(ULONG ulRowCount, ULONG ulFlags, LPSRowSet *lppRowSet)
  62. {
  63. ECRESULT er = erSuccess;
  64. HRESULT hr = hrSuccess;
  65. struct tableQueryRowsResponse sResponse;
  66. LockSoap();
  67. hr = HrOpenTable();
  68. if(hr != erSuccess)
  69. goto exit;
  70. START_SOAP_CALL
  71. {
  72. if(SOAP_OK != lpCmd->ns__tableQueryRows(ecSessionId, ulTableId, ulRowCount, ulFlags, &sResponse))
  73. er = KCERR_NETWORK_ERROR;
  74. else
  75. er = sResponse.er;
  76. }
  77. END_SOAP_CALL
  78. hr = CopySOAPRowSetToMAPIRowSet(m_lpProvider, &sResponse.sRowSet, lppRowSet, this->ulType);
  79. exit:
  80. UnLockSoap();
  81. return hr;
  82. }
  83. HRESULT WSTableView::HrCloseTable()
  84. {
  85. ECRESULT er = erSuccess;
  86. HRESULT hr = hrSuccess;
  87. LockSoap();
  88. if(ulTableId == 0)
  89. goto exit;
  90. START_SOAP_CALL
  91. {
  92. if(SOAP_OK != lpCmd->ns__tableClose(ecSessionId, this->ulTableId, &er))
  93. er = KCERR_NETWORK_ERROR;
  94. if(er == KCERR_END_OF_SESSION)
  95. er = erSuccess; // Don't care about end of session
  96. }
  97. END_SOAP_CALL
  98. exit:
  99. UnLockSoap();
  100. return hr;
  101. }
  102. HRESULT WSTableView::HrSetColumns(const SPropTagArray *lpsPropTagArray)
  103. {
  104. ECRESULT er = erSuccess;
  105. HRESULT hr = hrSuccess;
  106. struct propTagArray sColumns;
  107. LPSPropTagArray lpsOld = m_lpsPropTagArray;
  108. // Save the columns so that we can restore the column state when reconnecting
  109. m_lpsPropTagArray = (LPSPropTagArray) new char[CbNewSPropTagArray(lpsPropTagArray->cValues)];
  110. memcpy(&m_lpsPropTagArray->aulPropTag, &lpsPropTagArray->aulPropTag, sizeof(ULONG) * lpsPropTagArray->cValues);
  111. m_lpsPropTagArray->cValues = lpsPropTagArray->cValues;
  112. sColumns.__ptr = (unsigned int *)&lpsPropTagArray->aulPropTag;
  113. sColumns.__size = lpsPropTagArray->cValues;
  114. LockSoap();
  115. hr = HrOpenTable();
  116. if(hr != erSuccess)
  117. goto exit;
  118. START_SOAP_CALL
  119. {
  120. if(SOAP_OK != lpCmd->ns__tableSetColumns(ecSessionId, ulTableId, &sColumns, &er))
  121. er = KCERR_NETWORK_ERROR;
  122. }
  123. END_SOAP_CALL
  124. exit:
  125. delete[] lpsOld;
  126. UnLockSoap();
  127. return hr;
  128. }
  129. HRESULT WSTableView::HrQueryColumns(ULONG ulFlags, LPSPropTagArray *lppsPropTags)
  130. {
  131. ECRESULT er = erSuccess;
  132. HRESULT hr = hrSuccess;
  133. struct tableQueryColumnsResponse sResponse;
  134. LPSPropTagArray lpsPropTags = NULL;
  135. LockSoap();
  136. hr = HrOpenTable();
  137. if(hr != erSuccess)
  138. goto exit;
  139. START_SOAP_CALL
  140. {
  141. if(SOAP_OK != lpCmd->ns__tableQueryColumns(ecSessionId, ulTableId, ulFlags, &sResponse))
  142. er = KCERR_NETWORK_ERROR;
  143. else
  144. er = sResponse.er;
  145. }
  146. END_SOAP_CALL
  147. hr = ECAllocateBuffer(CbNewSPropTagArray(sResponse.sPropTagArray.__size),(void **)&lpsPropTags);
  148. if(hr != hrSuccess)
  149. goto exit;
  150. for (gsoap_size_t i = 0; i < sResponse.sPropTagArray.__size; ++i)
  151. lpsPropTags->aulPropTag[i] = sResponse.sPropTagArray.__ptr[i];
  152. lpsPropTags->cValues = sResponse.sPropTagArray.__size;
  153. *lppsPropTags = lpsPropTags;
  154. exit:
  155. UnLockSoap();
  156. return hr;
  157. }
  158. HRESULT WSTableView::HrRestrict(const SRestriction *lpsRestriction)
  159. {
  160. ECRESULT er = erSuccess;
  161. HRESULT hr = hrSuccess;
  162. struct restrictTable *lpsRestrictTable = NULL;
  163. LockSoap();
  164. if(lpsRestriction) {
  165. hr = CopyMAPIRestrictionToSOAPRestriction(&lpsRestrictTable, lpsRestriction);
  166. if(hr != hrSuccess)
  167. goto exit;
  168. }
  169. hr = HrOpenTable();
  170. if(hr != erSuccess)
  171. goto exit;
  172. START_SOAP_CALL
  173. {
  174. if(SOAP_OK != lpCmd->ns__tableRestrict(ecSessionId, ulTableId, lpsRestrictTable, &er))
  175. er = KCERR_NETWORK_ERROR;
  176. }
  177. END_SOAP_CALL
  178. exit:
  179. UnLockSoap();
  180. if(lpsRestrictTable)
  181. FreeRestrictTable(lpsRestrictTable);
  182. return hr;
  183. }
  184. HRESULT WSTableView::HrSortTable(const SSortOrderSet *lpsSortOrderSet)
  185. {
  186. ECRESULT er = erSuccess;
  187. HRESULT hr = hrSuccess;
  188. sortOrderArray sSort;
  189. unsigned int i=0;
  190. LPSSortOrderSet lpOld = m_lpsSortOrderSet;
  191. // Remember sort order for reconnect
  192. m_lpsSortOrderSet = (LPSSortOrderSet)new char [CbSSortOrderSet(lpsSortOrderSet)];
  193. memcpy(m_lpsSortOrderSet, lpsSortOrderSet, CbSSortOrderSet(lpsSortOrderSet));
  194. sSort.__size = lpsSortOrderSet->cSorts;
  195. sSort.__ptr = s_alloc<sortOrder>(nullptr, lpsSortOrderSet->cSorts);
  196. for (i = 0; i < lpsSortOrderSet->cSorts; ++i) {
  197. sSort.__ptr[i].ulOrder = lpsSortOrderSet->aSort[i].ulOrder;
  198. sSort.__ptr[i].ulPropTag = lpsSortOrderSet->aSort[i].ulPropTag;
  199. }
  200. LockSoap();
  201. hr = HrOpenTable();
  202. if(hr != erSuccess)
  203. goto exit;
  204. START_SOAP_CALL
  205. {
  206. if(SOAP_OK != lpCmd->ns__tableSort(ecSessionId, ulTableId, &sSort, lpsSortOrderSet->cCategories, lpsSortOrderSet->cExpanded, &er))
  207. er = KCERR_NETWORK_ERROR;
  208. }
  209. END_SOAP_CALL
  210. exit:
  211. UnLockSoap();
  212. delete[] lpOld;
  213. s_free(nullptr, sSort.__ptr);
  214. return hr;
  215. }
  216. HRESULT WSTableView::HrOpenTable()
  217. {
  218. ECRESULT er = erSuccess;
  219. HRESULT hr = hrSuccess;
  220. struct tableOpenResponse sResponse;
  221. LockSoap();
  222. if(this->ulTableId != 0)
  223. goto exit;
  224. START_SOAP_CALL
  225. {
  226. if(SOAP_OK != lpCmd->ns__tableOpen(ecSessionId, m_sEntryId, m_ulTableType, ulType, this->ulFlags, &sResponse))
  227. er = KCERR_NETWORK_ERROR;
  228. else
  229. er = sResponse.er;
  230. }
  231. END_SOAP_CALL
  232. this->ulTableId = sResponse.ulTableId;
  233. exit:
  234. UnLockSoap();
  235. return hr;
  236. }
  237. HRESULT WSTableView::HrGetRowCount(ULONG *lpulRowCount, ULONG *lpulCurrentRow)
  238. {
  239. ECRESULT er = erSuccess;
  240. HRESULT hr = hrSuccess;
  241. struct tableGetRowCountResponse sResponse;
  242. LockSoap();
  243. hr = HrOpenTable();
  244. if(hr != erSuccess)
  245. goto exit;
  246. START_SOAP_CALL
  247. {
  248. if(SOAP_OK != lpCmd->ns__tableGetRowCount(ecSessionId, ulTableId, &sResponse))
  249. er = KCERR_NETWORK_ERROR;
  250. else
  251. er = sResponse.er;
  252. }
  253. END_SOAP_CALL
  254. *lpulRowCount = sResponse.ulCount;
  255. *lpulCurrentRow = sResponse.ulRow;
  256. exit:
  257. UnLockSoap();
  258. return hr;
  259. }
  260. HRESULT WSTableView::HrFindRow(const SRestriction *lpsRestriction,
  261. BOOKMARK bkOrigin, ULONG ulFlags)
  262. {
  263. ECRESULT er = erSuccess;
  264. HRESULT hr = hrSuccess;
  265. struct restrictTable *lpRestrict = NULL;
  266. LockSoap();
  267. er = CopyMAPIRestrictionToSOAPRestriction(&lpRestrict, lpsRestriction);
  268. if(er != erSuccess) {
  269. hr = MAPI_E_INVALID_PARAMETER;
  270. goto exit;
  271. }
  272. hr = HrOpenTable();
  273. if(hr != erSuccess)
  274. goto exit;
  275. START_SOAP_CALL
  276. {
  277. if(SOAP_OK != lpCmd->ns__tableFindRow(ecSessionId, ulTableId, (unsigned int)bkOrigin, ulFlags, lpRestrict, &er))
  278. er = KCERR_NETWORK_ERROR;
  279. }
  280. END_SOAP_CALL
  281. exit:
  282. UnLockSoap();
  283. if(lpRestrict)
  284. FreeRestrictTable(lpRestrict);
  285. return hr;
  286. }
  287. HRESULT WSTableView::HrSeekRow(BOOKMARK bkOrigin, LONG lRows, LONG *lplRowsSought)
  288. {
  289. ECRESULT er = erSuccess;
  290. HRESULT hr = hrSuccess;
  291. struct tableSeekRowResponse sResponse;
  292. LockSoap();
  293. hr = HrOpenTable();
  294. if(hr != erSuccess)
  295. goto exit;
  296. START_SOAP_CALL
  297. {
  298. if(SOAP_OK != lpCmd->ns__tableSeekRow(ecSessionId, ulTableId, (unsigned int)bkOrigin, lRows, &sResponse))
  299. er = KCERR_NETWORK_ERROR;
  300. else
  301. er = sResponse.er;
  302. }
  303. END_SOAP_CALL
  304. if(lplRowsSought)
  305. *lplRowsSought = sResponse.lRowsSought;
  306. exit:
  307. UnLockSoap();
  308. return hr;
  309. }
  310. HRESULT WSTableView::CreateBookmark(BOOKMARK* lpbkPosition)
  311. {
  312. ECRESULT er = erSuccess;
  313. HRESULT hr = hrSuccess;
  314. tableBookmarkResponse sResponse;
  315. LockSoap();
  316. hr = HrOpenTable();
  317. if(hr != erSuccess)
  318. goto exit;
  319. if(lpbkPosition == NULL) {
  320. hr = MAPI_E_INVALID_PARAMETER;
  321. goto exit;
  322. }
  323. START_SOAP_CALL
  324. {
  325. if(SOAP_OK != lpCmd->ns__tableCreateBookmark(ecSessionId, ulTableId, &sResponse))
  326. er = KCERR_NETWORK_ERROR;
  327. else
  328. er = sResponse.er;
  329. }
  330. END_SOAP_CALL
  331. *lpbkPosition = sResponse.ulbkPosition;
  332. exit:
  333. UnLockSoap();
  334. return hr;
  335. }
  336. HRESULT WSTableView::FreeBookmark(BOOKMARK bkPosition)
  337. {
  338. ECRESULT er = erSuccess;
  339. HRESULT hr = hrSuccess;
  340. LockSoap();
  341. hr = HrOpenTable();
  342. if(hr != erSuccess)
  343. goto exit;
  344. START_SOAP_CALL
  345. {
  346. if(SOAP_OK != lpCmd->ns__tableFreeBookmark(ecSessionId, ulTableId, bkPosition, &er))
  347. er = KCERR_NETWORK_ERROR;
  348. }
  349. END_SOAP_CALL
  350. exit:
  351. UnLockSoap();
  352. return hr;
  353. }
  354. HRESULT WSTableView::HrExpandRow(ULONG cbInstanceKey, LPBYTE pbInstanceKey, ULONG ulRowCount, ULONG ulFlags, LPSRowSet * lppRows, ULONG *lpulMoreRows)
  355. {
  356. HRESULT hr = hrSuccess;
  357. ECRESULT er = erSuccess;
  358. xsd__base64Binary sInstanceKey;
  359. struct tableExpandRowResponse sResponse;
  360. LockSoap();
  361. hr = HrOpenTable();
  362. if(hr != erSuccess)
  363. goto exit;
  364. sInstanceKey.__size = cbInstanceKey;
  365. sInstanceKey.__ptr = pbInstanceKey;
  366. START_SOAP_CALL
  367. {
  368. if(SOAP_OK != lpCmd->ns__tableExpandRow(ecSessionId, this->ulTableId, sInstanceKey, ulRowCount, ulFlags, &sResponse))
  369. er = KCERR_NETWORK_ERROR;
  370. else
  371. er = sResponse.er;
  372. }
  373. END_SOAP_CALL
  374. if(lppRows)
  375. hr = CopySOAPRowSetToMAPIRowSet(m_lpProvider, &sResponse.rowSet, lppRows, this->ulType);
  376. if(lpulMoreRows)
  377. *lpulMoreRows = sResponse.ulMoreRows;
  378. exit:
  379. UnLockSoap();
  380. return hr;
  381. }
  382. HRESULT WSTableView::HrCollapseRow(ULONG cbInstanceKey, LPBYTE pbInstanceKey, ULONG ulFlags, ULONG *lpulRowCount)
  383. {
  384. HRESULT hr = hrSuccess;
  385. ECRESULT er = erSuccess;
  386. xsd__base64Binary sInstanceKey;
  387. struct tableCollapseRowResponse sResponse;
  388. LockSoap();
  389. hr = HrOpenTable();
  390. if(hr != erSuccess)
  391. goto exit;
  392. sInstanceKey.__size = cbInstanceKey;
  393. sInstanceKey.__ptr = pbInstanceKey;
  394. START_SOAP_CALL
  395. {
  396. if(SOAP_OK != lpCmd->ns__tableCollapseRow(ecSessionId, this->ulTableId, sInstanceKey, ulFlags, &sResponse))
  397. er = KCERR_NETWORK_ERROR;
  398. else
  399. er = sResponse.er;
  400. }
  401. END_SOAP_CALL
  402. *lpulRowCount = sResponse.ulRows;
  403. exit:
  404. UnLockSoap();
  405. return hr;
  406. }
  407. HRESULT WSTableView::HrGetCollapseState(BYTE **lppCollapseState, ULONG *lpcbCollapseState, BYTE *lpInstanceKey, ULONG cbInstanceKey)
  408. {
  409. HRESULT hr = hrSuccess;
  410. ECRESULT er = erSuccess;
  411. struct tableGetCollapseStateResponse sResponse;
  412. struct xsd__base64Binary sBookmark;
  413. sBookmark.__size = cbInstanceKey;
  414. sBookmark.__ptr = lpInstanceKey;
  415. LockSoap();
  416. hr = HrOpenTable();
  417. if(hr != erSuccess)
  418. goto exit;
  419. START_SOAP_CALL
  420. {
  421. if(SOAP_OK != lpCmd->ns__tableGetCollapseState(ecSessionId, this->ulTableId, sBookmark, &sResponse))
  422. er = KCERR_NETWORK_ERROR;
  423. else
  424. er = sResponse.er;
  425. }
  426. END_SOAP_CALL
  427. if ((hr = MAPIAllocateBuffer(sResponse.sCollapseState.__size, (void **)lppCollapseState)) != hrSuccess)
  428. goto exit;
  429. memcpy(*lppCollapseState, sResponse.sCollapseState.__ptr, sResponse.sCollapseState.__size);
  430. *lpcbCollapseState = sResponse.sCollapseState.__size;
  431. exit:
  432. UnLockSoap();
  433. return hr;
  434. }
  435. HRESULT WSTableView::HrSetCollapseState(BYTE *lpCollapseState, ULONG cbCollapseState, BOOKMARK *lpbkPosition)
  436. {
  437. HRESULT hr = hrSuccess;
  438. ECRESULT er = erSuccess;
  439. xsd__base64Binary sState;
  440. struct tableSetCollapseStateResponse sResponse;
  441. sState.__ptr = lpCollapseState;
  442. sState.__size = cbCollapseState;
  443. LockSoap();
  444. hr = HrOpenTable();
  445. if(hr != erSuccess)
  446. goto exit;
  447. START_SOAP_CALL
  448. {
  449. if(SOAP_OK != lpCmd->ns__tableSetCollapseState(ecSessionId, this->ulTableId, sState, &sResponse))
  450. er = KCERR_NETWORK_ERROR;
  451. else
  452. er = sResponse.er;
  453. }
  454. END_SOAP_CALL
  455. hr = kcerr_to_mapierr(er);
  456. if(hr != hrSuccess)
  457. goto exit;
  458. if(lpbkPosition)
  459. *lpbkPosition = sResponse.ulBookmark;
  460. exit:
  461. UnLockSoap();
  462. return hr;
  463. }
  464. HRESULT WSTableView::HrMulti(ULONG ulDeferredFlags, LPSPropTagArray lpsPropTagArray, LPSRestriction lpsRestriction, LPSSortOrderSet lpsSortOrderSet, ULONG ulRowCount, ULONG ulFlags, LPSRowSet *lppRowSet)
  465. {
  466. HRESULT hr = hrSuccess;
  467. ECRESULT er = erSuccess;
  468. struct propTagArray sColumns{__gszeroinit};
  469. struct tableMultiRequest sRequest{__gszeroinit};
  470. struct tableMultiResponse sResponse{__gszeroinit};
  471. struct restrictTable *lpsRestrictTable = NULL;
  472. struct tableQueryRowsRequest sQueryRows{__gszeroinit};
  473. struct tableSortRequest sSort{__gszeroinit};
  474. struct tableOpenRequest sOpen{__gszeroinit};
  475. unsigned int i;
  476. memset(&sRequest, 0, sizeof(sRequest));
  477. if(ulTableId == 0) {
  478. sOpen.sEntryId = m_sEntryId;
  479. sOpen.ulTableType = m_ulTableType;
  480. sOpen.ulType = this->ulType;
  481. sOpen.ulFlags = this->ulFlags;
  482. sRequest.lpOpen = &sOpen;
  483. } else {
  484. sRequest.ulTableId = ulTableId;
  485. }
  486. sRequest.ulFlags = ulDeferredFlags;
  487. if(lpsPropTagArray) {
  488. // Save the proptag set for if we need to reload
  489. delete[] m_lpsPropTagArray;
  490. m_lpsPropTagArray = (LPSPropTagArray) new char[CbNewSPropTagArray(lpsPropTagArray->cValues)];
  491. memcpy(&m_lpsPropTagArray->aulPropTag, &lpsPropTagArray->aulPropTag, sizeof(ULONG) * lpsPropTagArray->cValues);
  492. m_lpsPropTagArray->cValues = lpsPropTagArray->cValues;
  493. // Copy the setcolumns for the call
  494. sColumns.__size = lpsPropTagArray->cValues;
  495. sColumns.__ptr = (unsigned int *)&lpsPropTagArray->aulPropTag; // Don't copy, just reference their data
  496. sRequest.lpSetColumns = &sColumns;
  497. }
  498. if(lpsRestriction) {
  499. hr = CopyMAPIRestrictionToSOAPRestriction(&lpsRestrictTable, lpsRestriction);
  500. if(hr != hrSuccess)
  501. goto exit;
  502. sRequest.lpRestrict = lpsRestrictTable;
  503. }
  504. if(lpsSortOrderSet) {
  505. // Remember sort order for reconnect
  506. delete[] m_lpsSortOrderSet;
  507. m_lpsSortOrderSet = (LPSSortOrderSet)new char [CbSSortOrderSet(lpsSortOrderSet)];
  508. memcpy(m_lpsSortOrderSet, lpsSortOrderSet, CbSSortOrderSet(lpsSortOrderSet));
  509. // Copy sort order for call
  510. sSort.sSortOrder.__size = lpsSortOrderSet->cSorts;
  511. sSort.sSortOrder.__ptr = s_alloc<sortOrder>(nullptr, lpsSortOrderSet->cSorts);
  512. for (i = 0; i < lpsSortOrderSet->cSorts; ++i) {
  513. sSort.sSortOrder.__ptr[i].ulOrder = lpsSortOrderSet->aSort[i].ulOrder;
  514. sSort.sSortOrder.__ptr[i].ulPropTag = lpsSortOrderSet->aSort[i].ulPropTag;
  515. }
  516. sSort.ulExpanded = lpsSortOrderSet->cExpanded;
  517. sSort.ulCategories = lpsSortOrderSet->cCategories;
  518. sRequest.lpSort = &sSort;
  519. }
  520. if(ulRowCount > 0) {
  521. sQueryRows.ulCount = ulRowCount;
  522. sQueryRows.ulFlags = ulFlags;
  523. sRequest.lpQueryRows = &sQueryRows;
  524. }
  525. LockSoap();
  526. START_SOAP_CALL
  527. {
  528. if(SOAP_OK != lpCmd->ns__tableMulti(ecSessionId, sRequest, &sResponse))
  529. er = KCERR_NETWORK_ERROR;
  530. else
  531. er = sResponse.er;
  532. }
  533. END_SOAP_CALL
  534. if (sResponse.ulTableId != 0)
  535. ulTableId = sResponse.ulTableId;
  536. if (lppRowSet)
  537. hr = CopySOAPRowSetToMAPIRowSet(m_lpProvider, &sResponse.sRowSet, lppRowSet, this->ulType);
  538. exit:
  539. UnLockSoap();
  540. s_free(nullptr, sSort.sSortOrder.__ptr);
  541. if(lpsRestrictTable)
  542. FreeRestrictTable(lpsRestrictTable);
  543. return hr;
  544. }
  545. //FIXME: one lock/unlock function
  546. HRESULT WSTableView::LockSoap()
  547. {
  548. lpDataLock.lock();
  549. return erSuccess;
  550. }
  551. HRESULT WSTableView::UnLockSoap()
  552. {
  553. //Clean up data create with soap_malloc
  554. if(lpCmd->soap) {
  555. soap_destroy(lpCmd->soap);
  556. soap_end(lpCmd->soap);
  557. }
  558. lpDataLock.unlock();
  559. return erSuccess;
  560. }
  561. HRESULT WSTableView::Reload(void *lpParam, ECSESSIONID sessionId)
  562. {
  563. auto lpThis = static_cast<WSTableView *>(lpParam);
  564. lpThis->ecSessionId = sessionId;
  565. // Since we've switched sessions, our table is no longer open or valid
  566. lpThis->ulTableId = 0;
  567. // Restore state
  568. if (lpThis->m_lpsPropTagArray != nullptr)
  569. // ignore error
  570. lpThis->HrSetColumns(lpThis->m_lpsPropTagArray);
  571. if (lpThis->m_lpsSortOrderSet != nullptr)
  572. // ignore error
  573. lpThis->HrSortTable(lpThis->m_lpsSortOrderSet);
  574. // Call the reload callback if necessary
  575. if(lpThis->m_lpCallback)
  576. lpThis->m_lpCallback(lpThis->m_lpParam);
  577. return hrSuccess;
  578. }
  579. HRESULT WSTableView::SetReloadCallback(RELOADCALLBACK callback, void *lpParam)
  580. {
  581. this->m_lpCallback = callback;
  582. this->m_lpParam = lpParam;
  583. return hrSuccess;
  584. }
  585. // WSTableOutGoingQueue view
  586. WSTableOutGoingQueue::WSTableOutGoingQueue(KCmd *lpCmd,
  587. std::recursive_mutex &lpDataLock, ECSESSIONID ecSessionId, ULONG cbEntryId,
  588. LPENTRYID lpEntryId, ECMsgStore *lpMsgStore, WSTransport *lpTransport) :
  589. WSStoreTableView(MAPI_MESSAGE, 0, lpCmd, lpDataLock, ecSessionId,
  590. cbEntryId, lpEntryId, lpMsgStore, lpTransport)
  591. {
  592. }
  593. HRESULT WSTableOutGoingQueue::Create(KCmd *lpCmd,
  594. std::recursive_mutex &lpDataLock, ECSESSIONID ecSessionId, ULONG cbEntryId,
  595. LPENTRYID lpEntryId, ECMsgStore *lpMsgStore, WSTransport *lpTransport,
  596. WSTableOutGoingQueue **lppTableOutGoingQueue)
  597. {
  598. HRESULT hr = hrSuccess;
  599. auto lpTableOutGoingQueue = new(std::nothrow) WSTableOutGoingQueue(lpCmd,
  600. lpDataLock, ecSessionId, cbEntryId,
  601. lpEntryId, lpMsgStore, lpTransport);
  602. if (lpTableOutGoingQueue == nullptr)
  603. return MAPI_E_NOT_ENOUGH_MEMORY;
  604. hr = lpTableOutGoingQueue->QueryInterface(IID_ECTableOutGoingQueue, (void **) lppTableOutGoingQueue);
  605. if(hr != hrSuccess)
  606. delete lpTableOutGoingQueue;
  607. return hr;
  608. }
  609. HRESULT WSTableOutGoingQueue::QueryInterface(REFIID refiid, void **lppInterface)
  610. {
  611. REGISTER_INTERFACE3(ECTableOutGoingQueue, WSTableOutGoingQueue, this);
  612. return MAPI_E_INTERFACE_NOT_SUPPORTED;
  613. }
  614. HRESULT WSTableOutGoingQueue::HrOpenTable()
  615. {
  616. ECRESULT er = erSuccess;
  617. HRESULT hr = hrSuccess;
  618. struct tableOpenResponse sResponse;
  619. LockSoap();
  620. if(this->ulTableId != 0)
  621. goto exit;
  622. START_SOAP_CALL
  623. {
  624. //m_sEntryId is the id of a store
  625. if(SOAP_OK != lpCmd->ns__tableOpen(ecSessionId, m_sEntryId, TABLETYPE_SPOOLER, 0, this->ulFlags, &sResponse))
  626. er = KCERR_NETWORK_ERROR;
  627. else
  628. er = sResponse.er;
  629. }
  630. END_SOAP_CALL
  631. this->ulTableId = sResponse.ulTableId;
  632. exit:
  633. UnLockSoap();
  634. return hr;
  635. }