diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs index 8e16718..841c49b 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs @@ -97,6 +97,7 @@ namespace Acacia public const string ZPUSH_CAPABILITY_NOTES = "notes"; public const string ZPUSH_CAPABILITY_OUT_OF_OFFICE = "oof"; public const string ZPUSH_CAPABILITY_OUT_OF_OFFICE_TIMES = "ooftime"; + public const string ZPUSH_CAPABILITY_IMPERSONATE = "impersonate"; #endregion @@ -118,5 +119,6 @@ namespace Acacia public const string PLUGIN_REGISTRY_LOGLEVEL = "LogLevel"; #endregion + } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs index bcbfbed..f2e6495 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs @@ -65,6 +65,15 @@ namespace Acacia.Features.SharedFolders set { RegistryUtil.SetConfigValue("SharedFolders", "DefaultFolderNameFormat", value, Microsoft.Win32.RegistryValueKind.String); } } + [AcaciaOption("If enabled, the 'Impersonate' capability is added, allowing whole stores to be opened through " + + "user impersonation; if Z-Push supports it.")] + public bool AllowImpersonate + { + get { return GetOption(OPTION_ALLOW_IMPERSONATE); } + set { SetOption(OPTION_ALLOW_IMPERSONATE, value); } + } + private static readonly BoolOption OPTION_ALLOW_IMPERSONATE = new BoolOption("AllowImpersonate", false); + #endregion public override void Startup() @@ -84,6 +93,13 @@ namespace Acacia.Features.SharedFolders SetupHierarchyChangeSuppression(); } + override public void GetCapabilities(ZPushCapabilities caps) + { + base.GetCapabilities(caps); + if (AllowImpersonate) + caps.Add(Constants.ZPUSH_CAPABILITY_IMPERSONATE); + } + #region UI private bool CanManageFolder(MenuItem b, IFolder folder) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs index 1a48110..79a6ebf 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs @@ -290,6 +290,8 @@ namespace Acacia.Features.SharedFolders // Restart IRestarter restarter = ThisAddIn.Instance.Restarter(); restarter.CloseWindows = true; + foreach (StoreTreeNode node in state.stores) + restarter.OpenShare(_account, node.User); restarter.Restart(); } }, true) @@ -362,7 +364,7 @@ namespace Acacia.Features.SharedFolders if (select) { - FocusNode(node, false); + FocusNode(node, !_folders.SupportsWholeStore); } } @@ -392,6 +394,7 @@ namespace Acacia.Features.SharedFolders private void WholeStoreShareChanged(KTreeNode node) { + // TODO: check duplicate email address StoreTreeNode storeNode = (StoreTreeNode)node; _dirtyWholeStores[storeNode.User] = storeNode.IsWholeStoreDirty; CheckDirty(); diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs index 9936ac8..e69644d 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs @@ -43,7 +43,7 @@ namespace Acacia.Features.SharedFolders public bool SupportsWholeStore { - get { return true; } // TODO: use capability + get { return _feature.AllowImpersonate; } // TODO: use capability } public FeatureSharedFolders Feature { get { return _feature; } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs index d70571d..d725be5 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs @@ -65,7 +65,7 @@ namespace Acacia.Features.SharedFolders ChildLoader = new UserFolderLoader(this, folders, user); ChildLoader.ReloadOnCloseOpen = true; - HasCheckBox = folders.SupportsWholeStore; + HasCheckBox = !string.IsNullOrEmpty(user.EmailAddress) && folders.SupportsWholeStore; ApplyReadOnly(this, IsReadOnly); // TODO: better icons, better way of handling this diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs index 8361601..d49b3fe 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs @@ -27,6 +27,8 @@ namespace Acacia.Stubs { AccountType AccountType { get; } + string AccountId { get; } + IStore Store { get; } void SendReceive(); diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs index 061ee6b..960c338 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs @@ -35,6 +35,7 @@ namespace Acacia.Stubs IEnumerable Features { get; } IEnumerable> COMAddIns { get; } string Version { get; } + string VersionMajor { get; } ISyncObject GetSyncObject(); #region UI diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AccountWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AccountWrapper.cs index 87faf5e..af219a9 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AccountWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AccountWrapper.cs @@ -35,11 +35,13 @@ namespace Acacia.Stubs.OutlookWrappers [TypeConverter(typeof(ExpandableObjectConverter))] class AccountWrapper : ComWrapper, IAccount, LogContext { + private readonly string _accountId; private readonly string _regPath; private readonly IStore _store; internal AccountWrapper(NSOutlook.Application item, string regPath, IStore store) : base(item) { + this._accountId = System.IO.Path.GetFileName(regPath); this._regPath = regPath; this._store = store; @@ -81,10 +83,15 @@ namespace Acacia.Stubs.OutlookWrappers { get { - return (DeviceId == null) ? AccountType.Other : AccountType.EAS; + return (UserName == null) ? AccountType.Other : AccountType.EAS; } } + public string AccountId + { + get { return _accountId; } + } + [Browsable(false)] public IStore Store { diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs index aa8b534..34e9c41 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs @@ -304,7 +304,10 @@ namespace Acacia.Stubs.OutlookWrappers { get { return _app.Version; } } - + public string VersionMajor + { + get { return _app.Version.Split('.')[0]; } + } public FeatureType GetFeature() where FeatureType : Feature diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Restarter.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Restarter.cs index 3d61ea8..3ed828f 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Restarter.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/Restarter.cs @@ -72,29 +72,27 @@ namespace Acacia.Stubs.OutlookWrappers commandLine += " /cleankoe " + Util.QuoteCommandLine(path); } } - foreach(KeyValuePair share in _shares) + + if (_shares.Count > 0) { - using (RegistryKey key = OutlookRegistryUtils.OpenProfileOutlookKey(_addIn.ProfileName, RegistryKeyPermissionCheck.ReadWriteSubTree)) + foreach (KeyValuePair share in _shares) { - int accountId = (int)key.GetValue(OutlookConstants.REG_VAL_NEXT_ACCOUNT_ID); - using (RegistryKey accountKey = key.CreateSubKey(string.Format("{0:X8}", accountId))) - { - accountKey.SetValue(OutlookConstants.REG_VAL_ACCOUNTNAME, share.Value.UserName + " through " + share.Key.DisplayName); - accountKey.SetValue(OutlookConstants.REG_VAL_DISPLAYNAME, "Share for " + share.Value.DisplayName); - accountKey.SetValue(OutlookConstants.REG_VAL_EMAIL, "test" + share.Key.Account.SmtpAddress); - accountKey.SetValue(OutlookConstants.REG_VAL_EAS_SERVER, share.Key.Account.ServerURL); - accountKey.SetValue(OutlookConstants.REG_VAL_EAS_USERNAME, share.Key.Account.UserName + ".share." + share.Value.UserName); - accountKey.SetValue(OutlookConstants.REG_VAL_EAS_PASSWORD, share.Key.Account.EncryptedPassword); - //accountKey.SetValue(OutlookConstants.REG_VAL_EAS_DEVICEID, share.Key.Account.DeviceId); - accountKey.SetValue("clsid", "{ED475415-B0D6-11D2-8C3B-00104B2A6676}"); - } - key.SetValue(OutlookConstants.REG_VAL_NEXT_ACCOUNT_ID, accountId + 1); + // TODO: escaping + commandLine += " /sharekoe " + Util.QuoteCommandLine(_addIn.ProfileName + ":" + + _addIn.VersionMajor + ":" + + share.Key.Account.AccountId + ":" + + share.Value.UserName + ":" + share.Value.EmailAddress + ":" + + share.Value.EmailAddress); } } + string arch = Environment.Is64BitProcess ? "x64" : "x86"; // Run that Process process = new Process(); - process.StartInfo = new ProcessStartInfo(RestarterPath, Process.GetCurrentProcess().Id + " " + commandLine); + process.StartInfo = new ProcessStartInfo(RestarterPath, + Process.GetCurrentProcess().Id + " " + + arch + " " + + commandLine); process.Start(); // And close us and any other windows diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs index d8d260a..df9edf6 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs @@ -212,7 +212,7 @@ namespace Acacia.UI.Outlook string title = Properties.Resources.Ribbon_Title; // Convert to upper case for Outlook 2013, to match other ribbons - if (ThisAddIn.Instance.Version.StartsWith("15.")) + if (ThisAddIn.Instance.VersionMajor.Equals("15")) { title = title.ToUpper(); } diff --git a/src/AcaciaZPushPlugin/EASAccount/EASAccount.cpp b/src/AcaciaZPushPlugin/EASAccount/EASAccount.cpp index c42fd38..389a5e8 100644 --- a/src/AcaciaZPushPlugin/EASAccount/EASAccount.cpp +++ b/src/AcaciaZPushPlugin/EASAccount/EASAccount.cpp @@ -1,15 +1,26 @@ #include "EASAccount.h" +static const wstring R_ACCOUNT_NAME = L"Account Name"; +static const wstring R_DISPLAY_NAME = L"Display Name"; +static const wstring R_SERVER_URL = L"EAS Server URL"; +static const wstring R_USERNAME = L"EAS User"; +static const wstring R_EMAIL = L"Email"; +static const wstring R_EMAIL_ORIGINAL = L"KOE Share For"; +static const wstring R_PASSWORD = L"EAS Password"; + struct Account { public: wstring profileName; + wstring outlookVersion; wstring accountName; wstring displayName; wstring email; + wstring emailOriginal; wstring server; wstring username; wstring password; + vector encryptedPassword; wstring dataFolder; private: wstring path; @@ -55,7 +66,50 @@ public: void Create() { CheckInit(); - + DeterminePath(); + + // Set up the account + OpenProfileAdmin(); + EncryptPassword(); + CreateMessageService(); + GetEntryId(); + CreateAccount(); + CommitAccountKey(); + PatchMessageStore(); + } + + void LoadFromAccountId(const wstring &accountId) + { + OpenAccountKey(accountId); + + try + { + accountName = RegReadAccountKey(R_ACCOUNT_NAME); + displayName = RegReadAccountKey(R_DISPLAY_NAME); + email = RegReadAccountKey(R_EMAIL); + server = RegReadAccountKey(R_SERVER_URL); + username = RegReadAccountKey(R_USERNAME); + encryptedPassword = RegReadAccountKeyBinary(R_PASSWORD); + } + // Clean up + catch (...) + { + if (hKeyNewAccount) + { + RegCloseKey(hKeyNewAccount); + hKeyNewAccount = nullptr; + } + throw; + } + if (hKeyNewAccount) + { + RegCloseKey(hKeyNewAccount); + hKeyNewAccount = nullptr; + } + } +private: + void DeterminePath() + { // Determine the .ost path if (dataFolder.empty()) { @@ -65,25 +119,27 @@ public: } // Somehow it only works if there's a number in between parentheses path = dataFolder + email + L" - " + profileName + L"(1).ost"; - - // Set up the account - OpenProfileAdmin(); - CreateMessageService(); - GetEntryId(); - CreateAccount(); - CommitAccountKey(); - PatchMessageStore(); } -private: + + void EncryptPassword() + { + // TODO: handle the case password is not set in registry + if (encryptedPassword.empty()) + encryptedPassword = EncryptPassword(password, L"EAS Password"); + } + void CheckInit() { #define DoCheckInit(field) do{ if (field.empty()) throw exception("Field " #field " not initialised"); } while(0) DoCheckInit(profileName); + DoCheckInit(outlookVersion); DoCheckInit(accountName); DoCheckInit(displayName); DoCheckInit(email); DoCheckInit(server); DoCheckInit(username); + if (encryptedPassword.empty()) + DoCheckInit(password); #undef DoCheckInit } @@ -137,9 +193,8 @@ private: msprops[2].Value.lpszW = (LPWSTR)displayName.c_str(); msprops[3].ulPropTag = PR_PROFILE_SECURE_MAILBOX; - vector encPassword = EncryptPassword(password, L"S010267f0"); - msprops[3].Value.bin.cb = (ULONG)encPassword.size(); - msprops[3].Value.bin.lpb = &encPassword[0]; + msprops[3].Value.bin.cb = (ULONG)encryptedPassword.size(); + msprops[3].Value.bin.lpb = &encryptedPassword[0]; msprops[4].ulPropTag = PR_RESOURCE_FLAGS; msprops[4].Value.l = SERVICE_NO_PRIMARY_IDENTITY | SERVICE_CREATE_WITH_STORE; @@ -182,13 +237,31 @@ private: } } - void AllocateAccountKey() + void OpenAccountsKey() { + if (hKeyAccounts != nullptr) + return; + wchar_t keyPath[MAX_PATH]; // Open the accounts key - swprintf_s(keyPath, ARRAYSIZE(keyPath), KEY_ACCOUNTS, 16, profileName.c_str()); + swprintf_s(keyPath, ARRAYSIZE(keyPath), KEY_ACCOUNTS, outlookVersion.c_str(), profileName.c_str()); CHECK_L(RegOpenKey(HKEY_CURRENT_USER, keyPath, &hKeyAccounts), "OpenAccountsKey"); + } + + void OpenAccountKey(const wstring &accountId) + { + OpenAccountsKey(); + + // Open the subkey + CHECK_L(RegOpenKey(hKeyAccounts, accountId.c_str(), &hKeyNewAccount), "OpenAccountKey"); + } + + void AllocateAccountKey() + { + OpenAccountsKey(); + + wchar_t keyPath[MAX_PATH]; // Get the NextAccountID value DWORD size = sizeof(accountId); @@ -199,6 +272,23 @@ private: CHECK_L(RegCreateKey(hKeyAccounts, keyPath, &hKeyNewAccount), "CreateAccountKey"); } + wstring RegReadAccountKey(const wstring &name) + { + wchar_t buffer[4096]; + DWORD size = sizeof(buffer); + CHECK_L(RegQueryValueEx(hKeyNewAccount, name.c_str(), nullptr, nullptr, (LPBYTE)buffer, &size), "RegReadAccountKey"); + return buffer; + } + + vector RegReadAccountKeyBinary(const wstring &name) + { + vector buffer(4096); + DWORD size = (DWORD)buffer.size(); + CHECK_L(RegQueryValueEx(hKeyNewAccount, name.c_str(), nullptr, nullptr, (LPBYTE)&buffer[0], &size), "RegReadAccountKey"); + buffer.resize(size); + return buffer; + } + void WriteAccountKey(const wstring &name, const wstring &value) { CHECK_L(RegSetValueEx(hKeyNewAccount, name.c_str(), 0, REG_SZ, (LPBYTE)value.data(), (DWORD)value.size() * 2), "WriteAccountKey"); @@ -290,15 +380,18 @@ private: AllocateAccountKey(); // Write the values - WriteAccountKey(L"Account Name", accountName); - WriteAccountKey(L"Display Name", displayName); - WriteAccountKey(L"EAS Server URL", server); - WriteAccountKey(L"EAS User", username); - WriteAccountKey(L"Email", email); + WriteAccountKey(R_ACCOUNT_NAME, accountName); + WriteAccountKey(R_DISPLAY_NAME, displayName); + WriteAccountKey(R_SERVER_URL, server); + WriteAccountKey(R_USERNAME, username); + WriteAccountKey(R_EMAIL, email); + + if (!emailOriginal.empty()) + WriteAccountKey(R_EMAIL_ORIGINAL, emailOriginal); + WriteAccountKey(L"clsid", L"{ED475415-B0D6-11D2-8C3B-00104B2A6676}"); - vector encrypted = EncryptPassword(password, L"EAS Password"); - WriteAccountKey(L"EAS Password", &encrypted[0], encrypted.size()); + WriteAccountKey(R_PASSWORD, &encryptedPassword[0], encryptedPassword.size()); WriteAccountKey(L"Service UID", &service, sizeof(service)); @@ -400,6 +493,9 @@ private: // Delete existing store DeleteFile(path.c_str()); + if (entryId.size() == 0) + throw exception("entryId not initialised"); + // Open the msg store to finalise creation CHECK_H(session->OpenMsgStore(0, (ULONG)entryId.size(), (LPENTRYID)&entryId[0], nullptr, MDB_NO_DIALOG | MDB_WRITE | MAPI_DEFERRED_ERRORS, &msgStore), "OpenMsgStore"); @@ -430,15 +526,27 @@ private: }; -int __cdecl wmain(int, wchar_t **) +int __cdecl wmain(int argc, wchar_t **argv) { - // Parse the command line - // Usage: Account account; - // Main try { + if (argc != 7) + { + fwprintf(stderr, L"EASAccount: \n"); + exit(3); + } + + account.profileName = argv[1]; + account.outlookVersion = argv[2]; + account.LoadFromAccountId(argv[3]); + account.username = account.username + L"+share+" + argv[4]; + account.emailOriginal = account.email; + account.email = argv[5]; + account.accountName = account.email; + account.displayName = argv[6]; + // Create the account account.Create(); } diff --git a/src/AcaciaZPushPlugin/EASAccount/EASAccount.h b/src/AcaciaZPushPlugin/EASAccount/EASAccount.h index 7c0232e..8a8f139 100644 --- a/src/AcaciaZPushPlugin/EASAccount/EASAccount.h +++ b/src/AcaciaZPushPlugin/EASAccount/EASAccount.h @@ -38,7 +38,7 @@ using namespace std; -static const wchar_t *KEY_ACCOUNTS = L"SOFTWARE\\Microsoft\\Office\\%d.0\\Outlook\\Profiles\\%s\\9375CFF0413111d3B88A00104B2A6676"; +static const wchar_t *KEY_ACCOUNTS = L"SOFTWARE\\Microsoft\\Office\\%s.0\\Outlook\\Profiles\\%s\\9375CFF0413111d3B88A00104B2A6676"; static const wchar_t *KEY_OLKMAIL = L"{ED475418-B0D6-11D2-8C3B-00104B2A6676}"; static const wchar_t *KEY_OLKADDRESSBOOK = L"{ED475419-B0D6-11D2-8C3B-00104B2A6676}"; static const wchar_t *KEY_OLKSTORE = L"{ED475420-B0D6-11D2-8C3B-00104B2A6676}"; diff --git a/src/AcaciaZPushPlugin/EASAccount/EASAccount.vcxproj b/src/AcaciaZPushPlugin/EASAccount/EASAccount.vcxproj index 9c12160..4fcbd52 100644 --- a/src/AcaciaZPushPlugin/EASAccount/EASAccount.vcxproj +++ b/src/AcaciaZPushPlugin/EASAccount/EASAccount.vcxproj @@ -77,17 +77,25 @@ true $(SolutionDir)Build\$(Configuration)\ obj\$(Configuration)\ + $(ProjectName)-$(PlatformShortName) true + $(SolutionDir)Build\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)-$(PlatformShortName) false $(SolutionDir)Build\$(Configuration)\ obj\$(Configuration)\ + $(ProjectName)-$(PlatformShortName) false + $(SolutionDir)Build\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)-$(PlatformShortName) diff --git a/src/AcaciaZPushPlugin/OutlookRestarter/OutlookRestarter.cs b/src/AcaciaZPushPlugin/OutlookRestarter/OutlookRestarter.cs index b426472..31b1969 100644 --- a/src/AcaciaZPushPlugin/OutlookRestarter/OutlookRestarter.cs +++ b/src/AcaciaZPushPlugin/OutlookRestarter/OutlookRestarter.cs @@ -50,13 +50,15 @@ namespace OutlookRestarter try { - string procPath = args[1]; - List procArgs = args.Skip(2).ToList(); + int procId = int.Parse(args[0]); + string arch = args[1]; + string procPath = args[2]; + + List procArgs = args.Skip(3).ToList(); try { Logger.Instance.Debug(typeof(OutlookRestarter), "Waiting1"); // Attempt waiting for the process to finish - int procId = int.Parse(args[0]); Logger.Instance.Debug(typeof(OutlookRestarter), "Waiting2"); Process proc = Process.GetProcessById(procId); Logger.Instance.Debug(typeof(OutlookRestarter), "Waiting3"); @@ -76,6 +78,11 @@ namespace OutlookRestarter string path = procArgs[i]; HandleCleanKoe(path); } + else if (procArgs[i] == "/sharekoe") + { + ++i; + HandleShareKoe(arch, procArgs[i]); + } else if (procArgs[i].StartsWith("/")) { useArgs.Add(procArgs[i]); @@ -87,6 +94,7 @@ namespace OutlookRestarter } string argsString = string.Join(" ", useArgs); Logger.Instance.Debug(typeof(OutlookRestarter), "Parsed arguments: {0}", argsString); + // Start the process Process process = new Process(); process.StartInfo = new ProcessStartInfo(procPath, argsString); @@ -101,6 +109,40 @@ namespace OutlookRestarter } } + private static void HandleShareKoe(string arch, string rawArgs) + { + string baseDir = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + string path = Path.Combine(baseDir, "EASAccount-" + arch + ".exe"); + string[] args = rawArgs.Split(':'); + for (int i = 0; i < args.Length; ++i) + args[i] = "\"" + args[i] + "\""; + string argsString = string.Join(" ", args); + + Logger.Instance.Debug(typeof(OutlookRestarter), "Request to open account: {0}: {1}", path, argsString); + + Process process = new Process(); + process.StartInfo = new ProcessStartInfo(path, argsString); + process.StartInfo.CreateNoWindow = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.ErrorDataReceived += (s, e) => + { + if (!string.IsNullOrEmpty(e.Data.Trim())) + Logger.Instance.Warning(typeof(OutlookRestarter), "EASAccount: {0}", e.Data.Trim()); + }; + process.OutputDataReceived += (s, e) => + { + if (!string.IsNullOrEmpty(e.Data.Trim())) + Logger.Instance.Debug(typeof(OutlookRestarter), "EASAccount: {0}", e.Data.Trim()); + }; + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(FINISH_WAIT_TIME); + Logger.Instance.Debug(typeof(OutlookRestarter), "Opened accounts: {0}", argsString); + } + private static void HandleCleanKoe(string path) { Logger.Instance.Debug(typeof(OutlookRestarter), "Request to remove store: {0}", path);