/// <summary>
    /// Applies an individual application item to a given application configuration.
    /// </summary>
    /// <param name="indexApp">Index entry for the application.</param>
    /// <param name="pathTuple">The mod to apply the config to.</param>
    /// <param name="hash">Hash of the application's main executable.</param>
    public static void ApplyIndexEntry(AppItem indexApp, PathTuple <ApplicationConfig> pathTuple, string hash)
    {
        var hashMatches = hash.Equals(indexApp.Hash, StringComparison.OrdinalIgnoreCase);

        if (indexApp.AppStatus == Status.WrongExecutable && hashMatches)
        {
            Actions.DisplayMessagebox(Resources.AddAppRepoBadExecutable.Get(), indexApp.BadStatusDescription !);
        }

        pathTuple.Config.AppName = indexApp.AppName;
        // Apply GB Configurations
        Singleton <GameBananaPackageProviderFactory> .Instance.SetConfiguration(pathTuple,
                                                                                new GameBananaPackageProviderFactory.GameBananaProviderConfig()
        {
            GameId = (int)indexApp.GameBananaId
        });

        if (!hashMatches)
        {
            var viewModel = new AddAppHashMismatchDialogViewModel(indexApp.BadHashDescription !);
            Actions.ShowAddAppHashMismatchDialog(viewModel);
        }

        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(pathTuple);

        if (indexApp.TryGetError(Path.GetDirectoryName(appLocation) !, out var errors))
        {
            var viewModel = new AddApplicationWarningDialogViewModel(errors);
            Actions.ShowApplicationWarningDialog(viewModel);
        }
    }
    /// <summary>
    /// Executes the task asynchronously.
    /// </summary>
    /// <returns></returns>
    public async Task ExecuteAsync()
    {
        var config = _application.Config;

        await using var fileStream = new FileStream(ApplicationConfig.GetAbsoluteAppLocation(_application), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 524288);
        var indexApi = new IndexApi();
        var index    = await indexApi.GetIndexAsync();

        var hash         = Hashing.ToString(await Hashing.FromStreamAsync(fileStream));
        var applications = index.FindApplication(hash, config.AppId, out bool hashMatches);

        await await ActionWrappers.ExecuteWithApplicationDispatcherAsync(async() =>
        {
            if (applications.Count == 1 && hashMatches)
            {
                ApplyIndexEntry(await indexApi.GetApplicationAsync(applications[0]), _application, hash);
            }
            else if (applications.Count >= 1)
            {
                // Select application.
                var viewModel = new SelectAddedGameDialogViewModel(applications);
                var result    = Actions.ShowSelectAddedGameDialog(viewModel);
                if (result == null)
                {
                    return;
                }

                ApplyIndexEntry(await indexApi.GetApplicationAsync(result), _application, hash);
            }
        });
    }
    /// <summary>
    /// Applies an individual application item to a given application configuration.
    /// </summary>
    /// <param name="indexApp">Index entry for the application.</param>
    /// <param name="pathTuple">The mod to apply the config to.</param>
    public static void ApplyIndexEntry(AppItem indexApp, PathTuple <ApplicationConfig> pathTuple)
    {
        using var fileStream = new FileStream(ApplicationConfig.GetAbsoluteAppLocation(pathTuple), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 524288);
        var hash = Hashing.ToString(xxHash64.ComputeHash(fileStream));

        ApplyIndexEntry(indexApp, pathTuple, hash);
    }
    /// <summary>
    /// Obtains an image to represent a given application.
    /// The image is either a custom one or the icon of the application.
    /// </summary>
    private ImageSource GetImageForAppConfig(PathTuple <ApplicationConfig> applicationConfig)
    {
        // Check if custom icon exists.
        if (!string.IsNullOrEmpty(applicationConfig.Config.AppIcon))
        {
            if (ApplicationConfig.TryGetApplicationIcon(applicationConfig.Path, applicationConfig.Config, out var applicationIcon))
            {
                return(Misc.Imaging.BitmapFromUri(new Uri(applicationIcon, UriKind.Absolute)));
            }
        }

        // Otherwise extract new icon from executable.
        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(applicationConfig);

        if (File.Exists(appLocation))
        {
            // Else make new from icon.
            using Icon? ico = Icon.ExtractAssociatedIcon(appLocation);
            if (ico != null)
            {
                // Extract to config set location.
                BitmapSource bitmapImage = Imaging.CreateBitmapSourceFromHIcon(ico.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                bitmapImage.Freeze();
                return(bitmapImage);
            }
        }

        return(Misc.Imaging.GetPlaceholderIcon());
    }
Exemple #5
0
    /// <summary>
    /// Returns true if ASI loader is already installed, else false.
    /// This check works by checking the existence of ASI files in a supported directory.
    /// </summary>
    private bool AreAnyAsiPluginsInstalled(out string?modPath)
    {
        var appDirectory = Path.GetDirectoryName(ApplicationConfig.GetAbsoluteAppLocation(Application));

        foreach (var directory in AsiCommonDirectories)
        {
            var directoryPath = Path.Combine(appDirectory !, directory);

            if (!Directory.Exists(directoryPath))
            {
                continue;
            }

            if (!Directory.GetFiles(directoryPath).Any(x => x.EndsWith(PluginExtension, StringComparison.OrdinalIgnoreCase)))
            {
                continue;
            }

            modPath = directoryPath;
            return(true);
        }

        modPath = null;
        return(false);
    }
Exemple #6
0
    /// <summary>
    /// Searches for the application configuration corresponding to the current
    /// executing application
    /// </summary>
    private IApplicationConfig FindThisApplication()
    {
        var configurations = ApplicationConfig.GetAllApplications(LoaderConfig.GetApplicationConfigDirectory());
        var fullPath       = NormalizePath(Environment.CurrentProcessLocation.Value);

        Logger.LogWriteLineAsync($"Current Process Location: {fullPath}");

        foreach (var configuration in configurations)
        {
            var application = configuration.Config;
            var appLocation = ApplicationConfig.GetAbsoluteAppLocation(configuration);

            if (string.IsNullOrEmpty(appLocation))
            {
                continue;
            }

            var fullAppLocation = NormalizePath(appLocation);
            if (fullAppLocation.Equals(fullPath, StringComparison.OrdinalIgnoreCase))
            {
                return(application);
            }
        }

        return(null);
    }
    /* Interface */

    /// <inheritdoc />
    public bool CanExecute(object?parameter)
    {
        if (_config != null)
        {
            return(File.Exists(ApplicationConfig.GetAbsoluteAppLocation(_config)));
        }

        return(false);
    }
    /* Static API */

    /// <summary>
    /// Returns a complete list of all processes running Reloaded.
    /// </summary>
    /// <param name="processes">List of all processes running Reloaded.</param>
    /// <returns>True if there is more than one process, else false.</returns>
    public static bool GetAllProcesses(out IEnumerable <Process> processes)
    {
        var applications = ApplicationConfig.GetAllApplications();
        var trackers     = applications.Select(x => new ApplicationInstanceTracker(ApplicationConfig.GetAbsoluteAppLocation(x)));

        processes = trackers.SelectMany(x => x.GetProcesses().ReloadedProcesses);

        return(processes.Any());
    }
Exemple #9
0
    private string SelectEXEFile()
    {
        var dialog = new VistaOpenFileDialog();

        dialog.Title    = Resources.AddAppExecutableTitle.Get();
        dialog.Filter   = $"{Resources.AddAppExecutableFilter.Get()} (*.exe)|*.exe";
        dialog.FileName = ApplicationConfig.GetAbsoluteAppLocation(Application);

        if ((bool)dialog.ShowDialog() !)
        {
            return(dialog.FileName);
        }

        return("");
    }
Exemple #10
0
    /// <summary>
    /// Gets the folder to install the bootstrapper to.
    /// Returned folder should be created if it did not previously exist.
    /// </summary>
    /// <param name="alreadyHasAsiPlugins">Whether a supported folder with at least one ASI Plugin already exists. Assume loader already installed if it does.</param>
    private string GetBootstrapperInstallFolder(out bool alreadyHasAsiPlugins)
    {
        alreadyHasAsiPlugins = false;

        if (AreAnyAsiPluginsInstalled(out string?installPath))
        {
            alreadyHasAsiPlugins = true;
            return(installPath !);
        }

        var appDirectory    = Path.GetDirectoryName(ApplicationConfig.GetAbsoluteAppLocation(Application));
        var pluginDirectory = Path.Combine(appDirectory !, AsiCommonDirectories[0]);

        return(pluginDirectory);
    }
Exemple #11
0
 /* Implementation */
 private void ProcessWatcherOnOnNewProcess(Process newProcess)
 {
     try
     {
         string fullPath = newProcess.GetExecutablePath();
         var    config   = _configService.Items.FirstOrDefault(x => string.Equals(ApplicationConfig.GetAbsoluteAppLocation(x), fullPath, StringComparison.OrdinalIgnoreCase));
         if (config != null && config.Config.AutoInject)
         {
             var appInjector = new ApplicationInjector(newProcess);
             appInjector.Inject();
         }
     }
     catch (Exception)
     {
         // Ignored
     }
 }
Exemple #12
0
    /// <summary>
    /// Deploys the ASI loader (if needed) and bootstrapper to the game folder.
    /// </summary>
    public void DeployAsiLoader(out string?asiLoaderPath, out string bootstrapperPath)
    {
        asiLoaderPath = null;
        DeployBootstrapper(out bool alreadyHasAsiPlugins, out bootstrapperPath);
        if (alreadyHasAsiPlugins)
        {
            return;
        }

        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(Application);

        using var peParser = new BasicPeParser(appLocation);
        var appDirectory = Path.GetDirectoryName(appLocation);
        var dllName      = GetFirstSupportedDllFile(peParser);

        asiLoaderPath = Path.Combine(appDirectory !, dllName !);
        ExtractAsiLoader(asiLoaderPath, !peParser.Is32BitHeader);
    }
    /// <inheritdoc />
    public void Execute(object?parameter)
    {
        var loaderConfig = IoC.Get <LoaderConfig>();
        var shell        = (IShellLink) new ShellLink();

        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(_config);

        shell.SetDescription($"Launch {_config?.Config.AppName} via Reloaded II");
        shell.SetPath($"\"{loaderConfig.LauncherPath}\"");
        shell.SetArguments($"{Constants.ParameterLaunch} \"{appLocation}\"");
        shell.SetWorkingDirectory(Path.GetDirectoryName(loaderConfig.LauncherPath) !);

        if (_config != null)
        {
            var hasIcon = _config.Config.TryGetApplicationIcon(_config.Path, out var logoPath);
            if (hasIcon)
            {
                // Make path for icon.
                string newPath = Path.ChangeExtension(logoPath, ".ico");

                // Convert to ICO.
                _iconConverter.TryConvertToIcon(logoPath, newPath);
                shell.SetIconLocation(newPath, 0);
            }
            else
            {
                shell.SetIconLocation(appLocation, 0);
            }
        }

        // Save the shortcut.
        var file = (IPersistFile)shell;
        var link = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), $"{_config?.Config.AppName} (Reloaded).lnk");

        file.Save(link, false);

        Actions.DisplayMessagebox?.Invoke(Resources.AddAppShortcutCreatedTitle.Get(),
                                          $"{Resources.AddAppShortcutCreatedMessage.Get()} {link}",
                                          new Actions.DisplayMessageBoxParams()
        {
            StartupLocation = Actions.WindowStartupLocation.CenterScreen
        });
    }
Exemple #14
0
    /// <summary>
    /// Checks if the ASI loader can be deployed.
    /// </summary>
    public bool CanDeploy()
    {
        var appLocation = ApplicationConfig.GetAbsoluteAppLocation(Application);

        if (!File.Exists(appLocation))
        {
            return(false);
        }

        using var peParser = new BasicPeParser(appLocation);

        try
        {
            return(GetFirstSupportedDllFile(peParser) != null);
        }
        catch (Exception)
        {
            return(false);
        }
    }
    /// <inheritdoc />
    public ApplicationViewModel(PathTuple <ApplicationConfig> tuple, ModConfigService modConfigService, ModUserConfigService modUserConfigService, LoaderConfig loaderConfig)
    {
        ApplicationTuple      = tuple;
        _modConfigService     = modConfigService;
        _modUserConfigService = modUserConfigService;
        _instanceTracker      = new ApplicationInstanceTracker(ApplicationConfig.GetAbsoluteAppLocation(tuple), _initialiseTokenSrc.Token);

        if (_initialiseTokenSrc.IsCancellationRequested)
        {
            return;
        }

        MakeShortcutCommand = new MakeShortcutCommand(tuple, Lib.IconConverter);
        _modConfigService.Items.CollectionChanged += OnGetModifications;
        _instanceTracker.OnProcessesChanged       += OnProcessesChanged;

        UpdateReloadedProcesses();
        GetModsForThisApp();
        _refreshProcessesWithLoaderTimer = new Timer(RefreshTimerCallback, null, 500, loaderConfig.ProcessRefreshInterval);
    }
Exemple #16
0
 /// <summary>
 /// Gets the path of the bootstrapper DLL to copy.
 /// </summary>
 public string GetBootstrapperDllPath()
 {
     return(Is64Bit(ApplicationConfig.GetAbsoluteAppLocation(Application))
         ? IoC.Get <LoaderConfig>().Bootstrapper64Path
         : IoC.Get <LoaderConfig>().Bootstrapper32Path);
 }
    private static void CreateTemplate(CreateTemplateOptions createTemplate)
    {
        if (createTemplate.Type == TemplateType.Application)
        {
            var apps    = ApplicationConfig.GetAllApplications();
            var appById = apps.FirstOrDefault(x => x.Config.AppId == createTemplate.Id);

            if (appById == null)
            {
                Console.WriteLine($"Possible Applications");
                foreach (var app in apps)
                {
                    Console.WriteLine($"Id: {app.Config.AppId} | Name: {app.Config.AppName}");
                }

                var cmdLine = Parser.Default.FormatCommandLine(new CreateTemplateOptions()
                {
                    Id   = apps[0].Config.AppId,
                    Type = TemplateType.Application
                });

                Console.WriteLine($"Example Usage: `Reloaded.Community.Tool.exe {cmdLine}`");
            }
            else
            {
                Console.WriteLine("Copy Text Below, Save as .json file.\n" +
                                  "====================================");

                var config = TryGetGameBananaUpdateConfig(appById);
                SerializeAndPrint(new AppItem()
                {
                    AppId        = appById.Config.AppId,
                    AppName      = appById.Config.AppName,
                    AppStatus    = Status.Ok,
                    Hash         = Hashing.ToString(xxHash64.ComputeHash(File.ReadAllBytes(ApplicationConfig.GetAbsoluteAppLocation(appById)))),
                    GameBananaId = config.GameId
                });
            }
        }
        else
        {
            throw new Exception("Not Supported");
        }
    }
Exemple #18
0
 /// <summary>
 /// Creates an <see cref="ApplicationLauncher"/> from an application config.
 /// </summary>
 public static ApplicationLauncher FromApplicationConfig(PathTuple <ApplicationConfig> config)
 {
     return(FromLocationAndArguments($"{ApplicationConfig.GetAbsoluteAppLocation(config)}", $"{config.Config.AppArguments}"));
 }
    private static void LaunchApplicationAndExit(string applicationToLaunch)
    {
        // Acquire arguments
        var loaderConfig = IoC.Get <LoaderConfig>();

        loaderConfig.UpdatePaths(Paths.CurrentProgramFolder, Resources.ErrorLoaderNotFound.Get());
        IConfig <LoaderConfig> .ToPath(loaderConfig, Paths.LoaderConfigPath);

        _commandLineArguments.TryGetValue(Constants.ParameterArguments, out var arguments);
        arguments ??= "";
        applicationToLaunch = Path.GetFullPath(applicationToLaunch);

        var application = ApplicationConfig.GetAllApplications(loaderConfig.GetApplicationConfigDirectory()).FirstOrDefault(x => ApplicationConfig.GetAbsoluteAppLocation(x) == applicationToLaunch);

        if (application != null)
        {
            arguments = $"{arguments} {application.Config.AppArguments}";
        }

        // Show warning for Wine users.
        if (Shared.Environment.IsWine)
        {
            // Set up UI Resources, since they're needed for the dialog.
            if (CompatibilityDialogs.WineShowLaunchDialog())
            {
                StartGame(applicationToLaunch, arguments);
            }
        }
        else
        {
            StartGame(applicationToLaunch, arguments);
        }
    }
 /// <inheritdoc />
 public bool CanExecute(object?parameter) => File.Exists(ApplicationConfig.GetAbsoluteAppLocation(_application));