123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- /*
- * 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 <new>
- #include <kopano/platform.h>
- #include <kopano/memory.hpp>
- #include "ECMsgStorePublic.h"
- #include "ECMAPIFolder.h"
- #include <kopano/CommonUtil.h>
- #include <kopano/Util.h>
- #include "ClientUtil.h"
- #include "pcutil.hpp"
- #include <kopano/ECGetText.h>
- #include <kopano/mapiext.h>
- #include <mapiutil.h>
- #include "ECMAPIFolderPublic.h"
- #include <kopano/ECGuid.h>
- using namespace std;
- using namespace KCHL;
- ECMsgStorePublic::ECMsgStorePublic(char *lpszProfname, LPMAPISUP lpSupport, WSTransport *lpTransport, BOOL fModify, ULONG ulProfileFlags, BOOL fIsSpooler, BOOL bOfflineStore) :
- ECMsgStore(lpszProfname, lpSupport, lpTransport, fModify, ulProfileFlags, fIsSpooler, false, bOfflineStore)
- {
- TRACE_MAPI(TRACE_ENTRY, "ECMsgStorePublic::ECMsgStorePublic","");
- HrAddPropHandlers(PR_IPM_SUBTREE_ENTRYID, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- HrAddPropHandlers(PR_IPM_PUBLIC_FOLDERS_ENTRYID, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- HrAddPropHandlers(PR_IPM_FAVORITES_ENTRYID, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
- HrAddPropHandlers(PR_EC_PUBLIC_IPM_SUBTREE_ENTRYID, GetPropHandler, SetPropHandler, (void*) this, FALSE, TRUE);
- TRACE_MAPI(TRACE_RETURN, "ECMsgStorePublic::ECMsgStorePublic","");
- }
- ECMsgStorePublic::~ECMsgStorePublic(void)
- {
- TRACE_MAPI(TRACE_ENTRY, "ECMsgStorePublic::~ECMsgStorePublic","");
- if (m_lpDefaultMsgStore)
- m_lpDefaultMsgStore->Release();
- if (m_lpIPMSubTree)
- m_lpIPMSubTree->Release();
- MAPIFreeBuffer(m_lpIPMSubTreeID);
- MAPIFreeBuffer(m_lpIPMFavoritesID);
- MAPIFreeBuffer(m_lpIPMPublicFoldersID);
- TRACE_MAPI(TRACE_RETURN, "~ECMsgStorePublic::ECMsgStorePublic","");
- }
- HRESULT ECMsgStorePublic::Create(char *lpszProfname, LPMAPISUP lpSupport, WSTransport *lpTransport, BOOL fModify, ULONG ulProfileFlags, BOOL fIsSpooler, BOOL bOfflineStore, ECMsgStore **lppECMsgStore) {
- HRESULT hr = hrSuccess;
- auto lpStore = new(std::nothrow) ECMsgStorePublic(lpszProfname,
- lpSupport, lpTransport, fModify, ulProfileFlags,
- fIsSpooler, bOfflineStore);
- if (lpStore == nullptr)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- hr = lpStore->QueryInterface(IID_ECMsgStore, (void **)lppECMsgStore);
- if(hr != hrSuccess)
- delete lpStore;
- return hr;
- }
- HRESULT ECMsgStorePublic::QueryInterface(REFIID refiid, void **lppInterface)
- {
- return ECMsgStore::QueryInterface(refiid, lppInterface);
- }
- HRESULT ECMsgStorePublic::GetPropHandler(ULONG ulPropTag, void* lpProvider, ULONG ulFlags, LPSPropValue lpsPropValue, void *lpParam, void *lpBase)
- {
- HRESULT hr = hrSuccess;
- auto lpStore = static_cast<ECMsgStorePublic *>(lpParam);
- switch(ulPropTag) {
- case PR_IPM_SUBTREE_ENTRYID:
- return ::GetPublicEntryId(ePE_IPMSubtree, lpStore->GetStoreGuid(), lpBase, &lpsPropValue->Value.bin.cb, (LPENTRYID*)&lpsPropValue->Value.bin.lpb);
- case PR_IPM_PUBLIC_FOLDERS_ENTRYID:
- return ::GetPublicEntryId(ePE_PublicFolders, lpStore->GetStoreGuid(), lpBase, &lpsPropValue->Value.bin.cb, (LPENTRYID*)&lpsPropValue->Value.bin.lpb);
- case PR_IPM_FAVORITES_ENTRYID:
- return ::GetPublicEntryId(ePE_Favorites, lpStore->GetStoreGuid(), lpBase, &lpsPropValue->Value.bin.cb, (LPENTRYID*)&lpsPropValue->Value.bin.lpb);
- case PR_EC_PUBLIC_IPM_SUBTREE_ENTRYID:
- hr = lpStore->HrGetRealProp(PR_IPM_SUBTREE_ENTRYID, ulFlags, lpBase, lpsPropValue);
- if (hr == hrSuccess)
- lpsPropValue->ulPropTag = PR_EC_PUBLIC_IPM_SUBTREE_ENTRYID;
- return hr;
- default:
- return MAPI_E_NOT_FOUND;
- }
- }
- HRESULT ECMsgStorePublic::SetPropHandler(ULONG ulPropTag, void *lpProvider,
- const SPropValue *lpsPropValue, void *lpParam)
- {
- SPropValue sPropValue;
- auto lpStore = static_cast<ECMsgStorePublic *>(lpParam);
- switch(ulPropTag) {
- case PR_EC_PUBLIC_IPM_SUBTREE_ENTRYID:
- sPropValue.ulPropTag = PR_IPM_SUBTREE_ENTRYID;
- sPropValue.Value = lpsPropValue->Value; // Cheap copy
- return lpStore->HrSetRealProp(&sPropValue);
- default:
- return MAPI_E_NOT_FOUND;
- }
- }
- HRESULT ECMsgStorePublic::SetEntryId(ULONG cbEntryId, LPENTRYID lpEntryId)
- {
- HRESULT hr;
-
- hr = ECMsgStore::SetEntryId(cbEntryId, lpEntryId);
- if(hr != hrSuccess)
- return hr;
- return BuildIPMSubTree();
- }
- HRESULT ECMsgStorePublic::OpenEntry(ULONG cbEntryID, LPENTRYID lpEntryID, LPCIID lpInterface, ULONG ulFlags, ULONG *lpulObjType, LPUNKNOWN *lppUnk)
- {
- HRESULT hr = hrSuccess;
- unsigned int ulObjType = 0;
- object_ptr<ECMAPIFolder> lpMAPIFolder;
- BOOL fModifyObject = FALSE;
- enumPublicEntryID ePublicEntryID = ePE_None;
- ULONG ulResult = 0;
- object_ptr<IECPropStorage> lpPropStorage;
- object_ptr<WSMAPIFolderOps> lpFolderOps;
- memory_ptr<SPropValue> lpsPropValue, lpParentProp;
- memory_ptr<ENTRYID> lpEntryIDIntern;
- ULONG ulResults;
- // Check input/output variables
- if (lpulObjType == nullptr || lppUnk == nullptr)
- return MAPI_E_INVALID_PARAMETER;
- if(ulFlags & MAPI_MODIFY) {
- if (!fModify)
- return MAPI_E_NO_ACCESS;
- else
- fModifyObject = TRUE;
- }
- if(ulFlags & MAPI_BEST_ACCESS)
- fModifyObject = fModify;
- // Open always online the root folder
- if (cbEntryID == 0 || lpEntryID == nullptr)
- return ECMsgStore::OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, lppUnk);
- hr = HrCompareEntryIdWithStoreGuid(cbEntryID, lpEntryID, &GetStoreGuid());
- if(hr != hrSuccess)
- return hr;
- if(ComparePublicEntryId(ePE_IPMSubtree, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE)
- ePublicEntryID = ePE_IPMSubtree;
- else if(ComparePublicEntryId(ePE_Favorites, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE)
- ePublicEntryID = ePE_Favorites;
- else if(ComparePublicEntryId(ePE_PublicFolders, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE)
- ePublicEntryID = ePE_PublicFolders;
- else if (lpEntryID && (lpEntryID->abFlags[3] & KOPANO_FAVORITE)) {
- ePublicEntryID = ePE_FavoriteSubFolder;
- // Replace the original entryid because this one is only readable
- hr = MAPIAllocateBuffer(cbEntryID, &~lpEntryIDIntern);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpEntryIDIntern, lpEntryID, cbEntryID);
- // Remove Flags intern
- lpEntryIDIntern->abFlags[3] &= ~KOPANO_FAVORITE;
- lpEntryID = lpEntryIDIntern;
- }
-
- hr = HrGetObjTypeFromEntryId(cbEntryID, (LPBYTE)lpEntryID, &ulObjType);
- if(hr != hrSuccess)
- return hr;
- if (ulObjType != MAPI_FOLDER && ePublicEntryID != ePE_FavoriteSubFolder)
- // Open online Messages.
- // On success, message is open, now we can exit
- return ECMsgStore::OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, lppUnk);
- switch( ulObjType ) {
- case MAPI_FOLDER:
- if (ePublicEntryID == ePE_PublicFolders) {
- hr = MAPIAllocateBuffer(sizeof(SPropValue), &~lpsPropValue);
- if(hr != hrSuccess)
- return hr;
- // Get the online Subtree entryid
- hr = HrGetRealProp(PR_IPM_SUBTREE_ENTRYID, 0, lpsPropValue, lpsPropValue);
- if(hr != hrSuccess)
- return hr;
- cbEntryID = lpsPropValue->Value.bin.cb;
- lpEntryID = (LPENTRYID)lpsPropValue->Value.bin.lpb;
- }
- if (ePublicEntryID != ePE_IPMSubtree && ePublicEntryID != ePE_Favorites) {
- hr = lpTransport->HrOpenFolderOps(cbEntryID, lpEntryID, &~lpFolderOps);
- if(hr != hrSuccess)
- return hr;
- } else {
- lpFolderOps.reset();
- }
- hr = ECMAPIFolderPublic::Create(this, fModifyObject, lpFolderOps, ePublicEntryID, &~lpMAPIFolder);
- if(hr != hrSuccess)
- return hr;
- if (ePublicEntryID != ePE_IPMSubtree && ePublicEntryID != ePE_Favorites) {
- //FIXME: Wrong parent entryid
- hr = lpTransport->HrOpenPropStorage(m_cbEntryId, m_lpEntryId, cbEntryID, lpEntryID, ulFlags & SHOW_SOFT_DELETES, &~lpPropStorage);
- if(hr != hrSuccess)
- return hr;
- hr = lpMAPIFolder->HrSetPropStorage(lpPropStorage, TRUE);
- if(hr != hrSuccess)
- return hr;
- //if(ePublicEntryID == ePE_FavoriteSubFolder)
- //lpEntryID->abFlags[3] = KOPANO_FAVORITE;
- } else {
- lpMAPIFolder->HrLoadEmptyProps();
- }
- hr = lpMAPIFolder->SetEntryId(cbEntryID, lpEntryID);
- if(hr != hrSuccess)
- return hr;
- // Get the parent entryid of a folder a check if this is the online subtree entryid. When it is,
- // change the parent to the static parent entryid
- hr = MAPIAllocateBuffer(sizeof(SPropValue), &~lpsPropValue);
- if(hr != hrSuccess)
- return hr;
- if (HrGetOneProp((LPMAPIPROP)(&lpMAPIFolder->m_xMAPIFolder), PR_PARENT_ENTRYID, &~lpParentProp) == hrSuccess &&
- HrGetRealProp(PR_IPM_SUBTREE_ENTRYID, 0, lpsPropValue, lpsPropValue) == hrSuccess &&
- CompareEntryIDs(lpsPropValue->Value.bin.cb, (LPENTRYID)lpsPropValue->Value.bin.lpb, lpParentProp->Value.bin.cb, (LPENTRYID)lpParentProp->Value.bin.lpb, 0, &ulResults) == hrSuccess &&
- ulResults == TRUE)
- lpMAPIFolder->SetParentID(this->m_cIPMPublicFoldersID, this->m_lpIPMPublicFoldersID);
- AddChild(lpMAPIFolder);
- if(lpInterface)
- hr = lpMAPIFolder->QueryInterface(*lpInterface,(void **)lppUnk);
- else
- hr = lpMAPIFolder->QueryInterface(IID_IMAPIFolder, (void **)lppUnk);
- if(lpulObjType)
- *lpulObjType = MAPI_FOLDER;
- break;
- case MAPI_MESSAGE:
- //FIXME: change for offline support
- hr = ECMsgStore::OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, lppUnk);
- if (hr != hrSuccess)
- return hr;
- break;
- default:
- return MAPI_E_NOT_FOUND;
- }
- return hr;
- }
- HRESULT ECMsgStorePublic::InitEntryIDs()
- {
- HRESULT hr;
- if (m_lpIPMSubTreeID == NULL) {
- hr = ::GetPublicEntryId(ePE_IPMSubtree, GetStoreGuid(), NULL, &m_cIPMSubTreeID, &m_lpIPMSubTreeID);
- if(hr != hrSuccess)
- return hr;
- }
- if (m_lpIPMPublicFoldersID == NULL) {
- hr = ::GetPublicEntryId(ePE_PublicFolders, GetStoreGuid(), NULL, &m_cIPMPublicFoldersID, &m_lpIPMPublicFoldersID);
- if(hr != hrSuccess)
- return hr;
- }
- if (m_lpIPMFavoritesID == NULL) {
- hr = ::GetPublicEntryId(ePE_Favorites, GetStoreGuid(), NULL, &m_cIPMFavoritesID, &m_lpIPMFavoritesID);
- if(hr != hrSuccess)
- return hr;
- }
- return hrSuccess;
- }
- HRESULT ECMsgStorePublic::GetPublicEntryId(enumPublicEntryID ePublicEntryID, void *lpBase, ULONG *lpcbEntryID, LPENTRYID *lppEntryID)
- {
- ULONG cbPublicID = 0;
- LPENTRYID lpPublicID = NULL;
- LPENTRYID lpEntryID = NULL;
- HRESULT hr = InitEntryIDs();
- if(hr != hrSuccess)
- return hr;
- if (lpcbEntryID == NULL || lppEntryID == NULL)
- return MAPI_E_INVALID_PARAMETER;
- switch(ePublicEntryID)
- {
- case ePE_IPMSubtree:
- cbPublicID = m_cIPMSubTreeID;
- lpPublicID = m_lpIPMSubTreeID;
- break;
- case ePE_PublicFolders:
- cbPublicID = m_cIPMPublicFoldersID;
- lpPublicID = m_lpIPMPublicFoldersID;
- break;
- case ePE_Favorites:
- cbPublicID = m_cIPMFavoritesID;
- lpPublicID = m_lpIPMFavoritesID;
- break;
- default:
- return MAPI_E_INVALID_PARAMETER;
- }
- if (lpBase)
- hr = MAPIAllocateMore(cbPublicID, lpBase, (void**)&lpEntryID);
- else
- hr = MAPIAllocateBuffer(cbPublicID, (void**)&lpEntryID);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpEntryID, lpPublicID, cbPublicID);
- *lpcbEntryID = cbPublicID;
- *lppEntryID = lpEntryID;
- return hrSuccess;
- }
- HRESULT ECMsgStorePublic::ComparePublicEntryId(enumPublicEntryID ePublicEntryID, ULONG cbEntryID, LPENTRYID lpEntryID, ULONG *lpulResult)
- {
- HRESULT hr;
- ULONG ulResult = 0;
- ULONG cbPublicID = 0;
- LPENTRYID lpPublicID = NULL;
- hr = InitEntryIDs();
- if(hr != hrSuccess)
- return hr;
- if (lpEntryID == NULL || lpulResult == NULL)
- return MAPI_E_INVALID_PARAMETER;
- switch(ePublicEntryID)
- {
- case ePE_IPMSubtree:
- cbPublicID = m_cIPMSubTreeID;
- lpPublicID = m_lpIPMSubTreeID;
- break;
- case ePE_PublicFolders:
- cbPublicID = m_cIPMPublicFoldersID;
- lpPublicID = m_lpIPMPublicFoldersID;
- break;
- case ePE_Favorites:
- cbPublicID = m_cIPMFavoritesID;
- lpPublicID = m_lpIPMFavoritesID;
- break;
- default:
- return MAPI_E_INVALID_PARAMETER;
- }
- hr = GetMsgStore()->CompareEntryIDs(cbEntryID, lpEntryID, cbPublicID, lpPublicID, 0, &ulResult);
- if(hr != hrSuccess)
- return hr;
- *lpulResult = ulResult;
- return hrSuccess;
- }
- HRESULT ECMsgStorePublic::BuildIPMSubTree()
- {
- HRESULT hr = hrSuccess;
- ECMemTable *lpIPMSubTree = NULL;
- memory_ptr<SPropValue> lpProps;
- ULONG cProps = 0;
- ULONG cMaxProps = 0;
- ULONG ulRowId = 0;
- SPropValue sKeyProp;
- static constexpr const SizedSPropTagArray(13, sPropsHierarchyColumns) = {13, {
- PR_ENTRYID, PR_DISPLAY_NAME_W,
- PR_CONTENT_COUNT, PR_CONTENT_UNREAD,
- PR_STORE_ENTRYID, PR_STORE_RECORD_KEY,
- PR_STORE_SUPPORT_MASK, PR_INSTANCE_KEY,
- PR_RECORD_KEY, PR_ACCESS, PR_ACCESS_LEVEL,
- PR_OBJECT_TYPE, PR_FOLDER_TYPE} };
- if (m_lpIPMSubTree != NULL){
- assert(false);
- return hrSuccess;
- }
- hr = ECMemTable::Create(sPropsHierarchyColumns, PR_ROWID, &lpIPMSubTree);
- if(hr != hrSuccess)
- return hr;
- // Favorites
- ulRowId = 1;
- cMaxProps = 22;
- hr = MAPIAllocateBuffer(sizeof(SPropValue) * cMaxProps, &~lpProps);
- if(hr != hrSuccess)
- return hr;
- lpProps[cProps].ulPropTag = PR_ENTRYID;
- hr = GetPublicEntryId(ePE_Favorites, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_LONGTERM_ENTRYID_FROM_TABLE;
- hr = GetPublicEntryId(ePE_Favorites, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_DISPLAY_TYPE;
- lpProps[cProps++].Value.ul = DT_FOLDER;
- lpProps[cProps].ulPropTag = PR_DEPTH;
- lpProps[cProps++].Value.ul = 1;
- lpProps[cProps].ulPropTag = PR_PARENT_ENTRYID;
- hr = GetPublicEntryId(ePE_IPMSubtree, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if (hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_DISPLAY_NAME_W;
- lpProps[cProps++].Value.lpszW = _W("Favorites"); // FIXME: Use dynamic name, read from global profile (like exchange)
- lpProps[cProps].ulPropTag = PR_CONTENT_COUNT;
- lpProps[cProps++].Value.ul = 0;
- lpProps[cProps].ulPropTag = PR_CONTENT_UNREAD;
- lpProps[cProps++].Value.ul = 0;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_ENTRYID, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_RECORD_KEY, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_SUPPORT_MASK, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- lpProps[cProps].ulPropTag = PR_INSTANCE_KEY;
- lpProps[cProps].Value.bin.cb = sizeof(ULONG)*2;
- hr = MAPIAllocateMore(lpProps[cProps].Value.bin.cb, lpProps, (void**)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- memset(lpProps[cProps].Value.bin.lpb, 0, lpProps[cProps].Value.bin.cb );
- memcpy(lpProps[cProps].Value.bin.lpb, &ulRowId, sizeof(ULONG));
- ++cProps;
- lpProps[cProps].ulPropTag = PR_RECORD_KEY;
- hr = GetPublicEntryId(ePE_Favorites, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_ACCESS;
- lpProps[cProps++].Value.ul = MAPI_ACCESS_READ;
- lpProps[cProps].ulPropTag = PR_ACCESS_LEVEL;
- lpProps[cProps++].Value.ul = 0;
- lpProps[cProps].ulPropTag = PR_RIGHTS;
- lpProps[cProps++].Value.ul = ecRightsAll;
- lpProps[cProps].ulPropTag = PR_SUBFOLDERS;
- lpProps[cProps++].Value.b = true;
- lpProps[cProps].ulPropTag = PR_OBJECT_TYPE;
- lpProps[cProps++].Value.ul = MAPI_FOLDER;
- lpProps[cProps].ulPropTag = PR_FOLDER_TYPE;
- lpProps[cProps++].Value.ul = FOLDER_GENERIC;
- lpProps[cProps].ulPropTag = PR_ROWID;
- lpProps[cProps++].Value.ul = ulRowId;
- sKeyProp.ulPropTag = PR_ROWID;
- sKeyProp.Value.ul = ulRowId;
- hr = lpIPMSubTree->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpProps, cProps);
- if (hr != hrSuccess)
- return hr;
- assert(cProps <= cMaxProps);
- // the folder "Public Folders"
- ++ulRowId;
- cProps = 0;
- cMaxProps = 20;
- hr = MAPIAllocateBuffer(sizeof(SPropValue) * cMaxProps, &~lpProps);
- if(hr != hrSuccess)
- return hr;
- lpProps[cProps].ulPropTag = PR_ENTRYID;
- hr = ((ECMsgStorePublic*)GetMsgStore())->GetPublicEntryId(ePE_PublicFolders, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
-
- lpProps[cProps].ulPropTag = PR_LONGTERM_ENTRYID_FROM_TABLE;
- hr = GetPublicEntryId(ePE_PublicFolders, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_DISPLAY_TYPE;
- lpProps[cProps++].Value.ul = DT_FOLDER;
- lpProps[cProps].ulPropTag = PR_DEPTH;
- lpProps[cProps++].Value.ul = 1;
- lpProps[cProps].ulPropTag = PR_PARENT_ENTRYID;
- hr = GetPublicEntryId(ePE_IPMSubtree, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if (hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_DISPLAY_NAME_W;
- lpProps[cProps++].Value.lpszW = _W("Public Folders"); // FIXME: Use dynamic name, read from global profile (like exchange)
- lpProps[cProps].ulPropTag = PR_CONTENT_COUNT;
- lpProps[cProps++].Value.ul = 0;
- lpProps[cProps].ulPropTag = PR_CONTENT_UNREAD;
- lpProps[cProps++].Value.ul = 0;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_ENTRYID, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_RECORD_KEY, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- if (ECMAPIProp::DefaultMAPIGetProp(PR_STORE_SUPPORT_MASK, this, 0, &lpProps[cProps], this, lpProps) == hrSuccess)
- ++cProps;
- lpProps[cProps].ulPropTag = PR_INSTANCE_KEY;
- lpProps[cProps].Value.bin.cb = sizeof(ULONG)*2;
- hr = MAPIAllocateMore(lpProps[cProps].Value.bin.cb, lpProps, (void**)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- memset(lpProps[cProps].Value.bin.lpb, 0, lpProps[cProps].Value.bin.cb );
- memcpy(lpProps[cProps].Value.bin.lpb, &ulRowId, sizeof(ULONG));
- ++cProps;
- lpProps[cProps].ulPropTag = PR_RECORD_KEY;
- hr = GetPublicEntryId(ePE_PublicFolders, lpProps, &lpProps[cProps].Value.bin.cb, (LPENTRYID*)&lpProps[cProps].Value.bin.lpb);
- if(hr != hrSuccess)
- return hr;
- ++cProps;
- lpProps[cProps].ulPropTag = PR_ACCESS;
- lpProps[cProps++].Value.ul = 2; //FIXME: use variable
- lpProps[cProps].ulPropTag = PR_ACCESS_LEVEL;
- lpProps[cProps++].Value.ul = 1;
- //lpProps[cProps].ulPropTag = PR_RIGHTS;
- //lpProps[cProps++].Value.ul = 1;
- lpProps[cProps].ulPropTag = PR_SUBFOLDERS;
- lpProps[cProps++].Value.b = true;
- lpProps[cProps].ulPropTag = PR_OBJECT_TYPE;
- lpProps[cProps++].Value.ul = MAPI_FOLDER;
- lpProps[cProps].ulPropTag = PR_FOLDER_TYPE;
- lpProps[cProps++].Value.ul = FOLDER_GENERIC;
- lpProps[cProps].ulPropTag = PR_ROWID;
- lpProps[cProps++].Value.ul = ulRowId;
- sKeyProp.ulPropTag = PR_ROWID;
- sKeyProp.Value.ul = ulRowId;
- hr = lpIPMSubTree->HrModifyRow(ECKeyTable::TABLE_ROW_ADD, &sKeyProp, lpProps, cProps);
- if (hr != hrSuccess)
- return hr;
- assert(cProps <= cMaxProps);
- m_lpIPMSubTree = lpIPMSubTree;
- return hrSuccess;
- }
- ECMemTable *ECMsgStorePublic::GetIPMSubTree()
- {
- assert(m_lpIPMSubTree != NULL);
- return m_lpIPMSubTree;
- }
- HRESULT ECMsgStorePublic::GetDefaultShortcutFolder(IMAPIFolder** lppFolder)
- {
- HRESULT hr = hrSuccess;
- ULONG ulObjType;
- object_ptr<IMAPIFolder> lpFolder;
- object_ptr<IMsgStore> lpMsgStore;
- memory_ptr<SPropValue> lpPropValue;
- ULONG cbEntryId;
- memory_ptr<ENTRYID> lpEntryId, lpStoreEntryID;
- ULONG cbStoreEntryID;
- string strRedirServer;
- object_ptr<WSTransport> lpTmpTransport;
- if (m_lpDefaultMsgStore == NULL)
- {
- // Get the default store for this user
- hr = lpTransport->HrGetStore(0, NULL, &cbStoreEntryID, &~lpStoreEntryID, NULL, NULL, &strRedirServer);
- if (hr == MAPI_E_UNABLE_TO_COMPLETE) {
- // reopen store of user which is on another server
- hr = lpTransport->CreateAndLogonAlternate(strRedirServer.c_str(), &~lpTmpTransport);
- if (hr != hrSuccess)
- goto exit;
- hr = lpTmpTransport->HrGetStore(0, NULL, &cbStoreEntryID, &~lpStoreEntryID, NULL, NULL);
- }
- if(hr != hrSuccess)
- goto exit;
- hr = WrapStoreEntryID(0, (LPTSTR)WCLIENT_DLL_NAME, cbStoreEntryID, lpStoreEntryID, &cbEntryId, &~lpEntryId);
- if(hr != hrSuccess)
- goto exit;
- // Open default store
- hr = lpSupport->OpenEntry(cbEntryId, lpEntryId, &IID_IMsgStore, MAPI_BEST_ACCESS, &ulObjType, &~lpMsgStore);
- if(hr != hrSuccess)
- goto exit;
- hr = lpMsgStore->QueryInterface(IID_IMsgStore, (void**)&m_lpDefaultMsgStore);
- if (hr != hrSuccess)
- goto exit;
- }
- // Get shortcut entryid
- hr = HrGetOneProp(m_lpDefaultMsgStore, PR_IPM_FAVORITES_ENTRYID, &~lpPropValue);
- if(hr != hrSuccess)
- goto exit;
- // Open Shortcut folder
- hr = m_lpDefaultMsgStore->OpenEntry(lpPropValue->Value.bin.cb, reinterpret_cast<ENTRYID *>(lpPropValue->Value.bin.lpb), &IID_IMAPIFolder, MAPI_BEST_ACCESS, &ulObjType, &~lpFolder);
- if (hr != hrSuccess)
- goto exit;
- hr = lpFolder->QueryInterface(IID_IMAPIFolder, (void**)lppFolder);
- if (hr != hrSuccess)
- goto exit;
- exit:
- if (lpTmpTransport != nullptr)
- lpTmpTransport->HrLogOff();
- return hr;
- }
- HRESULT ECMsgStorePublic::Advise(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulEventMask, LPMAPIADVISESINK lpAdviseSink, ULONG *lpulConnection)
- {
- HRESULT hr = hrSuccess;
- ULONG ulResult = 0;
- memory_ptr<ENTRYID> lpEntryIDIntern;
- if(ComparePublicEntryId(ePE_IPMSubtree, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE) {
- return MAPI_E_NO_SUPPORT; // FIXME
- } else if(ComparePublicEntryId(ePE_Favorites, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE) {
- return MAPI_E_NO_SUPPORT; // FIXME
- } else if(ComparePublicEntryId(ePE_PublicFolders, cbEntryID, lpEntryID, &ulResult) == hrSuccess && ulResult == TRUE) {
- return MAPI_E_NO_SUPPORT; // FIXME
- } else if (lpEntryID && (lpEntryID->abFlags[3] & KOPANO_FAVORITE)) {
- // Replace the original entryid because this one is only readable
- hr = MAPIAllocateBuffer(cbEntryID, &~lpEntryIDIntern);
- if (hr != hrSuccess)
- return hr;
- memcpy(lpEntryIDIntern, lpEntryID, cbEntryID);
- // Remove Flags intern
- lpEntryIDIntern->abFlags[3] &= ~KOPANO_FAVORITE;
- lpEntryID = lpEntryIDIntern;
- }
- return ECMsgStore::Advise(cbEntryID, lpEntryID, ulEventMask, lpAdviseSink, lpulConnection);
- }
|