diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj index d0a457b..1f38191 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj @@ -279,6 +279,7 @@ + @@ -292,12 +293,14 @@ + + @@ -323,7 +326,6 @@ - UserControl diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs index 475187f..9b40c43 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs @@ -251,7 +251,7 @@ namespace Acacia.Features.GAB if (_processing == 0) { // Check parent folder is a GAB contacts folder - if (_gabFolders.Contains(item.ParentEntryId) && IsGABItem(item)) + if (_gabFolders.Contains(item.ParentEntryID) && IsGABItem(item)) { DoSuppressEvent(findInspector ? item : null, ref cancel); } @@ -434,7 +434,7 @@ namespace Acacia.Features.GAB gab.AttrHidden = false; // Update admin - _gabFolders.Add(gab.EntryId); + _gabFolders.Add(gab.EntryID); GABInfo gabInfo = GABInfo.Get(gab, domainName); gabInfo.Store(gab); @@ -548,7 +548,7 @@ namespace Acacia.Features.GAB GABInfo info = GetGABContactsFolderInfo(subfolder); if (info != null && !_domains.Contains(info.Domain)) { - Logger.Instance.Info(this, "Unused GAB folder: {0} - {1}", subfolder.EntryId, subfolder.Name); + Logger.Instance.Info(this, "Unused GAB folder: {0} - {1}", subfolder.EntryID, subfolder.Name); try { deletedSomething = true; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs index e2c67d6..3240279 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs @@ -205,7 +205,7 @@ namespace Acacia.Features.GAB // TODO: make type-checking iterator? if (item is IZPushItem) { - string entryId = item.EntryId; + string entryId = item.EntryID; Logger.Instance.Trace(this, "Checking chunk: {0}", item.Subject); if (_feature.ProcessItems2) { @@ -613,7 +613,7 @@ namespace Acacia.Features.GAB { using (IItem item = FindItemById(memberId)) { - Logger.Instance.Debug(this, "Finding member {0} of {1}: {2}", memberId, id, item?.EntryId); + Logger.Instance.Debug(this, "Finding member {0} of {1}: {2}", memberId, id, item?.EntryID); if (item != null) AddGroupMember(group, item); } @@ -670,7 +670,7 @@ namespace Acacia.Features.GAB { using (IItem groupItem = FindItemById(memberOf)) { - Logger.Instance.Debug(this, "Finding group {0} for {1}: {2}", memberOf, id, groupItem?.EntryId); + Logger.Instance.Debug(this, "Finding group {0} for {1}: {2}", memberOf, id, groupItem?.EntryID); if (groupItem is IDistributionList) { AddGroupMember((IDistributionList)groupItem, item); diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Notes/FeatureNotes.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Notes/FeatureNotes.cs index d481693..db8e357 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Notes/FeatureNotes.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Notes/FeatureNotes.cs @@ -92,7 +92,7 @@ namespace Acacia.Features.Notes { // Only patch if on a ZPush server that supports notes. Store the folder as entryId, there have been some // issues with the folder object being disposed in the past - string folderId = folder.EntryId; + string folderId = folder.EntryID; ZPushAccount zpush = Watcher.Accounts.GetAccount(folder); if (zpush != null) { @@ -219,7 +219,7 @@ namespace Acacia.Features.Notes { if ((int)item.GetProperty(OutlookConstants.PR_ICON_INDEX) != 771) { - Logger.Instance.Trace(this, "Patching item: {0}", item.EntryId); + Logger.Instance.Trace(this, "Patching item: {0}", item.EntryID); // Patch standard properties item.SetProperties( diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs index f6d9c8c..d79feb4 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs @@ -106,9 +106,9 @@ namespace Acacia.Features.SecondaryContacts Logger.Instance.Debug(this, "Patched secondary contacts folder: {0}", strippedName); // Register and show a warning, if not already done. // Note that patching may be done multiple times. - if (!_warnedFolders.Contains(folder.EntryId)) + if (!_warnedFolders.Contains(folder.EntryID)) { - _warnedFolders.Add(folder.EntryId); + _warnedFolders.Add(folder.EntryID); if (MessageBox.Show(StringUtil.GetResourceString("SecondaryContactsPatched_Body", strippedName), StringUtil.GetResourceString("SecondaryContactsPatched_Title"), @@ -121,7 +121,7 @@ namespace Acacia.Features.SecondaryContacts } } // If _warnedFolders does not contain the folder (and it's hidden), this means Outlook was restarted. - else if (!_warnedFolders.Contains(folder.EntryId)) + else if (!_warnedFolders.Contains(folder.EntryID)) { // Stage 2 diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Enums.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Enums.cs new file mode 100644 index 0000000..cc086ac --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Enums.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Acacia.Stubs +{ + // Replacement for olItemType + public enum ItemType + { + MailItem = 0, + AppointmentItem = 1, + ContactItem = 2, + TaskItem = 3, + JournalItem = 4, + NoteItem = 5, + PostItem = 6, + DistributionListItem = 7, + MobileItemSMS = 11, + MobileItemMMS = 12 + } + + // Replacement for olDefaultFolders + public enum DefaultFolder + { + DeletedItems = 3, + Outbox = 4, + SentMail = 5, + Inbox = 6, + Calendar = 9, + Contacts = 10, + Journal = 11, + Notes = 12, + Tasks = 13, + Drafts = 16, + FoldersAllPublicFolders = 18, + Conflicts = 19, + SyncIssues = 20, + LocalFailures = 21, + ServerFailures = 22, + Junk = 23, + RssFeeds = 25, + ToDo = 28, + ManagedEmail = 29, + SuggestedContacts = 30 + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IBase.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IBase.cs index 3e3cb77..bbf30ad 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IBase.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IBase.cs @@ -36,11 +36,16 @@ namespace Acacia.Stubs #region Ids and hierarchy - string EntryId { get; } + string EntryID { get; } IFolder Parent { get; } - string ParentEntryId { get; } + string ParentEntryID { get; } + /// + /// Returns the store. The owner is responsible for disposing. + /// TODO: make method to make disposing clear + /// IStore Store { get; } + /// /// Quick accessor to Store.Id, to prevent allocating a wrapper for it. /// diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IFolder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IFolder.cs index 13aca83..7164be6 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IFolder.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IFolder.cs @@ -41,6 +41,10 @@ namespace Acacia.Stubs IItem GetItemById(string id); + string FullFolderPath { get; } + + ItemType DefaultItemType { get; } + #endregion #region Searching diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStore.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStore.cs index f14e12d..5d4c04e 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStore.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStore.cs @@ -29,6 +29,17 @@ namespace Acacia.Stubs /// /// The root folder. The caller is responsible for disposing. IFolder GetRootFolder(); + + /// + /// Returns a default folder. + /// + /// The default folder. The caller is responsible for disposing. + IFolder GetDefaultFolder(DefaultFolder folder); + /// + /// Returns GetDefaultFolder.EntryID, for simplified memory manaement + /// + string GetDefaultFolderId(DefaultFolder folder); + IItem GetItemFromID(string id); string DisplayName { get; } string StoreID { get; } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ItemType.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ItemType.cs deleted file mode 100644 index 2c7857a..0000000 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ItemType.cs +++ /dev/null @@ -1,38 +0,0 @@ -/// Copyright 2016 Kopano b.v. -/// -/// This program is free software: you can redistribute it and/or modify -/// it under the terms of the GNU Affero General Public License, version 3, -/// as published by the Free Software Foundation. -/// -/// This program is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the -/// GNU Affero General Public License for more details. -/// -/// You should have received a copy of the GNU Affero General Public License -/// along with this program.If not, see. -/// -/// Consult LICENSE file for details - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Acacia.Stubs -{ - public enum ItemType - { - MailItem = 0, - AppointmentItem = 1, - ContactItem = 2, - TaskItem = 3, - JournalItem = 4, - NoteItem = 5, - PostItem = 6, - DistributionListItem = 7, - MobileItemSMS = 11, - MobileItemMMS = 12 - } -} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs index 2e75aed..6efb688 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs @@ -228,7 +228,7 @@ namespace Acacia.Stubs.OutlookWrappers // And fetch it and wrap NSOutlook.Stores stores = com.Add(session.Stores); - return StoreWrapper.Wrap(stores[stores.Count]); + return Mapping.Wrap(stores[stores.Count]); } } @@ -242,7 +242,7 @@ namespace Acacia.Stubs.OutlookWrappers NSOutlook.Stores stores = com.Add(session.Stores); foreach (NSOutlook.Store store in stores) { - yield return StoreWrapper.Wrap(store); + yield return Mapping.Wrap(store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AppointmentItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AppointmentItemWrapper.cs index 9071f7d..df654ee 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AppointmentItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AppointmentItemWrapper.cs @@ -93,7 +93,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -104,7 +104,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -123,7 +123,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs index f578ccc..9aac7ef 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ComWrapper.cs @@ -25,50 +25,7 @@ using System.Threading.Tasks; namespace Acacia.Stubs.OutlookWrappers { - abstract class RawComWrapper : IComWrapper - { - protected RawComWrapper() - { - Interlocked.Increment(ref Statistics.CreatedWrappers); - this._createdTrace = new System.Diagnostics.StackTrace(); - MustRelease = true; - } - - ~RawComWrapper() - { - Interlocked.Increment(ref Statistics.DeletedWrappers); - if (!_isDisposed) - { - Logger.Instance.Warning(this, "Undisposed wrapper: {0}", _createdTrace); - // Dispose, but don't count auto disposals, so the stats show it. - DoRelease(); - } - } - - private bool _isDisposed; - private readonly System.Diagnostics.StackTrace _createdTrace; - - virtual public void Dispose() - { - if (!_isDisposed) - { - Logger.Instance.TraceExtra(this, "Disposing wrapper: {0}", new System.Diagnostics.StackTrace()); - _isDisposed = true; - Interlocked.Increment(ref Statistics.DisposedWrappers); - DoRelease(); - } - } - - public bool MustRelease - { - get; - set; - } - - abstract protected void DoRelease(); - } - - abstract class ComWrapper : RawComWrapper + abstract class ComWrapper : DisposableWrapper, IComWrapper { protected ItemType _item { get; private set; } @@ -78,6 +35,13 @@ namespace Acacia.Stubs.OutlookWrappers protected ComWrapper(ItemType item) { this._item = item; + MustRelease = true; + } + + public bool MustRelease + { + get; + set; } override protected void DoRelease() diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ContactItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ContactItemWrapper.cs index a8617a2..223d4b7 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ContactItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ContactItemWrapper.cs @@ -218,7 +218,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -229,7 +229,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -248,7 +248,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/DistributionListWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/DistributionListWrapper.cs index 76753eb..4e30707 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/DistributionListWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/DistributionListWrapper.cs @@ -160,7 +160,7 @@ namespace Acacia.Stubs.OutlookWrappers { List id = new List(); id.AddRange(PREFIX_MEMBER_ID); - id.AddRange(StringUtil.HexToBytes(member.EntryId)); + id.AddRange(StringUtil.HexToBytes(member.EntryID)); return id.ToArray(); } @@ -234,7 +234,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -245,7 +245,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -264,7 +264,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/FolderWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/FolderWrapper.cs index 782e570..a2b217e 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/FolderWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/FolderWrapper.cs @@ -39,6 +39,8 @@ namespace Acacia.Stubs.OutlookWrappers return _item.PropertyAccessor; } + public string FullFolderPath { get { return _item.FullFolderPath; } } + public IFolder Parent { get @@ -48,7 +50,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -96,9 +98,10 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } + + public IStore Store { get { return Mapping.Wrap(_item.Store); } } - public IStore Store { get { return StoreWrapper.Wrap(_item.Store); } } public string StoreId { get @@ -460,5 +463,9 @@ namespace Acacia.Stubs.OutlookWrappers #endregion + public ItemType DefaultItemType + { + get { return (ItemType)(int)_item.DefaultItemType; } + } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/MailItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/MailItemWrapper.cs index b9753c1..9c4aa7a 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/MailItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/MailItemWrapper.cs @@ -127,7 +127,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -138,7 +138,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -157,7 +157,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Mapping.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Mapping.cs index 2dabe2b..c8d0ebd 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Mapping.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Mapping.cs @@ -80,11 +80,23 @@ namespace Acacia.Stubs.OutlookWrappers public static IRecipient Wrap(NSOutlook.Recipient r, bool mustRelease = true) { + if (r == null) + return null; RecipientWrapper wrapped = new RecipientWrapper(r); wrapped.MustRelease = mustRelease; return wrapped; } + // TODO: extension methods for this + public static IStore Wrap(NSOutlook.Store obj, bool mustRelease = true) + { + if (obj == null) + return null; + StoreWrapper wrapped = new StoreWrapper(obj); + wrapped.MustRelease = mustRelease; + return wrapped; + } + // TODO: are these not the same now? Differ only on wrong type? public static Type WrapOrDefault(object o, bool mustRelease = true) where Type : IBase diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/NoteItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/NoteItemWrapper.cs index 79e38e1..3ffee99 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/NoteItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/NoteItemWrapper.cs @@ -74,7 +74,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -85,7 +85,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -104,7 +104,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StorageItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StorageItemWrapper.cs index 5f15f21..dae5e8f 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StorageItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StorageItemWrapper.cs @@ -72,7 +72,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -83,7 +83,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -102,7 +102,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoreWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoreWrapper.cs index 2425db0..10d46f8 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoreWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoreWrapper.cs @@ -26,12 +26,7 @@ namespace Acacia.Stubs.OutlookWrappers { class StoreWrapper : ComWrapper, IStore { - internal static IStore Wrap(NSOutlook.Store store) - { - return store == null ? null : new StoreWrapper(store); - } - - private StoreWrapper(NSOutlook.Store store) : base(store) + internal StoreWrapper(NSOutlook.Store store) : base(store) { } @@ -41,6 +36,25 @@ namespace Acacia.Stubs.OutlookWrappers return new FolderWrapper((NSOutlook.Folder)_item.GetRootFolder()); } + public IFolder GetDefaultFolder(DefaultFolder folder) + { + // FolderWrapper manages the returned Folder + return new FolderWrapper((NSOutlook.Folder)_item.GetDefaultFolder((NSOutlook.OlDefaultFolders)(int)folder)); + } + + public string GetDefaultFolderId(DefaultFolder folder) + { + NSOutlook.MAPIFolder mapiFolder = _item.GetDefaultFolder((NSOutlook.OlDefaultFolders)(int)folder); + try + { + return mapiFolder.EntryID; + } + finally + { + ComRelease.Release(mapiFolder); + } + } + public IItem GetItemFromID(string id) { using (ComRelease com = new ComRelease()) @@ -79,6 +93,5 @@ namespace Acacia.Stubs.OutlookWrappers } } } - } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/TaskItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/TaskItemWrapper.cs index 9f6e7ac..be58bbe 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/TaskItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/TaskItemWrapper.cs @@ -72,7 +72,7 @@ namespace Acacia.Stubs.OutlookWrappers #region IBase implementation - public string EntryId { get { return _item.EntryID; } } + public string EntryID { get { return _item.EntryID; } } public IFolder Parent { @@ -83,7 +83,7 @@ namespace Acacia.Stubs.OutlookWrappers } } - public string ParentEntryId + public string ParentEntryID { get { @@ -102,7 +102,7 @@ namespace Acacia.Stubs.OutlookWrappers using (ComRelease com = new ComRelease()) { NSOutlook.Folder parent = com.Add(_item.Parent); - return StoreWrapper.Wrap(parent?.Store); + return Mapping.Wrap(parent?.Store); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs new file mode 100644 index 0000000..4ee284c --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NSOutlook = Microsoft.Office.Interop.Outlook; + +namespace Acacia.Stubs +{ + public static class Wrappers + { + public static IFolder Wrap(this NSOutlook.MAPIFolder obj) + { + throw new NotImplementedException(); // TODO + } + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs new file mode 100644 index 0000000..e68bad4 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DisposableWrapper.cs @@ -0,0 +1,47 @@ +using Acacia.Features.DebugSupport; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Acacia.Utils +{ + abstract public class DisposableWrapper : IDisposable + { + protected DisposableWrapper() + { + Interlocked.Increment(ref Statistics.CreatedWrappers); + this._createdTrace = new System.Diagnostics.StackTrace(); + } + + ~DisposableWrapper() + { + Interlocked.Increment(ref Statistics.DeletedWrappers); + if (!_isDisposed) + { + Logger.Instance.Warning(this, "Undisposed wrapper: {0}", _createdTrace); + // Dispose, but don't count auto disposals, so the stats show it. + DoRelease(); + } + } + + private bool _isDisposed; + private readonly System.Diagnostics.StackTrace _createdTrace; + + virtual public void Dispose() + { + if (!_isDisposed) + { + Logger.Instance.TraceExtra(this, "Disposing wrapper: {0}", new System.Diagnostics.StackTrace()); + _isDisposed = true; + Interlocked.Increment(ref Statistics.DisposedWrappers); + DoRelease(); + } + } + + abstract protected void DoRelease(); + } + +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs index d1efbec..4ea9fc8 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs @@ -252,7 +252,7 @@ namespace Acacia.ZPush.Connect } } - private class Request : RawComWrapper + private class Request : DisposableWrapper { private const string ACTIVESYNC_URL = "https://{0}/Microsoft-Server-ActiveSync?DeviceId={1}&Cmd={2}&User={3}&DeviceType={4}"; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs index 6f4d531..e6d8a93 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs @@ -15,6 +15,7 @@ /// Consult LICENSE file for details using Acacia.Stubs; +using Acacia.Stubs.OutlookWrappers; using Acacia.Utils; using Acacia.ZPush.Connect; using Microsoft.Win32; @@ -32,21 +33,20 @@ using NSOutlook = Microsoft.Office.Interop.Outlook; namespace Acacia.ZPush { [TypeConverter(typeof(ExpandableObjectConverter))] - public class ZPushAccount : LogContext + public class ZPushAccount : DisposableWrapper, LogContext { #region Miscellaneous private readonly string _regPath; - // TODO: this should probably be wrapped. Make ZPushAccount ComWrapper? - private readonly NSOutlook.Store _store; + private readonly IStore _store; /// /// Constructor. /// /// They registry key containing the account settings. - /// The store this account represents. - internal ZPushAccount(string regPath, NSOutlook.Store store) + /// The store this account represents. The new object takes ownership + internal ZPushAccount(string regPath, IStore store) { this._regPath = regPath; this._store = store; @@ -55,6 +55,11 @@ namespace Acacia.ZPush SmtpAddress = RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EMAIL, null); } + protected override void DoRelease() + { + _store.Dispose(); + } + [Browsable(false)] public string LogContextId { @@ -83,8 +88,7 @@ namespace Acacia.ZPush #region Properties [Browsable(false)] - // TODO: remove this - public NSOutlook.Store Store + public IStore Store { get { @@ -229,7 +233,7 @@ namespace Acacia.ZPush public void LinkedGABFolder(IFolder folder) { - GABFolderLinked = folder.EntryId; + GABFolderLinked = folder.EntryID; } internal void OnConfirmationResponse(ZPushConnection.Response response) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs index 60a6d7d..8797bfe 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs @@ -15,6 +15,7 @@ /// Consult LICENSE file for details using Acacia.Stubs; +using Acacia.Stubs.OutlookWrappers; using Acacia.Utils; using Microsoft.Win32; using System; @@ -238,36 +239,41 @@ namespace Acacia.ZPush /// private void StoreAdded(NSOutlook.Store s) { + IStore store = null; try { - using (ComRelease com = new ComRelease()) + // Accessing the store object causes random crashes, simply iterate to find new stores + Logger.Instance.Trace(this, "StoreAdded: {0}", s.StoreID); + foreach (NSOutlook.Store rawStore in _session.Stores.RawEnum(false)) { - Logger.Instance.Trace(this, "StoreAdded: {0}", s.StoreID); - foreach (NSOutlook.Store store in com.Add(com.Add(_app.Session).Stores)) + if (!_accountsByStoreId.ContainsKey(rawStore.StoreID)) { - if (!_accountsByStoreId.ContainsKey(store.StoreID)) + Logger.Instance.Trace(this, "New store: {0}", rawStore.DisplayName); + + store = Mapping.Wrap(rawStore); + ZPushAccount zpush = TryCreateFromRegistry(store); + if (zpush == null) { - Logger.Instance.Trace(this, "New store: {0}", store.DisplayName); - ZPushAccount zpush = TryCreateFromRegistry(store); - if (zpush == null) - { - // Add it to the cache so it is not evaluated again. - _accountsByStoreId.Add(store.StoreID, null); - Logger.Instance.Trace(this, "Not a ZPush store: {0}", store.DisplayName); - } - else - { - Logger.Instance.Trace(this, "New ZPush store: {0}: {1}", store.DisplayName, zpush); - _watcher.OnAccountDiscovered(zpush, false); - } + // Add it to the cache so it is not evaluated again. + _accountsByStoreId.Add(store.StoreID, null); + Logger.Instance.Trace(this, "Not a ZPush store: {0}", store.DisplayName); + store.Dispose(); + } + else + { + Logger.Instance.Trace(this, "New ZPush store: {0}: {1}", store.DisplayName, zpush); + _watcher.OnAccountDiscovered(zpush, false); + // zpush has taken ownership } - else ComRelease.Release(store); } + else ComRelease.Release(rawStore); } } catch(System.Exception e) { Logger.Instance.Error(this, "StoreAdded Exception: {0}", e); + if (store != null) + store.Dispose(); } } @@ -287,6 +293,7 @@ namespace Acacia.ZPush /// The account. The caller is responsible for releasing this. /// The associated ZPushAccount /// If the registry key cannot be found + // TODO: check management of account private ZPushAccount CreateFromRegistry(NSOutlook.Account account) { // TODO: check that caller releases account everywhere @@ -300,10 +307,10 @@ namespace Acacia.ZPush string storeId = ZPushAccount.GetStoreId(baseKey.Name); // Find the store - NSOutlook.Store store = _app.Session.GetStoreFromID(storeId); + NSOutlook.Store store = _session.GetStoreFromID(storeId); // Done, create and register - ZPushAccount zpush = new ZPushAccount(baseKey.Name, store); + ZPushAccount zpush = new ZPushAccount(baseKey.Name, Mapping.Wrap(store)); Register(zpush); return zpush; } @@ -312,9 +319,9 @@ namespace Acacia.ZPush /// /// Creates the ZPushAccount for the store, from the registry. /// - /// The store + /// The store. Ownership is transferred to the ZPushAccount. If the account is not created, the store is NOT disposed /// The ZPushAccount, or null if no account is associated with the store - private ZPushAccount TryCreateFromRegistry(NSOutlook.Store store) + private ZPushAccount TryCreateFromRegistry(IStore store) { using (RegistryKey baseKey = FindRegistryKey(store)) { @@ -363,7 +370,7 @@ namespace Acacia.ZPush /// Finds the registry key for the account associated with the store. /// /// The registry key, or null if it cannot be found - private RegistryKey FindRegistryKey(NSOutlook.Store store) + private RegistryKey FindRegistryKey(IStore store) { // Find the registry key by store id using (RegistryKey key = OpenBaseKey()) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs index 1f3d42f..c8ec64e 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs @@ -22,15 +22,12 @@ using System.Linq; using Acacia.Utils; using System.Text; using System.Threading.Tasks; -using NSOutlook = Microsoft.Office.Interop.Outlook; namespace Acacia.ZPush { - // TODO: make this contain Folder instead of inheriting, then FolderWrapper needn't be public - public class ZPushFolder : FolderWrapper + public class ZPushFolder : DisposableWrapper { - private readonly NSOutlook.Items _items; - private readonly NSOutlook.Folders _subFolders; + private IFolder _folder; private ZPushFolder _parent; private readonly ZPushWatcher _watcher; private List _itemsWatchers = new List(); @@ -40,24 +37,29 @@ namespace Acacia.ZPush /// protected readonly Dictionary _children = new Dictionary(); - internal ZPushFolder(ZPushWatcher watcher, NSOutlook.Folder folder) + internal ZPushFolder(ZPushWatcher watcher, IFolder folder) : this(watcher, null, folder) { Initialise(); } - private ZPushFolder(ZPushWatcher watcher, ZPushFolder parent, NSOutlook.Folder folder) - : - base(folder) + private ZPushFolder(ZPushWatcher watcher, ZPushFolder parent, IFolder folder) { Logger.Instance.Trace(this, "Watching folder: {1}: {0}", folder.EntryID, folder.Name); this._parent = parent; this._watcher = watcher; - this._items = folder.Items; - this._subFolders = folder.Folders; + this._folder = folder; } + protected override void DoRelease() + { + _folder.Dispose(); + } + + public IFolder Folder { get; } + public string Name { get { return _folder.Name; } } + private void Initialise() { // Register the events @@ -67,20 +69,21 @@ namespace Acacia.ZPush _watcher.OnFolderDiscovered(this); // Recurse the children - foreach (NSOutlook.Folder subfolder in this._subFolders) + foreach (IFolder subfolder in _folder.GetSubFolders()) { Tasks.Task(null, "WatchChild", () => WatchChild(subfolder)); } } - public override void Dispose() + // TODO + /*public override void Dispose() { Logger.Instance.Trace(this, "Disposing folder: {0}", _item.Name); Cleanup(); base.Dispose(); ComRelease.Release(_items); ComRelease.Release(_subFolders); - } + }*/ internal ItemsWatcher ItemsWatcher() { @@ -92,7 +95,7 @@ namespace Acacia.ZPush public void ReportExistingItems(TypedItemEventHandler handler) where TypedItem : IItem { - foreach(IItem item in Items) + foreach(IItem item in _folder.Items) { if (item is TypedItem) handler((TypedItem)item); @@ -101,6 +104,8 @@ namespace Acacia.ZPush private void HookEvents(bool register) { + // TODO + /* if (register) { // Item events @@ -122,12 +127,12 @@ namespace Acacia.ZPush _subFolders.FolderAdd -= SubFolders_FolderAdd; _subFolders.FolderRemove -= SubFolders_FolderRemove; _subFolders.FolderChange -= SubFolders_FolderChange; - } + }*/ } private void Cleanup() { - Logger.Instance.Trace(this, "Unwatching folder: {0}", _item.Name); + Logger.Instance.Trace(this, "Unwatching folder: {0}", _folder.Name); // The events need to be unhooked explicitly, otherwise we get double notifications if a folder is moved HookEvents(false); foreach (ZPushFolder child in _children.Values) @@ -141,7 +146,7 @@ namespace Acacia.ZPush /// Watches the child folder. /// /// The child folder. Ownership will be taken. - private void WatchChild(NSOutlook.Folder child) + private void WatchChild(IFolder child) { if (!_children.ContainsKey(child.EntryID)) { @@ -165,124 +170,5 @@ namespace Acacia.ZPush // Release the folder if not used ComRelease.Release(child); } - - #region Event handlers - - private void SubFolders_FolderAdd(NSOutlook.MAPIFolder folder) - { - try - { - Logger.Instance.Debug(this, "Folder added in {0}: {1}", this._item.Name, folder.Name); - WatchChild((NSOutlook.Folder)folder); - } - catch (System.Exception e) { Logger.Instance.Error(this, "Exception in SubFolders_FolderAdd: {0}: {1}", Name, e); } - } - - private void SubFolders_FolderRemove() - { - try - { - Logger.Instance.Debug(this, "Folder removed from {0}", this._item.Name); - - // Helpfully, Outlook doesn't tell us which folder was removed. Could use the BeforeFolderMove event instead, - // but that doesn't fire if a folder was removed on the server. - // Hence, fetch all the remaining folder ids, and remove any folder that no longer exists. - HashSet remaining = new HashSet(); - foreach (NSOutlook.Folder child in _subFolders) - { - try - { - remaining.Add(child.EntryID); - } - catch (System.Exception e) { Logger.Instance.Warning(this, "Ignoring failed child: {0}", e); } - } - - // Find the folders that need to be removed. There should be only one, but with Outlook we can never be sure, - // so compare all. We cannot modify the dictionary during iteration, so store entries to be removed in a - // temporary list - List> remove = new List>(); - foreach (var entry in _children) - { - if (!remaining.Contains(entry.Key)) - { - remove.Add(entry); - } - } - - // Actually remove the folders - foreach (var entry in remove) - { - Logger.Instance.Debug(this, "Removing subfolder {0}, {1}", this._item.Name, entry.Key); - _children.Remove(entry.Key); - entry.Value.Cleanup(); - } - } - catch (System.Exception e) { Logger.Instance.Error(this, "Exception in SubFolders_FolderRemove: {0}: {1}", Name, e); } - } - - private void SubFolders_FolderChange(NSOutlook.MAPIFolder folder) - { - try - { - Logger.Instance.Debug(this, "Folder changed in {0}: {1}", this._item.Name, folder.Name); - ZPushFolder child; - if (_children.TryGetValue(folder.EntryID, out child)) - { - _watcher.OnFolderChanged(child); - // TODO: release folder? - } - else - { - // On a clean profile, we sometimes get a change notification, but not an add notification - // Create it now - // This will send a discover notification if required, which is just as good as a change notification - Logger.Instance.Debug(this, "Folder change on unreported folder in {0}: {1}, {2}, {3}", this._item.Name, folder.Name, folder.EntryID, folder.Store.DisplayName); - WatchChild((NSOutlook.Folder)folder); - } - } - catch (System.Exception e) { Logger.Instance.Error(this, "Exception in SubFolders_FolderChange: {0}: {1}", Name, e); } - } - - private void Items_ItemAdd(object oItem) - { - try - { - using (IItem item = Mapping.Wrap(oItem)) - { - if (item != null) - { - Logger.Instance.Trace(this, "New item {0}: {1}", Name, item.EntryId); - foreach (ItemsWatcher watcher in _itemsWatchers) - watcher.OnItemAdd(this, item); - } - } - } - catch(System.Exception e) - { - Logger.Instance.Trace(this, "ItemAdd exception: {0}: {1}", Name, e); - } - } - - private void Items_ItemChange(object oItem) - { - try - { - using (IItem item = Mapping.Wrap(oItem)) - { - if (item != null) - { - Logger.Instance.Trace(this, "Changed item {0}", Name); - foreach (ItemsWatcher watcher in _itemsWatchers) - watcher.OnItemChange(this, item); - } - } - } - catch (System.Exception e) - { - Logger.Instance.Trace(this, "ItemChange exception: {0}: {1}", Name, e); - } - } - - #endregion } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs index c4c6588..f486810 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs @@ -37,6 +37,7 @@ namespace Acacia.ZPush /// public class ZPushWatcher { + // TODO: remove private readonly NSOutlook.Application _app; public readonly ZPushAccounts Accounts; public readonly ZPushSync Sync; @@ -277,7 +278,7 @@ namespace Acacia.ZPush private void HandleFolderWatchers(ZPushAccount account) { // We need to keep the object alive to keep receiving events - _rootFolder = new ZPushFolder(this, (NSOutlook.Folder)account.Store.GetRootFolder()); + _rootFolder = new ZPushFolder(this, account.Store.GetRootFolder()); } public void WatchFolder(FolderRegistration folder, FolderEventHandler handler, FolderEventHandler changedHandler = null) @@ -299,7 +300,7 @@ namespace Acacia.ZPush // Check existing folders for events foreach(ZPushFolder existing in _allFolders) { - if (folder.IsApplicable(existing)) + if (folder.IsApplicable(existing.Folder)) { DispatchFolderEvent(folder, watcher, existing, true); } @@ -326,7 +327,7 @@ namespace Acacia.ZPush // See if anybody is interested foreach (KeyValuePair entry in _folderWatchers) { - if (entry.Key.IsApplicable(folder)) + if (entry.Key.IsApplicable(folder.Folder)) { DispatchFolderEvent(entry.Key, entry.Value, folder, isNew); } @@ -337,17 +338,17 @@ namespace Acacia.ZPush { Logger.Instance.Debug(this, "Folder event: {0}, {1}, {2}", folder, reg, isNew); if (isNew) - watcher.OnDiscovered(folder); + watcher.OnDiscovered(folder.Folder); else - watcher.OnChanged(folder); + watcher.OnChanged(folder.Folder); } - internal bool ShouldFolderBeWatched(ZPushFolder parent, NSOutlook.Folder child) + internal bool ShouldFolderBeWatched(ZPushFolder parent, IFolder child) { - if (parent.IsAtDepth(0)) + if (parent.Folder.IsAtDepth(0)) { // Special mail folders cause issues, they are disallowed - if (child.DefaultItemType != NSOutlook.OlItemType.olMailItem) + if (child.DefaultItemType != ItemType.MailItem) return true; return !IsBlackListedMailFolder(child); @@ -355,30 +356,27 @@ namespace Acacia.ZPush return true; } - private static readonly NSOutlook.OlDefaultFolders[] BLACKLISTED_MAIL_FOLDERS = + private static readonly DefaultFolder[] BLACKLISTED_MAIL_FOLDERS = { - NSOutlook.OlDefaultFolders.olFolderOutbox, - NSOutlook.OlDefaultFolders.olFolderDrafts, - NSOutlook.OlDefaultFolders.olFolderConflicts, - NSOutlook.OlDefaultFolders.olFolderSyncIssues, - NSOutlook.OlDefaultFolders.olFolderRssFeeds, - NSOutlook.OlDefaultFolders.olFolderManagedEmail + DefaultFolder.Outbox, + DefaultFolder.Drafts, + DefaultFolder.Conflicts, + DefaultFolder.SyncIssues, + DefaultFolder.RssFeeds, + DefaultFolder.ManagedEmail }; - private static bool IsBlackListedMailFolder(NSOutlook.Folder folder) + private static bool IsBlackListedMailFolder(IFolder folder) { + string entryId = folder.EntryID; - using (ComRelease com = new ComRelease()) - { - NSOutlook.Store store = com.Add(folder.Store); - foreach(NSOutlook.OlDefaultFolders defaultFolder in BLACKLISTED_MAIL_FOLDERS) + + using (IStore store = folder.Store) + { + foreach(DefaultFolder defaultFolderId in BLACKLISTED_MAIL_FOLDERS) { - try - { - if (entryId == com.Add(store.GetDefaultFolder(defaultFolder)).EntryID) - return true; - } - catch (System.Exception) { } + if (entryId == store.GetDefaultFolderId(defaultFolderId)) + return true; } } return false;