mirror of
https://github.com/FroggMaster/CreamInstaller.git
synced 2026-06-12 11:01:23 -07:00
Add Extra Protection Option for CreamAPI Closes #21
- Adds the ability to enable ExtraProtection for CreamAPI, this is required for games that check the integrity of the steam_api.dll Related Work Items: #2, #21
This commit is contained in:
@@ -14,8 +14,10 @@ namespace CreamInstaller.Components;
|
||||
internal sealed class CustomTreeView : TreeView
|
||||
{
|
||||
private const string ProxyToggleString = "Proxy";
|
||||
private const string ExtraProtectionToggleString = "Extra Protection";
|
||||
|
||||
private readonly Dictionary<Selection, Rectangle> checkBoxBounds = [];
|
||||
private readonly Dictionary<Selection, Rectangle> extraProtectionCheckBoxBounds = [];
|
||||
private readonly Dictionary<Selection, Rectangle> comboBoxBounds = [];
|
||||
|
||||
private readonly Dictionary<TreeNode, Rectangle> selectionBounds = [];
|
||||
@@ -62,6 +64,7 @@ internal sealed class CustomTreeView : TreeView
|
||||
private void OnInvalidated(object sender, EventArgs e)
|
||||
{
|
||||
checkBoxBounds.Clear();
|
||||
extraProtectionCheckBoxBounds.Clear();
|
||||
comboBoxBounds.Clear();
|
||||
selectionBounds.Clear();
|
||||
backBrush?.Dispose();
|
||||
@@ -254,6 +257,42 @@ internal sealed class CustomTreeView : TreeView
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
|
||||
if (!Program.UseSmokeAPI)
|
||||
{
|
||||
CheckBoxState extraProtState = selection.UseExtraProtection
|
||||
? (Enabled ? CheckBoxState.CheckedNormal : CheckBoxState.CheckedDisabled)
|
||||
: (Enabled ? CheckBoxState.UncheckedNormal : CheckBoxState.UncheckedDisabled);
|
||||
size = CheckBoxRenderer.GetGlyphSize(graphics, extraProtState);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
Rectangle extraProtCheckBoxBounds = bounds;
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
point = new(bounds.Left, bounds.Top + bounds.Height / 2 - size.Height / 2 - 1);
|
||||
if (dark)
|
||||
ThemeManager.DrawDarkCheckBox(graphics, point, size, selection.UseExtraProtection, Enabled);
|
||||
else
|
||||
CheckBoxRenderer.DrawCheckBox(graphics, point, extraProtState);
|
||||
|
||||
text = ExtraProtectionToggleString;
|
||||
size = TextRenderer.MeasureText(graphics, text, font);
|
||||
int leftEP = 1;
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width + leftEP };
|
||||
selectionBounds = new(selectionBounds.Location, selectionBounds.Size + bounds.Size with { Height = 0 });
|
||||
extraProtCheckBoxBounds = new(extraProtCheckBoxBounds.Location, extraProtCheckBoxBounds.Size + bounds.Size with { Height = 0 });
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
point = new(bounds.Location.X - 1 + leftEP, bounds.Location.Y + 1);
|
||||
TextRenderer.DrawText(graphics, text, font, point,
|
||||
Enabled ? ThemeManager.CustomTreeViewProxyColor : ThemeManager.CustomTreeViewDisabledProxyColor,
|
||||
TextFormatFlags.Default);
|
||||
|
||||
extraProtectionCheckBoxBounds[selection] = RectangleToClient(extraProtCheckBoxBounds);
|
||||
|
||||
// Add spacing before proxy checkbox
|
||||
size = new(4, 0);
|
||||
bounds = bounds with { X = bounds.X + bounds.Width, Width = size.Width };
|
||||
graphics.FillRectangle(brush, bounds);
|
||||
}
|
||||
|
||||
CheckBoxState proxyState = selection.UseProxy
|
||||
? (Enabled ? CheckBoxState.CheckedNormal : CheckBoxState.CheckedDisabled)
|
||||
: (Enabled ? CheckBoxState.UncheckedNormal : CheckBoxState.UncheckedDisabled);
|
||||
@@ -399,5 +438,15 @@ internal sealed class CustomTreeView : TreeView
|
||||
selectForm?.OnProxyChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Selection, Rectangle> pair in extraProtectionCheckBoxBounds)
|
||||
if (!Selection.All.ContainsKey(pair.Key))
|
||||
_ = extraProtectionCheckBoxBounds.Remove(pair.Key);
|
||||
else if (pair.Value.Contains(clickPoint))
|
||||
{
|
||||
pair.Key.UseExtraProtection = !pair.Key.UseExtraProtection;
|
||||
selectForm?.OnExtraProtectionChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1065,13 +1065,18 @@ internal sealed partial class SelectForm : CustomForm
|
||||
|
||||
private static bool AreProxySelectionsDefault() => Selection.All.Keys.All(selection => !selection.UseProxy);
|
||||
|
||||
private static bool AreExtraProtectionSelectionsDefault() => Selection.All.Keys.All(selection => !selection.UseExtraProtection);
|
||||
|
||||
private bool CanSaveDlc() =>
|
||||
installButton.Enabled && (ProgramData.ReadDlcChoices().Any() || !AreSelectionsDefault());
|
||||
|
||||
private static bool CanSaveProxy() =>
|
||||
ProgramData.ReadProxyChoices().Any() || !AreProxySelectionsDefault();
|
||||
|
||||
private bool CanSaveSelections() => CanSaveDlc() || CanSaveProxy();
|
||||
private static bool CanSaveExtraProtection() =>
|
||||
ProgramData.ReadExtraProtectionChoices().Any() || !AreExtraProtectionSelectionsDefault();
|
||||
|
||||
private bool CanSaveSelections() => CanSaveDlc() || CanSaveProxy() || CanSaveExtraProtection();
|
||||
|
||||
private void OnSaveSelections(object sender, EventArgs e)
|
||||
{
|
||||
@@ -1099,6 +1104,17 @@ internal sealed partial class SelectForm : CustomForm
|
||||
|
||||
ProgramData.WriteProxyChoices(proxyChoices);
|
||||
|
||||
List<(Platform platform, string id)> extraProtectionChoices =
|
||||
ProgramData.ReadExtraProtectionChoices().ToList();
|
||||
foreach (Selection selection in Selection.All.Keys)
|
||||
{
|
||||
_ = extraProtectionChoices.RemoveAll(c => c.platform == selection.Platform && c.id == selection.Id);
|
||||
if (selection.UseExtraProtection)
|
||||
extraProtectionChoices.Add((selection.Platform, selection.Id));
|
||||
}
|
||||
|
||||
ProgramData.WriteExtraProtectionChoices(extraProtectionChoices);
|
||||
|
||||
loadButton.Enabled = CanLoadSelections();
|
||||
saveButton.Enabled = CanSaveSelections();
|
||||
}
|
||||
@@ -1107,7 +1123,9 @@ internal sealed partial class SelectForm : CustomForm
|
||||
|
||||
private static bool CanLoadProxy() => ProgramData.ReadProxyChoices().Any();
|
||||
|
||||
private static bool CanLoadSelections() => CanLoadDlc() || CanLoadProxy();
|
||||
private static bool CanLoadExtraProtection() => ProgramData.ReadExtraProtectionChoices().Any();
|
||||
|
||||
private static bool CanLoadSelections() => CanLoadDlc() || CanLoadProxy() || CanLoadExtraProtection();
|
||||
|
||||
private void OnLoadSelections(object sender, EventArgs e)
|
||||
{
|
||||
@@ -1149,6 +1167,14 @@ internal sealed partial class SelectForm : CustomForm
|
||||
}
|
||||
|
||||
ProgramData.WriteProxyChoices(proxyChoices);
|
||||
|
||||
List<(Platform platform, string id)> extraProtectionChoices =
|
||||
ProgramData.ReadExtraProtectionChoices().ToList();
|
||||
foreach (Selection selection in Selection.All.Keys)
|
||||
selection.UseExtraProtection = extraProtectionChoices.Any(c =>
|
||||
c.platform == selection.Platform && c.id == selection.Id);
|
||||
|
||||
ProgramData.WriteExtraProtectionChoices(extraProtectionChoices);
|
||||
loadButton.Enabled = CanLoadSelections();
|
||||
|
||||
OnProxyChanged();
|
||||
@@ -1158,7 +1184,9 @@ internal sealed partial class SelectForm : CustomForm
|
||||
|
||||
private static bool CanResetProxy() => !AreProxySelectionsDefault();
|
||||
|
||||
private bool CanResetSelections() => CanResetDlc() || CanResetProxy();
|
||||
private static bool CanResetExtraProtection() => !AreExtraProtectionSelectionsDefault();
|
||||
|
||||
private bool CanResetSelections() => CanResetDlc() || CanResetProxy() || CanResetExtraProtection();
|
||||
|
||||
private void OnResetSelections(object sender, EventArgs e)
|
||||
{
|
||||
@@ -1172,6 +1200,7 @@ internal sealed partial class SelectForm : CustomForm
|
||||
{
|
||||
selection.UseProxy = false;
|
||||
selection.Proxy = null;
|
||||
selection.UseExtraProtection = false;
|
||||
}
|
||||
|
||||
OnProxyChanged();
|
||||
@@ -1187,6 +1216,13 @@ internal sealed partial class SelectForm : CustomForm
|
||||
proxyAllCheckBox.CheckedChanged += OnProxyAllCheckBoxChanged;
|
||||
}
|
||||
|
||||
internal void OnExtraProtectionChanged()
|
||||
{
|
||||
selectionTreeView.Invalidate();
|
||||
saveButton.Enabled = CanSaveSelections();
|
||||
resetButton.Enabled = CanResetSelections();
|
||||
}
|
||||
|
||||
private void OnBlockProtectedGamesCheckBoxChanged(object sender, EventArgs e)
|
||||
{
|
||||
Program.BlockProtectedGames = blockedGamesCheckBox.Checked;
|
||||
|
||||
@@ -41,14 +41,15 @@ internal static class CreamAPI
|
||||
config.CreateFile(true, installForm)?.Close();
|
||||
StreamWriter writer = new(config, true, Encoding.Default);
|
||||
WriteConfig(writer, selection.Name, !int.TryParse(selection.Id, out _) ? "0" : selection.Id,
|
||||
new(dlc.ToDictionary(_dlc => _dlc.Id, _dlc => _dlc.Name), PlatformIdComparer.String), installForm);
|
||||
new(dlc.ToDictionary(_dlc => _dlc.Id, _dlc => _dlc.Name), PlatformIdComparer.String),
|
||||
selection.UseExtraProtection, installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
private static void WriteConfig(StreamWriter writer, string name, string appId,
|
||||
SortedList<string, string> dlc, InstallForm installForm = null)
|
||||
SortedList<string, string> dlc, bool extraProtection = false, InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine($"; {name}");
|
||||
writer.WriteLine("[steam]");
|
||||
@@ -58,7 +59,7 @@ internal static class CreamAPI
|
||||
writer.WriteLine("unlockall = false");
|
||||
writer.WriteLine("orgapi = steam_api_o.dll");
|
||||
writer.WriteLine("orgapi64 = steam_api64_o.dll");
|
||||
writer.WriteLine("extraprotection = false"); // we may want to set this on by default?
|
||||
writer.WriteLine($"extraprotection = {(extraProtection ? "true" : "false")}");
|
||||
writer.WriteLine("forceoffline = false");
|
||||
writer.WriteLine();
|
||||
writer.WriteLine("[steam_misc]"); // this line seems to be required in v5.3.0.0, or the config won't be read
|
||||
|
||||
@@ -34,6 +34,7 @@ internal sealed class Selection : IEquatable<Selection>
|
||||
internal readonly string RootDirectory;
|
||||
internal readonly TreeNode TreeNode;
|
||||
internal string Icon;
|
||||
internal bool UseExtraProtection;
|
||||
internal bool UseProxy;
|
||||
internal string Proxy;
|
||||
internal string Product;
|
||||
|
||||
@@ -29,6 +29,7 @@ internal static class ProgramData
|
||||
private static readonly string ProgramChoicesPath = DirectoryPath + @"\choices.json";
|
||||
private static readonly string DlcChoicesPath = DirectoryPath + @"\dlc.json";
|
||||
private static readonly string KoaloaderProxyChoicesPath = DirectoryPath + @"\proxies.json";
|
||||
private static readonly string ExtraProtectionChoicesPath = DirectoryPath + @"\extraprotection.json";
|
||||
|
||||
internal static readonly string LogPath = DirectoryPath + @"\scan.log";
|
||||
|
||||
@@ -229,4 +230,37 @@ internal static class ProgramData
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<(Platform platform, string id)> ReadExtraProtectionChoices()
|
||||
{
|
||||
if (ExtraProtectionChoicesPath.FileExists())
|
||||
try
|
||||
{
|
||||
if (JsonConvert.DeserializeObject(ExtraProtectionChoicesPath.ReadFile(),
|
||||
typeof(IEnumerable<(Platform platform, string id)>)) is
|
||||
IEnumerable<(Platform platform, string id)> choices)
|
||||
return choices;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
internal static void WriteExtraProtectionChoices(IEnumerable<(Platform platform, string id)> choices)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (choices is null || !choices.Any())
|
||||
ExtraProtectionChoicesPath.DeleteFile();
|
||||
else
|
||||
ExtraProtectionChoicesPath.WriteFile(JsonConvert.SerializeObject(choices));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user