123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <kopano/platform.h>
- #include <new>
- #include <utility>
- #include <kopano/Trace.h>
- #include "ZCABLogon.h"
- #include "ZCABContainer.h"
- #include <kopano/ECTags.h>
- #include <kopano/ECDebug.h>
- #include <kopano/ECDebugPrint.h>
- #include <kopano/ECGuid.h>
- #include <kopano/ECInterfaceDefs.h>
- #include <kopano/memory.hpp>
- #include "kcore.hpp"
- #include <mapix.h>
- #include <edkmdb.h>
- using namespace KCHL;
- ZCABLogon::ZCABLogon(LPMAPISUP lpMAPISup, ULONG ulProfileFlags, GUID *lpGUID) :
- ECUnknown("IABLogon"), m_lpMAPISup(lpMAPISup)
- {
- // The specific GUID for *this* addressbook provider, if available
- m_ABPGuid = lpGUID != nullptr ? *lpGUID : GUID_NULL;
- if(m_lpMAPISup)
- m_lpMAPISup->AddRef();
- }
- ZCABLogon::~ZCABLogon()
- {
- ClearFolderList();
- if (m_lpMAPISup != nullptr)
- m_lpMAPISup->Release();
- }
- HRESULT ZCABLogon::Create(LPMAPISUP lpMAPISup, ULONG ulProfileFlags, GUID *lpGuid, ZCABLogon **lppZCABLogon)
- {
- HRESULT hr = hrSuccess;
- auto lpABLogon = new(std::nothrow) ZCABLogon(lpMAPISup, ulProfileFlags, lpGuid);
- if (lpABLogon == nullptr)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- hr = lpABLogon->QueryInterface(IID_ZCABLogon, (void **)lppZCABLogon);
- if(hr != hrSuccess)
- delete lpABLogon;
- return hr;
- }
- HRESULT ZCABLogon::QueryInterface(REFIID refiid, void **lppInterface)
- {
- REGISTER_INTERFACE2(ZCABLogon, this);
- REGISTER_INTERFACE2(ECUnknown, this);
- REGISTER_INTERFACE2(IABLogon, &this->m_xABLogon);
- REGISTER_INTERFACE2(IUnknown, &this->m_xABLogon);
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- HRESULT ZCABLogon::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR *lppMAPIError)
- {
- return MAPI_E_CALL_FAILED;
- }
- HRESULT ZCABLogon::Logoff(ULONG ulFlags)
- {
- HRESULT hr = hrSuccess;
- //FIXME: Release all Other open objects ?
- //Releases all open objects, such as any subobjects or the status object.
- //Releases the provider's support object.
- if(m_lpMAPISup)
- {
- m_lpMAPISup->Release();
- m_lpMAPISup = NULL;
- }
- return hr;
- }
- /**
- * Adds a folder to the addressbook provider. Data is read from global profile section.
- *
- * @param[in] strDisplayName Display string in hierarchy table
- * @param[in] cbStore bytes in lpStore
- * @param[in] lpStore Store entryid lpFolder entryid is in
- * @param[in] cbFolder bytes in lpFolder
- * @param[in] lpFolder Folder entryid pointing to a contacts folder (assumed, should we check?)
- *
- * @return MAPI Error code
- */
- HRESULT ZCABLogon::AddFolder(const WCHAR* lpwDisplayName, ULONG cbStore, LPBYTE lpStore, ULONG cbFolder, LPBYTE lpFolder)
- {
- zcabFolderEntry entry;
- if (cbStore == 0 || lpStore == NULL || cbFolder == 0 || lpFolder == NULL)
- return MAPI_E_INVALID_PARAMETER;
- entry.strwDisplayName = lpwDisplayName;
- entry.cbStore = cbStore;
- HRESULT hr = MAPIAllocateBuffer(cbStore,
- reinterpret_cast<void **>(&entry.lpStore));
- if (hr != hrSuccess)
- return hr;
- memcpy(entry.lpStore, lpStore, cbStore);
- entry.cbFolder = cbFolder;
- hr = MAPIAllocateBuffer(cbFolder, (void**)&entry.lpFolder);
- if (hr != hrSuccess)
- return hr;
- memcpy(entry.lpFolder, lpFolder, cbFolder);
- m_lFolders.push_back(std::move(entry));
- return hrSuccess;
- }
- HRESULT ZCABLogon::ClearFolderList()
- {
- for (const auto &i : m_lFolders) {
- MAPIFreeBuffer(i.lpStore);
- MAPIFreeBuffer(i.lpFolder);
- }
- m_lFolders.clear();
- return hrSuccess;
- }
- /**
- * EntryID is NULL: Open "root container". Returns an ABContainer
- * which returns the provider root container. The EntryID in that one
- * table entry opens the ABContainer which has all the folders from
- * stores which were added using the AddFolder interface.
- *
- * Root container EntryID: 00000000727f0430e3924fdab86ae52a7fe46571 (version + guid)
- * Sub container EntryID : 00000000727f0430e3924fdab86ae52a7fe46571 + obj type + 0 + folder contact eid
- * Contact Item EntryID : 00000000727f0430e3924fdab86ae52a7fe46571 + obj type + email offset + kopano item eid
- *
- * @param[in] cbEntryID 0 or bytes in lpEntryID
- * @param[in] lpEntryID NULL or a valid entryid
- * @param[in] lpInterface NULL or supported interface
- * @param[in] ulFlags unused
- * @param[out] lpulObjType MAPI_ABCONT, or a type from ZCAB
- * @param[out] lppUnk pointer to ZCABContainer
- *
- * @return
- */
- HRESULT ZCABLogon::OpenEntry(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPUNKNOWN *lppUnk)
- {
- HRESULT hr = hrSuccess;
- object_ptr<ZCABContainer> lpRootContainer;
- object_ptr<ZCMAPIProp> lpContact;
- object_ptr<IProfSect> lpProfileSection;
- memory_ptr<SPropValue> lpFolderProps;
- ULONG cValues = 0;
- static constexpr const SizedSPropTagArray(3, sptaFolderProps) =
- {3, {PR_ZC_CONTACT_STORE_ENTRYIDS,
- PR_ZC_CONTACT_FOLDER_ENTRYIDS, PR_ZC_CONTACT_FOLDER_NAMES_W}};
-
- // Check input/output variables
- if (lpulObjType == nullptr || lppUnk == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- if(cbEntryID == 0 && lpEntryID == NULL) {
- // this is the "Kopano Contacts Folders" container. Get the hierarchy of this folder. SetEntryID(0000 + guid + MAPI_ABCONT + ?) ofzo?
- hr = ZCABContainer::Create(nullptr, nullptr, m_lpMAPISup, this, &~lpRootContainer);
- if (hr != hrSuccess)
- return hr;
- } else {
- if (cbEntryID == 0 || lpEntryID == nullptr)
- return MAPI_E_UNKNOWN_ENTRYID;
- // you can only open the top level container
- if (memcmp((LPBYTE)lpEntryID +4, &MUIDZCSAB, sizeof(GUID)) != 0)
- return MAPI_E_UNKNOWN_ENTRYID;
- hr = m_lpMAPISup->OpenProfileSection((LPMAPIUID)pbGlobalProfileSectionGuid, 0, &~lpProfileSection);
- if (hr != hrSuccess)
- return hr;
- hr = lpProfileSection->GetProps(sptaFolderProps, 0, &cValues, &~lpFolderProps);
- if (FAILED(hr))
- return hr;
- // remove old list, if present
- ClearFolderList();
- // make the list
- if (lpFolderProps[0].ulPropTag == PR_ZC_CONTACT_STORE_ENTRYIDS &&
- lpFolderProps[1].ulPropTag == PR_ZC_CONTACT_FOLDER_ENTRYIDS &&
- lpFolderProps[2].ulPropTag == PR_ZC_CONTACT_FOLDER_NAMES_W &&
- lpFolderProps[0].Value.MVbin.cValues == lpFolderProps[1].Value.MVbin.cValues &&
- lpFolderProps[1].Value.MVbin.cValues == lpFolderProps[2].Value.MVszW.cValues)
- for (ULONG c = 0; c < lpFolderProps[1].Value.MVbin.cValues; ++c)
- AddFolder(lpFolderProps[2].Value.MVszW.lppszW[c],
- lpFolderProps[0].Value.MVbin.lpbin[c].cb, lpFolderProps[0].Value.MVbin.lpbin[c].lpb,
- lpFolderProps[1].Value.MVbin.lpbin[c].cb, lpFolderProps[1].Value.MVbin.lpbin[c].lpb);
- hr = ZCABContainer::Create(&m_lFolders, nullptr, m_lpMAPISup, this, &~lpRootContainer);
- if (hr != hrSuccess)
- return hr;
- if (cbEntryID > 4+sizeof(GUID)) {
- // we're actually opening a contact .. so pass-through to the just opened rootcontainer
- hr = lpRootContainer->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, &~lpContact);
- if (hr != hrSuccess)
- return hr;
- }
- }
- if (lpContact) {
- if(lpInterface)
- hr = lpContact->QueryInterface(*lpInterface, (void **)lppUnk);
- else
- hr = lpContact->QueryInterface(IID_IMAPIProp, (void **)lppUnk);
- } else {
- *lpulObjType = MAPI_ABCONT;
- if(lpInterface)
- hr = lpRootContainer->QueryInterface(*lpInterface, (void **)lppUnk);
- else
- hr = lpRootContainer->QueryInterface(IID_IABContainer, (void **)lppUnk);
- }
- if(hr != hrSuccess)
- return hr;
- if (lpContact == nullptr)
- // root container has pointer to my m_lFolders
- AddChild(lpRootContainer);
- return hrSuccess;
- }
- HRESULT ZCABLogon::CompareEntryIDs(ULONG cbEntryID1, LPENTRYID lpEntryID1, ULONG cbEntryID2, LPENTRYID lpEntryID2, ULONG ulFlags, ULONG *lpulResult)
- {
- // we don't implement this .. a real ab provider should do this action.
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::Advise(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulEventMask, LPMAPIADVISESINK lpAdviseSink, ULONG *lpulConnection)
- {
- if (lpAdviseSink == NULL || lpulConnection == NULL)
- return MAPI_E_INVALID_PARAMETER;
- if (lpEntryID == NULL)
- return MAPI_E_INVALID_PARAMETER;
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::Unadvise(ULONG ulConnection)
- {
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::OpenStatusEntry(LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPMAPISTATUS * lppMAPIStatus)
- {
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::OpenTemplateID(ULONG cbTemplateID, LPENTRYID lpTemplateID, ULONG ulTemplateFlags, LPMAPIPROP lpMAPIPropData, LPCIID lpInterface, LPMAPIPROP * lppMAPIPropNew, LPMAPIPROP lpMAPIPropSibling)
- {
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::GetOneOffTable(ULONG ulFlags, LPMAPITABLE * lppTable)
- {
- return MAPI_E_NO_SUPPORT;
- }
- HRESULT ZCABLogon::PrepareRecips(ULONG ulFlags,
- const SPropTagArray *lpPropTagArray, LPADRLIST lpRecipList)
- {
- if(lpPropTagArray == NULL || lpPropTagArray->cValues == 0)
- /* There is no work to do. */
- return hrSuccess;
- return MAPI_E_NO_SUPPORT;
- }
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, QueryInterface, (REFIID, refiid), (void **, lppInterface))
- DEF_ULONGMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, AddRef, (void))
- DEF_ULONGMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Release, (void))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, GetLastError, (HRESULT, hResult), (ULONG, ulFlags), (LPMAPIERROR *, lppMAPIError))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Logoff, (ULONG, ulFlags))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenEntry, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulObjType), (LPUNKNOWN *, lppUnk))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, CompareEntryIDs, (ULONG, cbEntryID1), (LPENTRYID, lpEntryID1), (ULONG, cbEntryID2), (LPENTRYID, lpEntryID2), (ULONG, ulFlags), (ULONG *, lpulResult))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Advise, (ULONG, cbEntryID), (LPENTRYID, lpEntryID), (ULONG, ulEventMask), (LPMAPIADVISESINK, lpAdviseSink), (ULONG *, lpulConnection))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, Unadvise, (ULONG, ulConnection))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenStatusEntry, (LPCIID, lpInterface), (ULONG, ulFlags), (ULONG *, lpulObjType), (LPMAPISTATUS *, lppMAPIStatus))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, OpenTemplateID, (ULONG, cbTemplateID), (LPENTRYID, lpTemplateID), (ULONG, ulTemplateFlags), (LPMAPIPROP, lpMAPIPropData), (LPCIID, lpInterface), (LPMAPIPROP *, lppMAPIPropNew), (LPMAPIPROP, lpMAPIPropSibling))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, GetOneOffTable, (ULONG, ulFlags), (LPMAPITABLE *, lppTable))
- DEF_HRMETHOD1(TRACE_MAPI, ZCABLogon, ABLogon, PrepareRecips, (ULONG, ulFlags), (const SPropTagArray *, lpPropTagArray), (LPADRLIST, lpRecipList))
|