List <EntityVersion <string, DateTime> > QueryFolder(Folder folder, string filter, IGetVersionsLogger logger)
        {
            var versions = new List <EntityVersion <string, DateTime> > ();

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

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

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

                    versions.Add(new EntityVersion <string, DateTime> (entryId, lastModificationTime));
                }
            }

            return(versions);
        }
        List <EntityVersion <string, DateTime> > QueryFolder(Folder folder, string filter, IGetVersionsLogger logger)
        {
            var versions = new List <EntityVersion <string, DateTime> >();

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

                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 entity '{entryId}', use short-term ENTRYID as fallback.");
                    }

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

                    versions.Add(new EntityVersion <string, DateTime>(entryId, lastModificationTime.ToUniversalTime()));
                }
            }

            return(versions);
        }
        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);
        }