ECMAPIFolder.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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 <new>
  18. #include <kopano/platform.h>
  19. #include <kopano/ECInterfaceDefs.h>
  20. #include <kopano/mapi_ptr.h>
  21. #include <kopano/memory.hpp>
  22. #include "kcore.hpp"
  23. #include "ics.h"
  24. #include "pcutil.hpp"
  25. #include "ECMessage.h"
  26. #include "ECMAPIFolder.h"
  27. #include "ECMAPITable.h"
  28. #include "ECExchangeModifyTable.h"
  29. #include "ECExchangeImportHierarchyChanges.h"
  30. #include "ECExchangeImportContentsChanges.h"
  31. #include "ECExchangeExportChanges.h"
  32. #include "WSTransport.h"
  33. #include "WSMessageStreamExporter.h"
  34. #include "WSMessageStreamImporter.h"
  35. #include "Mem.h"
  36. #include <kopano/ECGuid.h>
  37. #include <edkguid.h>
  38. #include <kopano/Util.h>
  39. #include "ClientUtil.h"
  40. #include <kopano/ECDebug.h>
  41. #include <kopano/mapi_ptr.h>
  42. #include <edkmdb.h>
  43. #include <kopano/mapiext.h>
  44. #include <mapiutil.h>
  45. #include <cstdio>
  46. #include <kopano/stringutil.h>
  47. #include <kopano/charset/convstring.h>
  48. using namespace KCHL;
  49. static LONG __stdcall AdviseECFolderCallback(void *lpContext, ULONG cNotif,
  50. LPNOTIFICATION lpNotif)
  51. {
  52. if (lpContext == NULL)
  53. return S_OK;
  54. static_cast<ECMAPIFolder *>(lpContext)->m_bReload = TRUE;
  55. return S_OK;
  56. }
  57. ECMAPIFolder::ECMAPIFolder(ECMsgStore *lpMsgStore, BOOL fModify,
  58. WSMAPIFolderOps *lpFolderOps, const char *szClassName) :
  59. ECMAPIContainer(lpMsgStore, MAPI_FOLDER, fModify, szClassName)
  60. {
  61. // Folder counters
  62. HrAddPropHandlers(PR_ASSOC_CONTENT_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  63. HrAddPropHandlers(PR_CONTENT_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  64. HrAddPropHandlers(PR_CONTENT_UNREAD, GetPropHandler, DefaultSetPropComputed, (void *)this);
  65. HrAddPropHandlers(PR_SUBFOLDERS, GetPropHandler, DefaultSetPropComputed, (void *)this);
  66. HrAddPropHandlers(PR_FOLDER_CHILD_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  67. HrAddPropHandlers(PR_DELETED_MSG_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  68. HrAddPropHandlers(PR_DELETED_FOLDER_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  69. HrAddPropHandlers(PR_DELETED_ASSOC_MSG_COUNT, GetPropHandler, DefaultSetPropComputed, (void *)this);
  70. HrAddPropHandlers(PR_CONTAINER_CONTENTS, GetPropHandler, DefaultSetPropIgnore, (void *)this, FALSE, FALSE);
  71. HrAddPropHandlers(PR_FOLDER_ASSOCIATED_CONTENTS,GetPropHandler, DefaultSetPropIgnore, (void *)this, FALSE, FALSE);
  72. HrAddPropHandlers(PR_CONTAINER_HIERARCHY, GetPropHandler, DefaultSetPropIgnore, (void *)this, FALSE, FALSE);
  73. HrAddPropHandlers(PR_ACCESS, GetPropHandler, DefaultSetPropComputed, (void *)this);
  74. HrAddPropHandlers(PR_RIGHTS, DefaultMAPIGetProp, DefaultSetPropComputed, (void*) this);
  75. HrAddPropHandlers(PR_MESSAGE_SIZE, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
  76. HrAddPropHandlers(PR_FOLDER_TYPE, DefaultMAPIGetProp, DefaultSetPropComputed, (void*) this);
  77. // ACLs are only offline
  78. HrAddPropHandlers(PR_ACL_DATA, GetPropHandler, SetPropHandler, (void*)this);
  79. this->lpFolderOps = lpFolderOps;
  80. if (lpFolderOps)
  81. lpFolderOps->AddRef();
  82. this->isTransactedObject = FALSE;
  83. }
  84. ECMAPIFolder::~ECMAPIFolder()
  85. {
  86. if(lpFolderOps)
  87. lpFolderOps->Release();
  88. if (m_ulConnection > 0)
  89. GetMsgStore()->m_lpNotifyClient->UnRegisterAdvise(m_ulConnection);
  90. if (m_lpFolderAdviseSink)
  91. m_lpFolderAdviseSink->Release();
  92. }
  93. HRESULT ECMAPIFolder::Create(ECMsgStore *lpMsgStore, BOOL fModify, WSMAPIFolderOps *lpFolderOps, ECMAPIFolder **lppECMAPIFolder)
  94. {
  95. HRESULT hr = hrSuccess;
  96. auto lpMAPIFolder = new(std::nothrow) ECMAPIFolder(lpMsgStore, fModify, lpFolderOps, "IMAPIFolder");
  97. if (lpMAPIFolder == nullptr)
  98. return MAPI_E_NOT_ENOUGH_MEMORY;
  99. hr = lpMAPIFolder->QueryInterface(IID_ECMAPIFolder, (void **)lppECMAPIFolder);
  100. if(hr != hrSuccess)
  101. delete lpMAPIFolder;
  102. return hr;
  103. }
  104. HRESULT ECMAPIFolder::GetPropHandler(ULONG ulPropTag, void* lpProvider, ULONG ulFlags, LPSPropValue lpsPropValue, void *lpParam, void *lpBase)
  105. {
  106. HRESULT hr = hrSuccess;
  107. auto lpFolder = static_cast<ECMAPIFolder *>(lpParam);
  108. switch(ulPropTag) {
  109. case PR_CONTENT_COUNT:
  110. case PR_CONTENT_UNREAD:
  111. case PR_DELETED_MSG_COUNT:
  112. case PR_DELETED_FOLDER_COUNT:
  113. case PR_DELETED_ASSOC_MSG_COUNT:
  114. case PR_ASSOC_CONTENT_COUNT:
  115. case PR_FOLDER_CHILD_COUNT:
  116. if(lpFolder->HrGetRealProp(ulPropTag, ulFlags, lpBase, lpsPropValue) != hrSuccess)
  117. {
  118. // Don't return an error here: outlook is relying on PR_CONTENT_COUNT, etc being available at all times. Especially the
  119. // exit routine (which checks to see how many items are left in the outbox) will crash if PR_CONTENT_COUNT is MAPI_E_NOT_FOUND
  120. lpsPropValue->ulPropTag = ulPropTag;
  121. lpsPropValue->Value.ul = 0;
  122. }
  123. break;
  124. case PR_SUBFOLDERS:
  125. if(lpFolder->HrGetRealProp(ulPropTag, ulFlags, lpBase, lpsPropValue) != hrSuccess)
  126. {
  127. lpsPropValue->ulPropTag = PR_SUBFOLDERS;
  128. lpsPropValue->Value.b = FALSE;
  129. }
  130. break;
  131. case PR_ACCESS:
  132. if(lpFolder->HrGetRealProp(PR_ACCESS, ulFlags, lpBase, lpsPropValue) != hrSuccess)
  133. {
  134. lpsPropValue->ulPropTag = PR_ACCESS;
  135. lpsPropValue->Value.l = 0; // FIXME: tijdelijk voor test
  136. }
  137. break;
  138. case PR_CONTAINER_CONTENTS:
  139. case PR_FOLDER_ASSOCIATED_CONTENTS:
  140. case PR_CONTAINER_HIERARCHY:
  141. lpsPropValue->ulPropTag = ulPropTag;
  142. lpsPropValue->Value.x = 1;
  143. break;
  144. case PR_ACL_DATA:
  145. hr = lpFolder->GetSerializedACLData(lpBase, lpsPropValue);
  146. if (hr == hrSuccess)
  147. lpsPropValue->ulPropTag = PR_ACL_DATA;
  148. else {
  149. lpsPropValue->ulPropTag = CHANGE_PROP_TYPE(PR_ACL_DATA, PT_ERROR);
  150. lpsPropValue->Value.err = hr;
  151. }
  152. break;
  153. default:
  154. hr = MAPI_E_NOT_FOUND;
  155. break;
  156. }
  157. return hr;
  158. }
  159. HRESULT ECMAPIFolder::SetPropHandler(ULONG ulPropTag, void *lpProvider,
  160. const SPropValue *lpsPropValue, void *lpParam)
  161. {
  162. if (ulPropTag != PR_ACL_DATA)
  163. return MAPI_E_NOT_FOUND;
  164. return static_cast<ECMAPIFolder *>(lpParam)->SetSerializedACLData(lpsPropValue);
  165. }
  166. // This is similar to GetPropHandler, but works is a static function, and therefore cannot access
  167. // an open ECMAPIFolder object. (The folder is most probably also not open, so ...
  168. HRESULT ECMAPIFolder::TableRowGetProp(void* lpProvider, struct propVal *lpsPropValSrc, LPSPropValue lpsPropValDst, void **lpBase, ULONG ulType) {
  169. HRESULT hr = hrSuccess;
  170. switch(lpsPropValSrc->ulPropTag) {
  171. case PROP_TAG(PT_ERROR,PROP_ID(PR_DISPLAY_TYPE)):
  172. lpsPropValDst->Value.l = DT_FOLDER;
  173. lpsPropValDst->ulPropTag = PR_DISPLAY_TYPE;
  174. break;
  175. default:
  176. hr = MAPI_E_NOT_FOUND;
  177. }
  178. return hr;
  179. }
  180. HRESULT ECMAPIFolder::QueryInterface(REFIID refiid, void **lppInterface)
  181. {
  182. REGISTER_INTERFACE2(ECMAPIFolder, this);
  183. REGISTER_INTERFACE2(ECMAPIContainer, this);
  184. REGISTER_INTERFACE2(ECMAPIProp, this);
  185. REGISTER_INTERFACE2(ECUnknown, this);
  186. REGISTER_INTERFACE2(IMAPIFolder, &this->m_xMAPIFolder);
  187. REGISTER_INTERFACE2(IMAPIContainer, &this->m_xMAPIFolder);
  188. REGISTER_INTERFACE2(IMAPIProp, &this->m_xMAPIFolder);
  189. REGISTER_INTERFACE2(IUnknown, &this->m_xMAPIFolder);
  190. REGISTER_INTERFACE2(IFolderSupport, &this->m_xFolderSupport);
  191. REGISTER_INTERFACE2(IECSecurity, &this->m_xECSecurity);
  192. REGISTER_INTERFACE3(ISelectUnicode, IUnknown, &this->m_xUnknown);
  193. return MAPI_E_INTERFACE_NOT_SUPPORTED;
  194. }
  195. HRESULT ECMAPIFolder::HrSetPropStorage(IECPropStorage *lpStorage, BOOL fLoadProps)
  196. {
  197. HRESULT hr = hrSuccess;
  198. ULONG ulEventMask = fnevObjectModified | fnevObjectDeleted | fnevObjectMoved | fnevObjectCreated;
  199. object_ptr<WSMAPIPropStorage> lpMAPIPropStorage;
  200. ULONG cbEntryId;
  201. LPENTRYID lpEntryId = NULL;
  202. hr = HrAllocAdviseSink(AdviseECFolderCallback, this, &m_lpFolderAdviseSink);
  203. if (hr != hrSuccess)
  204. return hr;
  205. hr = lpStorage->QueryInterface(IID_WSMAPIPropStorage, &~lpMAPIPropStorage);
  206. if (hr != hrSuccess)
  207. return hr;
  208. hr = lpMAPIPropStorage->GetEntryIDByRef(&cbEntryId, &lpEntryId);
  209. if (hr != hrSuccess)
  210. return hr;
  211. hr = GetMsgStore()->InternalAdvise(cbEntryId, lpEntryId, ulEventMask, m_lpFolderAdviseSink, &m_ulConnection);
  212. if (hr == MAPI_E_NO_SUPPORT)
  213. hr = hrSuccess; // there is no spoon
  214. else if (hr != hrSuccess)
  215. return hr;
  216. else
  217. lpMAPIPropStorage->RegisterAdvise(ulEventMask, m_ulConnection);
  218. return ECGenericProp::HrSetPropStorage(lpStorage, fLoadProps);
  219. }
  220. HRESULT ECMAPIFolder::SetEntryId(ULONG cbEntryId, LPENTRYID lpEntryId)
  221. {
  222. return ECGenericProp::SetEntryId(cbEntryId, lpEntryId);
  223. }
  224. HRESULT ECMAPIFolder::OpenProperty(ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN *lppUnk)
  225. {
  226. HRESULT hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
  227. SPropValuePtr ptrSK, ptrDisplay;
  228. if (lpiid == NULL)
  229. return MAPI_E_INVALID_PARAMETER;
  230. if(ulPropTag == PR_CONTAINER_CONTENTS) {
  231. if (*lpiid == IID_IMAPITable)
  232. hr = GetContentsTable(ulInterfaceOptions, (LPMAPITABLE*)lppUnk);
  233. } else if(ulPropTag == PR_FOLDER_ASSOCIATED_CONTENTS) {
  234. if (*lpiid == IID_IMAPITable)
  235. hr = GetContentsTable( (ulInterfaceOptions|MAPI_ASSOCIATED), (LPMAPITABLE*)lppUnk);
  236. } else if(ulPropTag == PR_CONTAINER_HIERARCHY) {
  237. if(*lpiid == IID_IMAPITable)
  238. hr = GetHierarchyTable(ulInterfaceOptions, (LPMAPITABLE*)lppUnk);
  239. } else if(ulPropTag == PR_RULES_TABLE) {
  240. if(*lpiid == IID_IExchangeModifyTable)
  241. hr = ECExchangeModifyTable::CreateRulesTable(this, ulInterfaceOptions, (LPEXCHANGEMODIFYTABLE*)lppUnk);
  242. } else if(ulPropTag == PR_ACL_TABLE) {
  243. if(*lpiid == IID_IExchangeModifyTable)
  244. hr = ECExchangeModifyTable::CreateACLTable(this, ulInterfaceOptions, (LPEXCHANGEMODIFYTABLE*)lppUnk);
  245. } else if(ulPropTag == PR_COLLECTOR) {
  246. if(*lpiid == IID_IExchangeImportHierarchyChanges)
  247. hr = ECExchangeImportHierarchyChanges::Create(this, (LPEXCHANGEIMPORTHIERARCHYCHANGES*)lppUnk);
  248. else if(*lpiid == IID_IExchangeImportContentsChanges)
  249. hr = ECExchangeImportContentsChanges::Create(this, (LPEXCHANGEIMPORTCONTENTSCHANGES*)lppUnk);
  250. } else if(ulPropTag == PR_HIERARCHY_SYNCHRONIZER) {
  251. hr = HrGetOneProp(&m_xMAPIProp, PR_SOURCE_KEY, &~ptrSK);
  252. if(hr != hrSuccess)
  253. return hr;
  254. HrGetOneProp(&m_xMAPIProp, PR_DISPLAY_NAME_W, &~ptrDisplay); // ignore error
  255. hr = ECExchangeExportChanges::Create(this->GetMsgStore(), *lpiid, std::string((const char*)ptrSK->Value.bin.lpb, ptrSK->Value.bin.cb), !ptrDisplay ? L"" : ptrDisplay->Value.lpszW, ICS_SYNC_HIERARCHY, (LPEXCHANGEEXPORTCHANGES*) lppUnk);
  256. } else if(ulPropTag == PR_CONTENTS_SYNCHRONIZER) {
  257. hr = HrGetOneProp(&m_xMAPIProp, PR_SOURCE_KEY, &~ptrSK);
  258. if(hr != hrSuccess)
  259. return hr;
  260. HrGetOneProp(&m_xMAPIProp, PR_DISPLAY_NAME, &~ptrDisplay); // ignore error
  261. hr = ECExchangeExportChanges::Create(this->GetMsgStore(), *lpiid, std::string((const char*)ptrSK->Value.bin.lpb, ptrSK->Value.bin.cb), !ptrDisplay ? L"" : ptrDisplay->Value.lpszW, ICS_SYNC_CONTENTS, (LPEXCHANGEEXPORTCHANGES*) lppUnk);
  262. } else {
  263. hr = ECMAPIProp::OpenProperty(ulPropTag, lpiid, ulInterfaceOptions, ulFlags, lppUnk);
  264. }
  265. return hr;
  266. }
  267. HRESULT ECMAPIFolder::CopyTo(ULONG ciidExclude, LPCIID rgiidExclude,
  268. const SPropTagArray *lpExcludeProps, ULONG ulUIParam,
  269. LPMAPIPROGRESS lpProgress, LPCIID lpInterface, void *lpDestObj,
  270. ULONG ulFlags, SPropProblemArray **lppProblems)
  271. {
  272. return Util::DoCopyTo(&IID_IMAPIFolder, &this->m_xMAPIFolder, ciidExclude, rgiidExclude, lpExcludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
  273. }
  274. HRESULT ECMAPIFolder::CopyProps(const SPropTagArray *lpIncludeProps,
  275. ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface,
  276. void *lpDestObj, ULONG ulFlags, SPropProblemArray **lppProblems)
  277. {
  278. return Util::DoCopyProps(&IID_IMAPIFolder, &this->m_xMAPIFolder, lpIncludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
  279. }
  280. HRESULT ECMAPIFolder::SetProps(ULONG cValues, const SPropValue *lpPropArray,
  281. SPropProblemArray **lppProblems)
  282. {
  283. HRESULT hr;
  284. hr = ECMAPIContainer::SetProps(cValues, lpPropArray, lppProblems);
  285. if (hr != hrSuccess)
  286. return hr;
  287. return ECMAPIContainer::SaveChanges(KEEP_OPEN_READWRITE);
  288. }
  289. HRESULT ECMAPIFolder::DeleteProps(const SPropTagArray *lpPropTagArray,
  290. SPropProblemArray **lppProblems)
  291. {
  292. HRESULT hr;
  293. hr = ECMAPIContainer::DeleteProps(lpPropTagArray, lppProblems);
  294. if (hr != hrSuccess)
  295. return hr;
  296. return ECMAPIContainer::SaveChanges(KEEP_OPEN_READWRITE);
  297. }
  298. HRESULT ECMAPIFolder::SaveChanges(ULONG ulFlags)
  299. {
  300. return hrSuccess;
  301. }
  302. HRESULT ECMAPIFolder::SetSearchCriteria(LPSRestriction lpRestriction, LPENTRYLIST lpContainerList, ULONG ulSearchFlags)
  303. {
  304. if (lpFolderOps == NULL)
  305. return MAPI_E_NO_SUPPORT;
  306. return lpFolderOps->HrSetSearchCriteria(lpContainerList, lpRestriction, ulSearchFlags);
  307. }
  308. HRESULT ECMAPIFolder::GetSearchCriteria(ULONG ulFlags, LPSRestriction *lppRestriction, LPENTRYLIST *lppContainerList, ULONG *lpulSearchState)
  309. {
  310. if (lpFolderOps == NULL)
  311. return MAPI_E_NO_SUPPORT;
  312. // FIXME ulFlags ignore
  313. return lpFolderOps->HrGetSearchCriteria(lppContainerList, lppRestriction, lpulSearchState);
  314. }
  315. HRESULT ECMAPIFolder::CreateMessage(LPCIID lpInterface, ULONG ulFlags, LPMESSAGE *lppMessage)
  316. {
  317. return CreateMessageWithEntryID(lpInterface, ulFlags, 0, NULL, lppMessage);
  318. }
  319. HRESULT ECMAPIFolder::CreateMessageWithEntryID(LPCIID lpInterface, ULONG ulFlags, ULONG cbEntryID, LPENTRYID lpEntryID, LPMESSAGE *lppMessage)
  320. {
  321. HRESULT hr = hrSuccess;
  322. object_ptr<ECMessage> lpMessage;
  323. ecmem_ptr<MAPIUID> lpMapiUID;
  324. ULONG cbNewEntryId = 0;
  325. ecmem_ptr<ENTRYID> lpNewEntryId;
  326. SPropValue sPropValue[3];
  327. object_ptr<IECPropStorage> lpStorage;
  328. if (!fModify)
  329. return MAPI_E_NO_ACCESS;
  330. hr = ECMessage::Create(this->GetMsgStore(), TRUE, TRUE, ulFlags & MAPI_ASSOCIATED, FALSE, nullptr, &~lpMessage);
  331. if(hr != hrSuccess)
  332. return hr;
  333. if(cbEntryID == 0 || lpEntryID == NULL || HrCompareEntryIdWithStoreGuid(cbEntryID, lpEntryID, &this->GetMsgStore()->GetStoreGuid()) != hrSuccess) {
  334. // No entryid passed or bad entryid passed, create one
  335. hr = HrCreateEntryId(GetMsgStore()->GetStoreGuid(), MAPI_MESSAGE, &cbNewEntryId, &~lpNewEntryId);
  336. if (hr != hrSuccess)
  337. return hr;
  338. hr = lpMessage->SetEntryId(cbNewEntryId, lpNewEntryId);
  339. if (hr != hrSuccess)
  340. return hr;
  341. hr = this->GetMsgStore()->lpTransport->HrOpenPropStorage(m_cbEntryId, m_lpEntryId, cbNewEntryId, lpNewEntryId, ulFlags & MAPI_ASSOCIATED, &~lpStorage);
  342. if(hr != hrSuccess)
  343. return hr;
  344. } else {
  345. // use the passed entryid
  346. hr = lpMessage->SetEntryId(cbEntryID, lpEntryID);
  347. if(hr != hrSuccess)
  348. return hr;
  349. hr = this->GetMsgStore()->lpTransport->HrOpenPropStorage(m_cbEntryId, m_lpEntryId, cbEntryID, lpEntryID, ulFlags & MAPI_ASSOCIATED, &~lpStorage);
  350. if(hr != hrSuccess)
  351. return hr;
  352. }
  353. hr = lpMessage->HrSetPropStorage(lpStorage, FALSE);
  354. if(hr != hrSuccess)
  355. return hr;
  356. // Load an empty property set
  357. hr = lpMessage->HrLoadEmptyProps();
  358. if(hr != hrSuccess)
  359. return hr;
  360. //Set defaults
  361. // Same as ECAttach::OpenProperty
  362. hr = ECAllocateBuffer(sizeof(MAPIUID), &~lpMapiUID);
  363. if (hr != hrSuccess)
  364. return hr;
  365. hr = this->GetMsgStore()->lpSupport->NewUID(lpMapiUID);
  366. if(hr != hrSuccess)
  367. return hr;
  368. sPropValue[0].ulPropTag = PR_MESSAGE_FLAGS;
  369. sPropValue[0].Value.l = MSGFLAG_UNSENT | MSGFLAG_READ;
  370. sPropValue[1].ulPropTag = PR_MESSAGE_CLASS_A;
  371. sPropValue[1].Value.lpszA = const_cast<char *>("IPM");
  372. sPropValue[2].ulPropTag = PR_SEARCH_KEY;
  373. sPropValue[2].Value.bin.cb = sizeof(MAPIUID);
  374. sPropValue[2].Value.bin.lpb = reinterpret_cast<BYTE *>(lpMapiUID.get());
  375. lpMessage->SetProps(3, sPropValue, NULL);
  376. // We don't actually create the object until savechanges is called, so remember in which
  377. // folder it was created
  378. hr = Util::HrCopyEntryId(this->m_cbEntryId, this->m_lpEntryId, &lpMessage->m_cbParentID, &lpMessage->m_lpParentID);
  379. if(hr != hrSuccess)
  380. return hr;
  381. if(lpInterface)
  382. hr = lpMessage->QueryInterface(*lpInterface, (void **)lppMessage);
  383. else
  384. hr = lpMessage->QueryInterface(IID_IMessage, (void **)lppMessage);
  385. AddChild(lpMessage);
  386. return hr;
  387. }
  388. HRESULT ECMAPIFolder::CopyMessages(LPENTRYLIST lpMsgList, LPCIID lpInterface, LPVOID lpDestFolder, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  389. {
  390. HRESULT hr = hrSuccess;
  391. HRESULT hrEC = hrSuccess;
  392. object_ptr<IMAPIFolder> lpMapiFolder;
  393. ecmem_ptr<SPropValue> lpDestPropArray;
  394. ecmem_ptr<ENTRYLIST> lpMsgListEC, lpMsgListSupport;
  395. unsigned int i;
  396. GUID guidFolder;
  397. GUID guidMsg;
  398. if(lpMsgList == NULL || lpMsgList->cValues == 0)
  399. goto exit;
  400. if (lpMsgList->lpbin == NULL) {
  401. hr = MAPI_E_INVALID_PARAMETER;
  402. goto exit;
  403. }
  404. // FIXME progress bar
  405. //Get the interface of destinationfolder
  406. if(lpInterface == NULL || *lpInterface == IID_IMAPIFolder)
  407. hr = ((IMAPIFolder *)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  408. else if(*lpInterface == IID_IMAPIContainer)
  409. hr = ((IMAPIContainer *)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  410. else if(*lpInterface == IID_IUnknown)
  411. hr = ((IUnknown *)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  412. else if(*lpInterface == IID_IMAPIProp)
  413. hr = ((IMAPIProp *)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  414. else
  415. hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
  416. if(hr != hrSuccess)
  417. goto exit;
  418. // Get the destination entry ID, and check for favories public folders, so get PR_ORIGINAL_ENTRYID first.
  419. hr = HrGetOneProp(lpMapiFolder, PR_ORIGINAL_ENTRYID, &~lpDestPropArray);
  420. if (hr != hrSuccess)
  421. hr = HrGetOneProp(lpMapiFolder, PR_ENTRYID, &~lpDestPropArray);
  422. if (hr != hrSuccess)
  423. goto exit;
  424. // Check if the destination entryid is a kopano entryid and if there is a folder transport
  425. if( IsKopanoEntryId(lpDestPropArray[0].Value.bin.cb, lpDestPropArray[0].Value.bin.lpb) &&
  426. lpFolderOps != NULL)
  427. {
  428. hr = HrGetStoreGuidFromEntryId(lpDestPropArray[0].Value.bin.cb, lpDestPropArray[0].Value.bin.lpb, &guidFolder);
  429. if(hr != hrSuccess)
  430. goto exit;
  431. // Allocate memory for support list and kopano list
  432. hr = ECAllocateBuffer(sizeof(ENTRYLIST), &~lpMsgListEC);
  433. if(hr != hrSuccess)
  434. goto exit;
  435. lpMsgListEC->cValues = 0;
  436. hr = ECAllocateMore(sizeof(SBinary) * lpMsgList->cValues, lpMsgListEC, (void**)&lpMsgListEC->lpbin);
  437. if(hr != hrSuccess)
  438. goto exit;
  439. hr = ECAllocateBuffer(sizeof(ENTRYLIST), &~lpMsgListSupport);
  440. if(hr != hrSuccess)
  441. goto exit;
  442. lpMsgListSupport->cValues = 0;
  443. hr = ECAllocateMore(sizeof(SBinary) * lpMsgList->cValues, lpMsgListSupport, (void**)&lpMsgListSupport->lpbin);
  444. if(hr != hrSuccess)
  445. goto exit;
  446. //FIXME
  447. //hr = lpMapiFolder->SetReadFlags(GENERATE_RECEIPT_ONLY);
  448. //if(hr != hrSuccess)
  449. //goto exit;
  450. // Check if right store
  451. for (i = 0; i < lpMsgList->cValues; ++i) {
  452. hr = HrGetStoreGuidFromEntryId(lpMsgList->lpbin[i].cb, lpMsgList->lpbin[i].lpb, &guidMsg);
  453. // check if the message in the store of the folder (serverside copy possible)
  454. if(hr == hrSuccess && IsKopanoEntryId(lpMsgList->lpbin[i].cb, lpMsgList->lpbin[i].lpb) && memcmp(&guidMsg, &guidFolder, sizeof(MAPIUID)) == 0)
  455. lpMsgListEC->lpbin[lpMsgListEC->cValues++] = lpMsgList->lpbin[i];// cheap copy
  456. else
  457. lpMsgListSupport->lpbin[lpMsgListSupport->cValues++] = lpMsgList->lpbin[i];// cheap copy
  458. hr = hrSuccess;
  459. }
  460. if(lpMsgListEC->cValues > 0)
  461. {
  462. hr = this->lpFolderOps->HrCopyMessage(lpMsgListEC, lpDestPropArray[0].Value.bin.cb, (LPENTRYID)lpDestPropArray[0].Value.bin.lpb, ulFlags, 0);
  463. if(FAILED(hr))
  464. goto exit;
  465. hrEC = hr;
  466. }
  467. if(lpMsgListSupport->cValues > 0)
  468. {
  469. hr = this->GetMsgStore()->lpSupport->CopyMessages(&IID_IMAPIFolder, &this->m_xMAPIFolder, lpMsgListSupport, lpInterface, lpDestFolder, ulUIParam, lpProgress, ulFlags);
  470. if(FAILED(hr))
  471. goto exit;
  472. }
  473. }else
  474. {
  475. // Do copy with the storeobject
  476. // Copy between two or more different stores
  477. hr = this->GetMsgStore()->lpSupport->CopyMessages(&IID_IMAPIFolder, &this->m_xMAPIFolder, lpMsgList, lpInterface, lpDestFolder, ulUIParam, lpProgress, ulFlags);
  478. }
  479. exit:
  480. return (hr == hrSuccess)?hrEC:hr;
  481. }
  482. HRESULT ECMAPIFolder::DeleteMessages(LPENTRYLIST lpMsgList, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  483. {
  484. if (lpMsgList == NULL)
  485. return MAPI_E_INVALID_PARAMETER;
  486. if (!ValidateZEntryList(lpMsgList, MAPI_MESSAGE))
  487. return MAPI_E_INVALID_ENTRYID;
  488. // FIXME progress bar
  489. return this->GetMsgStore()->lpTransport->HrDeleteObjects(ulFlags, lpMsgList, 0);
  490. }
  491. HRESULT ECMAPIFolder::CreateFolder(ULONG ulFolderType, LPTSTR lpszFolderName, LPTSTR lpszFolderComment, LPCIID lpInterface, ULONG ulFlags, LPMAPIFOLDER *lppFolder)
  492. {
  493. HRESULT hr = hrSuccess;
  494. ULONG cbEntryId = 0;
  495. ecmem_ptr<ENTRYID> lpEntryId;
  496. object_ptr<IMAPIFolder> lpFolder;
  497. ULONG ulObjType = 0;
  498. // SC TODO: new code:
  499. // create new lpFolder object (load empty props ?)
  500. // create entryid and set it
  501. // create storage and set it
  502. // set props (comment)
  503. // save changes(keep open readwrite) <- the only call to the server
  504. if (lpFolderOps == nullptr)
  505. return MAPI_E_NO_SUPPORT;
  506. // Create the actual folder on the server
  507. hr = lpFolderOps->HrCreateFolder(ulFolderType,
  508. convstring(lpszFolderName, ulFlags),
  509. convstring(lpszFolderComment, ulFlags), ulFlags & OPEN_IF_EXISTS,
  510. 0, nullptr, 0, nullptr, &cbEntryId, &~lpEntryId);
  511. if(hr != hrSuccess)
  512. return hr;
  513. // Open the folder we just created
  514. hr = this->GetMsgStore()->OpenEntry(cbEntryId, lpEntryId, lpInterface, MAPI_MODIFY | MAPI_DEFERRED_ERRORS, &ulObjType, &~lpFolder);
  515. if(hr != hrSuccess)
  516. return hr;
  517. *lppFolder = lpFolder.release();
  518. return hrSuccess;
  519. }
  520. // @note if you change this function please look also at ECMAPIFolderPublic::CopyFolder
  521. HRESULT ECMAPIFolder::CopyFolder(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, LPVOID lpDestFolder, LPTSTR lpszNewFolderName, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  522. {
  523. HRESULT hr = hrSuccess;
  524. object_ptr<IMAPIFolder> lpMapiFolder;
  525. ecmem_ptr<SPropValue> lpPropArray;
  526. GUID guidDest;
  527. GUID guidFrom;
  528. //Get the interface of destinationfolder
  529. if(lpInterface == NULL || *lpInterface == IID_IMAPIFolder)
  530. hr = ((IMAPIFolder*)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  531. else if(*lpInterface == IID_IMAPIContainer)
  532. hr = ((IMAPIContainer*)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  533. else if(*lpInterface == IID_IUnknown)
  534. hr = ((IUnknown*)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  535. else if(*lpInterface == IID_IMAPIProp)
  536. hr = ((IMAPIProp*)lpDestFolder)->QueryInterface(IID_IMAPIFolder, &~lpMapiFolder);
  537. else
  538. hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
  539. if(hr != hrSuccess)
  540. return hr;
  541. // Get the destination entry ID
  542. hr = HrGetOneProp(lpMapiFolder, PR_ENTRYID, &~lpPropArray);
  543. if(hr != hrSuccess)
  544. return hr;
  545. // Check if it's the same store of kopano so we can copy/move fast
  546. if( IsKopanoEntryId(cbEntryID, (LPBYTE)lpEntryID) &&
  547. IsKopanoEntryId(lpPropArray[0].Value.bin.cb, lpPropArray[0].Value.bin.lpb) &&
  548. HrGetStoreGuidFromEntryId(cbEntryID, (LPBYTE)lpEntryID, &guidFrom) == hrSuccess &&
  549. HrGetStoreGuidFromEntryId(lpPropArray[0].Value.bin.cb, lpPropArray[0].Value.bin.lpb, &guidDest) == hrSuccess &&
  550. memcmp(&guidFrom, &guidDest, sizeof(GUID)) == 0 &&
  551. lpFolderOps != NULL)
  552. //FIXME: Progressbar
  553. hr = this->lpFolderOps->HrCopyFolder(cbEntryID, lpEntryID, lpPropArray[0].Value.bin.cb, (LPENTRYID)lpPropArray[0].Value.bin.lpb, convstring(lpszNewFolderName, ulFlags), ulFlags, 0);
  554. else
  555. // Support object handled de copy/move
  556. hr = this->GetMsgStore()->lpSupport->CopyFolder(&IID_IMAPIFolder, &this->m_xMAPIFolder, cbEntryID, lpEntryID, lpInterface, lpDestFolder, lpszNewFolderName, ulUIParam, lpProgress, ulFlags);
  557. return hr;
  558. }
  559. HRESULT ECMAPIFolder::DeleteFolder(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  560. {
  561. if (!ValidateZEntryId(cbEntryID, reinterpret_cast<LPBYTE>(lpEntryID), MAPI_FOLDER))
  562. return MAPI_E_INVALID_ENTRYID;
  563. if (lpFolderOps == NULL)
  564. return MAPI_E_NO_SUPPORT;
  565. return this->lpFolderOps->HrDeleteFolder(cbEntryID, lpEntryID, ulFlags, 0);
  566. }
  567. HRESULT ECMAPIFolder::SetReadFlags(LPENTRYLIST lpMsgList, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  568. {
  569. HRESULT hr = hrSuccess;
  570. BOOL bError = FALSE;
  571. ULONG ulObjType = 0;
  572. // Progress bar
  573. ULONG ulPGMin = 0;
  574. ULONG ulPGMax = 0;
  575. ULONG ulPGDelta = 0;
  576. ULONG ulPGFlags = 0;
  577. if((ulFlags &~ (CLEAR_READ_FLAG | CLEAR_NRN_PENDING | CLEAR_RN_PENDING | GENERATE_RECEIPT_ONLY | MAPI_DEFERRED_ERRORS | MESSAGE_DIALOG | SUPPRESS_RECEIPT)) != 0 ||
  578. (ulFlags & (SUPPRESS_RECEIPT | CLEAR_READ_FLAG)) == (SUPPRESS_RECEIPT | CLEAR_READ_FLAG) ||
  579. (ulFlags & (SUPPRESS_RECEIPT | CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY)) == (SUPPRESS_RECEIPT | CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY) ||
  580. (ulFlags & (CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY)) == (CLEAR_READ_FLAG | GENERATE_RECEIPT_ONLY) )
  581. {
  582. hr = MAPI_E_INVALID_PARAMETER;
  583. goto exit;
  584. }
  585. if (lpFolderOps == NULL) {
  586. hr = MAPI_E_NO_SUPPORT;
  587. goto exit;
  588. }
  589. //FIXME: (GENERATE_RECEIPT_ONLY | SUPPRESS_RECEIPT) not yet implement ok on the server (update PR_READ_RECEIPT_REQUESTED to false)
  590. if( (!(ulFlags & (SUPPRESS_RECEIPT|CLEAR_READ_FLAG|CLEAR_NRN_PENDING|CLEAR_RN_PENDING)) || (ulFlags&GENERATE_RECEIPT_ONLY))&& lpMsgList){
  591. if((ulFlags&MESSAGE_DIALOG ) && lpProgress) {
  592. lpProgress->GetMin(&ulPGMin);
  593. lpProgress->GetMax(&ulPGMax);
  594. ulPGDelta = (ulPGMax-ulPGMin);
  595. lpProgress->GetFlags(&ulPGFlags);
  596. }
  597. for (ULONG i = 0; i < lpMsgList->cValues; ++i) {
  598. object_ptr<IMessage> lpMessage;
  599. if (OpenEntry(lpMsgList->lpbin[i].cb, reinterpret_cast<ENTRYID *>(lpMsgList->lpbin[i].lpb), &IID_IMessage, MAPI_MODIFY, &ulObjType, &~lpMessage) == hrSuccess) {
  600. if(lpMessage->SetReadFlag(ulFlags&~MESSAGE_DIALOG) != hrSuccess)
  601. bError = TRUE;
  602. }else
  603. bError = TRUE;
  604. // Progress bar
  605. if((ulFlags&MESSAGE_DIALOG ) && lpProgress) {
  606. if (ulPGFlags & MAPI_TOP_LEVEL)
  607. hr = lpProgress->Progress((int)((float)i * ulPGDelta / lpMsgList->cValues + ulPGMin), i, lpMsgList->cValues);
  608. else
  609. hr = lpProgress->Progress((int)((float)i * ulPGDelta / lpMsgList->cValues + ulPGMin), 0, 0);
  610. if(hr == MAPI_E_USER_CANCEL) {// MAPI_E_USER_CANCEL is user click on the Cancel button.
  611. hr = hrSuccess;
  612. bError = TRUE;
  613. goto exit;
  614. }else if(hr != hrSuccess) {
  615. goto exit;
  616. }
  617. }
  618. }
  619. }else {
  620. hr = lpFolderOps->HrSetReadFlags(lpMsgList, ulFlags, 0);
  621. }
  622. exit:
  623. if(hr == hrSuccess && bError == TRUE)
  624. hr = MAPI_W_PARTIAL_COMPLETION;
  625. return hr;
  626. }
  627. HRESULT ECMAPIFolder::GetMessageStatus(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulFlags, ULONG *lpulMessageStatus)
  628. {
  629. if (lpEntryID == NULL || !IsKopanoEntryId(cbEntryID, reinterpret_cast<LPBYTE>(lpEntryID)))
  630. return MAPI_E_INVALID_ENTRYID;
  631. if (lpulMessageStatus == NULL)
  632. return MAPI_E_INVALID_OBJECT;
  633. if (lpFolderOps == NULL)
  634. return MAPI_E_NO_SUPPORT;
  635. return lpFolderOps->HrGetMessageStatus(cbEntryID, lpEntryID, ulFlags, lpulMessageStatus);
  636. }
  637. HRESULT ECMAPIFolder::SetMessageStatus(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulNewStatus, ULONG ulNewStatusMask, ULONG *lpulOldStatus)
  638. {
  639. if (lpEntryID == NULL || !IsKopanoEntryId(cbEntryID, reinterpret_cast<LPBYTE>(lpEntryID)))
  640. return MAPI_E_INVALID_ENTRYID;
  641. if (lpFolderOps == NULL)
  642. return MAPI_E_NO_SUPPORT;
  643. return lpFolderOps->HrSetMessageStatus(cbEntryID, lpEntryID, ulNewStatus, ulNewStatusMask, 0, lpulOldStatus);
  644. }
  645. HRESULT ECMAPIFolder::SaveContentsSort(const SSortOrderSet *lpSortCriteria, ULONG ulFlags)
  646. {
  647. return MAPI_E_NO_ACCESS;
  648. }
  649. HRESULT ECMAPIFolder::EmptyFolder(ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  650. {
  651. if((ulFlags &~ (DEL_ASSOCIATED | FOLDER_DIALOG | DELETE_HARD_DELETE)) != 0)
  652. return MAPI_E_INVALID_PARAMETER;
  653. if (lpFolderOps == NULL)
  654. return MAPI_E_NO_SUPPORT;
  655. return lpFolderOps->HrEmptyFolder(ulFlags, 0);
  656. }
  657. HRESULT ECMAPIFolder::GetProps(const SPropTagArray *lpPropTagArray,
  658. ULONG ulFlags, ULONG *lpcValues, SPropValue **lppPropArray)
  659. {
  660. HRESULT hr;
  661. // Check if there is a storage needed because favorites and ipmsubtree of the public folder
  662. // doesn't have a prop storage.
  663. if(lpStorage != NULL) {
  664. hr = HrLoadProps();
  665. if (hr != hrSuccess)
  666. return hr;
  667. }
  668. return ECMAPIProp::GetProps(lpPropTagArray, ulFlags, lpcValues, lppPropArray);
  669. }
  670. HRESULT ECMAPIFolder::GetSupportMask(DWORD * pdwSupportMask)
  671. {
  672. if (pdwSupportMask == NULL)
  673. return MAPI_E_INVALID_PARAMETER;
  674. *pdwSupportMask = FS_SUPPORTS_SHARING; //Indicates that the folder supports sharing.
  675. return hrSuccess;
  676. }
  677. HRESULT ECMAPIFolder::CreateMessageFromStream(ULONG ulFlags, ULONG ulSyncId, ULONG cbEntryID, LPENTRYID lpEntryID, WSMessageStreamImporter **lppsStreamImporter)
  678. {
  679. HRESULT hr;
  680. WSMessageStreamImporterPtr ptrStreamImporter;
  681. hr = GetMsgStore()->lpTransport->HrGetMessageStreamImporter(ulFlags, ulSyncId, cbEntryID, lpEntryID, m_cbEntryId, m_lpEntryId, true, nullptr, &~ptrStreamImporter);
  682. if (hr != hrSuccess)
  683. return hr;
  684. *lppsStreamImporter = ptrStreamImporter.release();
  685. return hrSuccess;
  686. }
  687. HRESULT ECMAPIFolder::GetChangeInfo(ULONG cbEntryID, LPENTRYID lpEntryID, LPSPropValue *lppPropPCL, LPSPropValue *lppPropCK)
  688. {
  689. return lpFolderOps->HrGetChangeInfo(cbEntryID, lpEntryID, lppPropPCL, lppPropCK);
  690. }
  691. HRESULT ECMAPIFolder::UpdateMessageFromStream(ULONG ulSyncId, ULONG cbEntryID, LPENTRYID lpEntryID, LPSPropValue lpConflictItems, WSMessageStreamImporter **lppsStreamImporter)
  692. {
  693. HRESULT hr;
  694. WSMessageStreamImporterPtr ptrStreamImporter;
  695. hr = GetMsgStore()->lpTransport->HrGetMessageStreamImporter(0, ulSyncId, cbEntryID, lpEntryID, m_cbEntryId, m_lpEntryId, false, lpConflictItems, &~ptrStreamImporter);
  696. if (hr != hrSuccess)
  697. return hr;
  698. *lppsStreamImporter = ptrStreamImporter.release();
  699. return hrSuccess;
  700. }
  701. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, QueryInterface, (REFIID, refiid), (void **, lppInterface))
  702. DEF_ULONGMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, AddRef, (void))
  703. DEF_ULONGMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, Release, (void))
  704. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetLastError, (HRESULT, hError), (ULONG, ulFlags), (LPMAPIERROR *, lppMapiError))
  705. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SaveChanges, (ULONG, ulFlags))
  706. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetProps, (const SPropTagArray *, lpPropTagArray), (ULONG, ulFlags), (ULONG *, lpcValues), (SPropValue **, lppPropArray))
  707. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetPropList, (ULONG, ulFlags), (LPSPropTagArray *, lppPropTagArray))
  708. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, OpenProperty, (ULONG, ulPropTag), (LPCIID, lpiid), (ULONG, ulInterfaceOptions), (ULONG, ulFlags), (LPUNKNOWN *, lppUnk))
  709. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SetProps, (ULONG, cValues), (const SPropValue *, lpPropArray), (SPropProblemArray **, lppProblems))
  710. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, DeleteProps, (const SPropTagArray *, lpPropTagArray), (SPropProblemArray **, lppProblems))
  711. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CopyTo, (ULONG, ciidExclude), (LPCIID, rgiidExclude), (const SPropTagArray *, lpExcludeProps), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (LPCIID, lpInterface), (void *, lpDestObj), (ULONG, ulFlags), (SPropProblemArray **, lppProblems))
  712. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CopyProps, (const SPropTagArray *, lpIncludeProps), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (LPCIID, lpInterface), (void *, lpDestObj), (ULONG, ulFlags), (SPropProblemArray **, lppProblems))
  713. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetNamesFromIDs, (LPSPropTagArray *, pptaga), (LPGUID, lpguid), (ULONG, ulFlags), (ULONG *, pcNames), (LPMAPINAMEID **, pppNames))
  714. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetIDsFromNames, (ULONG, cNames), (LPMAPINAMEID *, ppNames), (ULONG, ulFlags), (LPSPropTagArray *, pptaga))
  715. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetContentsTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
  716. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetHierarchyTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
  717. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, OpenEntry, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulObjType), (LPUNKNOWN *, lppUnk))
  718. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SetSearchCriteria, (LPSRestriction, lpRestriction), (LPENTRYLIST, lpContainerList), (ULONG, ulSearchFlags))
  719. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetSearchCriteria, (ULONG, ulFlags), (LPSRestriction *, lppRestriction), (LPENTRYLIST *, lppContainerList), (ULONG *, lpulSearchState))
  720. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CreateMessage, (LPCIID, lpInterface), (ULONG, ulFlags), (LPMESSAGE *, lppMessage))
  721. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CopyMessages, (LPENTRYLIST, lpMsgList), (LPCIID, lpInterface), (LPVOID, lpDestFolder), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  722. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, DeleteMessages, (LPENTRYLIST, lpMsgList), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  723. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CreateFolder, (ULONG, ulFolderType), (LPTSTR, lpszFolderName), (LPTSTR, lpszFolderComment), (LPCIID, lpInterface), (ULONG, ulFlags), (LPMAPIFOLDER *, lppFolder))
  724. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, CopyFolder, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (LPCIID, lpInterface), (LPVOID, lpDestFolder), (LPTSTR, lpszNewFolderName), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  725. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, DeleteFolder, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  726. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SetReadFlags, (LPENTRYLIST, lpMsgList), (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  727. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, GetMessageStatus, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (ULONG, ulFlags), (ULONG *, lpulMessageStatus))
  728. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SetMessageStatus, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (ULONG, ulNewStatus), (ULONG, ulNewStatusMask), (ULONG *, lpulOldStatus))
  729. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, SaveContentsSort, (const SSortOrderSet *, lpSortCriteria), (ULONG, ulFlags))
  730. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, MAPIFolder, EmptyFolder, (ULONG, ulUIParam), (LPMAPIPROGRESS, lpProgress), (ULONG, ulFlags))
  731. // IFolderSupport
  732. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, FolderSupport, QueryInterface, (REFIID, refiid), (void **, lppInterface))
  733. DEF_ULONGMETHOD1(TRACE_MAPI, ECMAPIFolder, FolderSupport, AddRef, (void))
  734. DEF_ULONGMETHOD1(TRACE_MAPI, ECMAPIFolder, FolderSupport, Release, (void))
  735. DEF_HRMETHOD1(TRACE_MAPI, ECMAPIFolder, FolderSupport, GetSupportMask, (DWORD *, pdwSupportMask))