123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /*
- * 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/ECInterfaceDefs.h>
- #include <kopano/memory.hpp>
- #include "ECFreeBusyData.h"
- #include "ECEnumFBBlock.h"
- namespace KC {
- ECFreeBusyData::ECFreeBusyData(void)
- {
- m_rtmStart = 0;
- m_rtmEnd = 0;
- }
- HRESULT ECFreeBusyData::Init(LONG rtmStart, LONG rtmEnd, ECFBBlockList* lpfbBlockList)
- {
- if(lpfbBlockList == NULL)
- return MAPI_E_INVALID_PARAMETER;
- m_rtmStart = rtmStart;
- m_rtmEnd = rtmEnd;
- m_fbBlockList.Copy(lpfbBlockList);
- // Update the start time if missing.
- if (m_rtmStart == 0) {
- FBBlock_1 blk;
- if (m_fbBlockList.Next(&blk) == hrSuccess)
- m_rtmStart = blk.m_tmStart;
- m_fbBlockList.Reset();
- }
- // Update the end time if missing.
- if (m_rtmEnd == 0)
- m_fbBlockList.GetEndTime(&m_rtmEnd);
- return hrSuccess;
- }
- HRESULT ECFreeBusyData::Create(ECFreeBusyData **lppECFreeBusyData)
- {
- HRESULT hr = hrSuccess;
- auto lpECFreeBusyData = new(std::nothrow) ECFreeBusyData;
- if (lpECFreeBusyData == nullptr)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- hr = lpECFreeBusyData->QueryInterface(IID_ECFreeBusyData, (void **)lppECFreeBusyData);
- if(hr != hrSuccess)
- delete lpECFreeBusyData;
- return hr;
- }
- HRESULT ECFreeBusyData::QueryInterface(REFIID refiid, void** lppInterface)
- {
- REGISTER_INTERFACE2(ECFreeBusyData, this);
- REGISTER_INTERFACE2(ECUnknown, this);
- REGISTER_INTERFACE2(IFreeBusyData, &this->m_xFreeBusyData);
- REGISTER_INTERFACE(IID_ECUnknown, &this->m_xFreeBusyData);
- /*NEW*/ REGISTER_INTERFACE2(IUnknown, &this->m_xFreeBusyData);
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- HRESULT ECFreeBusyData::EnumBlocks(IEnumFBBlock **ppenumfb, FILETIME ftmStart, FILETIME ftmEnd)
- {
- HRESULT hr = S_OK;
- LONG rtmStart = 0;
- LONG rtmEnd = 0;
- KCHL::object_ptr<ECEnumFBBlock> lpECEnumFBBlock;
- if(ppenumfb == NULL)
- return MAPI_E_INVALID_PARAMETER;
- FileTimeToRTime(&ftmStart, &rtmStart);
- FileTimeToRTime(&ftmEnd, &rtmEnd);
- hr = m_fbBlockList.Restrict(rtmStart, rtmEnd);
- if(hr != hrSuccess)
- return hr;
- hr = ECEnumFBBlock::Create(&m_fbBlockList, &~lpECEnumFBBlock);
- if(hr != hrSuccess)
- return hr;
- return lpECEnumFBBlock->QueryInterface(IID_IEnumFBBlock, (void**)ppenumfb);
- }
- /**
- * Documentation of this function cannot be found. This is what I think it does.
- *
- * Find first free block inside the specified range <ulBegin,ulEnd]. Note that ulBegin is non-inclusive, so
- * the earliest block that can be returned is starts at ulBegin + 1.
- *
- * I think that this function should normally look for the first position in the given range in which the specified
- * duration (ulMinutes) fits. However, in practice, it is only called to check if range <ulBegin, ulEnd] is free, since
- * ulEnd - ulBegin - 1 == ulMinutes. This means we can use a much simpler algorithm, and just check if the entire range
- * is free, and return that if it is.
- *
- * It is my theory that someone made this function, but later found out that it is not very useful since you always want to
- * find a specific slot, not the first slot that fits, so now it is only used to check for availability.
- *
- * @param ulBegin Begin time as RTIME
- * @param ulMinutes Duration of the slot to find
- * @param ulNumber (Guess) Number of resources that should be free at this moment (always one in my tests)
- * @param bA (Unknown) always TRUE
- * @param ulEnd End time as RTIME
- * @param ulUnknown Unknown, always 0
- * @param ulMinutesPerDay Unknown, always set to 1440 ( = 24 * 60 )
- * @result 0 for OK, anything else is an error
- */
- HRESULT ECFreeBusyData::FindFreeBlock(LONG ulBegin, LONG ulMinutes, LONG ulNumber, BOOL bA, LONG ulEnd, LONG ulUnknown, LONG ulMinutesPerDay, FBBlock_1 *lpBlock)
- {
- HRESULT hr;
- FBBlock_1 sBlock;
- BOOL bOverlap = false;
- if (ulBegin + 1 + ulMinutes > ulEnd)
- // Requested slot can never fit between start and end
- return MAPI_E_NOT_FOUND;
- m_fbBlockList.Reset();
- // Loop through FB data to find if there is a block that overlaps the requested slot
- while(TRUE) {
- hr = m_fbBlockList.Next(&sBlock);
- if(hr != hrSuccess)
- break;
- if(sBlock.m_tmStart >= ulEnd)
- break;
- if(sBlock.m_tmEnd > ulBegin+1 && sBlock.m_tmStart < ulEnd) {
- bOverlap = true;
- break;
- }
- }
- if (bOverlap)
- return MAPI_E_NOT_FOUND;
- lpBlock->m_fbstatus = fbFree;
- lpBlock->m_tmStart = ulBegin+1;
- lpBlock->m_tmEnd = lpBlock->m_tmStart + ulMinutes;
- return hrSuccess;
- }
- HRESULT ECFreeBusyData::SetFBRange(LONG rtmStart, LONG rtmEnd)
- {
- m_rtmStart = rtmStart;
- m_rtmEnd = rtmEnd;
- return S_OK;
- }
- HRESULT ECFreeBusyData::GetFBPublishRange(LONG *prtmStart, LONG *prtmEnd)
- {
- if(prtmStart == NULL || prtmEnd == NULL)
- return MAPI_E_INVALID_PARAMETER;
- *prtmStart = m_rtmStart;
- *prtmEnd = m_rtmEnd;
- return S_OK;
- }
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, QueryInterface, (REFIID, refiid), (void**, lppInterface))
- DEF_ULONGMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, AddRef, (void))
- DEF_ULONGMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, Release, (void))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, Reload, (void*, lpData))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, EnumBlocks, (IEnumFBBlock **, ppenumfb), (FILETIME, ftmStart), (FILETIME, ftmEnd))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, Merge, (void*, lpData))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, GetDelegateInfo, (void*, lpData))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, FindFreeBlock, (LONG, ulBegin), (LONG, ulMinutes), (LONG, ulNumber), (BOOL, bA), (LONG, ulEnd), (LONG, ulUnknown), (LONG, ulMinutesPerDay), (FBBlock_1 *, lpData))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, InterSect, (void *, lpData1), (LONG, ulA), (void *, lpData2))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, SetFBRange, (LONG, rtmStart), (LONG, rtmEnd))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, NextFBAppt, (void *, lpData1), (ULONG, ulA), (void *, lpData2), (ULONG, ulB), (void *, lpData3), (void *, lpData4))
- DEF_HRMETHOD1(TRACE_MAPI, ECFreeBusyData, FreeBusyData, GetFBPublishRange, (LONG *, prtmStart), (LONG *, prtmEnd))
- } /* namespace */
|