XTPCalendarMAPIDataProvider.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:110k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPCalendarMAPIDataProvider.cpp: implementation of the CXTPCalendarMAPIDataProvider class.
  2. //
  3. // This file is a part of the XTREME CALENDAR MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPVC80Helpers.h"
  22. #include "Common/XTPVC50Helpers.h"
  23. #include "Common/XTPPropExchange.h"
  24. #include "Common/XTPNotifyConnection.h"
  25. #include "XTPCalendarMAPIDataProvider.h"
  26. #include "XTPCalendarMemoryDataProvider.h"
  27. #include "XTPCalendarCustomProperties.h"
  28. #include "XTPCalendarNotifications.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. //#define XTP_TRACE_READ_EVENTS TRACE
  35. #ifndef XTP_TRACE_READ_EVENTS
  36. #define XTP_TRACE_READ_EVENTS //1 ? (void)0 : TRACE
  37. #endif
  38. //#define XTP_TRACE_READ_IDS TRACE
  39. #ifndef XTP_TRACE_READ_IDS
  40. #define XTP_TRACE_READ_IDS //1 ? (void)0 : TRACE
  41. #endif
  42. //#define XTP_TRACE_MAPI_NF TRACE
  43. #ifndef XTP_TRACE_MAPI_NF
  44. #define XTP_TRACE_MAPI_NF //1 ? (void)0 : TRACE
  45. #endif
  46. #define MAPI_FREEBUFFER(pProvider, pBuffer) if (pProvider && pBuffer) { pProvider->MAPIFreeBuffer(pBuffer); pBuffer = NULL;}
  47. #define MAPI_RELEASE(pProvider, x) if (pProvider && x) { pProvider->UlRelease(x); x = 0;}
  48. //long xtp_dbg_SafeRelease(void* pp)
  49. //{
  50. //  IUnknown** ppInterface = (IUnknown**)pp;
  51. //
  52. //  long nRes = -1;
  53. //  if (ppInterface && *ppInterface)
  54. //  {
  55. //      nRes = (*ppInterface)->Release();
  56. //      *ppInterface = 0;
  57. //  }
  58. //  return nRes;
  59. //}
  60. //#define MAPI_RELEASE(pProvider, x) xtp_dbg_SafeRelease(&x);
  61. #define cFileTimeUnitsPerSecond 10000000i64
  62. //////////////////////////////////////////////////////////////////////////
  63. IMPLEMENT_DYNAMIC(CXTPCalendarMAPIDataProvider, CXTPCalendarData)
  64. /////////////////////////////////////////////////////////////////////////////
  65. template<class _T>
  66. _T xtpGetDataT(const CByteArray& arData, int nOffset)
  67. {
  68. if (nOffset < 0)
  69. {
  70. return 0;
  71. }
  72. if ((int)(nOffset + sizeof(_T)) > (int)arData.GetSize())
  73. {
  74. ASSERT(FALSE);
  75. return 0;
  76. }
  77. const _T* pDataT = (const _T*)(arData.GetData() + nOffset);
  78. return *pDataT;
  79. }
  80. //---------------------------------------------------------------------------
  81. template<class _T>
  82. _T xtpGetNextDataT(const BYTE*& rpData, const BYTE* pMax = NULL)
  83. {
  84. if (!rpData || pMax && (rpData + sizeof(_T)) > pMax)
  85. {
  86. ASSERT(FALSE);
  87. return 0;
  88. }
  89. const _T* pDataT = (const _T*)(rpData);
  90. rpData += sizeof(_T);
  91. return *pDataT;
  92. }
  93. //---------------------------------------------------------------------------
  94. CString xtpGetNextData_MapiExcStr8(const BYTE*& rpData, const BYTE* pMax = NULL)
  95. {
  96. if (!rpData)
  97. {
  98. ASSERT(FALSE);
  99. return _T("");
  100. }
  101. // layout: [w:buf-size][w:str-len][ascii-char: count=len]
  102. int nBuffer = (int)xtpGetNextDataT<WORD>(rpData, pMax);
  103. UNUSED_ALWAYS(nBuffer);
  104. int nStrLen = (int)xtpGetNextDataT<WORD>(rpData, pMax);
  105. if (pMax && (rpData + nStrLen) > pMax)
  106. {
  107. ASSERT(FALSE);
  108. return _T("");
  109. }
  110. CString strData = CONSTRUCT_S((char*)rpData, nStrLen);
  111. rpData += nStrLen;
  112. return strData;
  113. }
  114. //===========================================================================
  115. template<class _T>
  116. void xtpAddDataT(CByteArray& rarData, _T tValue)
  117. {
  118. int nSize = sizeof(_T);
  119. BYTE* pBytes = (BYTE*)&tValue;
  120. for (int i = 0; i < nSize; i++)
  121. {
  122. rarData.Add(pBytes[i]);
  123. }
  124. }
  125. //---------------------------------------------------------------------------
  126. template<class _T>
  127. int xtpSetDataT(CByteArray& rarData, int nOffset, _T tValue)
  128. {
  129. if (nOffset < 0)
  130. {
  131. return nOffset;
  132. }
  133. int nValueSize = sizeof(_T);
  134. if (rarData.GetSize() < nOffset + nValueSize)
  135. {
  136. rarData.SetSize(nOffset + nValueSize, 4096);
  137. }
  138. _T* pValue = &tValue;
  139. _T* pDest = (_T*)(rarData.GetData() + nOffset);
  140. *pDest = *pValue;
  141. return nOffset + nValueSize;
  142. }
  143. //---------------------------------------------------------------------------
  144. void xtpAddData_MapiExcStr8(CByteArray& rarData, LPCTSTR pcszString)
  145. {
  146. // layout: [w:buf-size][w:str-len][ascii-char: count=len]
  147. int nStrLenW = (int)_tcslen(pcszString);
  148. int nStrSize = nStrLenW*2 + 1;
  149. CHAR* pStr = new CHAR[nStrSize];
  150. if (!pStr)
  151. {
  152. xtpAddDataT<WORD>(rarData, 1);
  153. xtpAddDataT<WORD>(rarData, 0);
  154. return;
  155. }
  156. ZeroMemory(pStr, nStrSize);
  157. WCSTOMBS_S(pStr, pcszString, nStrSize-1);
  158. int nStrLen = (int)strlen(pStr);
  159. int nBuffer = nStrLen + 1;
  160. xtpAddDataT<WORD>(rarData, (WORD)nBuffer);
  161. xtpAddDataT<WORD>(rarData, (WORD)nStrLen);
  162. int nSize = (int)rarData.GetSize();
  163. rarData.SetSize(nSize + nStrLen, 4096);
  164. void* pDest = rarData.GetData() + nSize;
  165. MEMCPY_S(pDest, pStr, nStrLen);
  166. delete[] pStr;
  167. }
  168. //===========================================================================
  169. void xtp_GetWinTZInfo(const CByteArray& arMapiTZInfo,
  170.   TIME_ZONE_INFORMATION* pTZInfo)
  171. {
  172. if (arMapiTZInfo.GetSize() < sizeof(XTP_MAPI_TIME_ZONE_INFORMATION) || !pTZInfo)
  173. {
  174. ASSERT(FALSE);
  175. return;
  176. }
  177. XTP_MAPI_TIME_ZONE_INFORMATION* pMapiTZInfo;
  178. pMapiTZInfo = (XTP_MAPI_TIME_ZONE_INFORMATION*)arMapiTZInfo.GetData();
  179. ZeroMemory(pTZInfo, sizeof(TIME_ZONE_INFORMATION));
  180. pTZInfo->Bias         = pMapiTZInfo->Bias;
  181. pTZInfo->StandardBias = pMapiTZInfo->StandardBias;
  182. pTZInfo->DaylightBias = pMapiTZInfo->DaylightBias;
  183. pTZInfo->StandardDate = pMapiTZInfo->StandardDate;
  184. pTZInfo->DaylightDate = pMapiTZInfo->DaylightDate;
  185. }
  186. void xtp_GetMapiTZInfo(TIME_ZONE_INFORMATION* pTZInfo, CByteArray& arMapiTZInfo)
  187. {
  188. XTP_MAPI_TIME_ZONE_INFORMATION* pMapiTZInfo;
  189. arMapiTZInfo.SetSize(sizeof(XTP_MAPI_TIME_ZONE_INFORMATION));
  190. pMapiTZInfo = (XTP_MAPI_TIME_ZONE_INFORMATION*)arMapiTZInfo.GetData();
  191. ZeroMemory(pMapiTZInfo, sizeof(XTP_MAPI_TIME_ZONE_INFORMATION));
  192. pMapiTZInfo->Bias         = pTZInfo->Bias;
  193. pMapiTZInfo->StandardBias = pTZInfo->StandardBias;
  194. pMapiTZInfo->DaylightBias = pTZInfo->DaylightBias;
  195. pMapiTZInfo->StandardDate = pTZInfo->StandardDate;
  196. pMapiTZInfo->DaylightDate = pTZInfo->DaylightDate;
  197. }
  198. COleDateTime xtp_UtcToTzTime(const TIME_ZONE_INFORMATION* pTZI,
  199.  const SYSTEMTIME& stUtcTime)
  200. {
  201. SYSTEMTIME stTzTime;
  202. if (!CXTPCalendarUtils::SystemTimeToTzSpecificLocalTime(pTZI, &stUtcTime, &stTzTime))
  203. {
  204. return (DATE)0;
  205. }
  206. COleDateTime dtTzTime(stTzTime);
  207. return dtTzTime;
  208. }
  209. SYSTEMTIME xtp_TimeToUtc(const COleDateTime& dtTzTime)
  210. {
  211. SYSTEMTIME stUtcTime;
  212. ZeroMemory(&stUtcTime, sizeof(stUtcTime));
  213. SYSTEMTIME stTzTime;
  214. if (!GETASSYSTEMTIME_DT(dtTzTime, stTzTime) )
  215. {
  216. return stUtcTime;
  217. }
  218. FILETIME ftTz;
  219. if (!SystemTimeToFileTime(&stTzTime, &ftTz))
  220. {
  221. return stUtcTime;
  222. }
  223. FILETIME ftUtc;
  224. if (!LocalFileTimeToFileTime(&ftTz, &ftUtc))
  225. {
  226. return stUtcTime;
  227. }
  228. if (!FileTimeToSystemTime(&ftUtc, &stUtcTime))
  229. {
  230. ZeroMemory(&stUtcTime, sizeof(stUtcTime));
  231. }
  232. return stUtcTime;
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. class CXTPCalendarMAPI_Recurrence
  236. {
  237. public:
  238. // Holds byte offsets of data fields within MAPI binary field
  239. struct XTP_RCDATA_LAYOUT
  240. {
  241. int     nType;          // radioSelector;
  242. int     nType2;         // type
  243. int     nRCShiftX;      // magic MAPI number. Probably used to generate occurrences.
  244. int     nInterval;      // interval;
  245. int     nRegenerate;    // regenerate   // for tasks only
  246. int     nWeekDayMask;   // weekDayMask  // week Of Month
  247. int     nInstance;      // instance
  248. int     nEndByType;     // endByType
  249. int     nOccurrences;
  250. int     nDynData;       // Unaligned data offset
  251. };
  252. // 0 - Daily, 1 - Weekly, 2 - MonYearly, 3 - MonYearly_Nth
  253. static XTP_RCDATA_LAYOUT s_arRCDataLayout[4];
  254. //=======================================================================
  255. class CXTPRcException
  256. {
  257. public:
  258. DWORD   dwNewStart;
  259. DWORD   dwNewEnd;
  260. DWORD   dwOrigStart;
  261. BOOL    bDeleted;
  262. WORD    wFlags;
  263. CString strSubject;     // xtpMAPIRcED_Subject
  264. BOOL    bIsMeeting;     // xtpMAPIRcED_IsMeeting
  265. int     nReminderTime;  // xtpMAPIRcED_ReminderTime
  266. BOOL    bIsReminder;    // xtpMAPIRcED_IsReminder
  267. CString strLocation;    // xtpMAPIRcED_Location
  268. int     nBusyStatus;    // xtpMAPIRcED_BusyStatus - enum XTPCalendarEventBusyStatus
  269. BOOL    bIsAllDay;      // xtpMAPIRcED_IsAllDay
  270. int     nLabel;         // xtpMAPIRcED_Label
  271. CXTPRcException();
  272. const CXTPRcException& operator=(const CXTPRcException& rSrc);
  273. void Set(CXTPCalendarEvent* pExc, CXTPCalendarEvent* pMaster);
  274. };
  275. class CXTPRcExceptions : public CArray<CXTPRcException, CXTPRcException&>
  276. {
  277. public:
  278. CXTPRcExceptions(){};
  279. virtual ~CXTPRcExceptions(){};
  280. int FindByOrigStart(DWORD dwOrigStart);
  281. void SortByOrigStart();
  282. void SortByNewStart();
  283. protected:
  284. typedef int (_cdecl* T_CompareFunc)(const CXTPRcException* pExc1, const CXTPRcException* pExc2);
  285. void _Sort(T_CompareFunc);
  286. static int _cdecl CompareAsc_ByOrigStart(const CXTPRcException* pExc1, const CXTPRcException* pExc2);
  287. static int _cdecl CompareAsc_ByNewStart(const CXTPRcException* pExc1, const CXTPRcException* pExc2);
  288. };
  289. //=======================================================================
  290. //struct XTP_RCDATA
  291. class CXTPRcData
  292. {
  293. public:
  294. WORD    wType;
  295. BYTE    ucType2;
  296. DWORD   dwRCShiftX;
  297. DWORD   dwInterval;
  298. DWORD   dwWeekDayMask;
  299. BYTE    ucInstance;
  300. DWORD   dwEndByType;
  301. DWORD   dwOccurrences;
  302. DWORD   dwEndDate;
  303. DWORD   dwStartDate;
  304. DWORD   dwOccStartTime;
  305. DWORD   dwOccEndTime;
  306. CXTPRcExceptions arExceptions;
  307. CXTPRcData();
  308. virtual ~CXTPRcData(){};
  309. };
  310. static BOOL ReadRCData(CXTPRcData& rRCData, const CByteArray& arRCData);
  311. static void SetRecurrenceOptions(CXTPCalendarRecurrencePattern* pPattern,
  312. const CXTPRcData& RCData);
  313. static void SetRecurrenceExceptions(CXTPCalendarEvent* pMasterEvent,
  314. CXTPCalendarRecurrencePattern* pPattern,
  315. const CXTPRcData& RCData);
  316. //-----------------------------------------------------------------------
  317. static BOOL FillRCData( CXTPRcData& rRCData,
  318. CXTPCalendarRecurrencePattern* pPattern,
  319. CXTPCalendarEvent* pMaster);
  320. static BOOL RCDataToBin(CXTPRcData& rRCData, CByteArray& rarRCData);
  321. static COleDateTime ConvertRecurrenceMinutesToDate(DWORD dwMinutes);
  322. static DWORD ConvertRecurrenceDateToMinutes(COleDateTime date);
  323. protected:
  324. static void _ReadRCDataExceptions (CXTPRcData& rRCData, const BYTE* pExcData,
  325. const BYTE* pMaxPtr, const BYTE* pExclusions);
  326. static DWORD _CalcRCShiftX(CXTPCalendarRecurrencePattern* pPattern);
  327. };
  328. //
  329. //  MAPI recurrence layouts definitions
  330. //
  331. CXTPCalendarMAPI_Recurrence::XTP_RCDATA_LAYOUT
  332. CXTPCalendarMAPI_Recurrence::s_arRCDataLayout[] =
  333. {
  334. //  daily
  335. {
  336. 4,  // type
  337. 6,  // type2
  338. 10, // RCShiftX
  339. 14, // interval
  340. 18, // regenerate
  341. -1, // weekDayMask
  342. -1, // instance
  343. 22, // endByType
  344. 26, // nOccurrences
  345. 26 + 2 * sizeof(DWORD) // nDynData
  346. },
  347. //  weakly
  348. {
  349. 4,  // type
  350. 6,  // type2
  351. 10, // RCShiftX
  352. 14, // interval
  353. 18, // regenerate
  354. 22, // weekDayMask
  355. -1, // instance
  356. 26, // endByType
  357. 30, // nOccurrences
  358. 30 + 2 * sizeof(DWORD) // nDynData
  359. },
  360. //  monthly
  361. {
  362. 4,  // type
  363. 6,  // type2
  364. 10, // RCShiftX
  365. 14, // interval
  366. 18, // regenerate
  367. -1, // weekDayMask
  368. 22, // instance
  369. 26, // endByType
  370. 30, // nOccurrences
  371. 30 + 2 * sizeof(DWORD) // nDynData
  372. },
  373. //  monthly Nth ()
  374. {
  375. 4,  // type
  376. 6,  // type2
  377. 10, // RCShiftX
  378. 14, // interval
  379. 18, // regenerate
  380. 22, // weekDayMask
  381. 26, // instance
  382. 30, // endByType
  383. 34, // nOccurrences
  384. 34 + 2 * sizeof(DWORD) // nDynData
  385. },
  386. };
  387. //////////////////////////////////////////////////////////////////////////
  388. CXTPCalendarMAPI_Recurrence::CXTPRcException::CXTPRcException()
  389. {
  390. dwNewStart = 0;
  391. dwNewEnd = 0;
  392. dwOrigStart = 0;
  393. bDeleted = FALSE;
  394. wFlags = 0;
  395. //strSubject;
  396. bIsMeeting = FALSE;
  397. nReminderTime = 0;
  398. bIsReminder = FALSE;
  399. //strLocation;
  400. nBusyStatus = 0;
  401. bIsAllDay = FALSE;
  402. nLabel = 0;
  403. }
  404. void CXTPCalendarMAPI_Recurrence::CXTPRcException::Set(CXTPCalendarEvent* pExc, CXTPCalendarEvent* pMaster)
  405. {
  406. CXTPRcException rexZero;
  407. *this = rexZero;
  408. if (!pExc || !pMaster)
  409. {
  410. ASSERT(FALSE);
  411. return;
  412. }
  413. wFlags = 0;
  414. bDeleted = pExc->IsRExceptionDeleted();
  415. dwOrigStart = CXTPCalendarMAPI_Recurrence::ConvertRecurrenceDateToMinutes(pExc->GetRException_StartTimeOrig());
  416. if (bDeleted)
  417. {
  418. return;
  419. }
  420. dwNewStart = CXTPCalendarMAPI_Recurrence::ConvertRecurrenceDateToMinutes(pExc->GetStartTime());
  421. dwNewEnd = CXTPCalendarMAPI_Recurrence::ConvertRecurrenceDateToMinutes(pExc->GetEndTime());
  422. if (pExc->GetSubject() != pMaster->GetSubject())
  423. {
  424. wFlags |= xtpMAPIRcED_Subject;
  425. strSubject = pExc->GetSubject();
  426. }
  427. if (pExc->IsMeeting() != pMaster->IsMeeting())
  428. {
  429. wFlags |= xtpMAPIRcED_IsMeeting;
  430. bIsMeeting = pExc->IsMeeting();
  431. }
  432. if (pExc->GetReminderMinutesBeforeStart() != pMaster->GetReminderMinutesBeforeStart())
  433. {
  434. wFlags |= xtpMAPIRcED_ReminderTime;
  435. nReminderTime = pExc->GetReminderMinutesBeforeStart();
  436. }
  437. if (pExc->IsReminder() != pMaster->IsReminder())
  438. {
  439. wFlags |= xtpMAPIRcED_IsReminder;
  440. bIsReminder = pExc->IsReminder();
  441. }
  442. if (pExc->GetLocation() != pMaster->GetLocation())
  443. {
  444. wFlags |= xtpMAPIRcED_Location;
  445. strLocation = pExc->GetLocation();
  446. }
  447. if (pExc->GetBusyStatus() != pMaster->GetBusyStatus())
  448. {
  449. wFlags |= xtpMAPIRcED_BusyStatus;
  450. nBusyStatus = pExc->GetBusyStatus();
  451. }
  452. if (pExc->IsAllDayEvent() != pMaster->IsAllDayEvent())
  453. {
  454. wFlags |= xtpMAPIRcED_IsAllDay;
  455. bIsAllDay = pExc->IsAllDayEvent();
  456. }
  457. if (pExc->GetLabelID() != pMaster->GetLabelID())
  458. {
  459. wFlags |= xtpMAPIRcED_Label;
  460. nLabel = pExc->GetLabelID();
  461. }
  462. }
  463. const CXTPCalendarMAPI_Recurrence::CXTPRcException&
  464. CXTPCalendarMAPI_Recurrence::CXTPRcException::operator= (
  465. const CXTPCalendarMAPI_Recurrence::CXTPRcException& rSrc)
  466. {
  467. dwNewStart = rSrc.dwNewStart;
  468. dwNewEnd = rSrc.dwNewEnd;
  469. dwOrigStart = rSrc.dwOrigStart;
  470. bDeleted = rSrc.bDeleted;
  471. wFlags = rSrc.wFlags;
  472. strSubject = rSrc.strSubject;
  473. bIsMeeting = rSrc.bIsMeeting;
  474. nReminderTime = rSrc.nReminderTime;
  475. bIsReminder = rSrc.bIsReminder;
  476. strLocation = rSrc.strLocation;
  477. nBusyStatus = rSrc.nBusyStatus;
  478. bIsAllDay = rSrc.bIsAllDay;
  479. nLabel = rSrc.nLabel;
  480. return *this;
  481. }
  482. int CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::FindByOrigStart(DWORD dwOrigStart)
  483. {
  484. int nCount = (int)GetSize();
  485. for (int i = 0; i < nCount; i++)
  486. {
  487. const CXTPRcException& rce = ElementAt(i);
  488. if (rce.dwOrigStart == dwOrigStart)
  489. {
  490. return i;
  491. }
  492. }
  493. return -1;
  494. }
  495. void CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::SortByOrigStart()
  496. {
  497. _Sort(CompareAsc_ByOrigStart);
  498. }
  499. void CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::SortByNewStart()
  500. {
  501. _Sort(CompareAsc_ByNewStart);
  502. }
  503. void CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::_Sort(T_CompareFunc pCompareFunc)
  504. {
  505. typedef int (_cdecl *GENERICCOMPAREFUNC)(const void *, const void*);
  506. qsort(GetData(), (size_t)GetSize(), sizeof(CXTPRcException),
  507.  (GENERICCOMPAREFUNC)pCompareFunc);
  508. }
  509. int _cdecl CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::CompareAsc_ByOrigStart(const CXTPRcException* pExc1, const CXTPRcException* pExc2)
  510. {
  511. if (pExc1->dwOrigStart < pExc2->dwOrigStart)
  512. {
  513. return -1;
  514. }
  515. if (pExc1->dwOrigStart > pExc2->dwOrigStart)
  516. {
  517. return 1;
  518. }
  519. return 0;
  520. }
  521. int _cdecl CXTPCalendarMAPI_Recurrence::CXTPRcExceptions::CompareAsc_ByNewStart(const CXTPRcException* pExc1, const CXTPRcException* pExc2)
  522. {
  523. if (pExc1->dwNewStart < pExc2->dwNewStart)
  524. {
  525. return -1;
  526. }
  527. if (pExc1->dwNewStart > pExc2->dwNewStart)
  528. {
  529. return 1;
  530. }
  531. return 0;
  532. }
  533. /////////////////////////////////////////////////////////////////////////////
  534. CXTPCalendarMAPI_Recurrence::CXTPRcData::CXTPRcData()
  535. {
  536. wType = 0;
  537. ucType2 = 0;
  538. dwRCShiftX = 0;
  539. dwInterval = 0;
  540. dwWeekDayMask = 0;
  541. ucInstance = 0;
  542. dwEndByType = 0;
  543. dwOccurrences = 0;
  544. dwEndDate = 0;
  545. dwStartDate = 0;
  546. dwOccStartTime = 0;
  547. dwOccEndTime = 0;
  548. //arExceptions;
  549. }
  550. BOOL CXTPCalendarMAPI_Recurrence::ReadRCData(
  551. CXTPCalendarMAPI_Recurrence::CXTPRcData& rRCData,
  552. const CByteArray& arRCData)
  553. {
  554. XTPCalendarMAPIRcType eRCType;
  555. XTPCalendarMAPIRcType2 eRCType2;
  556. eRCType =  (XTPCalendarMAPIRcType)xtpGetDataT<WORD>(arRCData, s_arRCDataLayout[0].nType);
  557. eRCType2 = (XTPCalendarMAPIRcType2)xtpGetDataT<BYTE>(arRCData, s_arRCDataLayout[0].nType2);
  558. BOOL bTypeValid = eRCType == xtpMAPIRcType_Daily    || eRCType == xtpMAPIRcType_Weekly ||
  559.   eRCType == xtpMAPIRcType_Monthly    || eRCType == xtpMAPIRcType_Yearly;
  560. if (eRCType2 < xtpMAPIRcType2_First || eRCType2 > xtpMAPIRcType2_Last || !bTypeValid)
  561. {
  562. return FALSE;
  563. }
  564. XTP_RCDATA_LAYOUT RCLayout;
  565. ::ZeroMemory(&RCLayout, sizeof(RCLayout));
  566. // select layout
  567. RCLayout = s_arRCDataLayout[eRCType2];
  568. rRCData.wType = xtpGetDataT<WORD>(arRCData, RCLayout.nType);
  569. rRCData.ucType2 = xtpGetDataT<BYTE>(arRCData, RCLayout.nType2);
  570. rRCData.dwRCShiftX = xtpGetDataT<DWORD>(arRCData, RCLayout.nRCShiftX);
  571. rRCData.dwInterval = xtpGetDataT<DWORD>(arRCData, RCLayout.nInterval);
  572. rRCData.dwWeekDayMask = xtpGetDataT<DWORD>(arRCData, RCLayout.nWeekDayMask);
  573. rRCData.ucInstance = xtpGetDataT<BYTE>(arRCData, RCLayout.nInstance);
  574. rRCData.dwEndByType = xtpGetDataT<DWORD>(arRCData, RCLayout.nEndByType);
  575. rRCData.dwOccurrences = xtpGetDataT<DWORD>(arRCData, RCLayout.nOccurrences);
  576. //
  577. const BYTE* p = arRCData.GetData() + RCLayout.nDynData;
  578. const BYTE* pMax = arRCData.GetData() + arRCData.GetSize();
  579. const BYTE* pExclusions = p;
  580. // skip old and new dates
  581. p += sizeof(DWORD) * (xtpGetNextDataT<DWORD>(p, pMax)); // skip old start dates
  582. p += sizeof(DWORD) * (xtpGetNextDataT<DWORD>(p, pMax)); // old new start dates
  583. // pick up start/end dates
  584. //Pattern Start Date
  585. rRCData.dwStartDate = xtpGetNextDataT<DWORD>(p, pMax);
  586. // /*DBG*/ ConvertRecurrenceMinutesToDate(rRCData.dwStartDate);
  587. //Pattern End Date
  588. rRCData.dwEndDate = xtpGetNextDataT<DWORD>(p, pMax);
  589. // /*DBG*/ ConvertRecurrenceMinutesToDate(rRCData.dwEndDate);
  590. // skip unknown reserved fields
  591. xtpGetNextDataT<DWORD>(p, pMax);
  592. xtpGetNextDataT<DWORD>(p, pMax);
  593. // Occurrence start/end time - in minutes from the day begin
  594. // hour = time / 60, minute = time % 60
  595. rRCData.dwOccStartTime = xtpGetNextDataT<DWORD>(p, pMax);
  596. rRCData.dwOccEndTime = xtpGetNextDataT<DWORD>(p, pMax);
  597. //p - points to detailed exceptions information.
  598. _ReadRCDataExceptions(rRCData, p, pMax, pExclusions);
  599. return TRUE;
  600. }
  601. void CXTPCalendarMAPI_Recurrence::_ReadRCDataExceptions(
  602. CXTPCalendarMAPI_Recurrence::CXTPRcData& rRCData,
  603. const BYTE* pExcData, const BYTE* pMaxPtr,
  604. const BYTE* pExclusions
  605. )
  606. {
  607. // read detailed recurrence exceptions information
  608. int nCount = (int)xtpGetNextDataT<WORD>(pExcData, pMaxPtr);
  609. int i;
  610. for (i = 0; i < nCount; i++)
  611. {
  612. CXTPRcException RCExc;
  613. RCExc.dwNewStart = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  614. RCExc.dwNewEnd = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  615. RCExc.dwOrigStart = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  616. RCExc.wFlags = xtpGetNextDataT<WORD>(pExcData, pMaxPtr);
  617. if (RCExc.wFlags & xtpMAPIRcED_Subject)
  618. {
  619. // layout: [w:buf-size][w:str-len][ascii-char: count=len]
  620. RCExc.strSubject = xtpGetNextData_MapiExcStr8(pExcData, pMaxPtr);
  621. }
  622. if (RCExc.wFlags & xtpMAPIRcED_IsMeeting)
  623. {
  624. // layout: [dw] - bool(0|1)
  625. RCExc.bIsMeeting = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr) != 0;
  626. }
  627. if (RCExc.wFlags & xtpMAPIRcED_ReminderTime)
  628. {
  629. // layout: [dw] minutes before start
  630. RCExc.nReminderTime = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  631. }
  632. if (RCExc.wFlags & xtpMAPIRcED_IsReminder)
  633. {
  634. // layout: [dw] - bool(0|1)
  635. RCExc.bIsReminder = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr) != 0;
  636. }
  637. if (RCExc.wFlags & xtpMAPIRcED_Location)
  638. {
  639. // layout: [w:buf-size][w:str-len][ascii-char: count=len]
  640. RCExc.strLocation = xtpGetNextData_MapiExcStr8(pExcData, pMaxPtr);
  641. }
  642. if (RCExc.wFlags & xtpMAPIRcED_BusyStatus)
  643. {
  644. // layout: [dw] - busy status [0..3] = XTPCalendarEventBusyStatus
  645. RCExc.nBusyStatus = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  646. }
  647. if (RCExc.wFlags & xtpMAPIRcED_IsAllDay)
  648. {
  649. // layout: [dw] - bool(0|1)
  650. RCExc.bIsAllDay = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr) != 0;
  651. }
  652. if (RCExc.wFlags & xtpMAPIRcED_Label)
  653. {
  654. // layout: [dw] -
  655. RCExc.nLabel = xtpGetNextDataT<DWORD>(pExcData, pMaxPtr);
  656. }
  657. rRCData.arExceptions.Add(RCExc);
  658. }
  659. ASSERT(rRCData.dwOccEndTime >= rRCData.dwOccStartTime);
  660. // determine and add deleted exceptions
  661. nCount = (int)xtpGetNextDataT<DWORD>(pExclusions, pMaxPtr);
  662. for (i = 0; i < nCount; i++)
  663. {
  664. CXTPRcException RCExc;
  665. RCExc.dwOrigStart = xtpGetNextDataT<DWORD>(pExclusions, pMaxPtr);
  666. RCExc.dwOrigStart += rRCData.dwOccStartTime;
  667. RCExc.bDeleted = TRUE;
  668. if (rRCData.arExceptions.FindByOrigStart(RCExc.dwOrigStart) < 0)
  669. {
  670. rRCData.arExceptions.Add(RCExc);
  671. }
  672. }
  673. }
  674. void CXTPCalendarMAPI_Recurrence::SetRecurrenceOptions(
  675. CXTPCalendarRecurrencePattern* pPattern,
  676. const CXTPCalendarMAPI_Recurrence::CXTPRcData& RCData)
  677. {
  678. ASSERT(pPattern);
  679. if (!pPattern)
  680. {
  681. return;
  682. }
  683. XTP_CALENDAR_RECURRENCE_OPTIONS opt;
  684. // Recurrence type
  685. switch(RCData.wType)
  686. {
  687. case xtpMAPIRcType_Daily:
  688. {
  689. opt.m_nRecurrenceType = xtpCalendarRecurrenceDaily;
  690. opt.m_Daily.bEveryWeekDayOnly = (RCData.ucType2 == xtpMAPIRcType2_Weekly);
  691. if (opt.m_Daily.bEveryWeekDayOnly)
  692. {
  693. opt.m_Daily.nIntervalDays = 1;
  694. }
  695. else
  696. {
  697. ASSERT(RCData.dwInterval % (24 * 60) == 0);
  698. opt.m_Daily.nIntervalDays = (int)RCData.dwInterval / (24 * 60);
  699. }
  700. }
  701. break;
  702. case xtpMAPIRcType_Weekly:
  703. {
  704. opt.m_nRecurrenceType = xtpCalendarRecurrenceWeekly;
  705. ASSERT(RCData.ucType2 == xtpMAPIRcType2_Weekly); // == 1, 0 only for tasks
  706. opt.m_Weekly.nIntervalWeeks = (int)RCData.dwInterval;
  707. opt.m_Weekly.nDayOfWeekMask = (int)RCData.dwWeekDayMask;
  708. }
  709. break;
  710. case xtpMAPIRcType_Monthly:
  711. {
  712. if (RCData.ucType2 == xtpMAPIRcType2_MonYearly)
  713. {
  714. opt.m_nRecurrenceType = xtpCalendarRecurrenceMonthly;
  715. opt.m_Monthly.nIntervalMonths = (int)RCData.dwInterval;
  716. opt.m_Monthly.nDayOfMonth = (int)RCData.ucInstance;
  717. }
  718. else if (RCData.ucType2 == xtpMAPIRcType2_MonYearly_Nth)
  719. {
  720. opt.m_nRecurrenceType = xtpCalendarRecurrenceMonthNth;
  721. opt.m_MonthNth.nIntervalMonths = (int)RCData.dwInterval;
  722. opt.m_MonthNth.nWhichDay = (int)RCData.ucInstance; // ???
  723. opt.m_MonthNth.nWhichDayMask = (int)RCData.dwWeekDayMask; // ???
  724. }
  725. else
  726. {
  727. ASSERT(FALSE);
  728. }
  729. }
  730. break;
  731. case xtpMAPIRcType_Yearly:
  732. {
  733. ASSERT(RCData.dwInterval % 12 == 0 && RCData.dwInterval);
  734. //---------------------------------------------------------------
  735. int nMonthOfYear = 1;
  736. // days per month   - jan feb mar apr may jun   jul aug sep oct nov dec
  737. static int arDays[] = {31, 28, 31, 30, 31, 30,   31, 31, 30, 31, 30, 31};
  738. int nDaysInMinutes = 0;
  739. for (int i = 0; i < 12; i++)
  740. {
  741. if (nDaysInMinutes >= (int)RCData.dwRCShiftX)
  742. {
  743. nMonthOfYear = i+1;
  744. break;
  745. }
  746. nDaysInMinutes += arDays[i] * 24 * 60;
  747. }
  748. ASSERT(nDaysInMinutes == (int)RCData.dwRCShiftX);
  749. //---------------------------------------------------------------
  750. if (RCData.ucType2 == xtpMAPIRcType2_MonYearly)
  751. {
  752. opt.m_nRecurrenceType = xtpCalendarRecurrenceYearly;
  753. opt.m_Yearly.nDayOfMonth = RCData.ucInstance;
  754. opt.m_Yearly.nMonthOfYear = nMonthOfYear;
  755. }
  756. else if (RCData.ucType2 == xtpMAPIRcType2_MonYearly_Nth)
  757. {
  758. opt.m_nRecurrenceType = xtpCalendarRecurrenceYearNth;
  759. opt.m_YearNth.nWhichDay = RCData.ucInstance;
  760. opt.m_YearNth.nWhichDayMask = RCData.dwWeekDayMask;
  761. opt.m_YearNth.nMonthOfYear = nMonthOfYear;
  762. }
  763. else
  764. {
  765. ASSERT(FALSE);
  766. }
  767. }
  768. break;
  769. default:
  770. ASSERT(FALSE);
  771. }
  772. pPattern->SetRecurrenceOptions(opt);
  773. pPattern->SetPatternStartDate(ConvertRecurrenceMinutesToDate(RCData.dwStartDate));
  774. XTP_CALENDAR_PATTERN_END rpEnd;
  775. switch(RCData.dwEndByType)
  776. {
  777. case xtpMAPIRcEnd_Date:
  778. rpEnd.m_nUseEnd = xtpCalendarPatternEndDate;
  779. rpEnd.m_dtPatternEndDate = ConvertRecurrenceMinutesToDate(RCData.dwEndDate);
  780. break;
  781. case xtpMAPIRcEnd_Number:
  782. rpEnd.m_nUseEnd = xtpCalendarPatternEndAfterOccurrences;
  783. rpEnd.m_nEndAfterOccurrences = RCData.dwOccurrences;
  784. break;
  785. case xtpMAPIRcEnd_Never:
  786. rpEnd.m_nUseEnd = xtpCalendarPatternEndNoDate;
  787. break;
  788. default: // Use no end date by default
  789. rpEnd.m_nUseEnd = xtpCalendarPatternEndNoDate;
  790. }
  791. pPattern->SetPatternEnd(rpEnd);
  792. COleDateTime dtOccStartTime;
  793. dtOccStartTime.SetTime(RCData.dwOccStartTime / 60, RCData.dwOccStartTime % 60, 0);
  794. pPattern->SetStartTime(dtOccStartTime);
  795. int nDuration = RCData.dwOccEndTime - RCData.dwOccStartTime;
  796. ASSERT(nDuration >= 0);
  797. pPattern->SetDurationMinutes(nDuration);
  798. }
  799. void CXTPCalendarMAPI_Recurrence::SetRecurrenceExceptions(
  800. CXTPCalendarEvent* pMasterEvent,
  801. CXTPCalendarRecurrencePattern* pPattern,
  802. const CXTPRcData& RCData)
  803. {
  804. if (!pMasterEvent || !pPattern)
  805. {
  806. ASSERT(FALSE);
  807. return;
  808. }
  809. int nCount = (int)RCData.arExceptions.GetSize();
  810. for (int i = 0; i < nCount; i++)
  811. {
  812. const CXTPRcException& RCExc = RCData.arExceptions[i];
  813. COleDateTime dtOrigStart = ConvertRecurrenceMinutesToDate(RCExc.dwOrigStart);
  814. COleDateTime dtOrigEnd = dtOrigStart + pPattern->GetDuration();
  815. CXTPCalendarEventPtr ptrExc = pMasterEvent->CloneForOccurrence(dtOrigStart, dtOrigEnd);
  816. if (!ptrExc)
  817. {
  818. return;
  819. }
  820. VERIFY( ptrExc->MakeAsRException() );
  821. if (RCExc.bDeleted)
  822. {
  823. ptrExc->SetRExceptionDeleted(TRUE);
  824. VERIFY( pPattern->SetException(ptrExc) );
  825. continue;
  826. }
  827. //---------------------------------------------------------------
  828. COleDateTime dtNewStart = dtOrigStart;
  829. COleDateTime dtNewEnd = dtOrigEnd;
  830. if (RCExc.dwNewStart)
  831. {
  832. dtNewStart = ConvertRecurrenceMinutesToDate(RCExc.dwNewStart);
  833. }
  834. if (RCExc.dwNewEnd)
  835. {
  836. dtNewEnd = ConvertRecurrenceMinutesToDate(RCExc.dwNewEnd);
  837. }
  838. ptrExc->SetStartTime(dtNewStart);
  839. ptrExc->SetEndTime(dtNewEnd);
  840. //---------------------------------------------------------------
  841. if (RCExc.wFlags & xtpMAPIRcED_Subject)
  842. {
  843. ptrExc->SetSubject(RCExc.strSubject);
  844. }
  845. if (RCExc.wFlags & xtpMAPIRcED_IsMeeting)
  846. {
  847. ptrExc->SetMeeting(RCExc.bIsMeeting);
  848. }
  849. if (RCExc.wFlags & xtpMAPIRcED_ReminderTime)
  850. {
  851. ptrExc->SetReminderMinutesBeforeStart(RCExc.nReminderTime);
  852. }
  853. if (RCExc.wFlags & xtpMAPIRcED_IsReminder)
  854. {
  855. ptrExc->SetReminder(RCExc.bIsReminder);
  856. }
  857. if (RCExc.wFlags & xtpMAPIRcED_Location)
  858. {
  859. ptrExc->SetLocation(RCExc.strLocation);
  860. }
  861. if (RCExc.wFlags & xtpMAPIRcED_BusyStatus)
  862. {
  863. ASSERT(RCExc.nBusyStatus < 4);
  864. if (RCExc.nBusyStatus >= 0 && RCExc.nBusyStatus < 4)
  865. {
  866. ptrExc->SetBusyStatus(RCExc.nBusyStatus);
  867. }
  868. }
  869. ASSERT((RCExc.wFlags & xtpMAPIRcED_Reserved) == 0);
  870. if (RCExc.wFlags & xtpMAPIRcED_IsAllDay)
  871. {
  872. ptrExc->SetAllDayEvent(RCExc.bIsAllDay);
  873. }
  874. if (RCExc.wFlags & xtpMAPIRcED_Label)
  875. {
  876. ptrExc->SetLabelID(RCExc.nLabel);
  877. }
  878. VERIFY( pPattern->SetException(ptrExc) );
  879. }
  880. }
  881. BOOL CXTPCalendarMAPI_Recurrence::FillRCData(CXTPRcData& rRCData,
  882. CXTPCalendarRecurrencePattern* pPattern,
  883. CXTPCalendarEvent* pMaster)
  884. {
  885. // FileTime zero date
  886. static const COleDateTime cdtFTZero(1601, 1, 1, 0, 0, 0);
  887. if (!pPattern || !pMaster)
  888. {
  889. ASSERT(FALSE);
  890. return FALSE;
  891. }
  892. XTP_CALENDAR_RECURRENCE_OPTIONS opt = pPattern->GetRecurrenceOptions();
  893. switch(opt.m_nRecurrenceType)
  894. {
  895. case xtpCalendarRecurrenceDaily:
  896. {
  897. rRCData.wType = xtpMAPIRcType_Daily;
  898. if (opt.m_Daily.bEveryWeekDayOnly)
  899. {
  900. rRCData.ucType2 = xtpMAPIRcType2_Weekly;
  901. rRCData.dwInterval = 1;
  902. rRCData.dwWeekDayMask = xtpCalendarDayMo_Fr;
  903. }
  904. else
  905. {
  906. rRCData.ucType2 = xtpMAPIRcType2_Daily;
  907. rRCData.dwInterval = opt.m_Daily.nIntervalDays * 24 * 60;
  908. }
  909. }
  910. break;
  911. case xtpCalendarRecurrenceWeekly:
  912. {
  913. rRCData.wType = xtpMAPIRcType_Weekly;
  914. rRCData.ucType2 = xtpMAPIRcType2_Weekly; // = 1, 0 only for tasks
  915. rRCData.dwInterval = opt.m_Weekly.nIntervalWeeks;
  916. rRCData.dwWeekDayMask = opt.m_Weekly.nDayOfWeekMask;
  917. }
  918. break;
  919. case xtpCalendarRecurrenceMonthly:
  920. {
  921. rRCData.wType = xtpMAPIRcType_Monthly;
  922. rRCData.ucType2 = xtpMAPIRcType2_MonYearly;
  923. rRCData.dwInterval = (DWORD)opt.m_Monthly.nIntervalMonths;
  924. rRCData.ucInstance = (BYTE)opt.m_Monthly.nDayOfMonth;
  925. }
  926. break;
  927. case xtpCalendarRecurrenceMonthNth:
  928. {
  929. rRCData.wType = xtpMAPIRcType_Monthly;
  930. rRCData.ucType2 = xtpMAPIRcType2_MonYearly_Nth;
  931. rRCData.dwInterval = (DWORD)opt.m_MonthNth.nIntervalMonths;
  932. rRCData.ucInstance = (BYTE)opt.m_MonthNth.nWhichDay;
  933. rRCData.dwWeekDayMask = (DWORD)opt.m_MonthNth.nWhichDayMask;
  934. }
  935. break;
  936. case xtpCalendarRecurrenceYearly:
  937. {
  938. rRCData.wType = xtpMAPIRcType_Yearly;
  939. rRCData.ucType2 = xtpMAPIRcType2_MonYearly;
  940. rRCData.ucInstance = (BYTE)opt.m_Yearly.nDayOfMonth;
  941. rRCData.dwInterval = 12;
  942. }
  943. break;
  944. case xtpCalendarRecurrenceYearNth:
  945. {
  946. rRCData.wType = xtpMAPIRcType_Yearly;
  947. rRCData.ucType2 = xtpMAPIRcType2_MonYearly_Nth;
  948. rRCData.ucInstance = (BYTE)opt.m_YearNth.nWhichDay;
  949. rRCData.dwWeekDayMask = (DWORD)opt.m_YearNth.nWhichDayMask;
  950. rRCData.dwInterval = 12;
  951. }
  952. break;
  953. default:
  954. ASSERT(FALSE);
  955. }
  956. rRCData.dwRCShiftX = _CalcRCShiftX(pPattern);
  957. rRCData.dwStartDate = ConvertRecurrenceDateToMinutes(pPattern->GetPatternStartDate());
  958. CXTPCalendarDatesArray arOccDates;
  959. XTP_CALENDAR_PATTERN_END rpEnd = pPattern->GetPatternEnd();
  960. switch(rpEnd.m_nUseEnd)
  961. {
  962. case xtpCalendarPatternEndDate:
  963. rRCData.dwEndByType  = xtpMAPIRcEnd_Date;
  964. rRCData.dwEndDate = ConvertRecurrenceDateToMinutes(rpEnd.m_dtPatternEndDate);
  965. pPattern->GetOccurrencesDates(arOccDates, pPattern->GetPatternStartDate(), pPattern->GetPatternEndDate());
  966. rRCData.dwOccurrences = (DWORD)arOccDates.GetSize();
  967. break;
  968. case xtpCalendarPatternEndAfterOccurrences:
  969. rRCData.dwEndByType  = xtpMAPIRcEnd_Number;
  970. rRCData.dwOccurrences = rpEnd.m_nEndAfterOccurrences;
  971. rRCData.dwEndDate = ConvertRecurrenceDateToMinutes(pMaster->GetEndTime());
  972. break;
  973. case xtpCalendarPatternEndNoDate:
  974. rRCData.dwEndByType  = xtpMAPIRcEnd_Never;
  975. break;
  976. default: // Use No end date by default
  977. rRCData.dwEndByType  = xtpMAPIRcEnd_Never;
  978. }
  979. COleDateTime dtOccStartTime = pPattern->GetStartTime();
  980. rRCData.dwOccStartTime = dtOccStartTime.GetHour() * 60 + dtOccStartTime.GetMinute();
  981. int nOccDuration = pPattern->GetDurationMinutes();
  982. if (pMaster->IsAllDayEvent() && ( (nOccDuration % (24 * 60)) || nOccDuration == 0) )
  983. {
  984. // align occurrence duration for full day(s) duration
  985. nOccDuration = (nOccDuration / (24 * 60) + 1) * 24 * 60;
  986. }
  987. rRCData.dwOccEndTime = rRCData.dwOccStartTime + nOccDuration;
  988. //------------------------------------------
  989. CXTPCalendarEventsPtr ptrExcAr = pPattern->GetExceptions();
  990. int nExcCount = ptrExcAr ? ptrExcAr->GetCount() : 0;
  991. for (int i = 0; i < nExcCount; i++)
  992. {
  993. CXTPCalendarEvent* pExc = ptrExcAr->GetAt(i);
  994. CXTPRcException rceTmp;
  995. rceTmp.Set(pExc, pMaster);
  996. rRCData.arExceptions.Add(rceTmp);
  997. }
  998. return TRUE;
  999. }
  1000. BOOL CXTPCalendarMAPI_Recurrence::RCDataToBin(CXTPRcData& RCData, CByteArray& rarData)
  1001. {
  1002. XTP_RCDATA_LAYOUT RCLayout;
  1003. ::ZeroMemory(&RCLayout, sizeof(RCLayout));
  1004. ASSERT(RCData.ucType2 <= 3);
  1005. if (RCData.ucType2 > 3)
  1006. {
  1007. return FALSE;
  1008. }
  1009. // select layout
  1010. RCLayout = s_arRCDataLayout[RCData.ucType2];
  1011. rarData.SetSize(RCLayout.nDynData, 4096);
  1012. // Set header
  1013.  xtpSetDataT<DWORD>(rarData, 0, 0x30043004);
  1014. // Set generic recurrence fields
  1015. xtpSetDataT<WORD> (rarData, RCLayout.nType,         RCData.wType);
  1016. xtpSetDataT<BYTE> (rarData, RCLayout.nType2,        RCData.ucType2);
  1017. xtpSetDataT<DWORD>(rarData, RCLayout.nRCShiftX,     RCData.dwRCShiftX);
  1018. xtpSetDataT<DWORD>(rarData, RCLayout.nInterval,     RCData.dwInterval);
  1019. xtpSetDataT<DWORD>(rarData, RCLayout.nWeekDayMask,  RCData.dwWeekDayMask);
  1020. xtpSetDataT<BYTE> (rarData, RCLayout.nInstance,     RCData.ucInstance);
  1021. xtpSetDataT<DWORD>(rarData, RCLayout.nEndByType,    RCData.dwEndByType);
  1022. xtpSetDataT<DWORD>(rarData, RCLayout.nOccurrences,   RCData.dwOccurrences);
  1023. // Add information about exceptions
  1024. //
  1025. ASSERT(rarData.GetSize() == RCLayout.nDynData);
  1026. int i = 0;
  1027. //- add ALL exceptions dates -----------------------------------------
  1028. RCData.arExceptions.SortByOrigStart();
  1029. int nExcCount = (int)RCData.arExceptions.GetSize();
  1030. xtpAddDataT<DWORD>(rarData, nExcCount);
  1031. for (i = 0; i < nExcCount; i++)
  1032. {
  1033. const CXTPRcException& rce = RCData.arExceptions[i];
  1034. DWORD dwOrigSartDate = (rce.dwOrigStart / 24 / 60) * 24 * 60;
  1035. xtpAddDataT<DWORD>(rarData, dwOrigSartDate);
  1036. }
  1037. //- add changed exception dates -----------------------------------------
  1038. RCData.arExceptions.SortByNewStart();
  1039. int nChangExcCountOffset = (int)rarData.GetSize();
  1040. xtpAddDataT<DWORD>(rarData, 0);
  1041. DWORD dwChangExcCount = 0;
  1042. for (i = 0; i < nExcCount; i++)
  1043. {
  1044. const CXTPRcException& rce = RCData.arExceptions[i];
  1045. if (!rce.bDeleted)
  1046. {
  1047. ASSERT(rce.dwNewStart != 0 && rce.dwNewEnd != 0);
  1048. DWORD dwNewSartDate = (rce.dwNewStart / 24 / 60) * 24 * 60;
  1049. xtpAddDataT<DWORD>(rarData, dwNewSartDate);
  1050. dwChangExcCount++;
  1051. }
  1052. }
  1053. xtpSetDataT<DWORD>(rarData, nChangExcCountOffset, dwChangExcCount);
  1054. // start/end date
  1055. xtpAddDataT<DWORD>(rarData, RCData.dwStartDate);
  1056. if (RCData.dwEndByType == xtpMAPIRcEnd_Date || RCData.dwEndByType == xtpMAPIRcEnd_Number)
  1057. {
  1058. xtpAddDataT<DWORD>(rarData, RCData.dwEndDate);
  1059. }
  1060. else
  1061. {
  1062. ASSERT(RCData.dwEndByType == xtpMAPIRcEnd_Never);
  1063. xtpAddDataT<DWORD>(rarData, 0x5AE980DF);
  1064. }
  1065. // unknown
  1066. xtpAddDataT<DWORD>(rarData, 0x00003006);
  1067. xtpAddDataT<DWORD>(rarData, 0x00003006);
  1068. // start/end time
  1069. xtpAddDataT<DWORD>(rarData, RCData.dwOccStartTime);
  1070. xtpAddDataT<DWORD>(rarData, RCData.dwOccEndTime);
  1071. // detailed exceptions
  1072. xtpAddDataT<WORD>(rarData, (WORD)dwChangExcCount);
  1073. for (i = 0; i < nExcCount; i++)
  1074. {
  1075. const CXTPRcException& rce = RCData.arExceptions[i];
  1076. if (rce.bDeleted)
  1077. {
  1078. continue;
  1079. }
  1080. ASSERT(rce.dwNewStart && rce.dwNewEnd && rce.dwOrigStart);
  1081. xtpAddDataT<DWORD>(rarData, rce.dwNewStart);
  1082. xtpAddDataT<DWORD>(rarData, rce.dwNewEnd);
  1083. xtpAddDataT<DWORD>(rarData, rce.dwOrigStart);
  1084. xtpAddDataT<WORD>(rarData, rce.wFlags);
  1085. if (rce.wFlags & xtpMAPIRcED_Subject)
  1086. {
  1087. xtpAddData_MapiExcStr8(rarData, rce.strSubject);
  1088. }
  1089. if (rce.wFlags & xtpMAPIRcED_IsMeeting)
  1090. {
  1091. // layout: [dw] - bool(0|1)
  1092. xtpAddDataT<DWORD>(rarData, rce.bIsMeeting);
  1093. }
  1094. if (rce.wFlags & xtpMAPIRcED_ReminderTime)
  1095. {
  1096. // layout: [dw] minutes before start
  1097. xtpAddDataT<DWORD>(rarData, rce.nReminderTime);
  1098. }
  1099. if (rce.wFlags & xtpMAPIRcED_IsReminder)
  1100. {
  1101. // layout: [dw] - bool(0|1)
  1102. xtpAddDataT<DWORD>(rarData, rce.bIsReminder);
  1103. }
  1104. if (rce.wFlags & xtpMAPIRcED_Location)
  1105. {
  1106. xtpAddData_MapiExcStr8(rarData, rce.strLocation);
  1107. }
  1108. if (rce.wFlags & xtpMAPIRcED_BusyStatus)
  1109. {
  1110. // layout: [dw] - busy status [0..3] = XTPCalendarEventBusyStatus
  1111. xtpAddDataT<DWORD>(rarData, rce.nBusyStatus);
  1112. }
  1113. if (rce.wFlags & xtpMAPIRcED_IsAllDay)
  1114. {
  1115. // layout: [dw] - bool(0|1)
  1116. xtpAddDataT<DWORD>(rarData, rce.bIsAllDay);
  1117. }
  1118. if (rce.wFlags & xtpMAPIRcED_Label)
  1119. {
  1120. // layout: [dw] -
  1121. xtpAddDataT<DWORD>(rarData, rce.nLabel);
  1122. }
  1123. }
  1124. return TRUE;
  1125. }
  1126. DWORD CXTPCalendarMAPI_Recurrence::_CalcRCShiftX(CXTPCalendarRecurrencePattern* pPattern)
  1127. {
  1128. // FileTime zero date
  1129. static const COleDateTime cdtFTZero(1601, 1, 1, 0, 0, 0);
  1130. ASSERT(pPattern);
  1131. if (!pPattern)
  1132. {
  1133. return 0;
  1134. }
  1135. DWORD dwRCShiftX = 0;
  1136. COleDateTime dtPatternStart = pPattern->GetPatternStartDate();
  1137. COleDateTimeSpan spX;
  1138. XTP_CALENDAR_RECURRENCE_OPTIONS opt = pPattern->GetRecurrenceOptions();
  1139. // xtpMAPIRcType2_Daily
  1140. if (opt.m_nRecurrenceType == xtpCalendarRecurrenceDaily && !opt.m_Daily.bEveryWeekDayOnly)
  1141. {
  1142. spX = dtPatternStart - cdtFTZero;
  1143. int nIntervalDays = max(1, opt.m_Daily.nIntervalDays);
  1144. int nDay = (int)GETTOTAL_DAYS_DTS(spX);
  1145. dwRCShiftX = nDay % nIntervalDays;
  1146. dwRCShiftX *= 24 * 60; // convert to minutes
  1147. }
  1148. // xtpMAPIRcType2_Weekly
  1149. else if (opt.m_nRecurrenceType == xtpCalendarRecurrenceDaily && opt.m_Daily.bEveryWeekDayOnly ||
  1150.  opt.m_nRecurrenceType == xtpCalendarRecurrenceWeekly)
  1151. {
  1152. int nIntervalWeeks = 1;
  1153. if (opt.m_nRecurrenceType == xtpCalendarRecurrenceWeekly)
  1154. {
  1155. nIntervalWeeks = opt.m_Weekly.nIntervalWeeks;
  1156. }
  1157. spX = dtPatternStart - cdtFTZero;
  1158. int nWeek = ((int)(GETTOTAL_DAYS_DTS(spX) + 1)) / 7;
  1159. dwRCShiftX = (nWeek * 7 - 1) % (nIntervalWeeks * 7);
  1160. dwRCShiftX *= 24 * 60; // convert to minutes
  1161. }
  1162. else
  1163. {
  1164. //xtpMAPIRcType2_MonYearly
  1165. //xtpMAPIRcType2_MonYearly_Nth
  1166. int nIntervalMonths = -1;
  1167. if (opt.m_nRecurrenceType == xtpCalendarRecurrenceMonthly)
  1168. {
  1169. nIntervalMonths = opt.m_Monthly.nIntervalMonths;
  1170. }
  1171. else if (opt.m_nRecurrenceType == xtpCalendarRecurrenceMonthNth)
  1172. {
  1173. nIntervalMonths = opt.m_MonthNth.nIntervalMonths;
  1174. }
  1175. else if (opt.m_nRecurrenceType == xtpCalendarRecurrenceYearly ||
  1176.  opt.m_nRecurrenceType == xtpCalendarRecurrenceYearNth)
  1177. {
  1178. nIntervalMonths = 12;
  1179. }
  1180. else
  1181. {
  1182. ASSERT(FALSE);
  1183. return 0;
  1184. }
  1185. nIntervalMonths = max(1, nIntervalMonths);
  1186. // days per month   - jan feb mar apr may jun   jul aug sep oct nov dec
  1187. static int arDays[] = {31, 28, 31, 30, 31, 30,   31, 31, 30, 31, 30, 31};
  1188. int nMonth = dtPatternStart.GetMonth() + 12 * (dtPatternStart.GetYear() - 1601);
  1189. for (int i = 1 ; i < ((nMonth - 1) % nIntervalMonths) + 1; i++ )
  1190. {
  1191. dwRCShiftX += arDays[(i - 1) % 12];
  1192. }
  1193. dwRCShiftX *= 24 * 60; // convert to minutes
  1194. }
  1195. return dwRCShiftX;
  1196. }
  1197. COleDateTime CXTPCalendarMAPI_Recurrence::ConvertRecurrenceMinutesToDate(DWORD dwMinutes)
  1198. {
  1199. COleDateTime dt = (DATE)0;
  1200. ULONGLONG   ullDT = (ULONGLONG) dwMinutes * 60i64 * cFileTimeUnitsPerSecond;
  1201. FILETIME    ft = *((FILETIME*)&ullDT); // { (DWORD) ( fileTimeUnitsBeforeStart & 0xFFFFFFFF), (DWORD) ( fileTimeUnitsBeforeStart >> 32)};
  1202. SYSTEMTIME  st;
  1203. BOOL bRes = ::FileTimeToSystemTime(&ft, &st);
  1204. ASSERT(bRes);
  1205. if (bRes)
  1206. {
  1207. dt = st;
  1208. }
  1209. //  TRACE(_T("MAPItime to DT %d = %sn"), dwMinutes, dt.Format());
  1210. return dt;
  1211. }
  1212. DWORD CXTPCalendarMAPI_Recurrence::ConvertRecurrenceDateToMinutes(COleDateTime dt)
  1213. {
  1214. SYSTEMTIME st;
  1215. FILETIME ft = {0, 0};
  1216. if (!GETASSYSTEMTIME_DT(dt, st))
  1217. {
  1218. ASSERT(FALSE);
  1219. return 0;
  1220. }
  1221. if (!SystemTimeToFileTime(&st, &ft))
  1222. {
  1223. ASSERT(FALSE);
  1224. return 0;
  1225. }
  1226. ULONGLONG ullMinutes =  *((ULONGLONG*)&ft); //( ( (ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
  1227. ullMinutes = ullMinutes / 60i64;
  1228. ullMinutes = ullMinutes / cFileTimeUnitsPerSecond;
  1229. return (DWORD)ullMinutes;
  1230. }
  1231. //////////////////////////////////////////////////////////////////////////
  1232. // see KB239795
  1233. STDMETHODIMP CXTPCalendarMAPIDataProvider::OpenInbox(
  1234. LPMDB lpMDB, LPMAPIFOLDER *lpInboxFolder, LPMAPIFOLDER *lpCalendarFolder, CXTPCalendarMAPIDataProvider* pProvider)
  1235. {
  1236. if (!lpMDB || !pProvider)
  1237. return E_POINTER;
  1238. ULONG        cbInbox;
  1239. LPENTRYID    lpbInbox;
  1240. ULONG        ulObjType;
  1241. HRESULT      hRes = S_OK;
  1242. LPMAPIFOLDER    lpTempFolder = NULL;
  1243. ULONG pCount; SPropValue *props;
  1244. SizedSPropTagArray(1, spec) = {1, {XTP_TAG_ID_MAPI_CALENDAR_FOLDER}};
  1245. *lpInboxFolder = NULL;
  1246. *lpCalendarFolder = NULL;
  1247. // The Inbox is usually the default receive folder for the message store
  1248. // You call this function as a shortcut to get it's Entry ID
  1249. hRes = lpMDB->GetReceiveFolder(
  1250. NULL,      // Get default receive folder
  1251. NULL,      // Flags
  1252. &cbInbox,  // Size and ...
  1253. &lpbInbox, // Value of the EntryID to be returned
  1254. NULL);     // You don't care to see the class returned
  1255. if (SUCCEEDED(hRes))
  1256. {
  1257. hRes = lpMDB->OpenEntry(
  1258. cbInbox,                      // Size and...
  1259. lpbInbox,                     // Value of the Inbox's EntryID
  1260. NULL,                         // We want the default interface    (IMAPIFolder)
  1261. MAPI_BEST_ACCESS,             // Flags
  1262. &ulObjType,                   // Object returned type
  1263. (LPUNKNOWN *) &lpTempFolder); // Returned folder
  1264. if (SUCCEEDED(hRes))
  1265. {
  1266. // Assign the out parameter
  1267. *lpInboxFolder = lpTempFolder;
  1268. // Open Calendar Folder
  1269. hRes = (*lpInboxFolder)->GetProps((SPropTagArray*)&spec, 0, &pCount, &props);
  1270. if (hRes == S_OK || hRes == MAPI_W_ERRORS_RETURNED)
  1271. {
  1272. if (props[0].ulPropTag != PT_ERROR)
  1273. {
  1274. hRes = lpMDB->OpenEntry(
  1275. props[0].Value.bin.cb,            // Size and...
  1276. (ENTRYID*)props[0].Value.bin.lpb, // Value of the Calendar's EntryID
  1277. NULL,                         // We want the default interface (IMAPIFolder)
  1278. MAPI_BEST_ACCESS,             // Flags
  1279. &ulObjType,                   // Object returned type
  1280. (LPUNKNOWN *) &lpTempFolder); // Returned folder
  1281. if (SUCCEEDED(hRes))
  1282. {
  1283. // Assign the out parameter
  1284. *lpCalendarFolder = lpTempFolder;
  1285. }
  1286. }
  1287. }
  1288. if (props)
  1289. {
  1290. pProvider->MAPIFreeBuffer(props);
  1291. props = NULL;
  1292. }
  1293. }
  1294. }
  1295. // Cleanup
  1296. pProvider->MAPIFreeBuffer(lpbInbox);
  1297. return hRes;
  1298. }
  1299. STDMETHODIMP CXTPCalendarMAPIDataProvider::OpenDefaultMessageStore(
  1300.    LPMAPISESSION lpMAPISession, LPMDB * lpMDB, CXTPCalendarMAPIDataProvider* pProvider)
  1301. {
  1302. if (!lpMAPISession || !pProvider)
  1303. return E_POINTER;
  1304. LPMAPITABLE pStoresTbl = NULL;
  1305. LPSRowSet   pRow = NULL;
  1306. static      SRestriction sres;
  1307. SPropValue  spv;
  1308. HRESULT     hRes;
  1309. LPMDB       lpTempMDB = NULL;
  1310. enum {EID, NAME, NUM_COLS};
  1311. static SizedSPropTagArray(NUM_COLS,sptCols) = {NUM_COLS, PR_ENTRYID, PR_DISPLAY_NAME};
  1312. *lpMDB = NULL;
  1313. //Get the table of all the message stores available
  1314. hRes = lpMAPISession->GetMsgStoresTable(0, &pStoresTbl);
  1315. if (SUCCEEDED(hRes))
  1316. {
  1317. //Set up restriction for the default store
  1318. sres.rt = RES_PROPERTY; //Comparing a property
  1319. sres.res.resProperty.relop = RELOP_EQ; //Testing equality
  1320. sres.res.resProperty.ulPropTag = PR_DEFAULT_STORE; //Tag to compare
  1321. sres.res.resProperty.lpProp = &spv; //Prop tag and value to compare against
  1322. spv.ulPropTag = PR_DEFAULT_STORE; //Tag type
  1323. spv.Value.b   = TRUE; //Tag value
  1324. //Convert the table to an array which can be stepped through
  1325. //Only one message store should have PR_DEFAULT_STORE set to true, so only one will be returned
  1326. hRes = pProvider->HrQueryAllRows(
  1327. pStoresTbl, //Table to query
  1328. (LPSPropTagArray) &sptCols, //Which columns to get
  1329. &sres, //Restriction to use
  1330. NULL, //No sort order
  1331. 0, //Max number of rows (0 means no limit)
  1332. &pRow); //Array to return
  1333. if (SUCCEEDED(hRes))
  1334. {
  1335. //Open the first returned (default) message store
  1336. hRes = lpMAPISession->OpenMsgStore(
  1337.   NULL,//Window handle for dialogs
  1338.   pRow->aRow[0].lpProps[EID].Value.bin.cb,//size and...
  1339.   (LPENTRYID)pRow->aRow[0].lpProps[EID].Value.bin.lpb,//value of entry to open
  1340.   NULL,//Use default interface (IMsgStore) to open store
  1341.   MAPI_BEST_ACCESS,//Flags
  1342.   &lpTempMDB);//Pointer to place the store in
  1343. if (SUCCEEDED(hRes))
  1344. {
  1345. //Assign the out parameter
  1346. *lpMDB = lpTempMDB;
  1347. }
  1348. }
  1349. }
  1350. // clean up
  1351. pProvider->FreeProws(pRow);
  1352. MAPI_RELEASE(pProvider, pStoresTbl);
  1353. if (FAILED(hRes))
  1354. {
  1355. LPMAPIERROR lpError;
  1356. HRESULT hr = lpMAPISession->GetLastError(hRes, 0, &lpError);
  1357. if (SUCCEEDED(hr) && lpError)
  1358. {
  1359. TRACE(_T("%sn%sn"), lpError->lpszError, lpError->lpszComponent);
  1360. pProvider->MAPIFreeBuffer(lpError);
  1361. }
  1362. }
  1363. return hRes;
  1364. }
  1365. /////////////////////////////////////////////////////////////////////////////
  1366. CXTPCalendarMAPIDataProvider::CXTPCalendarMemDPInternal::CXTPCalendarMemDPInternal(CXTPCalendarData* pDPExternal)
  1367. {
  1368. ASSERT(pDPExternal);
  1369. m_pDPExternal = pDPExternal;
  1370. }
  1371. void CXTPCalendarMAPIDataProvider::CXTPCalendarMemDPInternal::SendNotification(XTP_NOTIFY_CODE EventCode, WPARAM wParam , LPARAM lParam)
  1372. {
  1373. class CXTPCalendarDataSnNf : public CXTPCalendarData
  1374. {
  1375. public:
  1376. using CXTPCalendarData::SendNotification;
  1377. };
  1378. //===================================
  1379. if (m_bDisableNotificationsSending)
  1380. {
  1381. return;
  1382. }
  1383. if (m_pDPExternal)
  1384. {
  1385. ((CXTPCalendarDataSnNf*)m_pDPExternal)->SendNotification(EventCode, wParam, lParam);
  1386. }
  1387. else
  1388. {
  1389. CXTPCalendarData::SendNotification(EventCode, wParam, lParam);
  1390. }
  1391. }
  1392. //////////////////////////////////////////////////////////////////////////
  1393. CXTPCalendarMAPIDataProvider::CXTPCalendarMAPIDataProvider()
  1394. {
  1395. m_MapiHelper.m_pProvider = this;
  1396. m_typeProvider = xtpCalendarDataProviderMAPI;
  1397. m_bMAPIInitialized = FALSE;
  1398. m_lpMAPISession = NULL;
  1399. m_lpMDB = NULL;
  1400. m_lpCalendarFolder = NULL;
  1401. m_ulMAPIConID0 = 0;
  1402. m_ulMAPIConID1 = 0;
  1403. m_lpAdviseSink = NULL;
  1404. m_lpAdviseSink_ThrSafe = NULL;
  1405. //m_pMemDP = new CXTPCalendarMemoryDataProvider();
  1406. m_pMemDP = new CXTPCalendarMemDPInternal(this);
  1407. }
  1408. CXTPCalendarMAPIDataProvider::~CXTPCalendarMAPIDataProvider()
  1409. {
  1410. CMDTARGET_RELEASE(m_pMemDP);
  1411. }
  1412. CXTPCalendarEventsPtr CXTPCalendarMAPIDataProvider::DoRetrieveDayEvents(COleDateTime dtDay)
  1413. {
  1414. return m_pMemDP ? m_pMemDP->RetrieveDayEvents(dtDay) : NULL;
  1415. }
  1416. void CXTPCalendarMAPIDataProvider::DoRemoveAllEvents()
  1417. {
  1418. if (m_pMemDP)
  1419. {
  1420. m_pMemDP->RemoveAllEvents();
  1421. }
  1422. }
  1423. CXTPCalendarEventPtr CXTPCalendarMAPIDataProvider::DoRead_Event(DWORD dwEventID)
  1424. {
  1425. return m_pMemDP ? m_pMemDP->GetEvent(dwEventID) : NULL;
  1426. }
  1427. CXTPCalendarRecurrencePatternPtr CXTPCalendarMAPIDataProvider::DoRead_RPattern(DWORD dwPatternID)
  1428. {
  1429. return m_pMemDP ? m_pMemDP->GetRecurrencePattern(dwPatternID) : NULL;
  1430. }
  1431. BOOL CXTPCalendarMAPIDataProvider::DoCreate_Event(CXTPCalendarEvent* pEvent, DWORD& rdwNewEventID)
  1432. {
  1433. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  1434. m_bDisableNotificationsSending = TRUE;
  1435. if (!IsOpen())
  1436. {
  1437. return FALSE;
  1438. }
  1439. if (!m_lpCalendarFolder || !m_pMemDP || !pEvent)
  1440. {
  1441. ASSERT(FALSE);
  1442. return FALSE;
  1443. }
  1444. DWORD dwEventID = pEvent->GetEventID();
  1445. int nRState = pEvent->GetRecurrenceState();
  1446. if (nRState != xtpCalendarRecurrenceNotRecurring &&
  1447. nRState != xtpCalendarRecurrenceMaster)
  1448. {
  1449. ASSERT(nRState == xtpCalendarRecurrenceException);
  1450. rdwNewEventID = GetNextUniqueEventID(dwEventID);
  1451. return TRUE;
  1452. }
  1453. LPMESSAGE pMessage = NULL;
  1454. HRESULT hr = m_lpCalendarFolder->CreateMessage(NULL, 0, &pMessage);
  1455. if (FAILED(hr) || !pMessage)
  1456. {
  1457. ASSERT(FALSE);
  1458. return FALSE;
  1459. }
  1460. if (!UpdateMAPIEvent(pMessage, pEvent))
  1461. {
  1462. MAPI_RELEASE(this, pMessage);
  1463. return FALSE;
  1464. }
  1465. // to ensure that PR_SEARCH_KEY property is valid
  1466. hr = pMessage->SaveChanges(KEEP_OPEN_READONLY);
  1467. if (FAILED(hr))
  1468. {
  1469. ASSERT(FALSE);
  1470. MAPI_RELEASE(this, pMessage);
  1471. return FALSE;
  1472. }
  1473. _SetEventRuntimeProps(pEvent->GetCustomProperties(), pMessage);
  1474. //-----------------------------------------------------------------------
  1475. CByteArray arSearchKey;
  1476. HRESULT hrID = _getPropVal(pMessage, PR_SEARCH_KEY, arSearchKey);
  1477. if (FAILED(hrID))
  1478. {
  1479. ASSERT(FALSE);
  1480. MAPI_RELEASE(this, pMessage);
  1481. return NULL;
  1482. }
  1483. rdwNewEventID = GetEventID((int)arSearchKey.GetSize(),
  1484.    (LPENTRYID)arSearchKey.GetData(), TRUE);
  1485. //-----------------------------------------------------------------------
  1486. pEvent->SetEventID(rdwNewEventID);
  1487. BOOL bRes = m_pMemDP->AddEvent(pEvent);
  1488. MAPI_RELEASE(this, pMessage);
  1489. return bRes;
  1490. }
  1491. BOOL CXTPCalendarMAPIDataProvider::DoUpdate_Event(CXTPCalendarEvent* pEvent)
  1492. {
  1493. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  1494. m_bDisableNotificationsSending = TRUE;
  1495. if (!IsOpen())
  1496. {
  1497. return FALSE;
  1498. }
  1499. if (!m_lpCalendarFolder || !m_pMemDP || !pEvent)
  1500. {
  1501. ASSERT(FALSE);
  1502. return FALSE;
  1503. }
  1504. //=================================================
  1505. int nRState = pEvent->GetRecurrenceState();
  1506. if (nRState != xtpCalendarRecurrenceNotRecurring &&
  1507. nRState != xtpCalendarRecurrenceMaster)
  1508. {
  1509. ASSERT(nRState == xtpCalendarRecurrenceException);
  1510. return TRUE;
  1511. }
  1512. //=================================================
  1513. BOOL bRes = m_pMemDP->ChangeEvent(pEvent);
  1514. if (!bRes)
  1515. {
  1516. return FALSE;
  1517. }
  1518. DWORD dwEventID = pEvent->GetEventID();
  1519. CXTPMAPIBinary eKey;
  1520. if (!m_mapID.Lookup(dwEventID, eKey))
  1521. {
  1522. ASSERT(FALSE);
  1523. return FALSE;
  1524. }
  1525. LPMESSAGE pMessage = NULL;
  1526. ULONG ulObjType = NULL;
  1527. // Get event ID by its SearchKey
  1528. CXTPMAPIBinary eid = GetEntryID(eKey);
  1529. // open event from Calendar Folder storage
  1530. HRESULT hr = m_lpCalendarFolder->OpenEntry(
  1531. eid.GetBinarySize(), (LPENTRYID)eid.GetBinaryData(),
  1532. NULL,//default interface
  1533. MAPI_BEST_ACCESS,
  1534. &ulObjType,
  1535. (LPUNKNOWN*)&pMessage);
  1536. ASSERT(ulObjType == 5);
  1537. ASSERT(pMessage);
  1538. if (FAILED(hr) || !pMessage)
  1539. {
  1540. ASSERT(FALSE);
  1541. return FALSE;
  1542. }
  1543. if (!UpdateMAPIEvent(pMessage, pEvent))
  1544. {
  1545. MAPI_RELEASE(this, pMessage);
  1546. return FALSE;
  1547. }
  1548. hr = pMessage->SaveChanges(KEEP_OPEN_READONLY);
  1549. if (FAILED(hr))
  1550. {
  1551. ASSERT(FALSE);
  1552. MAPI_RELEASE(this, pMessage);
  1553. return FALSE;
  1554. }
  1555. //-----------------------------------------------------------------------
  1556. //  BOOL bRes = m_pMemDP->ChangeEvent(pEvent);
  1557. MAPI_RELEASE(this, pMessage);
  1558. return TRUE;
  1559. }
  1560. BOOL CXTPCalendarMAPIDataProvider::DoDelete_Event(CXTPCalendarEvent* pEvent)
  1561. {
  1562. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  1563. m_bDisableNotificationsSending = TRUE;
  1564. if (!IsOpen())
  1565. {
  1566. return FALSE;
  1567. }
  1568. if (!m_lpCalendarFolder || !m_pMemDP || !pEvent)
  1569. {
  1570. ASSERT(FALSE);
  1571. return FALSE;
  1572. }
  1573. int nRState = pEvent->GetRecurrenceState();
  1574. if (nRState != xtpCalendarRecurrenceNotRecurring &&
  1575. nRState != xtpCalendarRecurrenceMaster)
  1576. {
  1577. ASSERT(nRState == xtpCalendarRecurrenceException);
  1578. return TRUE;
  1579. }
  1580. CXTPMAPIBinary eKey;
  1581. DWORD dwEventID = pEvent->GetEventID();
  1582. if (!m_mapID.Lookup(dwEventID, eKey))
  1583. {
  1584. // ASSERT(FALSE); // possible when copied appointments
  1585. return FALSE;
  1586. }
  1587. // get event ID by its SearchKey
  1588. CXTPMAPIBinary eid = GetEntryID(eKey);
  1589. // delete event
  1590. ENTRYLIST eidList1;
  1591. SBinary   eidBinary;
  1592. eidList1.cValues = 1;
  1593. eidList1.lpbin = &eidBinary;
  1594. eidBinary.cb = eid.GetBinarySize();
  1595. eidBinary.lpb = (BYTE*)eid.GetBinaryData();
  1596. HRESULT hr = m_lpCalendarFolder->DeleteMessages(&eidList1, 0, NULL, 0);
  1597. if (FAILED(hr))
  1598. {
  1599. ASSERT(FALSE);
  1600. return FALSE;
  1601. }
  1602. //-----------------------------------------------------------------------
  1603. return m_pMemDP ? m_pMemDP->DeleteEvent(pEvent) : FALSE;
  1604. }
  1605. BOOL CXTPCalendarMAPIDataProvider::DoCreate_RPattern(CXTPCalendarRecurrencePattern* pPattern, DWORD& rdwNewPatternID)
  1606. {
  1607. rdwNewPatternID = pPattern->GetPatternID();
  1608. return TRUE;
  1609. }
  1610. BOOL CXTPCalendarMAPIDataProvider::DoUpdate_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  1611. {
  1612. UNREFERENCED_PARAMETER(pPattern);
  1613. return TRUE;
  1614. }
  1615. BOOL CXTPCalendarMAPIDataProvider::DoDelete_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  1616. {
  1617. UNREFERENCED_PARAMETER(pPattern);
  1618. return TRUE;
  1619. }
  1620. CXTPCalendarEventsPtr CXTPCalendarMAPIDataProvider::DoGetUpcomingEvents(COleDateTime dtFrom, COleDateTimeSpan spPeriod)
  1621. {
  1622. UNREFERENCED_PARAMETER(dtFrom); UNREFERENCED_PARAMETER(spPeriod);
  1623. return DoGetAllEvents_raw();
  1624. }
  1625. CXTPCalendarEventsPtr CXTPCalendarMAPIDataProvider::DoGetAllEvents_raw()
  1626. {
  1627. return m_pMemDP ? m_pMemDP->GetAllEvents_raw() : NULL;
  1628. }
  1629. BOOL AFX_CDECL CXTPCalendarMAPIDataProvider::GetParameterValueFromConStr(LPCTSTR lpszConnectionString, LPCTSTR pcszParameterName, CString& rstrValue)
  1630. {
  1631. rstrValue.Empty();
  1632. ASSERT(lpszConnectionString && pcszParameterName);
  1633. if (!lpszConnectionString || !pcszParameterName ||
  1634. 0 == _tcslen(lpszConnectionString) || 0 == _tcslen(pcszParameterName))
  1635. {
  1636. return FALSE;
  1637. }
  1638. CString strConnStr_lower = lpszConnectionString;
  1639. strConnStr_lower.MakeLower();
  1640. CString strParameterName_lower = pcszParameterName;
  1641. strParameterName_lower.MakeLower();
  1642. int nIndex = strConnStr_lower.Find(strParameterName_lower + _T("="));
  1643. if (nIndex == -1)
  1644. nIndex = strConnStr_lower.Find(strParameterName_lower + _T(" ="));
  1645. if (nIndex == -1)
  1646. return FALSE;
  1647. int nParamNameLen = (int)_tcslen(pcszParameterName);
  1648. CString strParam = lpszConnectionString;
  1649. strParam = strParam.Mid(nIndex + nParamNameLen);
  1650. if (strParam[0] == _T(' '))
  1651. DELETE_S(strParam, 0);
  1652. if (strParam[0] == _T('='))
  1653. DELETE_S(strParam, 0);
  1654. if (strParam.IsEmpty())
  1655. return TRUE;
  1656. if (strParam[0] == _T(''') || strParam[0] == _T('"'))
  1657. {
  1658. if (strParam.GetLength() <= 2)
  1659. return TRUE;
  1660. TCHAR chQuot = strParam[0];
  1661. DELETE_S(strParam, 0);
  1662. int nQuot2Idx = FIND_S(strParam, chQuot, 0);
  1663. if (nQuot2Idx >= 0)
  1664. {
  1665. DELETE_S(strParam, nQuot2Idx, strParam.GetLength() - nQuot2Idx);
  1666. }
  1667. }
  1668. else
  1669. {
  1670. int nParamEndIdx = FIND_S(strParam, _T(';'), 0);
  1671. if (nParamEndIdx >= 0)
  1672. {
  1673. DELETE_S(strParam, nParamEndIdx, strParam.GetLength() - nParamEndIdx);
  1674. }
  1675. }
  1676. rstrValue = strParam;
  1677. return TRUE;
  1678. }
  1679. void CXTPCalendarMAPIDataProvider::GetMAPILogonParams(LPTSTR& rpszProfile, LPTSTR& rpszPassword, FLAGS& ruFlags)
  1680. {
  1681. rpszProfile = NULL;
  1682. rpszPassword = NULL;
  1683. ruFlags = MAPI_LOGON_UI; //Allow a profile picker box to show if not logged in
  1684. if (GetParameterValueFromConStr(m_strConnectionString, cszMAPIProfileName, m_strProfile_tmp))
  1685. rpszProfile = (LPTSTR)(LPCTSTR)m_strProfile_tmp;
  1686. if (GetParameterValueFromConStr(m_strConnectionString, cszMAPIPassword, m_strPassword_tmp))
  1687. rpszPassword = (LPTSTR)(LPCTSTR)m_strPassword_tmp;
  1688. CString strFlags;
  1689. if (GetParameterValueFromConStr(m_strConnectionString, cszMAPIFlags, strFlags))
  1690. {
  1691. DWORD dwFlags = 0;
  1692. SCANF_S(strFlags, _T("%x"), &dwFlags);
  1693. ruFlags = dwFlags;
  1694. }
  1695. }
  1696. BOOL CXTPCalendarMAPIDataProvider::Open()
  1697. {
  1698. if (m_pMemDP)
  1699. {
  1700. m_pMemDP->Open();
  1701. }
  1702. HRESULT       hRes;
  1703. LPMAPIFOLDER  lpInboxFolder = NULL;
  1704. LPSPropValue  lpCalendarFolderEntryID = NULL;
  1705. hRes = this->MAPIInitialize(NULL);
  1706. if (SUCCEEDED(hRes))
  1707. {
  1708. LPTSTR pcszProfile;
  1709. LPTSTR pcszPassword;
  1710. FLAGS uFlags;
  1711. GetMAPILogonParams(pcszProfile, pcszPassword, uFlags);
  1712. m_bMAPIInitialized = TRUE;
  1713. hRes = this->MAPILogonEx(0, pcszProfile, pcszPassword, uFlags, &m_lpMAPISession);
  1714. if (SUCCEEDED(hRes))
  1715. {
  1716. hRes = OpenDefaultMessageStore(m_lpMAPISession, &m_lpMDB, this);
  1717. if (SUCCEEDED(hRes))
  1718. {
  1719. hRes = OpenInbox(m_lpMDB, &lpInboxFolder, &m_lpCalendarFolder, this);
  1720. if (SUCCEEDED(hRes))
  1721. {
  1722. //Checking to see that we did get the Calendar folder
  1723. hRes = this->HrGetOneProp(m_lpCalendarFolder, PR_ENTRYID,
  1724. &lpCalendarFolderEntryID);
  1725. if (SUCCEEDED(hRes))
  1726. {
  1727. m_eidCalendarFolder.Set(lpCalendarFolderEntryID);
  1728. }
  1729. }
  1730. }
  1731. }
  1732. }
  1733. if (SUCCEEDED(hRes))
  1734. {
  1735. // copy all events to the cache data provider
  1736. if (m_pMemDP)
  1737. {
  1738. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  1739. m_bDisableNotificationsSending = TRUE;
  1740. m_pMemDP->AddEvents(ImportAllEvents());
  1741. }
  1742. // advise to MAPI notifications
  1743. hRes = this->HrAllocAdviseSink(MAPICallBack_OnNotify, this, &m_lpAdviseSink);
  1744. ASSERT(SUCCEEDED(hRes) && m_lpAdviseSink);
  1745. hRes = this->HrThisThreadAdviseSink(m_lpAdviseSink, &m_lpAdviseSink_ThrSafe);
  1746. ASSERT(SUCCEEDED(hRes) && m_lpAdviseSink_ThrSafe);
  1747. if (SUCCEEDED(hRes) && m_lpAdviseSink_ThrSafe)
  1748. {
  1749. ULONG uEventsMask = fnevObjectCreated | fnevObjectDeleted | fnevObjectModified |
  1750. fnevObjectMoved; // | fnevObjectCopied;
  1751. ULONG uEIDsize =  lpCalendarFolderEntryID->Value.bin.cb;
  1752. LPENTRYID pEIDdata = (LPENTRYID)lpCalendarFolderEntryID->Value.bin.lpb;
  1753. hRes = m_lpMDB->Advise(0, NULL, uEventsMask, m_lpAdviseSink_ThrSafe,
  1754. &m_ulMAPIConID0);
  1755. ASSERT(SUCCEEDED(hRes));
  1756. // to receive fnevObjectDeleted notification
  1757. hRes = m_lpMDB->Advise(uEIDsize, pEIDdata, uEventsMask,
  1758. m_lpAdviseSink_ThrSafe, &m_ulMAPIConID1);
  1759. ASSERT(SUCCEEDED(hRes));
  1760. // to force Advise call in the RPC.
  1761. ULONG nValues = 0;
  1762. LPSPropValue pPropArray;
  1763. hRes = m_lpMDB->GetProps(NULL, 0, &nValues, &pPropArray);
  1764. ASSERT(SUCCEEDED(hRes));
  1765. MAPI_FREEBUFFER(this, pPropArray);
  1766. }
  1767. }
  1768. MAPI_FREEBUFFER(this, lpCalendarFolderEntryID);
  1769. MAPI_RELEASE(this, lpInboxFolder);
  1770. if (FAILED(hRes))
  1771. {
  1772. // cleanup
  1773. m_bOpened = TRUE; // to let Close run.
  1774. Close();
  1775. }
  1776. if (SUCCEEDED(hRes))
  1777. {
  1778. CXTPCalendarData::Open();
  1779. }
  1780. return SUCCEEDED(hRes);
  1781. }
  1782. BOOL CXTPCalendarMAPIDataProvider::Create()
  1783. {
  1784. return Open();
  1785. }
  1786. BOOL CXTPCalendarMAPIDataProvider::Save()
  1787. {
  1788. CXTPCalendarData::Save();
  1789. return TRUE;
  1790. }
  1791. void CXTPCalendarMAPIDataProvider::Close()
  1792. {
  1793. if (!m_bOpened)
  1794. return;
  1795. if (m_pMemDP)
  1796. {
  1797. m_pMemDP->Close();
  1798. }
  1799. HRESULT hRes = 0;
  1800. // Unadvise -------------------------------------
  1801. if (m_ulMAPIConID0)
  1802. {
  1803. hRes = m_lpMDB->Unadvise(m_ulMAPIConID0);
  1804. ASSERT(SUCCEEDED(hRes));
  1805. m_ulMAPIConID0 = 0;
  1806. }
  1807. if (m_ulMAPIConID1)
  1808. {
  1809. hRes = m_lpMDB->Unadvise(m_ulMAPIConID1);
  1810. ASSERT(SUCCEEDED(hRes));
  1811. m_ulMAPIConID1 = 0;
  1812. }
  1813. // release opened objects -----------------------
  1814. MAPI_RELEASE(this, m_lpAdviseSink_ThrSafe);
  1815. MAPI_RELEASE(this, m_lpAdviseSink);
  1816. MAPI_RELEASE(this, m_lpCalendarFolder);
  1817. MAPI_RELEASE(this, m_lpMDB);
  1818. // LogOff session -------------------------------
  1819. if (m_lpMAPISession)
  1820. {
  1821. hRes = m_lpMAPISession->Logoff(0, 0, 0);
  1822. ASSERT(SUCCEEDED(hRes));
  1823. }
  1824. MAPI_RELEASE(this, m_lpMAPISession);
  1825. // Initialize MAPI dll --------------------------
  1826. if (m_bMAPIInitialized)
  1827. {
  1828. this->MAPIUninitialize();
  1829. m_bMAPIInitialized = FALSE;
  1830. }
  1831. CXTPCalendarData::Close();
  1832. }
  1833. BOOL CXTPCalendarMAPIDataProvider::IsOpen()
  1834. {
  1835. return m_lpCalendarFolder != NULL;
  1836. }
  1837. //LPSRestriction CXTPCalendarMAPIDataProvider::BuildDayRestriction(const COleDateTime dtDay)
  1838. //{
  1839. //  return 0;
  1840. ///*    static SRestriction sres;
  1841. //  static SPropValue spv[2];
  1842. //  static SRestriction sr[2];
  1843. //  ZeroMemory(spv, 2 * sizeof(SPropValue));
  1844. //  // Set up restriction for the current day event
  1845. //  sres.rt = RES_AND; // Comparing a property
  1846. //  sres.res.resAnd.cRes = 2; // Count of restrictions
  1847. //  sres.res.resAnd.lpRes = sr;
  1848. //
  1849. //  // Start time is current or less
  1850. //  sr[0].rt = RES_PROPERTY; // Comparing a property
  1851. //  sr[0].res.resProperty.relop = RELOP_LE; // lower or equal
  1852. //  sr[0].res.resProperty.ulPropTag = XTP_PR_MAPI_EVENT_START_TIME; // Tag to compare
  1853. //  sr[0].res.resProperty.lpProp = &spv[0]; // Prop tag and value to compare against
  1854. //
  1855. //  spv[0].ulPropTag = XTP_PR_MAPI_EVENT_START_TIME; // Tag type
  1856. //  SYSTEMTIME st;
  1857. //  COleDateTime dtEndDay = CXTPCalendarUtils::ResetTime(dtDay) + COleDateTimeSpan(0, 23, 59, 59);
  1858. //  if (dtEndDay.GetAsSystemTime(st))
  1859. //  {
  1860. //      SystemTimeToFileTime(&st, &spv[0].Value.ft); // Tag value
  1861. //  }
  1862. //
  1863. //  // End time is more or current
  1864. //  sr[1].rt = RES_PROPERTY; // Comparing a property
  1865. //  sr[1].res.resProperty.relop = RELOP_GE; // greater or equal
  1866. //  sr[1].res.resProperty.ulPropTag = XTP_PR_MAPI_EVENT_END_TIME; // Tag to compare
  1867. //  sr[1].res.resProperty.lpProp = &spv[1]; // Prop tag and value to compare against
  1868. //
  1869. //  spv[1].ulPropTag = XTP_PR_MAPI_EVENT_END_TIME; // Tag type
  1870. //  if (CXTPCalendarUtils::ResetTime(dtDay).GetAsSystemTime(st))
  1871. //  {
  1872. //      SystemTimeToFileTime(&st, &spv[1].Value.ft); // Tag value
  1873. //  }
  1874. //
  1875. //  return &sres;
  1876. //  */
  1877. //}
  1878. LPSRestriction CXTPCalendarMAPIDataProvider::BuildBinaryRestriction(ULONG cbSize, LPBYTE lpData, ULONG ulPropTag)
  1879. {
  1880. static SRestriction sres;
  1881. static SPropValue spv;
  1882. ZeroMemory(&spv, sizeof(SPropValue));
  1883. // Set up restriction for the current day event
  1884. sres.rt = RES_PROPERTY; // Comparing a property
  1885. sres.res.resProperty.relop = RELOP_EQ; // Equal
  1886. sres.res.resProperty.ulPropTag = ulPropTag; // Entry ID
  1887. sres.res.resProperty.lpProp = &spv; // Prop tag and value to compare against
  1888. spv.ulPropTag = ulPropTag; // Tag type
  1889. spv.Value.bin.cb = cbSize;
  1890. spv.Value.bin.lpb = lpData;
  1891. return &sres;
  1892. }
  1893. void CXTPCalendarMAPIDataProvider::_SetEventRuntimeProps(CXTPCalendarCustomProperties* pEventProps, LPMESSAGE pMessage)
  1894. {
  1895. ASSERT(pEventProps && pMessage);
  1896. if (!pEventProps || !pMessage)
  1897. return;
  1898. CByteArray arEntryID, arSearchKey;
  1899. HRESULT hrID = _getPropVal(pMessage, PR_ENTRYID, arEntryID);
  1900. if (SUCCEEDED(hrID))
  1901. {
  1902. COleVariant varEntryID(arEntryID);
  1903. pEventProps->SetProperty(cszMAPIpropVal_EntryID, varEntryID);
  1904. }
  1905. hrID = _getPropVal(pMessage, PR_SEARCH_KEY, arSearchKey);
  1906. if (SUCCEEDED(hrID))
  1907. {
  1908. COleVariant varSearchKey(arSearchKey);
  1909. pEventProps->SetProperty(cszMAPIpropVal_SearchKey, varSearchKey);
  1910. }
  1911. }
  1912. void CXTPCalendarMAPIDataProvider::_MoveMAPIEventRuntimeProps(CXTPCalendarCustomProperties* pDest,
  1913. CXTPCalendarCustomProperties* pSrc)
  1914. {
  1915. ASSERT(pSrc && pDest);
  1916. if (!pSrc || !pDest)
  1917. return;
  1918. COleVariant varValue;
  1919. if (pDest && pSrc->GetProperty(cszMAPIpropVal_EntryID, varValue))
  1920. {
  1921. pDest->SetProperty(cszMAPIpropVal_EntryID, varValue);
  1922. }
  1923. pSrc->RemoveProperty(cszMAPIpropVal_EntryID);
  1924. if (pDest && pSrc->GetProperty(cszMAPIpropVal_SearchKey, varValue))
  1925. {
  1926. pDest->SetProperty(cszMAPIpropVal_SearchKey, varValue);
  1927. }
  1928. pSrc->RemoveProperty(cszMAPIpropVal_SearchKey);
  1929. }
  1930. CXTPCalendarEventPtr CXTPCalendarMAPIDataProvider::ImportEvent_FromCalendarFolderOnly(
  1931. ULONG cbEntryID, LPENTRYID lpEntryID)
  1932. {
  1933. LPSRestriction pRestriction = BuildBinaryRestriction(cbEntryID, (LPBYTE)lpEntryID, PR_ENTRYID);
  1934. CXTPCalendarEventsPtr ptrEvents = ImportAllEvents(pRestriction);
  1935. CXTPCalendarEventPtr ptrEvent;
  1936. if (ptrEvents && ptrEvents->GetCount())
  1937. {
  1938. ASSERT(ptrEvents->GetCount() == 1);
  1939. ptrEvent = ptrEvents->GetAt(0, TRUE);
  1940. }
  1941. return ptrEvent;
  1942. }
  1943. CXTPCalendarEventPtr CXTPCalendarMAPIDataProvider::ImportEvent(LPSRow lpRow)
  1944. {
  1945. if (!lpRow)
  1946. return NULL;
  1947. // ------- ID --------
  1948. if (PR_ENTRYID != lpRow->lpProps[0].ulPropTag)
  1949. {
  1950. ASSERT(FALSE);
  1951. return NULL;
  1952. }
  1953. CXTPCalendarEventPtr ptrEvent = ImportEvent(lpRow->lpProps[0].Value.bin.cb,
  1954. (LPENTRYID)lpRow->lpProps[0].Value.bin.lpb);
  1955. return ptrEvent;
  1956. }
  1957. CXTPCalendarEventPtr CXTPCalendarMAPIDataProvider::ImportEvent(ULONG cbEntryID,
  1958. LPENTRYID lpEntryID)
  1959. {
  1960. if (cbEntryID == 0 || !lpEntryID)
  1961. {
  1962. ASSERT(FALSE);
  1963. return NULL;
  1964. }
  1965. LPMESSAGE pMessage = NULL;
  1966. ULONG ulObjType = NULL;
  1967. // open event from Calendar Folder storage
  1968. m_lpCalendarFolder->OpenEntry(cbEntryID, lpEntryID,
  1969. NULL,//default interface
  1970. MAPI_BEST_ACCESS,
  1971. &ulObjType,
  1972. (LPUNKNOWN*)&pMessage);
  1973. ASSERT(ulObjType == 5);
  1974. ASSERT(pMessage);
  1975. if (!pMessage)
  1976. return NULL;
  1977. CXTPCalendarEventPtr ptrEvent = ImportEvent(pMessage);
  1978. MAPI_RELEASE(this, pMessage);
  1979. return ptrEvent;
  1980. }
  1981. CXTPCalendarEventPtr CXTPCalendarMAPIDataProvider::ImportEvent(LPMESSAGE pMessage)
  1982. {
  1983. ASSERT(pMessage);
  1984. if (!pMessage)
  1985. return NULL;
  1986. //-----------------------------------------------------------------------
  1987. CByteArray arSearchKey;
  1988. HRESULT hrID = _getPropVal(pMessage, PR_SEARCH_KEY, arSearchKey);
  1989. if (FAILED(hrID))
  1990. {
  1991. ASSERT(FALSE);
  1992. return NULL;
  1993. }
  1994. DWORD dwEventID = GetEventID((int)arSearchKey.GetSize(),
  1995.  (LPENTRYID)arSearchKey.GetData(), TRUE);
  1996. //============================================================
  1997. CXTPCalendarEventPtr ptrEvent(CreateNewEvent(dwEventID));
  1998. // ------- Is Recurrence --------
  1999. int nIsRecurrence = _getPropVal_int(pMessage, xtpMAPIpropEvent_IsRecuring);
  2000. // get TimeZone
  2001. TIME_ZONE_INFORMATION tziEvent;
  2002. GetTimeZoneInformation(&tziEvent);
  2003. if (nIsRecurrence)
  2004. {
  2005. ULONG ulTZTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_TimeZone);
  2006. CByteArray arTZIData;
  2007. HRESULT hrTZ = _getPropVal(pMessage, ulTZTag, arTZIData);
  2008. if (SUCCEEDED(hrTZ))
  2009. {
  2010. xtp_GetWinTZInfo(arTZIData, &tziEvent);
  2011. }
  2012. }
  2013. XTP_TRACE_READ_EVENTS(_T("nEvent:------------------n"));
  2014. // ------- Subject --------
  2015. CString strTmp = _getPropVal_str(pMessage, PR_SUBJECT);
  2016. ptrEvent->SetSubject(strTmp);
  2017. XTP_TRACE_READ_EVENTS(_T("Subject: %sn"), strTmp);
  2018. // ------- Body --------
  2019. strTmp = _getPropVal_str(pMessage, PR_BODY);
  2020. ptrEvent->SetBody(strTmp);
  2021. XTP_TRACE_READ_EVENTS(_T("Body: %sn"), strTmp.Left(255));
  2022. // ------- StartTime --------
  2023. SYSTEMTIME stUTC = _getPropVal_UtcTime(pMessage, xtpMAPIpropEvent_StartTime);
  2024. //TRACE(_T("StartTime orig: %sn"), dtTmp.Format());
  2025. COleDateTime dtTmp = xtp_UtcToTzTime(&tziEvent, stUTC);
  2026. ptrEvent->SetStartTime(dtTmp);
  2027. XTP_TRACE_READ_EVENTS(_T("StartTime tz  : %sn"), dtTmp.Format());
  2028. // ------- EndTime --------
  2029. stUTC = _getPropVal_UtcTime(pMessage, xtpMAPIpropEvent_EndTime);
  2030. dtTmp = xtp_UtcToTzTime(&tziEvent, stUTC);
  2031. ptrEvent->SetEndTime(dtTmp);
  2032. //XTP_TRACE_READ_EVENTS(_T("EndTime: %sn"), ptrEvent->GetEndTime().Format());
  2033. // ------- LOCATION --------
  2034. strTmp = _getPropVal_str(pMessage, xtpMAPIpropEvent_Location);
  2035. ptrEvent->SetLocation(strTmp);
  2036. XTP_TRACE_READ_EVENTS(_T("LOCATION: %sn"), strTmp.Left(255));
  2037. // ------- AllDayEvent --------
  2038. int nTmp = _getPropVal_int(pMessage, xtpMAPIpropEvent_AllDay);
  2039. ptrEvent->SetAllDayEvent(nTmp != 0);
  2040. XTP_TRACE_READ_EVENTS(_T("All day: %dn"), nTmp);
  2041. // ------- IsReminder --------
  2042. nTmp = _getPropVal_int(pMessage, xtpMAPIpropCommon_ReminderSet);
  2043. ptrEvent->SetReminder(nTmp);
  2044. // ------- ReminderMinutesBeforeStart --------
  2045. nTmp = _getPropVal_int(pMessage, xtpMAPIpropCommon_ReminderMinutesBefore);
  2046. ptrEvent->SetReminderMinutesBeforeStart(nTmp);
  2047. // ------- BusyStatus --------
  2048. nTmp = _getPropVal_int(pMessage, xtpMAPIpropEvent_BusyStatus);
  2049. ptrEvent->SetBusyStatus(nTmp);
  2050. // ------- Importance --------
  2051. nTmp = _getPropVal_int(pMessage, PR_IMPORTANCE);
  2052. ptrEvent->SetImportance(nTmp);
  2053. // ------- Label --------
  2054. nTmp = _getPropVal_int(pMessage, xtpMAPIpropEvent_Color);
  2055. ptrEvent->SetLabelID(nTmp);
  2056. // ------- Meeting --------
  2057. nTmp = _getPropVal_int(pMessage, xtpMAPIpropEvent_MeetingStatus);
  2058. ptrEvent->SetMeeting(nTmp != 0);
  2059. // ------- Private --------
  2060. nTmp = _getPropVal_int(pMessage, xtpMAPIpropCommon_IsPrivate);
  2061. ptrEvent->SetPrivate(nTmp != 0);
  2062. // ------- CreationTime --------
  2063. stUTC = _getPropVal_UtcTime(pMessage, PR_CREATION_TIME);
  2064. dtTmp = xtp_UtcToTzTime(&tziEvent, stUTC);
  2065. ptrEvent->SetCreationTime(dtTmp);
  2066. // ------- LastModificationTime --------
  2067. stUTC = _getPropVal_UtcTime(pMessage, PR_LAST_MODIFICATION_TIME);
  2068. dtTmp = xtp_UtcToTzTime(&tziEvent, stUTC);
  2069. ptrEvent->SetLastModificationTime(dtTmp);
  2070. // ------- Custom Properties -------
  2071. CXTPCalendarCustomProperties* pProps = ptrEvent->GetCustomProperties();
  2072. if (pProps)
  2073. {
  2074. strTmp = _getPropVal_str(pMessage, xtpMAPIpropEvent_CustomProperties);
  2075. pProps->LoadFromXML(strTmp);
  2076. _SetEventRuntimeProps(pProps, pMessage);
  2077. }
  2078. // nIsRecurrence
  2079. if (nIsRecurrence)
  2080. {
  2081. ULONG ulPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceState);
  2082. CByteArray arRecData;
  2083. HRESULT hr = _getPropVal(pMessage, ulPropTag, arRecData);
  2084. ASSERT(SUCCEEDED(hr));
  2085. VERIFY(ptrEvent->MakeEventAsRecurrence());
  2086. ImportRecurrence(ptrEvent, arRecData);
  2087. }
  2088. // -------
  2089. return ptrEvent;
  2090. }
  2091. int CXTPCalendarMAPIDataProvider::GetEventGlobalPropVal_int(LPCTSTR pcszPropName, int nDefault)
  2092. {
  2093. CXTPCalendarCustomProperties* pProps = GetCustomProperties();
  2094. ASSERT(pProps);
  2095. if (!pProps)
  2096. return nDefault;
  2097. COleVariant varValue;
  2098. BOOL bRes = pProps->GetProperty(pcszPropName, varValue);
  2099. if (!bRes)
  2100. return nDefault;
  2101. if (varValue.vt != VT_I4)
  2102. {
  2103. if (FAILED(::VariantChangeType(&varValue, &varValue, 0, VT_I4)))
  2104. return nDefault;
  2105. }
  2106. return V_I4(&varValue);
  2107. }
  2108. CString CXTPCalendarMAPIDataProvider::GetEventGlobalPropVal_str(LPCTSTR pcszPropName, LPCTSTR pcszDefault)
  2109. {
  2110. CXTPCalendarCustomProperties* pProps = GetCustomProperties();
  2111. ASSERT(pProps);
  2112. if (!pProps)
  2113. return pcszDefault;
  2114. COleVariant varValue;
  2115. BOOL bRes = pProps->GetProperty(pcszPropName, varValue);
  2116. if (!bRes)
  2117. return pcszDefault;
  2118. if (varValue.vt != VT_BSTR)
  2119. {
  2120. if (FAILED(::VariantChangeType(&varValue, &varValue, 0, VT_BSTR)))
  2121. return pcszDefault;
  2122. }
  2123. return CString(V_BSTR(&varValue));
  2124. }
  2125. void CXTPCalendarMAPIDataProvider::_SetMAPIEventGlobalPropsIfNeed(LPMESSAGE pMessage,
  2126.    CXTPCalendarEvent* pEvent)
  2127. {
  2128. if (!pMessage || !pEvent)
  2129. {
  2130. ASSERT(FALSE);
  2131. return;
  2132. }
  2133. //-----------------------------------------------------------------------
  2134. int nPropTag;
  2135. //**** Common customizable properties
  2136. int nRState = pEvent->GetRecurrenceState();
  2137. int nApptIcon = (nRState == xtpCalendarRecurrenceMaster) ? cnMAPIpropVal_AppointmentIconRecurr :
  2138. cnMAPIpropVal_AppointmentIcon;
  2139. VERIFY(_setPropTagVal_int(pMessage, XTP_PR_MAPI_EVENT_ICON_INDEX, nApptIcon));
  2140. //---------------------------------------
  2141. CString strMsgClass = GetEventGlobalPropVal_str(cszMAPIpropName_AppointmentMessageClass,
  2142. cszMAPIpropVal_AppointmentMessageClass);
  2143. VERIFY(_setPropTagVal_str(pMessage, PR_MESSAGE_CLASS_A, strMsgClass));
  2144. //---------------------------------------
  2145. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_OutlookInternalVersion);
  2146. int nOutlookVer = _getPropVal_int(pMessage, nPropTag);
  2147. if (nOutlookVer == 0)
  2148. {
  2149. nOutlookVer = GetEventGlobalPropVal_int(cszMAPIpropName_OutlookInternalVersion,
  2150. cnMAPIpropVal_OutlookInternalVersionDef);
  2151. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nOutlookVer));
  2152. }
  2153. //---------------------------------------
  2154. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_OutlookVersion);
  2155. CString strOutlookVer = _getPropVal_str(pMessage, nPropTag);
  2156. if (strOutlookVer.IsEmpty())
  2157. {
  2158. strOutlookVer = GetEventGlobalPropVal_str(cszMAPIpropName_OutlookVersion,
  2159. cszMAPIpropVal_OutlookVersionDef);
  2160. VERIFY(_setPropTagVal_str(pMessage, nPropTag, strOutlookVer));
  2161. }
  2162. }
  2163. BOOL CXTPCalendarMAPIDataProvider::UpdateMAPIEvent(LPMESSAGE pMessage,
  2164.    CXTPCalendarEvent* pEvent)
  2165. {
  2166. if (!pMessage || !pEvent)
  2167. {
  2168. ASSERT(FALSE);
  2169. return FALSE;
  2170. }
  2171. //-----------------------------------------------------------------------
  2172. // ------- Is Recurrence --------
  2173. int nRState = pEvent->GetRecurrenceState();
  2174. int nIsRecurrence = (nRState == xtpCalendarRecurrenceMaster);
  2175. if (nRState != xtpCalendarRecurrenceNotRecurring &&
  2176. nRState != xtpCalendarRecurrenceMaster)
  2177. {
  2178. ASSERT(FALSE);
  2179. return TRUE;
  2180. }
  2181. // get TimeZone
  2182. //  TIME_ZONE_INFORMATION tziEvent;
  2183. //  GetTimeZoneInformation(&tziEvent);
  2184. int nPropTag;
  2185. //-------------------
  2186. //**** Common customizable properties
  2187. _SetMAPIEventGlobalPropsIfNeed(pMessage, pEvent);
  2188. //****
  2189. // ------- Subject --------
  2190. CString strTmp = pEvent->GetSubject();
  2191. VERIFY(_setPropTagVal_str(pMessage, PR_SUBJECT_A, strTmp));
  2192. // ------- Body --------
  2193. strTmp = pEvent->GetBody();
  2194. VERIFY(_setPropTagVal_str(pMessage, PR_BODY_A, strTmp));
  2195. // ------- StartTime --------
  2196. COleDateTime dtTmp = pEvent->GetStartTime();
  2197. SYSTEMTIME stUTCstart = xtp_TimeToUtc(dtTmp);
  2198. ASSERT(stUTCstart.wYear);
  2199. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_StartTime);
  2200. VERIFY(_setPropTagVal_UtcTime(pMessage, nPropTag, stUTCstart));
  2201. // ------- EndTime --------
  2202. dtTmp = pEvent->GetEndTime();
  2203. SYSTEMTIME stUTCend = xtp_TimeToUtc(dtTmp);
  2204. ASSERT(stUTCend.wYear);
  2205. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_EndTime);
  2206. VERIFY(_setPropTagVal_UtcTime(pMessage, nPropTag, stUTCend));
  2207. // ------- LOCATION --------
  2208. strTmp = pEvent->GetLocation();
  2209. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_Location);
  2210. VERIFY(_setPropTagVal_str(pMessage, nPropTag, strTmp));
  2211. // ------- AllDayEvent --------
  2212. int nTmp = pEvent->IsAllDayEvent();
  2213. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_AllDay);
  2214. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2215. // ------- IsReminder --------
  2216. nTmp = pEvent->IsReminder();
  2217. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_ReminderSet);
  2218. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2219. // ------- ReminderMinutesBeforeStart --------
  2220. nTmp = pEvent->GetReminderMinutesBeforeStart();
  2221. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_ReminderMinutesBefore);
  2222. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2223. // ------- ReminderDate --------
  2224. ULONG nPTagRmdDate = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_ReminderDate);
  2225. if (pEvent->IsReminder())
  2226. {
  2227. VERIFY(_setPropTagVal_UtcTime(pMessage, nPTagRmdDate, stUTCstart)); // always equal to start time
  2228. }
  2229. else
  2230. {
  2231. _deletePropTag(pMessage, nPTagRmdDate);
  2232. }
  2233. // ------- BusyStatus --------
  2234. nTmp = pEvent->GetBusyStatus();
  2235. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_BusyStatus);
  2236. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2237. // ------- Importance --------
  2238. nTmp = pEvent->GetImportance();
  2239. VERIFY(_setPropTagVal_int(pMessage, PR_IMPORTANCE, nTmp));
  2240. // ------- Label --------
  2241. nTmp = pEvent->GetLabelID();
  2242. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_Color);
  2243. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2244. // ------- Meeting --------
  2245. nTmp = pEvent->IsMeeting();
  2246. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_MeetingStatus);
  2247. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2248. // ------- Private --------
  2249. nTmp = pEvent->IsPrivate();
  2250. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropCommon_IsPrivate);
  2251. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nTmp));
  2252. VERIFY(_setPropTagVal_int(pMessage, PR_SENSITIVITY, nTmp ? SENSITIVITY_PRIVATE : SENSITIVITY_NONE));
  2253. // ------- CreationTime --------
  2254. dtTmp = pEvent->GetCreationTime();
  2255. SYSTEMTIME stUTC = xtp_TimeToUtc(dtTmp);
  2256. ASSERT(stUTC.wYear);
  2257. VERIFY(_setPropTagVal_UtcTime(pMessage, PR_CREATION_TIME, stUTC));
  2258. // ------- LastModificationTime --------
  2259. dtTmp = pEvent->GetLastModificationTime();
  2260. stUTC = xtp_TimeToUtc(dtTmp);
  2261. ASSERT(stUTC.wYear);
  2262. VERIFY(_setPropTagVal_UtcTime(pMessage, PR_LAST_MODIFICATION_TIME, stUTC));
  2263. // -------- Custom Properties -------
  2264. CXTPCalendarCustomProperties* pProps = pEvent->GetCustomProperties();
  2265. if (pProps)
  2266. {
  2267. CXTPCalendarCustomProperties tmpStorage;
  2268. _MoveMAPIEventRuntimeProps(&tmpStorage, pProps);
  2269. pProps->SaveToXML(strTmp);
  2270. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_CustomProperties);
  2271. VERIFY(_setPropTagVal_str(pMessage, nPropTag, strTmp));
  2272. _MoveMAPIEventRuntimeProps(pProps, &tmpStorage);
  2273. }
  2274. // nIsRecurrence
  2275. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_IsRecuring);
  2276. VERIFY(_setPropTagVal_int(pMessage, nPropTag, nIsRecurrence));
  2277. if (nIsRecurrence)
  2278. {
  2279. CByteArray arRecData;
  2280. CXTPCalendarMAPI_Recurrence::CXTPRcData RCData;
  2281. CXTPCalendarRecurrencePatternPtr ptrPattern = pEvent->GetRecurrencePattern();
  2282. BOOL bRes = CXTPCalendarMAPI_Recurrence::FillRCData(RCData, ptrPattern, pEvent);
  2283. ASSERT(bRes);
  2284. if (bRes)
  2285. {
  2286. bRes = CXTPCalendarMAPI_Recurrence::RCDataToBin(RCData, arRecData);
  2287. ASSERT(bRes);
  2288. if (bRes)
  2289. {
  2290. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceState);
  2291. VERIFY(_setPropTagVal_bin(pMessage, nPropTag, arRecData));
  2292. }
  2293. }
  2294. //---------------------------------------------------------------------
  2295. TIME_ZONE_INFORMATION tziEvent;
  2296. GetTimeZoneInformation(&tziEvent);
  2297. CByteArray arTZIData;
  2298. xtp_GetMapiTZInfo(&tziEvent, arTZIData);
  2299. ULONG ulTZTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_TimeZone);
  2300. VERIFY(_setPropTagVal_bin(pMessage, ulTZTag, arTZIData));
  2301. //- recurrence Start/end ----------------------------------------------
  2302. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceStart);
  2303. VERIFY(_setPropTagVal_UtcTime(pMessage, nPropTag, stUTCstart));
  2304. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceEnd);
  2305. VERIFY(_setPropTagVal_UtcTime(pMessage, nPropTag, stUTCend));
  2306. if (ptrPattern->GetUseEndMethod() == xtpCalendarPatternEndNoDate)
  2307. {
  2308. // the end date set above was for 1 Jan 9999, which is fine for Outlook
  2309. // but at least some versions of exchange server don't like it. Outlook
  2310. // sets the end date to the end date/time of the first instance of the
  2311. // pattern in this case.
  2312. // ------- Fixed EndTime --------
  2313. int nDuration = RCData.dwOccEndTime - RCData.dwOccStartTime;
  2314. dtTmp = pEvent->GetStartTime() + CXTPCalendarUtils::Minutes2Span(nDuration);
  2315. stUTCend = xtp_TimeToUtc(dtTmp);
  2316. ASSERT(stUTCend.wYear);
  2317. nPropTag = m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_EndTime);
  2318. VERIFY(_setPropTagVal_UtcTime(pMessage, nPropTag, stUTCend));
  2319. }
  2320. }
  2321. else
  2322. {
  2323. CUIntArray arPropsTags;
  2324. arPropsTags.Add( (ULONG)m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceState));
  2325. arPropsTags.Add( (ULONG)m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceStart));
  2326. arPropsTags.Add( (ULONG)m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_RecurrenceEnd));
  2327. arPropsTags.Add( (ULONG)m_MapiHelper.GetPropTagByID(pMessage, xtpMAPIpropEvent_TimeZone));
  2328. _deletePropsTags(pMessage, arPropsTags);
  2329. }
  2330. // -------
  2331. return TRUE;
  2332. }
  2333. UINT CXTPCalendarMAPIDataProvider::_getStreamSize(IStream* pStream)
  2334. {
  2335. ASSERT(pStream);
  2336. if (!pStream)
  2337. {
  2338. return 0;
  2339. }
  2340. ULARGE_INTEGER  uliSize = {0, 0};
  2341. LARGE_INTEGER   liZero = {0, 0};
  2342. HRESULT hr = pStream->Seek(liZero, STREAM_SEEK_END, &uliSize);
  2343. if (FAILED(hr))
  2344. return 0;
  2345. hr = pStream->Seek(liZero, STREAM_SEEK_SET, NULL);
  2346. if (FAILED(hr))
  2347. {
  2348. return 0;
  2349. }
  2350. return uliSize.u.LowPart;
  2351. }
  2352. int CXTPCalendarMAPIDataProvider::_getSimpleMAPITypeSize(int nType)
  2353. {
  2354. switch(nType)
  2355. {
  2356. case PT_I2:     return 2;       /* Signed 16-bit value */
  2357. case PT_LONG:   return 4;       /* Signed 32-bit value */
  2358. case PT_R4:     return 4;       /* 4-byte floating point */
  2359. case PT_DOUBLE:     return 8;   /* Floating point double */
  2360. case PT_CURRENCY:   return 8;   /* Signed 64-bit int (decimal w/    4 digits right of decimal pt) */
  2361. case PT_APPTIME:    return sizeof(double);  /* Application time */
  2362. case PT_ERROR:      return 4;   /* 32-bit error value */
  2363. case PT_BOOLEAN:    return 2;   /* 16-bit boolean (non-zero true) */
  2364. case PT_I8:         return 8;   /* 8-byte signed integer */
  2365. case PT_SYSTIME:    return sizeof(FILETIME);    /* FILETIME 64-bit int w/ number of 100ns periods since Jan 1,1601 */
  2366. case PT_CLSID:      return sizeof(GUID);        /* OLE GUID */
  2367. case PT_OBJECT:     /* Embedded object in a property */
  2368. case PT_STRING8:    /* Null terminated 8-bit character string */
  2369. case PT_UNICODE:    /* Null terminated Unicode string */
  2370. case PT_BINARY:     /* Uninterpreted (counted byte array) */
  2371. return 0;
  2372. default:
  2373. ASSERT(FALSE);
  2374. }
  2375. return 0;
  2376. }
  2377. BOOL CXTPCalendarMAPIDataProvider::_setPropTagVal_int(LPMESSAGE pMessage,
  2378.   ULONG ulPropTag, int nValue)
  2379. {
  2380. int nType = PROP_TYPE(ulPropTag);
  2381. int nTypeSize = _getSimpleMAPITypeSize(nType);
  2382. if (nTypeSize <= 0 || nTypeSize > 4)
  2383. {
  2384. ASSERT(FALSE);
  2385. return FALSE;
  2386. }
  2387. SPropValue PropVal;
  2388. ZeroMemory(&PropVal, sizeof(PropVal));
  2389. PropVal.ulPropTag = ulPropTag;
  2390. switch(nType)
  2391. {
  2392. case PT_I2:
  2393. PropVal.Value.i = (short int)nValue;
  2394. break;
  2395. case PT_LONG:           /* Signed 32-bit value */
  2396. PropVal.Value.l = (long)nValue;
  2397. break;
  2398. case PT_ERROR:      /* 32-bit error value */
  2399. PropVal.Value.err = (SCODE)nValue;
  2400. break;
  2401. case PT_BOOLEAN:        /* 16-bit boolean (non-zero true) */
  2402. PropVal.Value.b = (unsigned short int)nValue;
  2403. break;
  2404. //  case PT_R4:     return 4;       /* 4-byte floating point */
  2405. //  case PT_DOUBLE:     return 8;   /* Floating point double */
  2406. //  case PT_CURRENCY:   return 8;   /* Signed 64-bit int (decimal w/    4 digits right of decimal pt) */
  2407. //  case PT_APPTIME:    return sizeof(double);  /* Application time */
  2408. //  case PT_I8:         return 8;   /* 8-byte signed integer */
  2409. //  case PT_SYSTIME:    return sizeof(FILETIME);    /* FILETIME 64-bit int w/ number of 100ns periods since Jan 1,1601 */
  2410. //  case PT_CLSID:      return sizeof(GUID);        /* OLE GUID */
  2411. //  case PT_OBJECT:     /* Embedded object in a property */
  2412. //  case PT_STRING8:    /* Null terminated 8-bit character string */
  2413. //  case PT_UNICODE:    /* Null terminated Unicode string */
  2414. //  case PT_BINARY:     /* Uninterpreted (counted byte array) */
  2415. //      return 0;
  2416. default:
  2417. ASSERT(FALSE);
  2418. return FALSE;
  2419. }
  2420. HRESULT hRes = this->HrSetOneProp(pMessage, &PropVal);
  2421. return SUCCEEDED(hRes);
  2422. }
  2423. BOOL CXTPCalendarMAPIDataProvider::_setPropTagVal_str(LPMESSAGE pMessage,
  2424.   ULONG ulPropTag, LPCTSTR pcszValue)
  2425. {
  2426. int nType = PROP_TYPE(ulPropTag);
  2427. LPSPropValue pPropVal = NULL;
  2428. if (nType == PT_STRING8) /* Null terminated 8-bit character string */
  2429. {
  2430. int nStrBuffSize = (int)_tcslen(pcszValue) * sizeof(TCHAR) + 2;
  2431. int nBufSize = sizeof(SPropValue) + nStrBuffSize + 4;
  2432. SCODE sc = this->MAPIAllocateBuffer(nBufSize, (void**)&pPropVal);
  2433. if (sc != S_OK || !pPropVal)
  2434. {
  2435. return FALSE;
  2436. }
  2437. ZeroMemory(pPropVal, nBufSize);
  2438. pPropVal->ulPropTag = ulPropTag;
  2439. pPropVal->Value.lpszA = (LPSTR)(pPropVal+1);
  2440. WCSTOMBS_S(pPropVal->Value.lpszA, pcszValue, nStrBuffSize);
  2441. }
  2442. else if (nType == PT_UNICODE) /* Null terminated Unicode string */
  2443. {
  2444. ASSERT(FALSE); //not implemented
  2445. return FALSE;
  2446. }
  2447. else
  2448. {
  2449. ASSERT(FALSE);
  2450. return FALSE;
  2451. }
  2452. HRESULT hRes = this->HrSetOneProp(pMessage, pPropVal);
  2453. MAPI_FREEBUFFER(this, pPropVal);
  2454. return SUCCEEDED(hRes);
  2455. }
  2456. BOOL CXTPCalendarMAPIDataProvider::_setPropTagVal_UtcTime(LPMESSAGE pMessage,
  2457.   ULONG ulPropTag, const SYSTEMTIME& stTime)
  2458. {
  2459. int nType = PROP_TYPE(ulPropTag);
  2460. SPropValue PropVal;
  2461. ZeroMemory(&PropVal, sizeof(SPropValue));
  2462. if (nType == PT_SYSTIME) // FILETIME
  2463. {
  2464. PropVal.ulPropTag = ulPropTag;
  2465. FILETIME ft;
  2466. ZeroMemory(&ft, sizeof(ft));
  2467. if (!SystemTimeToFileTime(&stTime, &ft))
  2468. {
  2469. ASSERT(FALSE);
  2470. return FALSE;
  2471. }
  2472. PropVal.Value.ft = ft;
  2473. }
  2474. else
  2475. {
  2476. ASSERT(FALSE);
  2477. return FALSE;
  2478. }
  2479. HRESULT hRes = this->HrSetOneProp(pMessage, &PropVal);
  2480. return SUCCEEDED(hRes);
  2481. }
  2482. BOOL CXTPCalendarMAPIDataProvider::_setPropTagVal_bin(LPMESSAGE pMessage,
  2483. ULONG ulPropTag, const CByteArray& arData)
  2484. {
  2485. int nType = PROP_TYPE(ulPropTag);
  2486. SPropValue PropVal;
  2487. ZeroMemory(&PropVal, sizeof(SPropValue));
  2488. if (nType == PT_BINARY)
  2489. {
  2490. PropVal.ulPropTag = ulPropTag;
  2491. PropVal.Value.bin.cb = (ULONG)arData.GetSize();
  2492. PropVal.Value.bin.lpb = (BYTE*)arData.GetData();
  2493. }
  2494. else
  2495. {
  2496. ASSERT(FALSE);
  2497. return FALSE;
  2498. }
  2499. HRESULT hRes = this->HrSetOneProp(pMessage, &PropVal);
  2500. return SUCCEEDED(hRes);
  2501. }
  2502. HRESULT CXTPCalendarMAPIDataProvider::_getPropVal(LPMESSAGE pMessage,
  2503.   ULONG ulPropTag, CByteArray& rData)
  2504. {
  2505. rData.RemoveAll();
  2506. LPSTREAM pStream = NULL;
  2507. LPSPropValue pProp = NULL;
  2508. HRESULT hRes = this->HrGetOneProp(pMessage, ulPropTag, &pProp);
  2509. if (hRes == MAPI_E_NOT_ENOUGH_MEMORY)
  2510. {
  2511. hRes = pMessage->OpenProperty(ulPropTag, &IID_IStream, STGM_READ,
  2512. NULL, (LPUNKNOWN*)&pStream);
  2513. if (FAILED(hRes) || !pStream)
  2514. {
  2515. hRes = FAILED(hRes) ? hRes : E_FAIL;
  2516. }
  2517. else
  2518. {
  2519. UINT nDataSize = _getStreamSize(pStream);
  2520. if (!nDataSize)
  2521. {
  2522. hRes = E_FAIL;
  2523. }
  2524. else
  2525. {
  2526. rData.SetSize((int)nDataSize);
  2527. ULONG nDataSize2 = 0;
  2528. hRes = pStream->Read(rData.GetData(), nDataSize, &nDataSize2);
  2529. ASSERT(nDataSize == nDataSize2);
  2530. rData.SetSize((int)nDataSize2);
  2531. }
  2532. pStream->Release();
  2533. }
  2534. }
  2535. else if (SUCCEEDED(hRes))
  2536. {
  2537. int nType = PROP_TYPE(pProp->ulPropTag);
  2538. int nTypeSize = _getSimpleMAPITypeSize(nType);
  2539. void* pData_src = NULL;
  2540. if (nTypeSize > 0)
  2541. {
  2542. pData_src = (void*)&pProp->Value;
  2543. }
  2544. else
  2545. {
  2546. if (nType == PT_STRING8) /* Null terminated 8-bit character string */
  2547. {
  2548. pData_src = (void*)pProp->Value.lpszA;
  2549. nTypeSize = (int)strlen(pProp->Value.lpszA) + 1;
  2550. }
  2551. else if (nType == PT_UNICODE) /* Null terminated Unicode string */
  2552. {
  2553. pData_src = (void*)pProp->Value.lpszW;
  2554. nTypeSize = (int)wcslen(pProp->Value.lpszW) * 2 + 2;
  2555. }
  2556. else if (nType == PT_BINARY) /* Uninterpreted (counted byte array) */
  2557. {
  2558. pData_src = (void*)pProp->Value.bin.lpb;
  2559. nTypeSize = pProp->Value.bin.cb;
  2560. }
  2561. }
  2562. rData.SetSize(nTypeSize);
  2563. MEMCPY_S(rData.GetData(), pData_src, nTypeSize);
  2564. }
  2565. MAPI_FREEBUFFER(this, pProp);
  2566. return hRes;
  2567. }
  2568. CString CXTPCalendarMAPIDataProvider::_getPropVal_str(LPMESSAGE pMessage,
  2569.   ULONG ulPropTag)
  2570. {
  2571. CString str;
  2572. CByteArray arData;
  2573. int nType = PROP_TYPE(ulPropTag);
  2574. ASSERT(nType == PT_STRING8 || nType == PT_UNICODE);
  2575. HRESULT hr = _getPropVal(pMessage, ulPropTag, arData);
  2576. if (FAILED(hr) || arData.GetSize() == 0)
  2577. {
  2578. return str;
  2579. }
  2580. if (nType == PT_STRING8) /* Null terminated 8-bit character string */
  2581. {
  2582. str = (LPCSTR)arData.GetData();
  2583. }
  2584. else if (nType == PT_UNICODE) /* Null terminated Unicode string */
  2585. {
  2586. str = (LPCWSTR)arData.GetData();
  2587. }
  2588. return str;
  2589. }
  2590. int CXTPCalendarMAPIDataProvider::_getPropVal_int(LPMESSAGE pMessage, ULONG ulPropTag)
  2591. {
  2592. CByteArray arData;
  2593. int nType = PROP_TYPE(ulPropTag);
  2594. ASSERT( nType == PT_I2 ||       nType == PT_LONG ||
  2595. nType == PT_ERROR ||    nType == PT_BOOLEAN ||
  2596. nType == PT_I8);
  2597. HRESULT hr = _getPropVal(pMessage, ulPropTag, arData);
  2598. if (FAILED(hr) || arData.GetSize() == 0)
  2599. {
  2600. return 0;
  2601. }
  2602. int nSize = (int)arData.GetSize();
  2603. int nValue = 0;
  2604. ASSERT(sizeof(ULONGLONG) == 8);
  2605. if (nSize == 1)
  2606. {
  2607. nValue = (int)arData[0];
  2608. }
  2609. else if (nSize == 2)
  2610. {
  2611. nValue = (int)*((WORD*)arData.GetData());
  2612. }
  2613. else if (nSize == 3)
  2614. {
  2615. nValue = (int)RGB(arData[0], arData[1], arData[2]);
  2616. }
  2617. else if (nSize == 4)
  2618. {
  2619. nValue = (int)*((DWORD*)arData.GetData());
  2620. }
  2621. else if (nSize == 8)
  2622. {
  2623. nValue = (int)*((ULONGLONG*)arData.GetData());
  2624. }
  2625. else
  2626. {
  2627. ASSERT(FALSE);
  2628. }
  2629. return nValue;
  2630. }
  2631. SYSTEMTIME CXTPCalendarMAPIDataProvider::_getPropVal_UtcTime(LPMESSAGE pMessage,
  2632.    ULONG ulPropTag)
  2633. {
  2634. SYSTEMTIME stUTCTime, stUTCTime0;
  2635. ZeroMemory(&stUTCTime, sizeof(stUTCTime));
  2636. ZeroMemory(&stUTCTime0, sizeof(stUTCTime0));
  2637. if (ulPropTag == 0)
  2638. {
  2639. return stUTCTime0;
  2640. }
  2641. int nType = PROP_TYPE(ulPropTag);
  2642. if (nType != PT_SYSTIME)
  2643. {
  2644. ASSERT(FALSE);
  2645. return stUTCTime0;
  2646. }
  2647. CByteArray arData;
  2648. HRESULT hr = _getPropVal(pMessage, ulPropTag, arData);
  2649. if (FAILED(hr) || arData.GetSize() == 0)
  2650. {
  2651. return stUTCTime0;
  2652. }
  2653. ASSERT(arData.GetSize() == sizeof(FILETIME));
  2654. FILETIME* pUTCTime = ((FILETIME*)arData.GetData());
  2655. if (FileTimeToSystemTime(pUTCTime, &stUTCTime))
  2656. {
  2657. return stUTCTime;
  2658. }
  2659. return stUTCTime0;
  2660. }
  2661. CString CXTPCalendarMAPIDataProvider::_getPropVal_str(LPMESSAGE pMessage,
  2662. const XTP_MAPI_PROP_NAME& propNameEx)
  2663. {
  2664. ULONG ulPropTag = m_MapiHelper.GetPropTagByID(pMessage, propNameEx);
  2665. return _getPropVal_str(pMessage, ulPropTag);
  2666. }
  2667. int CXTPCalendarMAPIDataProvider::_getPropVal_int(LPMESSAGE pMessage,
  2668. const XTP_MAPI_PROP_NAME& propNameEx)
  2669. {
  2670. ULONG ulPropTag = m_MapiHelper.GetPropTagByID(pMessage, propNameEx);
  2671. return _getPropVal_int(pMessage, ulPropTag);
  2672. }
  2673. SYSTEMTIME CXTPCalendarMAPIDataProvider::_getPropVal_UtcTime(LPMESSAGE pMessage,
  2674. const XTP_MAPI_PROP_NAME& propNameEx)
  2675. {
  2676. ULONG ulPropTag = m_MapiHelper.GetPropTagByID(pMessage, propNameEx);
  2677. return _getPropVal_UtcTime(pMessage, ulPropTag);
  2678. }
  2679. HRESULT CXTPCalendarMAPIDataProvider::_deletePropTag(LPMESSAGE pMessage, ULONG ulPropTag)
  2680. {
  2681. CUIntArray arPropsTags;
  2682. arPropsTags.Add(ulPropTag);
  2683. return _deletePropsTags(pMessage, arPropsTags);
  2684. }
  2685. HRESULT CXTPCalendarMAPIDataProvider::_deletePropsTags(LPMESSAGE pMessage, CUIntArray& arPropsTags)
  2686. {
  2687. if (!pMessage || arPropsTags.GetSize() == 0)
  2688. {
  2689. ASSERT(FALSE);
  2690. return E_INVALIDARG;
  2691. }
  2692. int nTagsCount = (int)arPropsTags.GetSize();
  2693. SPropTagArray* pPorpTagsArray = NULL;
  2694. int nBufSize = sizeof(SPropTagArray) + nTagsCount * sizeof(ULONG) + 4;
  2695. SCODE sc = this->MAPIAllocateBuffer(nBufSize, (void**)&pPorpTagsArray);
  2696. if (sc != S_OK || !pPorpTagsArray)
  2697. {
  2698. return E_OUTOFMEMORY;
  2699. }
  2700. //---------------------------------------------
  2701. pPorpTagsArray->cValues = nTagsCount;
  2702. for (int i = 0; i < nTagsCount; i++)
  2703. {
  2704. pPorpTagsArray->aulPropTag[i] = (ULONG)arPropsTags[i];
  2705. }
  2706. HRESULT hrDelete = pMessage->DeleteProps(pPorpTagsArray, NULL);
  2707. //---------------------------------------------
  2708. MAPI_FREEBUFFER(this, pPorpTagsArray);
  2709. return hrDelete;
  2710. }
  2711. void CXTPCalendarMAPIDataProvider::ImportRecurrence(CXTPCalendarEvent* pMasterEvent,
  2712. const CByteArray& arRCData)
  2713. {
  2714. ASSERT(pMasterEvent->GetRecurrenceState() == xtpCalendarRecurrenceMaster);
  2715. CXTPCalendarRecurrencePatternPtr ptrPattern = pMasterEvent->GetRecurrencePattern();
  2716. ASSERT(ptrPattern);
  2717. if (!ptrPattern)
  2718. {
  2719. return;
  2720. }
  2721. CXTPCalendarMAPI_Recurrence::CXTPRcData RCData;
  2722. BOOL bRead = CXTPCalendarMAPI_Recurrence::ReadRCData(RCData, arRCData);
  2723. ASSERT(bRead);
  2724. if (!bRead)
  2725. {
  2726. return;
  2727. }
  2728. ASSERT((RCData.wType - xtpMAPIRcType_Daily) >= 0 && (RCData.wType - xtpMAPIRcType_Daily) <= 3);
  2729. CXTPCalendarMAPI_Recurrence::SetRecurrenceOptions(ptrPattern, RCData);
  2730. CXTPCalendarMAPI_Recurrence::SetRecurrenceExceptions(pMasterEvent, ptrPattern, RCData);
  2731. VERIFY( pMasterEvent->UpdateRecurrence(ptrPattern) );
  2732. }
  2733. CXTPCalendarEventsPtr CXTPCalendarMAPIDataProvider::ImportAllEvents(LPSRestriction lpRestriction)
  2734. {
  2735. HRESULT hRes = S_OK;
  2736. LPMAPITABLE lpContentsTable = NULL;
  2737. LPSRowSet pRows = NULL;
  2738. ULONG i;
  2739. CXTPCalendarEventsPtr ptrEvents = new CXTPCalendarEvents();
  2740. static SizedSPropTagArray(1, sptCols) = {1, {PR_ENTRYID} };
  2741. hRes = m_lpCalendarFolder->GetContentsTable(0, &lpContentsTable);
  2742. if (SUCCEEDED(hRes))
  2743. {
  2744. hRes = this->HrQueryAllRows(lpContentsTable, (LPSPropTagArray) &sptCols,
  2745.   lpRestriction, //restriction...current day
  2746.   NULL,//sort order...we're not using this parameter
  2747.   0, &pRows);
  2748. if (SUCCEEDED(hRes))
  2749. {
  2750. for (i = 0; i < pRows->cRows; i++)
  2751. {
  2752. CXTPCalendarEventPtr ptrNextEvent = ImportEvent(&pRows->aRow[i]);
  2753. ASSERT(ptrNextEvent);
  2754. if (ptrNextEvent)
  2755. {
  2756. ptrEvents->Add(ptrNextEvent);
  2757. }
  2758. }
  2759. }
  2760. }
  2761. //-------------------------------------------------------------------------
  2762. if (pRows)
  2763. {
  2764. this->FreeProws(pRows);
  2765. }
  2766. MAPI_RELEASE(this, lpContentsTable);
  2767. return ptrEvents;
  2768. }
  2769. BOOL CXTPCalendarMAPIDataProvider::ImportNewEvents()
  2770. {
  2771. ASSERT(m_pMemDP);
  2772. if (!m_pMemDP)
  2773. {
  2774. return FALSE;
  2775. }
  2776. BOOL bChanged = FALSE;
  2777. HRESULT hRes = S_OK;
  2778. LPMAPITABLE lpContentsTable = NULL;
  2779. LPSRowSet pRows = NULL;
  2780. ULONG i;
  2781. CMap_EventIDs mapExistingEntries;
  2782. CMap_EventIDs mapMissedEntries;
  2783. // Retrieve EntryID's of all items from the MAPI Calendar folder
  2784. static SizedSPropTagArray(2, sptCols) = {2, {PR_ENTRYID, PR_SEARCH_KEY} };
  2785. hRes = m_lpCalendarFolder->GetContentsTable(0, &lpContentsTable);
  2786. if (SUCCEEDED(hRes))
  2787. {
  2788. hRes = this->HrQueryAllRows(lpContentsTable, (LPSPropTagArray) &sptCols,
  2789. NULL, //lpRestriction, //restriction...current day??
  2790. NULL,//sort order...we're not using this parameter
  2791. 0, &pRows);
  2792. if (SUCCEEDED(hRes))
  2793. {
  2794. // Iterate all appointment items read from data source
  2795. for (i = 0; i < pRows->cRows; i++)
  2796. {
  2797. // ------- SEARCH_KEY --------
  2798. if (PR_SEARCH_KEY != pRows->aRow[i].lpProps[1].ulPropTag)
  2799. {
  2800. ASSERT(FALSE);
  2801. continue;
  2802. }
  2803. // trying to find this eventID
  2804. DWORD dwEventID = GetEventID(pRows->aRow[i].lpProps[1].Value.bin.cb,
  2805. (LPENTRYID)pRows->aRow[i].lpProps[1].Value.bin.lpb);
  2806. // if not found - import
  2807. if (XTP_CALENDAR_UNKNOWN_EVENT_ID == dwEventID)
  2808. {
  2809. CXTPCalendarEventPtr ptrNextEvent = ImportEvent(&pRows->aRow[i]);
  2810. ASSERT(ptrNextEvent);
  2811. if (ptrNextEvent)
  2812. {
  2813. bChanged = TRUE;
  2814. VERIFY(m_pMemDP->AddEvent(ptrNextEvent));
  2815. }
  2816. }
  2817. else
  2818. {
  2819. // if event found - add its ID into a map
  2820. mapExistingEntries.SetAt(dwEventID, TRUE);
  2821. }
  2822. }
  2823. // Delete all items which exists in internal data storage, but
  2824. // were not just found in the contents table of the external folder.
  2825. m_mapID.FindMissing(mapExistingEntries, mapMissedEntries);
  2826. POSITION pos = mapMissedEntries.GetStartPosition();
  2827. DWORD dwKey;
  2828. BOOL bValue = FALSE;
  2829. while (pos != NULL)
  2830. {
  2831. bChanged = TRUE;
  2832. mapMissedEntries.GetNextAssoc(pos, dwKey, bValue);
  2833. CXTPCalendarEventPtr ptrEventToDel = m_pMemDP->GetEvent(dwKey);
  2834. // ASSERT(ptrEventToDel); // could be NULL if processing a few notifications in a row
  2835. if (ptrEventToDel)
  2836. {
  2837. VERIFY(m_pMemDP->DeleteEvent(ptrEventToDel));
  2838. }
  2839. }
  2840. }
  2841. }
  2842. // Cleanup
  2843. if (pRows)
  2844. {
  2845. this->FreeProws(pRows);
  2846. }
  2847. MAPI_RELEASE(this, lpContentsTable);
  2848. return bChanged;
  2849. }
  2850. LONG STDAPICALLTYPE CXTPCalendarMAPIDataProvider::MAPICallBack_OnNotify(
  2851. LPVOID          lpvContext,
  2852. ULONG           cNotif,
  2853. LPNOTIFICATION  lpNotif)
  2854. {
  2855. BOOL bProcessed = FALSE;
  2856. // get current MAPI data provider
  2857. CXTPCalendarMAPIDataProvider* pThis = (CXTPCalendarMAPIDataProvider*)lpvContext;
  2858. ASSERT(pThis);
  2859. if (!pThis)
  2860. return MAPI_E_INVALID_PARAMETER;
  2861. CXTPCalendarData* pMemDP = pThis->m_pMemDP;
  2862. if (!pMemDP)
  2863. {
  2864. return S_OK;
  2865. }
  2866. //***********************
  2867. SAFE_MANAGE_STATE(pThis->m_pModuleState);
  2868. //***********************
  2869. XTP_TRACE_MAPI_NF(_T("n MAPICallBack_OnNotify [%s] (notifications count = %d)n"),
  2870.   COleDateTime::GetCurrentTime().Format(), (int)cNotif);
  2871. for (int i = 0; i < (int)cNotif; i++)
  2872. {
  2873. ULONG ulNfSender = lpNotif[i].info.obj.ulObjType;
  2874. ULONG ulNfType = lpNotif[i].ulEventType;
  2875. XTP_TRACE_MAPI_NF(_T("    NfSender = %d (%s)n"), (int)ulNfSender,
  2876. ulNfSender == MAPI_FOLDER ? _T("MAPI_FOLDER") : (ulNfSender == MAPI_MESSAGE ? _T("MAPI_MESSAGE") : _T("")) );
  2877. // Check is notification related to active calendar folder ----------
  2878. CString str_dbg_CalRel;
  2879. CXTPMAPIBinary eidObj;
  2880. if (ulNfSender == MAPI_FOLDER)
  2881. {
  2882. eidObj.Set(lpNotif[i].info.obj.cbEntryID, (LPBYTE)lpNotif[i].info.obj.lpEntryID);
  2883. str_dbg_CalRel = _T("this");
  2884. }
  2885. else if (ulNfSender == MAPI_MESSAGE)
  2886. {
  2887. eidObj.Set(lpNotif[i].info.obj.cbParentID, (LPBYTE)lpNotif[i].info.obj.lpParentID);
  2888. str_dbg_CalRel = _T("Parent folder");
  2889. }
  2890. if (!pThis->Equal(eidObj, pThis->m_eidCalendarFolder))
  2891. {
  2892. if (ulNfSender == MAPI_MESSAGE)
  2893. {
  2894. eidObj.Set(lpNotif[i].info.obj.cbOldParentID, (LPBYTE)lpNotif[i].info.obj.lpOldParentID);
  2895. if (!pThis->Equal(eidObj, pThis->m_eidCalendarFolder))
  2896. {
  2897. XTP_TRACE_MAPI_NF(_T("    Calendar is: not related! SKIP. n"));
  2898. continue;
  2899. }
  2900. else
  2901. {
  2902. str_dbg_CalRel = _T("OLD Parent folder");
  2903. pThis->ImportNewEvents();
  2904. bProcessed = TRUE;
  2905. }
  2906. }
  2907. else
  2908. {
  2909. XTP_TRACE_MAPI_NF(_T("    Calendar is: not related! SKIP. n"));
  2910. continue;
  2911. }
  2912. }
  2913. XTP_TRACE_MAPI_NF(_T("    Calendar is: %sn"), str_dbg_CalRel);
  2914. CString str_dbg_NF;
  2915. str_dbg_NF += (ulNfType & fnevObjectCreated) ? _T(" | Created") : _T("");
  2916. str_dbg_NF += (ulNfType & fnevObjectDeleted) ? _T(" | Deleted") : _T("");
  2917. str_dbg_NF += (ulNfType & fnevObjectModified) ?_T(" | Modified") : _T("");
  2918. str_dbg_NF += (ulNfType & fnevObjectMoved)   ? _T(" | Moved") : _T("");
  2919. str_dbg_NF += (ulNfType & fnevObjectCopied)  ? _T(" | Copied") : _T("");
  2920. XTP_TRACE_MAPI_NF(_T("    fnevObject =%s n"), str_dbg_NF);
  2921. if (bProcessed)
  2922. {
  2923. return SUCCESS_SUCCESS;
  2924. }
  2925. //-------------------------------------------------------------------
  2926. CXTPMAPIBinary keyID = pThis->GetSearchKey(lpNotif[i].info.obj.cbEntryID, lpNotif[i].info.obj.lpEntryID);
  2927. DWORD dwEventID = pThis->GetEventID(keyID.GetBinarySize(), (LPENTRYID)keyID.GetBinaryData());
  2928. CXTPCalendarEventPtr ptrEvent = pMemDP->GetEvent(dwEventID);
  2929. XTP_TRACE_MAPI_NF(_T("    event ID = %d (%s)n"), dwEventID,
  2930. (LPCTSTR)(ptrEvent ? _T("exists") : _T("non-exists")) );
  2931. // look what type of change was performed
  2932. if (ulNfType & fnevObjectDeleted)
  2933. {
  2934. // Delete the event
  2935. // Note that this message will never be received for deleted item for Exchange 5.5 and 2000.
  2936. // More info at MS KB261172
  2937. if (ptrEvent)
  2938. {
  2939. VERIFY( pMemDP->DeleteEvent(ptrEvent) );
  2940. XTP_TRACE_MAPI_NF(_T("    Action = DELETEn"));
  2941. //#pragma NOTE("Advice to DP notification and resend")
  2942. //pThis->m_pConnect->SendEvent(XTP_NC_CALENDAREVENTWASDELETED, (WPARAM)dwEventID, (LPARAM)(CXTPCalendarEvent*)ptrEvent);
  2943. }
  2944. continue;
  2945. }
  2946. if ((ulNfType & fnevObjectCreated) && ulNfSender == MAPI_MESSAGE)
  2947. {
  2948. if (dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID)
  2949. {
  2950. //ASSERT(FALSE);
  2951. XTP_TRACE_MAPI_NF(_T("    Action = skipn"));
  2952. return SUCCESS_SUCCESS;
  2953. }
  2954. // Add a new event
  2955. CXTPCalendarEventPtr ptrEvent2 = pThis->ImportEvent(
  2956. lpNotif[i].info.obj.cbEntryID,
  2957. lpNotif[i].info.obj.lpEntryID);
  2958. if (ptrEvent && ptrEvent2)
  2959. {
  2960. //Event already exists
  2961. VERIFY( pMemDP->ChangeEvent(ptrEvent2) );
  2962. XTP_TRACE_MAPI_NF(_T("    Action = CHANGEn"));
  2963. }
  2964. else if (ptrEvent2)
  2965. {
  2966. VERIFY( pMemDP->AddEvent(ptrEvent2) );
  2967. XTP_TRACE_MAPI_NF(_T("    Action = ADDn"));
  2968. }
  2969. continue;
  2970. }
  2971. if ((ulNfType & fnevObjectMoved) && ulNfSender == MAPI_MESSAGE)
  2972. {
  2973. CXTPCalendarEventPtr ptrEvent2 = pThis->ImportEvent_FromCalendarFolderOnly(
  2974. lpNotif[i].info.obj.cbEntryID,
  2975. lpNotif[i].info.obj.lpEntryID);
  2976. if (ptrEvent && ptrEvent2)
  2977. {
  2978. //Event was moved inside Calendar folder
  2979. VERIFY( pMemDP->ChangeEvent(ptrEvent2) );
  2980. XTP_TRACE_MAPI_NF(_T("    Action = CHANGEn"));
  2981. }
  2982. else if (ptrEvent)
  2983. {
  2984. //Event was moved Out of Calendar folder (to "Deleted Items" folder)
  2985. VERIFY( pMemDP->DeleteEvent(ptrEvent) );
  2986. XTP_TRACE_MAPI_NF(_T("    Action = DELETE (moved to other folder)n"));
  2987. }
  2988. continue;
  2989. }
  2990. if ((ulNfType & fnevObjectModified) && ulNfSender == MAPI_MESSAGE)
  2991. {
  2992. // is Our event changed
  2993. if (ptrEvent)
  2994. {
  2995. // Read new event data
  2996. CXTPCalendarEventPtr ptrEvent2 = pThis->ImportEvent(
  2997. lpNotif[i].info.obj.cbEntryID,
  2998. lpNotif[i].info.obj.lpEntryID);
  2999. ASSERT(ptrEvent2);
  3000. // Update event properties in the cache
  3001. if (ptrEvent2)
  3002. {
  3003. ASSERT(ptrEvent->GetEventID() == ptrEvent2->GetEventID());
  3004. DWORD dwPatternID = ptrEvent->GetRecurrencePatternID();
  3005. if (dwPatternID != XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID)
  3006. {
  3007. ptrEvent2->SetRecurrencePatternID(dwPatternID);
  3008. }
  3009. pMemDP->ChangeEvent(ptrEvent2);
  3010. XTP_TRACE_MAPI_NF(_T("    Action = CHANGE.2n"));
  3011. }
  3012. }
  3013. continue;
  3014. }
  3015. }
  3016. return SUCCESS_SUCCESS;
  3017. }
  3018. DWORD CXTPCalendarMAPIDataProvider::GetNextUniqueEventID(DWORD dwEventID)
  3019. {
  3020. if (XTP_CALENDAR_UNKNOWN_EVENT_ID == dwEventID)
  3021. dwEventID = GetNextFreeTempID();
  3022. CXTPMAPIBinary eKeyTmp;
  3023. while (m_mapID.Lookup(dwEventID, eKeyTmp))
  3024. {
  3025. dwEventID = GetNextFreeTempID();
  3026. }
  3027. ASSERT(m_mapID.Lookup(dwEventID, eKeyTmp) == FALSE);
  3028. return dwEventID;
  3029. }
  3030. CXTPMAPIBinary CXTPCalendarMAPIDataProvider::GetSearchKey(ULONG cbEntryID, LPENTRYID lpEntryID)
  3031. {
  3032. CXTPMAPIBinary keySearch;
  3033. if (cbEntryID == 0 || !lpEntryID || !m_lpCalendarFolder)
  3034. {
  3035. ASSERT(FALSE);
  3036. return keySearch;
  3037. }
  3038. LPMESSAGE pMessage = NULL;
  3039. ULONG ulObjType = NULL;
  3040. // open event from Calendar Folder storage
  3041. m_lpCalendarFolder->OpenEntry(cbEntryID, lpEntryID,
  3042. NULL,//default interface
  3043. MAPI_BEST_ACCESS,
  3044. &ulObjType,
  3045. (LPUNKNOWN*)&pMessage);
  3046. //ASSERT(ulObjType == 5);
  3047. //ASSERT(pMessage); // CHECK
  3048. if (!pMessage)
  3049. {
  3050. return keySearch;
  3051. }
  3052. // Get SearchKey
  3053. CByteArray arSearchKey;
  3054. HRESULT hrID = _getPropVal(pMessage, PR_SEARCH_KEY, arSearchKey);
  3055. if (SUCCEEDED(hrID))
  3056. {
  3057. keySearch.Set((int)arSearchKey.GetSize(), arSearchKey.GetData());
  3058. }
  3059. MAPI_RELEASE(this, pMessage);
  3060. return keySearch;
  3061. }
  3062. CXTPMAPIBinary CXTPCalendarMAPIDataProvider::GetEntryID(CXTPMAPIBinary& eSearchKey)
  3063. {
  3064. if (eSearchKey.GetBinarySize() == 0 || !eSearchKey.GetBinaryData() || !m_lpCalendarFolder)
  3065. {
  3066. ASSERT(FALSE);
  3067. return eSearchKey;
  3068. }
  3069. HRESULT hRes = S_OK;
  3070. LPMAPITABLE lpContentsTable = NULL;
  3071. LPSRowSet pRows = NULL;
  3072. CXTPMAPIBinary eid;
  3073. LPSRestriction pRestriction = BuildBinaryRestriction(eSearchKey.GetBinarySize(), eSearchKey.GetBinaryData(), PR_SEARCH_KEY);
  3074. static SizedSPropTagArray(1, sptCols) = {1, {PR_ENTRYID} };
  3075. hRes = m_lpCalendarFolder->GetContentsTable(0, &lpContentsTable);
  3076. if (SUCCEEDED(hRes))
  3077. {
  3078. hRes = this->HrQueryAllRows(lpContentsTable, (LPSPropTagArray) &sptCols,
  3079. pRestriction, //restriction...
  3080. NULL,//sort order...we're not using this parameter
  3081. 0, &pRows);
  3082. if (SUCCEEDED(hRes) && pRows->cRows > 0)
  3083. {
  3084. // ASSERT(pRows->cRows == 1); // we can get only one item by its Search Key
  3085. ASSERT(PR_ENTRYID == pRows->aRow[0].lpProps[0].ulPropTag); // we asked only for EntryID
  3086. eid.Set(pRows->aRow[0].lpProps[0].Value.bin.cb,
  3087. pRows->aRow[0].lpProps[0].Value.bin.lpb);
  3088. }
  3089. }
  3090. // cleanup
  3091. if (pRows)
  3092. {
  3093. this->FreeProws(pRows);
  3094. }
  3095. MAPI_RELEASE(this, lpContentsTable);
  3096. return eid;
  3097. }
  3098. DWORD CXTPCalendarMAPIDataProvider::GetEventID(
  3099. ULONG cbSearchKey, LPENTRYID lpSearchKey, BOOL bAddNew)
  3100. {
  3101. CXTPMAPIBinary eKey(cbSearchKey, lpSearchKey);
  3102. DWORD dwNextID = XTP_CALENDAR_UNKNOWN_EVENT_ID;
  3103. // lookup a map.
  3104. if (m_mapID.Lookup(eKey, dwNextID))
  3105. return dwNextID;
  3106. // ID not found - add new one if necessary
  3107. if (!bAddNew)
  3108. return XTP_CALENDAR_UNKNOWN_EVENT_ID;
  3109. dwNextID = GetNextUniqueEventID();
  3110. m_mapID.Add(dwNextID, eKey);
  3111. return dwNextID;
  3112. }
  3113. BOOL CXTPCalendarMAPIDataProvider::Equal(const CXTPMAPIBinary& eid1, const CXTPMAPIBinary& eid2)
  3114. {
  3115. BOOL bRes = FALSE;
  3116. // 1st check using simple byte-to-byte comparison
  3117. bRes = CXTPMAPIBinary::IsBinaryEqual(eid1, eid2);
  3118. if (bRes)
  3119. return bRes;
  3120. // 2nd check using CompareEntryIDs method.
  3121. // This is required because EntryID versions can change (i.e. A single
  3122. // provider can support more than one form of entry id) and it is up to
  3123. // a specific provider to decide if two EntryID's compare. The way of
  3124. // doing this is calling the CompareEntryIDs method on the on the
  3125. // appropriate object.
  3126. if (!m_lpMAPISession)
  3127. return bRes;
  3128. ULONG ulRes;
  3129. if (SUCCEEDED(m_lpMAPISession->CompareEntryIDs(
  3130. eid1.m_cb, (LPENTRYID)eid1.GetBinaryData(),
  3131. eid2.m_cb, (LPENTRYID)eid2.GetBinaryData(),
  3132. 0, &ulRes)))
  3133. {
  3134. bRes = (BOOL)ulRes;
  3135. }
  3136. return bRes;
  3137. }
  3138. BOOL CXTPCalendarMAPIDataProvider::OnTimeZoneChanged()
  3139. {
  3140. if (IsOpen())
  3141. {
  3142. // Re-Read all events to the cache data provider
  3143. if (m_pMemDP)
  3144. {
  3145. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  3146. m_bDisableNotificationsSending = TRUE;
  3147. m_pMemDP->RemoveAllEvents();
  3148. m_pMemDP->AddEvents(ImportAllEvents());
  3149. }
  3150. return TRUE;
  3151. }
  3152. return FALSE;
  3153. };
  3154. /////////////////////////////////////////////////////////////////////////////
  3155. //
  3156. // CXTPMAPIBinary
  3157. //
  3158. CXTPMAPIBinary::CXTPMAPIBinary()
  3159. {
  3160. m_cb = 0;
  3161. }
  3162. CXTPMAPIBinary::CXTPMAPIBinary(ULONG cbEntryID, LPENTRYID lpEntryID)
  3163. {
  3164. Set(cbEntryID, (LPBYTE)lpEntryID);
  3165. }
  3166. CXTPMAPIBinary::CXTPMAPIBinary(const CXTPMAPIBinary& eid)
  3167. {
  3168. m_cb = eid.m_cb;
  3169. m_arBytes.RemoveAll();
  3170. m_arBytes.Append(eid.m_arBytes);
  3171. }
  3172. CXTPMAPIBinary::~CXTPMAPIBinary()
  3173. {
  3174. }
  3175. CXTPMAPIBinary& CXTPMAPIBinary::operator=(const CXTPMAPIBinary& eid)
  3176. {
  3177. m_cb = eid.m_cb;
  3178. m_arBytes.SetSize(m_cb);
  3179. MEMCPY_S(m_arBytes.GetData(), eid.GetBinaryData(), m_cb);
  3180. return *this;
  3181. }
  3182. ULONG CXTPMAPIBinary::GetBinarySize() const
  3183. {
  3184. return m_cb;
  3185. }
  3186. LPBYTE CXTPMAPIBinary::GetBinaryData() const
  3187. {
  3188. return (BYTE*)m_arBytes.GetData();
  3189. }
  3190. void CXTPMAPIBinary::Set(ULONG cbSize, LPBYTE lpData)
  3191. {
  3192. m_cb = cbSize;
  3193. m_arBytes.SetSize(m_cb);
  3194. MEMCPY_S(m_arBytes.GetData(), lpData, m_cb);
  3195. }
  3196. void CXTPMAPIBinary::Set(LPSPropValue pPropEntryID)
  3197. {
  3198. if (!pPropEntryID || pPropEntryID->ulPropTag != PR_ENTRYID)
  3199. {
  3200. ASSERT(FALSE);
  3201. Set(0, NULL);
  3202. return;
  3203. }
  3204. Set(pPropEntryID->Value.bin.cb, pPropEntryID->Value.bin.lpb);
  3205. }
  3206. BOOL CXTPMAPIBinary::IsBinaryEqual(
  3207. const CXTPMAPIBinary& eid1, const CXTPMAPIBinary& eid2)
  3208. {
  3209. if ((eid1.m_cb != eid2.m_cb) ||
  3210.  (eid1.m_arBytes.GetSize() != eid2.m_arBytes.GetSize()) )
  3211. return FALSE;
  3212. return 0 == memcmp(
  3213. eid1.m_arBytes.GetData(),
  3214. eid2.m_arBytes.GetData(),
  3215. eid1.m_arBytes.GetSize() );
  3216. }
  3217. #ifdef _DEBUG
  3218. void CXTPMAPIBinary::DebugPrint()
  3219. {
  3220. TRACE(_T("Bin size:%dt"), m_cb);
  3221. for (int i = 0; i < m_arBytes.GetSize(); i++)
  3222. {
  3223. TRACE(_T("%d "), m_arBytes.GetAt(i));
  3224. }
  3225. TRACE(_T("n"));
  3226. }
  3227. #endif
  3228. /////////////////////////////////////////////////////////////////////////////
  3229. //
  3230. // CXTP_ID_Collection
  3231. //
  3232. CXTP_ID_Collection::CXTP_ID_Collection()
  3233. {
  3234. m_mapEventID.InitHashTable(XTP_OBJECT_CACHE_HASH_TABLE_SIZE, FALSE);
  3235. m_mapEntryID.InitHashTable(XTP_OBJECT_CACHE_HASH_TABLE_SIZE, FALSE);
  3236. }
  3237. BOOL CXTP_ID_Collection::Lookup(
  3238. const DWORD dwEventID, CXTPMAPIBinary& obEntryID)
  3239. {
  3240. return m_mapEventID.Lookup(dwEventID, obEntryID);
  3241. }
  3242. BOOL CXTP_ID_Collection::Lookup(
  3243. CXTPMAPIBinary& obEntryID, DWORD& dwEventID)
  3244. {
  3245. return m_mapEntryID.Lookup(obEntryID, dwEventID);
  3246. }
  3247. BOOL CXTP_ID_Collection::Add(
  3248. const DWORD dwEventID, CXTPMAPIBinary& obEntryID)
  3249. {
  3250. m_mapEventID.SetAt(dwEventID, obEntryID);
  3251. m_mapEntryID.SetAt(obEntryID, dwEventID);
  3252. return TRUE;
  3253. }
  3254. void CXTP_ID_Collection::FindMissing(CMap_EventIDs& mapExisting, CMap_EventIDs& mapMissed)
  3255. {
  3256. POSITION pos = m_mapEventID.GetStartPosition();
  3257. DWORD dwKey;
  3258. CXTPMAPIBinary eID;
  3259. BOOL bValue = FALSE;
  3260. while (pos != NULL)
  3261. {
  3262. m_mapEventID.GetNextAssoc(pos, dwKey, eID);
  3263. BOOL bFound = mapExisting.Lookup(dwKey, bValue);
  3264. if (!bFound)
  3265. {
  3266. mapMissed.SetAt(dwKey, TRUE);
  3267. }
  3268. }
  3269. }
  3270. /////////////////////////////////////////////////////////////////////////////
  3271. //
  3272. // CMAPIPropIDMap
  3273. //
  3274. CXTPCalendarMAPIDataProvider::CMAPIPropIDMap::CMAPIPropIDMap()
  3275. : m_pProvider(NULL)
  3276. {
  3277. m_mapPropID2Tag.InitHashTable(199, FALSE);
  3278. m_mapPropTag2ID.InitHashTable(199, FALSE);
  3279. }
  3280. void CXTPCalendarMAPIDataProvider::CMAPIPropIDMap::_UpdateMaps(LPMESSAGE pMessage)
  3281. {
  3282. ASSERT(pMessage);
  3283. if (!pMessage)
  3284. return;
  3285. ULONG ulPropNames = 0;
  3286. LPMAPINAMEID* ppArPropNames = NULL;
  3287. LPSPropTagArray pPropTags = NULL;
  3288. HRESULT hRes = pMessage->GetPropList(0, &pPropTags);
  3289. if (SUCCEEDED(hRes) && pPropTags)
  3290. {
  3291. hRes = pMessage->GetNamesFromIDs(&pPropTags, NULL, MAPI_NO_STRINGS,
  3292.  &ulPropNames, &ppArPropNames);
  3293. if (SUCCEEDED(hRes) && ppArPropNames && ulPropNames)
  3294. {
  3295. ASSERT(pPropTags->cValues == ulPropNames);
  3296. XTP_TRACE_READ_IDS(_T("Prop ID -> Tag (%d)n"), ulPropNames);
  3297. for (int i = 0; i < (int)ulPropNames; i++)
  3298. {
  3299. if (!ppArPropNames[i])
  3300. {
  3301. continue;
  3302. }
  3303. if (ppArPropNames[i]->ulKind == MNID_ID)
  3304. {
  3305. ULONG ulID = (ULONG)ppArPropNames[i]->Kind.lID;
  3306. ULONG ulTag = pPropTags->aulPropTag[i];
  3307. m_mapPropID2Tag[ulID] = ulTag;
  3308. m_mapPropTag2ID[ulTag] = ulID;
  3309. //if (ulID >= 0x8000)
  3310. {
  3311. XTP_TRACE_READ_IDS(_T("Prop ID -> Tag (%x -> %x)n"), ulID, ulTag);
  3312. }
  3313. }
  3314. }
  3315. }
  3316. }
  3317. MAPI_FREEBUFFER(m_pProvider, ppArPropNames);
  3318. MAPI_FREEBUFFER(m_pProvider, pPropTags);
  3319. }
  3320. ULONG CXTPCalendarMAPIDataProvider::CMAPIPropIDMap::_GetPropTagFromID_ex(LPMESSAGE pMessage,
  3321. const XTP_MAPI_PROP_NAME& propNameEx)
  3322. {
  3323. ASSERT(pMessage);
  3324. if (!pMessage || !m_pProvider)
  3325. return 0;
  3326. ULONG ulPropTag = 0;
  3327. LPMAPINAMEID pPropName = NULL;
  3328. LPSPropTagArray pPropTag = NULL;
  3329. HRESULT hRes = m_pProvider->MAPIAllocateBuffer(sizeof(MAPINAMEID), (void**)&pPropName);
  3330. if (SUCCEEDED(hRes) && pPropName)
  3331. {
  3332. ZeroMemory(pPropName, sizeof(MAPINAMEID));
  3333. pPropName->lpguid = (LPGUID)&propNameEx.m_GuidPS;
  3334. pPropName->ulKind = MNID_ID;
  3335. pPropName->Kind.lID = propNameEx.m_ulID;
  3336. hRes = pMessage->GetIDsFromNames(1, &pPropName, MAPI_CREATE, &pPropTag);
  3337. if (SUCCEEDED(hRes) && pPropTag && pPropTag->cValues)
  3338. {
  3339. ulPropTag = pPropTag->aulPropTag[0];
  3340. // validate prop type
  3341. ulPropTag = CHANGE_PROP_TYPE(ulPropTag, propNameEx.m_ulType);
  3342. }
  3343. }
  3344. MAPI_FREEBUFFER(m_pProvider, pPropName);
  3345. MAPI_FREEBUFFER(m_pProvider, pPropTag);
  3346. return ulPropTag;
  3347. }
  3348. ULONG CXTPCalendarMAPIDataProvider::CMAPIPropIDMap::GetPropTagByID(
  3349. LPMESSAGE pMessage, const XTP_MAPI_PROP_NAME& propNameEx)
  3350. {
  3351. ULONG ulTag = 0;
  3352. if (!m_mapPropID2Tag.Lookup(propNameEx.m_ulID, ulTag))
  3353. {
  3354. _UpdateMaps(pMessage);
  3355. if (!m_mapPropID2Tag.Lookup(propNameEx.m_ulID, ulTag))
  3356. {
  3357. ulTag = _GetPropTagFromID_ex(pMessage, propNameEx);
  3358. ASSERT(ulTag); // WARNING!
  3359. if (ulTag)
  3360. {
  3361. m_mapPropID2Tag[propNameEx.m_ulID] = ulTag;
  3362. m_mapPropTag2ID[ulTag] = propNameEx.m_ulID;
  3363. return ulTag;
  3364. }
  3365. }
  3366. }
  3367. return ulTag;
  3368. }
  3369. ULONG CXTPCalendarMAPIDataProvider::CMAPIPropIDMap::GetPropIDByTag(LPMESSAGE pMessage,
  3370.  ULONG ulPropTag)
  3371. {
  3372. ULONG ulID = 0;
  3373. if (!m_mapPropTag2ID.Lookup(ulPropTag, ulID))
  3374. {
  3375. _UpdateMaps(pMessage);
  3376. }
  3377. if (!m_mapPropTag2ID.Lookup(ulPropTag, ulID))
  3378. {
  3379. ulID = 0;
  3380. }
  3381. return ulID;
  3382. }