public OutlookContactRepository(IOutlookSession session, string folderId, string folderStoreId, IDaslFilterProvider daslFilterProvider, IQueryOutlookContactItemFolderStrategy queryFolderStrategy, IComWrapperFactory comWrapperFactory, bool useDefaultFolderItemType)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (daslFilterProvider == null)
            {
                throw new ArgumentNullException(nameof(daslFilterProvider));
            }
            if (queryFolderStrategy == null)
            {
                throw new ArgumentNullException(nameof(queryFolderStrategy));
            }
            if (comWrapperFactory == null)
            {
                throw new ArgumentNullException(nameof(comWrapperFactory));
            }

            _session                  = session;
            _folderId                 = folderId;
            _folderStoreId            = folderStoreId;
            _daslFilterProvider       = daslFilterProvider;
            _queryFolderStrategy      = queryFolderStrategy;
            _comWrapperFactory        = comWrapperFactory;
            _useDefaultFolderItemType = useDefaultFolderItemType;
        }
        public ContactAndDistListSynchronizer(
            IPartialSynchronizer <string, DateTime, WebResourceName, string, ICardDavRepositoryLogger> contactSynchronizer,
            ISynchronizer <DistributionListSychronizationContext> distributionListSynchronizer,
            EmailAddressCacheDataAccess emailAddressCacheDataAccess,
            IEntityRepository <WebResourceName, string, vCard, ICardDavRepositoryLogger> loggingCardDavRepositoryDecorator,
            IOutlookSession outlookSession)
        {
            if (contactSynchronizer == null)
            {
                throw new ArgumentNullException(nameof(contactSynchronizer));
            }
            if (distributionListSynchronizer == null)
            {
                throw new ArgumentNullException(nameof(distributionListSynchronizer));
            }
            if (loggingCardDavRepositoryDecorator == null)
            {
                throw new ArgumentNullException(nameof(loggingCardDavRepositoryDecorator));
            }
            if (outlookSession == null)
            {
                throw new ArgumentNullException(nameof(outlookSession));
            }

            _contactSynchronizer               = contactSynchronizer;
            _distributionListSynchronizer      = distributionListSynchronizer;
            _emailAddressCacheDataAccess       = emailAddressCacheDataAccess;
            _loggingCardDavRepositoryDecorator = loggingCardDavRepositoryDecorator;
            _outlookSession = outlookSession;
        }
        public EventSynchronizationContextFactory(OutlookEventRepository outlookRepository, IEntityRepository <WebResourceName, string, IICalendar, IEventSynchronizationContext> btypeRepository, IEntityRelationDataAccess <AppointmentId, DateTime, WebResourceName, string> entityRelationDataAccess, bool cleanupDuplicateEvents, IEqualityComparer <AppointmentId> idComparer, IOutlookSession outlookSession, IColorCategoryMapperFactory colorCategoryMapperFactory)
        {
            if (outlookRepository == null)
            {
                throw new ArgumentNullException(nameof(outlookRepository));
            }
            if (btypeRepository == null)
            {
                throw new ArgumentNullException(nameof(btypeRepository));
            }
            if (entityRelationDataAccess == null)
            {
                throw new ArgumentNullException(nameof(entityRelationDataAccess));
            }
            if (idComparer == null)
            {
                throw new ArgumentNullException(nameof(idComparer));
            }
            if (outlookSession == null)
            {
                throw new ArgumentNullException(nameof(outlookSession));
            }

            _outlookRepository        = outlookRepository;
            _btypeRepository          = btypeRepository;
            _entityRelationDataAccess = entityRelationDataAccess;
            _cleanupDuplicateEvents   = cleanupDuplicateEvents;
            _idComparer                 = idComparer;
            _outlookSession             = outlookSession;
            _colorCategoryMapperFactory = colorCategoryMapperFactory;
        }
 public ColorCategoryMapperFactory(IOutlookSession outlookSession, IColorMappingsDataAccess colorMappingsDataAccess)
 {
     if (outlookSession == null)
     {
         throw new ArgumentNullException(nameof(outlookSession));
     }
     if (colorMappingsDataAccess == null)
     {
         throw new ArgumentNullException(nameof(colorMappingsDataAccess));
     }
     _outlookSession          = outlookSession;
     _colorMappingsDataAccess = colorMappingsDataAccess;
 }
コード例 #5
0
        public ColorCategoryMapper(IOutlookSession outlookSession, IColorMappingsDataAccess colorMappingsDataAccess)
        {
            _colorMappingsDataAccess = colorMappingsDataAccess;
            _outlookSession          = outlookSession ?? throw new ArgumentNullException(nameof(outlookSession));

            var mappingEntries = colorMappingsDataAccess.Load();

            _categoryByHtmlColor = mappingEntries.ToDictionary(e => e.HtmlColor, StringComparer.OrdinalIgnoreCase);

            _outlookColorByCategory = outlookSession.GetCategories()
                                      .Where(c => c.Color != OlCategoryColor.olCategoryColorNone)
                                      .ToDictionary(c => c.Name, c => c.Color, StringComparer.InvariantCultureIgnoreCase);
        }
コード例 #6
0
        public ProfileExportProcessor(IOutlookSession session, IOptionTasks optionTasks)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (optionTasks == null)
            {
                throw new ArgumentNullException(nameof(optionTasks));
            }

            _session     = session;
            _optionTasks = optionTasks;
        }
コード例 #7
0
        public OutlookEventRepository(
            IOutlookSession session,
            string folderId,
            string folderStoreId,
            IDateTimeRangeProvider dateTimeRangeProvider,
            EventMappingConfiguration configuration,
            IDaslFilterProvider daslFilterProvider,
            IQueryOutlookAppointmentItemFolderStrategy queryFolderStrategy,
            IComWrapperFactory comWrapperFactory)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (dateTimeRangeProvider == null)
            {
                throw new ArgumentNullException(nameof(dateTimeRangeProvider));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }
            if (daslFilterProvider == null)
            {
                throw new ArgumentNullException(nameof(daslFilterProvider));
            }
            if (queryFolderStrategy == null)
            {
                throw new ArgumentNullException(nameof(queryFolderStrategy));
            }
            if (comWrapperFactory == null)
            {
                throw new ArgumentNullException(nameof(comWrapperFactory));
            }

            _session               = session;
            _folderId              = folderId;
            _folderStoreId         = folderStoreId;
            _dateTimeRangeProvider = dateTimeRangeProvider;
            _configuration         = configuration;
            _daslFilterProvider    = daslFilterProvider;
            _queryFolderStrategy   = queryFolderStrategy;
            _comWrapperFactory     = comWrapperFactory;
        }
コード例 #8
0
        public OptionTasks(NameSpace session, IEnumDisplayNameProvider enumDisplayNameProvider, IOutlookSession outlookSession)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (enumDisplayNameProvider == null)
            {
                throw new ArgumentNullException(nameof(enumDisplayNameProvider));
            }
            if (outlookSession == null)
            {
                throw new ArgumentNullException(nameof(outlookSession));
            }

            _session = session;
            _enumDisplayNameProvider = enumDisplayNameProvider;
            _outlookSession          = outlookSession;
        }
コード例 #9
0
        public CategorySwitcher(IOutlookSession session, DaslFilterProvider daslFilterProvider, OutlookFolderStrategyWrapper queryFolderStrategyWrapper)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (daslFilterProvider == null)
            {
                throw new ArgumentNullException(nameof(daslFilterProvider));
            }
            if (queryFolderStrategyWrapper == null)
            {
                throw new ArgumentNullException(nameof(queryFolderStrategyWrapper));
            }

            _session                    = session;
            _daslFilterProvider         = daslFilterProvider;
            _queryFolderStrategyWrapper = queryFolderStrategyWrapper;
        }
コード例 #10
0
        public DistributionListSychronizationContext(CacheItem[] emailAddressCacheItems, IOutlookSession outlookSession)
        {
            if (emailAddressCacheItems == null)
            {
                throw new ArgumentNullException(nameof(emailAddressCacheItems));
            }
            if (outlookSession == null)
            {
                throw new ArgumentNullException(nameof(outlookSession));
            }

            OutlookSession = outlookSession;
            foreach (var cacheItem in emailAddressCacheItems)
            {
                foreach (var emailAddress in cacheItem.EmailAddresses)
                {
                    var serverFileName = cacheItem.Id.GetServerFileName();
                    _serverFileNamesByEmailAddress[emailAddress] = serverFileName;
                }
            }
        }
コード例 #11
0
        public OutlookTaskRepository(IOutlookSession session, string folderId, string folderStoreId, IDaslFilterProvider daslFilterProvider, TaskMappingConfiguration configuration, IQueryOutlookTaskItemFolderStrategy queryFolderStrategy, IComWrapperFactory comWrapperFactory, bool useDefaultFolderItemType)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (daslFilterProvider == null)
            {
                throw new ArgumentNullException(nameof(daslFilterProvider));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }
            if (queryFolderStrategy == null)
            {
                throw new ArgumentNullException(nameof(queryFolderStrategy));
            }
            if (comWrapperFactory == null)
            {
                throw new ArgumentNullException(nameof(comWrapperFactory));
            }
            if (String.IsNullOrEmpty(folderId))
            {
                throw new ArgumentException("Argument is null or empty", nameof(folderId));
            }
            if (String.IsNullOrEmpty(folderStoreId))
            {
                throw new ArgumentException("Argument is null or empty", nameof(folderStoreId));
            }

            _session                  = session;
            _folderId                 = folderId;
            _folderStoreId            = folderStoreId;
            _daslFilterProvider       = daslFilterProvider;
            _configuration            = configuration;
            _queryFolderStrategy      = queryFolderStrategy;
            _comWrapperFactory        = comWrapperFactory;
            _useDefaultFolderItemType = useDefaultFolderItemType;
        }
        List <EntityVersion <string, DateTime> > IQueryOutlookTaskItemFolderStrategy.QueryTaskFolder(IOutlookSession session, Folder folder, string filter)
        {
            var tasks = new List <EntityVersion <string, DateTime> > ();

            using (var tableWrapper = GenericComObjectWrapper.Create(
                       folder.GetTable(filter)))
            {
                var table = tableWrapper.Inner;
                table.Columns.RemoveAll();
                table.Columns.Add(c_entryIdColumnName);

                var storeId = folder.StoreID;

                while (!table.EndOfTable)
                {
                    var row     = table.GetNextRow();
                    var entryId = (string)row[c_entryIdColumnName];
                    try
                    {
                        using (var taskWrapper = GenericComObjectWrapper.Create(session.GetTaskItem(entryId, storeId)))
                        {
                            tasks.Add(new EntityVersion <string, DateTime> (taskWrapper.Inner.EntryID, taskWrapper.Inner.LastModificationTime));
                        }
                    }
                    catch (COMException ex)
                    {
                        s_logger.Error("Could not fetch TaskItem, skipping.", ex);
                    }
                }
            }
            return(tasks);
        }
        List <AppointmentSlim> IQueryOutlookAppointmentItemFolderStrategy.QueryAppointmentFolder(IOutlookSession session, Folder calendarFolder, string filter)
        {
            var events = new List <AppointmentSlim>();

            using (var tableWrapper = GenericComObjectWrapper.Create(
                       calendarFolder.GetTable(filter)))
            {
                var table = tableWrapper.Inner;
                table.Columns.RemoveAll();
                table.Columns.Add(c_entryIdColumnName);

                var storeId = calendarFolder.StoreID;

                while (!table.EndOfTable)
                {
                    var row     = table.GetNextRow();
                    var entryId = (string)row[c_entryIdColumnName];
                    try
                    {
                        using (var appointmentWrapper = GenericComObjectWrapper.Create(session.GetAppointmentItem(entryId, storeId)))
                        {
                            events.Add(AppointmentSlim.FromAppointmentItem(appointmentWrapper.Inner));
                        }
                    }
                    catch (COMException ex)
                    {
                        s_logger.Error("Could not fetch AppointmentItem, skipping.", ex);
                    }
                }
            }
            return(events);
        }
コード例 #14
0
 public List <EntityVersion <string, DateTime> > QueryDistListFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter)
 {
     return(_strategy.QueryDistListFolder(session, folder, expectedFolderId, filter));
 }
コード例 #15
0
 public List <EntityVersion <string, DateTime> > QueryTaskFolder(IOutlookSession session, Folder folder, string filter)
 {
     return(_strategy.QueryTaskFolder(session, folder, filter));
 }
コード例 #16
0
 public OneTimeTaskRunner(IOutlookSession session)
 {
     _session = session ?? throw new ArgumentNullException(nameof(session));
 }
コード例 #17
0
 public List <AppointmentSlim> QueryAppointmentFolder(IOutlookSession session, Folder folder, string filter)
 {
     return(_strategy.QueryAppointmentFolder(session, folder, filter));
 }
 List <EntityVersion <string, DateTime> > IQueryOutlookContactItemFolderStrategy.QueryContactItemFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter)
 {
     return(QueryFolder(folder, filter));
 }
コード例 #19
0
 public TestOptionsFactory(IOutlookSession session, IOptionsDataAccess optionsDataAccess)
 {
     _optionsDataAccess = optionsDataAccess ?? throw new ArgumentNullException(nameof(optionsDataAccess));
     _session           = session ?? throw new ArgumentNullException(nameof(session));
 }
コード例 #20
0
 public List <EntityVersion <string, DateTime> > QueryTaskFolder(IOutlookSession session, Folder folder, string filter, IGetVersionsLogger logger)
 {
     throw new NotImplementedException();
 }
コード例 #21
0
 public List <AppointmentSlim> QueryAppointmentFolder(IOutlookSession session, Folder calendarFolder, string filter, IGetVersionsLogger logger)
 {
     throw new NotImplementedException();
 }
コード例 #22
0
 public List <EntityVersion <string, DateTime> > QueryDistListFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter)
 {
     throw new NotImplementedException();
 }
 List <EntityVersion <string, DateTime> > IQueryOutlookTaskItemFolderStrategy.QueryTaskFolder(IOutlookSession session, Folder folder, string filter, IGetVersionsLogger logger)
 {
     return(QueryFolder(folder, filter, logger));
 }
 List <EntityVersion <string, DateTime> > IQueryOutlookDistListItemFolderStrategy.QueryDistListFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter, IGetVersionsLogger logger)
 {
     return(QueryFolder(folder, filter, logger));
 }
        List <EntityVersion <string, DateTime> > IQueryOutlookContactItemFolderStrategy.QueryContactItemFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter)
        {
            var contacts = new List <EntityVersion <string, DateTime> > ();

            using (var tableWrapper = GenericComObjectWrapper.Create(folder.GetTable(filter)))
            {
                var table = tableWrapper.Inner;
                table.Columns.RemoveAll();
                table.Columns.Add(c_entryIdColumnName);

                var storeId = folder.StoreID;

                while (!table.EndOfTable)
                {
                    var row     = table.GetNextRow();
                    var entryId = (string)row[c_entryIdColumnName];

                    var contact = session.GetContactItemOrNull(entryId, expectedFolderId, storeId);
                    if (contact != null)
                    {
                        using (var contactWrapper = GenericComObjectWrapper.Create(contact))
                        {
                            contacts.Add(new EntityVersion <string, DateTime> (contactWrapper.Inner.EntryID, contactWrapper.Inner.LastModificationTime));
                        }
                    }
                }
            }

            return(contacts);
        }
        List <AppointmentSlim> IQueryOutlookAppointmentItemFolderStrategy.QueryAppointmentFolder(IOutlookSession session, Folder calendarFolder, string filter)
        {
            var events = new List <AppointmentSlim>();

            using (var tableWrapper = GenericComObjectWrapper.Create(
                       calendarFolder.GetTable(filter)))
            {
                var table = tableWrapper.Inner;
                table.Columns.RemoveAll();
                table.Columns.Add(PR_GLOBAL_OBJECT_ID);
                table.Columns.Add(PR_LONG_TERM_ENTRYID_FROM_TABLE);
                table.Columns.Add(LastModificationTimeColumnId);
                table.Columns.Add(SubjectColumnId);
                table.Columns.Add(StartColumnId);
                table.Columns.Add(EndColumnId);

                while (!table.EndOfTable)
                {
                    var    row                 = table.GetNextRow();
                    var    entryId             = row.BinaryToString(PR_LONG_TERM_ENTRYID_FROM_TABLE);
                    string globalAppointmentId = null;
                    try
                    {
                        byte[] globalIdArray = row[PR_GLOBAL_OBJECT_ID] as byte[];
                        if (globalIdArray != null && globalIdArray.Length > 0)
                        {
                            globalAppointmentId = row.BinaryToString(PR_GLOBAL_OBJECT_ID);
                        }
                    }
                    catch (Exception ex)
                    {
                        s_logger.Warn("Could not access GlobalAppointmentID of appointment", ex);
                    }

                    var lastModificationTime = (DateTime)row[LastModificationTimeColumnId];
                    var subject = (string)row[SubjectColumnId];
                    var start   = (DateTime)row[StartColumnId];
                    var end     = (DateTime)row[EndColumnId];

                    events.Add(new AppointmentSlim(EntityVersion.Create(new AppointmentId(entryId, globalAppointmentId), lastModificationTime), start, end, subject));
                }
            }
            return(events);
        }
コード例 #27
0
 public TestOptionsFactory(IOutlookSession session)
 {
     _session = session ?? throw new ArgumentNullException(nameof(session));
 }
 public List <EntityVersion <string, DateTime> > QueryContactItemFolder(IOutlookSession session, Folder folder, string expectedFolderId, string filter, IGetVersionsLogger logger)
 {
     return(_strategy.QueryContactItemFolder(session, folder, expectedFolderId, filter, logger));
 }
コード例 #29
0
        public ComponentContainer(Application application, IGeneralOptionsDataAccess generalOptionsDataAccess, IComWrapperFactory comWrapperFactory, IExceptionHandlingStrategy exceptionHandlingStrategy)
        {
            if (application == null)
            {
                throw new ArgumentNullException(nameof(application));
            }
            if (generalOptionsDataAccess == null)
            {
                throw new ArgumentNullException(nameof(generalOptionsDataAccess));
            }
            if (comWrapperFactory == null)
            {
                throw new ArgumentNullException(nameof(comWrapperFactory));
            }

            s_logger.Info("Startup...");
            s_logger.Info($"Version: {Assembly.GetExecutingAssembly().GetName().Version}");
            s_logger.Info($"Operating system: {Environment.OSVersion}");

            _profileTypeRegistry = ProfileTypeRegistry.Instance;

            if (GeneralOptionsDataAccess.WpfRenderModeSoftwareOnly)
            {
                RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
            }

            _generalOptionsDataAccess = generalOptionsDataAccess;

            _synchronizationStatus = new SynchronizationStatus();

            var generalOptions = _generalOptionsDataAccess.LoadOptions();

            _daslFilterProvider = new DaslFilterProvider(generalOptions.IncludeCustomMessageClasses);

            SetWpfLocale(generalOptions.CultureName);

            ConfigureServicePointManager(generalOptions);
            ConfigureLogLevel(generalOptions.EnableDebugLog);

            _session = application.Session;

            _outlookAccountPasswordProvider =
                string.IsNullOrEmpty(_session.CurrentProfileName)
              ? NullOutlookAccountPasswordProvider.Instance
              : new OutlookAccountPasswordProvider(_session.CurrentProfileName, application.Version);

            _globalTimeZoneCache = new GlobalTimeZoneCache();


            var applicationDataDirectoryBase = Path.Combine(
                Environment.GetFolderPath(
                    generalOptions.StoreAppDataInRoamingFolder ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.LocalApplicationData),
                "CalDavSynchronizer");

            string optionsFilePath;

            (_applicationDataDirectory, optionsFilePath) = GetOrCreateDataDirectory(applicationDataDirectoryBase, _session.CurrentProfileName);

            _optionsDataAccess = new OptionsDataAccess(optionsFilePath);

            _uiService = new UiService();
            var options = _optionsDataAccess.Load();

            _permanentStatusesViewModel = new PermanentStatusesViewModel(_uiService, this, options);
            _permanentStatusesViewModel.OptionsRequesting += PermanentStatusesViewModel_OptionsRequesting;

            _queryFolderStrategyWrapper = new OutlookFolderStrategyWrapper(QueryOutlookFolderByRequestingItemStrategy.Instance);

            _totalProgressFactory = new TotalProgressFactory(
                _uiService,
                generalOptions.ShowProgressBar,
                generalOptions.ThresholdForProgressDisplay,
                ExceptionHandler.Instance);


            _outlookSession      = new OutlookSession(_session);
            _synchronizerFactory = new SynchronizerFactory(
                GetProfileDataDirectory,
                _totalProgressFactory,
                _outlookSession,
                _daslFilterProvider,
                _outlookAccountPasswordProvider,
                _globalTimeZoneCache,
                _queryFolderStrategyWrapper,
                exceptionHandlingStrategy,
                comWrapperFactory,
                _optionsDataAccess,
                _profileTypeRegistry);

            _synchronizationReportRepository = CreateSynchronizationReportRepository();

            UpdateGeneralOptionDependencies(generalOptions);

            _scheduler = new Scheduler(
                _synchronizerFactory,
                this,
                EnsureSynchronizationContext,
                new FolderChangeWatcherFactory(
                    _session),
                _synchronizationStatus);

            EnsureCacheCompatibility(options);

            _availableVersionService          = new AvailableVersionService();
            _updateChecker                    = new UpdateChecker(_availableVersionService, () => _generalOptionsDataAccess.IgnoreUpdatesTilVersion);
            _updateChecker.NewerVersionFound += UpdateChecker_NewerVersionFound;
            _updateChecker.IsEnabled          = generalOptions.ShouldCheckForNewerVersions;

            _reportGarbageCollection = new ReportGarbageCollection(_synchronizationReportRepository, TimeSpan.FromDays(generalOptions.MaxReportAgeInDays));

            _trayNotifier = generalOptions.EnableTrayIcon ? new TrayNotifier(this) : NullTrayNotifer.Instance;

            try
            {
                using (var syncObjects = GenericComObjectWrapper.Create(_session.SyncObjects))
                {
                    if (syncObjects.Inner != null && syncObjects.Inner.Count > 0)
                    {
                        _syncObject = syncObjects.Inner[1];
                        if (generalOptions.TriggerSyncAfterSendReceive)
                        {
                            _syncObject.SyncEnd += SyncObject_SyncEnd;
                        }
                    }
                }
            }
            catch (COMException ex)
            {
                s_logger.Error("Can't access SyncObjects", ex);
            }

            _oneTimeTaskRunner = new OneTimeTaskRunner(_outlookSession);

            DDayICalWorkaround.DDayICalCustomization.InitializeNoThrow();
        }
        List <AppointmentSlim> IQueryOutlookAppointmentItemFolderStrategy.QueryAppointmentFolder(IOutlookSession session, Folder calendarFolder, string filter, IGetVersionsLogger logger)
        {
            var events = new List <AppointmentSlim>();

            using (var tableWrapper = GenericComObjectWrapper.Create(
                       calendarFolder.GetTable(filter)))
            {
                var table = tableWrapper.Inner;
                table.Columns.RemoveAll();
                table.Columns.Add(PR_GLOBAL_OBJECT_ID);
                table.Columns.Add(PR_LONG_TERM_ENTRYID_FROM_TABLE);
                table.Columns.Add(PR_ENTRYID);
                table.Columns.Add(LastModificationTimeColumnId);
                table.Columns.Add(SubjectColumnId);
                table.Columns.Add(StartColumnId);
                table.Columns.Add(EndColumnId);

                while (!table.EndOfTable)
                {
                    var row = table.GetNextRow();

                    string entryId;
                    byte[] entryIdArray = row[PR_LONG_TERM_ENTRYID_FROM_TABLE] as byte[];
                    if (entryIdArray != null && entryIdArray.Length > 0)
                    {
                        entryId = row.BinaryToString(PR_LONG_TERM_ENTRYID_FROM_TABLE);
                    }
                    else
                    {
                        // Fall back to short-term ENTRYID if long-term ID not available
                        entryId = row.BinaryToString(PR_ENTRYID);
                        s_logger.Warn($"Could not access long-term ENTRYID of appointment '{entryId}', use short-term ENTRYID as fallback.");
                    }

                    string globalAppointmentId = null;
                    try
                    {
                        byte[] globalIdArray = row[PR_GLOBAL_OBJECT_ID] as byte[];
                        if (globalIdArray != null && globalIdArray.Length > 0)
                        {
                            globalAppointmentId = row.BinaryToString(PR_GLOBAL_OBJECT_ID);
                        }
                    }
                    catch (Exception ex)
                    {
                        s_logger.Warn($"Could not access GlobalAppointmentID of appointment '{entryId}'.", ex);
                    }

                    var subject       = (string)row[SubjectColumnId];
                    var appointmentId = new AppointmentId(entryId, globalAppointmentId);

                    var      lastModificationTimeObject = row[LastModificationTimeColumnId];
                    DateTime lastModificationTime;
                    if (lastModificationTimeObject != null)
                    {
                        lastModificationTime = ((DateTime)lastModificationTimeObject).ToUniversalTime();
                    }
                    else
                    {
                        s_logger.Warn($"Column '{nameof(LastModificationTimeColumnId)}' of event '{entryId}' is NULL.");
                        logger.LogWarning(entryId, $"Column '{nameof(LastModificationTimeColumnId)}' is NULL.");
                        lastModificationTime = OutlookUtility.OUTLOOK_DATE_NONE;
                    }

                    var      startObject = row[StartColumnId];
                    DateTime?start;
                    if (startObject != null)
                    {
                        start = (DateTime)startObject;
                    }
                    else
                    {
                        s_logger.Warn($"Column '{nameof(StartColumnId)}' of event '{entryId}' is NULL.");
                        logger.LogWarning(entryId, $"Column '{nameof(StartColumnId)}' is NULL.");
                        start = null;
                    }

                    var      endObject = row[EndColumnId];
                    DateTime?end;
                    if (endObject != null)
                    {
                        end = (DateTime)endObject;
                    }
                    else
                    {
                        s_logger.Warn($"Column '{nameof(EndColumnId)}' of event '{entryId}' is NULL.");
                        logger.LogWarning(entryId, $"Column '{nameof(EndColumnId)}' is NULL.");
                        end = null;
                    }

                    events.Add(new AppointmentSlim(EntityVersion.Create(appointmentId, lastModificationTime.ToUniversalTime()), start, end, subject));
                }
            }

            return(events);
        }