mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
211 lines
7.7 KiB
C#
211 lines
7.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Security;
|
|
using Microsoft.Win32;
|
|
|
|
#nullable enable
|
|
|
|
namespace Wabbajack.Common.StoreHandlers
|
|
{
|
|
public class BethNetGame : AStoreGame
|
|
{
|
|
public override Game Game { get; internal set; }
|
|
public override StoreType Type { get; internal set; } = StoreType.BethNet;
|
|
}
|
|
|
|
public class BethNetHandler : AStoreHandler
|
|
{
|
|
public override StoreType Type { get; internal set; } = StoreType.BethNet;
|
|
|
|
private const string RegKey = @"SOFTWARE\WOW6432Node\bethesda softworks\Bethesda.net";
|
|
|
|
public AbsolutePath BethPath { get; set; }
|
|
private AbsolutePath Launcher => new RelativePath("BethesdaNetLauncher.exe").RelativeTo(BethPath);
|
|
private AbsolutePath GamesFolder => new RelativePath("games").RelativeTo(BethPath);
|
|
|
|
public override bool Init()
|
|
{
|
|
try
|
|
{
|
|
var key = Registry.LocalMachine.OpenSubKey(RegKey);
|
|
|
|
var pathKey = key?.GetValue("installLocation");
|
|
if (pathKey == null)
|
|
{
|
|
Utils.Error(new StoreException("Could not open the BethNetPath registry key!"));
|
|
return false;
|
|
}
|
|
|
|
var bethPath = pathKey.ToString() ?? string.Empty;
|
|
if (string.IsNullOrWhiteSpace(bethPath))
|
|
{
|
|
Utils.Error(new StoreException("Path to the BethNet Directory from registry is Null or Empty!"));
|
|
return false;
|
|
}
|
|
|
|
BethPath = (AbsolutePath)bethPath;
|
|
|
|
if (!BethPath.IsDirectory || !BethPath.Exists)
|
|
{
|
|
Utils.Error(new StoreException($"Path to the BethNet Directory from registry does not exists: {BethPath}"));
|
|
return false;
|
|
}
|
|
|
|
if (Launcher.Exists && Launcher.IsFile)
|
|
return true;
|
|
|
|
Utils.Error(new StoreException($"The BethNet Launcher could not be located: {Launcher}"));
|
|
return false;
|
|
}
|
|
catch (SecurityException se)
|
|
{
|
|
Utils.Error(se, "BethNetHandler could not read from registry!");
|
|
}
|
|
catch (UnauthorizedAccessException uae)
|
|
{
|
|
Utils.Error(uae, "BethNetHandler could not read from registry!");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool LoadAllGames()
|
|
{
|
|
List<BethNetGame> possibleGames = new List<BethNetGame>();
|
|
// games folder
|
|
|
|
if (!GamesFolder.Exists)
|
|
{
|
|
Utils.Error(new StoreException($"The GamesFolder for BethNet at {GamesFolder} does not exist!"));
|
|
return false;
|
|
}
|
|
|
|
if (GamesFolder.Exists && GamesFolder.IsDirectory)
|
|
{
|
|
GamesFolder.EnumerateDirectories(false).Do(d =>
|
|
{
|
|
var files = d.EnumerateFiles();
|
|
var game = GameRegistry.Games.Values
|
|
.FirstOrDefault(g => g.RequiredFiles.All(f =>
|
|
{
|
|
var absPath = new RelativePath(f).RelativeTo(d);
|
|
return files.Contains(absPath);
|
|
}));
|
|
|
|
if (game != null)
|
|
{
|
|
possibleGames.Add(new BethNetGame
|
|
{
|
|
Game = game.Game,
|
|
ID = game.BethNetID,
|
|
Name = game.Game.ToString(),
|
|
Path = d,
|
|
Type = StoreType.BethNet
|
|
});
|
|
}
|
|
else
|
|
{
|
|
Utils.Log($"BethNet Game at {d} is not supported!");
|
|
}
|
|
});
|
|
}
|
|
|
|
possibleGames.Do(g =>
|
|
{
|
|
try
|
|
{
|
|
var regString = g.Game.MetaData().RegString;
|
|
var regKey = Registry.LocalMachine.OpenSubKey(regString);
|
|
regString = @"HKEY_LOCAL_MACHINE\" + regString;
|
|
if (regKey == null)
|
|
{
|
|
Utils.Error(new StoreException($@"Could not open registry key at {regString}"));
|
|
return;
|
|
}
|
|
|
|
var pathValue = regKey.GetValue("Path");
|
|
var uninstallStringValue = regKey.GetValue("UninstallString");
|
|
|
|
if (pathValue == null || uninstallStringValue == null)
|
|
{
|
|
Utils.Error(new StoreException($@"Could not get Value from either {regString}\Path or UninstallString"));
|
|
return;
|
|
}
|
|
|
|
var path = pathValue.ToString() ?? string.Empty;
|
|
var uninstallString = uninstallStringValue.ToString() ?? string.Empty;
|
|
|
|
if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(uninstallString))
|
|
{
|
|
Utils.Error(new StoreException($@"Path or UninstallString is null or empty for {regString}!"));
|
|
return;
|
|
}
|
|
|
|
path = FixRegistryValue(path);
|
|
|
|
if ((AbsolutePath)path != g.Path)
|
|
{
|
|
Utils.Error(new StoreException($"Path from registry does not equal game path: {path} != {g.Path} at {regString}"));
|
|
return;
|
|
}
|
|
|
|
var split = uninstallString.Split("\"");
|
|
if (split.Length != 3)
|
|
{
|
|
Utils.Error(new StoreException($"UninstallString at {regString} can not be split into 3 parts!"));
|
|
return;
|
|
}
|
|
|
|
var updaterPath = (AbsolutePath)split[1];
|
|
var args = split[2].Trim();
|
|
|
|
if (!updaterPath.Exists)
|
|
{
|
|
Utils.Error(new StoreException($"UpdaterPath from {regString} does not exist at {updaterPath}"));
|
|
return;
|
|
}
|
|
|
|
if (updaterPath.Parent != BethPath)
|
|
{
|
|
Utils.Error(new StoreException($"Parent of UpdatePath from {regString} is not BethPath: {updaterPath.Parent} != {BethPath}"));
|
|
return;
|
|
}
|
|
|
|
if (!args.Equals($"bethesdanet://uninstall/{g.ID}", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
Utils.Error(new StoreException($"Uninstall arguments from {regString} is not valid: {args}"));
|
|
return;
|
|
}
|
|
|
|
Utils.Log($"Found BethNet game \"{g.Game}\" ({g.ID}) at {g.Path}");
|
|
|
|
Games.Add(g);
|
|
}
|
|
catch (SecurityException se)
|
|
{
|
|
Utils.Error(se, "BethNetHandler could not read from registry!");
|
|
}
|
|
catch (UnauthorizedAccessException uae)
|
|
{
|
|
Utils.Error(uae, "BethNetHandler could not read from registry!");
|
|
}
|
|
});
|
|
|
|
Utils.Log($"Total number of BethNet Games found: {Games.Count}");
|
|
|
|
return Games.Count != 0;
|
|
}
|
|
|
|
private static string FixRegistryValue(string value)
|
|
{
|
|
var s = value;
|
|
if (s.StartsWith("\""))
|
|
s = s[1..];
|
|
if (s.EndsWith("\""))
|
|
s = s[..^1];
|
|
return s;
|
|
}
|
|
}
|
|
}
|