- Minor refactoring & optimization
- Removed the no-longer-necessary locked DLL check in favor of SafeIO
- Fixed uninstall all cancel functionality
- Improved SafeIO crucial checks and warning outputs
This commit is contained in:
pointfeev 2023-06-09 19:04:54 -04:00
parent 43b9d9f153
commit c5fc5f561a
18 changed files with 151 additions and 217 deletions

View file

@ -4,7 +4,7 @@
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net7.0-windows</TargetFramework>
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<Version>4.9.4</Version> <Version>4.9.5</Version>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright> <Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
<Company>CreamInstaller</Company> <Company>CreamInstaller</Company>
<Product>Automatic DLC Unlocker Installer &amp; Configuration Generator</Product> <Product>Automatic DLC Unlocker Installer &amp; Configuration Generator</Product>

View file

@ -14,14 +14,12 @@ namespace CreamInstaller.Forms;
internal sealed partial class InstallForm : CustomForm internal sealed partial class InstallForm : CustomForm
{ {
private readonly HashSet<Selection> disabledSelections = new(); private readonly HashSet<Selection> activeSelections = new();
private readonly int programCount = Selection.AllEnabled.Count();
private readonly bool uninstalling; private readonly bool uninstalling;
private int completeOperationsCount; private int completeOperationsCount;
private int operationsCount; private int operationsCount;
internal bool Reselecting; internal bool Reselecting;
private int selectionCount;
internal InstallForm(bool uninstall = false) internal InstallForm(bool uninstall = false)
{ {
@ -77,7 +75,7 @@ internal sealed partial class InstallForm : CustomForm
foreach (string directory in invalidDirectories) foreach (string directory in invalidDirectories)
{ {
if (Program.Canceled) if (Program.Canceled)
throw new CustomMessageException("The operation was canceled."); return;
directory.GetKoaloaderComponents(out string old_config, out string config); directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader)) if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| directory != selection.RootDirectory && Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists()) || directory != selection.RootDirectory && Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists())
@ -91,7 +89,7 @@ internal sealed partial class InstallForm : CustomForm
foreach ((string directory, BinaryType _) in selection.ExecutableDirectories) foreach ((string directory, BinaryType _) in selection.ExecutableDirectories)
{ {
if (Program.Canceled) if (Program.Canceled)
throw new CustomMessageException("The operation was canceled."); return;
directory.GetKoaloaderComponents(out string old_config, out string config); directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader)) if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists()) || old_config.FileExists() || config.FileExists()) || Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists()) || old_config.FileExists() || config.FileExists())
@ -105,15 +103,15 @@ internal sealed partial class InstallForm : CustomForm
foreach (string directory in selection.DllDirectories) foreach (string directory in selection.DllDirectories)
{ {
if (Program.Canceled) if (Program.Canceled)
throw new CustomMessageException("The operation was canceled."); return;
if (selection.Platform is Platform.Steam or Platform.Paradox) if (selection.Platform is Platform.Steam or Platform.Paradox)
{ {
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config, directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
out string config, out string old_log, out string log, out string cache); out string config, out string old_log, out string log, out string cache);
if (uninstallProxy if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || old_config.FileExists() || config.FileExists() || old_log.FileExists() ? api32_o.FileExists() || api64_o.FileExists() || old_config.FileExists() || config.FileExists() || old_log.FileExists() || log.FileExists()
|| log.FileExists() || cache.FileExists() || cache.FileExists()
: api32.FileExists() || api64.FileExists()) : api32.FileExists() || api64.FileExists())
{ {
UpdateUser( UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name $"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -128,8 +126,8 @@ internal sealed partial class InstallForm : CustomForm
{ {
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log); directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log);
if (uninstallProxy if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists() ? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists()) : api32.FileExists() || api64.FileExists())
{ {
UpdateUser( UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name $"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -144,8 +142,8 @@ internal sealed partial class InstallForm : CustomForm
{ {
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log); directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log);
if (uninstallProxy if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists() ? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists()) : api32.FileExists() || api64.FileExists())
{ {
UpdateUser( UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name $"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -157,8 +155,8 @@ internal sealed partial class InstallForm : CustomForm
} }
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config, out log); directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config, out log);
if (uninstallProxy if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists() ? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: old_api32.FileExists() || old_api64.FileExists() || api32.FileExists() || api64.FileExists()) : old_api32.FileExists() || old_api64.FileExists() || api32.FileExists() || api64.FileExists())
{ {
UpdateUser( UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name $"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -175,7 +173,7 @@ internal sealed partial class InstallForm : CustomForm
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories) foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{ {
if (Program.Canceled) if (Program.Canceled)
throw new CustomMessageException("The operation was canceled."); return;
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation); UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this); await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this);
} }
@ -184,19 +182,19 @@ internal sealed partial class InstallForm : CustomForm
private async Task Operate() private async Task Operate()
{ {
HashSet<Selection> programSelections = Selection.AllEnabled.ToHashSet(); operationsCount = activeSelections.Count;
operationsCount = programSelections.Count;
completeOperationsCount = 0; completeOperationsCount = 0;
foreach (Selection selection in programSelections) foreach (Selection selection in activeSelections)
{ {
if (Program.Canceled || !Program.AreDllsLockedDialog(this, selection)) if (Program.Canceled)
throw new CustomMessageException("The operation was canceled."); throw new CustomMessageException("The operation was canceled.");
try try
{ {
await OperateFor(selection); await OperateFor(selection);
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success); UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success);
selection.Enabled = false; _ = activeSelections.Remove(selection);
_ = disabledSelections.Add(selection);
} }
catch (Exception exception) catch (Exception exception)
{ {
@ -205,15 +203,12 @@ internal sealed partial class InstallForm : CustomForm
++completeOperationsCount; ++completeOperationsCount;
} }
Program.Cleanup(); Program.Cleanup();
HashSet<Selection> failedSelections = Selection.AllEnabled.ToHashSet(); int activeCount = activeSelections.Count;
if (failedSelections.Count > 0) if (activeCount > 0)
if (failedSelections.Count == 1) if (activeCount == 1)
throw new CustomMessageException($"Operation failed for {failedSelections.First().Name}."); throw new CustomMessageException($"Operation failed for {activeSelections.First().Name}.");
else else
throw new CustomMessageException($"Operation failed for {failedSelections.Count} programs."); throw new CustomMessageException($"Operation failed for {activeCount} programs.");
foreach (Selection selection in disabledSelections)
selection.Enabled = true;
disabledSelections.Clear();
} }
private async void Start() private async void Start()
@ -227,7 +222,7 @@ internal sealed partial class InstallForm : CustomForm
try try
{ {
await Operate(); await Operate();
UpdateUser($"DLC unlocker(s) successfully {(uninstalling ? "uninstalled" : "installed and generated")} for " + programCount + " program(s).", UpdateUser($"DLC unlocker(s) successfully {(uninstalling ? "uninstalled" : "installed and generated")} for " + selectionCount + " program(s).",
LogTextBox.Success); LogTextBox.Success);
} }
catch (Exception exception) catch (Exception exception)
@ -241,13 +236,19 @@ internal sealed partial class InstallForm : CustomForm
reselectButton.Enabled = true; reselectButton.Enabled = true;
} }
private void OnLoad(object sender, EventArgs _) private void OnLoad(object sender, EventArgs a)
{ {
retry: retry:
try try
{ {
userInfoLabel.Text = "Loading . . . "; userInfoLabel.Text = "Loading . . . ";
logTextBox.Text = string.Empty; logTextBox.Text = string.Empty;
selectionCount = 0;
foreach (Selection selection in Selection.AllEnabled)
{
selectionCount++;
_ = activeSelections.Add(selection);
}
Start(); Start();
} }
catch (Exception e) catch (Exception e)
@ -276,9 +277,6 @@ internal sealed partial class InstallForm : CustomForm
{ {
Program.Cleanup(); Program.Cleanup();
Reselecting = true; Reselecting = true;
foreach (Selection selection in disabledSelections)
selection.Enabled = true;
disabledSelections.Clear();
Close(); Close();
} }
} }

View file

@ -535,7 +535,7 @@ internal sealed partial class SelectForm : CustomForm
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL"))); programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
if (SteamLibrary.InstallPath.DirectoryExists()) if (SteamLibrary.InstallPath.DirectoryExists())
foreach ((string appId, string name, string _, int _, string _) in (await SteamLibrary.GetGames()).Where(g foreach ((string appId, string name, string _, int _, string _) in (await SteamLibrary.GetGames()).Where(g
=> !Program.IsGameBlocked(g.name, g.gameDirectory))) => !Program.IsGameBlocked(g.name, g.gameDirectory)))
gameChoices.Add((Platform.Steam, appId, name, gameChoices.Add((Platform.Steam, appId, name,
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Steam && p.id == appId))); programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
if (EpicLibrary.EpicManifestsPath.DirectoryExists() || HeroicLibrary.HeroicLibraryPath.DirectoryExists()) if (EpicLibrary.EpicManifestsPath.DirectoryExists() || HeroicLibrary.HeroicLibraryPath.DirectoryExists())
@ -709,7 +709,7 @@ internal sealed partial class SelectForm : CustomForm
programsGroupBox.Size = programsGroupBox.Size with programsGroupBox.Size = programsGroupBox.Size with
{ {
Height = programsGroupBox.Size.Height - 3 - progressLabel.Size.Height - progressLabelGames.Size.Height - progressLabelDLCs.Size.Height Height = programsGroupBox.Size.Height - 3 - progressLabel.Size.Height - progressLabelGames.Size.Height - progressLabelDLCs.Size.Height
- progressBar.Size.Height - progressBar.Size.Height
}; };
} }
@ -723,7 +723,7 @@ internal sealed partial class SelectForm : CustomForm
programsGroupBox.Size = programsGroupBox.Size with programsGroupBox.Size = programsGroupBox.Size with
{ {
Height = programsGroupBox.Size.Height + 3 + progressLabel.Size.Height + progressLabelGames.Size.Height + progressLabelDLCs.Size.Height Height = programsGroupBox.Size.Height + 3 + progressLabel.Size.Height + progressLabelGames.Size.Height + progressLabelDLCs.Size.Height
+ progressBar.Size.Height + progressBar.Size.Height
}; };
} }
@ -785,7 +785,11 @@ internal sealed partial class SelectForm : CustomForm
if (id == "PL") if (id == "PL")
{ {
_ = items.Add(new ToolStripSeparator()); _ = items.Add(new ToolStripSeparator());
async void EventHandler(object sender, EventArgs e) => await ParadoxLauncher.Repair(this, selection); async void EventHandler(object sender, EventArgs e)
{
_ = await ParadoxLauncher.Repair(this, selection);
Program.Canceled = false;
}
_ = items.Add(new ContextMenuItem("Repair", "Command Prompt", EventHandler)); _ = items.Add(new ContextMenuItem("Repair", "Command Prompt", EventHandler));
} }
_ = items.Add(new ToolStripSeparator()); _ = items.Add(new ToolStripSeparator());
@ -890,11 +894,7 @@ internal sealed partial class SelectForm : CustomForm
private void OnAccept(bool uninstall = false) private void OnAccept(bool uninstall = false)
{ {
if (Selection.All.IsEmpty) if (Selection.All.IsEmpty || !uninstall && ParadoxLauncher.DlcDialog(this))
return;
if (Selection.AllEnabled.Any(selection => !Program.AreDllsLockedDialog(this, selection)))
return;
if (!uninstall && ParadoxLauncher.DlcDialog(this))
return; return;
Hide(); Hide();
InstallForm form = new(uninstall); InstallForm form = new(uninstall);

View file

@ -155,7 +155,7 @@ internal sealed partial class UpdateForm : CustomForm
long bytesRead = 0; long bytesRead = 0;
int newBytes; int newBytes;
while (cancellation is not null && !Program.Canceled while (cancellation is not null && !Program.Canceled
&& (newBytes = await download.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellation.Token)) != 0) && (newBytes = await download.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellation.Token)) != 0)
{ {
if (cancellation is null || Program.Canceled) if (cancellation is null || Program.Canceled)
throw new TaskCanceledException(); throw new TaskCanceledException();

View file

@ -12,11 +12,7 @@ namespace CreamInstaller.Platforms.Paradox;
internal static class ParadoxLauncher internal static class ParadoxLauncher
{ {
public enum RepairResult public enum RepairResult { Failure = -1, Unnecessary = 0, Success }
{
ProgramRunning = -2, Failure, Unnecessary = 0,
Success
}
private static string installPath; private static string installPath;
@ -61,26 +57,23 @@ internal static class ParadoxLauncher
internal static async Task<RepairResult> Repair(Form form, Selection selection) internal static async Task<RepairResult> Repair(Form form, Selection selection)
{ {
InstallForm installForm = form as InstallForm; InstallForm installForm = form as InstallForm;
if (!Program.AreDllsLockedDialog(form, selection)) using DialogForm dialogForm = new(form);
return form is InstallForm
? throw new CustomMessageException("Repair failed! One or more DLLs crucial to unlocker installation are locked!")
: RepairResult.ProgramRunning;
bool smokeInstalled = false; bool smokeInstalled = false;
byte[] steamOriginalSdk32 = null; byte[] steamOriginalSdk32 = null;
byte[] steamOriginalSdk64 = null; byte[] steamOriginalSdk64 = null;
bool screamInstalled = false; bool screamInstalled = false;
byte[] epicOriginalSdk32 = null; byte[] epicOriginalSdk32 = null;
byte[] epicOriginalSdk64 = null; byte[] epicOriginalSdk64 = null;
foreach (string directory in selection.DllDirectories) foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{ {
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Any(pair => pair.path.FileExists() && pair.path.IsResourceFile()); .Any(pair => pair.path.FileExists() && pair.path.IsResourceFile());
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config, directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
out string config, out _, out _, out _); out string config, out _, out _, out _);
smokeInstalled = smokeInstalled || api32_o.FileExists() || api64_o.FileExists() smokeInstalled = smokeInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (old_config.FileExists() || config.FileExists()) && !koaloaderInstalled || (old_config.FileExists() || config.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32) || api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64); || api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
await SmokeAPI.Uninstall(directory, deleteOthers: false); await SmokeAPI.Uninstall(directory, deleteOthers: false);
if (steamOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.Steamworks32)) if (steamOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.Steamworks32))
steamOriginalSdk32 = api32.ReadFileBytes(true); steamOriginalSdk32 = api32.ReadFileBytes(true);
@ -88,20 +81,19 @@ internal static class ParadoxLauncher
steamOriginalSdk64 = api64.ReadFileBytes(true); steamOriginalSdk64 = api64.ReadFileBytes(true);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string log); directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string log);
screamInstalled = screamInstalled || api32_o.FileExists() || api64_o.FileExists() screamInstalled = screamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (config.FileExists() || log.FileExists()) && !koaloaderInstalled || (config.FileExists() || log.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32) || api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64); || api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
await ScreamAPI.Uninstall(directory, deleteOthers: false); await ScreamAPI.Uninstall(directory, deleteOthers: false);
if (epicOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)) if (epicOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
epicOriginalSdk32 = api32.ReadFileBytes(true); epicOriginalSdk32 = api32.ReadFileBytes(true);
if (epicOriginalSdk64 is null && api64.FileExists() && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64)) if (epicOriginalSdk64 is null && api64.FileExists() && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64))
epicOriginalSdk64 = api64.ReadFileBytes(true); epicOriginalSdk64 = api64.ReadFileBytes(true);
} }
using DialogForm dialogForm = new(form);
if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null) if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null)
{ {
bool neededRepair = false; bool neededRepair = false;
foreach (string directory in selection.DllDirectories) foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{ {
directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _, out _, out _); directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _, out _, out _);
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32)) if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
@ -134,27 +126,36 @@ internal static class ParadoxLauncher
if (screamInstalled) if (screamInstalled)
await ScreamAPI.Install(directory, selection, generateConfig: false); await ScreamAPI.Install(directory, selection, generateConfig: false);
} }
if (neededRepair) if (!Program.Canceled)
{ {
if (neededRepair)
{
if (installForm is not null)
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
else
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", customFormText: "Paradox Launcher");
return RepairResult.Success;
}
if (installForm is not null) if (installForm is not null)
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success); installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
else else
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", customFormText: "Paradox Launcher"); _ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
return RepairResult.Success; return RepairResult.Unnecessary;
} }
if (installForm is not null) }
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success); if (Program.Canceled)
else {
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher"); _ = form is InstallForm
return RepairResult.Unnecessary; ? throw new CustomMessageException("Repair failed! The operation was canceled.")
: dialogForm.Show(SystemIcons.Error, "Paradox Launcher repair failed! The operation was canceled.", customFormText: "Paradox Launcher");
return RepairResult.Failure;
} }
_ = form is InstallForm _ = form is InstallForm
? throw new CustomMessageException("Repair failed! " + "An original Steamworks and/or Epic Online Services file could not be found. " ? throw new CustomMessageException("Repair failed! " + "An original Steamworks and/or Epic Online Services file could not be found. "
+ "You will likely have to reinstall Paradox Launcher to fix this issue.") + "You will likely have to reinstall Paradox Launcher to fix this issue.")
: dialogForm.Show(SystemIcons.Error, : dialogForm.Show(SystemIcons.Error,
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found." "Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", + "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", customFormText: "Paradox Launcher");
customFormText: "Paradox Launcher");
return RepairResult.Failure; return RepairResult.Failure;
} }
} }

View file

@ -42,7 +42,7 @@ internal static class SteamCMD
private static string GetArguments(string appId) private static string GetArguments(string appId)
=> AttemptCount.TryGetValue(appId, out int attempts) => AttemptCount.TryGetValue(appId, out int attempts)
? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} " ? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} "
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit" + string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
: $"+login anonymous +app_info_print {appId} +quit"; : $"+login anonymous +app_info_print {appId} +quit";
private static async Task<string> Run(string appId) private static async Task<string> Run(string appId)
@ -129,7 +129,7 @@ internal static class SteamCMD
try try
{ {
byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip")); byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"));
file.WriteResource(ArchivePath); _ = file.WriteResource(ArchivePath);
ArchivePath.ExtractZip(DirectoryPath); ArchivePath.ExtractZip(DirectoryPath);
ArchivePath.DeleteFile(); ArchivePath.DeleteFile();
break; break;

View file

@ -31,7 +31,7 @@ internal static class SteamLibrary
if (Program.Canceled) if (Program.Canceled)
return games; return games;
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory( foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory(
libraryDirectory)).Where(game => games.All(_game => _game.appId != game.appId))) libraryDirectory)).Where(game => games.All(_game => _game.appId != game.appId)))
games.Add(game); games.Add(game);
} }
return games; return games;

View file

@ -71,7 +71,7 @@ internal static class SteamStore
(Exception e) (Exception e)
{ {
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "") DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Unsuccessful serialization (" + e.Message + ")"); + ": Unsuccessful serialization (" + e.Message + ")");
} }
#else #else
{ {
@ -82,13 +82,13 @@ internal static class SteamStore
} }
#if DEBUG #if DEBUG
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "") DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response data null (" + app.Value.ToString(Formatting.None) + ")"); + ": Response data null (" + app.Value.ToString(Formatting.None) + ")");
#endif #endif
} }
#if DEBUG #if DEBUG
else else
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "") DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response details null (" + app.Value.ToString(Formatting.None) + ")"); + ": Response details null (" + app.Value.ToString(Formatting.None) + ")");
#endif #endif
} }
catch catch
@ -96,7 +96,7 @@ internal static class SteamStore
(Exception e) (Exception e)
{ {
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "") DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Unsuccessful deserialization (" + e.Message + ")"); + ": Unsuccessful deserialization (" + e.Message + ")");
} }
#else #else
{ {
@ -106,7 +106,7 @@ internal static class SteamStore
#if DEBUG #if DEBUG
else else
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "") DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response deserialization null"); + ": Response deserialization null");
#endif #endif
} }
else else

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
@ -39,27 +38,7 @@ internal static class Program
internal static bool IsGameBlocked(string name, string directory = null) internal static bool IsGameBlocked(string name, string directory = null)
=> BlockProtectedGames && (ProtectedGames.Contains(name) || directory is not null && !ProtectedGameDirectoryExceptions.Contains(name) => BlockProtectedGames && (ProtectedGames.Contains(name) || directory is not null && !ProtectedGameDirectoryExceptions.Contains(name)
&& ProtectedGameDirectories.Any(path && ProtectedGameDirectories.Any(path => (directory + path).DirectoryExists()));
=> (directory + path).DirectoryExists()));
internal static bool AreDllsLockedDialog(Form form, Selection selection)
{
while (true)
{
if (selection.AreDllsLocked)
{
using DialogForm dialogForm = new(form);
if (dialogForm.Show(SystemIcons.Error,
$"ERROR: One or more DLLs crucial to unlocker installation are locked for {selection.Name}!"
+ "\n\nPlease close the program/game or resolve your anti-virus and press retry to continue . . . ", "Retry", "Cancel")
== DialogResult.OK)
continue;
}
else
return true;
return false;
}
}
[STAThread] [STAThread]
private static void Main() private static void Main()

View file

@ -24,11 +24,11 @@ internal static class Koaloader
internal static IEnumerable<string> GetKoaloaderProxies(this string directory) internal static IEnumerable<string> GetKoaloaderProxies(this string directory)
=> from resource in EmbeddedResources => from resource in EmbeddedResources
select resource[(resource.IndexOf('.') + 1)..] select resource[(resource.IndexOf('.') + 1)..]
into resource into resource
select resource[(resource.IndexOf('.') + 1)..] select resource[(resource.IndexOf('.') + 1)..]
into resource into resource
select directory + @"\" + resource; select directory + @"\" + resource;
internal static void GetKoaloaderComponents(this string directory, out string old_config, out string config) internal static void GetKoaloaderComponents(this string directory, out string old_config, out string config)
{ {
@ -137,15 +137,15 @@ internal static class Koaloader
{ {
directory.GetKoaloaderComponents(out string old_config, out string config); directory.GetKoaloaderComponents(out string old_config, out string config);
foreach (string proxyPath in directory.GetKoaloaderProxies().Where(proxyPath foreach (string proxyPath in directory.GetKoaloaderProxies().Where(proxyPath
=> proxyPath.FileExists() && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader))) => proxyPath.FileExists() && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
{ {
proxyPath.DeleteFile(); proxyPath.DeleteFile(true);
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
} }
foreach ((string unlocker, string path) in AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) foreach ((string unlocker, string path) in AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Where(pair => pair.path.FileExists() && pair.path.IsResourceFile())) .Where(pair => pair.path.FileExists() && pair.path.IsResourceFile()))
{ {
path.DeleteFile(); path.DeleteFile(true);
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
} }
if (deleteConfig && old_config.FileExists()) if (deleteConfig && old_config.FileExists())
@ -174,7 +174,7 @@ internal static class Koaloader
string path = directory + @"\" + proxy + ".dll"; string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetKoaloaderProxies().Where(p => p != path && p.FileExists() && p.IsResourceFile(ResourceIdentifier.Koaloader))) foreach (string _path in directory.GetKoaloaderProxies().Where(p => p != path && p.FileExists() && p.IsResourceFile(ResourceIdentifier.Koaloader)))
{ {
_path.DeleteFile(); _path.DeleteFile(true);
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false);
} }
if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Koaloader)) if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Koaloader))

View file

@ -464,20 +464,21 @@ internal static class Resources
} }
} }
internal static void WriteResource(this byte[] resource, string filePath) internal static bool WriteResource(this byte[] resource, string filePath)
{ {
while (!Program.Canceled) while (!Program.Canceled)
try try
{ {
using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write); using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write);
fileStream.Write(resource); fileStream.Write(resource);
break; return true;
} }
catch (Exception e) catch (Exception e)
{ {
if (filePath.IOWarn("Failed to write a crucial resource", e) is not DialogResult.OK) if (filePath.IOWarn("Failed to write a crucial resource", e) is not DialogResult.OK)
break; break;
} }
return false;
} }
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => NativeImports.GetBinaryType(path, out binaryType); internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => NativeImports.GetBinaryType(path, out binaryType);
@ -504,8 +505,7 @@ internal static class Resources
if (Program.Canceled) if (Program.Canceled)
return null; return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
&& binaryType is BinaryType.BIT64)
executables.Add((path, binaryType)); executables.Add((path, binaryType));
} }
foreach (string path in rootDirectory.EnumerateDirectory("*.exe", true)) foreach (string path in rootDirectory.EnumerateDirectory("*.exe", true))
@ -513,8 +513,7 @@ internal static class Resources
if (Program.Canceled) if (Program.Canceled)
return null; return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
&& binaryType is BinaryType.BIT32)
executables.Add((path, binaryType)); executables.Add((path, binaryType));
} }
return executables.Count > 0 ? executables : null; return executables.Count > 0 ? executables : null;
@ -524,10 +523,9 @@ internal static class Resources
{ {
string subPath = path[rootDirectory.Length..].ToUpperInvariant(); string subPath = path[rootDirectory.Length..].ToUpperInvariant();
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT") return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) || subPath.Contains("HELPER") || subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) || subPath.Contains("HELPER") || subPath.Contains("CEFPROCESS")
|| subPath.Contains("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("MODDING")
|| subPath.Contains("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("ANTICHEAT");
|| subPath.Contains("ANTICHEAT");
} }
internal static async Task<HashSet<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform) internal static async Task<HashSet<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform)

View file

@ -108,7 +108,7 @@ internal static class ScreamAPI
{ {
if (api32.FileExists()) if (api32.FileExists())
{ {
api32.DeleteFile(); api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
} }
api32_o.MoveFile(api32!); api32_o.MoveFile(api32!);
@ -118,7 +118,7 @@ internal static class ScreamAPI
{ {
if (api64.FileExists()) if (api64.FileExists())
{ {
api64.DeleteFile(); api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
} }
api64_o.MoveFile(api64!); api64_o.MoveFile(api64!);
@ -144,7 +144,7 @@ internal static class ScreamAPI
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _); directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _);
if (api32.FileExists() && !api32_o.FileExists()) if (api32.FileExists() && !api32_o.FileExists())
{ {
api32.MoveFile(api32_o!); api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
} }
if (api32_o.FileExists()) if (api32_o.FileExists())
@ -154,7 +154,7 @@ internal static class ScreamAPI
} }
if (api64.FileExists() && !api64_o.FileExists()) if (api64.FileExists() && !api64_o.FileExists())
{ {
api64.MoveFile(api64_o!); api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
} }
if (api64_o.FileExists()) if (api64_o.FileExists())

View file

@ -157,7 +157,7 @@ internal static class SmokeAPI
{ {
if (api32.FileExists()) if (api32.FileExists())
{ {
api32.DeleteFile(); api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
} }
api32_o.MoveFile(api32!); api32_o.MoveFile(api32!);
@ -167,7 +167,7 @@ internal static class SmokeAPI
{ {
if (api64.FileExists()) if (api64.FileExists())
{ {
api64.DeleteFile(); api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
} }
api64_o.MoveFile(api64!); api64_o.MoveFile(api64!);
@ -214,7 +214,7 @@ internal static class SmokeAPI
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _, out _, out _, out _); directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _, out _, out _, out _);
if (api32.FileExists() && !api32_o.FileExists()) if (api32.FileExists() && !api32_o.FileExists())
{ {
api32.MoveFile(api32_o!); api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
} }
if (api32_o.FileExists()) if (api32_o.FileExists())
@ -224,7 +224,7 @@ internal static class SmokeAPI
} }
if (api64.FileExists() && !api64_o.FileExists()) if (api64.FileExists() && !api64_o.FileExists())
{ {
api64.MoveFile(api64_o!); api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
} }
if (api64_o.FileExists()) if (api64_o.FileExists())

View file

@ -77,7 +77,7 @@ internal static class UplayR1
{ {
if (api32.FileExists()) if (api32.FileExists())
{ {
api32.DeleteFile(); api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false);
} }
api32_o.MoveFile(api32!); api32_o.MoveFile(api32!);
@ -87,7 +87,7 @@ internal static class UplayR1
{ {
if (api64.FileExists()) if (api64.FileExists())
{ {
api64.DeleteFile(); api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false);
} }
api64_o.MoveFile(api64!); api64_o.MoveFile(api64!);
@ -112,7 +112,7 @@ internal static class UplayR1
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _); directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _);
if (api32.FileExists() && !api32_o.FileExists()) if (api32.FileExists() && !api32_o.FileExists())
{ {
api32.MoveFile(api32_o!); api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
} }
if (api32_o.FileExists()) if (api32_o.FileExists())
@ -122,7 +122,7 @@ internal static class UplayR1
} }
if (api64.FileExists() && !api64_o.FileExists()) if (api64.FileExists() && !api64_o.FileExists())
{ {
api64.MoveFile(api64_o!); api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
} }
if (api64_o.FileExists()) if (api64_o.FileExists())

View file

@ -83,7 +83,7 @@ internal static class UplayR2
string api = old_api32.FileExists() ? old_api32 : api32; string api = old_api32.FileExists() ? old_api32 : api32;
if (api.FileExists()) if (api.FileExists())
{ {
api.DeleteFile(); api.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
} }
api32_o.MoveFile(api!); api32_o.MoveFile(api!);
@ -94,7 +94,7 @@ internal static class UplayR2
string api = old_api64.FileExists() ? old_api64 : api64; string api = old_api64.FileExists() ? old_api64 : api64;
if (api.FileExists()) if (api.FileExists())
{ {
api.DeleteFile(); api.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
} }
api64_o.MoveFile(api!); api64_o.MoveFile(api!);
@ -121,7 +121,7 @@ internal static class UplayR2
string api = old_api32.FileExists() ? old_api32 : api32; string api = old_api32.FileExists() ? old_api32 : api32;
if (api.FileExists() && !api32_o.FileExists()) if (api.FileExists() && !api32_o.FileExists())
{ {
api.MoveFile(api32_o!); api.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
} }
if (api32_o.FileExists()) if (api32_o.FileExists())
@ -132,7 +132,7 @@ internal static class UplayR2
api = old_api64.FileExists() ? old_api64 : api64; api = old_api64.FileExists() ? old_api64 : api64;
if (api.FileExists() && !api64_o.FileExists()) if (api.FileExists() && !api64_o.FileExists())
{ {
api.MoveFile(api64_o!); api.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false); installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
} }
if (api64_o.FileExists()) if (api64_o.FileExists())

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using CreamInstaller.Forms; using CreamInstaller.Forms;
using CreamInstaller.Resources;
using CreamInstaller.Utility; using CreamInstaller.Utility;
using static CreamInstaller.Resources.Resources; using static CreamInstaller.Resources.Resources;
@ -62,47 +61,6 @@ internal sealed class Selection : IEquatable<Selection>
internal IEnumerable<SelectionDLC> DLC => SelectionDLC.All.Keys.Where(dlc => dlc.Selection.Equals(this)); internal IEnumerable<SelectionDLC> DLC => SelectionDLC.All.Keys.Where(dlc => dlc.Selection.Equals(this));
internal bool AreDllsLocked
{
get
{
foreach (string directory in DllDirectories)
{
if (Platform is Platform.Steam or Platform.Paradox)
{
directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked())
return true;
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out string old_config, out config, out string old_log,
out string log, out string cache);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || old_config.FileLocked()
|| config.FileLocked() || old_log.FileLocked() || log.FileLocked() || cache.FileLocked())
return true;
}
if (Platform is Platform.Epic or Platform.Paradox)
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
out string log);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
}
if (Platform is Platform.Ubisoft)
{
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
out string log);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config,
out log);
if (old_api32.FileLocked() || old_api64.FileLocked() || api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked()
|| api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
}
}
return false;
}
}
public bool Equals(Selection other) => other is not null && (ReferenceEquals(this, other) || Id == other.Id && Platform == other.Platform); public bool Equals(Selection other) => other is not null && (ReferenceEquals(this, other) || Id == other.Id && Platform == other.Platform);
internal static Selection GetOrCreate(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories, internal static Selection GetOrCreate(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories,

View file

@ -21,7 +21,7 @@ internal static class ExceptionHandler
string[] stackTrace = e.StackTrace?.Split('\n'); string[] stackTrace = e.StackTrace?.Split('\n');
if (stackTrace is not null && stackTrace.Length > 0) if (stackTrace is not null && stackTrace.Length > 0)
{ {
_ = output.Append(e.GetType() + (": " + e.Message)); _ = output.Append($"[{e.HResult & 0x0000FFFF}] {e.GetType()}: {e.Message}");
foreach (string line in stackTrace) foreach (string line in stackTrace)
{ {
int atNum = line.IndexOf("at ", StringComparison.Ordinal); int atNum = line.IndexOf("at ", StringComparison.Ordinal);

View file

@ -12,21 +12,6 @@ namespace CreamInstaller.Utility;
internal static class SafeIO internal static class SafeIO
{ {
internal static bool FileLocked(this string filePath)
{
if (!FileExists(filePath))
return false;
try
{
File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None).Close();
}
catch
{
return true;
}
return false;
}
internal static bool DirectoryExists(this string directoryPath) => Directory.Exists(directoryPath); internal static bool DirectoryExists(this string directoryPath) => Directory.Exists(directoryPath);
internal static void CreateDirectory(this string directoryPath, bool crucial = false, Form form = null) internal static void CreateDirectory(this string directoryPath, bool crucial = false, Form form = null)
@ -37,7 +22,7 @@ internal static class SafeIO
try try
{ {
_ = Directory.CreateDirectory(directoryPath); _ = Directory.CreateDirectory(directoryPath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -54,7 +39,7 @@ internal static class SafeIO
try try
{ {
Directory.Move(directoryPath, newDirectoryPath); Directory.Move(directoryPath, newDirectoryPath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -71,12 +56,12 @@ internal static class SafeIO
try try
{ {
Directory.Delete(directoryPath, true); Directory.Delete(directoryPath, true);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
if (!crucial || !directoryPath.DirectoryExists() if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to delete a crucial directory", e, form) is not DialogResult.OK) || directoryPath.IOWarn("Failed to delete a crucial directory", e, form) is not DialogResult.OK)
break; break;
} }
} }
@ -96,7 +81,7 @@ internal static class SafeIO
catch (Exception e) catch (Exception e)
{ {
if (!crucial || !directoryPath.DirectoryExists() if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's files", e, form) is not DialogResult.OK) || directoryPath.IOWarn("Failed to enumerate a crucial directory's files", e, form) is not DialogResult.OK)
break; break;
} }
return Enumerable.Empty<string>(); return Enumerable.Empty<string>();
@ -117,7 +102,7 @@ internal static class SafeIO
catch (Exception e) catch (Exception e)
{ {
if (!crucial || !directoryPath.DirectoryExists() if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's subdirectories", e, form) is not DialogResult.OK) || directoryPath.IOWarn("Failed to enumerate a crucial directory's subdirectories", e, form) is not DialogResult.OK)
break; break;
} }
return Enumerable.Empty<string>(); return Enumerable.Empty<string>();
@ -148,7 +133,7 @@ internal static class SafeIO
try try
{ {
File.Move(filePath, newFilePath); File.Move(filePath, newFilePath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -165,7 +150,7 @@ internal static class SafeIO
try try
{ {
File.Delete(filePath); File.Delete(filePath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -214,7 +199,7 @@ internal static class SafeIO
try try
{ {
File.WriteAllText(filePath, text, Encoding.UTF8); File.WriteAllText(filePath, text, Encoding.UTF8);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -231,7 +216,7 @@ internal static class SafeIO
try try
{ {
ZipFile.ExtractToDirectory(archivePath, destinationPath); ZipFile.ExtractToDirectory(archivePath, destinationPath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -251,11 +236,26 @@ internal static class SafeIO
private static DialogResult IOWarnInternal(this string filePath, string message, Exception e, Form form = null) private static DialogResult IOWarnInternal(this string filePath, string message, Exception e, Form form = null)
{ {
using DialogForm dialogForm = new(form); using DialogForm dialogForm = new(form);
string description = message + ": " + filePath.ResolvePath() + "\n\n"; string description = message + ": " + (filePath.ResolvePath() ?? filePath) + "\n\n";
if (e is IOException && (e.HResult & 0x0000FFFF) == 225) // virus or potentially unwanted software int code = e.HResult & 0x0000FFFF;
description += "Please resolve your anti-virus and press retry to continue . . . "; switch (code) // https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
else {
description += e.FormatException(); case 5: // ERROR_ACCESS_DENIED
return dialogForm.Show(SystemIcons.Warning, description, "Retry", "OK"); case 32: // ERROR_SHARING_VIOLATION
case 33: // ERROR_LOCK_VIOLATION
description += "Please close the program/game and press retry to continue . . . ";
break;
case 225: // ERROR_VIRUS_INFECTED
case 226: // ERROR_VIRUS_DELETED
description += "Please resolve your anti-virus and press retry to continue . . . ";
break;
default:
description += e.FormatException();
break;
}
DialogResult result = dialogForm.Show(SystemIcons.Warning, description, "Retry", "Cancel");
if (result is not DialogResult.OK)
Program.Canceled = true;
return result;
} }
} }