refactoring & koaloader testing

This commit is contained in:
pointfeev 2022-08-23 21:24:57 -04:00
parent 104e7d1a86
commit 325f6ad117
6 changed files with 355 additions and 49 deletions

View file

@ -58,67 +58,106 @@ internal partial class InstallForm : CustomForm
private async Task OperateFor(ProgramSelection selection)
{
UpdateProgress(0);
int count = selection.DllDirectories.Count;
int cur = 0;
if (selection.Id == "PL")
{
UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation);
_ = await Repair(this, selection);
}
foreach (string directory in selection.DllDirectories)
if (selection.Koaloader && !Uninstalling)
{
if (selection.Platform is Platform.Steam || selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden)
|| selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden)))
foreach (string directory in await selection.RootDirectory.GetExecutableDirectories())
{
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string cache);
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache))
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
await Koaloader.Install(directory, selection, this);
}
}
else
{
if (Uninstalling)
{
foreach (string directory in await selection.RootDirectory.GetExecutableDirectories())
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} SmokeAPI" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await SmokeAPI.Uninstall(directory, this);
else
await SmokeAPI.Install(directory, selection, this);
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
bool proxyExists = false;
foreach (string proxy in proxies)
if (File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader))
{
proxyExists = true;
break;
}
bool dllExists = false;
foreach ((string unlocker, string dll) in Koaloader.AutoLoadDlls)
{
string path = directory + @"\" + dll;
if (File.Exists(path))
{
dllExists = true;
break;
}
}
if (proxyExists || dllExists || File.Exists(config))
{
UpdateUser("Uninstalling Koaloader from " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
await Koaloader.Uninstall(directory, selection, this);
}
}
}
if (selection.Platform is Platform.Epic || selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)
|| selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)))
int count = selection.DllDirectories.Count, cur = 0;
foreach (string directory in selection.DllDirectories)
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config))
if (selection.Platform is Platform.Steam || selection.SelectedDlc.Any(d => d.Value.type is DlcType.Steam or DlcType.SteamHidden)
|| selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.Steam or DlcType.SteamHidden)))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} ScreamAPI" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await ScreamAPI.Uninstall(directory, this);
else
await ScreamAPI.Install(directory, selection, this);
directory.GetSmokeApiComponents(out _, out string api32_o, out _, out string api64_o, out string config, out string cache);
if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} SmokeAPI" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await SmokeAPI.Uninstall(directory, this);
else
await SmokeAPI.Install(directory, selection, this);
}
}
if (selection.Platform is Platform.Epic || selection.SelectedDlc.Any(d => d.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)
|| selection.Platform is Platform.Paradox || selection.ExtraSelectedDlc.Any(item => item.dlc.Any(dlc => dlc.Value.type is DlcType.EpicCatalogItem or DlcType.EpicEntitlement)))
{
directory.GetScreamApiComponents(out _, out string api32_o, out _, out string api64_o, out string config);
if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} ScreamAPI" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await ScreamAPI.Uninstall(directory, this);
else
await ScreamAPI.Install(directory, selection, this);
}
}
if (selection.Platform is Platform.Ubisoft)
{
directory.GetUplayR1Components(out _, out string api32_o, out _, out string api64_o, out string config);
if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await UplayR1.Uninstall(directory, this);
else
await UplayR1.Install(directory, selection, this);
}
directory.GetUplayR2Components(out _, out _, out _, out api32_o, out _, out api64_o, out config);
if (File.Exists(api32_o) || File.Exists(api64_o) || File.Exists(config))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await UplayR2.Uninstall(directory, this);
else
await UplayR2.Install(directory, selection, this);
}
}
UpdateProgress(++cur / count * 100);
}
if (selection.Platform is Platform.Ubisoft)
{
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await UplayR1.Uninstall(directory, this);
else
await UplayR1.Install(directory, selection, this);
}
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config);
if (File.Exists(old_api32) || File.Exists(old_api64) || File.Exists(api32) || File.Exists(api32_o) || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config))
{
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" +
$" {(Uninstalling ? "from" : "for")} " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
if (Uninstalling)
await UplayR2.Uninstall(directory, this);
else
await UplayR2.Install(directory, selection, this);
}
}
UpdateProgress(++cur / count * 100);
}
UpdateProgress(100);
}

View file

@ -134,11 +134,11 @@ internal partial class SelectForm : CustomForm
_ = selectionTreeView.Nodes.Add(programNode);
}
}
int totalGames = 0, gamesChecked = 0;
if (ProgramsToScan.Any(c => c.platform is Platform.Steam))
{
List<(string appId, string name, string branch, int buildId, string gameDirectory)> steamGames = await SteamLibrary.GetGames();
int totalGames = steamGames.Count;
int gamesChecked = 0;
totalGames = steamGames.Count;
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) in steamGames)
{
if (Program.Canceled) return;
@ -437,6 +437,7 @@ internal partial class SelectForm : CustomForm
if (Program.Canceled) return;
await task;
}
gamesChecked = totalGames;
}
private List<(Platform platform, string id, string name)> ProgramsToScan;

View file

@ -43,6 +43,8 @@ internal class ProgramSelection
internal string RootDirectory;
internal List<string> DllDirectories;
internal bool Koaloader = true;
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.String);
internal readonly SortedList<string, (DlcType type, string name, string icon)> SelectedDlc = new(PlatformIdComparer.String);

View file

@ -0,0 +1,239 @@
using ABI.System.Collections.Generic;
using CreamInstaller.Components;
using CreamInstaller.Utility;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Media.Playback;
using Windows.Networking.Connectivity;
namespace CreamInstaller.Resources;
internal static class Koaloader
{
internal static void GetKoaloaderComponents(
this string directory,
out List<string> proxies,
out string config
)
{
proxies = new();
foreach (string proxy in Resources.EmbeddedResources)
{
string proxyPath = proxy[(proxy.IndexOf('.') + 1)..];
proxyPath = proxyPath[(proxyPath.IndexOf('.') + 1)..];
proxies.Add(directory + @"\" + proxyPath);
}
config = directory + @"\Koaloader.json";
}
internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new()
{
("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"),
("ScreamAPI", "ScreamAPI32.dll"), ("ScreamAPI", "ScreamAPI64.dll"),
("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll"),
("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll")
};
internal static void WriteConfig(StreamWriter writer, SortedList<string, string> targets, SortedList<string, string> modules, InstallForm installForm = null)
{
writer.WriteLine("{");
writer.WriteLine(" \"logging\": false,");
writer.WriteLine(" \"enabled\": true,");
writer.WriteLine(" \"auto_load\": " + (modules.Any() ? "false" : "true") + ",");
if (targets.Any())
{
writer.WriteLine(" \"targets\": [");
System.Collections.Generic.KeyValuePair<string, string> lastTarget = targets.Last();
foreach (System.Collections.Generic.KeyValuePair<string, string> pair in targets)
{
string path = pair.Value;
writer.WriteLine($" \"{path}\"{(pair.Equals(lastTarget) ? "" : ",")}");
if (installForm is not null)
installForm.UpdateUser($"Added target to Koaloader.json with path {path}", InstallationLog.Action, info: false);
}
writer.WriteLine(" ]");
}
else
writer.WriteLine(" \"targets\": []");
if (modules.Any())
{
writer.WriteLine(" \"modules\": [");
System.Collections.Generic.KeyValuePair<string, string> lastModule = modules.Last();
foreach (System.Collections.Generic.KeyValuePair<string, string> pair in modules)
{
string path = pair.Value;
writer.WriteLine(" {");
writer.WriteLine($" \"path\": \"" + path + "\",");
writer.WriteLine($" \"required\": true");
writer.WriteLine(" }" + (pair.Equals(lastModule) ? "" : ","));
if (installForm is not null)
installForm.UpdateUser($"Added module to Koaloader.json with path {path}", InstallationLog.Action, info: false);
}
writer.WriteLine(" ]");
}
else
writer.WriteLine(" \"modules\": []");
writer.WriteLine("}");
}
internal static async Task Uninstall(string directory, ProgramSelection selection, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() =>
{
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
foreach (string proxy in proxies)
{
if (File.Exists(proxy) && proxy.IsResourceFile(Resources.ResourceIdentifier.Koaloader))
{
File.Delete(proxy);
if (installForm is not null)
installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxy)}", InstallationLog.Action, info: false);
}
}
foreach ((string unlocker, string dll) in AutoLoadDlls)
{
string path = directory + @"\" + dll;
if (File.Exists(path))
{
File.Delete(path);
if (installForm is not null)
installForm.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
}
if (deleteConfig && File.Exists(config))
{
File.Delete(config);
if (installForm is not null)
installForm.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false);
}
});
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() =>
{
directory.GetKoaloaderComponents(out List<string> proxies, out string config);
string path = directory + @"\version.dll";
"Koaloader.version_64.version.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
if (selection.Platform is Platform.Steam or Platform.Paradox)
{
bool did32 = false, did64 = false;
foreach (string dllDirectory in selection.DllDirectories)
{
dllDirectory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _);
if (!did32 && File.Exists(api32))
{
did32 = true;
path = directory + @"\SmokeAPI32.dll";
"SmokeAPI.steam_api.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64 && File.Exists(api64))
{
did64 = true;
path = directory + @"\SmokeAPI64.dll";
"SmokeAPI.steam_api64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32 && did64)
break;
}
}
if (selection.Platform is Platform.Epic or Platform.Paradox)
{
bool did32 = false, did64 = false;
foreach (string dllDirectory in selection.DllDirectories)
{
dllDirectory.GetScreamApiComponents(out string api32, out _, out string api64, out _, out _);
if (!did32 && File.Exists(api32))
{
did32 = true;
path = directory + @"\ScreamAPI32.dll";
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64 && File.Exists(api64))
{
did64 = true;
path = directory + @"\ScreamAPI64.dll";
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32 && did64)
break;
}
}
if (selection.Platform is Platform.Ubisoft)
{
bool did32r1 = false, did64r1 = false, did32r2 = false, did64r2 = false;
foreach (string dllDirectory in selection.DllDirectories)
{
dllDirectory.GetUplayR1Components(out string api32, out _, out string api64, out _, out _);
if (!did32r1 && File.Exists(api32))
{
did32r1 = true;
path = directory + @"\UplayR1Unlocker32.dll";
"UplayR1.uplay_r1_loader.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64r1 && File.Exists(api64))
{
did64r1 = true;
path = directory + @"\UplayR1Unlocker64.dll";
"UplayR1.uplay_r1_loader64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
dllDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out _, out api64, out _, out _);
if (!did32r2 && (File.Exists(old_api32) || File.Exists(old_api32)))
{
did32r2 = true;
path = directory + @"\UplayR2Unlocker32.dll";
"UplayR2.upc_r2_loader.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64r2 && (File.Exists(old_api64) || File.Exists(api64)))
{
did64r2 = true;
path = directory + @"\UplayR2Unlocker64.dll";
"UplayR2.upc_r2_loader64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32r1 && did64r1 && did32r2 && did64r2)
break;
}
}
if (generateConfig)
{
SortedList<string, string> targets = new(PlatformIdComparer.String);
SortedList<string, string> modules = new(PlatformIdComparer.String);
if (targets.Any() || modules.Any())
{
if (installForm is not null)
installForm.UpdateUser("Generating Koaloader configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
File.Create(config).Close();
StreamWriter writer = new(config, true, Encoding.UTF8);
WriteConfig(writer, targets, modules, installForm);
writer.Flush();
writer.Close();
}
else if (File.Exists(config))
{
File.Delete(config);
if (installForm is not null)
installForm.UpdateUser($"Deleted unnecessary configuration: {Path.GetFileName(config)}", InstallationLog.Action, info: false);
}
}
});
}

View file

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace CreamInstaller.Resources;
@ -417,4 +419,25 @@ internal static class Resources
internal static bool IsResourceFile(this string filePath, ResourceIdentifier identifier) => filePath.ComputeMD5() is string hash && ResourceMD5s[identifier].Contains(hash);
internal static bool IsResourceFile(this string filePath) => filePath.ComputeMD5() is string hash && ResourceMD5s.Values.Any(hashes => hashes.Contains(hash));
internal static async Task<List<string>> GetExecutableDirectories(this string rootDirectory) => await Task.Run(async () =>
{
List<string> executableDirectories = new();
if (Program.Canceled || !Directory.Exists(rootDirectory)) return null;
if (Directory.GetFiles(rootDirectory, "*.exe").Any())
executableDirectories.Add(rootDirectory);
string[] directories = Directory.GetDirectories(rootDirectory);
foreach (string _directory in directories)
{
if (Program.Canceled) return null;
try
{
List<string> moreExecutableDirectories = await _directory.GetExecutableDirectories();
if (moreExecutableDirectories is not null)
executableDirectories.AddRange(moreExecutableDirectories);
}
catch { }
}
return !executableDirectories.Any() ? null : executableDirectories;
});
}

View file

@ -110,6 +110,7 @@ internal static class SteamLibrary
gameDirectories.Add(libraryFolder);
string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result))
#pragma warning disable IDE0220 // Add explicit cast
foreach (VProperty property in result.Value.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _)))
{
string path = property.Value.GetChild("path")?.ToString();
@ -117,6 +118,7 @@ internal static class SteamLibrary
path += @"\steamapps";
if (Directory.Exists(path) && !gameDirectories.Contains(path)) gameDirectories.Add(path);
}
#pragma warning restore IDE0220 // Add explicit cast
}
}
return gameDirectories;