public string GetFilePath(string fileExt) { SMCollection collection = Core.SM.Collection; return(GetFilePathForSlotId( collection, SlotIdOrOffset, fileExt )); /* * switch (LinkType) * { * case RegistryLinkType.File: * case RegistryLinkType.FileAndRtx: * SMCollection collection = SMA.Instance.Collection; * * return GetFilePathForSlotId( * collection, * SlotIdOrOffset, * fileExt * ); * * default: * return null; * }*/ }
public CollectionConfigurationService(SMCollection collection, ISMAPlugin plugin) { _collection = collection; _subDir = plugin.AssemblyName; EnsureFolderExists(); }
private async Task LoadConfig(SMCollection collection) { Core.CollectionConfiguration = new CollectionConfigurationService(collection, "Core"); // CollectionsCfg CollectionConfig = await Core.CollectionConfiguration.Load <CollectionCfg>() ?? new CollectionCfg(); }
private async Task LoadConfigAsync(SMCollection collection) { Core.CollectionConfiguration = new CollectionConfigurationService(collection, "Core"); // CollectionsCfg CollectionConfig = await Core.CollectionConfiguration.LoadAsync <CollectionCfg>().ConfigureAwait(false) ?? new CollectionCfg(); }
public CollectionConfigurationService(SMCollection collection, string subDir) { _collection = collection; _subDir = subDir; EnsureFolderExists(); }
public static string GetFilePathForSlotId( SMCollection collection, int slotId, string slotFileExt) { if (slotId <= 10) { return(collection.GetElementFilePath($"{slotId}.{slotFileExt}")); } List <int> folders = new List <int>(); int nBranch = (int)Math.Floor((slotId - 1) / 10.0); do { folders.Add((nBranch - 1) % 30 + 1); nBranch = (int)Math.Floor((nBranch - 1) / 30.0); } while (nBranch > 0); folders.Reverse(); var folderPath = string.Join("\\", folders); return(collection.GetElementFilePath( Path.Combine( folderPath, $"{slotId}.{slotFileExt}" ) )); }
public static string GetInfoFilePath( this SMCollection collection, string fileName) { return(collection.GetFilePath(SMConst.Paths.InfoFolder, fileName)); }
public static string GetRtfFilePath( this SMCollection collection, IRegistryFileDescriptor fileDesc) { return(collection.GetFilePath(SMConst.Paths.RegistryFolder, fileDesc.RtfFileName)); }
// // Core hook methods public IProcess CreateAndHook( SMCollection collection, ISMHookSystem systemCallback, IEnumerable <ISMHookIO> ioCallbacks) { try { SystemCallback = systemCallback; IOCallbacks.AddRange(ioCallbacks); IOTargetFilePaths.AddRange(IOCallbacks.SelectMany(c => c.GetTargetFilePaths())); // Initialize event to non-Signaled HookInitEvent = new AutoResetEvent(false); SMAInitEvent = new AutoResetEvent(false); HookSuccess = false; HookException = null; // Start a new IPC server StartIPCServer(); // Start SuperMemo application with given collection as parameter, // and immediatly install hooks RemoteHooking.CreateAndInject( SMConst.BinPath, collection.GetKnoFilePath().Quotify(), 0, InjectionOptions.Default, SMAConst.Assembly.GetInjectionLibFilePath(), null, out var pId ); // Wait for Signal from OnHookInstalled with timeout HookInitEvent.WaitOne(WaitTimeout); if (HookSuccess == false) { StopIPCServer(); var ex = new HookException("Hook setup failed: " + HookException?.Message, HookException); HookException = null; throw ex; } return(new ProcessSharp <SM17Natives>( pId, Process.NET.Memory.MemoryType.Remote, true, SMA.Instance.Config.PatternsHintAddresses)); } finally { HookInitEvent = null; } }
// // Collection loading management public async Task <bool> Start( NativeDataCfg nativeDataCfg, StartupCfg startupCfg, SMCollection collection) { try { if (_sm != null) { throw new InvalidOperationException("_sm is already instantiated"); } await LoadConfig(collection, startupCfg); var nativeData = CheckSuperMemoExecutable(nativeDataCfg); _sm = InstantiateSuperMemo(collection, nativeData.SMVersion); // TODO: Move somewhere else _sm.UI.ElementWdw.OnAvailable += OnSuperMemoWindowsAvailable; await _sm.Start(nativeData); // TODO: Ensure opened collection (windows title) matches parameter } catch (Exception ex) { if (ex is SMAException) { LogTo.Warning(ex, "Failed to start SM."); } else { LogTo.Error(ex, "Failed to start SM."); } _sm?.Dispose(); _sm = null; try { if (OnSMStoppedEvent != null) { await OnSMStoppedEvent.InvokeAsync(this, new SMProcessArgs(_sm, null)).ConfigureAwait(true); } } catch (Exception pluginEx) { LogTo.Error(pluginEx, "Exception while notifying plugins OnSMStoppedEvent."); } // TODO: Handle exception return(false); } return(true); }
private void DeleteCollection(SMCollection collection) { if (Forge.Forms.Show.Window().For(new Confirmation("Are you sure ?")).Result.Model.Confirmed) { SavedCollections.Remove(collection); SaveConfig(); } }
// // Core hook methods public async Task <IProcess> CreateAndHook( SMCollection collection, string binPath, ISMAHookSystem systemCallback, IEnumerable <ISMAHookIO> ioCallbacks) { LogTo.Debug("Starting and injecting SuperMemo"); SystemCallback = systemCallback; IOCallbacks.AddRange(ioCallbacks); IOTargetFilePaths.AddRange(IOCallbacks.SelectMany(c => c.GetTargetFilePaths())); HookSuccess = false; HookException = null; // Start a new IPC server var channelName = StartIPCServer(); // Start SuperMemo application with given collection as parameter, // and immediatly install hooks RemoteHooking.CreateAndInject( binPath, collection.GetKnoFilePath().Quotify(), 0, InjectionOptions.Default, SMAFileSystem.InjectionLibFile.FullPath, null, out var pId, channelName ); LogTo.Debug("Waiting for signal from Injected library"); // Wait for Signal from OnHookInstalled with timeout await HookInitEvent.WaitAsync(WaitTimeout); if (HookSuccess == false) { LogTo.Debug("Hook failed, aborting"); StopIPCServer(); var ex = new HookException("Hook setup failed: " + HookException?.Message, HookException); HookException = null; throw ex; } LogTo.Debug($"SuperMemo started and injected, pId: {pId}"); return(new ProcessSharp <SM17Natives>( pId, Process.NET.Memory.MemoryType.Remote, true, SMA.SMA.Instance.StartupConfig.PatternsHintAddresses)); }
private static SuperMemoCore GetSuperMemoFactory(SMCollection collection, Version smVersion) { if (SM17.Versions.Contains(smVersion)) { return(new SM17(collection, CoreConfig.SuperMemo.SMBinPath)); } throw new SMAException($"Unsupported SM version {smVersion}"); }
/// <inheritdoc /> protected SuperMemoCore(SMCollection collection, string binPath) : base(collection, binPath) { Core.SM = this; _registry = new SuperMemoRegistryCore(); _ui = new SuperMemoUICore(); Hook = new SMHookEngine(); }
private SuperMemoCore InstantiateSuperMemo(SMCollection collection, Version smVersion) { if (SM17.Versions.Contains(smVersion)) { return(new SM17(collection, StartupConfig.SMBinPath)); } throw new SMAException($"Unsupported SM version {smVersion}"); }
/// <inheritdoc /> protected override void OnCollectionSelected(SMCollection col) { base.OnCollectionSelected(col); ImportConfig = Svc.CollectionConfiguration.Load <ImportCollectionCfg>() ?? new ImportCollectionCfg(); _importService = new ImportPluginService(); CreateBrowserRegistryKeys(); PublishService <IImportPluginService, ImportPluginService>(_importService, ImportConst.ChannelName); }
// // Collection loading management public async Task <Exception> StartAsync( NativeDataCfg nativeDataCfg, SMCollection collection) { try { if (_sm != null) { throw new InvalidOperationException("_sm is already instantiated"); } // Load collection config await LoadConfigAsync(collection).ConfigureAwait(false); // Make sure the SuperMemo version is compatible and instantiate it var nativeData = CheckSuperMemoExecutable(nativeDataCfg); _sm = GetSuperMemoFactory(collection, nativeData.SMVersion); // Notify Plugins of selected collection await OnCollectionSelectedAsync(collection).ConfigureAwait(false); await _sm.StartAsync(nativeData).ConfigureAwait(false); // TODO: Ensure opened collection (windows title) matches parameter } catch (Exception ex) { if (ex is SMAException) { LogTo.Warning(ex, "Failed to start SM."); } else { LogTo.Error(ex, "Failed to start SM."); } _sm?.Dispose(); _sm = null; // TODO: Handle exception return(ex); } return(null); }
private async Task DeleteCollectionAsync(SMCollection collection) { var res = await Forge.Forms.Show.Window().For(new Confirmation("Are you sure ?")).ConfigureAwait(true); if (res.Model.Confirmed) { // ObservableHashSet does not have index, which results in an exception when notifying for removal var tmpCollections = SavedCollections; SavedCollections = null; tmpCollections.Remove(collection); SaveConfig(); SavedCollections = tmpCollections; } }
// // Collection loading management public async Task <Exception> Start( NativeDataCfg nativeDataCfg, SMCollection collection) { try { if (_sm != null) { throw new InvalidOperationException("_sm is already instantiated"); } await LoadConfig(collection); var nativeData = CheckSuperMemoExecutable(nativeDataCfg); _sm = InstantiateSuperMemo(collection, nativeData.SMVersion); // TODO: Move somewhere else _sm.UI.ElementWdw.OnAvailable += OnSuperMemoWindowsAvailable; await _sm.Start(nativeData); // TODO: Ensure opened collection (windows title) matches parameter } catch (Exception ex) { if (ex is SMAException) { LogTo.Warning(ex, "Failed to start SM."); } else { LogTo.Error(ex, "Failed to start SM."); } _sm?.Dispose(); _sm = null; // TODO: Handle exception return(ex); } return(null); }
protected SuperMemoBase(SMCollection collection) { Collection = collection; OnPreInit(); SMProcess = SMHookEngine.Instance.CreateAndHook( collection, this, GetIOCallbacks() ); SMProcess.Native.Exited += OnSMExited; OnPostInit(); SMHookEngine.Instance.SignalWakeUp(); }
private void LoadConfig(SMCollection collection) { var knoPath = collection.GetKnoFilePath(); // StartupCfg StartupConfig = Core.Configuration.Load <StartupCfg>().Result ?? new StartupCfg(); // CollectionsCfg _collectionsCfg = Core.Configuration.Load <CollectionsCfg>().Result ?? new CollectionsCfg(); CollectionConfig = _collectionsCfg.CollectionsConfig.SafeGet(knoPath); if (CollectionConfig == null) { CollectionConfig = new CollectionCfg(); _collectionsCfg.CollectionsConfig[knoPath] = CollectionConfig; } }
public bool ValidateCollection(SMCollection collection) { if (collection.Exists() == false) { Forge.Forms.Show.Window().For(new Alert("Collection doesn't exist anymore.", "Error")); return(false); } // Check whether collection is locked if (collection.IsLocked()) { Forge.Forms.Show.Window().For(new Alert("Collection is locked. Is SuperMemo already running ?", "Error")); return(false); } return(true); }
public void CommitFromFiles(SMCollection collection, IRegistryFileDescriptor registryFileDesc) { var memFilePath = collection.GetMemFilePath(registryFileDesc); var rtxFilePath = collection.GetRtxFilePath(registryFileDesc); var memExists = File.Exists(memFilePath); var rtxExists = File.Exists(rtxFilePath); switch (registryFileDesc.IsOptional) { case true when rtxExists == false || memExists == false: return; case false when memExists == false: throw new InvalidOperationException($"({GetType().Name}) Failed to load registry file: no such file {memFilePath}"); case false when rtxExists == false: throw new InvalidOperationException($"({GetType().Name}) Failed to load registry file: no such file {rtxFilePath}"); } using (Stream memStream = File.OpenRead(memFilePath)) using (Stream rtxStream = File.OpenRead(rtxFilePath)) //using (Stream rtfStream = File.OpenRead(rtfFilePath)) { Dictionary <int, RegMemElem17> memElems = memStream.StreamToStruct <RegMemElem17, RegMemElem17>( RegMemElem17.SizeOfMemElem, e => e ); foreach (var id in memElems.Keys.OrderBy(id => id)) { var memElem = memElems[id]; var rtxElem = ParseRtStream(rtxStream, memElem); Commit(id, memElem, rtxElem); } } }
public bool ValidateCollection(SMCollection collection) { var knoFilePath = new FilePath(collection.GetKnoFilePath()); if (knoFilePath.Exists() == false || Directory.Exists(collection.GetRootDirPath()) == false) { Forge.Forms.Show.Window().For(new Alert("Collection doesn't exist anymore.", "Error")); return(false); } // Check whether collection is locked if (knoFilePath.IsLocked()) { Forge.Forms.Show.Window().For(new Alert("Collection is locked. Is SuperMemo already running ?", "Error")); return(false); } return(true); }
public static (AppDomain domain, PluginHost runner) Create(SMCollection collection) { DirectoryEx.EnsureExists(SMAConst.Paths.AppDomainCachePath); DirectoryEx.EnsureExists(SMAConst.Paths.PluginPath); DirectoryEx.EnsureExists(collection.GetSMAFolder()); DirectoryEx.EnsureExists(collection.GetSMAElementsFolder()); DirectoryEx.EnsureExists(collection.GetSMAPluginsFolder()); DirectoryEx.EnsureExists(collection.GetSMASystemFolder()); var assemblyPaths = String.Join(";", GetAssemblyPaths()); var setup = new AppDomainSetup() { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase, CachePath = SMAConst.Paths.AppDomainCachePath, PrivateBinPath = assemblyPaths, ShadowCopyFiles = "true", ShadowCopyDirectories = assemblyPaths }; var permissions = GetPermissions(collection); var domain = AppDomain.CreateDomain( AppDomainName, AppDomain.CurrentDomain.Evidence, setup, permissions ); var runner = (PluginHost)domain.CreateInstanceAndUnwrap( typeof(PluginHost).Assembly.FullName, // ReSharper disable once AssignNullToNotNullAttribute typeof(PluginHost).FullName ); return(domain, runner); }
public async Task OnCollectionSelectedAsync(SMCollection collection) { try { _sm.UI.ElementWdw.OnAvailableInternal += OnSuperMemoWindowsAvailable; if (OnCollectionSelectedInternalEvent != null) { await OnCollectionSelectedInternalEvent.InvokeAsync(this, new SMEventArgs(_sm)).ConfigureAwait(false); } OnCollectionSelectedEvent?.InvokeRemote( nameof(OnCollectionSelectedAsync), collection, h => OnCollectionSelectedEvent -= h ); } catch (Exception ex) { LogTo.Error(ex, "Exception while notifying subscribers of OnCollectionSelected"); throw; } }
/// <inheritdoc /> public void CommitFromFiles(SMCollection collection) { using (Stream cttStream = File.OpenRead(collection.GetInfoFilePath(SMConst.Files.ContentsFileName))) using (Stream elStream = File.OpenRead(collection.GetInfoFilePath(SMConst.Files.ElementsInfoFileName))) { var cttElems = cttStream.StreamToStruct <InfContentsElem17, InfContentsElem17>( InfContentsElem17.SizeOfContentsElem, s => s ); var elElems = elStream.StreamToStruct <InfElementsElemContainer17, InfElementsElem17>( InfElementsElem17.SizeOfElementsElem, e => new InfElementsElemContainer17(e) ); foreach (int id in cttElems.Keys.Union(elElems.Keys)) { Commit(id, cttElems.SafeGet(id), elElems.SafeGet(id)); } } }
private static PermissionSet GetPermissions(SMCollection collection) { // TODO: Switch back to restricted var permissions = new PermissionSet(PermissionState.Unrestricted); //permissions.SetPermission(new EnvironmentPermission(PermissionState.Unrestricted)); //permissions.SetPermission(new UIPermission(PermissionState.Unrestricted)); //permissions.SetPermission(new FileDialogPermission(PermissionState.Unrestricted)); //permissions.SetPermission(new MediaPermission(PermissionState.Unrestricted)); //permissions.SetPermission(new ReflectionPermission(PermissionState.Unrestricted)); /*permissions.SetPermission( * new SecurityPermission(SecurityPermissionFlag.AllFlags)); * SecurityPermissionFlag.Execution | SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.BindingRedirects | SecurityPermissionFlag.Assertion | SecurityPermissionFlag.RemotingConfiguration | SecurityPermissionFlag.ControlThread));*/ permissions.RemovePermission(typeof(FileIOPermission)); permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path.GetTempPath())); permissions.AddPermission(new FileIOPermission( FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles)) ); permissions.AddPermission(new FileIOPermission( FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86)) ); permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, collection.GetSMAFolder())); permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, SMAConst.Paths.AppDataPath)); permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, AppDomain.CurrentDomain.BaseDirectory)); return(permissions); }
private async Task LoadApp(SMAParameters args) { // // Installer events if (SMAInstaller.HandleEvent(args, out var firstRun)) { if (firstRun) { await "SuperMemo Assistant has been successfully installed.".MsgBox("Installation"); } Shutdown(); return; } // // Make sure assemblies are available, and SMA is installed in "%LocalAppData%\SuperMemoAssistant" if (AssemblyCheck.CheckRequired(out var errMsg) == false || CheckSMALocation(out errMsg) == false) { LogTo.Warning(errMsg); await errMsg.ErrorMsgBox(); Shutdown(SMAExitCodes.ExitCodeDependencyError); return; } // // Load system configs if (await LoadConfigs(out var nativeDataCfg, out var startupCfg) == false) { errMsg = $"At least one essential config file could not be loaded: nativeDataCfg ? {nativeDataCfg == null} ; startupCfg ? {startupCfg == null}"; LogTo.Warning(errMsg); await errMsg.ErrorMsgBox(); Shutdown(SMAExitCodes.ExitCodeConfigError); return; } // // Make sure SuperMemo exe path is correct. Prompt user to input the path otherwise. if (SMASetup.ShouldFindSuperMemo(startupCfg, nativeDataCfg)) { var smFinder = new Setup.SuperMemoFinder(nativeDataCfg, startupCfg); smFinder.ShowDialog(); if (smFinder.DialogResult == null || smFinder.DialogResult == false) { LogTo.Warning(errMsg); Shutdown(SMAExitCodes.ExitCodeSMExeError); return; } } // // (Optional) Start the debug Key logger (logs key strokes with modifiers, e.g. ctrl, alt, ..) if (args.KeyLogger) { SMA.Core.KeyboardHotKey.MainCallback = hk => LogTo.Debug($"Key pressed: {hk}"); } // // Determine which collection to open SMCollection smCollection = null; var selectionWdw = new CollectionSelectionWindow(startupCfg); // Try to open command line collection, if one was passed if (args.CollectionKnoPath != null && selectionWdw.ValidateSuperMemoPath()) { smCollection = new SMCollection(args.CollectionKnoPath, DateTime.Now); if (selectionWdw.ValidateCollection(smCollection) == false) { smCollection = null; } } // No valid collection passed, show selection window if (smCollection == null) { selectionWdw.ShowDialog(); smCollection = selectionWdw.Collection; } // // If a collection was defined, start SMA if (smCollection != null) { SMA.Core.SMA.OnSMStoppedEvent += OnSMStoppedEvent; if (await SMA.Core.SMA.Start(nativeDataCfg, startupCfg, smCollection).ConfigureAwait(true) == false) { await $"SMA failed to start. Please check the logs in '{SMAFileSystem.LogDir.FullPath}' for details.".ErrorMsgBox(); Shutdown(SMAExitCodes.ExitCodeSMAStartupError); return; } if (SMAExecutableInfo.Instance.IsDev == false) { await SMAInstaller.Instance.Update(); } } else { Shutdown(); } }
protected SuperMemoBase(SMCollection collection, string binPath) { Collection = collection; _binPath = binPath; }