From c65350f012966e7583f28d3d0ef476052c8db2cc Mon Sep 17 00:00:00 2001 From: Morten Aune Lyrstad <4653628+malware-dev@users.noreply.github.com> Date: Tue, 7 Sep 2021 19:48:36 +0200 Subject: [PATCH] Valve VDF change --- Source/DocGen.sln | 8 +- Source/DocGen2/DocGen2.csproj | 2 +- Source/MDK/MDKPackage.GeneratedInfo.cs | 2 +- Source/MDK/source.extension.vsixmanifest | 2 +- Source/MDKServices/DTEExtensions.cs | 1 + Source/MDKServices/HealthAnalysis.cs | 22 ++++- .../MDKProjectProperties.GeneratedInfo.cs | 2 +- Source/Mixin.SteamAndSE/Steam.cs | 93 ++++++++++++++++-- Source/SteamAndSE/SpaceEngineers.cs | 56 ----------- Source/SteamAndSE/Steam.cs | 98 ------------------- Source/SteamAndSE/SteamAndSE.projitems | 15 --- Source/SteamAndSE/SteamAndSE.shproj | 13 --- 12 files changed, 114 insertions(+), 200 deletions(-) delete mode 100644 Source/SteamAndSE/SpaceEngineers.cs delete mode 100644 Source/SteamAndSE/Steam.cs delete mode 100644 Source/SteamAndSE/SteamAndSE.projitems delete mode 100644 Source/SteamAndSE/SteamAndSE.shproj diff --git a/Source/DocGen.sln b/Source/DocGen.sln index 5831e93..889f98f 100644 --- a/Source/DocGen.sln +++ b/Source/DocGen.sln @@ -5,14 +5,14 @@ VisualStudioVersion = 16.0.29609.76 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MDKWhitelistExtractor", "MDKWhitelistExtractor\MDKWhitelistExtractor.csproj", "{02E93D45-C296-49F4-BEF2-3D5429549917}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SteamAndSE", "SteamAndSE\SteamAndSE.shproj", "{9E28967B-803C-4CF2-9A9C-B8135C85266B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocGen2", "DocGen2\DocGen2.csproj", "{76F6E75A-EA20-4BA8-8FA5-A1E713BFAFF4}" EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Mixin.SteamAndSE", "Mixin.SteamAndSE\Mixin.SteamAndSE.shproj", "{9E28967B-803C-4CF2-9A9C-B8135C85266B}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - SteamAndSE\SteamAndSE.projitems*{76f6e75a-ea20-4ba8-8fa5-a1e713bfaff4}*SharedItemsImports = 4 - SteamAndSE\SteamAndSE.projitems*{9e28967b-803c-4cf2-9a9c-b8135c85266b}*SharedItemsImports = 13 + Mixin.SteamAndSE\Mixin.SteamAndSE.projitems*{76f6e75a-ea20-4ba8-8fa5-a1e713bfaff4}*SharedItemsImports = 4 + Mixin.SteamAndSE\Mixin.SteamAndSE.projitems*{9e28967b-803c-4cf2-9a9c-b8135c85266b}*SharedItemsImports = 13 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Source/DocGen2/DocGen2.csproj b/Source/DocGen2/DocGen2.csproj index 5f8bfcc..809b8cb 100644 --- a/Source/DocGen2/DocGen2.csproj +++ b/Source/DocGen2/DocGen2.csproj @@ -239,6 +239,6 @@ - + \ No newline at end of file diff --git a/Source/MDK/MDKPackage.GeneratedInfo.cs b/Source/MDK/MDKPackage.GeneratedInfo.cs index 607ff6c..7d17fef 100644 --- a/Source/MDK/MDKPackage.GeneratedInfo.cs +++ b/Source/MDK/MDKPackage.GeneratedInfo.cs @@ -10,7 +10,7 @@ public partial class MDKPackage /// /// The current package version /// - public static readonly Version Version = new Version("1.4.8"); + public static readonly Version Version = new Version("1.4.9"); /// /// The required IDE version diff --git a/Source/MDK/source.extension.vsixmanifest b/Source/MDK/source.extension.vsixmanifest index b4abfab..550b613 100644 --- a/Source/MDK/source.extension.vsixmanifest +++ b/Source/MDK/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + MDK/SE A toolkit to help with ingame script (programmable block) development for Keen Software House's space sandbox Space Engineers. diff --git a/Source/MDKServices/DTEExtensions.cs b/Source/MDKServices/DTEExtensions.cs index eb77f87..d6ac99b 100644 --- a/Source/MDKServices/DTEExtensions.cs +++ b/Source/MDKServices/DTEExtensions.cs @@ -4,6 +4,7 @@ using Microsoft.VisualStudio.Shell.Interop; using System; using System.Diagnostics; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Task = System.Threading.Tasks.Task; diff --git a/Source/MDKServices/HealthAnalysis.cs b/Source/MDKServices/HealthAnalysis.cs index 896db90..e782bf0 100644 --- a/Source/MDKServices/HealthAnalysis.cs +++ b/Source/MDKServices/HealthAnalysis.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using EnvDTE; using Microsoft.VisualStudio.Shell; +using System.Runtime.InteropServices; namespace Malware.MDKServices { @@ -31,13 +32,28 @@ public class HealthAnalysis /// public static Task AnalyzeAsync(Solution solution, HealthAnalysisOptions options) => System.Threading.Tasks.Task.WhenAll(solution.Projects.Cast().Select(project => System.Threading.Tasks.Task.Run(() => Analyze(project, options)))); + // ReSharper disable once InconsistentNaming + private const int RPC_E_SERVERCALL_RETRYLATER = unchecked((int)0x8001010A); + static HealthAnalysis Analyze(Project project, HealthAnalysisOptions options) { options.Echo?.Invoke("Analyzing project..."); - if (!project.IsLoaded()) + while (true) { - options.Echo?.Invoke("Project is not loaded."); - return new HealthAnalysis(project, null, options); + try + { + if (!project.IsLoaded()) + { + options.Echo?.Invoke("Project is not loaded."); + return new HealthAnalysis(project, null, options); + } + + break; + } + catch (COMException ce) when (ce.HResult == RPC_E_SERVERCALL_RETRYLATER) + { + System.Threading.Thread.Sleep(500); + } } var projectInfo = MDKProjectProperties.Load(project.FullName, project.Name, options.Echo); diff --git a/Source/Mixin.MDKProjectProperties/MDKProjectProperties.GeneratedInfo.cs b/Source/Mixin.MDKProjectProperties/MDKProjectProperties.GeneratedInfo.cs index 2028e5c..f85479e 100644 --- a/Source/Mixin.MDKProjectProperties/MDKProjectProperties.GeneratedInfo.cs +++ b/Source/Mixin.MDKProjectProperties/MDKProjectProperties.GeneratedInfo.cs @@ -7,6 +7,6 @@ partial class MDKProjectProperties /// /// The current package version this utility assembly targets /// - public static readonly Version TargetPackageVersion = new Version("1.4.8"); + public static readonly Version TargetPackageVersion = new Version("1.4.9"); } } diff --git a/Source/Mixin.SteamAndSE/Steam.cs b/Source/Mixin.SteamAndSE/Steam.cs index 0dd08af..6c2a539 100644 --- a/Source/Mixin.SteamAndSE/Steam.cs +++ b/Source/Mixin.SteamAndSE/Steam.cs @@ -66,33 +66,112 @@ public string GetInstallFolder(string subfolderName, string verificationFilePath return null; } var configPath = Path.Combine(basePath, @"steamapps\libraryfolders.vdf"); - string configuration; + Dictionary configuration; try { - configuration = File.ReadAllText(configPath); + configuration = ReadVdf(configPath); } catch (Exception) { return null; } + if (!configuration.ContainsKey("libraryfolders")) + return null; + + configuration = (Dictionary)configuration["libraryfolders"]; + int n = 1; var basePaths = new List { basePath }; - - var matches = Regex.Matches(configuration, @"""\d+""[ \t]+""([^""]+)""", RegexOptions.Singleline); - foreach (Match match in matches) - basePaths.Add(match.Groups[1].Value); + string path; + while (true) + { + var key = n.ToString(); + n++; + if (!configuration.ContainsKey(key)) + break; + var folder = (Dictionary)configuration[key]; + path = (string)folder["path"]; + basePaths.Add(path); + } // Search through the potential base path, returning the first path which contains the desired // verification file. - var path = basePaths.Select(p => Path.Combine(p, "SteamApps", "common", subfolderName)) + path = basePaths.Select(p => Path.Combine(p, "SteamApps", "common", subfolderName)) .FirstOrDefault(p => File.Exists(Path.Combine(p, verificationFilePath))); if (path != null && !path.EndsWith("\\")) path += "\\"; return path; } + + private Dictionary ReadVdf(string configPath) + { + var lines = File.ReadAllLines(configPath); + int pos = 0; + return ReadVdfObject(lines, ref pos, false); + } + + private Dictionary ReadVdfObject(string[] lines, ref int pos, bool nested) + { + if (nested) + { + if (pos >= lines.Length && !Regex.IsMatch(lines[pos], @"\A\s*{\s*\z", RegexOptions.Singleline)) + throw new InvalidDataException("Steam .vdf file format failure"); + pos++; + } + + var obj = new Dictionary(); + while (true) + { + if (nested) + { + if (pos < lines.Length && Regex.IsMatch(lines[pos], @"\A\s*}\s*\z", RegexOptions.Singleline)) + { + pos++; + return obj; + } + } + + var part = ReadVdfLine(lines, ref pos); + if (part == null) + break; + if (part.Value.Value == null) + { + obj[Unquote(part.Value.Key)] = ReadVdfObject(lines, ref pos, true); + continue; + } + + obj[Unquote(part.Value.Key)] = Unquote(part.Value.Value); + } + if (nested) + throw new InvalidDataException("Steam .vdf file format failure"); + return obj; + } + + private string Unquote(string value) + { + return value.Substring(1, value.Length - 2).Replace("\\\"", "\""); + } + + private static KeyValuePair? ReadVdfLine(string[] lines, ref int pos) + { + if (pos >= lines.Length) + return null; + var matches = Regex.Matches(lines[pos], @"\s*(""[^""\\]*(?:\\.[^""\\]*)*"")", RegexOptions.Singleline); + switch (matches.Count) + { + case 1: + pos++; + return new KeyValuePair(matches[0].Groups[1].Value, null); + case 2: + pos++; + return new KeyValuePair(matches[0].Groups[1].Value, matches[1].Groups[1].Value); + default: + return null; + } + } } } diff --git a/Source/SteamAndSE/SpaceEngineers.cs b/Source/SteamAndSE/SpaceEngineers.cs deleted file mode 100644 index 53a8dc6..0000000 --- a/Source/SteamAndSE/SpaceEngineers.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.IO; -using System.Linq; - -namespace Malware.MDKUtilities -{ - /// - /// Utility service to retrieve information about Space Engineers (copyright Keen Software House, no affiliation) - /// - class SpaceEngineers - { - /// - /// The service - /// - public Steam Steam { get; } = new Steam(); - - /// - /// The Steam App ID of Space Engineers - /// - public const long SteamAppId = 244850; - - /// - /// Attempts to get the install path of Space Engineers. - /// - /// The desired subfolder path, if any - /// - public string GetInstallPath(params string[] subfolders) - { - if (!Steam.Exists) - return null; - var installFolder = Steam.GetInstallFolder("SpaceEngineers", "Bin64\\SpaceEngineers.exe"); - if (string.IsNullOrEmpty(installFolder)) - return null; - if (subfolders == null || subfolders.Length == 0) - return Path.GetFullPath(installFolder); - - subfolders = new[] {installFolder}.Concat(subfolders).ToArray(); - return Path.GetFullPath(Path.Combine(subfolders)); - } - - /// - /// Attempts to get the default data path for Space Engineers. - /// - /// The desired subfolder path, if any - /// - public string GetDataPath(params string[] subfolders) - { - var dataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SpaceEngineers"); - if (subfolders == null || subfolders.Length <= 0) - return Path.GetFullPath(dataFolder); - - subfolders = new[] {dataFolder}.Concat(subfolders).ToArray(); - return Path.GetFullPath(Path.Combine(subfolders)); - } - } -} diff --git a/Source/SteamAndSE/Steam.cs b/Source/SteamAndSE/Steam.cs deleted file mode 100644 index 0dd08af..0000000 --- a/Source/SteamAndSE/Steam.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using Microsoft.Win32; - -namespace Malware.MDKUtilities -{ - /// - /// A service to retrieve information about the current Steam (copyright Valve, no affiliation) installation. - /// - class Steam - { - string _exePath; - bool _isLoaded; - - /// - /// Gets the current executable path for Steam - /// - public string ExePath - { - get - { - if (!_isLoaded) - { - _isLoaded = true; - _exePath = FindSteam(); - } - return _exePath; - } - } - - /// - /// Determines whether Steam exists - /// - public bool Exists => ExePath != null && File.Exists(ExePath); - - string FindSteam() - { - var path = Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Valve\Steam", "SteamExe", null) as string; - if (!File.Exists(path)) - return null; - return path; - } - - /// - /// Attempts to determine the installation folder for the given game - /// - /// The install folder name of the game in question - /// The relative path to a file which existence verify the correctness of the install folder. - /// - public string GetInstallFolder(string subfolderName, string verificationFilePath) - { - string basePath; - try - { - basePath = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Valve\Steam", "SteamPath", null) as string; - } - catch (Exception) - { - return null; - } - if (basePath == null) - { - return null; - } - var configPath = Path.Combine(basePath, @"steamapps\libraryfolders.vdf"); - string configuration; - try - { - configuration = File.ReadAllText(configPath); - } - catch (Exception) - { - return null; - } - - var basePaths = new List - { - basePath - }; - - var matches = Regex.Matches(configuration, @"""\d+""[ \t]+""([^""]+)""", RegexOptions.Singleline); - foreach (Match match in matches) - basePaths.Add(match.Groups[1].Value); - - // Search through the potential base path, returning the first path which contains the desired - // verification file. - var path = basePaths.Select(p => Path.Combine(p, "SteamApps", "common", subfolderName)) - .FirstOrDefault(p => File.Exists(Path.Combine(p, verificationFilePath))); - - if (path != null && !path.EndsWith("\\")) - path += "\\"; - return path; - } - } -} diff --git a/Source/SteamAndSE/SteamAndSE.projitems b/Source/SteamAndSE/SteamAndSE.projitems deleted file mode 100644 index 038082b..0000000 --- a/Source/SteamAndSE/SteamAndSE.projitems +++ /dev/null @@ -1,15 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - 9e28967b-803c-4cf2-9a9c-b8135c85266b - - - Malware.MDKUtilities - - - - - - \ No newline at end of file diff --git a/Source/SteamAndSE/SteamAndSE.shproj b/Source/SteamAndSE/SteamAndSE.shproj deleted file mode 100644 index 6d26c3e..0000000 --- a/Source/SteamAndSE/SteamAndSE.shproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - 9e28967b-803c-4cf2-9a9c-b8135c85266b - 14.0 - - - - - - - -