From 350d2961c135f8a12b68ddcae896c79433f45dc0 Mon Sep 17 00:00:00 2001 From: Mino <1381835+Minoost@users.noreply.github.com> Date: Wed, 11 Mar 2020 11:52:51 +0900 Subject: [PATCH] galaxy brain 2: bit of restructure (Bootstrap) --- .../Bootstrapper.cs | 26 +++++---- .../BootstrapperOptions.cs | 6 +- .../Crypto/Blowfish.cs | 43 ++++++++++----- Dalamud.Bootstrap/Dalamud.Bootstrap.csproj | 14 +++++ Dalamud.Bootstrap/Exceptions.cs | 21 +++++++ Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs | 55 +++++++++++++++++++ Dalamud.Bootstrap/SqexArg/ArgumentDecoder.cs | 47 ++++++++++++++++ .../Windows}/Process.cs | 23 +++----- .../Windows/Win32.cs | 2 +- Dalamud.Injector/Dalamud.Injector.csproj | 3 +- Dalamud.Injector/DalamudLauncherException.cs | 29 ---------- Dalamud.Injector/Options.cs | 33 +++++++++++ Dalamud.Injector/Program.cs | 52 ++++++++++++++++++ Dalamud.Injector/Program/Options.cs | 18 ------ Dalamud.Injector/Program/Program.cs | 20 ------- Dalamud.Injector/Windows/NtException.cs | 24 -------- Dalamud.Testing/Dalamud.Testing.csproj | 23 ++++++++ Dalamud.Testing/UnitTest1.cs | 14 +++++ Dalamud.sln | 28 ++++++++++ 19 files changed, 345 insertions(+), 136 deletions(-) rename Dalamud.Injector/DalamudLauncher.cs => Dalamud.Bootstrap/Bootstrapper.cs (87%) rename Dalamud.Injector/DalamudLauncherOptions.cs => Dalamud.Bootstrap/BootstrapperOptions.cs (83%) rename {Dalamud.Injector => Dalamud.Bootstrap}/Crypto/Blowfish.cs (95%) create mode 100644 Dalamud.Bootstrap/Dalamud.Bootstrap.csproj create mode 100644 Dalamud.Bootstrap/Exceptions.cs create mode 100644 Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs create mode 100644 Dalamud.Bootstrap/SqexArg/ArgumentDecoder.cs rename {Dalamud.Injector => Dalamud.Bootstrap/Windows}/Process.cs (89%) rename {Dalamud.Injector => Dalamud.Bootstrap}/Windows/Win32.cs (99%) delete mode 100644 Dalamud.Injector/DalamudLauncherException.cs create mode 100644 Dalamud.Injector/Options.cs create mode 100644 Dalamud.Injector/Program.cs delete mode 100644 Dalamud.Injector/Program/Options.cs delete mode 100644 Dalamud.Injector/Program/Program.cs delete mode 100644 Dalamud.Injector/Windows/NtException.cs create mode 100644 Dalamud.Testing/Dalamud.Testing.csproj create mode 100644 Dalamud.Testing/UnitTest1.cs diff --git a/Dalamud.Injector/DalamudLauncher.cs b/Dalamud.Bootstrap/Bootstrapper.cs similarity index 87% rename from Dalamud.Injector/DalamudLauncher.cs rename to Dalamud.Bootstrap/Bootstrapper.cs index b2aca2bf3..26dd30c7b 100644 --- a/Dalamud.Injector/DalamudLauncher.cs +++ b/Dalamud.Bootstrap/Bootstrapper.cs @@ -5,16 +5,13 @@ using CoreHook.BinaryInjection.RemoteInjection; using CoreHook.BinaryInjection.RemoteInjection.Configuration; using CoreHook.IPC.Platform; -namespace Dalamud.Injector +namespace Dalamud.Bootstrap { - public sealed partial class DalamudLauncher + public sealed class Bootstrapper { - private readonly DalamudLauncherOptions m_options; - } + private readonly BootstrapperOptions m_options; - public sealed partial class DalamudLauncher - { - public DalamudLauncher(DalamudLauncherOptions options) + public Bootstrapper(BootstrapperOptions options) { m_options = options; } @@ -46,10 +43,17 @@ namespace Dalamud.Injector // Acquire the process handle and read the command line using var process = Process.Open(pid); - var commandLines = process.ReadCommandLine(); - - // .... + var arguments = process.ReadCommandLine(); + // TODO: + // .... if arg1 exists + // DecodeSqexArg(arguments[1]); + // args = ParseArgument() + // FindArguments(args, "T") + // RemoveArgs(args, "T") + // AddArgs(args, "T", newTick) + // str = ToString() + // EncodeSqexArg(str, newKey) process.Terminate(); @@ -90,7 +94,7 @@ namespace Dalamud.Injector // Could not inject Dalamud for whatever reason; it could be process is not actually running, insufficient os privilege, or whatever the thing SE put in their game; // Therefore there's not much we can do on this side; You have to trobleshoot by yourself somehow. - throw new DalamudLauncherException(pid, message, ex); + throw new BootstrapException(pid, message, ex); } } } diff --git a/Dalamud.Injector/DalamudLauncherOptions.cs b/Dalamud.Bootstrap/BootstrapperOptions.cs similarity index 83% rename from Dalamud.Injector/DalamudLauncherOptions.cs rename to Dalamud.Bootstrap/BootstrapperOptions.cs index 27e39363a..52464a988 100644 --- a/Dalamud.Injector/DalamudLauncherOptions.cs +++ b/Dalamud.Bootstrap/BootstrapperOptions.cs @@ -1,11 +1,11 @@ using System; using System.IO; -namespace Dalamud.Injector +namespace Dalamud.Bootstrap { - public sealed class DalamudLauncherOptions + public sealed class BootstrapperOptions { - public static DalamudLauncherOptions Default => new DalamudLauncherOptions + public static BootstrapperOptions Default => new BootstrapperOptions { RootDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Dalamud"), BinaryDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Dalamud", "bin"), diff --git a/Dalamud.Injector/Crypto/Blowfish.cs b/Dalamud.Bootstrap/Crypto/Blowfish.cs similarity index 95% rename from Dalamud.Injector/Crypto/Blowfish.cs rename to Dalamud.Bootstrap/Crypto/Blowfish.cs index 800fd0b19..2b3b41469 100644 --- a/Dalamud.Injector/Crypto/Blowfish.cs +++ b/Dalamud.Bootstrap/Crypto/Blowfish.cs @@ -1,15 +1,8 @@ using System; -using System.Buffers.Binary; using System.Runtime.CompilerServices; -namespace Dalamud.Injector.Crypto +namespace Dalamud.Bootstrap.Crypto { - /// - /// A struct that implements Blowfish algorithm. - /// - /// - /// - /// internal unsafe partial struct BlowfishState { // References: @@ -369,12 +362,12 @@ namespace Dalamud.Injector.Crypto } } - internal sealed partial class BlowfishLe + internal sealed partial class Blowfish { private BlowfishState m_state; } - internal sealed partial class BlowfishLe + internal sealed partial class Blowfish { /// /// Initializes a new instance of the Blowfish class. @@ -384,12 +377,36 @@ namespace Dalamud.Injector.Crypto /// /// A secret key used for blowfish. Key length must be between 32 and 448 bits. /// Length of the key is either too short or too long. - public BlowfishLe(ReadOnlySpan key) + public Blowfish(ReadOnlySpan key) { m_state = new BlowfishState(key); } - public unsafe void EncryptBlockUnsafe(byte* input, byte* output) + public void EncryptInPlace(Span buffer) + { + // TODO: this is shit + } + + public void DecryptInPlace(Span buffer) + { + if (buffer.Length % 8 != 0) + { + throw new ArgumentException("TODO: buffer length", nameof(buffer)); + } + + unsafe + { + fixed (byte* pBuffer = buffer) + { + for (byte* it = pBuffer; it < pBuffer + buffer.Length; it += 8) + { + DecryptBlockInPlace(it, it); + } + } + } + } + + private unsafe void EncryptBlockInPlace(byte* input, byte* output) { var inputBlock = (uint*)input; var outputBlock = (uint*)output; @@ -417,7 +434,7 @@ namespace Dalamud.Injector.Crypto outputBlock[1] = xr; } - public unsafe void DecryptBlockUnsafe(byte* input, byte* output) + private unsafe void DecryptBlockInPlace(byte* input, byte* output) { var inputBlock = (uint*)input; var outputBlock = (uint*)output; diff --git a/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj new file mode 100644 index 000000000..a28f10736 --- /dev/null +++ b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.1 + preview + enable + true + + + + + + + diff --git a/Dalamud.Bootstrap/Exceptions.cs b/Dalamud.Bootstrap/Exceptions.cs new file mode 100644 index 000000000..39602ab80 --- /dev/null +++ b/Dalamud.Bootstrap/Exceptions.cs @@ -0,0 +1,21 @@ +using System; + +namespace Dalamud.Bootstrap +{ + /// + /// An error that is thrown when bootstraping Dalamud failed. + /// + public class BootstrapException : Exception + { + internal BootstrapException() : base() { } + + internal BootstrapException(string message) : base(message) { } + + internal BootstrapException(string message, Exception innerException) : base(message, innerException) { } + } + + public class NtException : BootstrapException + { + + } +} diff --git a/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs b/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs new file mode 100644 index 000000000..46b47f0c0 --- /dev/null +++ b/Dalamud.Bootstrap/SqexArg/ArgumentBuilder.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Text; + +namespace Dalamud.Bootstrap.SqexArg +{ + internal sealed class ArgumentBuilder + { + private readonly Dictionary m_dict; + + public ArgumentBuilder() + { + m_dict = new Dictionary(); + } + + public ArgumentBuilder Add(string key, string value) + { + m_dict.Add(key, value); + + return this; + } + + public ArgumentBuilder Clear() + { + m_dict.Clear(); + + return this; + } + + private static void Write(StringBuilder buffer, string key, string value) + { + var escapedKey = EscapeValue(key); + var escapedvalue = EscapeValue(value); + + buffer.Append($" /{escapedKey} ={escapedvalue}"); + } + + private static string EscapeValue(string value) + { + // a single space character is represented as dobule spaces + return value.Replace(" ", " "); + } + + public override string ToString() + { + var buffer = new StringBuilder(256); + + foreach (var kv in m_dict) + { + Write(buffer, kv.Key, kv.Value); + } + + return buffer.ToString(); + } + } +} diff --git a/Dalamud.Bootstrap/SqexArg/ArgumentDecoder.cs b/Dalamud.Bootstrap/SqexArg/ArgumentDecoder.cs new file mode 100644 index 000000000..1f181bd07 --- /dev/null +++ b/Dalamud.Bootstrap/SqexArg/ArgumentDecoder.cs @@ -0,0 +1,47 @@ +using System; + +namespace Dalamud.Bootstrap.SqexArg +{ + internal static class ArgumentDecoder + { + public static void Decode(ReadOnlySpan argument, uint key) + { + // 1. strip //**sqex003 and **// + // 2. extract checksum + // 3. deduce upper nibble key + // 4. + + // //**c**// + if (argument.Length <= 9) + { + throw new ArgumentException(nameof(argument)); + } + + if (!argument.StartsWith("//**") || !argument.EndsWith("**//")) + { + throw new ArgumentException(nameof(argument)); + } + + var payload = argument[4..^5]; + var checksum = argument[^5]; + + // undo url safe + //payload.re + + + + // stuff + + } + + private static void DecodeUrlSafeBase64(ReadOnlySpan content) + { + var buffer = new byte[(content.Length / 3) * 4]; + if (!Convert.TryFromBase64Chars(payload, buffer, out var _)) + { + // TODO + } + } + + } +} diff --git a/Dalamud.Injector/Process.cs b/Dalamud.Bootstrap/Windows/Process.cs similarity index 89% rename from Dalamud.Injector/Process.cs rename to Dalamud.Bootstrap/Windows/Process.cs index 89a894191..8c68d242e 100644 --- a/Dalamud.Injector/Process.cs +++ b/Dalamud.Bootstrap/Windows/Process.cs @@ -1,10 +1,10 @@ -using Dalamud.Injector.Windows; +using Dalamud.Bootstrap.Windows; using Microsoft.Win32.SafeHandles; using System; using System.ComponentModel; using System.Runtime.InteropServices; -namespace Dalamud.Injector +namespace Dalamud.Bootstrap { /// /// TODO @@ -12,10 +12,7 @@ namespace Dalamud.Injector internal sealed partial class Process : IDisposable { private SafeProcessHandle m_handle; - } - internal sealed partial class Process - { /// /// Creates a process object that can be used to manipulate process's internal state. /// @@ -35,6 +32,7 @@ namespace Dalamud.Injector { const PROCESS_ACCESS_RIGHT access = PROCESS_ACCESS_RIGHT.PROCESS_VM_OPERATION | PROCESS_ACCESS_RIGHT.PROCESS_VM_READ + // | PROCESS_ACCESS_RIGHT.PROCESS_VM_WRITE // we don't need it for now | PROCESS_ACCESS_RIGHT.PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_ACCESS_RIGHT.PROCESS_QUERY_INFORMATION | PROCESS_ACCESS_RIGHT.PROCESS_CREATE_THREAD @@ -77,7 +75,7 @@ namespace Dalamud.Injector throw new Win32Exception(); } - // this is okay as Span can't really be longer than int.Max + // this is okay as the length of the span can't be longer than int.Max return (int)bytesRead; } } @@ -108,13 +106,6 @@ namespace Dalamud.Injector return buffer; } - private ref T ReadMemoryValue(IntPtr address, Span buffer) where T : unmanaged - { - ReadMemoryExact(address, buffer); - - return ref MemoryMarshal.AsRef(buffer); - } - private T ReadMemoryValue(IntPtr address) where T : unmanaged { unsafe @@ -123,7 +114,7 @@ namespace Dalamud.Injector Span buffer = stackalloc byte[sizeof(T)]; ReadMemoryExact(address, buffer); - // I reckon this is still far better than allocating on the heap when T is small enough. + // this is still far better than allocating the temporary buffer on the heap when sizeof(T) is small enough. return MemoryMarshal.Read(buffer); } } @@ -153,7 +144,7 @@ namespace Dalamud.Injector var peb = ReadMemoryValue(pebAddr); var procParam = ReadMemoryValue(peb.ProcessParameters); - // Read the command line (utf16-like string) + // Read the command line (which is utf16-like string) var commandLine = ReadMemoryExact(procParam.CommandLine.Buffer, procParam.CommandLine.Length); return ParseCommandLine(commandLine); } @@ -168,6 +159,8 @@ namespace Dalamud.Injector fixed (byte* pCommandLine = commandLine) { + // TODO: maybe explain why we can't just call .Split(' ') + // https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw argv = Win32.CommandLineToArgvW(pCommandLine, &argc); } diff --git a/Dalamud.Injector/Windows/Win32.cs b/Dalamud.Bootstrap/Windows/Win32.cs similarity index 99% rename from Dalamud.Injector/Windows/Win32.cs rename to Dalamud.Bootstrap/Windows/Win32.cs index df3aa1f80..89a45f458 100644 --- a/Dalamud.Injector/Windows/Win32.cs +++ b/Dalamud.Bootstrap/Windows/Win32.cs @@ -2,7 +2,7 @@ using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; -namespace Dalamud.Injector.Windows +namespace Dalamud.Bootstrap.Windows { internal static unsafe class Win32 { diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj index a894eecd4..16b8e1785 100644 --- a/Dalamud.Injector/Dalamud.Injector.csproj +++ b/Dalamud.Injector/Dalamud.Injector.csproj @@ -4,12 +4,11 @@ netcoreapp3.1 preview enable - true - + diff --git a/Dalamud.Injector/DalamudLauncherException.cs b/Dalamud.Injector/DalamudLauncherException.cs deleted file mode 100644 index c2597d95f..000000000 --- a/Dalamud.Injector/DalamudLauncherException.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace Dalamud.Injector -{ - /// - /// An error that is thrown when injecting Dalamud into the process failed. - /// - public sealed partial class DalamudLauncherException : Exception - { - /// - /// A target process id that was attempted to. - /// - public uint ProcessId { get; } - } - - public sealed partial class DalamudLauncherException - { - public DalamudLauncherException() : base() { } - - public DalamudLauncherException(string message) : base(message) { } - - public DalamudLauncherException(string message, Exception inner) : base(message, inner) { } - - public DalamudLauncherException(uint pid, string message, Exception inner) : base(message, inner) - { - ProcessId = pid; - } - } -} diff --git a/Dalamud.Injector/Options.cs b/Dalamud.Injector/Options.cs new file mode 100644 index 000000000..ab473cc63 --- /dev/null +++ b/Dalamud.Injector/Options.cs @@ -0,0 +1,33 @@ +using CommandLine; + +namespace Dalamud.Injector +{ + [Verb("inject")] + internal sealed class InjectOptions + { + [Option('p', "pid", Required = true, HelpText = "A target process id to inject.")] + public uint Pid { get; set; } + + [Option("root", Required = false)] + public string? RootDirectory { get; set; } + + [Option("bin", Required = false)] + public string? BinaryDirectory { get; set; } + } + + [Verb("launch")] + internal sealed class LaunchOptions + { + [Value(0)] + public string ExecutablePath { get; set; } = null!; + + [Value(1, Required = false)] + public string? CommandLine { get; set; } + + [Option("root", Required = false)] + public string? RootDirectory { get; set; } + + [Option("bin", Required = false)] + public string? BinaryDirectory { get; set; } + } +} diff --git a/Dalamud.Injector/Program.cs b/Dalamud.Injector/Program.cs new file mode 100644 index 000000000..1a29af1d0 --- /dev/null +++ b/Dalamud.Injector/Program.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; +using CommandLine; +using Dalamud.Bootstrap; +using static System.Environment; + +namespace Dalamud.Injector +{ + internal static class Program + { + private static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .WithParsed(Inject) + .WithParsed(Launch); + } + + private static void Inject(InjectOptions options) + { + var binDirectory = options.BinaryDirectory ?? GetDefaultBinaryDirectory(); + var rootDirectory = options.RootDirectory ?? GetDefaultRootDirectory(); + + var boot = new Bootstrapper(new BootstrapperOptions + { + BinaryDirectory = binDirectory, + RootDirectory = rootDirectory, + }); + + // .. + boot.Relaunch(options.Pid); + } + + private static void Launch(LaunchOptions options) + { + + } + + private static string GetDefaultBinaryDirectory() + { + var root = GetDefaultRootDirectory(); + + return Path.Combine(root, "bin"); + } + + private static string GetDefaultRootDirectory() + { + var localApp = Environment.GetFolderPath(SpecialFolder.LocalApplicationData); + + return Path.Combine(localApp, "Dalamud"); + } + } +} diff --git a/Dalamud.Injector/Program/Options.cs b/Dalamud.Injector/Program/Options.cs deleted file mode 100644 index a5a1b99f2..000000000 --- a/Dalamud.Injector/Program/Options.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CommandLine; - -namespace Dalamud.Injector -{ - [Verb("inject")] - internal sealed class InjectOptions - { - [Option('p', "pid", Required = true, HelpText = "A target process id to inject.")] - public uint Pid { get; set; } - - [Option("root", Required = true, HelpText = "")] - public string RootDirectory { get; set; } = null!; - - [Option("bin", Required = true, HelpText = "")] - public string BinaryDirectory { get; set; } = null!; - } -} diff --git a/Dalamud.Injector/Program/Program.cs b/Dalamud.Injector/Program/Program.cs deleted file mode 100644 index 4a00a37eb..000000000 --- a/Dalamud.Injector/Program/Program.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using CommandLine; -using Dalamud.Injector.Windows; - -namespace Dalamud.Injector -{ - internal static class Program - { - private static void Main(string[] args) - { - var shit = Process.Open(12732); - var cmd = shit.ReadCommandLine(); - /*Parser.Default.ParseArguments(args) - .WithParsed(opt => - { - - });*/ - } - } -} diff --git a/Dalamud.Injector/Windows/NtException.cs b/Dalamud.Injector/Windows/NtException.cs deleted file mode 100644 index 819dbec8a..000000000 --- a/Dalamud.Injector/Windows/NtException.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Dalamud.Injector.Windows -{ - /// - /// An exception that is thrown when the function call to ntdll failed. - /// - internal sealed class NtException : Exception - { - private const string DefaultMessage = "TODO: NtStatus failed message goes here"; - - public NtStatus Status { get; } - - public NtException(NtStatus status) : base(DefaultMessage) - { - Status = status; - } - - public NtException(NtStatus status, string message) : base(message) - { - Status = status; - } - } -} diff --git a/Dalamud.Testing/Dalamud.Testing.csproj b/Dalamud.Testing/Dalamud.Testing.csproj new file mode 100644 index 000000000..e6f67d320 --- /dev/null +++ b/Dalamud.Testing/Dalamud.Testing.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp3.1 + preview + true + false + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/Dalamud.Testing/UnitTest1.cs b/Dalamud.Testing/UnitTest1.cs new file mode 100644 index 000000000..f7aab3d3f --- /dev/null +++ b/Dalamud.Testing/UnitTest1.cs @@ -0,0 +1,14 @@ +using System; +using Xunit; + +namespace Dalamud.Testing +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} diff --git a/Dalamud.sln b/Dalamud.sln index 15a926f7f..83bb6fe78 100644 --- a/Dalamud.sln +++ b/Dalamud.sln @@ -39,6 +39,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreHook.IPC", "lib\CoreHoo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreHook.Memory", "lib\CoreHook\src\CoreHook.Memory\CoreHook.Memory.csproj", "{ED4FFE13-5F83-42B9-8847-E7C4D7A988E8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Bootstrap", "Dalamud.Bootstrap\Dalamud.Bootstrap.csproj", "{19032128-E336-460F-B6E4-EAF6055589E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Testing", "Dalamud.Testing\Dalamud.Testing.csproj", "{0A99A6B3-12E2-4197-A6F3-9211B6D4D824}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -217,6 +221,30 @@ Global {ED4FFE13-5F83-42B9-8847-E7C4D7A988E8}.Release|x64.Build.0 = Release|Any CPU {ED4FFE13-5F83-42B9-8847-E7C4D7A988E8}.Release|x86.ActiveCfg = Release|Any CPU {ED4FFE13-5F83-42B9-8847-E7C4D7A988E8}.Release|x86.Build.0 = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|x64.ActiveCfg = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|x64.Build.0 = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|x86.ActiveCfg = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Debug|x86.Build.0 = Debug|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|Any CPU.Build.0 = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|x64.ActiveCfg = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|x64.Build.0 = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|x86.ActiveCfg = Release|Any CPU + {19032128-E336-460F-B6E4-EAF6055589E5}.Release|x86.Build.0 = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|x64.ActiveCfg = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|x64.Build.0 = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|x86.ActiveCfg = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Debug|x86.Build.0 = Debug|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|Any CPU.Build.0 = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x64.ActiveCfg = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x64.Build.0 = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x86.ActiveCfg = Release|Any CPU + {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE