ZCABLogon.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 <utility>
  20. #include <kopano/Trace.h>
  21. #include "ZCABLogon.h"
  22. #include "ZCABContainer.h"
  23. #include <kopano/ECTags.h>
  24. #include <kopano/ECDebug.h>
  25. #include <kopano/ECDebugPrint.h>
  26. #include <kopano/ECGuid.h>
  27. #include <kopano/ECInterfaceDefs.h>
  28. #include <kopano/memory.hpp>
  29. #include "kcore.hpp"
  30. #include <mapix.h>
  31. #include <edkmdb.h>
  32. using namespace KCHL;
  33. ZCABLogon::ZCABLogon(LPMAPISUP lpMAPISup, ULONG ulProfileFlags, GUID *lpGUID) :
  34. ECUnknown("IABLogon"), m_lpMAPISup(lpMAPISup)
  35. {
  36. // The specific GUID for *this* addressbook provider, if available
  37. m_ABPGuid = lpGUID != nullptr ? *lpGUID : GUID_NULL;
  38. if(m_lpMAPISup)
  39. m_lpMAPISup->AddRef();
  40. }
  41. ZCABLogon::~ZCABLogon()
  42. {
  43. ClearFolderList();
  44. if (m_lpMAPISup != nullptr)
  45. m_lpMAPISup->Release();
  46. }
  47. HRESULT ZCABLogon::Create(LPMAPISUP lpMAPISup, ULONG ulProfileFlags, GUID *lpGuid, ZCABLogon **lppZCABLogon)
  48. {
  49. HRESULT hr = hrSuccess;
  50. auto lpABLogon = new(std::nothrow) ZCABLogon(lpMAPISup, ulProfileFlags, lpGuid);
  51. if (lpABLogon == nullptr)
  52. return MAPI_E_NOT_ENOUGH_MEMORY;
  53. hr = lpABLogon->QueryInterface(IID_ZCABLogon, (void **)lppZCABLogon);
  54. if(hr != hrSuccess)
  55. delete lpABLogon;
  56. return hr;
  57. }
  58. HRESULT ZCABLogon::QueryInterface(REFIID refiid, void **lppInterface)
  59. {
  60. REGISTER_INTERFACE2(ZCABLogon, this);
  61. REGISTER_INTERFACE2(ECUnknown, this);
  62. REGISTER_INTERFACE2(IABLogon, &this->m_xABLogon);
  63. REGISTER_INTERFACE2(IUnknown, &this->m_xABLogon);
  64. return MAPI_E_INTERFACE_NOT_SUPPORTED;
  65. }
  66. HRESULT ZCABLogon::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR *lppMAPIError)
  67. {
  68. return MAPI_E_CALL_FAILED;
  69. }
  70. HRESULT ZCABLogon::Logoff(ULONG ulFlags)
  71. {
  72. HRESULT hr = hrSuccess;
  73. //FIXME: Release all Other open objects ?
  74. //Releases all open objects, such as any subobjects or the status object.
  75. //Releases the provider's support object.
  76. if(m_lpMAPISup)
  77. {
  78. m_lpMAPISup->Release();
  79. m_lpMAPISup = NULL;
  80. }
  81. return hr;
  82. }
  83. /**
  84. * Adds a folder to the addressbook provider. Data is read from global profile section.
  85. *
  86. * @param[in] strDisplayName Display string in hierarchy table
  87. * @param[in] cbStore bytes in lpStore
  88. * @param[in] lpStore Store entryid lpFolder entryid is in
  89. * @param[in] cbFolder bytes in lpFolder
  90. * @param[in] lpFolder Folder entryid pointing to a contacts folder (assumed, should we check?)
  91. *
  92. * @return MAPI Error code
  93. */
  94. HRESULT ZCABLogon::AddFolder(const WCHAR* lpwDisplayName, ULONG cbStore, LPBYTE lpStore, ULONG cbFolder, LPBYTE lpFolder)
  95. {
  96. zcabFolderEntry entry;
  97. if (cbStore == 0 || lpStore == NULL || cbFolder == 0 || lpFolder == NULL)
  98. return MAPI_E_INVALID_PARAMETER;
  99. entry.strwDisplayName = lpwDisplayName;
  100. entry.cbStore = cbStore;
  101. HRESULT hr = MAPIAllocateBuffer(cbStore,
  102. reinterpret_cast<void **>(&entry.lpStore));
  103. if (hr != hrSuccess)
  104. return hr;
  105. memcpy(entry.lpStore, lpStore, cbStore);
  106. entry.cbFolder = cbFolder;
  107. hr = MAPIAllocateBuffer(cbFolder, (void**)&entry.lpFolder);
  108. if (hr != hrSuccess)
  109. return hr;
  110. memcpy(entry.lpFolder, lpFolder, cbFolder);
  111. m_lFolders.push_back(std::move(entry));
  112. return hrSuccess;
  113. }
  114. HRESULT ZCABLogon::ClearFolderList()
  115. {
  116. for (const auto &i : m_lFolders) {
  117. MAPIFreeBuffer(i.lpStore);
  118. MAPIFreeBuffer(i.lpFolder);
  119. }
  120. m_lFolders.clear();
  121. return hrSuccess;
  122. }
  123. /**
  124. * EntryID is NULL: Open "root container". Returns an ABContainer
  125. * which returns the provider root container. The EntryID in that one
  126. * table entry opens the ABContainer which has all the folders from
  127. * stores which were added using the AddFolder interface.
  128. *
  129. * Root container EntryID: 00000000727f0430e3924fdab86ae52a7fe46571 (version + guid)
  130. * Sub container EntryID : 00000000727f0430e3924fdab86ae52a7fe46571 + obj type + 0 + folder contact eid
  131. * Contact Item EntryID : 00000000727f0430e3924fdab86ae52a7fe46571 + obj type + email offset + kopano item eid
  132. *
  133. * @param[in] cbEntryID 0 or bytes in lpEntryID
  134. * @param[in] lpEntryID NULL or a valid entryid
  135. * @param[in] lpInterface NULL or supported interface
  136. * @param[in] ulFlags unused
  137. * @param[out] lpulObjType MAPI_ABCONT, or a type from ZCAB
  138. * @param[out] lppUnk pointer to ZCABContainer
  139. *
  140. * @return
  141. */
  142. HRESULT ZCABLogon::OpenEntry(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPUNKNOWN *lppUnk)
  143. {
  144. HRESULT hr = hrSuccess;
  145. object_ptr<ZCABContainer> lpRootContainer;
  146. object_ptr<ZCMAPIProp> lpContact;
  147. object_ptr<IProfSect> lpProfileSection;
  148. memory_ptr<SPropValue> lpFolderProps;
  149. ULONG cValues = 0;
  150. static constexpr const SizedSPropTagArray(3, sptaFolderProps) =
  151. {3, {PR_ZC_CONTACT_STORE_ENTRYIDS,
  152. PR_ZC_CONTACT_FOLDER_ENTRYIDS, PR_ZC_CONTACT_FOLDER_NAMES_W}};
  153. // Check input/output variables
  154. if (lpulObjType == nullptr || lppUnk == nullptr)
  155. return MAPI_E_INVALID_PARAMETER;
  156. if(cbEntryID == 0 && lpEntryID == NULL) {
  157. // this is the "Kopano Contacts Folders" container. Get the hierarchy of this folder. SetEntryID(0000 + guid + MAPI_ABCONT + ?) ofzo?
  158. hr = ZCABContainer::Create(nullptr, nullptr, m_lpMAPISup, this, &~lpRootContainer);
  159. if (hr != hrSuccess)
  160. return hr;
  161. } else {
  162. if (cbEntryID == 0 || lpEntryID == nullptr)
  163. return MAPI_E_UNKNOWN_ENTRYID;
  164. // you can only open the top level container
  165. if (memcmp((LPBYTE)lpEntryID +4, &MUIDZCSAB, sizeof(GUID)) != 0)
  166. return MAPI_E_UNKNOWN_ENTRYID;
  167. hr = m_lpMAPISup->OpenProfileSection((LPMAPIUID)pbGlobalProfileSectionGuid, 0, &~lpProfileSection);
  168. if (hr != hrSuccess)
  169. return hr;
  170. hr = lpProfileSection->GetProps(sptaFolderProps, 0, &cValues, &~lpFolderProps);
  171. if (FAILED(hr))
  172. return hr;
  173. // remove old list, if present
  174. ClearFolderList();
  175. // make the list
  176. if (lpFolderProps[0].ulPropTag == PR_ZC_CONTACT_STORE_ENTRYIDS &&
  177. lpFolderProps[1].ulPropTag == PR_ZC_CONTACT_FOLDER_ENTRYIDS &&
  178. lpFolderProps[2].ulPropTag == PR_ZC_CONTACT_FOLDER_NAMES_W &&
  179. lpFolderProps[0].Value.MVbin.cValues == lpFolderProps[1].Value.MVbin.cValues &&
  180. lpFolderProps[1].Value.MVbin.cValues == lpFolderProps[2].Value.MVszW.cValues)
  181. for (ULONG c = 0; c < lpFolderProps[1].Value.MVbin.cValues; ++c)
  182. AddFolder(lpFolderProps[2].Value.MVszW.lppszW[c],
  183. lpFolderProps[0].Value.MVbin.lpbin[c].cb, lpFolderProps[0].Value.MVbin.lpbin[c].lpb,
  184. lpFolderProps[1].Value.MVbin.lpbin[c].cb, lpFolderProps[1].Value.MVbin.lpbin[c].lpb);
  185. hr = ZCABContainer::Create(&m_lFolders, nullptr, m_lpMAPISup, this, &~lpRootContainer);
  186. if (hr != hrSuccess)
  187. return hr;
  188. if (cbEntryID > 4+sizeof(GUID)) {
  189. // we're actually opening a contact .. so pass-through to the just opened rootcontainer
  190. hr = lpRootContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, &~lpContact);
  191. if (hr != hrSuccess)
  192. return hr;
  193. }
  194. }
  195. if (lpContact) {
  196. if(lpInterface)
  197. hr = lpContact->QueryInterface(*lpInterface, (void **)lppUnk);
  198. else
  199. hr = lpContact->QueryInterface(IID_IMAPIProp, (void **)lppUnk);
  200. } else {
  201. *lpulObjType = MAPI_ABCONT;
  202. if(lpInterface)
  203. hr = lpRootContainer->QueryInterface(*lpInterface, (void **)lppUnk);
  204. else
  205. hr = lpRootContainer->QueryInterface(IID_IABContainer, (void **)lppUnk);
  206. }
  207. if(hr != hrSuccess)
  208. return hr;
  209. if (lpContact == nullptr)
  210. // root container has pointer to my m_lFolders
  211. AddChild(lpRootContainer);
  212. return hrSuccess;
  213. }
  214. HRESULT ZCABLogon::CompareEntryIDs(ULONG cbEntryID1, LPENTRYID lpEntryID1, ULONG cbEntryID2, LPENTRYID lpEntryID2, ULONG ulFlags, ULONG *lpulResult)
  215. {
  216. // we don't implement this .. a real ab provider should do this action.
  217. return MAPI_E_NO_SUPPORT;
  218. }
  219. HRESULT ZCABLogon::Advise(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulEventMask, LPMAPIADVISESINK lpAdviseSink, ULONG *lpulConnection)
  220. {
  221. if (lpAdviseSink == NULL || lpulConnection == NULL)
  222. return MAPI_E_INVALID_PARAMETER;
  223. if (lpEntryID == NULL)
  224. return MAPI_E_INVALID_PARAMETER;
  225. return MAPI_E_NO_SUPPORT;
  226. }
  227. HRESULT ZCABLogon::Unadvise(ULONG ulConnection)
  228. {
  229. return MAPI_E_NO_SUPPORT;
  230. }
  231. HRESULT ZCABLogon::OpenStatusEntry(LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPMAPISTATUS * lppMAPIStatus)
  232. {
  233. return MAPI_E_NO_SUPPORT;
  234. }
  235. HRESULT ZCABLogon::OpenTemplateID(ULONG cbTemplateID, LPENTRYID lpTemplateID, ULONG ulTemplateFlags, LPMAPIPROP lpMAPIPropData, LPCIID lpInterface, LPMAPIPROP * lppMAPIPropNew, LPMAPIPROP lpMAPIPropSibling)
  236. {
  237. return MAPI_E_NO_SUPPORT;
  238. }
  239. HRESULT ZCABLogon::GetOneOffTable(ULONG ulFlags, LPMAPITABLE * lppTable)
  240. {
  241. return MAPI_E_NO_SUPPORT;
  242. }
  243. HRESULT ZCABLogon::PrepareRecips(ULONG ulFlags,
  244. const SPropTagArray *lpPropTagArray, LPADRLIST lpRecipList)
  245. {
  246. if(lpPropTagArray == NULL || lpPropTagArray->cValues == 0)
  247. /* There is no work to do. */
  248. return hrSuccess;
  249. return MAPI_E_NO_SUPPORT;
  250. }
  251. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, QueryInterface, (REFIID, refiid), (void **, lppInterface))
  252. DEF_ULONGMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, AddRef, (void))
  253. DEF_ULONGMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Release, (void))
  254. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, GetLastError, (HRESULT, hResult), (ULONG, ulFlags), (LPMAPIERROR *, lppMAPIError))
  255. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Logoff, (ULONG, ulFlags))
  256. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenEntry, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulObjType), (LPUNKNOWN *, lppUnk))
  257. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, CompareEntryIDs, (ULONG, cbEntryID1), (LPENTRYID, lpEntryID1), (ULONG, cbEntryID2), (LPENTRYID, lpEntryID2), (ULONG, ulFlags), (ULONG *, lpulResult))
  258. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Advise, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (ULONG, ulEventMask), (LPMAPIADVISESINK, lpAdviseSink), (ULONG *, lpulConnection))
  259. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Unadvise, (ULONG, ulConnection))
  260. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenStatusEntry, (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulObjType), (LPMAPISTATUS *, lppMAPIStatus))
  261. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenTemplateID, (ULONG, cbTemplateID), (LPENTRYID, lpTemplateID), (ULONG, ulTemplateFlags), (LPMAPIPROP, lpMAPIPropData), (LPCIID, lpInterface), (LPMAPIPROP *, lppMAPIPropNew), (LPMAPIPROP, lpMAPIPropSibling))
  262. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, GetOneOffTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
  263. DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, PrepareRecips, (ULONG, ulFlags), (const SPropTagArray *, lpPropTagArray), (LPADRLIST, lpRecipList))