From c84d719ccd88477e368be42f73ddf0087bb240a5 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Fri, 29 Mar 2024 17:44:07 -0500 Subject: [PATCH 01/20] [third_party/RemoteNET] Simplify resource bundling --- .../RemoteNET/src/RemoteNET/Bootstrapper.cs | 179 ++++++++++-------- .../Internal/Extensions/HashUtils.cs | 26 --- .../Properties/Resources.Designer.cs | 120 ------------ .../src/RemoteNET/Properties/Resources.resx | 136 ------------- .../RemoteNET/src/RemoteNET/RemoteNET.csproj | 69 ++----- .../src/RemoteNET/Resources/Bootstrapper.dll | 1 - .../RemoteNET/Resources/Bootstrapper_x64.dll | 1 - .../src/RemoteNET/Resources/Launcher.exe | 1 - .../src/RemoteNET/Resources/Launcher_x64.exe | 1 - .../Microsoft.Diagnostics.Runtime.dll | 1 - .../RemoteNET/src/RemoteNET/app.config | 19 -- .../src/ScubaDiver/ScubaDiver.csproj | 14 +- .../RemoteNET/src/ScubaDiver/app.config | 28 +-- .../src/ScubaDiver/packages.lock.json | 12 +- 14 files changed, 137 insertions(+), 471 deletions(-) delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Extensions/HashUtils.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Properties/Resources.Designer.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Properties/Resources.resx delete mode 100644 third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper.dll delete mode 100644 third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper_x64.dll delete mode 100644 third_party/RemoteNET/src/RemoteNET/Resources/Launcher.exe delete mode 100644 third_party/RemoteNET/src/RemoteNET/Resources/Launcher_x64.exe delete mode 100644 third_party/RemoteNET/src/RemoteNET/Resources/Microsoft.Diagnostics.Runtime.dll delete mode 100644 third_party/RemoteNET/src/RemoteNET/app.config diff --git a/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs b/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs index 1afc767b..fe32adea 100644 --- a/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs +++ b/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs @@ -1,102 +1,127 @@ using System; using System.Diagnostics; using System.IO; +using System.Reflection; using MTGOSDK.Win32.Extensions; -using RemoteNET.Internal.Extensions; -using RemoteNET.Properties; +namespace RemoteNET; -namespace RemoteNET +public static class Bootstrapper { - public static class Bootstrapper - { - public static string AppDataDir => - Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - ExtractDir - ); + public static string AppDataDir => + Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + ExtractDir + ); - public static string ExtractDir = typeof(RemoteApp).Assembly.GetName().Name; + public static string ExtractDir = typeof(RemoteApp).Assembly.GetName().Name; - public static void Inject(Process target, ushort diverPort) - { - // Not injected yet, Injecting adapter now (which should load the Diver) - GetInjectionToolkit(target, out string launcherPath, out string diverPath); - string adapterExecutionArg = string.Join("*", - diverPath, - "ScubaDiver.DllEntry", - "EntryPoint", - diverPort.ToString()); - - var injectorProc = Process.Start(new ProcessStartInfo(launcherPath, - $"{target.Id} {adapterExecutionArg}") - { - WorkingDirectory = AppDataDir, - UseShellExecute = false, - RedirectStandardOutput = true - }); - if (injectorProc != null && injectorProc.WaitForExit(5000)) - { - // Injector finished early, there's probably an error. - if (injectorProc.ExitCode != 0) + public static void Inject(Process target, ushort diverPort) + { + // Not injected yet, Injecting adapter now (which should load the Diver) + GetInjectionToolkit(target, out string launcherPath, out string diverPath); + string adapterExecutionArg = string.Join("*", + diverPath, + "ScubaDiver.DllEntry", + "EntryPoint", + diverPort.ToString()); + + var injectorProc = Process.Start(new ProcessStartInfo(launcherPath, + $"{target.Id} {adapterExecutionArg}") { - var stderr = injectorProc.StandardError.ReadToEnd(); - throw new Exception("Injector returned error: " + stderr); - } - } - else + WorkingDirectory = AppDataDir, + UseShellExecute = false, + RedirectStandardOutput = true + }); + if (injectorProc != null && injectorProc.WaitForExit(5000)) + { + // Injector finished early, there's probably an error. + if (injectorProc.ExitCode != 0) { - // Stdout must be read to prevent deadlock when injector process exits. - _ = injectorProc.StandardOutput.ReadToEnd(); + var stderr = injectorProc.StandardError.ReadToEnd(); + throw new Exception("Injector returned error: " + stderr); } } + else + { + // Stdout must be read to prevent deadlock when injector process exits. + _ = injectorProc.StandardOutput.ReadToEnd(); + } + } - private static void GetInjectionToolkit( - Process target, - out string launcherPath, - out string diverPath) + public static byte[] ExtractResource(string filename) + { + Assembly asm = Assembly.GetExecutingAssembly(); + using (Stream resource = asm.GetManifestResourceStream(filename)) { - // Dumping injector + adapter DLL to a %localappdata%\RemoteNET - DirectoryInfo remoteNetAppDataDirInfo = new DirectoryInfo(AppDataDir); - if (!remoteNetAppDataDirInfo.Exists) - remoteNetAppDataDirInfo.Create(); - - // Decide which injection toolkit to use x32 or x64 - byte[] launcherResource = target.Is64Bit() - ? Resources.Launcher_x64 - : Resources.Launcher; - launcherPath = target.Is64Bit() - ? Path.Combine(AppDataDir, "Launcher_x64.exe") - : Path.Combine(AppDataDir, "Launcher.exe"); - byte[] adapterResource = target.Is64Bit() - ? Resources.Bootstrapper_x64 - : Resources.Bootstrapper; - var adapterPath = target.Is64Bit() - ? Path.Combine(AppDataDir, "Bootstrapper_x64.dll") - : Path.Combine(AppDataDir, "Bootstrapper.dll"); - - // Get the .NET diver assembly to inject into the target process - byte[] diverResource = Resources.ScubaDiver; - diverPath = Path.Combine(AppDataDir, Resources.ScubaDiver_AsmName); - - // Check if injector or bootstrap resources differ from copies on disk - OverrideFileIfChanged(launcherPath, launcherResource); - OverrideFileIfChanged(adapterPath, adapterResource); - OverrideFileIfChanged(diverPath, diverResource); + var byteStream = new MemoryStream(); + resource.CopyTo(byteStream); + + return byteStream.ToArray(); } + } - private static void OverrideFileIfChanged(string path, byte[] data) + private static void GetInjectionToolkit( + Process target, + out string launcherPath, + out string diverPath) + { + DirectoryInfo remoteNetAppDataDirInfo = new DirectoryInfo(AppDataDir); + if (!remoteNetAppDataDirInfo.Exists) + remoteNetAppDataDirInfo.Create(); + + byte[] launcherResource = target.Is64Bit() + ? ExtractResource(@"Resources\Launcher_x64") + : ExtractResource(@"Resources\Launcher"); + launcherPath = target.Is64Bit() + ? Path.Combine(AppDataDir, "Launcher_x64.exe") + : Path.Combine(AppDataDir, "Launcher.exe"); + + byte[] adapterResource = target.Is64Bit() + ? ExtractResource(@"Resources\Bootstrapper_x64") + : ExtractResource(@"Resources\Bootstrapper"); + var adapterPath = target.Is64Bit() + ? Path.Combine(AppDataDir, "Bootstrapper_x64.dll") + : Path.Combine(AppDataDir, "Bootstrapper.dll"); + + // Get the .NET diver assembly to inject into the target process + byte[] diverResource = ExtractResource(@"Resources\Microsoft.Diagnostics.Runtime"); + diverPath = Path.Combine(AppDataDir, "Microsoft.Diagnostics.Runtime.dll"); + + // Check if injector or bootstrap resources differ from copies on disk + OverrideFileIfChanged(launcherPath, launcherResource); + OverrideFileIfChanged(adapterPath, adapterResource); + OverrideFileIfChanged(diverPath, diverResource); + } + + private static void OverrideFileIfChanged(string filePath, byte[] data) + { + bool fileChanged = true; + + if (File.Exists(filePath)) { - string newDataHash = HashUtils.BufferSHA256(data); - string existingDataHash = File.Exists(path) - ? HashUtils.FileSHA256(path) - : string.Empty; - if (newDataHash != existingDataHash) + using (FileStream file = new(filePath, FileMode.Open, FileAccess.Read)) { - File.WriteAllBytes(path, data); + if (file.Length == data.Length) + { + fileChanged = false; + for (int i = 0; i < file.Length; i++) + { + if (file.ReadByte() != data[i]) + { + fileChanged = true; + break; + } + } + } } } + + if (fileChanged) + { + File.WriteAllBytes(filePath, data); + } } } diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/HashUtils.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/HashUtils.cs deleted file mode 100644 index e5611a6b..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/HashUtils.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.IO; -using System.Security.Cryptography; - - -namespace RemoteNET.Internal.Extensions -{ - public static class HashUtils - { - public static string FileSHA256(string filePath) - { - using SHA256 SHA256 = System.Security.Cryptography.SHA256.Create(); - using FileStream fileStream = File.OpenRead(filePath); - return BitConverter.ToString(SHA256.ComputeHash(fileStream)) - .Replace("-", "") - .ToLowerInvariant(); - } - public static string BufferSHA256(byte[] buff) - { - using SHA256 SHA256 = System.Security.Cryptography.SHA256.Create(); - return BitConverter.ToString(SHA256.ComputeHash(buff)) - .Replace("-", "") - .ToLowerInvariant(); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Properties/Resources.Designer.cs b/third_party/RemoteNET/src/RemoteNET/Properties/Resources.Designer.cs deleted file mode 100644 index ce1f83e3..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Properties/Resources.Designer.cs +++ /dev/null @@ -1,120 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace RemoteNET.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - public Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RemoteNET.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] Launcher { - get { - object obj = ResourceManager.GetObject("Launcher", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] Launcher_x64 { - get { - object obj = ResourceManager.GetObject("Launcher_x64", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] Bootstrapper { - get { - object obj = ResourceManager.GetObject("Bootstrapper", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] Bootstrapper_x64 { - get { - object obj = ResourceManager.GetObject("Bootstrapper_x64", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - public static byte[] ScubaDiver { - get { - object obj = ResourceManager.GetObject("ScubaDiver", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.String. - /// - public static string ScubaDiver_AsmName { - get => "Microsoft.Diagnostics.Runtime.dll"; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Properties/Resources.resx b/third_party/RemoteNET/src/RemoteNET/Properties/Resources.resx deleted file mode 100644 index 86864040..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Properties/Resources.resx +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\Launcher.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\Launcher_x64.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\Bootstrapper.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\Bootstrapper_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\Microsoft.Diagnostics.Runtime.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj b/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj index 23216f77..cf1bd5e8 100644 --- a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj +++ b/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj @@ -3,67 +3,36 @@ netstandard2.0 Latest - Always - True + $(NoWarn);NU1702 - - - - True - True - Resources.resx - - - ResXFileCodeGenerator - Resources.Designer.cs - + + + + + - - - $(NoWarn);NU1702 - - - - false - False - - - false - False - - - false - False - - - false - False - - - false - False - - - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper.dll b/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper.dll deleted file mode 100644 index 421376db..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper.dll +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper_x64.dll b/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper_x64.dll deleted file mode 100644 index 421376db..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Resources/Bootstrapper_x64.dll +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/third_party/RemoteNET/src/RemoteNET/Resources/Launcher.exe b/third_party/RemoteNET/src/RemoteNET/Resources/Launcher.exe deleted file mode 100644 index 421376db..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Resources/Launcher.exe +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/third_party/RemoteNET/src/RemoteNET/Resources/Launcher_x64.exe b/third_party/RemoteNET/src/RemoteNET/Resources/Launcher_x64.exe deleted file mode 100644 index 421376db..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Resources/Launcher_x64.exe +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/third_party/RemoteNET/src/RemoteNET/Resources/Microsoft.Diagnostics.Runtime.dll b/third_party/RemoteNET/src/RemoteNET/Resources/Microsoft.Diagnostics.Runtime.dll deleted file mode 100644 index 421376db..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Resources/Microsoft.Diagnostics.Runtime.dll +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/third_party/RemoteNET/src/RemoteNET/app.config b/third_party/RemoteNET/src/RemoteNET/app.config deleted file mode 100644 index 2ab4b35a..00000000 --- a/third_party/RemoteNET/src/RemoteNET/app.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj b/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj index 269f249e..e7646bed 100644 --- a/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj +++ b/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj @@ -33,14 +33,11 @@ + Version="3.1.512801" /> - + Version="8.0.0" /> @@ -48,7 +45,7 @@ Version="3.0.41" /> - + - - - + \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver/app.config b/third_party/RemoteNET/src/ScubaDiver/app.config index 8d39468f..af48e603 100644 --- a/third_party/RemoteNET/src/ScubaDiver/app.config +++ b/third_party/RemoteNET/src/ScubaDiver/app.config @@ -1,30 +1,12 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver/packages.lock.json b/third_party/RemoteNET/src/ScubaDiver/packages.lock.json index 4b9ef1b0..96d8db35 100644 --- a/third_party/RemoteNET/src/ScubaDiver/packages.lock.json +++ b/third_party/RemoteNET/src/ScubaDiver/packages.lock.json @@ -10,18 +10,18 @@ }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Direct", - "requested": "[7.0.0, )", - "resolved": "7.0.0", - "contentHash": "3aeMZ1N0lJoSyzqiP03hqemtb1BijhsJADdobn/4nsMJ8V1H+CrpuduUe4hlRdx+ikBQju1VGjMD1GJ3Sk05Eg==", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", "dependencies": { "System.Threading.Tasks.Extensions": "4.5.4" } }, "Microsoft.Diagnostics.Runtime": { "type": "Direct", - "requested": "[3.0.442202, )", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", + "requested": "[3.1.512801, )", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", "dependencies": { "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", "System.Collections.Immutable": "6.0.0", From adf749a41e1f5d6c3d11d11bd155cb906cb3b691 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 06:32:27 -0500 Subject: [PATCH 02/20] [MTGOSDK] Merge RemoteNET and ScubaDiver.API projects Moves the RemoteNET and ScubaDiver.API libraries into the main MTGOSDK project. This allows for tighter coupling of the type-marshalling/proxy protocol being developed for the main library, which should be preferred over the previous RemoteNET approach. TODO: Refactor and deduplicate RemoteNET + API architecture --- .../src/Extensions/ProcessExtensions.cs | 13 + MTGOSDK/MTGOSDK.csproj | 94 +-- MTGOSDK/MTGOSDK.pkg.props | 19 + MTGOSDK/MTGOSDK.ref.props | 37 ++ MTGOSDK/packages.lock.json | 266 +++++++- MTGOSDK/src/API/Collection/Card.cs | 2 +- MTGOSDK/src/API/Interface/WindowUtilities.cs | 4 + MTGOSDK/src/Core/Reflection/ProxyObject.cs | 4 + MTGOSDK/src/Core/Reflection/RemoteProxy.cs | 2 + MTGOSDK/src/Core/RemoteClient.cs | 2 +- .../src/Core/Remoting}/Bootstrapper.cs | 6 + MTGOSDK/src/Core/Remoting/CandidateObject.cs | 18 + MTGOSDK/src/Core/Remoting/CandidateType.cs | 13 + .../Core/Remoting/Internal/DiverDiscovery.cs | 84 +++ .../Internal/DynamicRemoteEnumerator.cs | 32 + .../Remoting/Internal/DynamicRemoteObject.cs | 606 ++++++++++++++++++ .../Internal/DynamicRemoteObjectFactory.cs | 24 + .../ProxiedReflection/IProxiedMember.cs | 12 + .../ProxiedReflection/ProxiedEventInfo.cs | 49 ++ .../ProxiedReflection/ProxiedMemberType.cs | 16 + .../ProxiedReflection/ProxiedMethodGroup.cs | 15 + .../ProxiedMethodOverload.cs | 23 + .../ProxiedValueMemberInfo.cs | 22 + .../Internal/Reflection/DummyGenericType.cs | 187 ++++++ .../Internal/Reflection/DynamicRemoteEnum.cs | 22 + .../Reflection/LazyRemoteTypeResolver.cs | 42 ++ .../Reflection/RemoteConstructorInfo.cs | 96 +++ .../Internal/Reflection/RemoteEnum.cs | 28 + .../Internal/Reflection/RemoteEventInfo.cs | 72 +++ .../Internal/Reflection/RemoteFieldInfo.cs | 162 +++++ .../Reflection/RemoteFunctionsInvokeHelper.cs | 156 +++++ .../Internal/Reflection/RemoteMethodInfo.cs | 132 ++++ .../Reflection/RemoteParameterInfo.cs | 30 + .../Internal/Reflection/RemotePropertyInfo.cs | 112 ++++ .../Internal/Reflection/RemoteType.cs | 338 ++++++++++ .../Internal/Reflection/RemoteTypesFactory.cs | 359 +++++++++++ .../Internal/Reflection/TypesResolver.cs | 74 +++ .../Core/Remoting/Internal/RemoteObjectRef.cs | 155 +++++ .../Internal/Utils/MethodBaseExtensions.cs | 62 ++ .../Remoting/Interop}/CallbacksListener.cs | 0 .../Remoting/Interop}/DiverCommunicator.cs | 0 .../Interop}/Exceptions/RemoteException.cs | 0 .../Exceptions/RemoteObjectMovedException.cs | 0 .../Remoting/Interop}/Extensions/IntPtrExt.cs | 0 .../Interop}/Extensions/WildCardType.cs | 0 .../Callbacks/CallbackInvocationRequest.cs | 0 .../Callbacks/EventRegistrationResults.cs | 0 .../Client/UnregisterClientResponse.cs | 0 .../Interop}/Interactions/DiverError.cs | 0 .../Interactions/Dumps/DomainsDump.cs | 0 .../Interop}/Interactions/Dumps/HeapDump.cs | 0 .../Interop}/Interactions/Dumps/MemberDump.cs | 0 .../Interop}/Interactions/Dumps/ObjectDump.cs | 0 .../Interop}/Interactions/Dumps/TypeDump.cs | 0 .../Interactions/Dumps/TypeDumpRequest.cs | 0 .../Interop}/Interactions/Dumps/TypesDump.cs | 0 .../Interactions/InvocationRequest.cs | 0 .../Interactions/InvocationResults.cs | 0 .../Object/CtorInvocationRequest.cs | 0 .../Interactions/Object/FieldGetRequest.cs | 0 .../Interactions/Object/FieldSetRequest.cs | 0 .../Object/IndexedItemAccessRequest.cs | 0 .../Interop}/ObjectOrRemoteAddress.cs | 0 .../Remoting/Interop}/ReverseCommunicator.cs | 0 .../Core/Remoting/Interop}/Utils/Filter.cs | 0 .../Interop}/Utils/NewtonsoftProxy.cs | 0 .../Interop}/Utils/PrimitivesEncoder.cs | 0 .../Core/Remoting/Interop}/Utils/TypeExt.cs | 0 MTGOSDK/src/Core/Remoting/Logger.cs | 37 ++ MTGOSDK/src/Core/Remoting/RemoteActivator.cs | 66 ++ MTGOSDK/src/Core/Remoting/RemoteApp.cs | 314 +++++++++ MTGOSDK/src/Core/Remoting/RemoteObject.cs | 133 ++++ NOTICE | 50 ++ .../src/RemoteNET/CandidateObject.cs | 20 - .../RemoteNET/src/RemoteNET/CandidateType.cs | 14 - .../src/RemoteNET/Internal/DiverDiscovery.cs | 78 --- .../Internal/DynamicRemoteEnumerator.cs | 33 - .../RemoteNET/Internal/DynamicRemoteObject.cs | 602 ----------------- .../Internal/DynamicRemoteObjectFactory.cs | 16 - .../Extensions/ProcessModuleCollectionExt.cs | 17 - .../ProxiedReflection/IProxiedMember.cs | 7 - .../ProxiedReflection/ProxiedEventInfo.cs | 49 -- .../ProxiedReflection/ProxiedMemberType.cs | 11 - .../ProxiedReflection/ProxiedMethodGroup.cs | 10 - .../ProxiedMethodOverload.cs | 18 - .../ProxiedValueMemberInfo.cs | 18 - .../Internal/Reflection/DummyGenericType.cs | 185 ------ .../Internal/Reflection/DynamicRemoteEnum.cs | 24 - .../Reflection/LazyRemoteTypeResolver.cs | 37 -- .../Reflection/RemoteConstructorInfo.cs | 96 --- .../Internal/Reflection/RemoteEnum.cs | 26 - .../Internal/Reflection/RemoteEventInfo.cs | 74 --- .../Internal/Reflection/RemoteFieldInfo.cs | 159 ----- .../Reflection/RemoteFunctionsInvokeHelper.cs | 151 ----- .../Internal/Reflection/RemoteMethodInfo.cs | 132 ---- .../Reflection/RemoteParameterInfo.cs | 31 - .../Internal/Reflection/RemotePropertyInfo.cs | 115 ---- .../Internal/Reflection/RemoteType.cs | 336 ---------- .../Internal/Reflection/RemoteTypesFactory.cs | 385 ----------- .../Internal/Reflection/TypesResolver.cs | 69 -- .../src/RemoteNET/Internal/RemoteObjectRef.cs | 162 ----- third_party/RemoteNET/src/RemoteNET/Logger.cs | 32 - .../src/RemoteNET/RemoteActivator.cs | 71 -- .../RemoteNET/src/RemoteNET/RemoteApp.cs | 310 --------- .../RemoteNET/src/RemoteNET/RemoteNET.csproj | 32 +- .../RemoteNET/src/RemoteNET/RemoteObject.cs | 133 ---- .../RemoteNET/Utils/DebuggableRemoteObject.cs | 55 -- .../RemoteNET/src/RemoteNET/Utils/Lambda.cs | 20 - .../RemoteNET/Utils/MethodBaseExtensions.cs | 42 -- .../src/RemoteNET/packages.lock.json | 153 ----- .../src/ScubaDiver.API/ScubaDiver.API.csproj | 12 +- .../src/ScubaDiver.API/packages.lock.json | 139 ---- .../src/ScubaDiver/Properties/AssemblyInfo.cs | 35 - .../src/ScubaDiver/ScubaDiver.csproj | 43 +- .../src/ScubaDiver/packages.lock.json | 37 +- 115 files changed, 3967 insertions(+), 4012 deletions(-) create mode 100644 MTGOSDK/MTGOSDK.pkg.props create mode 100644 MTGOSDK/MTGOSDK.ref.props rename {third_party/RemoteNET/src/RemoteNET => MTGOSDK/src/Core/Remoting}/Bootstrapper.cs (96%) create mode 100644 MTGOSDK/src/Core/Remoting/CandidateObject.cs create mode 100644 MTGOSDK/src/Core/Remoting/CandidateType.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs create mode 100644 MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/CallbacksListener.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/DiverCommunicator.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Exceptions/RemoteException.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Exceptions/RemoteObjectMovedException.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Extensions/IntPtrExt.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Extensions/WildCardType.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Callbacks/CallbackInvocationRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Callbacks/EventRegistrationResults.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Client/UnregisterClientResponse.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/DiverError.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/DomainsDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/HeapDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/MemberDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/ObjectDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/TypeDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/TypeDumpRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Dumps/TypesDump.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/InvocationRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/InvocationResults.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Object/CtorInvocationRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Object/FieldGetRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Object/FieldSetRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Interactions/Object/IndexedItemAccessRequest.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/ObjectOrRemoteAddress.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/ReverseCommunicator.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Utils/Filter.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Utils/NewtonsoftProxy.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Utils/PrimitivesEncoder.cs (100%) rename {third_party/RemoteNET/src/ScubaDiver.API => MTGOSDK/src/Core/Remoting/Interop}/Utils/TypeExt.cs (100%) create mode 100644 MTGOSDK/src/Core/Remoting/Logger.cs create mode 100644 MTGOSDK/src/Core/Remoting/RemoteActivator.cs create mode 100644 MTGOSDK/src/Core/Remoting/RemoteApp.cs create mode 100644 MTGOSDK/src/Core/Remoting/RemoteObject.cs create mode 100644 NOTICE delete mode 100644 third_party/RemoteNET/src/RemoteNET/CandidateObject.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/CandidateType.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/DiverDiscovery.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteEnumerator.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObject.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObjectFactory.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Extensions/ProcessModuleCollectionExt.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/IProxiedMember.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedEventInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMemberType.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodGroup.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodOverload.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DummyGenericType.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DynamicRemoteEnum.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/LazyRemoteTypeResolver.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteConstructorInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEnum.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEventInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFieldInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFunctionsInvokeHelper.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteMethodInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteParameterInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemotePropertyInfo.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteType.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteTypesFactory.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/Reflection/TypesResolver.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Internal/RemoteObjectRef.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Logger.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/RemoteActivator.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/RemoteApp.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/RemoteObject.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Utils/DebuggableRemoteObject.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Utils/Lambda.cs delete mode 100644 third_party/RemoteNET/src/RemoteNET/Utils/MethodBaseExtensions.cs delete mode 100644 third_party/RemoteNET/src/ScubaDiver/Properties/AssemblyInfo.cs diff --git a/MTGOSDK.Win32/src/Extensions/ProcessExtensions.cs b/MTGOSDK.Win32/src/Extensions/ProcessExtensions.cs index 1675d737..9154607e 100644 --- a/MTGOSDK.Win32/src/Extensions/ProcessExtensions.cs +++ b/MTGOSDK.Win32/src/Extensions/ProcessExtensions.cs @@ -77,6 +77,19 @@ public static IEnumerable GetModules(this Process process) } } + /// + /// Converts a to an enumerable collection of . + /// + /// The to convert. + /// An enumerable collection of . + public static IEnumerable AsEnumerable(this ProcessModuleCollection collection) + { + foreach (ProcessModule module in collection) + { + yield return module; + } + } + /// /// Determines whether the specified process is a 64-bit process. /// diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 8656a5b8..1fa2ea99 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -1,65 +1,65 @@ - net8.0-windows + netstandard2.0;net8.0-windows Latest enable enable - - $(NoWarn);CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;IDE0065; - - true - - - - - MTGOSDK - 1.0.0 - Cory Bennett - Videre Project - - - - - ..\publish\ - embedded - True + $(NoWarn); + + CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;IDE0065; + + CS8601;CS8608;CS8610;CS8618;CS8619;CS8620;CS8765; + + 1701;1702;8600;8602;8603;8618;8625; + CS0436;CS9113;CS8767;MSB3277 + + + + - - - - - - $(_MTGOSDK_Refs)\3.4.*.* - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MTGOSDK/MTGOSDK.pkg.props b/MTGOSDK/MTGOSDK.pkg.props new file mode 100644 index 00000000..184f578d --- /dev/null +++ b/MTGOSDK/MTGOSDK.pkg.props @@ -0,0 +1,19 @@ + + + + + + MTGOSDK + 1.0.0 + Cory Bennett + Videre Project + + + + + ..\publish\ + embedded + True + + + \ No newline at end of file diff --git a/MTGOSDK/MTGOSDK.ref.props b/MTGOSDK/MTGOSDK.ref.props new file mode 100644 index 00000000..97a2bd33 --- /dev/null +++ b/MTGOSDK/MTGOSDK.ref.props @@ -0,0 +1,37 @@ + + + + + + $(NoWarn);NU1702; + + true + + + + + + $(_MTGOSDK_Refs)\3.4.*.* + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MTGOSDK/packages.lock.json b/MTGOSDK/packages.lock.json index ebca2fb7..195304fd 100644 --- a/MTGOSDK/packages.lock.json +++ b/MTGOSDK/packages.lock.json @@ -1,7 +1,7 @@ { "version": 1, "dependencies": { - "net8.0-windows7.0": { + ".NETStandard,Version=v2.0": { "ImpromptuInterface": { "type": "Direct", "requested": "[8.0.4, )", @@ -13,6 +13,38 @@ "System.Reflection.Emit": "4.7.0" } }, + "Meziantou.Polyfill": { + "type": "Direct", + "requested": "[1.0.37, )", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, + "Microsoft.CSharp": { + "type": "Direct", + "requested": "[4.7.0, )", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Diagnostics.Runtime": { + "type": "Direct", + "requested": "[3.1.512801, )", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", + "System.Collections.Immutable": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "NETStandard.Library": { + "type": "Direct", + "requested": "[2.0.3, )", + "resolved": "2.0.3", + "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, "Newtonsoft.Json": { "type": "Direct", "requested": "[13.0.3, )", @@ -31,12 +63,10 @@ "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.0", - "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" - }, - "Microsoft.CSharp": { - "type": "Transitive", - "resolved": "4.7.0", - "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.2" + } }, "Microsoft.Diagnostics.NETCore.Client": { "type": "Transitive", @@ -47,16 +77,6 @@ "Microsoft.Extensions.Logging": "2.1.1" } }, - "Microsoft.Diagnostics.Runtime": { - "type": "Transitive", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", - "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, "Microsoft.Extensions.Configuration": { "type": "Transitive", "resolved": "2.1.1", @@ -130,11 +150,17 @@ "resolved": "1.1.0", "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, "System.Collections.Immutable": { "type": "Transitive", "resolved": "6.0.0", "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", "dependencies": { + "System.Memory": "4.5.4", "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, @@ -148,13 +174,31 @@ }, "System.Memory": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "sDJYJpGtTgx+23Ayu5euxG5mAXWdkDb4+b0rD0Cab0M1oQS9H0HXGPriKcqpXuiJDTV7fTp/d+fMDJmnr6sNvA==" + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" }, "System.Reflection.Emit": { "type": "Transitive", "resolved": "4.7.0", - "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" + "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==", + "dependencies": { + "System.Reflection.Emit.ILGeneration": "4.7.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "AucBYo3DSI0IDxdUjKksBcQJXPHyoPyrCXYURW1WDsLI4M65Ar/goSHjdnHOAY9MiYDNKqDlIgaYm+zL2hA1KA==" }, "System.Runtime": { "type": "Transitive", @@ -170,23 +214,187 @@ "resolved": "6.0.0", "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.2", + "contentHash": "BG/TNxDFv0svAzx8OiMXDlsHfGw623BZ8tCXw4YLhDFDvDhNUEV58jKYMGRnkbJNm7c3JNNJDiN7JBMzxRBR2w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.5.2" + } + }, "mtgosdk.win32": { "type": "Project" + } + }, + "net8.0-windows7.0": { + "ImpromptuInterface": { + "type": "Direct", + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "acQoJpopRKHw66kporxut6/ucEiSajaxQoAsz0xD/BbVbxYtW3LMC31tHSgTmTMbhtmYp+sEq6zpH65gJGh+3Q==", + "dependencies": { + "Dynamitey": "3.0.3", + "Microsoft.CSharp": "4.7.0", + "System.Reflection.Emit": "4.7.0" + } + }, + "Meziantou.Polyfill": { + "type": "Direct", + "requested": "[1.0.37, )", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, + "Microsoft.CSharp": { + "type": "Direct", + "requested": "[4.7.0, )", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Diagnostics.Runtime": { + "type": "Direct", + "requested": "[3.1.512801, )", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.410101" + } }, - "remotenet": { - "type": "Project", + "Newtonsoft.Json": { + "type": "Direct", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "Dynamitey": { + "type": "Transitive", + "resolved": "3.0.3", + "contentHash": "ocF4rRKgnmBkblk8RrgRP9YxxeJBvoaoCNLXgmUMgQCjZRw2v6Rtqxt5Kni6/TtbvICeWVN9X/69G5jltUEnbQ==", "dependencies": { - "MTGOSDK.Win32": "[1.0.0, )", - "Microsoft.CSharp": "[4.7.0, )", - "ScubaDiver.API": "[1.0.0, )" + "Microsoft.CSharp": "4.7.0", + "System.ComponentModel": "4.3.0" } }, - "scubadiver.api": { - "type": "Project", + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.Diagnostics.NETCore.Client": { + "type": "Transitive", + "resolved": "0.2.410101", + "contentHash": "I4hMjlbPcM5R+M4ThD2Zt1z58M8uZnWkDbFLXHntOOAajajEucrw4XYNSaoi5rgoqksgxQ3g388Vof4QzUNwdQ==", "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", - "Newtonsoft.Json": "[13.0.3, )" + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.Logging": "2.1.1" } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.1.1" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "2.1.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Primitives": "2.1.1" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", + "dependencies": { + "System.Memory": "4.5.1", + "System.Runtime.CompilerServices.Unsafe": "4.5.1" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "System.ComponentModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "sDJYJpGtTgx+23Ayu5euxG5mAXWdkDb4+b0rD0Cab0M1oQS9H0HXGPriKcqpXuiJDTV7fTp/d+fMDJmnr6sNvA==" + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw==" + }, + "mtgosdk.win32": { + "type": "Project" } } } diff --git a/MTGOSDK/src/API/Collection/Card.cs b/MTGOSDK/src/API/Collection/Card.cs index f7f39424..87933808 100644 --- a/MTGOSDK/src/API/Collection/Card.cs +++ b/MTGOSDK/src/API/Collection/Card.cs @@ -50,7 +50,7 @@ public sealed class Card(dynamic card) : CollectionItem /// public IList Types => ((string)Unbind(@base).Types.ToString()) - .Split(", ") + .Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries) .ToList(); /// diff --git a/MTGOSDK/src/API/Interface/WindowUtilities.cs b/MTGOSDK/src/API/Interface/WindowUtilities.cs index 27cfdb1a..0cb286dc 100644 --- a/MTGOSDK/src/API/Interface/WindowUtilities.cs +++ b/MTGOSDK/src/API/Interface/WindowUtilities.cs @@ -38,6 +38,9 @@ public static class WindowUtilities /// public static ICollection GetWindows() { +#if NETSTANDARD2_0 + throw new PlatformNotSupportedException(); +#else // This is a hack that caches the dispatcher's registered windows. _ = Unbind(s_windowUtilities).AllWindows; _ = s_windowUtilities.AllWindows; @@ -57,6 +60,7 @@ public static ICollection GetWindows() } throw new InvalidOperationException("Failed to get window collection."); +#endif } /// diff --git a/MTGOSDK/src/Core/Reflection/ProxyObject.cs b/MTGOSDK/src/Core/Reflection/ProxyObject.cs index be4b8547..4d8da61d 100644 --- a/MTGOSDK/src/Core/Reflection/ProxyObject.cs +++ b/MTGOSDK/src/Core/Reflection/ProxyObject.cs @@ -40,12 +40,16 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) value = @base.GetType().GetProperty(binder.Name).GetValue(@base); // Get the default value for the return type. +#if !NETSTANDARD2_0 Type returnType = binder.ReturnType; dynamic typeRef = RuntimeHelpers.GetUninitializedObject(returnType); dynamic typeDefault = typeRef .GetType() .GetConstructor(Type.EmptyTypes) .Invoke(typeRef, null); +#else + dynamic typeDefault = null; +#endif #pragma warning disable CS8601 result = (value != null || value != typeDefault) diff --git a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs index e62203a7..3266e217 100644 --- a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs +++ b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs @@ -16,7 +16,9 @@ public sealed class RemoteProxy(Func c) : DLRWrapper() where I : class /// /// Converts the captured member group to a typed delegate. /// +#if !NETSTANDARD2_0 internal override Lazy obj => new(() => c.Invoke()); +#endif private object refLock = new(); private dynamic refObj = new DynamicRemoteObject(); diff --git a/MTGOSDK/src/Core/RemoteClient.cs b/MTGOSDK/src/Core/RemoteClient.cs index ddf494f7..0002735a 100644 --- a/MTGOSDK/src/Core/RemoteClient.cs +++ b/MTGOSDK/src/Core/RemoteClient.cs @@ -37,7 +37,7 @@ public sealed class RemoteClient : DLRWrapper /// The directory path to extract runtime injector and diver assemblies to. /// public static string ExtractDir = - Path.Join(/* %appdata%\..\Local\ */ "MTGOSDK", "MTGOInjector", "bin"); + Path.Combine(/* %appdata%\..\Local\ */ "MTGOSDK", "MTGOInjector", "bin"); /// /// Whether to destroy the MTGO process when disposing of the Remote Client. diff --git a/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs similarity index 96% rename from third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs rename to MTGOSDK/src/Core/Remoting/Bootstrapper.cs index fe32adea..9df5949d 100644 --- a/third_party/RemoteNET/src/RemoteNET/Bootstrapper.cs +++ b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs @@ -1,3 +1,9 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + using System; using System.Diagnostics; using System.IO; diff --git a/MTGOSDK/src/Core/Remoting/CandidateObject.cs b/MTGOSDK/src/Core/Remoting/CandidateObject.cs new file mode 100644 index 00000000..083e9987 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/CandidateObject.cs @@ -0,0 +1,18 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +namespace RemoteNET; + +/// +/// A candidate for a remote object. +/// Holding this item does not mean having a meaningful hold of the remote object. To gain one use +/// +public class CandidateObject(ulong address, string typeFullName, int hashCode) +{ + public ulong Address = address; + public string TypeFullName = typeFullName; + public int HashCode = hashCode; +} diff --git a/MTGOSDK/src/Core/Remoting/CandidateType.cs b/MTGOSDK/src/Core/Remoting/CandidateType.cs new file mode 100644 index 00000000..cb5ca835 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/CandidateType.cs @@ -0,0 +1,13 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +namespace RemoteNET; + +public class CandidateType(string typeName, string assembly) +{ + public string TypeFullName = typeName; + public string Assembly = assembly; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs b/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs new file mode 100644 index 00000000..730666fa --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs @@ -0,0 +1,84 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Net.Sockets; + +using MTGOSDK.Win32.Extensions; + +using ScubaDiver.API; + + +namespace RemoteNET.Internal; + +public enum DiverState +{ + NoDiver, + Alive, + Corpse, + HollowSnapshot +} + +public static class DiverDiscovery +{ + public static DiverState QueryStatus( + Process target, + string diverAddr, + ushort diverPort) + { + DiverCommunicator com = new DiverCommunicator(diverAddr, diverPort); + + // We WANT to check liveness of the diver using HTTP but this might take a + // LOT of time if it is dead (Trying to TCP SYN several times, with a + // timeout between each). So a simple circuit-breaker is implemented + // before that: If we manage to bind to the expected diver endpoint, we + // assume it's not alive + + bool diverPortIsFree = false; + try + { + IPAddress localAddr = IPAddress.Parse(diverAddr); + TcpListener server = new TcpListener(localAddr, diverPort); + server.Start(); + diverPortIsFree = true; + server.Stop(); + } + catch + { + // Had some issues, perhaps it's the diver holding that port. + } + + if (!diverPortIsFree && com.CheckAliveness()) + { + return DiverState.Alive; + } + + // // Check if this is a snapshot created by the diver. + // if (target.Threads.Count == 0) + // return DiverState.HollowSnapshot; + + // Diver isn't alive. It's possible that it was never injected or it was + // injected and killed + bool containsToolkitDll = false; + try + { + containsToolkitDll |= target.Modules.AsEnumerable() + .Any(module => module.ModuleName.Contains("Bootstrapper")); + } + catch + { + // Sometimes this happens because of x32 vs x64 process interaction + } + if (containsToolkitDll) + { + return DiverState.Corpse; + } + + return DiverState.NoDiver; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs new file mode 100644 index 00000000..aee01986 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs @@ -0,0 +1,32 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Collections; + + +namespace RemoteNET.Internal; + +public class DynamicRemoteEnumerator(dynamic remoteEnumerator) : IEnumerator +{ + public object Current => remoteEnumerator.Current; + + public bool MoveNext() => remoteEnumerator.MoveNext(); + + public void Reset() => remoteEnumerator.Reset(); + + public void Dispose() + { + try + { + remoteEnumerator.Dispose(); + } + catch + { + // TODO: Handle IDisposable's Dispose method explicitly when expected + // by a using statement or a call to Dispose(). + } + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs new file mode 100644 index 00000000..25d34958 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs @@ -0,0 +1,606 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Dynamic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +using Microsoft.CSharp.RuntimeBinder; +using Binder = Microsoft.CSharp.RuntimeBinder.Binder; + +using ScubaDiver.API.Utils; + +using RemoteNET.Internal.ProxiedReflection; +using RemoteNET.Internal.Reflection; +using RemoteNET.Internal.Utils; + + +namespace RemoteNET.Internal; + +/// +/// A proxy of a remote object. +/// Usages of this class should be strictly as a `dynamic` variable. +/// Field/Property reads/writes are redirect to reading/writing to the fields of +/// the remote object, and method calls are redirected to functions calls in the +/// remote process on the remote object. +/// +[DebuggerDisplay("Dynamic Proxy of {" + nameof(__ro) + "}")] +public class DynamicRemoteObject : DynamicObject, IEnumerable +{ + public class DynamicRemoteMethod : DynamicObject + { + string _name; + ProxiedMethodGroup _methods; + DynamicRemoteObject _parent; + Type[] _genericArguments; + + public DynamicRemoteMethod( + string name, + DynamicRemoteObject parent, + ProxiedMethodGroup methods, + Type[] genericArguments = null) + { + genericArguments ??= Array.Empty(); + + _name = name; + _parent = parent; + _methods = methods; + + _genericArguments = genericArguments; + } + + public override bool TryInvoke( + InvokeBinder binder, + object[] args, + out object result) + => TryInvoke(args, out result); + + public bool TryInvoke(object[] args, out object result) + { + List overloads = _methods; + + // Narrow down (hopefuly to one) overload with the same amount of types + // TODO: We COULD possibly check the args types (local ones, + // RemoteObjects, DynamicObjects, ...) if we still have multiple results + overloads = overloads + .Where(overload => overload.GetParameters().Length == args.Length) + .ToList(); + + if (overloads.Count == 1) + { + // Easy case - a unique function name so we can just return it. + RemoteMethodInfo overload = overloads.Single(); + if (_genericArguments != null && _genericArguments.Any()) + { + if (!overload.IsGenericMethod) + { + throw new ArgumentException("A non-generic method was intialized with some generic arguments."); + } + else if (overload.IsGenericMethod + && overload.GetGenericArguments().Length != _genericArguments.Length) + { + throw new ArgumentException("Wrong number of generic arguments was provided to a generic method"); + } + // OK, invoking with generic arguments + result = overloads.Single() + .MakeGenericMethod(_genericArguments) + .Invoke(_parent.__ro, args); + } + else + { + if (overload.IsGenericMethod) + { + throw new ArgumentException("A generic method was intialized with no generic arguments."); + } + // OK, invoking without generic arguments + result = overloads.Single() + .Invoke(_parent.__ro, args); + } + } + else if (overloads.Count > 1) + { + // Multiple overloads. This sucks because we need to... return some "Router" func... + + throw new NotImplementedException($"Multiple overloads aren't supported at the moment. " + + $"Method `{_methods[0]}` had {overloads.Count} overloads registered."); + } + else // This case is for "overloads.Count == 0" + { + throw new ArgumentException($"Incorrent number of parameters provided to function.\n" + + $"After filtering all overloads with given amount of parameters ({args.Length}) we were left with 0 overloads."); + } + return true; + } + + public override bool Equals(object obj) + { + return obj is DynamicRemoteMethod method && + _name == method._name && + EqualityComparer.Default.Equals(_parent, method._parent) && + EqualityComparer.Default.Equals(_genericArguments, method._genericArguments); + } + + public override int GetHashCode() + { + int hashCode = -734779080; + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_name); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_parent); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_genericArguments); + return hashCode; + } + + // Functions to turn our base method into a "generic" one - with specific + // arguments instead of generic placeholders. I wish I could've overridden + // the 'MyFunc' notation but I don't think that syntax is modifiable in + // C#. + // + // Instead we go to the second best solution which is use indexers: + // MyFunc[typeof(T)] + // - or - + // Type t = typeof(T); + // MyFunc[t] + // + // Since some methods support multiple generic arguments I also overrode + // some multi-dimensional indexers below. This allows that to compile: + // Type t,p,q = ...; + // MyOtherFunc[t,p,q] + + public DynamicRemoteMethod this[Type t] => + new DynamicRemoteMethod(_name, _parent, _methods, + _genericArguments.Concat(new Type[] { t }).ToArray()); + + public DynamicRemoteMethod this[Type t1, Type t2] => + this[t1][t2]; + public DynamicRemoteMethod this[Type t1, Type t2, Type t3] => + this[t1, t2][t3]; + public DynamicRemoteMethod this[Type t1, Type t2, Type t3, Type t4] => + this[t1, t2, t3][t4]; + public DynamicRemoteMethod this[Type t1, Type t2, Type t3, Type t4, Type t5] => + this[t1, t2, t3, t4][t5]; + } + + public RemoteApp __ra; + public RemoteObject __ro; + public RemoteType __type; + + private IEnumerable __ongoingMembersDumper = null; + private IEnumerator __ongoingMembersDumperEnumerator = null; + private List __membersInner = null; + public IEnumerable __members => MindFuck(); + + public DynamicRemoteObject(RemoteApp ra, RemoteObject ro) + { + __ra = ra; + __ro = ro; + __type = ro.GetType() as RemoteType; + if (__type == null && ro.GetType() != null) + { + throw new ArgumentException("Can only create DynamicRemoteObjects of RemoteObjects with Remote Types. (As returned from GetType())"); + } + } + + public DynamicRemoteObject() // For avoiding overriding reference type + { + __ra = null; + __ro = null; + __type = null; + } + + /// + /// Gets the type of the proxied remote object, in the remote app. (This does not reutrn `typeof(DynamicRemoteMethod)`) + /// + public new Type GetType() => __type; + + private IEnumerable GetAllMembersRecursive() + { + Type lastType = __type; + Type nextType = __type; + + // We use this dictionary to make sure overides from subclasses don't get exported twice (for the parent as well) + Dictionary> _processedOverloads = new Dictionary>(); + do + { + var members = nextType.GetMembers((BindingFlags)0xffff); + foreach (MemberInfo member in members) + { + if (member is MethodBase newMethods) + { + if (!_processedOverloads.ContainsKey(member.Name)) + _processedOverloads[member.Name] = new List(); + List oldMethods = _processedOverloads[member.Name]; + + bool overridden = oldMethods.Any(oldMethod => oldMethod.SignatureEquals(newMethods)); + if (overridden) + continue; + + _processedOverloads[member.Name].Add(newMethods); + + } + yield return member; + } + lastType = nextType; + nextType = nextType.BaseType; + } + while (nextType != null && lastType != typeof(object)); + } + + private IEnumerable MindFuck() + { + if (__membersInner != null && __ongoingMembersDumper == null) + { + return __membersInner; + } + // Defining a new method so we can use "yield return" (Outer function + // already returned a "real" IEnumerable in the above case) so using + // "yield return" as well is forbidden. + IEnumerable Aggregator() + { + __membersInner ??= new List(); + __ongoingMembersDumper ??= GetAllMembersRecursive(); + __ongoingMembersDumperEnumerator ??= __ongoingMembersDumper.GetEnumerator(); + foreach (var member in __membersInner) + { + yield return member; + } + while(__ongoingMembersDumperEnumerator.MoveNext()) + { + var member = __ongoingMembersDumperEnumerator.Current; + __membersInner.Add(member); + yield return member; + } + __ongoingMembersDumper = null; + __ongoingMembersDumperEnumerator = null; + + }; + return Aggregator(); + } + + public T InvokeMethod(string name, params object[] args) + { + var matchingMethods = from member in __members + where member.Name == name + where ((MethodInfo)member).GetParameters().Length == args.Length + select member; + return (T)(matchingMethods.Single() as MethodInfo).Invoke(__ro, args); + } + + #region Dynamic Object API + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + Type lastType = __type; + Type nextType = __type; + do + { + bool found = TryGetMember(nextType, binder.Name, out result); + if (found) + return true; + lastType = nextType; + nextType = nextType.BaseType; + } + while (nextType != null || lastType == typeof(object)); + + result = null; + return false; + } + + private bool TryGetMember(Type t, string name, out object result) + { + result = null; + MemberInfo[] members = t.GetMembers((BindingFlags)0xffff); + List matches = members + .Where(member => member.Name == name) + .ToList(); + + if (!matches.Any()) + { + result = null; + return false; + } + + // At least 1 member with that name + MemberInfo firstMember = matches[0]; + MemberTypes type = firstMember.MemberType; + bool singleMatch = matches.Count == 1; + + switch (type) + { + case MemberTypes.Field: + // if (!singleMatch) + // { + // throw new ArgumentException($"Multiple members were found for the name `{name}` and at least one of them was a field"); + // } + try + { + result = ((FieldInfo)firstMember).GetValue(__ro); + } + catch (Exception ex) + { + throw new Exception($"Field \"{name}\"'s getter threw an exception", innerException: ex); + } + break; + case MemberTypes.Property: + // if (!singleMatch) + // { + // throw new ArgumentException($"Multiple members were found for the name `{name}` and at least one of them was a property"); + // } + try + { + result = ((PropertyInfo)firstMember).GetValue(__ro); + } + catch (Exception ex) + { + throw new Exception($"Property \"{name}\"'s getter threw an exception", innerException: ex); + } + break; + case MemberTypes.Method: + // The cases that get here are when the user is trying to: + // 1. Save a method in a variable: + // var methodGroup = dro.Insert; + // 2. The user is trying to use the "RemoteNET way" of specifing generic: + // Type t = typeof(SomeType); + // dro.Insert[t](); + result = GetMethodProxy(name); + break; + case MemberTypes.Event: + // TODO: + throw new NotImplementedException("Cannot hook to remote events yet."); + default: + throw new Exception($"No such member \"{name}\""); + } + return true; + } + + private DynamicRemoteMethod GetMethodProxy(string name) + { + var methods = __members + .Where(member => member.Name == name) + .ToArray(); + if (methods.Length == 0) + { + throw new Exception($"Method \"{name}\" wasn't found in the members of type {__type.Name}."); + } + + if (methods.Any(member => member.MemberType != MemberTypes.Method)) + { + throw new Exception($"A member called \"{name}\" exists in the type and it isn't a method (It's a {methods.First(m => m.MemberType != MemberTypes.Method).MemberType})"); + } + if (methods.Any(member => !(member is RemoteMethodInfo))) + { + throw new Exception($"A method overload for \"{name}\" wasn't a MethodInfo"); + } + + ProxiedMethodGroup methodGroup = new ProxiedMethodGroup(); + methodGroup.AddRange(methods.Cast()); + try + { + return new DynamicRemoteMethod(name, this, methodGroup); + } + catch (Exception ex) + { + + throw new Exception($"Constructing {nameof(DynamicRemoteMethod)} of \"{name}\" threw an exception", innerException: ex); + } + } + + public override bool TryInvokeMember( + InvokeMemberBinder binder, + object[] args, + out object result) + { + // If "TryInvokeMember" was called first (instead of "TryGetMember") + // it means that the user specified generic args (if any are even requied) + // within '<' and '>' signs or there aren't any generic args. We can just + // do the call here instead of letting the dynamic runtime resort to + // calling 'TryGetMember' + + DynamicRemoteMethod drm = GetMethodProxy(binder.Name); + Type binderType = binder.GetType(); + System.Reflection.PropertyInfo TypeArgumentsPropInfo = binderType.GetProperty("TypeArguments"); + if (TypeArgumentsPropInfo != null) + { + // We got ourself a binder which implemented .NET's internal + // "ICSharpInvokeOrInvokeMemberBinder" Interface: + // https://github.com/microsoft/referencesource/blob/master/Microsoft.CSharp/Microsoft/CSharp/ICSharpInvokeOrInvokeMemberBinder.cs + // + // We can now see if the invoked for the function specified generic types + // In that case, we can hijack and do the call here + // Otherwise - Just let TryGetMembre return a proxy + if (TypeArgumentsPropInfo.GetValue(binder) is IList genArgs) + { + foreach (Type t in genArgs) + { + // Aggregate the generic types into the dynamic remote method + // Example: + // * Invoke method is Insert<,> + // * Given types are ['T', 'S'] + // * First loop iteration: Inert<,> --> Insert + // * Second loop iteration: Inert --> Insert + drm = drm[t]; + } + } + } + return drm.TryInvoke(args, out result); + } + + public bool HasMember(string name) => + __members.Any(member => member.Name == name); + public override bool TrySetMember(SetMemberBinder binder, object value) + { + List matches = __members + .Where(member => member.Name == binder.Name) + .ToList(); + + if (!matches.Any()) + { + return false; + } + + // At least 1 member with that name + MemberInfo firstMember = matches[0]; + MemberTypes type = firstMember.MemberType; + bool singleMatch = matches.Count == 1; + + // In case we are resolving a field or property + switch (type) + { + case MemberTypes.Field: + // if (!singleMatch) + // { + // throw new ArgumentException($"Multiple members were found for the name `{binder.Name}` and at least one of them was a field"); + // } + try + { + ((FieldInfo)firstMember).SetValue(__ro, value); + } + catch (Exception ex) + { + throw new Exception($"Field \"{binder.Name}\"'s getter threw an exception", innerException: ex); + } + break; + case MemberTypes.Property: + // if (!singleMatch) + // { + // throw new ArgumentException($"Multiple members were found for the name `{binder.Name}` and at least one of them was a property"); + // } + try + { + ((PropertyInfo)firstMember).SetValue(__ro, value); + } + catch (Exception ex) + { + throw new Exception($"Property \"{binder.Name}\"'s getter threw an exception", innerException: ex); + } + break; + case MemberTypes.Method: + throw new Exception("Can't modifying method members."); + case MemberTypes.Event: + // TODO: + throw new NotImplementedException("Cannot hook to remote events yet."); + default: + throw new Exception($"No such member \"{binder.Name}\"."); + } + return true; + } + + /// + /// Helper function to access the member of the object . + /// This is equivilent to explicitly compiling the expression '.'. + /// + public static bool TryGetDynamicMember(object obj, string memberName, out object output) + { + var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, obj.GetType(), + new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); + var callsite = CallSite>.Create(binder); + if (obj is DynamicRemoteObject dro) + { + if (dro.HasMember(memberName)) + { + if (dro.TryGetMember(binder as GetMemberBinder, out output)) + { + return true; + } + } + } + + // Fallback? Does it always just result in TryGetMember? + try + { + output = callsite.Target(callsite, obj); + return true; + } + catch + { + output = null; + return false; + } + } +#endregion + + #region ToString / GetHashCode / Equals + + public override string ToString() => InvokeMethod(nameof(ToString)); + + public override int GetHashCode() => InvokeMethod(nameof(GetHashCode)); + + public override bool Equals(object obj) + { + throw new NotImplementedException($"Can not call `Equals` on {nameof(DynamicRemoteObject)} instances"); + } + #endregion + + /// + /// Array access. Key can be any primitive / RemoteObject / DynamicRemoteObject + /// + public dynamic this[object key] + { + get + { + + ScubaDiver.API.ObjectOrRemoteAddress ooraKey = RemoteFunctionsInvokeHelper.CreateRemoteParameter(key); + ScubaDiver.API.ObjectOrRemoteAddress item = __ro.GetItem(ooraKey); + if (item.IsNull) + { + return null; + } + else if (item.IsRemoteAddress) + { + return this.__ra.GetRemoteObject(item.RemoteAddress, item.Type).Dynamify(); + } + else + { + return PrimitivesEncoder.Decode(item.EncodedObject, item.Type); + } + } + set => throw new NotImplementedException(); + } + + #region Array Casting + private static T[] __cast_to_array(DynamicRemoteObject dro) + { + dynamic dyn = dro; + int length = dyn.Length; + T[] array = new T[length]; + for (int i = 0; i < length; i++) + array[i] = dyn[i]; + return array; + } + + public static implicit operator bool[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator byte[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator char[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator short[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator ushort[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator int[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator uint[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator long[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator ulong[](DynamicRemoteObject dro) => + __cast_to_array(dro); + public static implicit operator string[](DynamicRemoteObject dro) => + __cast_to_array(dro); + #endregion + + public IEnumerator GetEnumerator() + { + if (!__members.Any(member => member.Name == nameof(GetEnumerator))) + throw new Exception($"No method called {nameof(GetEnumerator)} found. The remote object probably doesn't implement IEnumerable"); + + dynamic enumeratorDro = InvokeMethod(nameof(GetEnumerator)); + return new DynamicRemoteEnumerator(enumeratorDro); + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs new file mode 100644 index 00000000..d695ce7d --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs @@ -0,0 +1,24 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using ScubaDiver.API.Interactions.Dumps; + + +namespace RemoteNET.Internal; + +public class DynamicRemoteObjectFactory +{ + private RemoteApp _app; + + public DynamicRemoteObject Create( + RemoteApp rApp, + RemoteObject remoteObj, + TypeDump typeDump) + { + _app = rApp; + return new DynamicRemoteObject(rApp, remoteObj); + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs new file mode 100644 index 00000000..169bdb0a --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs @@ -0,0 +1,12 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +namespace RemoteNET.Internal.ProxiedReflection; + +public interface IProxiedMember +{ + public ProxiedMemberType Type { get; } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs new file mode 100644 index 00000000..bb7bb8fe --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs @@ -0,0 +1,49 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + + +namespace RemoteNET.Internal.ProxiedReflection; + +public class ProxiedEventInfo(RemoteObject ro, string name, List args) + : IProxiedMember +{ + public ProxiedMemberType Type => ProxiedMemberType.Event; + + private readonly RemoteObject _ro = ro; + private string Name { get; set; } = name; + private List ArgumentsTypes { get; set; } = args; + + public static ProxiedEventInfo operator +(ProxiedEventInfo c1, Delegate x) + { + ParameterInfo[] parameters = x.Method.GetParameters(); + + if (parameters.Length != c1.ArgumentsTypes.Count) + { + throw new Exception($"The '{c1.Name}' event expects {c1.ArgumentsTypes.Count} parameters, " + + $"the callback that was being registered have {parameters.Length}"); + } + + if (parameters.Any(p => p.GetType().IsAssignableFrom(typeof(DynamicRemoteObject)))) + { + throw new Exception("A Remote event's local callback must have only 'dynamic' parameters"); + } + + c1._ro.EventSubscribe(c1.Name, x); + + return c1; + } + + public static ProxiedEventInfo operator -(ProxiedEventInfo c1, Delegate x) + { + c1._ro.EventUnsubscribe(c1.Name, x); + return c1; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs new file mode 100644 index 00000000..0cc8708c --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs @@ -0,0 +1,16 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +namespace RemoteNET.Internal.ProxiedReflection; + +public enum ProxiedMemberType +{ + Unknown, + Field, + Property, + Method, + Event +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs new file mode 100644 index 00000000..68c3e3d3 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs @@ -0,0 +1,15 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Collections.Generic; + +using RemoteNET.Internal.Reflection; + + +namespace RemoteNET.Internal.ProxiedReflection; + +public class ProxiedMethodGroup : List +{ } diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs new file mode 100644 index 00000000..dece12e5 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs @@ -0,0 +1,23 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; + +using RemoteNET.Internal.Reflection; + + +namespace RemoteNET.Internal.ProxiedReflection; + +public class ProxiedMethodOverload +{ + public Type ReturnType { get; set; } + public List Parameters { get; set; } + public Func Proxy => (object[] arr) => GenericProxy(null, arr); + public Func GenericProxy { get; set; } + public List GenericArgs { get; set; } + public bool IsGenericMethod => GenericArgs?.Count > 0; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs new file mode 100644 index 00000000..4e49178a --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs @@ -0,0 +1,22 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; + + +namespace RemoteNET.Internal.ProxiedReflection; + +/// +/// Info of proxied field or property +/// +public class ProxiedValueMemberInfo(ProxiedMemberType type) : IProxiedMember +{ + public string FullTypeName { get; set; } + public Action Setter { get; set; } + public Func Getter { get; set; } + + public ProxiedMemberType Type { get; set; } = type; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs new file mode 100644 index 00000000..092d94fa --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs @@ -0,0 +1,187 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Globalization; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +public class DummyGenericType(string name) : Type +{ + public override Module Module { get; } + public override string Namespace { get; } + + public override string Name => name; + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + protected override TypeAttributes GetAttributeFlagsImpl() + { + throw new NotImplementedException(); + } + + protected override ConstructorInfo GetConstructorImpl( + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetElementType() + { + throw new NotImplementedException(); + } + + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override EventInfo[] GetEvents(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override FieldInfo GetField(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override FieldInfo[] GetFields(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override MemberInfo[] GetMembers(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + protected override MethodInfo GetMethodImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override object InvokeMember( + string name, + BindingFlags invokeAttr, + Binder binder, + object target, + object[] args, + ParameterModifier[] modifiers, + CultureInfo culture, + string[] namedParameters) + { + throw new NotImplementedException(); + } + + public override Type UnderlyingSystemType { get; } + + protected override bool IsArrayImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsByRefImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsCOMObjectImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPointerImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPrimitiveImpl() + { + throw new NotImplementedException(); + } + + public override Assembly Assembly { get; } + public override string AssemblyQualifiedName { get; } + public override Type BaseType { get; } + public override string FullName { get; } + public override Guid GUID { get; } + + protected override PropertyInfo GetPropertyImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + Type returnType, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + protected override bool HasElementTypeImpl() + { + throw new NotImplementedException(); + } + + public override Type GetNestedType(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type[] GetNestedTypes(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetInterface(string name, bool ignoreCase) + { + throw new NotImplementedException(); + } + + public override Type[] GetInterfaces() + { + throw new NotImplementedException(); + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs new file mode 100644 index 00000000..1ef31da7 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs @@ -0,0 +1,22 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Dynamic; + + +namespace RemoteNET.Internal.Reflection; + +public class DynamicRemoteEnum(RemoteEnum remoteEnum) : DynamicObject +{ + public RemoteApp App => remoteEnum.App; + + public override bool TryGetMember(GetMemberBinder binder, out dynamic result) + { + string memberName = binder.Name; + result = remoteEnum.GetValue(memberName); + return true; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs new file mode 100644 index 00000000..b85362ea --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs @@ -0,0 +1,42 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; + + +namespace RemoteNET.Internal.Reflection; + +public class LazyRemoteTypeResolver +{ + private Lazy _factory; + private string _beforeDumpingTypeName; + private string _beforeDumpingAssemblyName; + private Type _resolved; + + public string Assembly => _resolved?.Assembly?.FullName ?? _beforeDumpingAssemblyName; + public string TypeFullName => _resolved?.FullName ?? _beforeDumpingTypeName; + + public Type Value + { + get + { + _resolved ??= _factory.Value; + return _resolved; + } + } + + public LazyRemoteTypeResolver(Lazy factory, string assembly, string typeFullName) + { + _factory = factory; + _beforeDumpingAssemblyName = assembly; + _beforeDumpingTypeName = typeFullName; + } + + public LazyRemoteTypeResolver(Type resolved) + { + _resolved = resolved; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs new file mode 100644 index 00000000..d76cf6b0 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs @@ -0,0 +1,96 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +public class RemoteConstructorInfo(Type declaringType, + ParameterInfo[] paramInfos) : ConstructorInfo +{ + public override MethodAttributes Attributes => throw new NotImplementedException(); + + public override RuntimeMethodHandle MethodHandle => throw new NotImplementedException(); + + public override Type DeclaringType { get; } = declaringType; + + public override string Name => ".ctor"; + + public override Type ReflectedType => throw new NotImplementedException(); + + private RemoteApp App => (DeclaringType as RemoteType)?.App; + + public RemoteConstructorInfo(RemoteType declaringType, ConstructorInfo ci) : + this(declaringType, + ci.GetParameters().Select(pi => + new RemoteParameterInfo(pi)).Cast().ToArray()) + { } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override MethodImplAttributes GetMethodImplementationFlags() + { + throw new NotImplementedException(); + } + + public override ParameterInfo[] GetParameters() => paramInfos; + + public override object Invoke( + BindingFlags invokeAttr, + Binder binder, + object[] parameters, + CultureInfo culture) + { + return RemoteFunctionsInvokeHelper + .Invoke( + App, + DeclaringType, + Name, + null, + new Type[0], + parameters); + } + + public override object Invoke( + object obj, + BindingFlags invokeAttr, + Binder binder, + object[] parameters, + CultureInfo culture) + { + // Empirically, invoking a ctor on an existing object should return null. + if (obj == null) + { + // Last chance - If this overload was used but no real object given lets + // redirect to normal Invoke (also happens with normal 'ConstructorInfo's) + return Invoke(invokeAttr, binder, parameters, culture); + } + return null; + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override string ToString() + { + string args = string.Join(", ", paramInfos.Select(pi => pi.ParameterType.FullName)); + return $"Void {this.Name}({args})"; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs new file mode 100644 index 00000000..45e0e14b --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs @@ -0,0 +1,28 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +namespace RemoteNET.Internal.Reflection; + +public class RemoteEnum(RemoteType remoteType) +{ + public RemoteApp App => remoteType?.App; + + public object GetValue(string valueName) + { + // NOTE: This is breaking the "RemoteX"/"DynamicX" paradigm because we are + // effectively returning a DRO here. + // + // Unlike RemoteObject which directly uses a remote token + TypeDump to + // read/write fields/props/methods, RemoteEnum was created after + // RemoteType was defined and it felt much easier to utilize it. + // + // RemoteType itself, as part of the reflection API, returns DROs. + RemoteFieldInfo verboseField = remoteType.GetField(valueName) as RemoteFieldInfo; + return verboseField.GetValue(null); + } + + public dynamic Dynamify() => new DynamicRemoteEnum(this); +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs new file mode 100644 index 00000000..1623d6ce --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs @@ -0,0 +1,72 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +public class RemoteEventInfo( + RemoteType declaringType, + Lazy eventHandlerType, + string name) : EventInfo +{ + public override EventAttributes Attributes => + throw new NotImplementedException(); + + public override Type DeclaringType { get; } = declaringType; + + public override string Name { get; } = name; + + public override Type ReflectedType => + throw new NotImplementedException(); + + public RemoteMethodInfo RemoteAddMethod { get; set; } + public RemoteMethodInfo RemoteRemoveMethod { get; set; } + public override MethodInfo AddMethod => RemoteAddMethod; + public override MethodInfo RemoveMethod => RemoteRemoveMethod; + + public override Type EventHandlerType => eventHandlerType.Value; + + public RemoteEventInfo( + RemoteType declaringType, + Type eventHandlerType, + string name) + : this(declaringType, new Lazy(() => eventHandlerType), name) + { } + + public RemoteEventInfo( + RemoteType declaringType, + EventInfo ei) + : this(declaringType, new Lazy(() => ei.EventHandlerType), ei.Name) + { } + + public override MethodInfo GetAddMethod(bool nonPublic) => RemoteAddMethod; + public override MethodInfo GetRemoveMethod(bool nonPublic) => RemoteRemoveMethod; + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override MethodInfo GetRaiseMethod(bool nonPublic) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override string ToString() => $"{eventHandlerType.Value} {Name}"; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs new file mode 100644 index 00000000..062f372b --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs @@ -0,0 +1,162 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Globalization; +using System.Reflection; + +using ScubaDiver.API; +using ScubaDiver.API.Utils; + + +namespace RemoteNET.Internal.Reflection; + +public class RemoteFieldInfo( + Type declaringType, + Lazy fieldType, + string name) : FieldInfo +{ + private RemoteApp App => (DeclaringType as RemoteType)?.App; + + public override Type FieldType => fieldType.Value; + public override Type DeclaringType { get; } = declaringType; + public override string Name { get; } = name; + + public RemoteFieldInfo(Type declaringType, Type fieldType, string name) + : this(declaringType, new Lazy(() => fieldType), name) + { } + + public RemoteFieldInfo(RemoteType declaringType, FieldInfo fi) + : this(declaringType, new Lazy(()=> fi.FieldType), fi.Name) + { } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override Type ReflectedType { get; } + public override object GetValue(object obj) + { + ObjectOrRemoteAddress oora = null; + if (obj == null) + { + // No 'this' object --> Static field + + if (App == null) + { + throw new InvalidOperationException( + $"Trying to get a static field (null target object) " + + $"on a {nameof(RemoteFieldInfo)} but it's associated " + + $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); + } + + oora = App.Communicator.GetField(0, DeclaringType.FullName, Name).ReturnedObjectOrAddress; + } + else + { + // obj is NOT null. Make sure it's a RemoteObject or DynamicRemoteObject. + RemoteObject ro = obj as RemoteObject; + ro ??= (obj as DynamicRemoteObject)?.__ro; + if (ro != null) + { + oora = ro.GetField(Name); + } + else + { + throw new NotImplementedException( + $"{nameof(RemoteFieldInfo)}.{nameof(GetValue)} only supports {nameof(RemoteObject)} or {nameof(DynamicRemoteObject)} targets."); + } + } + + if (oora == null) + { + string offendingFunc = obj == null ? $"{nameof(DiverCommunicator)}.{nameof(DiverCommunicator.GetField)}" : $"{nameof(RemoteObject)}.{nameof(RemoteObject.GetField)}"; + throw new Exception($"Could not get {nameof(ObjectOrRemoteAddress)} object. Seems like invoking {offendingFunc} returned null."); + } + else + { + if (oora.IsRemoteAddress) + { + var remoteObject = App.GetRemoteObject(oora.RemoteAddress, oora.Type); + return remoteObject.Dynamify(); + } + else if (oora.IsNull) + { + return null; + } + // Primitive + return PrimitivesEncoder.Decode(oora.EncodedObject, oora.Type); + } + } + + public override void SetValue( + object obj, + object value, + BindingFlags invokeAttr, + Binder binder, + CultureInfo culture) + { + var val = value; + if (val.GetType().IsEnum) + { + var enumClass = App.GetRemoteEnum(val.GetType().FullName); + // TODO: This will break on the first enum value which represents 2 or more flags + object enumVal = enumClass.GetValue(val.ToString()); + // NOTE: Object stays in place in the remote app as long as we have it's reference + // in the the value variable(so untill end of this method) + value = enumVal; + } + + // Might throw if the parameter is a local object (not RemoteObject or DynamicRemoteObject). + ObjectOrRemoteAddress remoteNewValue = RemoteFunctionsInvokeHelper.CreateRemoteParameter(value); + + if (obj == null) + { + // No 'this' object --> Static field + + if (App == null) + { + throw new InvalidOperationException( + $"Trying to get a static field (null target object) " + + $"on a {nameof(RemoteFieldInfo)} but it's associated " + + $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); + } + + App.Communicator.SetField(0, DeclaringType.FullName, Name, remoteNewValue); + return; + } + + // obj is NOT null. Make sure it's a RemoteObject or DynamicRemoteObject. + RemoteObject ro = obj as RemoteObject; + ro ??= (obj as DynamicRemoteObject)?.__ro; + if (ro != null) + { + ro.SetField(Name, remoteNewValue); + return; + } + + throw new NotImplementedException( + $"{nameof(RemoteFieldInfo)}.{nameof(SetValue)} only supports {nameof(RemoteObject)} or {nameof(DynamicRemoteObject)} targets."); + } + + public override FieldAttributes Attributes { get; } + public override RuntimeFieldHandle FieldHandle { get; } + + public override string ToString() => $"{FieldType.FullName} {Name}"; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs new file mode 100644 index 00000000..e7c53ea9 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs @@ -0,0 +1,156 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Linq; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions; +using ScubaDiver.API.Utils; + + +namespace RemoteNET.Internal.Reflection; + +/// +/// In this context: "function" = Methods + Constructors. +/// +internal static class RemoteFunctionsInvokeHelper +{ + public static ObjectOrRemoteAddress CreateRemoteParameter(object parameter) + { + if(parameter == null) + { + return ObjectOrRemoteAddress.Null; + } + else if (parameter.GetType().IsPrimitiveEtc() + || parameter.GetType().IsPrimitiveEtcArray() + || parameter.GetType().IsStringCoercible()) + { + return ObjectOrRemoteAddress.FromObj(parameter); + } + else if (parameter is RemoteObject remoteArg) + { + return ObjectOrRemoteAddress + .FromToken(remoteArg.RemoteToken, remoteArg.GetType().FullName); + } + else if (parameter is DynamicRemoteObject dro) + { + RemoteObject originRemoteObject = dro.__ro; + return ObjectOrRemoteAddress + .FromToken(originRemoteObject.RemoteToken, originRemoteObject.GetType().FullName); + } + else if (parameter is Type t) + { + return ObjectOrRemoteAddress.FromType(t); + } + else + { + throw new Exception( + $"{nameof(RemoteMethodInfo)}.{nameof(Invoke)} only works with primitive (int, " + + $"double, string,...) or remote (in {nameof(RemoteObject)}) parameters. " + + $"One of the parameter was of unsupported type {parameter.GetType()}"); + } + } + + public static object Invoke( + RemoteApp app, + Type declaringType, + string funcName, + object obj, + Type[] genericArgs, + object[] parameters) + => Invoke( + app, + declaringType, + funcName, + obj, + genericArgs.Select(arg => arg.FullName).ToArray(), + parameters); + + public static object Invoke( + RemoteApp app, + Type declaringType, + string funcName, + object obj, + string[] genericArgsFullNames, + object[] parameters) + { + // invokeAttr, binder and culture currently ignored + // TODO: Actually validate parameters and expected parameters. + + object[] paramsNoEnums = parameters.ToArray(); + for (int i = 0; i < paramsNoEnums.Length; i++) + { + var val = paramsNoEnums[i]; + if (val != null && val.GetType().IsEnum) + { + var enumClass = app.GetRemoteEnum(val.GetType().FullName); + // TODO: This will break on the first enum value which represents 2 or more flags + object enumVal = enumClass.GetValue(val.ToString()); + // NOTE: Object stays in place in the remote app as long as we have it's reference + // in the paramsNoEnums array (so untill end of this method) + paramsNoEnums[i] = enumVal; + } + } + + ObjectOrRemoteAddress[] remoteParams = paramsNoEnums + .Select(CreateRemoteParameter) + .ToArray(); + + bool hasResults; + ObjectOrRemoteAddress oora; + if (obj == null) + { + if (app == null) + { + throw new InvalidOperationException( + $"Trying to invoke a static call (null target object) " + + $"on a {nameof(RemoteMethodInfo)} but it's associated " + + $"Declaring Type ({declaringType}) does not have a RemoteApp associated. " + + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); + } + + InvocationResults invokeRes = app.Communicator + .InvokeStaticMethod(declaringType.FullName, funcName, genericArgsFullNames, remoteParams); + if (invokeRes.VoidReturnType) + { + hasResults = false; + oora = null; + } + else + { + hasResults = true; + oora = invokeRes.ReturnedObjectOrAddress; + } + } + else + { + // obj is NOT null. Make sure it's a RemoteObject. + if (!(obj is RemoteObject ro)) + { + throw new NotImplementedException( + $"{nameof(RemoteMethodInfo)}.{nameof(Invoke)} only supports {nameof(RemoteObject)} targets at the moment."); + } + (hasResults, oora) = ro.InvokeMethod(funcName, genericArgsFullNames, remoteParams); + } + + if (!hasResults) + return null; + + // Non-void function. + if (oora.IsNull) + return null; + if (!oora.IsRemoteAddress) + { + return PrimitivesEncoder.Decode(oora); + } + else + { + RemoteObject ro = app.GetRemoteObject(oora.RemoteAddress, oora.Type); + return ro.Dynamify(); + } + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs new file mode 100644 index 00000000..ad78a327 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs @@ -0,0 +1,132 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Globalization; +using System.Linq; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +public class RemoteMethodInfo( + Type declaringType, + LazyRemoteTypeResolver returnType, + string name, + Type[] genericArgs, + ParameterInfo[] paramInfos) : MethodInfo +{ + public override ICustomAttributeProvider ReturnTypeCustomAttributes => + throw new NotImplementedException(); + + public override string Name { get; } = name; + + public override Type DeclaringType { get; } = declaringType; + + public override Type ReturnType => returnType.Value; + + public override Type ReflectedType => + throw new NotImplementedException(); + + public override RuntimeMethodHandle MethodHandle => + throw new NotImplementedException(); + + public override MethodAttributes Attributes => + throw new NotImplementedException(); + + public override bool IsGenericMethod => + AssignedGenericArgs.Length > 0; + + public override bool IsGenericMethodDefinition => + AssignedGenericArgs.Length > 0 && + AssignedGenericArgs.All(t => t is DummyGenericType); + + public override bool ContainsGenericParameters => + AssignedGenericArgs.Length > 0 && + AssignedGenericArgs.All(t => t is DummyGenericType); + + public override Type[] GetGenericArguments() => + AssignedGenericArgs; + + public Type[] AssignedGenericArgs { get; } = genericArgs ?? Type.EmptyTypes; + + private RemoteApp App => (DeclaringType as RemoteType)?.App; + + public RemoteMethodInfo(RemoteType declaringType, MethodInfo mi) : + this(declaringType, + new LazyRemoteTypeResolver(mi.ReturnType), + mi.Name, + mi.GetGenericArguments(), + mi.GetParameters() + .Select(pi => new RemoteParameterInfo(pi)) + .Cast() + .ToArray()) + {} + + public RemoteMethodInfo( + Type declaringType, + Type returnType, + string name, + Type[] genericArgs, + ParameterInfo[] paramInfos) : this(declaringType, new LazyRemoteTypeResolver(returnType), name, genericArgs, paramInfos) + { } + + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) + { + return new RemoteMethodInfo(DeclaringType, ReturnType, Name, typeArguments, paramInfos); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override ParameterInfo[] GetParameters() => paramInfos; + + public override MethodImplAttributes GetMethodImplementationFlags() + { + throw new NotImplementedException(); + } + + public override object Invoke( + object obj, + BindingFlags invokeAttr, + Binder binder, + object[] parameters, + CultureInfo culture) + { + return RemoteFunctionsInvokeHelper + .Invoke(this.App, DeclaringType, Name, obj, AssignedGenericArgs, parameters); + } + + public override MethodInfo GetBaseDefinition() + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override string ToString() + { + try + { + string args = string.Join(", ", paramInfos.Select(pi => pi.ToString())); + return $"{returnType.TypeFullName} {Name}({args})"; + } + catch (Exception) + { + throw; + } + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs new file mode 100644 index 00000000..15b2c75b --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs @@ -0,0 +1,30 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +/// +/// A parameter of a remote method. The parameter's type itself might be a remote type (but can also be local) +/// +public class RemoteParameterInfo( + string name, + LazyRemoteTypeResolver paramType) : ParameterInfo +{ + public override string Name { get; } = name; + + public override Type ParameterType => paramType.Value; + + // TODO: Type needs to be converted to a remote type ? + public RemoteParameterInfo(ParameterInfo pi) + : this(pi.Name, new LazyRemoteTypeResolver(pi.ParameterType)) + { } + + public override string ToString() => $"{paramType.TypeFullName} {Name}"; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs new file mode 100644 index 00000000..44364111 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs @@ -0,0 +1,112 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Globalization; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +public class RemotePropertyInfo(Type declaringType, Lazy propType, string name) : PropertyInfo +{ + private RemoteApp App => (DeclaringType as RemoteType)?.App; + public override PropertyAttributes Attributes => + throw new NotImplementedException(); + + public override bool CanRead => GetMethod != null; + public override bool CanWrite => SetMethod != null; + + public override Type PropertyType => propType.Value; + + public override Type DeclaringType { get; } = declaringType; + + public override string Name { get; } = name; + + public override Type ReflectedType => + throw new NotImplementedException(); + + public RemoteMethodInfo RemoteGetMethod { get; set; } + public RemoteMethodInfo RemoteSetMethod { get; set; } + + public override MethodInfo GetMethod => RemoteGetMethod; + public override MethodInfo SetMethod => RemoteSetMethod; + + public RemotePropertyInfo(Type declaringType, Type propType, string name) : + this(declaringType, new Lazy(() => propType), name) + {} + + public RemotePropertyInfo(RemoteType declaringType, PropertyInfo pi) + : this(declaringType, new Lazy(() => pi.PropertyType), pi.Name) + {} + + public override MethodInfo[] GetAccessors(bool nonPublic) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override MethodInfo GetGetMethod(bool nonPublic) => this.GetMethod; + public override MethodInfo GetSetMethod(bool nonPublic) => this.SetMethod; + + public override ParameterInfo[] GetIndexParameters() + { + throw new NotImplementedException(); + } + + public override object GetValue( + object obj, + BindingFlags invokeAttr, + Binder binder, + object[] index, + CultureInfo culture) + { + RemoteMethodInfo getMethod = GetGetMethod() as RemoteMethodInfo; + if (getMethod != null) + { + return getMethod.Invoke(obj, new object[0]); + } + else + { + throw new Exception($"Couldn't retrieve 'get' method of property '{this.Name}'"); + } + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override void SetValue( + object obj, + object value, + BindingFlags invokeAttr, + Binder binder, + object[] index, + CultureInfo culture) + { + RemoteMethodInfo setMethod = GetSetMethod() as RemoteMethodInfo; + if (setMethod != null) + { + setMethod.Invoke(obj, new object[1] { value }); + } + else + { + throw new Exception($"Couldn't retrieve 'set' method of property '{this.Name}'"); + } + } + + public override string ToString() => $"{PropertyType.FullName} {Name}"; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs new file mode 100644 index 00000000..83217624 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs @@ -0,0 +1,338 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +internal class RemoteAssemblyDummy(string assemblyName) : Assembly +{ + private AssemblyName name = new(assemblyName); + + public override string FullName => + throw new Exception( + $"You tried to get the 'FullName' property on a {nameof(RemoteAssemblyDummy)}." + + $"Currently, this is forbidden to reduce confusion between 'full name' and 'short name'." + + $"You should call 'GetName().Name' instead."); + + public override AssemblyName GetName() => name; +} + +public class RemoteType : Type +{ + private readonly List _ctors = new List(); + private readonly List _methods = new List(); + private readonly List _fields = new List(); + private readonly List _properties = new List(); + private readonly List _events = new List(); + private readonly bool _isArray; + private readonly bool _isGenericParameter; + + public RemoteApp App { get; set; } + + public override bool IsGenericParameter => _isGenericParameter; + + private Lazy _parent; + public override Type BaseType => _parent?.Value; + + public RemoteType(RemoteApp app, Type localType) + : this(app, localType.FullName, localType.Assembly.GetName().Name, localType.IsArray, localType.IsGenericParameter) + { + if (localType is RemoteType) + { + throw new ArgumentException("This constructor of RemoteType is designed to copy a LOCAL Type object. A RemoteType object was provided instead."); + } + + // TODO: This ctor is experimentatl because it makes a LOT of assumptions. + // Most notably the RemoteXXXInfo objects freely use mi's,ci's,pi's (etc) "ReturnType","FieldType","PropertyType" + // not checking if they are actually RemoteTypes themselves... + + foreach (MethodInfo mi in localType.GetMethods()) + AddMethod(new RemoteMethodInfo(this, mi)); + foreach (ConstructorInfo ci in localType.GetConstructors()) + AddConstructor(new RemoteConstructorInfo(this, ci)); + foreach (PropertyInfo pi in localType.GetProperties()) + { + RemotePropertyInfo remotePropInfo = new RemotePropertyInfo(this, pi); + remotePropInfo.RemoteGetMethod = _methods.FirstOrDefault(m => m.Name == "get_" + pi.Name); + remotePropInfo.RemoteSetMethod = _methods.FirstOrDefault(m => m.Name == "set_" + pi.Name); + AddProperty(remotePropInfo); + } + foreach (FieldInfo fi in localType.GetFields()) + AddField(new RemoteFieldInfo(this, fi)); + foreach (EventInfo ei in localType.GetEvents()) + AddEvent(new RemoteEventInfo(this, ei)); + } + + public RemoteType( + RemoteApp app, + string fullName, + string assemblyName, + bool isArray, + bool isGenericParameter = false) + { + App = app; + FullName = fullName; + _isGenericParameter = isGenericParameter; + _isArray = isArray; + Assembly = new RemoteAssemblyDummy(assemblyName); + + // Derieving name from full name + Name = fullName.Substring(fullName.LastIndexOf('.') + 1); + if (fullName.Contains("`")) + { + // Generic. Need to cut differently + string outterTypeFullName = fullName.Substring(0, fullName.IndexOf('`')); + Name = outterTypeFullName.Substring(outterTypeFullName.LastIndexOf('.') + 1); + } + } + + public void AddConstructor(RemoteConstructorInfo rci) + { + _ctors.Add(rci); + } + + public void AddMethod(RemoteMethodInfo rmi) + { + _methods.Add(rmi); + } + + public void AddField(RemoteFieldInfo fieldInfo) + { + _fields.Add(fieldInfo); + } + public void AddProperty(RemotePropertyInfo fieldInfo) + { + _properties.Add(fieldInfo); + } + public void AddEvent(RemoteEventInfo eventInfo) + { + _events.Add(eventInfo); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => + _ctors.Cast().ToArray(); + + public override Type GetInterface(string name, bool ignoreCase) + { + throw new NotImplementedException(); + } + + public override Type[] GetInterfaces() + { + throw new NotImplementedException(); + } + + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + { + return GetEvents().Single(ei => ei.Name == name); + } + + public override EventInfo[] GetEvents(BindingFlags bindingAttr) + { + return _events.ToArray(); + } + + public override Type[] GetNestedTypes(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetNestedType(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetElementType() + { + throw new NotImplementedException(); + } + + protected override bool HasElementTypeImpl() + { + throw new NotImplementedException(); + } + + protected override PropertyInfo GetPropertyImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + Type returnType, + Type[] types, + ParameterModifier[] modifiers) + { + return GetProperties().Single(prop => prop.Name == name); + } + + public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + return _properties.ToArray(); + } + + protected override MethodInfo GetMethodImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + var methodGroup = GetMethods().Where(method => + method.Name == name); + if (types == null) + { + // Parameters unknown from caller. Hope we have only one method to return. + return methodGroup.Single(); + } + + bool overloadsComparer(MethodInfo method) + { + var parameters = method.GetParameters(); + // Compare Full Names mainly because the RemoteMethodInfo contains + // RemoteParameterInfos and we might be comparing with local parameters + // (like System.String) + bool matchingExpectingTypes = parameters + .Select(arg => arg.ParameterType.FullName) + .SequenceEqual(types.Select(type => type.FullName)); + return matchingExpectingTypes; + } + + // Need to filer also by types + return methodGroup.Single(overloadsComparer); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + return _methods.ToArray(); + } + + public override FieldInfo GetField(string name, BindingFlags bindingAttr) + { + return GetFields().Single(field => field.Name == name); + } + + public override FieldInfo[] GetFields(BindingFlags bindingAttr) + { + return _fields.ToArray(); + } + + private IEnumerable GetMembersInner(BindingFlags bf) + { + foreach (var ctor in GetConstructors(bf)) + { + yield return ctor; + } + foreach (var field in GetFields(bf)) + { + yield return field; + } + foreach (var prop in GetProperties(bf)) + { + yield return prop; + } + foreach (var eventt in GetEvents(bf)) + { + yield return eventt; + } + foreach (var method in GetMethods(bf)) + { + yield return method; + } + } + + internal void SetParent(Lazy parent) + { + _parent = parent; + } + + public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => + GetMembersInner(bindingAttr).ToArray(); + + protected override TypeAttributes GetAttributeFlagsImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsArrayImpl() + { + return _isArray; + } + + protected override bool IsByRefImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPointerImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPrimitiveImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsCOMObjectImpl() + { + throw new NotImplementedException(); + } + + public override object InvokeMember( + string name, + BindingFlags invokeAttr, + Binder binder, + object target, + object[] args, + ParameterModifier[] modifiers, + CultureInfo culture, + string[] namedParameters) + { + throw new NotImplementedException(); + } + + public override Type UnderlyingSystemType { get; } + + protected override ConstructorInfo GetConstructorImpl( + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override string Name { get; } + public override Guid GUID { get; } + public override Module Module { get; } + public override Assembly Assembly { get; } + public override string FullName { get; } + public override string Namespace { get; } + public override string AssemblyQualifiedName { get; } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override string ToString() => FullName; +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs new file mode 100644 index 00000000..7025c9da --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs @@ -0,0 +1,359 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions.Dumps; + + +namespace RemoteNET.Internal.Reflection; + +public class RemoteTypesFactory(TypesResolver resolver, + DiverCommunicator communicator) +{ + /// + /// This collection marks which types the factory is currently creating + /// it's important since might recursively call itself and + /// types might depend on one another (circular references) + /// + private readonly Dictionary, Type> _onGoingCreations = + new Dictionary, Type>(); + + public Type ResolveTypeWhileCreating( + RemoteApp app, + string typeInProgress, + string methodName, + string assembly, + string type) + { + if (type.Length > 200) + { + if (type.Contains("[][][][][][]")) + { + throw new Exception("Nestered self arrays types was detected and avoided."); + } + } + if (type.Length > 500) + { + // Too long for any reasonable type + throw new Exception("Incredibly long type names aren't supported."); + } + if (type.Contains("JetBrains.DataFlow.PropertyChangedEventArgs") && type.Length > 100) + { + // Too long for any reasonable type + throw new Exception("Incredibly long type names aren't supported."); + } + + + Type paramType = resolver.Resolve(assembly, type); + if (paramType != null) + { + // Either found in cache or found locally. + + // If it's a local non-primitive type we need to wrap it in a "fake" + // RemoteType (So method invocations will happen on the remote app) + if (!(paramType is RemoteType) && !paramType.IsPrimitive) + { + paramType = new RemoteType(app, paramType); + // TODO: Registring here in the cache is a hack but we couldn't + // register within "TypesResolver.Resolve" because we don't have the + // RemoteApp to associate the fake remote type with. + // + // Maybe this should move somewhere else... + resolver.RegisterType(paramType); + } + } + + if (paramType == null) + { + // Second: Search types which are on-going creation + if (!_onGoingCreations.TryGetValue( + new Tuple(assembly, type), out paramType) || paramType == null) + { + TypeDump dumpedArgType = + communicator.DumpType(type, assembly); + if (dumpedArgType == null) + { + throw new Exception( + $"{nameof(RemoteTypesFactory)} tried to dump type {type} when handling method {methodName} of type" + + $"{typeInProgress} but the {nameof(DiverCommunicator)}.{nameof(DiverCommunicator.DumpType)} function failed."); + } + + Type newCreatedType = Create(app, dumpedArgType); + paramType = newCreatedType + ?? throw new Exception( + $"{nameof(RemoteTypesFactory)} tried to dump type {type} when handling method {methodName} of type" + + $"{typeInProgress} but the inner {nameof(RemoteTypesFactory)}.{nameof(RemoteTypesFactory.Create)} function failed."); + } + } + return paramType; + } + + private Type Create(RemoteApp app, string fullTypeName, string assembly) + { + Type shortOutput = resolver.Resolve(assembly, fullTypeName); + if (shortOutput != null) + { + return shortOutput; + } + + TypeDump parentDump = communicator.DumpType(fullTypeName, assembly) + ?? throw new Exception( + $"{nameof(RemoteTypesFactory)} tried to dump type {fullTypeName} " + + $"but the {nameof(DiverCommunicator)}.{nameof(DiverCommunicator.DumpType)} function failed."); + return Create(app, parentDump); + } + + public Type Create(RemoteApp app, TypeDump typeDump) + { + Type shortOutput = resolver.Resolve(typeDump.Assembly, typeDump.Type); + if (shortOutput != null) + { + return shortOutput; + } + + RemoteType output = new RemoteType(app, typeDump.Type, typeDump.Assembly, typeDump.IsArray); + + // Temporarily indicate we are on-going creation + _onGoingCreations[new Tuple(typeDump.Assembly, typeDump.Type)] = output; + + string parentType = typeDump.ParentFullTypeName; + if (parentType != null) + { + Lazy parent = new Lazy(() => + { + try + { + return Create(app, parentType, typeDump.ParentAssembly); + } + catch (Exception ex) + { + Debug.WriteLine("Failed to dump parent type: " + parentType); + Debug.WriteLine(ex.ToString()); + return null; + } + }); + output.SetParent(parent); + } + AddMembers(app, typeDump, output); + + // remove on-going creation indication + _onGoingCreations.Remove(new Tuple(typeDump.Assembly, typeDump.Type)); + + // Register at resolver + resolver.RegisterType(typeDump.Assembly, typeDump.Type, output); + + return output; + } + + private void AddMembers(RemoteApp app, TypeDump typeDump, RemoteType output) + { + AddGroupOfFunctions(app, typeDump, typeDump.Methods, output, areConstructors: false); + AddGroupOfFunctions(app, typeDump, typeDump.Constructors, output, areConstructors: true); + AddFields(app, typeDump, output); + AddProperties(app, typeDump, output); + AddEvents(app, typeDump, output); + + // Enrich properties with getters and setters + AttachAccessorsToProperties(output); + + // Enrich events with add/remove methods + AttachAddAndRemoveToEvents(output); + } + + private void AttachAccessorsToProperties(RemoteType output) + { + MethodInfo[] methods = output.GetMethods(); + foreach (PropertyInfo pi in output.GetProperties()) + { + RemotePropertyInfo rpi = pi as RemotePropertyInfo; + MethodInfo getter = methods.FirstOrDefault(mi => mi.Name == "get_" + pi.Name); + rpi.RemoteGetMethod = getter as RemoteMethodInfo; + MethodInfo setter = methods.FirstOrDefault(mi => mi.Name == "set_" + pi.Name); + rpi.RemoteSetMethod = setter as RemoteMethodInfo; + } + } + + private void AddProperties(RemoteApp app, TypeDump typeDump, RemoteType output) + { + foreach (TypeDump.TypeProperty propDump in typeDump.Properties) + { + Lazy factory = new Lazy(() => + { + try + { + return ResolveTypeWhileCreating(app, typeDump.Type, "prop__resolving__logic", + propDump.Assembly, propDump.TypeFullName); + } + catch (Exception e) + { + Debug.WriteLine($"[RemoteTypesFactory] failed to create field {propDump.Name} because its type couldn't be created.\n" + + "The throw exception was: " + e); + return null; + } + }); + + RemotePropertyInfo propInfo = new RemotePropertyInfo(output, factory, propDump.Name); + output.AddProperty(propInfo); + } + } + + private void AttachAddAndRemoveToEvents(RemoteType output) + { + MethodInfo[] methods = output.GetMethods(); + foreach (EventInfo ei in output.GetEvents()) + { + RemoteEventInfo rpi = ei as RemoteEventInfo; + MethodInfo add = methods.FirstOrDefault(mi => mi.Name == "add_" + ei.Name); + rpi.RemoteAddMethod = add as RemoteMethodInfo; + MethodInfo remove = methods.FirstOrDefault(mi => mi.Name == "remove_" + ei.Name); + rpi.RemoteRemoveMethod = remove as RemoteMethodInfo; + } + } + + private void AddEvents(RemoteApp app, TypeDump typeDump, RemoteType output) + { + foreach (TypeDump.TypeEvent eventType in typeDump.Events) + { + Lazy factory = new Lazy(() => + { + try + { + return ResolveTypeWhileCreating(app, typeDump.Type, "event__resolving__logic", eventType.Assembly, eventType.TypeFullName); + } + catch (Exception e) + { + Debug.WriteLine($"[RemoteTypesFactory] failed to create event {eventType.Name} because its type couldn't be created.\n" + + "The throw exception was: " + e); + return null; + } + }); + + var eventInfo = new RemoteEventInfo(output, factory, eventType.Name); + output.AddEvent(eventInfo); + } + } + + private void AddFields(RemoteApp app, TypeDump typeDump, RemoteType output) + { + foreach (TypeDump.TypeField fieldDump in typeDump.Fields) + { + Lazy factory = new Lazy(() => + { + try + { + return ResolveTypeWhileCreating(app, typeDump.Type, "field__resolving__logic", + fieldDump.Assembly, fieldDump.TypeFullName); + } + catch (Exception e) + { + Debug.WriteLine($"[RemoteTypesFactory] failed to create field {fieldDump.Name} because its type couldn't be created.\n" + + "The throw exception was: " + e); + return null; + } + }); + + RemoteFieldInfo fieldInfo = new RemoteFieldInfo(output, factory, fieldDump.Name); + output.AddField(fieldInfo); + } + } + + private void AddGroupOfFunctions(RemoteApp app, TypeDump typeDump, List functions, RemoteType declaringType, bool areConstructors) + { + foreach (TypeDump.TypeMethod func in functions) + { + List parameters = new List(func.Parameters.Count); + foreach (TypeDump.TypeMethod.MethodParameter methodParameter in func.Parameters) + { + Lazy paramFactory = new Lazy(() => + { + // First: Search cache (which means local types & already-seen remote types) + if (methodParameter.IsGenericParameter) + { + // In case of a generic type we have no way to "resolve" it + // We are just creating a dummy type + return new RemoteType(app, typeDump.Type, "FakeAssemblyForGenericTypes", typeDump.IsArray, true); + } + else + { + // Non-generic parameter + // Cases that will not arrive here: + // void MyMethod(T item) <-- The 'item' parameter won't get here + // Cases that will arrive here: + // void MyOtherMethod(System.Text.StringBuilder sb) <-- The 'sb' parameter WILL get here + try + { + Type paramType = ResolveTypeWhileCreating(app, typeDump.Type, func.Name, methodParameter.Assembly, + methodParameter.Type); + if (paramType == null) + { + // TODO: Add stub method to indicate this error to the users? + Debug.WriteLine( + $"[RemoteTypesFactory] Could not resolve method {func.Name} of {methodParameter.Type} using the function {nameof(ResolveTypeWhileCreating)} " + + $"and it did not throw any exceptions (returned NULL)."); + return null; + } + return paramType; + } + catch (Exception e) + { + // TODO: Add stub method to indicate this error to the users? + Debug.WriteLine( + $"[RemoteTypesFactory] Could not resolve method {func.Name} of {methodParameter.Type} using the function {nameof(ResolveTypeWhileCreating)} " + + $"and it threw this exception: " + e); + return null; + } + } + }); + LazyRemoteTypeResolver paramTypeResolver = new LazyRemoteTypeResolver(paramFactory, + methodParameter.Assembly, + methodParameter.Type); + RemoteParameterInfo rpi = new RemoteParameterInfo(methodParameter.Name, paramTypeResolver); + parameters.Add(rpi); + } + + Lazy factory = new Lazy(() => + { + try + { + return ResolveTypeWhileCreating(app, typeDump.Type, func.Name, + func.ReturnTypeAssembly, func.ReturnTypeFullName); + } + catch (Exception e) + { + // TODO: This sometimes throws because of generic results (like List) + Debug.WriteLine($"[RemoteTypesFactory] failed to create method {func.Name} because its return type could be created.\n" + + "The throw exception was: " + e); + // TODO: Add stub method to indicate this error to the users? + return null; + } + }); + LazyRemoteTypeResolver resolver = new LazyRemoteTypeResolver(factory, func.ReturnTypeAssembly, func.ReturnTypeFullName); + + if (areConstructors) + { + RemoteConstructorInfo ctorInfo = + new RemoteConstructorInfo(declaringType, parameters.ToArray()); + declaringType.AddConstructor(ctorInfo); + } + else + { + Type[] genericArgs = func.GenericArgs.Select(arg => new DummyGenericType(arg)).ToArray(); + + // Regular method + RemoteMethodInfo methodInfo = + new RemoteMethodInfo(declaringType, resolver, func.Name, genericArgs, parameters.ToArray()); + declaringType.AddMethod(methodInfo); + } + } + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs new file mode 100644 index 00000000..21536393 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs @@ -0,0 +1,74 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + + +namespace RemoteNET.Internal.Reflection; + +/// +/// Resolves local and remote types. Contains a cache so the same TypeFullName +/// object is returned for different resolutions for the same remote type. +/// +public class TypesResolver() +{ + // Since the resolver works with a cache that should be global we make the + // whole class a singleton + public static TypesResolver Instance = new TypesResolver(); + + private readonly Dictionary, Type> _cache = new(); + + public void RegisterType(Type type) + => RegisterType(type.Assembly.GetName().Name, type.FullName, type); + + public void RegisterType(string assemblyName, string typeFullName, Type type) + { + _cache[new Tuple(assemblyName, typeFullName)] = type; + } + + public Type Resolve(string assemblyName, string typeFullName) + { + // Start by searching cache + if (_cache.TryGetValue(new Tuple(assemblyName, typeFullName), + out Type resolvedType)) + { + return resolvedType; + } + + // Search for locally available types + // EXCEPT for enums because that breaks RemoteEnum + IEnumerable assemblies = AppDomain.CurrentDomain.GetAssemblies(); + // Filter assemblies but avoid filtering for "mscorlib" + if(assemblyName?.Equals("mscorlib") == false) + { + assemblies = assemblies.Where(assm => assm.FullName.Contains(assemblyName ?? "")); + } + foreach (Assembly assembly in assemblies) + { + resolvedType = assembly.GetType(typeFullName); + if(resolvedType != null) + { + // Found the type! + // But retreat if it's an enum (and get remote proxy of it instead) + if(resolvedType.IsEnum) + { + resolvedType = null; + } + break; + } + } + + if (resolvedType != null && resolvedType is RemoteType) + { + RegisterType(assemblyName, typeFullName, resolvedType); + } + + return resolvedType; + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs b/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs new file mode 100644 index 00000000..544895cf --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs @@ -0,0 +1,155 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Linq; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions; +using ScubaDiver.API.Interactions.Dumps; + + +namespace RemoteNET.Internal; + +internal class RemoteObjectRef( + ObjectDump remoteObjectInfo, + TypeDump typeInfo, + DiverCommunicator creatingCommunicator) +{ + private bool _isReleased = false; + + // TODO: I think addresses as token should be reworked + public ulong Token => remoteObjectInfo.PinnedAddress; + public DiverCommunicator Communicator => creatingCommunicator; + + public TypeDump GetTypeDump() => typeInfo; + + /// + /// Gets the value of a remote field. Returned value might be a cached version unless is set to True. + /// + /// Name of field to get the value of + /// Whether the value should be read again for this invocation or a cache version is good enough + public MemberDump GetFieldDump(string name, bool refresh = false) + { + ThrowIfReleased(); + if (refresh) + { + remoteObjectInfo = creatingCommunicator + .DumpObject(remoteObjectInfo.PinnedAddress, remoteObjectInfo.Type); + } + + var field = remoteObjectInfo.Fields.Single(fld => fld.Name == name); + if (!string.IsNullOrEmpty(field.RetrievalError)) + throw new Exception( + $"Field of the remote object could not be retrieved. Error: {field.RetrievalError}"); + + // field has a value. Returning as-is for the user to parse + return field; + } + /// + /// Gets the value of a remote property. Returned value might be a cached version unless is set to True. + /// + /// Name of property to get the value of + /// Whether the value should be read again for this invocation or a cache version is good enough + public MemberDump GetProperty(string name, bool refresh = false) + { + ThrowIfReleased(); + if (refresh) + { + throw new NotImplementedException("Refreshing property values not supported yet"); + } + + var property = remoteObjectInfo.Properties.Single(prop => prop.Name == name); + if (!string.IsNullOrEmpty(property.RetrievalError)) + { + throw new Exception( + $"Property of the remote object could not be retrieved. Error: {property.RetrievalError}"); + } + + // property has a value. Returning as-is for the user to parse + return property; + } + + private void ThrowIfReleased() + { + if (_isReleased) + { + throw new ObjectDisposedException("Cannot use RemoteObjectRef object after `Release` have been called"); + } + } + + public InvocationResults InvokeMethod( + string methodName, + string[] genericArgsFullTypeNames, + ObjectOrRemoteAddress[] args) + { + ThrowIfReleased(); + return creatingCommunicator + .InvokeMethod( + remoteObjectInfo.PinnedAddress, + remoteObjectInfo.Type, + methodName, + genericArgsFullTypeNames, + args); + } + + public InvocationResults SetField( + string fieldName, + ObjectOrRemoteAddress newValue) + { + ThrowIfReleased(); + return creatingCommunicator + .SetField( + remoteObjectInfo.PinnedAddress, + remoteObjectInfo.Type, + fieldName, + newValue); + } + public InvocationResults GetField(string fieldName) + { + ThrowIfReleased(); + return creatingCommunicator + .GetField( + remoteObjectInfo.PinnedAddress, + remoteObjectInfo.Type, + fieldName); + } + + public void EventSubscribe( + string eventName, + DiverCommunicator.LocalEventCallback callbackProxy) + { + ThrowIfReleased(); + creatingCommunicator.EventSubscribe(remoteObjectInfo.PinnedAddress, eventName, callbackProxy); + } + + public void EventUnsubscribe( + string eventName, + DiverCommunicator.LocalEventCallback callbackProxy) + { + ThrowIfReleased(); + creatingCommunicator.EventUnsubscribe(callbackProxy); + } + + /// + /// Releases hold of the remote object in the remote process and the local proxy. + /// + public void RemoteRelease() + { + creatingCommunicator.UnpinObject(remoteObjectInfo.PinnedAddress); + _isReleased = true; + } + + public override string ToString() + { + return $"RemoteObjectRef. Address: {remoteObjectInfo.PinnedAddress}, TypeFullName: {typeInfo.Type}"; + } + + internal ObjectOrRemoteAddress GetItem(ObjectOrRemoteAddress key) + { + return creatingCommunicator.GetItem(Token, key); + } +} diff --git a/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs b/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs new file mode 100644 index 00000000..717b1a6c --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs @@ -0,0 +1,62 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Reflection; + + +namespace RemoteNET.Internal.Utils; + +public static class MethodBaseExtensions +{ + /// + /// Determines whether the signature of two objects are equal. + /// + /// The first object. + /// The second object. + /// true if the signatures are equal; otherwise, false. + public static bool SignatureEquals(this MethodBase a, MethodBase b) + { + // Ensure that objects share the same name and parameter types. + if (a.Name != b.Name + && !ParametersEqual(a.GetParameters(), b.GetParameters())) + { + return false; + } + + // For methods, compare the objects' method signature and return types. + if ((a is MethodInfo aInfo) && (b is MethodInfo bInfo) + && aInfo.ReturnType != null && bInfo.ReturnType != null) + { + return aInfo.ReturnType.FullName == bInfo.ReturnType.FullName; + } + // For classes, compare the declaring type of the objects' constructors. + else if ((a is ConstructorInfo aCtor) && (b is ConstructorInfo bCtor)) + { + return aCtor.DeclaringType == bCtor.DeclaringType; + } + + // Unknown derived class of MethodBase + return false; + } + + /// + /// Determines whether the parameter arrays and are equal. + /// + /// The first parameter array. + /// The second parameter array. + /// true if the parameter arrays are equal; otherwise, false. + public static bool ParametersEqual(ParameterInfo[] a, ParameterInfo[] b) + { + if(a.Length != b.Length) + return false; + + for (int i = 0; i < a.Length; i++) + if (a[i].ParameterType != b[i].ParameterType) + return false; + + return true; + } +} diff --git a/third_party/RemoteNET/src/ScubaDiver.API/CallbacksListener.cs b/MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/CallbacksListener.cs rename to MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/DiverCommunicator.cs b/MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/DiverCommunicator.cs rename to MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Exceptions/RemoteException.cs b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Exceptions/RemoteException.cs rename to MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Exceptions/RemoteObjectMovedException.cs b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Exceptions/RemoteObjectMovedException.cs rename to MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Extensions/IntPtrExt.cs b/MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Extensions/IntPtrExt.cs rename to MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Extensions/WildCardType.cs b/MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Extensions/WildCardType.cs rename to MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Callbacks/CallbackInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Callbacks/CallbackInvocationRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Callbacks/EventRegistrationResults.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Callbacks/EventRegistrationResults.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Client/UnregisterClientResponse.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Client/UnregisterClientResponse.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/DiverError.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/DiverError.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/DomainsDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/DomainsDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/HeapDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/HeapDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/MemberDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/MemberDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/ObjectDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/ObjectDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypeDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypeDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypeDumpRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypeDumpRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypesDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Dumps/TypesDump.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/InvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/InvocationRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/InvocationResults.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/InvocationResults.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/CtorInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/CtorInvocationRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/FieldGetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/FieldGetRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/FieldSetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/FieldSetRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/IndexedItemAccessRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Interactions/Object/IndexedItemAccessRequest.cs rename to MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/ObjectOrRemoteAddress.cs b/MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/ObjectOrRemoteAddress.cs rename to MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/ReverseCommunicator.cs b/MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/ReverseCommunicator.cs rename to MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Utils/Filter.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Utils/Filter.cs rename to MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Utils/NewtonsoftProxy.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Utils/NewtonsoftProxy.cs rename to MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Utils/PrimitivesEncoder.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Utils/PrimitivesEncoder.cs rename to MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs diff --git a/third_party/RemoteNET/src/ScubaDiver.API/Utils/TypeExt.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs similarity index 100% rename from third_party/RemoteNET/src/ScubaDiver.API/Utils/TypeExt.cs rename to MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs diff --git a/MTGOSDK/src/Core/Remoting/Logger.cs b/MTGOSDK/src/Core/Remoting/Logger.cs new file mode 100644 index 00000000..1e48b74c --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Logger.cs @@ -0,0 +1,37 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Diagnostics; + + +namespace RemoteNET; + +internal class Logger +{ + public static Lazy DebugInRelease = new Lazy(() => + !string.IsNullOrWhiteSpace( + Environment.GetEnvironmentVariable("REMOTE_NET_DIVER_MAGIC_DEBUG"))); + +#if DEBUG + public static bool IsDebug = true; +#else + public static bool IsDebug = false; +#endif + + internal static void Debug(string s) + { + if (IsDebug || Debugger.IsAttached) + { + System.Diagnostics.Debug.WriteLine(s); + } + // Allow debug logging in release only if the environment variable is set. + else if(DebugInRelease.Value) + { + Console.WriteLine(s); + } + } +} diff --git a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs new file mode 100644 index 00000000..296e2cc1 --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs @@ -0,0 +1,66 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Linq; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions; + +using RemoteNET.Internal.Reflection; + + +namespace RemoteNET; + +public class RemoteActivator(DiverCommunicator communicator, RemoteApp app) +{ + public RemoteObject CreateInstance(Type t) => + CreateInstance(t, new object[0]); + + public RemoteObject CreateInstance(Type t, + params object[] parameters) => + CreateInstance(t.Assembly.FullName, t.FullName, parameters); + + public RemoteObject CreateInstance(string typeFullName, + params object[] parameters) => + CreateInstance(null, typeFullName, parameters); + + public RemoteObject CreateInstance(string assembly, + string typeFullName, + params object[] parameters) + { + object[] paramsNoEnums = parameters.ToArray(); + for (int i = 0; i < paramsNoEnums.Length; i++) + { + var val = paramsNoEnums[i]; + if (val.GetType().IsEnum) + { + var enumClass = app.GetRemoteEnum(val.GetType().FullName); + // TODO: This will break on the first enum value which represents 2 or more flags + object enumVal = enumClass.GetValue(val.ToString()); + // NOTE: Object stays in place in the remote app as long as we have it's reference + // in the paramsNoEnums array (so until end of this method) + paramsNoEnums[i] = enumVal; + } + } + + ObjectOrRemoteAddress[] remoteParams = paramsNoEnums.Select( + RemoteFunctionsInvokeHelper.CreateRemoteParameter).ToArray(); + + // Create object + pin + InvocationResults invoRes = communicator + .CreateObject(typeFullName, remoteParams); + + // Get proxy object + var remoteObject = app.GetRemoteObject( + invoRes.ReturnedObjectOrAddress.RemoteAddress, + invoRes.ReturnedObjectOrAddress.Type); + + return remoteObject; + } + + public RemoteObject CreateInstance() => CreateInstance(typeof(T)); +} diff --git a/MTGOSDK/src/Core/Remoting/RemoteApp.cs b/MTGOSDK/src/Core/Remoting/RemoteApp.cs new file mode 100644 index 00000000..96b4838a --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/RemoteApp.cs @@ -0,0 +1,314 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions.Dumps; +using ScubaDiver.API.Utils; + +using RemoteNET.Internal; +using RemoteNET.Internal.Reflection; + + +namespace RemoteNET; + +public class RemoteApp : IDisposable +{ + internal class RemoteObjectsCollection + { + // The WeakReferences are to RemoteObject + private readonly Dictionary> _pinnedAddressesToRemoteObjects; + private readonly object _lock = new object(); + + private readonly RemoteApp _app; + + public RemoteObjectsCollection(RemoteApp app) + { + _app = app; + _pinnedAddressesToRemoteObjects = new Dictionary>(); + } + + private RemoteObject GetRemoteObjectUncached( + ulong remoteAddress, + string typeName, + int? hashCode = null) + { + ObjectDump od; + TypeDump td; + try + { + od = _app._communicator.DumpObject(remoteAddress, typeName, true, hashCode); + td = _app._communicator.DumpType(od.Type); + } + catch (Exception e) + { + throw new Exception("Could not dump remote object/type.", e); + } + + var remoteObject = new RemoteObject( + new RemoteObjectRef(od, td, _app._communicator), _app); + + return remoteObject; + } + + public RemoteObject GetRemoteObject( + ulong address, + string typeName, + int? hashcode = null) + { + RemoteObject ro; + WeakReference weakRef; + // Easiest way - Non-collected and previously obtained object ("Cached") + if (_pinnedAddressesToRemoteObjects.TryGetValue(address, out weakRef) && + weakRef.TryGetTarget(out ro)) + { + // Not GC'd! + return ro; + } + + // Harder case - At time of checking, item wasn't cached. + // We need exclusive access to the cache now to make sure we are the only one adding it. + lock (_lock) + { + // Last chance - when we waited on the lock some other thread might've added it to the cache. + if (_pinnedAddressesToRemoteObjects.TryGetValue(address, out weakRef)) + { + bool gotTarget = weakRef.TryGetTarget(out ro); + if (gotTarget) + { + // Not GC'd! + return ro; + } + else + { + // Object was GC'd... + _pinnedAddressesToRemoteObjects.Remove(address); + // Now let's make sure the GC'd object finalizer was also called (otherwise some "object moved" errors might happen). + GC.WaitForPendingFinalizers(); + // Now we need to-read the remote object since stuff might have moved + } + } + + // Get remote + ro = GetRemoteObjectUncached(address, typeName, hashcode); + // Add to cache + weakRef = new WeakReference(ro); + _pinnedAddressesToRemoteObjects[ro.RemoteToken] = weakRef; + } + + return ro; + } + } + + private Process _procWithDiver; + private DiverCommunicator _communicator; + private DomainsDump _domains; + private readonly RemoteObjectsCollection _remoteObjects; + + public Process Process => _procWithDiver; + public RemoteActivator Activator { get; private set; } + + public DiverCommunicator Communicator => _communicator; + public static bool IsReconnected = false; + + internal RemoteApp(Process procWithDiver, DiverCommunicator communicator) + { + _procWithDiver = procWithDiver; + _communicator = communicator; + _remoteObjects = new RemoteObjectsCollection(this); + Activator = new RemoteActivator(communicator, this); + } + + // + // Init + // + + /// + /// Creates a new provider. + /// + /// Process to create the provider for + /// A provider for the given process + public static RemoteApp Connect(Process target) + { + return Connect(target, (ushort)target.Id); + } + + public static RemoteApp Connect(Process target, ushort diverPort) + { + // Use discovery to check for existing diver + string diverAddr = "127.0.0.1"; + switch(DiverDiscovery.QueryStatus(target, diverAddr, diverPort)) + { + case DiverState.NoDiver: + // No diver, we need to inject one + try + { + Bootstrapper.Inject(target, diverPort); + break; + } + catch (IOException e) + { + throw new Exception("Failed to inject diver.", e); + } + case DiverState.Alive: + // Skip injection as diver assembly is already bootstrapped + IsReconnected = true; + break; + case DiverState.Corpse: + throw new Exception("Diver could not finish bootstrapping."); + case DiverState.HollowSnapshot: + throw new Exception("Target process is empty. Did you attach to the correct process?"); + } + + // Now register our program as a "client" of the diver + DiverCommunicator com = new DiverCommunicator(diverAddr, diverPort); + if (com.RegisterClient() == false) + throw new Exception("Registering as a client in the Diver failed."); + + return new RemoteApp(target, com); + } + + // + // Remote Heap querying + // + + public IEnumerable QueryTypes(string typeFullNameFilter) + { + Predicate matchesFilter = Filter.CreatePredicate(typeFullNameFilter); + + _domains ??= _communicator.DumpDomains(); + foreach (DomainsDump.AvailableDomain domain in _domains.AvailableDomains) + { + foreach (string assembly in domain.AvailableModules) + { + List typeIdentifiers; + try + { + typeIdentifiers = _communicator.DumpTypes(assembly).Types; + } + catch + { + // TODO: + Debug.WriteLine($"[{nameof(RemoteApp)}][{nameof(QueryTypes)}] Exception thrown when Dumping/Iterating assembly: {assembly}"); + continue; + } + foreach (TypesDump.TypeIdentifiers type in typeIdentifiers) + { + // TODO: Filtering should probably be done in the Diver's side + if (matchesFilter(type.TypeName)) + yield return new CandidateType(type.TypeName, assembly); + } + + } + } + + } + + public IEnumerable QueryInstances(Type typeFilter, bool dumpHashcodes = true) => QueryInstances(typeFilter.FullName, dumpHashcodes); + + /// + /// Gets all object candidates for a specific filter + /// + /// Objects with Full Type Names of this EXACT string will be returned. You can use '*' as a "0 or more characters" wildcard + /// Whether to also dump hashcodes of every matching object. + /// This makes resolving the candidates later more reliable but for wide queries (e.g. "*") this might fail the entire search since it causes instabilities in the heap when examining it. + /// + public IEnumerable QueryInstances(string typeFullNameFilter, bool dumpHashcodes = true) + { + return _communicator.DumpHeap(typeFullNameFilter, dumpHashcodes).Objects + .Select(heapObj => + new CandidateObject(heapObj.Address, heapObj.Type, heapObj.HashCode)); + } + + // + // Resolving Types + // + + /// + /// Gets a handle to a remote type (even ones from assemblies we aren't + /// referencing/loading to the local process) + /// + /// Full name of the type to get. For example 'System.Xml.XmlDocument' + /// Optional short name of the assembly containing the type. For example 'System.Xml.ReaderWriter.dll' + /// + public Type GetRemoteType(string typeFullName, string assembly = null) + { + // Easy case: Trying to resolve from cache or from local assemblies + var resolver = TypesResolver.Instance; + Type res = resolver.Resolve(assembly, typeFullName); + if (res != null) + { + // Either found in cache or found locally. + + // If it's a local type we need to wrap it in a "fake" RemoteType (So + // method invocations will actually happened in the remote app, for + // example) (But not for primitives...) + if (!(res is RemoteType) && !res.IsPrimitive) + { + res = new RemoteType(this, res); + // TODO: Registering here in the cache is a hack but we couldn't + // register within "TypesResolver.Resolve" because we don't have the + // RemoteApp to associate the fake remote type with. + // Maybe this should move somewhere else... + resolver.RegisterType(res); + } + return res; + } + + // Harder case: Dump the remote type. This takes much more time (includes + // dumping of dependent types) and should be avoided as much as possible. + RemoteTypesFactory rtf = new RemoteTypesFactory(resolver, _communicator); + var dumpedType = _communicator.DumpType(typeFullName, assembly); + return rtf.Create(this, dumpedType); + } + /// + /// Returns a handle to a remote type based on a given local type. + /// + public Type GetRemoteType(Type localType) => + GetRemoteType(localType.FullName, localType.Assembly.GetName().Name); + public Type GetRemoteType(CandidateType candidate) => + GetRemoteType(candidate.TypeFullName, candidate.Assembly); + internal Type GetRemoteType(TypeDump typeDump) => + GetRemoteType(typeDump.Type, typeDump.Assembly); + + public RemoteEnum GetRemoteEnum(string typeFullName, string assembly = null) + { + RemoteType remoteType = GetRemoteType(typeFullName, assembly) as RemoteType + ?? throw new Exception("Failed to dump remote enum (and get a RemoteType object)"); + return new RemoteEnum(remoteType); + } + + // + // Getting Remote Objects + // + + public RemoteObject GetRemoteObject(CandidateObject candidate) => + GetRemoteObject(candidate.Address, candidate.TypeFullName, candidate.HashCode); + + public RemoteObject GetRemoteObject( + ulong remoteAddress, + string typeName, + int? hashCode = null) + { + return _remoteObjects.GetRemoteObject(remoteAddress, typeName, hashCode); + } + + // + // IDisposable + // + public void Dispose() + { + Communicator?.KillDiver(); + _communicator = null; + _procWithDiver = null; + } +} diff --git a/MTGOSDK/src/Core/Remoting/RemoteObject.cs b/MTGOSDK/src/Core/Remoting/RemoteObject.cs new file mode 100644 index 00000000..a34304bd --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/RemoteObject.cs @@ -0,0 +1,133 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; +using System.Collections.Generic; + +using ScubaDiver.API; +using ScubaDiver.API.Interactions; +using ScubaDiver.API.Interactions.Dumps; + +using RemoteNET.Internal; + + +namespace RemoteNET; + +public class RemoteObject +{ + private readonly RemoteApp _app; + private RemoteObjectRef _ref; + private Type _type = null; + + private readonly Dictionary _eventCallbacksAndProxies = new(); + + public ulong RemoteToken => _ref.Token; + + internal RemoteObject(RemoteObjectRef reference, RemoteApp remoteApp) + { + _app = remoteApp; + _ref = reference; + } + + /// + /// Gets the type of the proxied remote object, in the remote app. (This does not return `typeof(RemoteObject)`) + /// + public new Type GetType() => _type ??= _app.GetRemoteType(_ref.GetTypeDump()); + + public ObjectOrRemoteAddress SetField(string fieldName, ObjectOrRemoteAddress newValue) + { + InvocationResults invokeRes = _ref.SetField(fieldName, newValue); + return invokeRes.ReturnedObjectOrAddress; + + } + + public (bool hasResults, ObjectOrRemoteAddress returnedValue) InvokeMethod( + string methodName, + params ObjectOrRemoteAddress[] args) + => InvokeMethod(methodName, args); + + public (bool hasResults, ObjectOrRemoteAddress returnedValue) InvokeMethod( + string methodName, + string[] genericArgsFullTypeNames, + params ObjectOrRemoteAddress[] args) + { + InvocationResults invokeRes = _ref.InvokeMethod(methodName, genericArgsFullTypeNames, args); + if (invokeRes.VoidReturnType) + { + return (false, null); + } + return (true, invokeRes.ReturnedObjectOrAddress); + } + + public dynamic Dynamify() + { + // Adding fields + TypeDump typeDump = _ref.GetTypeDump(); + + var factory = new DynamicRemoteObjectFactory(); + return factory.Create(_app, this, typeDump); + } + + ~RemoteObject() + { + _ref?.RemoteRelease(); + _ref = null; + } + + public override string ToString() + { + return $"RemoteObject. Type: {_type?.FullName ?? "UNK"} Reference: [{_ref}]"; + } + + public ObjectOrRemoteAddress GetField(string name) + { + var res = _ref.GetField(name); + return res.ReturnedObjectOrAddress; + } + + public void EventSubscribe(string eventName, Delegate callback) + { + // TODO: Add a check for amount of parameters and types (need to be dynamics) + // See implementation inside DynamicEventProxy + + (bool voidReturnType, ObjectOrRemoteAddress res) callbackProxy(ObjectOrRemoteAddress[] args) + { + DynamicRemoteObject[] droParameters = new DynamicRemoteObject[args.Length]; + for (int i = 0; i < args.Length; i++) + { + RemoteObject ro = _app.GetRemoteObject(args[i].RemoteAddress, args[i].Type); + DynamicRemoteObject dro = ro.Dynamify() as DynamicRemoteObject; + + droParameters[i] = dro; + } + + // Call the callback with the proxied parameters (using DynamicRemoteObjects) + callback.DynamicInvoke(droParameters); + + // TODO: Return the result of the callback + return (true, null); + } + + _eventCallbacksAndProxies[callback] = callbackProxy; + + _ref.EventSubscribe(eventName, callbackProxy); + } + + public void EventUnsubscribe(string eventName, Delegate callback) + { + if (_eventCallbacksAndProxies.TryGetValue(callback, out DiverCommunicator.LocalEventCallback callbackProxy)) + { + _ref.EventUnsubscribe(eventName, callbackProxy); + + _eventCallbacksAndProxies.Remove(callback); + } + } + + internal ObjectOrRemoteAddress GetItem(ObjectOrRemoteAddress key) + { + return _ref.GetItem(key); + } +} diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..b8ff5b6d --- /dev/null +++ b/NOTICE @@ -0,0 +1,50 @@ +MTGOSDK + +Copyright (c) 2023, Cory Bennett. All rights reserved. + +Source code in this repository is variously licensed under the Apache License +Version 2.0, or an Apache-compatible license. Please see +LICENSE for more information. + +* For a copy of the Apache License Version 2.0, please see LICENSE + as included in this repository's top-level directory. + +* For a copy of all other Apache-compatible licenses and notices, + please see below. + +======================================================================== +NOTICES +======================================================================== + +Certain files in this code base have been modified and/or copied, +either partially or wholely, from source code from the RemoteNET +library, which is licensed under the open-source MIT License with +the following copyright information. + +MIT License +======================================================================== + +RemoteNET +(formerly known as DynamicX) + +Copyright (c) 2021, Xappy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +======================================================================== diff --git a/third_party/RemoteNET/src/RemoteNET/CandidateObject.cs b/third_party/RemoteNET/src/RemoteNET/CandidateObject.cs deleted file mode 100644 index ffa16b2e..00000000 --- a/third_party/RemoteNET/src/RemoteNET/CandidateObject.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace RemoteNET -{ - /// - /// A candidate for a remote object. - /// Holding this item does not mean having a meaningful hold of the remote object. To gain one use - /// - public class CandidateObject - { - public ulong Address { get; set; } - public string TypeFullName { get; set; } - public int HashCode { get; private set; } - - public CandidateObject(ulong address, string typeFullName, int hashCode) - { - Address = address; - TypeFullName = typeFullName; - HashCode = hashCode; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/CandidateType.cs b/third_party/RemoteNET/src/RemoteNET/CandidateType.cs deleted file mode 100644 index 0b3d4f36..00000000 --- a/third_party/RemoteNET/src/RemoteNET/CandidateType.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace RemoteNET -{ - public class CandidateType - { - public string TypeFullName { get; set; } - public string Assembly { get; set; } - - public CandidateType(string typeName, string assembly) - { - TypeFullName = typeName; - Assembly = assembly; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/DiverDiscovery.cs b/third_party/RemoteNET/src/RemoteNET/Internal/DiverDiscovery.cs deleted file mode 100644 index 8798351d..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/DiverDiscovery.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Diagnostics; -using System.Linq; -using System.Net; -using System.Net.Sockets; - -using ScubaDiver.API; - -using RemoteNET.Internal.Extensions; - - -namespace RemoteNET.Internal -{ - public enum DiverState - { - NoDiver, - Alive, - Corpse, - HollowSnapshot - } - public static class DiverDiscovery - { - public static DiverState QueryStatus( - Process target, - string diverAddr, - ushort diverPort) - { - DiverCommunicator com = new DiverCommunicator(diverAddr, diverPort); - - // We WANT to check liveness of the diver using HTTP but this might take a - // LOT of time if it is dead (Trying to TCP SYN several times, with a - // timeout between each). So a simple circuit-breaker is implemented - // before that: If we manage to bind to the expected diver endpoint, we - // assume it's not alive - - bool diverPortIsFree = false; - try - { - IPAddress localAddr = IPAddress.Parse(diverAddr); - TcpListener server = new TcpListener(localAddr, diverPort); - server.Start(); - diverPortIsFree = true; - server.Stop(); - } - catch - { - // Had some issues, perhaps it's the diver holding that port. - } - - if (!diverPortIsFree && com.CheckAliveness()) - { - return DiverState.Alive; - } - - // // Check if this is a snapshot created by the diver. - // if (target.Threads.Count == 0) - // return DiverState.HollowSnapshot; - - // Diver isn't alive. It's possible that it was never injected or it was - // injected and killed - bool containsToolkitDll = false; - try - { - containsToolkitDll |= target.Modules.AsEnumerable() - .Any(module => module.ModuleName.Contains("Bootstrapper")); - } - catch - { - // Sometimes this happens because of x32 vs x64 process interaction - } - if (containsToolkitDll) - { - return DiverState.Corpse; - } - - return DiverState.NoDiver; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteEnumerator.cs b/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteEnumerator.cs deleted file mode 100644 index 3f6a1c8e..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteEnumerator.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections; - - -namespace RemoteNET.Internal -{ - public class DynamicRemoteEnumerator : IEnumerator - { - private dynamic _remoteEnumerator; - public DynamicRemoteEnumerator(dynamic remoteEnumerator) - { - _remoteEnumerator = remoteEnumerator; - } - - public object Current => _remoteEnumerator.Current; - - public bool MoveNext() => _remoteEnumerator.MoveNext(); - - public void Reset() => _remoteEnumerator.Reset(); - - public void Dispose() - { - try - { - _remoteEnumerator.Dispose(); - } - catch - { - // TODO: Handle IDisposable's Dispose method explicitly when expected - // by a using statement or a call to Dispose(). - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObject.cs b/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObject.cs deleted file mode 100644 index 84f69b72..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObject.cs +++ /dev/null @@ -1,602 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Dynamic; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; - -using Microsoft.CSharp.RuntimeBinder; -using Binder = Microsoft.CSharp.RuntimeBinder.Binder; - -using ScubaDiver.API.Utils; - -using RemoteNET.Internal.ProxiedReflection; -using RemoteNET.Internal.Reflection; -using RemoteNET.Utils; - - -namespace RemoteNET.Internal -{ - - /// - /// A proxy of a remote object. - /// Usages of this class should be strictly as a `dynamic` variable. - /// Field/Property reads/writes are redirect to reading/writing to the fields of the remote object - /// Function calls are redirected to functions calls in the remote process on the remote object - /// - /// - [DebuggerDisplay("Dynamic Proxy of {" + nameof(__ro) + "}")] - public class DynamicRemoteObject : DynamicObject, IEnumerable - { - public class DynamicRemoteMethod : DynamicObject - { - string _name; - ProxiedMethodGroup _methods; - DynamicRemoteObject _parent; - Type[] _genericArguments; - - public DynamicRemoteMethod( - string name, - DynamicRemoteObject parent, - ProxiedMethodGroup methods, - Type[] genericArguments = null) - { - genericArguments ??= Array.Empty(); - - _name = name; - _parent = parent; - _methods = methods; - - _genericArguments = genericArguments; - } - - public override bool TryInvoke( - InvokeBinder binder, - object[] args, - out object result) - => TryInvoke(args, out result); - - public bool TryInvoke(object[] args, out object result) - { - List overloads = _methods; - - // Narrow down (hopefuly to one) overload with the same amount of types - // TODO: We COULD possibly check the args types (local ones, - // RemoteObjects, DynamicObjects, ...) if we still have multiple results - overloads = overloads - .Where(overload => overload.GetParameters().Length == args.Length) - .ToList(); - - if (overloads.Count == 1) - { - // Easy case - a unique function name so we can just return it. - RemoteMethodInfo overload = overloads.Single(); - if (_genericArguments != null && _genericArguments.Any()) - { - if (!overload.IsGenericMethod) - { - throw new ArgumentException("A non-generic method was intialized with some generic arguments."); - } - else if (overload.IsGenericMethod - && overload.GetGenericArguments().Length != _genericArguments.Length) - { - throw new ArgumentException("Wrong number of generic arguments was provided to a generic method"); - } - // OK, invoking with generic arguments - result = overloads.Single() - .MakeGenericMethod(_genericArguments) - .Invoke(_parent.__ro, args); - } - else - { - if (overload.IsGenericMethod) - { - throw new ArgumentException("A generic method was intialized with no generic arguments."); - } - // OK, invoking without generic arguments - result = overloads.Single() - .Invoke(_parent.__ro, args); - } - } - else if (overloads.Count > 1) - { - // Multiple overloads. This sucks because we need to... return some "Router" func... - - throw new NotImplementedException($"Multiple overloads aren't supported at the moment. " + - $"Method `{_methods[0]}` had {overloads.Count} overloads registered."); - } - else // This case is for "overloads.Count == 0" - { - throw new ArgumentException($"Incorrent number of parameters provided to function.\n" + - $"After filtering all overloads with given amount of parameters ({args.Length}) we were left with 0 overloads."); - } - return true; - } - - public override bool Equals(object obj) - { - return obj is DynamicRemoteMethod method && - _name == method._name && - EqualityComparer.Default.Equals(_parent, method._parent) && - EqualityComparer.Default.Equals(_genericArguments, method._genericArguments); - } - - public override int GetHashCode() - { - int hashCode = -734779080; - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_name); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_parent); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(_genericArguments); - return hashCode; - } - - // Functions to turn our base method into a "generic" one - with specific - // arguments instead of generic placeholders. I wish I could've overridden - // the 'MyFunc' notation but I don't think that syntax is modifiable in - // C#. - // - // Instead we go to the second best solution which is use indexers: - // MyFunc[typeof(T)] - // - or - - // Type t = typeof(T); - // MyFunc[t] - // - // Since some methods support multiple generic arguments I also overrode - // some multi-dimensional indexers below. This allows that to compile: - // Type t,p,q = ...; - // MyOtherFunc[t,p,q] - - public DynamicRemoteMethod this[Type t] => - new DynamicRemoteMethod(_name, _parent, _methods, - _genericArguments.Concat(new Type[] { t }).ToArray()); - - public DynamicRemoteMethod this[Type t1, Type t2] => - this[t1][t2]; - public DynamicRemoteMethod this[Type t1, Type t2, Type t3] => - this[t1, t2][t3]; - public DynamicRemoteMethod this[Type t1, Type t2, Type t3, Type t4] => - this[t1, t2, t3][t4]; - public DynamicRemoteMethod this[Type t1, Type t2, Type t3, Type t4, Type t5] => - this[t1, t2, t3, t4][t5]; - } - - public RemoteApp __ra; - public RemoteObject __ro; - public RemoteType __type; - - private IEnumerable __ongoingMembersDumper = null; - private IEnumerator __ongoingMembersDumperEnumerator = null; - private List __membersInner = null; - public IEnumerable __members => MindFuck(); - - public DynamicRemoteObject(RemoteApp ra, RemoteObject ro) - { - __ra = ra; - __ro = ro; - __type = ro.GetType() as RemoteType; - if (__type == null && ro.GetType() != null) - { - throw new ArgumentException("Can only create DynamicRemoteObjects of RemoteObjects with Remote Types. (As returned from GetType())"); - } - } - - public DynamicRemoteObject() // For avoiding overriding reference type - { - __ra = null; - __ro = null; - __type = null; - } - - /// - /// Gets the type of the proxied remote object, in the remote app. (This does not reutrn `typeof(DynamicRemoteMethod)`) - /// - public new Type GetType() => __type; - - private IEnumerable GetAllMembersRecursive() - { - Type lastType = __type; - Type nextType = __type; - - // We use this dictionary to make sure overides from subclasses don't get exported twice (for the parent as well) - Dictionary> _processedOverloads = new Dictionary>(); - do - { - var members = nextType.GetMembers((BindingFlags)0xffff); - foreach (MemberInfo member in members) - { - if (member is MethodBase newMethods) - { - if (!_processedOverloads.ContainsKey(member.Name)) - _processedOverloads[member.Name] = new List(); - List oldMethods = _processedOverloads[member.Name]; - - bool overridden = oldMethods.Any(oldMethod => oldMethod.SignatureEquals(newMethods)); - if (overridden) - continue; - - _processedOverloads[member.Name].Add(newMethods); - - } - yield return member; - } - lastType = nextType; - nextType = nextType.BaseType; - } - while (nextType != null && lastType != typeof(object)); - } - - private IEnumerable MindFuck() - { - if (__membersInner != null && __ongoingMembersDumper == null) - { - return __membersInner; - } - // Defining a new method so we can use "yield return" (Outer function - // already returned a "real" IEnumerable in the above case) so using - // "yield return" as well is forbidden. - IEnumerable Aggregator() - { - __membersInner ??= new List(); - __ongoingMembersDumper ??= GetAllMembersRecursive(); - __ongoingMembersDumperEnumerator ??= __ongoingMembersDumper.GetEnumerator(); - foreach (var member in __membersInner) - { - yield return member; - } - while(__ongoingMembersDumperEnumerator.MoveNext()) - { - var member = __ongoingMembersDumperEnumerator.Current; - __membersInner.Add(member); - yield return member; - } - __ongoingMembersDumper = null; - __ongoingMembersDumperEnumerator = null; - - }; - return Aggregator(); - } - - public T InvokeMethod(string name, params object[] args) - { - var matchingMethods = from member in __members - where member.Name == name - where ((MethodInfo)member).GetParameters().Length == args.Length - select member; - return (T)(matchingMethods.Single() as MethodInfo).Invoke(__ro, args); - } - - #region Dynamic Object API - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - Type lastType = __type; - Type nextType = __type; - do - { - bool found = TryGetMember(nextType, binder.Name, out result); - if (found) - return true; - lastType = nextType; - nextType = nextType.BaseType; - } - while (nextType != null || lastType == typeof(object)); - - result = null; - return false; - } - - private bool TryGetMember(Type t, string name, out object result) - { - result = null; - MemberInfo[] members = t.GetMembers((BindingFlags)0xffff); - List matches = members - .Where(member => member.Name == name) - .ToList(); - - if (!matches.Any()) - { - result = null; - return false; - } - - // At least 1 member with that name - MemberInfo firstMember = matches[0]; - MemberTypes type = firstMember.MemberType; - bool singleMatch = matches.Count == 1; - - switch (type) - { - case MemberTypes.Field: - // if (!singleMatch) - // { - // throw new ArgumentException($"Multiple members were found for the name `{name}` and at least one of them was a field"); - // } - try - { - result = ((FieldInfo)firstMember).GetValue(__ro); - } - catch (Exception ex) - { - throw new Exception($"Field \"{name}\"'s getter threw an exception", innerException: ex); - } - break; - case MemberTypes.Property: - // if (!singleMatch) - // { - // throw new ArgumentException($"Multiple members were found for the name `{name}` and at least one of them was a property"); - // } - try - { - result = ((PropertyInfo)firstMember).GetValue(__ro); - } - catch (Exception ex) - { - throw new Exception($"Property \"{name}\"'s getter threw an exception", innerException: ex); - } - break; - case MemberTypes.Method: - // The cases that get here are when the user is trying to: - // 1. Save a method in a variable: - // var methodGroup = dro.Insert; - // 2. The user is trying to use the "RemoteNET way" of specifing generic: - // Type t = typeof(SomeType); - // dro.Insert[t](); - result = GetMethodProxy(name); - break; - case MemberTypes.Event: - // TODO: - throw new NotImplementedException("Cannot hook to remote events yet."); - default: - throw new Exception($"No such member \"{name}\""); - } - return true; - } - - private DynamicRemoteMethod GetMethodProxy(string name) - { - var methods = __members - .Where(member => member.Name == name) - .ToArray(); - if (methods.Length == 0) - { - throw new Exception($"Method \"{name}\" wasn't found in the members of type {__type.Name}."); - } - - if (methods.Any(member => member.MemberType != MemberTypes.Method)) - { - throw new Exception($"A member called \"{name}\" exists in the type and it isn't a method (It's a {methods.First(m => m.MemberType != MemberTypes.Method).MemberType})"); - } - if (methods.Any(member => !(member is RemoteMethodInfo))) - { - throw new Exception($"A method overload for \"{name}\" wasn't a MethodInfo"); - } - - ProxiedMethodGroup methodGroup = new ProxiedMethodGroup(); - methodGroup.AddRange(methods.Cast()); - try - { - return new DynamicRemoteMethod(name, this, methodGroup); - } - catch (Exception ex) - { - - throw new Exception($"Constructing {nameof(DynamicRemoteMethod)} of \"{name}\" threw an exception", innerException: ex); - } - } - - public override bool TryInvokeMember( - InvokeMemberBinder binder, - object[] args, - out object result) - { - // If "TryInvokeMember" was called first (instead of "TryGetMember") - // it means that the user specified generic args (if any are even requied) - // within '<' and '>' signs or there aren't any generic args. We can just - // do the call here instead of letting the dynamic runtime resort to - // calling 'TryGetMember' - - DynamicRemoteMethod drm = GetMethodProxy(binder.Name); - Type binderType = binder.GetType(); - System.Reflection.PropertyInfo TypeArgumentsPropInfo = binderType.GetProperty("TypeArguments"); - if (TypeArgumentsPropInfo != null) - { - // We got ourself a binder which implemented .NET's internal - // "ICSharpInvokeOrInvokeMemberBinder" Interface: - // https://github.com/microsoft/referencesource/blob/master/Microsoft.CSharp/Microsoft/CSharp/ICSharpInvokeOrInvokeMemberBinder.cs - // - // We can now see if the invoked for the function specified generic types - // In that case, we can hijack and do the call here - // Otherwise - Just let TryGetMembre return a proxy - if (TypeArgumentsPropInfo.GetValue(binder) is IList genArgs) - { - foreach (Type t in genArgs) - { - // Aggregate the generic types into the dynamic remote method - // Example: - // * Invoke method is Insert<,> - // * Given types are ['T', 'S'] - // * First loop iteration: Inert<,> --> Insert - // * Second loop iteration: Inert --> Insert - drm = drm[t]; - } - } - } - return drm.TryInvoke(args, out result); - } - - public bool HasMember(string name) => - __members.Any(member => member.Name == name); - public override bool TrySetMember(SetMemberBinder binder, object value) - { - List matches = __members - .Where(member => member.Name == binder.Name) - .ToList(); - - if (!matches.Any()) - { - return false; - } - - // At least 1 member with that name - MemberInfo firstMember = matches[0]; - MemberTypes type = firstMember.MemberType; - bool singleMatch = matches.Count == 1; - - // In case we are resolving a field or property - switch (type) - { - case MemberTypes.Field: - // if (!singleMatch) - // { - // throw new ArgumentException($"Multiple members were found for the name `{binder.Name}` and at least one of them was a field"); - // } - try - { - ((FieldInfo)firstMember).SetValue(__ro, value); - } - catch (Exception ex) - { - throw new Exception($"Field \"{binder.Name}\"'s getter threw an exception", innerException: ex); - } - break; - case MemberTypes.Property: - // if (!singleMatch) - // { - // throw new ArgumentException($"Multiple members were found for the name `{binder.Name}` and at least one of them was a property"); - // } - try - { - ((PropertyInfo)firstMember).SetValue(__ro, value); - } - catch (Exception ex) - { - throw new Exception($"Property \"{binder.Name}\"'s getter threw an exception", innerException: ex); - } - break; - case MemberTypes.Method: - throw new Exception("Can't modifying method members."); - case MemberTypes.Event: - // TODO: - throw new NotImplementedException("Cannot hook to remote events yet."); - default: - throw new Exception($"No such member \"{binder.Name}\"."); - } - return true; - } - - /// - /// Helper function to access the member of the object . - /// This is equivilent to explicitly compiling the expression '.'. - /// - public static bool TryGetDynamicMember(object obj, string memberName, out object output) - { - var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, obj.GetType(), - new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); - var callsite = CallSite>.Create(binder); - if (obj is DynamicRemoteObject dro) - { - if (dro.HasMember(memberName)) - { - if (dro.TryGetMember(binder as GetMemberBinder, out output)) - { - return true; - } - } - } - - // Fallback? Does it always just result in TryGetMember? - try - { - output = callsite.Target(callsite, obj); - return true; - } - catch - { - output = null; - return false; - } - } -#endregion - - #region ToString / GetHashCode / Equals - - public override string ToString() => InvokeMethod(nameof(ToString)); - - public override int GetHashCode() => InvokeMethod(nameof(GetHashCode)); - - public override bool Equals(object obj) - { - throw new NotImplementedException($"Can not call `Equals` on {nameof(DynamicRemoteObject)} instances"); - } - #endregion - - /// - /// Array access. Key can be any primitive / RemoteObject / DynamicRemoteObject - /// - public dynamic this[object key] - { - get - { - - ScubaDiver.API.ObjectOrRemoteAddress ooraKey = RemoteFunctionsInvokeHelper.CreateRemoteParameter(key); - ScubaDiver.API.ObjectOrRemoteAddress item = __ro.GetItem(ooraKey); - if (item.IsNull) - { - return null; - } - else if (item.IsRemoteAddress) - { - return this.__ra.GetRemoteObject(item.RemoteAddress, item.Type).Dynamify(); - } - else - { - return PrimitivesEncoder.Decode(item.EncodedObject, item.Type); - } - } - set => throw new NotImplementedException(); - } - - #region Array Casting - private static T[] __cast_to_array(DynamicRemoteObject dro) - { - dynamic dyn = dro; - int length = dyn.Length; - T[] array = new T[length]; - for (int i = 0; i < length; i++) - array[i] = dyn[i]; - return array; - } - - public static implicit operator bool[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator byte[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator char[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator short[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator ushort[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator int[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator uint[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator long[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator ulong[](DynamicRemoteObject dro) => - __cast_to_array(dro); - public static implicit operator string[](DynamicRemoteObject dro) => - __cast_to_array(dro); - #endregion - - public IEnumerator GetEnumerator() - { - if (!__members.Any(member => member.Name == nameof(GetEnumerator))) - throw new Exception($"No method called {nameof(GetEnumerator)} found. The remote object probably doesn't implement IEnumerable"); - - dynamic enumeratorDro = InvokeMethod(nameof(GetEnumerator)); - return new DynamicRemoteEnumerator(enumeratorDro); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObjectFactory.cs b/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObjectFactory.cs deleted file mode 100644 index b2461b10..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/DynamicRemoteObjectFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ScubaDiver.API.Interactions.Dumps; - - -namespace RemoteNET.Internal -{ - public class DynamicRemoteObjectFactory - { - private RemoteApp _app; - - public DynamicRemoteObject Create(RemoteApp rApp, RemoteObject remoteObj, TypeDump typeDump) - { - _app = rApp; - return new DynamicRemoteObject(rApp, remoteObj); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/ProcessModuleCollectionExt.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/ProcessModuleCollectionExt.cs deleted file mode 100644 index 15cef1e8..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Extensions/ProcessModuleCollectionExt.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; - - -namespace RemoteNET.Internal.Extensions -{ - public static class ProcessModuleCollectionExt - { - public static IEnumerable AsEnumerable(this ProcessModuleCollection collection) - { - for (var i = 0; i < collection.Count; i++) - { - yield return collection[i]; - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/IProxiedMember.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/IProxiedMember.cs deleted file mode 100644 index b6d84fb4..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/IProxiedMember.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace RemoteNET.Internal.ProxiedReflection -{ - public interface IProxiedMember - { - public ProxiedMemberType Type { get; } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedEventInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedEventInfo.cs deleted file mode 100644 index 192db351..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedEventInfo.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - - -namespace RemoteNET.Internal.ProxiedReflection -{ - public class ProxiedEventInfo : IProxiedMember - { - public ProxiedMemberType Type => ProxiedMemberType.Event; - - private readonly RemoteObject _ro; - private string Name { get; set; } - private List ArgumentsTypes { get; set; } - - public ProxiedEventInfo(RemoteObject ro, string name, List args) - { - _ro = ro; - Name = name; - ArgumentsTypes = args; - } - - public static ProxiedEventInfo operator +(ProxiedEventInfo c1, Delegate x) - { - System.Reflection.ParameterInfo[] parameters = x.Method.GetParameters(); - - if (parameters.Length != c1.ArgumentsTypes.Count) - { - throw new Exception($"The '{c1.Name}' event expects {c1.ArgumentsTypes.Count} parameters, " + - $"the callback that was being registered have {parameters.Length}"); - } - - if (parameters.Any(p => p.GetType().IsAssignableFrom(typeof(DynamicRemoteObject)))) - { - throw new Exception("A Remote event's local callback must have only 'dynamic' parameters"); - } - - c1._ro.EventSubscribe(c1.Name, x); - - return c1; - } - - public static ProxiedEventInfo operator -(ProxiedEventInfo c1, Delegate x) - { - c1._ro.EventUnsubscribe(c1.Name, x); - return c1; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMemberType.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMemberType.cs deleted file mode 100644 index b6093e02..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMemberType.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace RemoteNET.Internal.ProxiedReflection -{ - public enum ProxiedMemberType - { - Unknown, - Field, - Property, - Method, - Event - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodGroup.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodGroup.cs deleted file mode 100644 index 677ed202..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodGroup.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; - -using RemoteNET.Internal.Reflection; - - -namespace RemoteNET.Internal.ProxiedReflection -{ - public class ProxiedMethodGroup : List - {} -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodOverload.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodOverload.cs deleted file mode 100644 index 8b65fc83..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedMethodOverload.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; - -using RemoteNET.Internal.Reflection; - - -namespace RemoteNET.Internal.ProxiedReflection -{ - public class ProxiedMethodOverload - { - public Type ReturnType { get; set; } - public List Parameters { get; set; } - public Func Proxy => (object[] arr) => GenericProxy(null, arr); - public Func GenericProxy { get; set; } - public List GenericArgs { get; set; } - public bool IsGenericMethod => GenericArgs?.Count > 0; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs deleted file mode 100644 index f307f73d..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - - -namespace RemoteNET.Internal.ProxiedReflection -{ - /// - /// Info of proxied field or property - /// - public class ProxiedValueMemberInfo : IProxiedMember - { - public string FullTypeName { get; set; } - public Action Setter { get; set; } - public Func Getter { get; set; } - - public ProxiedMemberType Type { get; set; } - public ProxiedValueMemberInfo(ProxiedMemberType type) => Type = type; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DummyGenericType.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DummyGenericType.cs deleted file mode 100644 index 8461da65..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DummyGenericType.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Globalization; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class DummyGenericType : Type - { - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override Module Module { get; } - public override string Namespace { get; } - - private string _name; - public override string Name => _name; - - public DummyGenericType(string name) => _name = name; - - protected override TypeAttributes GetAttributeFlagsImpl() - { - throw new NotImplementedException(); - } - - protected override ConstructorInfo GetConstructorImpl( - BindingFlags bindingAttr, - Binder binder, - CallingConventions callConvention, - Type[] types, ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetElementType() - { - throw new NotImplementedException(); - } - - public override EventInfo GetEvent(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override EventInfo[] GetEvents(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override FieldInfo GetField(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override FieldInfo[] GetFields(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override MemberInfo[] GetMembers(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - protected override MethodInfo GetMethodImpl( - string name, - BindingFlags bindingAttr, - Binder binder, - CallingConventions callConvention, - Type[] types, - ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override MethodInfo[] GetMethods(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override object InvokeMember( - string name, - BindingFlags invokeAttr, - Binder binder, - object target, - object[] args, - ParameterModifier[] modifiers, - CultureInfo culture, - string[] namedParameters) - { - throw new NotImplementedException(); - } - - public override Type UnderlyingSystemType { get; } - - protected override bool IsArrayImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsByRefImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsCOMObjectImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPointerImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPrimitiveImpl() - { - throw new NotImplementedException(); - } - - public override Assembly Assembly { get; } - public override string AssemblyQualifiedName { get; } - public override Type BaseType { get; } - public override string FullName { get; } - public override Guid GUID { get; } - - protected override PropertyInfo GetPropertyImpl( - string name, - BindingFlags bindingAttr, - Binder binder, - Type returnType, - Type[] types, - ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - protected override bool HasElementTypeImpl() - { - throw new NotImplementedException(); - } - - public override Type GetNestedType(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type[] GetNestedTypes(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetInterface(string name, bool ignoreCase) - { - throw new NotImplementedException(); - } - - public override Type[] GetInterfaces() - { - throw new NotImplementedException(); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DynamicRemoteEnum.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DynamicRemoteEnum.cs deleted file mode 100644 index cc31546a..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/DynamicRemoteEnum.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Dynamic; - - -namespace RemoteNET.Internal.Reflection -{ - public class DynamicRemoteEnum : DynamicObject - { - private readonly RemoteEnum _remoteEnum; - public RemoteApp App => _remoteEnum.App; - - public DynamicRemoteEnum(RemoteEnum remoteEnum) - { - _remoteEnum = remoteEnum; - } - - public override bool TryGetMember(GetMemberBinder binder, out dynamic result) - { - string memberName = binder.Name; - result = _remoteEnum.GetValue(memberName); - return true; - } - - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/LazyRemoteTypeResolver.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/LazyRemoteTypeResolver.cs deleted file mode 100644 index 5eaec554..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/LazyRemoteTypeResolver.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - - -namespace RemoteNET.Internal.Reflection -{ - public class LazyRemoteTypeResolver - { - private Lazy _factory; - private string _beforeDumpingTypeName; - private string _beforeDumpingAssemblyName; - private Type _resolved; - - public string Assembly => _resolved?.Assembly?.FullName ?? _beforeDumpingAssemblyName; - public string TypeFullName => _resolved?.FullName ?? _beforeDumpingTypeName; - - public Type Value - { - get - { - _resolved ??= _factory.Value; - return _resolved; - } - } - - public LazyRemoteTypeResolver(Lazy factory, string assembly, string typeFullName) - { - _factory = factory; - _beforeDumpingAssemblyName = assembly; - _beforeDumpingTypeName = typeFullName; - } - - public LazyRemoteTypeResolver(Type resolved) - { - _resolved = resolved; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteConstructorInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteConstructorInfo.cs deleted file mode 100644 index 0113f809..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteConstructorInfo.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteConstructorInfo : ConstructorInfo - { - public override MethodAttributes Attributes => throw new NotImplementedException(); - - public override RuntimeMethodHandle MethodHandle => throw new NotImplementedException(); - - public override Type DeclaringType { get; } - - public override string Name => ".ctor"; - - public override Type ReflectedType => throw new NotImplementedException(); - - private readonly ParameterInfo[] _paramInfos; - private RemoteApp App => (DeclaringType as RemoteType)?.App; - - public RemoteConstructorInfo(Type declaringType, ParameterInfo[] paramInfos) - { - DeclaringType = declaringType; - _paramInfos = paramInfos; - } - - public RemoteConstructorInfo(RemoteType declaringType, ConstructorInfo ci) : - this(declaringType, - ci.GetParameters().Select(pi => new RemoteParameterInfo(pi)).Cast().ToArray()) - {} - - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override MethodImplAttributes GetMethodImplementationFlags() - { - throw new NotImplementedException(); - } - - public override ParameterInfo[] GetParameters() => _paramInfos; - - public override object Invoke( - BindingFlags invokeAttr, - Binder binder, - object[] parameters, - CultureInfo culture) - { - return RemoteFunctionsInvokeHelper - .Invoke( - App, - DeclaringType, - Name, - null, - new Type[0], - parameters); - } - - public override object Invoke( - object obj, - BindingFlags invokeAttr, - Binder binder, - object[] parameters, - CultureInfo culture) - { - // Empirically, invoking a ctor on an existing object should return null. - if (obj == null) - { - // Last chance - If this overload was used but no real object given lets - // redirect to normal Invoke (also happens with normal 'ConstructorInfo's) - return Invoke(invokeAttr, binder, parameters, culture); - } - return null; - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override string ToString() - { - string args = string.Join(", ", _paramInfos.Select(pi => pi.ParameterType.FullName)); - return $"Void {this.Name}({args})"; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEnum.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEnum.cs deleted file mode 100644 index de0708da..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEnum.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace RemoteNET.Internal.Reflection -{ - public class RemoteEnum - { - private readonly RemoteType _remoteType; - public RemoteApp App => _remoteType?.App; - - public RemoteEnum(RemoteType remoteType) => _remoteType = remoteType; - - public object GetValue(string valueName) - { - // NOTE: This is breaking the "RemoteX"/"DynamicX" paradigm because we are - // effectively returning a DRO here. - // - // Unlike RemoteObject which directly uses a remote token + TypeDump to - // read/write fields/props/methods, RemoteEnum was created after - // RemoteType was defined and it felt much easier to utilize it. - // - // RemoteType itself, as part of the reflection API, returns DROs. - RemoteFieldInfo verboseField = _remoteType.GetField(valueName) as RemoteFieldInfo; - return verboseField.GetValue(null); - } - - public dynamic Dynamify() => new DynamicRemoteEnum(this); - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEventInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEventInfo.cs deleted file mode 100644 index 62b3db9a..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteEventInfo.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteEventInfo : EventInfo - { - private Lazy _eventHandlerType; - - public override EventAttributes Attributes => - throw new NotImplementedException(); - - public override Type DeclaringType { get; } - - public override string Name { get; } - - public override Type ReflectedType => - throw new NotImplementedException(); - - public RemoteMethodInfo RemoteAddMethod { get; set; } - public RemoteMethodInfo RemoteRemoveMethod { get; set; } - public override MethodInfo AddMethod => RemoteAddMethod; - public override MethodInfo RemoveMethod => RemoteRemoveMethod; - - - public override Type EventHandlerType => _eventHandlerType.Value; - public RemoteEventInfo( - RemoteType declaringType, - Lazy eventHandlerType, - string name) - { - DeclaringType = declaringType; - _eventHandlerType = eventHandlerType; - Name = name; - } - - public RemoteEventInfo( - RemoteType declaringType, - Type eventHandlerType, - string name) : this(declaringType, new Lazy(() => eventHandlerType), name) - {} - - public RemoteEventInfo( - RemoteType declaringType, - EventInfo ei) : this(declaringType, new Lazy(() => ei.EventHandlerType), ei.Name) - {} - - public override MethodInfo GetAddMethod(bool nonPublic) => RemoteAddMethod; - public override MethodInfo GetRemoveMethod(bool nonPublic) => RemoteRemoveMethod; - - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override MethodInfo GetRaiseMethod(bool nonPublic) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override string ToString() => $"{_eventHandlerType.Value} {Name}"; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFieldInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFieldInfo.cs deleted file mode 100644 index e313b112..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFieldInfo.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Globalization; -using System.Reflection; - -using ScubaDiver.API; -using ScubaDiver.API.Utils; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteFieldInfo : FieldInfo - { - private RemoteApp App => (DeclaringType as RemoteType)?.App; - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - private Lazy _fieldType; - public override Type FieldType => _fieldType.Value; - public override Type DeclaringType { get; } - public override string Name { get; } - - public RemoteFieldInfo(Type declaringType, Lazy fieldType, string name) - { - _fieldType = fieldType; - DeclaringType = declaringType; - Name = name; - } - - public RemoteFieldInfo(Type declaringType, Type fieldType, string name) : this(declaringType, new Lazy(() => fieldType), name) - { - } - - public RemoteFieldInfo(RemoteType declaringType, FieldInfo fi) : this(declaringType, new Lazy(()=> fi.FieldType), fi.Name) - { - } - - public override Type ReflectedType { get; } - public override object GetValue(object obj) - { - ObjectOrRemoteAddress oora = null; - if (obj == null) - { - // No 'this' object --> Static field - - if (App == null) - { - throw new InvalidOperationException($"Trying to get a static field (null target object) " + - $"on a {nameof(RemoteFieldInfo)} but it's associated " + - $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + - $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); - } - - oora = App.Communicator.GetField(0, DeclaringType.FullName, Name).ReturnedObjectOrAddress; - } - else - { - // obj is NOT null. Make sure it's a RemoteObject or DynamicRemoteObject. - RemoteObject ro = obj as RemoteObject; - ro ??= (obj as DynamicRemoteObject)?.__ro; - if (ro != null) - { - oora = ro.GetField(Name); - } - else - { - throw new NotImplementedException( - $"{nameof(RemoteFieldInfo)}.{nameof(GetValue)} only supports {nameof(RemoteObject)} or {nameof(DynamicRemoteObject)} targets."); - } - } - - if (oora == null) - { - string offendingFunc = obj == null ? $"{nameof(DiverCommunicator)}.{nameof(DiverCommunicator.GetField)}" : $"{nameof(RemoteObject)}.{nameof(RemoteObject.GetField)}"; - throw new Exception($"Could not get {nameof(ObjectOrRemoteAddress)} object. Seems like invoking {offendingFunc} returned null."); - } - else - { - if (oora.IsRemoteAddress) - { - var remoteObject = App.GetRemoteObject(oora.RemoteAddress, oora.Type); - return remoteObject.Dynamify(); - } - else if (oora.IsNull) - { - return null; - } - // Primitive - return PrimitivesEncoder.Decode(oora.EncodedObject, oora.Type); - } - } - - public override void SetValue( - object obj, - object value, - BindingFlags invokeAttr, - Binder binder, - CultureInfo culture) - { - var val = value; - if (val.GetType().IsEnum) - { - var enumClass = App.GetRemoteEnum(val.GetType().FullName); - // TODO: This will break on the first enum value which represents 2 or more flags - object enumVal = enumClass.GetValue(val.ToString()); - // NOTE: Object stays in place in the remote app as long as we have it's reference - // in the the value variable(so untill end of this method) - value = enumVal; - } - - // Might throw if the parameter is a local object (not RemoteObject or DynamicRemoteObject). - ObjectOrRemoteAddress remoteNewValue = RemoteFunctionsInvokeHelper.CreateRemoteParameter(value); - - if (obj == null) - { - // No 'this' object --> Static field - - if (App == null) - { - throw new InvalidOperationException($"Trying to get a static field (null target object) " + - $"on a {nameof(RemoteFieldInfo)} but it's associated " + - $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + - $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); - } - - App.Communicator.SetField(0, DeclaringType.FullName, Name, remoteNewValue); - return; - } - - // obj is NOT null. Make sure it's a RemoteObject or DynamicRemoteObject. - RemoteObject ro = obj as RemoteObject; - ro ??= (obj as DynamicRemoteObject)?.__ro; - if (ro != null) - { - ro.SetField(Name, remoteNewValue); - return; - } - - throw new NotImplementedException( - $"{nameof(RemoteFieldInfo)}.{nameof(SetValue)} only supports {nameof(RemoteObject)} or {nameof(DynamicRemoteObject)} targets."); - } - - public override FieldAttributes Attributes { get; } - public override RuntimeFieldHandle FieldHandle { get; } - - public override string ToString() => $"{FieldType.FullName} {Name}"; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFunctionsInvokeHelper.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFunctionsInvokeHelper.cs deleted file mode 100644 index 22cf4805..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteFunctionsInvokeHelper.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Linq; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Utils; - - -namespace RemoteNET.Internal.Reflection -{ - /// - /// In this context: "function" = Methods + Constructors. - /// - internal static class RemoteFunctionsInvokeHelper - { - public static ObjectOrRemoteAddress CreateRemoteParameter(object parameter) - { - if(parameter == null) - { - return ObjectOrRemoteAddress.Null; - } - else if (parameter.GetType().IsPrimitiveEtc() - || parameter.GetType().IsPrimitiveEtcArray() - || parameter.GetType().IsStringCoercible()) - { - return ObjectOrRemoteAddress.FromObj(parameter); - } - else if (parameter is RemoteObject remoteArg) - { - return ObjectOrRemoteAddress - .FromToken(remoteArg.RemoteToken, remoteArg.GetType().FullName); - } - else if (parameter is DynamicRemoteObject dro) - { - RemoteObject originRemoteObject = dro.__ro; - return ObjectOrRemoteAddress - .FromToken(originRemoteObject.RemoteToken, originRemoteObject.GetType().FullName); - } - else if (parameter is Type t) - { - return ObjectOrRemoteAddress.FromType(t); - } - else - { - throw new Exception( - $"{nameof(RemoteMethodInfo)}.{nameof(Invoke)} only works with primitive (int, " + - $"double, string,...) or remote (in {nameof(RemoteObject)}) parameters. " + - $"One of the parameter was of unsupported type {parameter.GetType()}"); - } - } - - public static object Invoke( - RemoteApp app, - Type declaringType, - string funcName, - object obj, - Type[] genericArgs, - object[] parameters) - => Invoke( - app, - declaringType, - funcName, - obj, - genericArgs.Select(arg => arg.FullName).ToArray(), - parameters); - - public static object Invoke( - RemoteApp app, - Type declaringType, - string funcName, - object obj, - string[] genericArgsFullNames, - object[] parameters) - { - // invokeAttr, binder and culture currently ignored - // TODO: Actually validate parameters and expected parameters. - - object[] paramsNoEnums = parameters.ToArray(); - for (int i = 0; i < paramsNoEnums.Length; i++) - { - var val = paramsNoEnums[i]; - if (val != null && val.GetType().IsEnum) - { - var enumClass = app.GetRemoteEnum(val.GetType().FullName); - // TODO: This will break on the first enum value which represents 2 or more flags - object enumVal = enumClass.GetValue(val.ToString()); - // NOTE: Object stays in place in the remote app as long as we have it's reference - // in the paramsNoEnums array (so untill end of this method) - paramsNoEnums[i] = enumVal; - } - } - - ObjectOrRemoteAddress[] remoteParams = paramsNoEnums - .Select(CreateRemoteParameter) - .ToArray(); - - bool hasResults; - ObjectOrRemoteAddress oora; - if (obj == null) - { - if (app == null) - { - throw new InvalidOperationException( - $"Trying to invoke a static call (null target object) " + - $"on a {nameof(RemoteMethodInfo)} but it's associated " + - $"Declaring Type ({declaringType}) does not have a RemoteApp associated. " + - $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); - } - - InvocationResults invokeRes = app.Communicator - .InvokeStaticMethod(declaringType.FullName, funcName, genericArgsFullNames, remoteParams); - if (invokeRes.VoidReturnType) - { - hasResults = false; - oora = null; - } - else - { - hasResults = true; - oora = invokeRes.ReturnedObjectOrAddress; - } - } - else - { - // obj is NOT null. Make sure it's a RemoteObject. - if (!(obj is RemoteObject ro)) - { - throw new NotImplementedException( - $"{nameof(RemoteMethodInfo)}.{nameof(Invoke)} only supports {nameof(RemoteObject)} targets at the moment."); - } - (hasResults, oora) = ro.InvokeMethod(funcName, genericArgsFullNames, remoteParams); - } - - if (!hasResults) - return null; - - // Non-void function. - if (oora.IsNull) - return null; - if (!oora.IsRemoteAddress) - { - return PrimitivesEncoder.Decode(oora); - } - else - { - RemoteObject ro = app.GetRemoteObject(oora.RemoteAddress, oora.Type); - return ro.Dynamify(); - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteMethodInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteMethodInfo.cs deleted file mode 100644 index 7b6a07aa..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteMethodInfo.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteMethodInfo : MethodInfo - { - private LazyRemoteTypeResolver _retType; - - public override ICustomAttributeProvider ReturnTypeCustomAttributes => - throw new NotImplementedException(); - public override string Name { get; } - public override Type DeclaringType { get; } - public override Type ReturnType => _retType.Value; - public override Type ReflectedType => - throw new NotImplementedException(); - public override RuntimeMethodHandle MethodHandle => - throw new NotImplementedException(); - public override MethodAttributes Attributes => - throw new NotImplementedException(); - - public override bool IsGenericMethod => - AssignedGenericArgs.Length > 0; - public override bool IsGenericMethodDefinition => - AssignedGenericArgs.Length > 0 && - AssignedGenericArgs.All(t => t is DummyGenericType); - public override bool ContainsGenericParameters => - AssignedGenericArgs.Length > 0 && - AssignedGenericArgs.All(t => t is DummyGenericType); - public override Type[] GetGenericArguments() => - AssignedGenericArgs; - - public Type[] AssignedGenericArgs { get; } - private readonly ParameterInfo[] _paramInfos; - - private RemoteApp App => (DeclaringType as RemoteType)?.App; - - public RemoteMethodInfo(RemoteType declaringType, MethodInfo mi) : - this(declaringType, - new LazyRemoteTypeResolver(mi.ReturnType), - mi.Name, - mi.GetGenericArguments(), - mi.GetParameters() - .Select(pi => new RemoteParameterInfo(pi)) - .Cast() - .ToArray()) - {} - - public RemoteMethodInfo( - Type declaringType, - LazyRemoteTypeResolver returnType, - string name, - Type[] genericArgs, - ParameterInfo[] paramInfos) - { - Name = name; - DeclaringType = declaringType; - _paramInfos = paramInfos; - _retType = returnType; - - genericArgs ??= Type.EmptyTypes; - AssignedGenericArgs = genericArgs; - } - - public RemoteMethodInfo( - Type declaringType, - Type returnType, - string name, - Type[] genericArgs, - ParameterInfo[] paramInfos) : this(declaringType, new LazyRemoteTypeResolver(returnType), name, genericArgs, paramInfos) - {} - - public override MethodInfo MakeGenericMethod(params Type[] typeArguments) - { - return new RemoteMethodInfo(DeclaringType, ReturnType, Name, typeArguments, _paramInfos); - } - - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override ParameterInfo[] GetParameters() => _paramInfos; - - public override MethodImplAttributes GetMethodImplementationFlags() - { - throw new NotImplementedException(); - } - - public override object Invoke( - object obj, - BindingFlags invokeAttr, - Binder binder, - object[] parameters, - CultureInfo culture) - { - return RemoteFunctionsInvokeHelper - .Invoke(this.App, DeclaringType, Name, obj, AssignedGenericArgs, parameters); - } - - public override MethodInfo GetBaseDefinition() - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override string ToString() - { - try - { - string args = string.Join(", ", _paramInfos.Select(pi => pi.ToString())); - return $"{_retType.TypeFullName} {Name}({args})"; - } - catch (Exception) - { - throw; - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteParameterInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteParameterInfo.cs deleted file mode 100644 index 1d9bb72a..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteParameterInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - /// - /// A parameter of a remote method. The parameter's type itself might be a remote type (but can also be local) - /// - public class RemoteParameterInfo : ParameterInfo - { - private LazyRemoteTypeResolver _paramType; - public override Type ParameterType => _paramType.Value; - - // TODO: Type needs to be converted to a remote type ? - public RemoteParameterInfo(ParameterInfo pi) - : this(pi.Name, new LazyRemoteTypeResolver(pi.ParameterType)) - { - } - - public RemoteParameterInfo( - string name, - LazyRemoteTypeResolver paramType) - { - NameImpl = name; - _paramType = paramType; - } - - public override string ToString() => $"{_paramType.TypeFullName} {Name}"; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemotePropertyInfo.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemotePropertyInfo.cs deleted file mode 100644 index 7de0c573..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemotePropertyInfo.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Globalization; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemotePropertyInfo : PropertyInfo - { - private Lazy _propType; - - private RemoteApp App => (DeclaringType as RemoteType)?.App; - public override PropertyAttributes Attributes => - throw new NotImplementedException(); - - public override bool CanRead => GetMethod != null; - public override bool CanWrite => SetMethod != null; - - public override Type PropertyType => _propType.Value; - - public override Type DeclaringType { get; } - - public override string Name { get; } - - public override Type ReflectedType => - throw new NotImplementedException(); - - public RemoteMethodInfo RemoteGetMethod { get; set; } - public RemoteMethodInfo RemoteSetMethod { get; set; } - - public override MethodInfo GetMethod => RemoteGetMethod; - public override MethodInfo SetMethod => RemoteSetMethod; - - public RemotePropertyInfo(Type declaringType, Lazy propType, string name) - { - _propType = propType; - DeclaringType = declaringType; - Name = name; - } - public RemotePropertyInfo(Type declaringType, Type propType, string name) : - this(declaringType, new Lazy(()=> propType), name) - {} - - public RemotePropertyInfo(RemoteType declaringType, PropertyInfo pi) - : this(declaringType, new Lazy(()=> pi.PropertyType), pi.Name) - {} - - public override MethodInfo[] GetAccessors(bool nonPublic) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override MethodInfo GetGetMethod(bool nonPublic) => this.GetMethod; - public override MethodInfo GetSetMethod(bool nonPublic) => this.SetMethod; - - public override ParameterInfo[] GetIndexParameters() - { - throw new NotImplementedException(); - } - - public override object GetValue( - object obj, - BindingFlags invokeAttr, - Binder binder, - object[] index, - CultureInfo culture) - { - RemoteMethodInfo getMethod = GetGetMethod() as RemoteMethodInfo; - if (getMethod != null) - { - return getMethod.Invoke(obj, new object[0]); - } - else - { - throw new Exception($"Couldn't retrieve 'get' method of property '{this.Name}'"); - } - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override void SetValue( - object obj, - object value, - BindingFlags invokeAttr, - Binder binder, - object[] index, - CultureInfo culture) - { - RemoteMethodInfo setMethod = GetSetMethod() as RemoteMethodInfo; - if (setMethod != null) - { - setMethod.Invoke(obj, new object[1] { value }); - } - else - { - throw new Exception($"Couldn't retrieve 'set' method of property '{this.Name}'"); - } - } - - public override string ToString() => $"{PropertyType.FullName} {Name}"; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteType.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteType.cs deleted file mode 100644 index 49d5cca8..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteType.cs +++ /dev/null @@ -1,336 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteType : Type - { - public class RemoteAssemblyDummy : Assembly - { - AssemblyName _name; - public RemoteAssemblyDummy(string assemblyName) - { - _name = new AssemblyName(assemblyName); - } - public override string FullName => - throw new Exception( - $"You tried to get the 'FullName' property on a {nameof(RemoteAssemblyDummy)}." + - $"Currently, this is forbidden to reduce confusion between 'full name' and 'short name'." + - $"You should call 'GetName().Name' instead."); - - public override AssemblyName GetName() => _name; - } - - private readonly List _ctors = new List(); - private readonly List _methods = new List(); - private readonly List _fields = new List(); - private readonly List _properties = new List(); - private readonly List _events = new List(); - private readonly bool _isArray; - private readonly bool _isGenericParameter; - - public RemoteApp App { get; set; } - - public override bool IsGenericParameter => _isGenericParameter; - - private Lazy _parent; - public override Type BaseType => _parent?.Value; - - public RemoteType(RemoteApp app, Type localType) - : this(app, localType.FullName, localType.Assembly.GetName().Name, localType.IsArray, localType.IsGenericParameter) - { - if (localType is RemoteType) - { - throw new ArgumentException("This constructor of RemoteType is designed to copy a LOCAL Type object. A RemoteType object was provided instead."); - } - - // TODO: This ctor is experimentatl because it makes a LOT of assumptions. - // Most notably the RemoteXXXInfo objects freely use mi's,ci's,pi's (etc) "ReturnType","FieldType","PropertyType" - // not checking if they are actually RemoteTypes themselves... - - foreach (MethodInfo mi in localType.GetMethods()) - AddMethod(new RemoteMethodInfo(this, mi)); - foreach (ConstructorInfo ci in localType.GetConstructors()) - AddConstructor(new RemoteConstructorInfo(this, ci)); - foreach (PropertyInfo pi in localType.GetProperties()) - { - RemotePropertyInfo remotePropInfo = new RemotePropertyInfo(this, pi); - remotePropInfo.RemoteGetMethod = _methods.FirstOrDefault(m => m.Name == "get_" + pi.Name); - remotePropInfo.RemoteSetMethod = _methods.FirstOrDefault(m => m.Name == "set_" + pi.Name); - AddProperty(remotePropInfo); - } - foreach (FieldInfo fi in localType.GetFields()) - AddField(new RemoteFieldInfo(this, fi)); - foreach (EventInfo ei in localType.GetEvents()) - AddEvent(new RemoteEventInfo(this, ei)); - } - - public RemoteType( - RemoteApp app, - string fullName, - string assemblyName, - bool isArray, - bool isGenericParameter = false) - { - App = app; - FullName = fullName; - _isGenericParameter = isGenericParameter; - _isArray = isArray; - Assembly = new RemoteAssemblyDummy(assemblyName); - - // Derieving name from full name - Name = fullName.Substring(fullName.LastIndexOf('.') + 1); - if (fullName.Contains("`")) - { - // Generic. Need to cut differently - string outterTypeFullName = fullName.Substring(0, fullName.IndexOf('`')); - Name = outterTypeFullName.Substring(outterTypeFullName.LastIndexOf('.') + 1); - } - } - - public void AddConstructor(RemoteConstructorInfo rci) - { - _ctors.Add(rci); - } - - public void AddMethod(RemoteMethodInfo rmi) - { - _methods.Add(rmi); - } - - public void AddField(RemoteFieldInfo fieldInfo) - { - _fields.Add(fieldInfo); - } - public void AddProperty(RemotePropertyInfo fieldInfo) - { - _properties.Add(fieldInfo); - } - public void AddEvent(RemoteEventInfo eventInfo) - { - _events.Add(eventInfo); - } - - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => - _ctors.Cast().ToArray(); - - public override Type GetInterface(string name, bool ignoreCase) - { - throw new NotImplementedException(); - } - - public override Type[] GetInterfaces() - { - throw new NotImplementedException(); - } - - public override EventInfo GetEvent(string name, BindingFlags bindingAttr) - { - return GetEvents().Single(ei => ei.Name == name); - } - - public override EventInfo[] GetEvents(BindingFlags bindingAttr) - { - return _events.ToArray(); - } - - public override Type[] GetNestedTypes(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetNestedType(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetElementType() - { - throw new NotImplementedException(); - } - - protected override bool HasElementTypeImpl() - { - throw new NotImplementedException(); - } - - protected override PropertyInfo GetPropertyImpl( - string name, - BindingFlags bindingAttr, - Binder binder, - Type returnType, - Type[] types, - ParameterModifier[] modifiers) - { - return GetProperties().Single(prop => prop.Name == name); - } - - public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) - { - return _properties.ToArray(); - } - - protected override MethodInfo GetMethodImpl( - string name, - BindingFlags bindingAttr, - Binder binder, - CallingConventions callConvention, - Type[] types, - ParameterModifier[] modifiers) - { - var methodGroup = GetMethods().Where(method => - method.Name == name); - if (types == null) - { - // Parameters unknown from caller. Hope we have only one method to return. - return methodGroup.Single(); - } - - bool overloadsComparer(MethodInfo method) - { - var parameters = method.GetParameters(); - // Compare Full Names mainly because the RemoteMethodInfo contains - // RemoteParameterInfos and we might be comparing with local parameters - // (like System.String) - bool matchingExpectingTypes = parameters - .Select(arg => arg.ParameterType.FullName) - .SequenceEqual(types.Select(type => type.FullName)); - return matchingExpectingTypes; - } - - // Need to filer also by types - return methodGroup.Single(overloadsComparer); - } - - public override MethodInfo[] GetMethods(BindingFlags bindingAttr) - { - return _methods.ToArray(); - } - - public override FieldInfo GetField(string name, BindingFlags bindingAttr) - { - return GetFields().Single(field => field.Name == name); - } - - public override FieldInfo[] GetFields(BindingFlags bindingAttr) - { - return _fields.ToArray(); - } - - private IEnumerable GetMembersInner(BindingFlags bf) - { - foreach (var ctor in GetConstructors(bf)) - { - yield return ctor; - } - foreach (var field in GetFields(bf)) - { - yield return field; - } - foreach (var prop in GetProperties(bf)) - { - yield return prop; - } - foreach (var eventt in GetEvents(bf)) - { - yield return eventt; - } - foreach (var method in GetMethods(bf)) - { - yield return method; - } - } - - internal void SetParent(Lazy parent) - { - _parent = parent; - } - - public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => - GetMembersInner(bindingAttr).ToArray(); - - protected override TypeAttributes GetAttributeFlagsImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsArrayImpl() - { - return _isArray; - } - - protected override bool IsByRefImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPointerImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPrimitiveImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsCOMObjectImpl() - { - throw new NotImplementedException(); - } - - public override object InvokeMember( - string name, - BindingFlags invokeAttr, - Binder binder, - object target, - object[] args, - ParameterModifier[] modifiers, - CultureInfo culture, - string[] namedParameters) - { - throw new NotImplementedException(); - } - - public override Type UnderlyingSystemType { get; } - - protected override ConstructorInfo GetConstructorImpl( - BindingFlags bindingAttr, - Binder binder, - CallingConventions callConvention, - Type[] types, - ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override string Name { get; } - public override Guid GUID { get; } - public override Module Module { get; } - public override Assembly Assembly { get; } - public override string FullName { get; } - public override string Namespace { get; } - public override string AssemblyQualifiedName { get; } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override string ToString() => FullName; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteTypesFactory.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteTypesFactory.cs deleted file mode 100644 index 3afe5f66..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/RemoteTypesFactory.cs +++ /dev/null @@ -1,385 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions.Dumps; - - -namespace RemoteNET.Internal.Reflection -{ - public class RemoteTypesFactory - { - private readonly TypesResolver _resolver; - private DiverCommunicator _communicator; - - private bool _avoidGenericsRecursion; - - public RemoteTypesFactory( - TypesResolver resolver, - DiverCommunicator communicator, - bool avoidGenericsRecursion) - { - _resolver = resolver; - - // "Generic Recursion" is a made-up term which means for RemoteNET that Types that look like: - // SomeType< SomeType< SomeType< SomeType< SomeType .... >>>> - // You might ask yourself where such an object is possible and if C# even allows defining such a type. - // Well the example I found is within JetBra*ns "Platform.Core" assembly, where trying to dump some types result - // in a dependent type which looks like: - // JetBra*ns.DataFlow.PropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.PropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.PropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.PropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.BeforePropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.BeforePropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.BeforePropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.BeforePropertyChangedEventArgs`1[[ - // JetBra*ns.DataFlow.BeforePropertyChangedEventArgs`1[[ - // ... - _avoidGenericsRecursion = avoidGenericsRecursion; - _communicator = communicator; - } - - /// - /// This collection marks which types the factory is currently creating - /// it's important since might recursively call itself and - /// types might depend on one another (circular references) - /// - private readonly Dictionary, Type> _onGoingCreations = - new Dictionary, Type>(); - - - public Type ResolveTypeWhileCreating( - RemoteApp app, - string typeInProgress, - string methodName, - string assembly, - string type) - { - if (type.Length > 200) - { - if (type.Contains("[][][][][][]")) - { - throw new Exception("Nestered self arrays types was detected and avoided."); - } - } - if (type.Length > 500) - { - // Too long for any reasonable type - throw new Exception("Incredibly long type names aren't supported."); - } - if (type.Contains("JetBrains.DataFlow.PropertyChangedEventArgs") && type.Length > 100) - { - // Too long for any reasonable type - throw new Exception("Incredibly long type names aren't supported."); - } - - - Type paramType = _resolver.Resolve(assembly, type); - if (paramType != null) - { - // Either found in cache or found locally. - - // If it's a local non-primitive type we need to wrap it in a "fake" - // RemoteType (So method invocations will happen on the remote app) - if (!(paramType is RemoteType) && !paramType.IsPrimitive) - { - paramType = new RemoteType(app, paramType); - // TODO: Registring here in the cache is a hack but we couldn't - // register within "TypesResolver.Resolve" because we don't have the - // RemoteApp to associate the fake remote type with. - // - // Maybe this should move somewhere else... - _resolver.RegisterType(paramType); - } - } - - if (paramType == null) - { - // Second: Search types which are on-going creation - if (!_onGoingCreations.TryGetValue( - new Tuple(assembly, type), out paramType) || paramType == null) - { - TypeDump dumpedArgType = - _communicator.DumpType(type, assembly); - if (dumpedArgType == null) - { - throw new Exception( - $"{nameof(RemoteTypesFactory)} tried to dump type {type} when handling method {methodName} of type" + - $"{typeInProgress} but the {nameof(DiverCommunicator)}.{nameof(DiverCommunicator.DumpType)} function failed."); - } - - Type newCreatedType = Create(app, dumpedArgType); - paramType = newCreatedType - ?? throw new Exception( - $"{nameof(RemoteTypesFactory)} tried to dump type {type} when handling method {methodName} of type" + - $"{typeInProgress} but the inner {nameof(RemoteTypesFactory)}.{nameof(RemoteTypesFactory.Create)} function failed."); - } - } - return paramType; - } - - private Type Create(RemoteApp app, string fullTypeName, string assembly) - { - Type shortOutput = _resolver.Resolve(assembly, fullTypeName); - if (shortOutput != null) - { - return shortOutput; - } - - TypeDump parentDump = _communicator.DumpType(fullTypeName, assembly) - ?? throw new Exception( - $"{nameof(RemoteTypesFactory)} tried to dump type {fullTypeName} " + - $"but the {nameof(DiverCommunicator)}.{nameof(DiverCommunicator.DumpType)} function failed."); - return Create(app, parentDump); - } - - public Type Create(RemoteApp app, TypeDump typeDump) - { - Type shortOutput = _resolver.Resolve(typeDump.Assembly, typeDump.Type); - if (shortOutput != null) - { - return shortOutput; - } - - RemoteType output = new RemoteType(app, typeDump.Type, typeDump.Assembly, typeDump.IsArray); - - // Temporarily indicate we are on-going creation - _onGoingCreations[new Tuple(typeDump.Assembly, typeDump.Type)] = output; - - string parentType = typeDump.ParentFullTypeName; - if (parentType != null) - { - Lazy parent = new Lazy(() => - { - try - { - return Create(app, parentType, typeDump.ParentAssembly); - } - catch (Exception ex) - { - Debug.WriteLine("Failed to dump parent type: " + parentType); - Debug.WriteLine(ex.ToString()); - return null; - } - }); - output.SetParent(parent); - } - AddMembers(app, typeDump, output); - - // remove on-going creation indication - _onGoingCreations.Remove(new Tuple(typeDump.Assembly, typeDump.Type)); - - // Register at resolver - _resolver.RegisterType(typeDump.Assembly, typeDump.Type, output); - - return output; - } - - private void AddMembers(RemoteApp app, TypeDump typeDump, RemoteType output) - { - AddGroupOfFunctions(app, typeDump, typeDump.Methods, output, areConstructors: false); - AddGroupOfFunctions(app, typeDump, typeDump.Constructors, output, areConstructors: true); - AddFields(app, typeDump, output); - AddProperties(app, typeDump, output); - AddEvents(app, typeDump, output); - - // Enrich properties with getters and setters - AttachAccessorsToProperties(output); - - // Enrich events with add/remove methods - AttachAddAndRemoveToEvents(output); - } - - private void AttachAccessorsToProperties(RemoteType output) - { - MethodInfo[] methods = output.GetMethods(); - foreach (PropertyInfo pi in output.GetProperties()) - { - RemotePropertyInfo rpi = pi as RemotePropertyInfo; - MethodInfo getter = methods.FirstOrDefault(mi => mi.Name == "get_" + pi.Name); - rpi.RemoteGetMethod = getter as RemoteMethodInfo; - MethodInfo setter = methods.FirstOrDefault(mi => mi.Name == "set_" + pi.Name); - rpi.RemoteSetMethod = setter as RemoteMethodInfo; - } - } - - private void AddProperties(RemoteApp app, TypeDump typeDump, RemoteType output) - { - foreach (TypeDump.TypeProperty propDump in typeDump.Properties) - { - Lazy factory = new Lazy(() => - { - try - { - return ResolveTypeWhileCreating(app, typeDump.Type, "prop__resolving__logic", - propDump.Assembly, propDump.TypeFullName); - } - catch (Exception e) - { - Debug.WriteLine($"[RemoteTypesFactory] failed to create field {propDump.Name} because its type couldn't be created.\n" + - "The throw exception was: " + e); - return null; - } - }); - - RemotePropertyInfo propInfo = new RemotePropertyInfo(output, factory, propDump.Name); - output.AddProperty(propInfo); - } - } - - private void AttachAddAndRemoveToEvents(RemoteType output) - { - MethodInfo[] methods = output.GetMethods(); - foreach (EventInfo ei in output.GetEvents()) - { - RemoteEventInfo rpi = ei as RemoteEventInfo; - MethodInfo add = methods.FirstOrDefault(mi => mi.Name == "add_" + ei.Name); - rpi.RemoteAddMethod = add as RemoteMethodInfo; - MethodInfo remove = methods.FirstOrDefault(mi => mi.Name == "remove_" + ei.Name); - rpi.RemoteRemoveMethod = remove as RemoteMethodInfo; - } - } - - private void AddEvents(RemoteApp app, TypeDump typeDump, RemoteType output) - { - foreach (TypeDump.TypeEvent eventType in typeDump.Events) - { - Lazy factory = new Lazy(() => - { - try - { - return ResolveTypeWhileCreating(app, typeDump.Type, "event__resolving__logic", eventType.Assembly, eventType.TypeFullName); - } - catch (Exception e) - { - Debug.WriteLine($"[RemoteTypesFactory] failed to create event {eventType.Name} because its type couldn't be created.\n" + - "The throw exception was: " + e); - return null; - } - }); - - var eventInfo = new RemoteEventInfo(output, factory, eventType.Name); - output.AddEvent(eventInfo); - } - } - - private void AddFields(RemoteApp app, TypeDump typeDump, RemoteType output) - { - foreach (TypeDump.TypeField fieldDump in typeDump.Fields) - { - Lazy factory = new Lazy(() => - { - try - { - return ResolveTypeWhileCreating(app, typeDump.Type, "field__resolving__logic", - fieldDump.Assembly, fieldDump.TypeFullName); - } - catch (Exception e) - { - Debug.WriteLine($"[RemoteTypesFactory] failed to create field {fieldDump.Name} because its type couldn't be created.\n" + - "The throw exception was: " + e); - return null; - } - }); - - RemoteFieldInfo fieldInfo = new RemoteFieldInfo(output, factory, fieldDump.Name); - output.AddField(fieldInfo); - } - } - - private void AddGroupOfFunctions(RemoteApp app, TypeDump typeDump, List functions, RemoteType declaringType, bool areConstructors) - { - foreach (TypeDump.TypeMethod func in functions) - { - List parameters = new List(func.Parameters.Count); - foreach (TypeDump.TypeMethod.MethodParameter methodParameter in func.Parameters) - { - Lazy paramFactory = new Lazy(() => - { - // First: Search cache (which means local types & already-seen remote types) - if (methodParameter.IsGenericParameter) - { - // In case of a generic type we have no way to "resolve" it - // We are just creating a dummy type - return new RemoteType(app, typeDump.Type, "FakeAssemblyForGenericTypes", typeDump.IsArray, true); - } - else - { - // Non-generic parameter - // Cases that will not arrive here: - // void MyMethod(T item) <-- The 'item' parameter won't get here - // Cases that will arrive here: - // void MyOtherMethod(System.Text.StringBuilder sb) <-- The 'sb' parameter WILL get here - try - { - Type paramType = ResolveTypeWhileCreating(app, typeDump.Type, func.Name, methodParameter.Assembly, - methodParameter.Type); - if (paramType == null) - { - // TODO: Add stub method to indicate this error to the users? - Debug.WriteLine( - $"[RemoteTypesFactory] Could not resolve method {func.Name} of {methodParameter.Type} using the function {nameof(ResolveTypeWhileCreating)} " + - $"and it did not throw any exceptions (returned NULL)."); - return null; - } - return paramType; - } - catch (Exception e) - { - // TODO: Add stub method to indicate this error to the users? - Debug.WriteLine( - $"[RemoteTypesFactory] Could not resolve method {func.Name} of {methodParameter.Type} using the function {nameof(ResolveTypeWhileCreating)} " + - $"and it threw this exception: " + e); - return null; - } - } - }); - LazyRemoteTypeResolver paramTypeResolver = new LazyRemoteTypeResolver(paramFactory, - methodParameter.Assembly, - methodParameter.Type); - RemoteParameterInfo rpi = new RemoteParameterInfo(methodParameter.Name, paramTypeResolver); - parameters.Add(rpi); - } - - Lazy factory = new Lazy(() => - { - try - { - return ResolveTypeWhileCreating(app, typeDump.Type, func.Name, - func.ReturnTypeAssembly, func.ReturnTypeFullName); - } - catch (Exception e) - { - // TODO: This sometimes throws because of generic results (like List) - Debug.WriteLine($"[RemoteTypesFactory] failed to create method {func.Name} because its return type could be created.\n" + - "The throw exception was: " + e); - // TODO: Add stub method to indicate this error to the users? - return null; - } - }); - LazyRemoteTypeResolver resolver = new LazyRemoteTypeResolver(factory, func.ReturnTypeAssembly, func.ReturnTypeFullName); - - if (areConstructors) - { - RemoteConstructorInfo ctorInfo = - new RemoteConstructorInfo(declaringType, parameters.ToArray()); - declaringType.AddConstructor(ctorInfo); - } - else - { - Type[] genericArgs = func.GenericArgs.Select(arg => new DummyGenericType(arg)).ToArray(); - - // Regular method - RemoteMethodInfo methodInfo = - new RemoteMethodInfo(declaringType, resolver, func.Name, genericArgs, parameters.ToArray()); - declaringType.AddMethod(methodInfo); - } - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/TypesResolver.cs b/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/TypesResolver.cs deleted file mode 100644 index 2aca911e..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/Reflection/TypesResolver.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - - -namespace RemoteNET.Internal.Reflection -{ - /// - /// Resolves local and remote types. Contains a cache so the same TypeFullName - /// object is returned for different resolutions for the same remote type. - /// - public class TypesResolver - { - // Since the resolver works with a cache that should be global we make the - // whole class a singleton - public static TypesResolver Instance = new TypesResolver(); - - private TypesResolver() { } - - private readonly Dictionary, Type> _cache = new Dictionary, Type>(); - - public void RegisterType(Type type) - => RegisterType(type.Assembly.GetName().Name, type.FullName, type); - - public void RegisterType(string assemblyName, string typeFullName, Type type) - { - _cache[new Tuple(assemblyName, typeFullName)] = type; - } - - public Type Resolve(string assemblyName, string typeFullName) - { - // Start by searching cache - if (_cache.TryGetValue(new Tuple(assemblyName, typeFullName), out Type resolvedType)) - { - return resolvedType; - } - - // Search for locally available types - // EXCEPT for enums because that breaks RemoteEnum - IEnumerable assemblies = AppDomain.CurrentDomain.GetAssemblies(); - // Filter assemblies but avoid filtering for "mscorlib" - if(assemblyName?.Equals("mscorlib") == false) - { - assemblies = assemblies.Where(assm => assm.FullName.Contains(assemblyName ?? "")); - } - foreach (Assembly assembly in assemblies) - { - resolvedType = assembly.GetType(typeFullName); - if(resolvedType != null) - { - // Found the type! - // But retreat if it's an enum (and get remote proxy of it instead) - if(resolvedType.IsEnum) - { - resolvedType = null; - } - break; - } - } - - if (resolvedType != null && resolvedType is RemoteType) - { - RegisterType(assemblyName, typeFullName, resolvedType); - } - return resolvedType; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Internal/RemoteObjectRef.cs b/third_party/RemoteNET/src/RemoteNET/Internal/RemoteObjectRef.cs deleted file mode 100644 index 16b6ffc1..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Internal/RemoteObjectRef.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Linq; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Dumps; - - -namespace RemoteNET.Internal -{ - internal class RemoteObjectRef - { - private bool _isReleased; - private readonly TypeDump _typeInfo; - private ObjectDump _remoteObjectInfo; - private readonly DiverCommunicator _creatingCommunicator; - - // TODO: I think addresses as token should be reworked - public ulong Token => _remoteObjectInfo.PinnedAddress; - public DiverCommunicator Communicator => _creatingCommunicator; - - - public RemoteObjectRef( - ObjectDump remoteObjectInfo, - TypeDump typeInfo, - DiverCommunicator creatingCommunicator) - { - _remoteObjectInfo = remoteObjectInfo; - _typeInfo = typeInfo - ?? throw new ArgumentNullException(nameof(typeInfo)); - _creatingCommunicator = creatingCommunicator; - _isReleased = false; - } - - public TypeDump GetTypeDump() - { - return _typeInfo; - } - - /// - /// Gets the value of a remote field. Returned value might be a cached version unless is set to True. - /// - /// Name of field to get the value of - /// Whether the value should be read again for this invocation or a cache version is good enough - public MemberDump GetFieldDump(string name, bool refresh = false) - { - ThrowIfReleased(); - if (refresh) - { - _remoteObjectInfo = _creatingCommunicator - .DumpObject(_remoteObjectInfo.PinnedAddress, _remoteObjectInfo.Type); - } - - var field = _remoteObjectInfo.Fields.Single(fld => fld.Name == name); - if (!string.IsNullOrEmpty(field.RetrievalError)) - throw new Exception( - $"Field of the remote object could not be retrieved. Error: {field.RetrievalError}"); - - // field has a value. Returning as-is for the user to parse - return field; - } - /// - /// Gets the value of a remote property. Returned value might be a cached version unless is set to True. - /// - /// Name of property to get the value of - /// Whether the value should be read again for this invocation or a cache version is good enough - public MemberDump GetProperty(string name, bool refresh = false) - { - ThrowIfReleased(); - if (refresh) - { - throw new NotImplementedException("Refreshing property values not supported yet"); - } - - var property = _remoteObjectInfo.Properties.Single(prop => prop.Name == name); - if (!string.IsNullOrEmpty(property.RetrievalError)) - { - throw new Exception( - $"Property of the remote object could not be retrieved. Error: {property.RetrievalError}"); - } - - // property has a value. Returning as-is for the user to parse - return property; - } - - private void ThrowIfReleased() - { - if (_isReleased) - { - throw new ObjectDisposedException("Cannot use RemoteObjectRef object after `Release` have been called"); - } - } - - public InvocationResults InvokeMethod( - string methodName, - string[] genericArgsFullTypeNames, - ObjectOrRemoteAddress[] args) - { - ThrowIfReleased(); - return _creatingCommunicator - .InvokeMethod( - _remoteObjectInfo.PinnedAddress, - _remoteObjectInfo.Type, - methodName, - genericArgsFullTypeNames, - args); - } - - public InvocationResults SetField(string fieldName, ObjectOrRemoteAddress newValue) - { - ThrowIfReleased(); - return _creatingCommunicator - .SetField( - _remoteObjectInfo.PinnedAddress, - _remoteObjectInfo.Type, - fieldName, - newValue); - } - public InvocationResults GetField(string fieldName) - { - ThrowIfReleased(); - return _creatingCommunicator - .GetField( - _remoteObjectInfo.PinnedAddress, - _remoteObjectInfo.Type, - fieldName); - } - - public void EventSubscribe(string eventName, DiverCommunicator.LocalEventCallback callbackProxy) - { - ThrowIfReleased(); - - _creatingCommunicator.EventSubscribe(_remoteObjectInfo.PinnedAddress, eventName, callbackProxy); - } - - public void EventUnsubscribe(string eventName, DiverCommunicator.LocalEventCallback callbackProxy) - { - ThrowIfReleased(); - - _creatingCommunicator.EventUnsubscribe(callbackProxy); - } - - /// - /// Releases hold of the remote object in the remote process and the local proxy. - /// - public void RemoteRelease() - { - _creatingCommunicator.UnpinObject(_remoteObjectInfo.PinnedAddress); - _isReleased = true; - } - - public override string ToString() - { - return $"RemoteObjectRef. Address: {_remoteObjectInfo.PinnedAddress}, TypeFullName: {_typeInfo.Type}"; - } - - internal ObjectOrRemoteAddress GetItem(ObjectOrRemoteAddress key) - { - return _creatingCommunicator.GetItem(Token, key); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Logger.cs b/third_party/RemoteNET/src/RemoteNET/Logger.cs deleted file mode 100644 index c22ca0c2..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Logger.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Diagnostics; - - -namespace RemoteNET -{ - internal class Logger - { - public static Lazy DebugInRelease = new Lazy(() => - !string.IsNullOrWhiteSpace( - Environment.GetEnvironmentVariable("REMOTE_NET_DIVER_MAGIC_DEBUG"))); - - #if DEBUG - public static bool IsDebug = true; - #else - public static bool IsDebug = false; - #endif - - internal static void Debug(string s) - { - if (IsDebug || Debugger.IsAttached) - { - System.Diagnostics.Debug.WriteLine(s); - } - // Allow debug logging in release only if the environment variable is set. - else if(DebugInRelease.Value) - { - Console.WriteLine(s); - } - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteActivator.cs b/third_party/RemoteNET/src/RemoteNET/RemoteActivator.cs deleted file mode 100644 index 4bd0de6a..00000000 --- a/third_party/RemoteNET/src/RemoteNET/RemoteActivator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Linq; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions; - -using RemoteNET.Internal.Reflection; - - -namespace RemoteNET -{ - public class RemoteActivator - { - private readonly RemoteApp _app; - private readonly DiverCommunicator _communicator; - - internal RemoteActivator(DiverCommunicator communicator, RemoteApp app) - { - _communicator = communicator; - _app = app; - } - - public RemoteObject CreateInstance(Type t) => - CreateInstance(t, new object[0]); - - public RemoteObject CreateInstance(Type t, params object[] parameters) => - CreateInstance(t.Assembly.FullName, t.FullName, parameters); - - public RemoteObject CreateInstance( - string typeFullName, - params object[] parameters) - => CreateInstance(null, typeFullName, parameters); - - public RemoteObject CreateInstance( - string assembly, - string typeFullName, - params object[] parameters) - { - object[] paramsNoEnums = parameters.ToArray(); - for (int i = 0; i < paramsNoEnums.Length; i++) - { - var val = paramsNoEnums[i]; - if (val.GetType().IsEnum) - { - var enumClass = _app.GetRemoteEnum(val.GetType().FullName); - // TODO: This will break on the first enum value which represents 2 or more flags - object enumVal = enumClass.GetValue(val.ToString()); - // NOTE: Object stays in place in the remote app as long as we have it's reference - // in the paramsNoEnums array (so until end of this method) - paramsNoEnums[i] = enumVal; - } - } - - ObjectOrRemoteAddress[] remoteParams = paramsNoEnums.Select( - RemoteFunctionsInvokeHelper.CreateRemoteParameter).ToArray(); - - // Create object + pin - InvocationResults invoRes = _communicator - .CreateObject(typeFullName, remoteParams); - - // Get proxy object - var remoteObject = _app.GetRemoteObject( - invoRes.ReturnedObjectOrAddress.RemoteAddress, - invoRes.ReturnedObjectOrAddress.Type); - return remoteObject; - } - - public RemoteObject CreateInstance() => - CreateInstance(typeof(T)); - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteApp.cs b/third_party/RemoteNET/src/RemoteNET/RemoteApp.cs deleted file mode 100644 index 3b41628b..00000000 --- a/third_party/RemoteNET/src/RemoteNET/RemoteApp.cs +++ /dev/null @@ -1,310 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions.Dumps; -using ScubaDiver.API.Utils; - -using RemoteNET.Internal; -using RemoteNET.Internal.Reflection; - - -namespace RemoteNET -{ - public class RemoteApp : IDisposable - { - internal class RemoteObjectsCollection - { - // The WeakReferences are to RemoteObject - private readonly Dictionary> _pinnedAddressesToRemoteObjects; - private readonly object _lock = new object(); - - private readonly RemoteApp _app; - - public RemoteObjectsCollection(RemoteApp app) - { - _app = app; - _pinnedAddressesToRemoteObjects = new Dictionary>(); - } - - private RemoteObject GetRemoteObjectUncached( - ulong remoteAddress, - string typeName, - int? hashCode = null) - { - ObjectDump od; - TypeDump td; - try - { - od = _app._communicator.DumpObject(remoteAddress, typeName, true, hashCode); - td = _app._communicator.DumpType(od.Type); - } - catch (Exception e) - { - throw new Exception("Could not dump remote object/type.", e); - } - - var remoteObject = new RemoteObject( - new RemoteObjectRef(od, td, _app._communicator), _app); - - return remoteObject; - } - - public RemoteObject GetRemoteObject( - ulong address, - string typeName, - int? hashcode = null) - { - RemoteObject ro; - WeakReference weakRef; - // Easiert way - Non-collected and previouslt obtained object ("Cached") - if (_pinnedAddressesToRemoteObjects.TryGetValue(address, out weakRef) && - weakRef.TryGetTarget(out ro)) - { - // Not GC'd! - return ro; - } - - // Harder case - At time of checking, item wasn't cached. - // We need exclusive access to the cahce now to make sure we are the only one adding it. - lock (_lock) - { - // Last chance - when we waited on the lock some other thread might've added it to the cache. - if (_pinnedAddressesToRemoteObjects.TryGetValue(address, out weakRef)) - { - bool gotTarget = weakRef.TryGetTarget(out ro); - if (gotTarget) - { - // Not GC'd! - return ro; - } - else - { - // Object was GC'd... - _pinnedAddressesToRemoteObjects.Remove(address); - // Now let's make sure the GC'd object finalizer was also called (otherwise some "object moved" errors might happen). - GC.WaitForPendingFinalizers(); - // Now we need to-read the remote object since stuff might have moved - } - } - - // Get remote - ro = GetRemoteObjectUncached(address, typeName, hashcode); - // Add to cache - weakRef = new WeakReference(ro); - _pinnedAddressesToRemoteObjects[ro.RemoteToken] = weakRef; - } - - return ro; - } - } - - private Process _procWithDiver; - private DiverCommunicator _communicator; - private DomainsDump _domains; - private readonly RemoteObjectsCollection _remoteObjects; - - public Process Process => _procWithDiver; - public RemoteActivator Activator { get; private set; } - - public DiverCommunicator Communicator => _communicator; - public static bool IsReconnected = false; - - private RemoteApp(Process procWithDiver, DiverCommunicator communicator) - { - _procWithDiver = procWithDiver; - _communicator = communicator; - Activator = new RemoteActivator(communicator, this); - _remoteObjects = new RemoteObjectsCollection(this); - } - - // - // Init - // - - /// - /// Creates a new provider. - /// - /// Process to create the provider for - /// A provider for the given process - public static RemoteApp Connect(Process target) - { - return Connect(target, (ushort)target.Id); - } - - public static RemoteApp Connect(Process target, ushort diverPort) - { - // Use discovery to check for existing diver - string diverAddr = "127.0.0.1"; - switch(DiverDiscovery.QueryStatus(target, diverAddr, diverPort)) - { - case DiverState.NoDiver: - // No diver, we need to inject one - try - { - Bootstrapper.Inject(target, diverPort); - break; - } - catch (IOException e) - { - throw new Exception("Failed to inject diver.", e); - } - case DiverState.Alive: - // Skip injection as diver assembly is already bootstrapped - IsReconnected = true; - break; - case DiverState.Corpse: - throw new Exception("Diver could not finish bootstrapping."); - case DiverState.HollowSnapshot: - throw new Exception("Target process is empty. Did you attach to the correct process?"); - } - - // Now register our program as a "client" of the diver - DiverCommunicator com = new DiverCommunicator(diverAddr, diverPort); - if (com.RegisterClient() == false) - throw new Exception("Registering as a client in the Diver failed."); - - return new RemoteApp(target, com); - } - - // - // Remote Heap querying - // - - public IEnumerable QueryTypes(string typeFullNameFilter) - { - Predicate matchesFilter = Filter.CreatePredicate(typeFullNameFilter); - - _domains ??= _communicator.DumpDomains(); - foreach (DomainsDump.AvailableDomain domain in _domains.AvailableDomains) - { - foreach (string assembly in domain.AvailableModules) - { - List typeIdentifiers; - try - { - typeIdentifiers = _communicator.DumpTypes(assembly).Types; - } - catch - { - // TODO: - Debug.WriteLine($"[{nameof(RemoteApp)}][{nameof(QueryTypes)}] Exception thrown when Dumping/Iterating assembly: {assembly}"); - continue; - } - foreach (TypesDump.TypeIdentifiers type in typeIdentifiers) - { - // TODO: Filtering should probably be done in the Diver's side - if (matchesFilter(type.TypeName)) - yield return new CandidateType(type.TypeName, assembly); - } - - } - } - - } - - public IEnumerable QueryInstances(Type typeFilter, bool dumpHashcodes = true) => QueryInstances(typeFilter.FullName, dumpHashcodes); - - /// - /// Gets all object candidates for a specific filter - /// - /// Objects with Full Type Names of this EXACT string will be returned. You can use '*' as a "0 or more characters" wildcard - /// Whether to also dump hashcodes of every matching object. - /// This makes resolving the candidates later more reliable but for wide queries (e.g. "*") this might fail the entire search since it causes instabilities in the heap when examining it. - /// - public IEnumerable QueryInstances(string typeFullNameFilter, bool dumpHashcodes = true) - { - return _communicator.DumpHeap(typeFullNameFilter, dumpHashcodes).Objects - .Select(heapObj => - new CandidateObject(heapObj.Address, heapObj.Type, heapObj.HashCode)); - } - - // - // Resolving Types - // - - /// - /// Gets a handle to a remote type (even ones from assemblies we aren't - /// referencing/loading to the local process) - /// - /// Full name of the type to get. For example 'System.Xml.XmlDocument' - /// Optional short name of the assembly containing the type. For example 'System.Xml.ReaderWriter.dll' - /// - public Type GetRemoteType(string typeFullName, string assembly = null) - { - // Easy case: Trying to resolve from cache or from local assemblies - var resolver = TypesResolver.Instance; - Type res = resolver.Resolve(assembly, typeFullName); - if (res != null) - { - // Either found in cache or found locally. - - // If it's a local type we need to wrap it in a "fake" RemoteType (So - // method invocations will actually happened in the remote app, for - // example) (But not for primitives...) - if (!(res is RemoteType) && !res.IsPrimitive) - { - res = new RemoteType(this, res); - // TODO: Registering here in the cache is a hack but we couldn't - // register within "TypesResolver.Resolve" because we don't have the - // RemoteApp to associate the fake remote type with. - // Maybe this should move somewhere else... - resolver.RegisterType(res); - } - return res; - } - - // Harder case: Dump the remote type. This takes much more time (includes - // dumping of dependent types) and should be avoided as much as possible. - RemoteTypesFactory rtf = new RemoteTypesFactory(resolver, _communicator, - avoidGenericsRecursion: true); - var dumpedType = _communicator.DumpType(typeFullName, assembly); - return rtf.Create(this, dumpedType); - } - /// - /// Returns a handle to a remote type based on a given local type. - /// - public Type GetRemoteType(Type localType) => - GetRemoteType(localType.FullName, localType.Assembly.GetName().Name); - public Type GetRemoteType(CandidateType candidate) => - GetRemoteType(candidate.TypeFullName, candidate.Assembly); - internal Type GetRemoteType(TypeDump typeDump) => - GetRemoteType(typeDump.Type, typeDump.Assembly); - - public RemoteEnum GetRemoteEnum(string typeFullName, string assembly = null) - { - RemoteType remoteType = GetRemoteType(typeFullName, assembly) as RemoteType - ?? throw new Exception("Failed to dump remote enum (and get a RemoteType object)"); - return new RemoteEnum(remoteType); - } - - // - // Getting Remote Objects - // - - public RemoteObject GetRemoteObject(CandidateObject candidate) => - GetRemoteObject(candidate.Address, candidate.TypeFullName, candidate.HashCode); - - public RemoteObject GetRemoteObject( - ulong remoteAddress, - string typeName, - int? hashCode = null) - { - return _remoteObjects.GetRemoteObject(remoteAddress, typeName, hashCode); - } - - // - // IDisposable - // - public void Dispose() - { - Communicator?.KillDiver(); - _communicator = null; - _procWithDiver = null; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj b/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj index cf1bd5e8..c80659b3 100644 --- a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj +++ b/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj @@ -3,36 +3,10 @@ netstandard2.0 Latest - $(NoWarn);NU1702 - - - - - - - - - - - - - - - - - - - - - - - + + + \ No newline at end of file diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteObject.cs b/third_party/RemoteNET/src/RemoteNET/RemoteObject.cs deleted file mode 100644 index bb690c4e..00000000 --- a/third_party/RemoteNET/src/RemoteNET/RemoteObject.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Collections.Generic; - -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Dumps; - -using RemoteNET.Internal; - - -namespace RemoteNET -{ - public class RemoteObject - { - private static int NextIndex = 1; - public int Index; - - private readonly RemoteApp _app; - private RemoteObjectRef _ref; - private Type _type = null; - - private readonly Dictionary _eventCallbacksAndProxies; - - public ulong RemoteToken => _ref.Token; - - internal RemoteObject(RemoteObjectRef reference, RemoteApp remoteApp) - { - Index = NextIndex++; - _app = remoteApp; - _ref = reference; - _eventCallbacksAndProxies = new Dictionary(); - } - - /// - /// Gets the type of the proxied remote object, in the remote app. (This does not return `typeof(RemoteObject)`) - /// - public new Type GetType() => _type ??= _app.GetRemoteType(_ref.GetTypeDump()); - - public ObjectOrRemoteAddress SetField(string fieldName, ObjectOrRemoteAddress newValue) - { - InvocationResults invokeRes = _ref.SetField(fieldName, newValue); - return invokeRes.ReturnedObjectOrAddress; - - } - - public (bool hasResults, ObjectOrRemoteAddress returnedValue) InvokeMethod( - string methodName, - params ObjectOrRemoteAddress[] args) - => InvokeMethod(methodName, args); - - public (bool hasResults, ObjectOrRemoteAddress returnedValue) InvokeMethod( - string methodName, - string[] genericArgsFullTypeNames, - params ObjectOrRemoteAddress[] args) - { - InvocationResults invokeRes = _ref.InvokeMethod(methodName, genericArgsFullTypeNames, args); - if (invokeRes.VoidReturnType) - { - return (false, null); - } - return (true, invokeRes.ReturnedObjectOrAddress); - } - - public dynamic Dynamify() - { - // Adding fields - TypeDump typeDump = _ref.GetTypeDump(); - - var factory = new DynamicRemoteObjectFactory(); - return factory.Create(_app, this, typeDump); - } - - ~RemoteObject() - { - _ref?.RemoteRelease(); - _ref = null; - } - - public override string ToString() - { - return $"RemoteObject. Type: {_type?.FullName ?? "UNK"} Reference: [{_ref}]"; - } - - public ObjectOrRemoteAddress GetField(string name) - { - var res = _ref.GetField(name); - return res.ReturnedObjectOrAddress; - } - - public void EventSubscribe(string eventName, Delegate callback) - { - // TODO: Add a check for amount of parameters and types (need to be dynamics) - // See implementation inside DynamicEventProxy - - (bool voidReturnType, ObjectOrRemoteAddress res) callbackProxy(ObjectOrRemoteAddress[] args) - { - DynamicRemoteObject[] droParameters = new DynamicRemoteObject[args.Length]; - for (int i = 0; i < args.Length; i++) - { - RemoteObject ro = _app.GetRemoteObject(args[i].RemoteAddress, args[i].Type); - DynamicRemoteObject dro = ro.Dynamify() as DynamicRemoteObject; - - droParameters[i] = dro; - } - - // Call the callback with the proxied parameters (using DynamicRemoteObjects) - callback.DynamicInvoke(droParameters); - - // TODO: Return the result of the callback - return (true, null); - } - - _eventCallbacksAndProxies[callback] = callbackProxy; - - _ref.EventSubscribe(eventName, callbackProxy); - } - - public void EventUnsubscribe(string eventName, Delegate callback) - { - if (_eventCallbacksAndProxies.TryGetValue(callback, out DiverCommunicator.LocalEventCallback callbackProxy)) - { - _ref.EventUnsubscribe(eventName, callbackProxy); - - _eventCallbacksAndProxies.Remove(callback); - } - } - - internal ObjectOrRemoteAddress GetItem(ObjectOrRemoteAddress key) - { - return _ref.GetItem(key); - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Utils/DebuggableRemoteObject.cs b/third_party/RemoteNET/src/RemoteNET/Utils/DebuggableRemoteObject.cs deleted file mode 100644 index f480bb9c..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Utils/DebuggableRemoteObject.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -using RemoteNET.Internal; - - -namespace RemoteNET.Utils -{ - public class DebuggableRemoteObject - { - private DynamicRemoteObject _dro; - - public Dictionary Fields => - GetMembersValues(_dro.GetType().GetFields()); - public Dictionary Properties => - GetMembersValues(_dro.GetType().GetProperties()); - public Dictionary Methods => - _dro.GetType().GetMethods().ToDictionary(mi => mi.Name, mi => (object)mi); - - public DebuggableRemoteObject(DynamicRemoteObject dro) - { - _dro = dro; - } - - private Dictionary GetMembersValues(IEnumerable members) - { - Dictionary output =new Dictionary(); - foreach (var member in members) - { - try - { - if (DynamicRemoteObject.TryGetDynamicMember(_dro, member.Name, out object value)) - output[member.Name] = value; - else - output[member.Name] = new Exception("TryGetDynamicMember failed"); - } - catch (Exception ex) - { - output[member.Name] = new Exception("TryGetDynamicMember failed threw an exception: " + ex); - } - } - return output; - } - } - - public static class DebuggableRemoteObjectExt - { - public static DebuggableRemoteObject AsDebuggable(this DynamicRemoteObject dro) => - new DebuggableRemoteObject(dro); - public static DebuggableRemoteObject AsDebuggable(this RemoteObject ro) => - new DebuggableRemoteObject(ro.Dynamify()); - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Utils/Lambda.cs b/third_party/RemoteNET/src/RemoteNET/Utils/Lambda.cs deleted file mode 100644 index 88e9ebd4..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Utils/Lambda.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; - - -namespace RemoteNET.Utils -{ - public static class Lambda - { - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - public static object __(Action a) => a; - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/Utils/MethodBaseExtensions.cs b/third_party/RemoteNET/src/RemoteNET/Utils/MethodBaseExtensions.cs deleted file mode 100644 index 562c5ca9..00000000 --- a/third_party/RemoteNET/src/RemoteNET/Utils/MethodBaseExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Reflection; - - -namespace RemoteNET.Utils -{ - public static class MethodBaseExtensions - { - public static bool SignatureEquals(this MethodBase a, MethodBase b) - { - if (a.Name != b.Name) - return false; - if (!ParametersEqual(a.GetParameters(), b.GetParameters())) - return false; - - if((a is MethodInfo aInfo) && (b is MethodInfo bInfo) - && aInfo.ReturnType != null && bInfo.ReturnType != null) - { - return aInfo.ReturnType.FullName == bInfo.ReturnType.FullName; - } - else if((a is ConstructorInfo aCtro) && (b is ConstructorInfo bCtor)) - { - // The "Return" type of a ctor is it's defining type... - return aCtro.DeclaringType == bCtor.DeclaringType; - } - else - { - // Unknown derived class of MethodBase - return false; - } - } - - public static bool ParametersEqual(ParameterInfo[] a, ParameterInfo[] b) - { - if(a.Length != b.Length) - return false; - for (int i = 0; i < a.Length; i++) - if (a[i].ParameterType != b[i].ParameterType) - return false; - return true; - } - } -} diff --git a/third_party/RemoteNET/src/RemoteNET/packages.lock.json b/third_party/RemoteNET/src/RemoteNET/packages.lock.json index 7f04c524..b7e843ee 100644 --- a/third_party/RemoteNET/src/RemoteNET/packages.lock.json +++ b/third_party/RemoteNET/src/RemoteNET/packages.lock.json @@ -2,12 +2,6 @@ "version": 1, "dependencies": { ".NETStandard,Version=v2.0": { - "Microsoft.CSharp": { - "type": "Direct", - "requested": "[4.7.0, )", - "resolved": "4.7.0", - "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" - }, "NETStandard.Library": { "type": "Direct", "requested": "[2.0.3, )", @@ -17,157 +11,10 @@ "Microsoft.NETCore.Platforms": "1.1.0" } }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.2" - } - }, - "Microsoft.Diagnostics.NETCore.Client": { - "type": "Transitive", - "resolved": "0.2.410101", - "contentHash": "I4hMjlbPcM5R+M4ThD2Zt1z58M8uZnWkDbFLXHntOOAajajEucrw4XYNSaoi5rgoqksgxQ3g388Vof4QzUNwdQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "1.1.0", - "Microsoft.Extensions.Logging": "2.1.1" - } - }, - "Microsoft.Diagnostics.Runtime": { - "type": "Transitive", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", - "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", - "dependencies": { - "Microsoft.Extensions.Configuration": "2.1.1" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "2.1.1", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Logging.Abstractions": "2.1.1", - "Microsoft.Extensions.Options": "2.1.1" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==" - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Primitives": "2.1.1" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", - "dependencies": { - "System.Memory": "4.5.1", - "System.Runtime.CompilerServices.Unsafe": "4.5.1" - } - }, "Microsoft.NETCore.Platforms": { "type": "Transitive", "resolved": "1.1.0", "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.3", - "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", - "dependencies": { - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.4.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.2", - "contentHash": "BG/TNxDFv0svAzx8OiMXDlsHfGw623BZ8tCXw4YLhDFDvDhNUEV58jKYMGRnkbJNm7c3JNNJDiN7JBMzxRBR2w==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.2" - } - }, - "mtgosdk.win32": { - "type": "Project" - }, - "scubadiver.api": { - "type": "Project", - "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", - "Newtonsoft.Json": "[13.0.3, )" - } } } } diff --git a/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj b/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj index fa50bc66..a805b0ef 100644 --- a/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj +++ b/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj @@ -3,16 +3,10 @@ netstandard2.0 latest - enable - 1701;1702;8600;8602;8603;8618;8625 - True - - - - + + + \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json b/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json index 44eeabcf..b7e843ee 100644 --- a/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json +++ b/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json @@ -2,17 +2,6 @@ "version": 1, "dependencies": { ".NETStandard,Version=v2.0": { - "Microsoft.Diagnostics.Runtime": { - "type": "Direct", - "requested": "[3.0.442202, )", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", - "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, "NETStandard.Library": { "type": "Direct", "requested": "[2.0.3, )", @@ -22,138 +11,10 @@ "Microsoft.NETCore.Platforms": "1.1.0" } }, - "Newtonsoft.Json": { - "type": "Direct", - "requested": "[13.0.3, )", - "resolved": "13.0.3", - "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.2" - } - }, - "Microsoft.Diagnostics.NETCore.Client": { - "type": "Transitive", - "resolved": "0.2.410101", - "contentHash": "I4hMjlbPcM5R+M4ThD2Zt1z58M8uZnWkDbFLXHntOOAajajEucrw4XYNSaoi5rgoqksgxQ3g388Vof4QzUNwdQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "1.1.0", - "Microsoft.Extensions.Logging": "2.1.1" - } - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", - "dependencies": { - "Microsoft.Extensions.Configuration": "2.1.1" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==" - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "2.1.1", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Logging.Abstractions": "2.1.1", - "Microsoft.Extensions.Options": "2.1.1" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==" - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Primitives": "2.1.1" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", - "dependencies": { - "System.Memory": "4.5.1", - "System.Runtime.CompilerServices.Unsafe": "4.5.1" - } - }, "Microsoft.NETCore.Platforms": { "type": "Transitive", "resolved": "1.1.0", "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", - "dependencies": { - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.4.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.2", - "contentHash": "BG/TNxDFv0svAzx8OiMXDlsHfGw623BZ8tCXw4YLhDFDvDhNUEV58jKYMGRnkbJNm7c3JNNJDiN7JBMzxRBR2w==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.2" - } } } } diff --git a/third_party/RemoteNET/src/ScubaDiver/Properties/AssemblyInfo.cs b/third_party/RemoteNET/src/ScubaDiver/Properties/AssemblyInfo.cs deleted file mode 100644 index c0659f11..00000000 --- a/third_party/RemoteNET/src/ScubaDiver/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ScubaDiver")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ScubaDiver")] -[assembly: AssemblyCopyright("Copyright © 2021")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("8df5d538-941d-44e8-803e-9e135926ebe8")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj b/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj index e7646bed..5b5edd23 100644 --- a/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj +++ b/third_party/RemoteNET/src/ScubaDiver/ScubaDiver.csproj @@ -5,7 +5,6 @@ Latest Library ScubaDiver - Properties false @@ -27,8 +26,8 @@ + - @@ -46,30 +45,22 @@ - + + + + + + + + + + @(Assemblies-> '%(Filename)%(Extension)', ' ') + @(Flags-> '%(Identity)', ' ') + $(ILMergeConsolePath) $(ILMergeAssemblies) $(ILMergeFlags) + + + diff --git a/third_party/RemoteNET/src/ScubaDiver/packages.lock.json b/third_party/RemoteNET/src/ScubaDiver/packages.lock.json index 96d8db35..4e7f2407 100644 --- a/third_party/RemoteNET/src/ScubaDiver/packages.lock.json +++ b/third_party/RemoteNET/src/ScubaDiver/packages.lock.json @@ -34,6 +34,29 @@ "resolved": "6.0.0", "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, + "Dynamitey": { + "type": "Transitive", + "resolved": "3.0.3", + "contentHash": "ocF4rRKgnmBkblk8RrgRP9YxxeJBvoaoCNLXgmUMgQCjZRw2v6Rtqxt5Kni6/TtbvICeWVN9X/69G5jltUEnbQ==" + }, + "ImpromptuInterface": { + "type": "Transitive", + "resolved": "8.0.4", + "contentHash": "acQoJpopRKHw66kporxut6/ucEiSajaxQoAsz0xD/BbVbxYtW3LMC31tHSgTmTMbhtmYp+sEq6zpH65gJGh+3Q==", + "dependencies": { + "Dynamitey": "3.0.3" + } + }, + "Meziantou.Polyfill": { + "type": "Transitive", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, "Microsoft.Diagnostics.NETCore.Client": { "type": "Transitive", "resolved": "0.2.410101", @@ -148,15 +171,19 @@ "System.Runtime.CompilerServices.Unsafe": "4.5.3" } }, - "mtgosdk.win32": { - "type": "Project" - }, - "scubadiver.api": { + "mtgosdk": { "type": "Project", "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", + "ImpromptuInterface": "[8.0.4, )", + "MTGOSDK.Win32": "[1.0.0, )", + "Meziantou.Polyfill": "[1.0.37, )", + "Microsoft.CSharp": "[4.7.0, )", + "Microsoft.Diagnostics.Runtime": "[3.1.512801, )", "Newtonsoft.Json": "[13.0.3, )" } + }, + "mtgosdk.win32": { + "type": "Project" } } } From e72f273506a0680c9577071320f5bfe6cdf68208 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 12:45:06 -0500 Subject: [PATCH 03/20] Remove old projects, simplify MSBuild pipeline --- Directory.Build.props | 7 ++- Directory.Build.targets | 2 +- MTGOSDK/MTGOSDK.csproj | 2 +- SDK.sln | 36 +------------- examples/BasicBot/packages.lock.json | 47 ++++++------------- examples/BasicInjector/packages.lock.json | 47 ++++++------------- examples/GameTracker/packages.lock.json | 47 ++++++------------- .../RemoteNET/src/RemoteNET/RemoteNET.csproj | 12 ----- .../src/RemoteNET/packages.lock.json | 21 --------- .../src/ScubaDiver.API/ScubaDiver.API.csproj | 12 ----- .../src/ScubaDiver.API/packages.lock.json | 21 --------- .../RemoteNET/src/ScubaDiver/DllEntry.cs | 6 +-- 12 files changed, 53 insertions(+), 207 deletions(-) delete mode 100644 third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj delete mode 100644 third_party/RemoteNET/src/RemoteNET/packages.lock.json delete mode 100644 third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj delete mode 100644 third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json diff --git a/Directory.Build.props b/Directory.Build.props index 2d2525ca..5ee0b451 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,12 +2,15 @@ + $(MSBuildThisFileDirectory) $(SolutionDir)\dist + + $([MSBuild]::NormalizeDirectory($(AppData)\..\Local)) - $([MSBuild]::NormalizeDirectory($(AppData)\..\Local)) + true - + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets index 8241c03b..d2ca2a0a 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -16,4 +16,4 @@ --> - + \ No newline at end of file diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 1fa2ea99..1da9b14c 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -37,7 +37,7 @@ + Private="false" /> diff --git a/SDK.sln b/SDK.sln index 0d563230..ce4e0473 100644 --- a/SDK.sln +++ b/SDK.sln @@ -10,29 +10,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameTracker", "examples\Gam EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTGOSDK", "MTGOSDK\MTGOSDK.csproj", "{ABBC9015-9107-45AE-BBA3-7F73F62674D4}" EndProject - ProjectSection(ProjectDependencies) = postProject - {0DE6081F-5E88-4B34-8CAB-4035DCAA30EB} = {0DE6081F-5E88-4B34-8CAB-4035DCAA30EB} - {44F6A719-BFA6-4529-9675-D98FAF6132F5} = {44F6A719-BFA6-4529-9675-D98FAF6132F5} - {C6812753-F249-45AC-99EE-2A9F06E386E4} = {C6812753-F249-45AC-99EE-2A9F06E386E4} - EndProjectSection Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTGOSDK.MSBuild", "MTGOSDK.MSBuild\MTGOSDK.MSBuild.csproj", "{44F6A719-BFA6-4529-9675-D98FAF6132F5}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTGOSDK.Ref", "MTGOSDK.Ref\MTGOSDK.Ref.csproj", "{C6812753-F249-45AC-99EE-2A9F06E386E4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTGOSDK.Win32", "MTGOSDK.Win32\MTGOSDK.Win32.csproj", "{0DE6081F-5E88-4B34-8CAB-4035DCAA30EB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RemoteNET", "third_party\RemoteNET\src\RemoteNET\RemoteNET.csproj", "{D1ACBDEC-184B-4F5B-85CD-E02B5F712121}" - ProjectSection(ProjectDependencies) = postProject - {E9771628-EF64-4DD8-9906-E7B1990A0FB9} = {E9771628-EF64-4DD8-9906-E7B1990A0FB9} - {8DF5D538-941D-44E8-803E-9E135926EBE8} = {8DF5D538-941D-44E8-803E-9E135926EBE8} - {71033F61-0D65-468E-81E7-A5765BCF9282} = {71033F61-0D65-468E-81E7-A5765BCF9282} - {5DE7F97C-B97B-489F-A1E4-9F9656317F94} = {5DE7F97C-B97B-489F-A1E4-9F9656317F94} - {0C3EB2F7-92BA-4895-99FC-7098A16FFE8C} = {0C3EB2F7-92BA-4895-99FC-7098A16FFE8C} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScubaDiver", "third_party\RemoteNET\src\ScubaDiver\ScubaDiver.csproj", "{8DF5D538-941D-44E8-803E-9E135926EBE8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScubaDiver.API", "third_party\RemoteNET\src\ScubaDiver.API\ScubaDiver.API.csproj", "{0FE20420-27E2-467F-AB2D-78B6A795B255}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScubaDiver", "third_party\RemoteNET\src\ScubaDiver\ScubaDiver.csproj", "{8DF5D538-941D-44E8-803E-9E135926EBE8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bootstrapper", "third_party\SharpNeedle\src\Bootstrapper\Bootstrapper.vcxproj", "{5DE7F97C-B97B-489F-A1E4-9F9656317F94}" EndProject @@ -110,14 +94,6 @@ Global {0DE6081F-5E88-4B34-8CAB-4035DCAA30EB}.Release|Any CPU.Build.0 = Release|Any CPU {0DE6081F-5E88-4B34-8CAB-4035DCAA30EB}.Release|Mixed.ActiveCfg = Release|Any CPU {0DE6081F-5E88-4B34-8CAB-4035DCAA30EB}.Release|Mixed.Build.0 = Release|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Debug|Mixed.ActiveCfg = Debug|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Debug|Mixed.Build.0 = Debug|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Release|Any CPU.Build.0 = Release|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Release|Mixed.ActiveCfg = Release|Any CPU - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121}.Release|Mixed.Build.0 = Release|Any CPU {8DF5D538-941D-44E8-803E-9E135926EBE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8DF5D538-941D-44E8-803E-9E135926EBE8}.Debug|Any CPU.Build.0 = Debug|Any CPU {8DF5D538-941D-44E8-803E-9E135926EBE8}.Debug|Mixed.ActiveCfg = Debug|Any CPU @@ -126,14 +102,6 @@ Global {8DF5D538-941D-44E8-803E-9E135926EBE8}.Release|Any CPU.Build.0 = Release|Any CPU {8DF5D538-941D-44E8-803E-9E135926EBE8}.Release|Mixed.ActiveCfg = Release|Any CPU {8DF5D538-941D-44E8-803E-9E135926EBE8}.Release|Mixed.Build.0 = Release|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Debug|Mixed.ActiveCfg = Debug|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Debug|Mixed.Build.0 = Debug|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Release|Any CPU.Build.0 = Release|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Release|Mixed.ActiveCfg = Release|Any CPU - {0FE20420-27E2-467F-AB2D-78B6A795B255}.Release|Mixed.Build.0 = Release|Any CPU {5DE7F97C-B97B-489F-A1E4-9F9656317F94}.Debug|Any CPU.ActiveCfg = Debug|Win32 {5DE7F97C-B97B-489F-A1E4-9F9656317F94}.Debug|Any CPU.Build.0 = Debug|Win32 {5DE7F97C-B97B-489F-A1E4-9F9656317F94}.Debug|Mixed.ActiveCfg = Debug|Win32 @@ -174,9 +142,7 @@ Global {55881B74-5ADF-4633-B46D-01F0C60FE877} = {1B98C787-C0E6-479D-B577-5EAD610B1DFA} {65BCE52F-3A67-4B94-96D3-917D4E577D8C} = {1B98C787-C0E6-479D-B577-5EAD610B1DFA} {566C0ACC-27A7-4398-9E82-CB1E7594B1E0} = {1B98C787-C0E6-479D-B577-5EAD610B1DFA} - {D1ACBDEC-184B-4F5B-85CD-E02B5F712121} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} {8DF5D538-941D-44E8-803E-9E135926EBE8} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} - {0FE20420-27E2-467F-AB2D-78B6A795B255} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} {5DE7F97C-B97B-489F-A1E4-9F9656317F94} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} {E9771628-EF64-4DD8-9906-E7B1990A0FB9} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} {0C3EB2F7-92BA-4895-99FC-7098A16FFE8C} = {EF3E9033-3E13-44FE-851E-418B0CF61FE4} diff --git a/examples/BasicBot/packages.lock.json b/examples/BasicBot/packages.lock.json index fd1a99c0..f3d53018 100644 --- a/examples/BasicBot/packages.lock.json +++ b/examples/BasicBot/packages.lock.json @@ -21,6 +21,11 @@ "System.Reflection.Emit": "4.7.0" } }, + "Meziantou.Polyfill": { + "type": "Transitive", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.0", @@ -42,12 +47,10 @@ }, "Microsoft.Diagnostics.Runtime": { "type": "Transitive", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "Microsoft.Diagnostics.NETCore.Client": "0.2.410101" } }, "Microsoft.Extensions.Configuration": { @@ -128,14 +131,6 @@ "resolved": "13.0.3", "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, "System.ComponentModel": { "type": "Transitive", "resolved": "4.3.0", @@ -165,36 +160,22 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + "resolved": "4.5.1", + "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw==" }, "mtgosdk": { "type": "Project", "dependencies": { "ImpromptuInterface": "[8.0.4, )", "MTGOSDK.Win32": "[1.0.0, )", - "Newtonsoft.Json": "[13.0.3, )", - "RemoteNET": "[1.0.0, )", - "ScubaDiver.API": "[1.0.0, )" + "Meziantou.Polyfill": "[1.0.37, )", + "Microsoft.CSharp": "[4.7.0, )", + "Microsoft.Diagnostics.Runtime": "[3.1.512801, )", + "Newtonsoft.Json": "[13.0.3, )" } }, "mtgosdk.win32": { "type": "Project" - }, - "remotenet": { - "type": "Project", - "dependencies": { - "MTGOSDK.Win32": "[1.0.0, )", - "Microsoft.CSharp": "[4.7.0, )", - "ScubaDiver.API": "[1.0.0, )" - } - }, - "scubadiver.api": { - "type": "Project", - "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", - "Newtonsoft.Json": "[13.0.3, )" - } } } } diff --git a/examples/BasicInjector/packages.lock.json b/examples/BasicInjector/packages.lock.json index fd1a99c0..f3d53018 100644 --- a/examples/BasicInjector/packages.lock.json +++ b/examples/BasicInjector/packages.lock.json @@ -21,6 +21,11 @@ "System.Reflection.Emit": "4.7.0" } }, + "Meziantou.Polyfill": { + "type": "Transitive", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.0", @@ -42,12 +47,10 @@ }, "Microsoft.Diagnostics.Runtime": { "type": "Transitive", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "Microsoft.Diagnostics.NETCore.Client": "0.2.410101" } }, "Microsoft.Extensions.Configuration": { @@ -128,14 +131,6 @@ "resolved": "13.0.3", "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, "System.ComponentModel": { "type": "Transitive", "resolved": "4.3.0", @@ -165,36 +160,22 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + "resolved": "4.5.1", + "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw==" }, "mtgosdk": { "type": "Project", "dependencies": { "ImpromptuInterface": "[8.0.4, )", "MTGOSDK.Win32": "[1.0.0, )", - "Newtonsoft.Json": "[13.0.3, )", - "RemoteNET": "[1.0.0, )", - "ScubaDiver.API": "[1.0.0, )" + "Meziantou.Polyfill": "[1.0.37, )", + "Microsoft.CSharp": "[4.7.0, )", + "Microsoft.Diagnostics.Runtime": "[3.1.512801, )", + "Newtonsoft.Json": "[13.0.3, )" } }, "mtgosdk.win32": { "type": "Project" - }, - "remotenet": { - "type": "Project", - "dependencies": { - "MTGOSDK.Win32": "[1.0.0, )", - "Microsoft.CSharp": "[4.7.0, )", - "ScubaDiver.API": "[1.0.0, )" - } - }, - "scubadiver.api": { - "type": "Project", - "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", - "Newtonsoft.Json": "[13.0.3, )" - } } } } diff --git a/examples/GameTracker/packages.lock.json b/examples/GameTracker/packages.lock.json index fd1a99c0..f3d53018 100644 --- a/examples/GameTracker/packages.lock.json +++ b/examples/GameTracker/packages.lock.json @@ -21,6 +21,11 @@ "System.Reflection.Emit": "4.7.0" } }, + "Meziantou.Polyfill": { + "type": "Transitive", + "resolved": "1.0.37", + "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "1.1.0", @@ -42,12 +47,10 @@ }, "Microsoft.Diagnostics.Runtime": { "type": "Transitive", - "resolved": "3.0.442202", - "contentHash": "lLKVmm5EsxtEYuPivwMNsS+EtNqWPO9kPs99kFGeGN/XH3brzrmyoN5YX8Adwcpzom4OUk5AifKn1K3Eo2EGWQ==", + "resolved": "3.1.512801", + "contentHash": "0lMUDr2oxNZa28D6NH5BuSQEe5T9tZziIkvkD44YkkCGQXPJqvFjLq5ZQq1hYLl3RjQJrY+hR0jFgap+EWPDTw==", "dependencies": { - "Microsoft.Diagnostics.NETCore.Client": "0.2.410101", - "System.Collections.Immutable": "6.0.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "Microsoft.Diagnostics.NETCore.Client": "0.2.410101" } }, "Microsoft.Extensions.Configuration": { @@ -128,14 +131,6 @@ "resolved": "13.0.3", "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, "System.ComponentModel": { "type": "Transitive", "resolved": "4.3.0", @@ -165,36 +160,22 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + "resolved": "4.5.1", + "contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw==" }, "mtgosdk": { "type": "Project", "dependencies": { "ImpromptuInterface": "[8.0.4, )", "MTGOSDK.Win32": "[1.0.0, )", - "Newtonsoft.Json": "[13.0.3, )", - "RemoteNET": "[1.0.0, )", - "ScubaDiver.API": "[1.0.0, )" + "Meziantou.Polyfill": "[1.0.37, )", + "Microsoft.CSharp": "[4.7.0, )", + "Microsoft.Diagnostics.Runtime": "[3.1.512801, )", + "Newtonsoft.Json": "[13.0.3, )" } }, "mtgosdk.win32": { "type": "Project" - }, - "remotenet": { - "type": "Project", - "dependencies": { - "MTGOSDK.Win32": "[1.0.0, )", - "Microsoft.CSharp": "[4.7.0, )", - "ScubaDiver.API": "[1.0.0, )" - } - }, - "scubadiver.api": { - "type": "Project", - "dependencies": { - "Microsoft.Diagnostics.Runtime": "[3.0.442202, )", - "Newtonsoft.Json": "[13.0.3, )" - } } } } diff --git a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj b/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj deleted file mode 100644 index c80659b3..00000000 --- a/third_party/RemoteNET/src/RemoteNET/RemoteNET.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - netstandard2.0 - Latest - - - - - - - \ No newline at end of file diff --git a/third_party/RemoteNET/src/RemoteNET/packages.lock.json b/third_party/RemoteNET/src/RemoteNET/packages.lock.json deleted file mode 100644 index b7e843ee..00000000 --- a/third_party/RemoteNET/src/RemoteNET/packages.lock.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": 1, - "dependencies": { - ".NETStandard,Version=v2.0": { - "NETStandard.Library": { - "type": "Direct", - "requested": "[2.0.3, )", - "resolved": "2.0.3", - "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - } - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - } - } - } -} \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj b/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj deleted file mode 100644 index a805b0ef..00000000 --- a/third_party/RemoteNET/src/ScubaDiver.API/ScubaDiver.API.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - netstandard2.0 - latest - - - - - - - \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json b/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json deleted file mode 100644 index b7e843ee..00000000 --- a/third_party/RemoteNET/src/ScubaDiver.API/packages.lock.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": 1, - "dependencies": { - ".NETStandard,Version=v2.0": { - "NETStandard.Library": { - "type": "Direct", - "requested": "[2.0.3, )", - "resolved": "2.0.3", - "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - } - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - } - } - } -} \ No newline at end of file diff --git a/third_party/RemoteNET/src/ScubaDiver/DllEntry.cs b/third_party/RemoteNET/src/ScubaDiver/DllEntry.cs index 064da0b3..e1e8bb8a 100644 --- a/third_party/RemoteNET/src/ScubaDiver/DllEntry.cs +++ b/third_party/RemoteNET/src/ScubaDiver/DllEntry.cs @@ -15,14 +15,14 @@ public static void DiverHost(object pwzArgument) _instance.Start(port); // Diver killed (politely) - Logger.Debug("[DiverHost] Diver finished gracefully, returning"); + Logger.Debug("[DiverHost] Diver finished gracefully."); } catch (Exception e) { Logger.Debug("[DiverHost] ScubaDiver crashed."); Logger.Debug(e.ToString()); - Logger.Debug("[DiverHost] Exiting entry point in 60 secs..."); - Thread.Sleep(TimeSpan.FromSeconds(60)); + Logger.Debug("[DiverHost] Exiting entry point in 10 seconds."); + Thread.Sleep(TimeSpan.FromSeconds(10)); } } From be4b5f63b9da21d284a43252892bf77166f8d23f Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 12:49:32 -0500 Subject: [PATCH 04/20] [MTGOSDK.MSBuild] Indicate whether Ref assembly generation was skipped --- MTGOSDK.MSBuild/build/MTGOSDK.MSBuild.targets | 13 ++++++++----- .../src/Tasks/ExtractMTGOInstallation.cs | 4 ++-- .../src/Tasks/GenerateReferenceAssemblies.cs | 11 +++++++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/MTGOSDK.MSBuild/build/MTGOSDK.MSBuild.targets b/MTGOSDK.MSBuild/build/MTGOSDK.MSBuild.targets index 691f25bd..806a8679 100644 --- a/MTGOSDK.MSBuild/build/MTGOSDK.MSBuild.targets +++ b/MTGOSDK.MSBuild/build/MTGOSDK.MSBuild.targets @@ -39,9 +39,6 @@ - - + + Importance="high" + Condition="'$(HasSkipped)' != 'true'" /> + Importance="high" + Condition="'$(HasSkipped)' != 'true'" /> \ No newline at end of file diff --git a/MTGOSDK.MSBuild/src/Tasks/ExtractMTGOInstallation.cs b/MTGOSDK.MSBuild/src/Tasks/ExtractMTGOInstallation.cs index 6de98d82..8fbc2fd3 100644 --- a/MTGOSDK.MSBuild/src/Tasks/ExtractMTGOInstallation.cs +++ b/MTGOSDK.MSBuild/src/Tasks/ExtractMTGOInstallation.cs @@ -20,14 +20,14 @@ namespace MTGOSDK.MSBuild.Tasks; public class ExtractMTGOInstallation : Task { /// - /// The path to the MTGO application directory. + /// The path to the MTGO application directory. /// [Required] [Output] public string MTGOAppDir { get; set; } = string.Empty; /// - /// The path to the MTGO user data directory. + /// The path to the MTGO user data directory. /// [Output] public string MTGODataDir { get; set; } = string.Empty; diff --git a/MTGOSDK.MSBuild/src/Tasks/GenerateReferenceAssemblies.cs b/MTGOSDK.MSBuild/src/Tasks/GenerateReferenceAssemblies.cs index 35de2ff1..1dcb4db3 100644 --- a/MTGOSDK.MSBuild/src/Tasks/GenerateReferenceAssemblies.cs +++ b/MTGOSDK.MSBuild/src/Tasks/GenerateReferenceAssemblies.cs @@ -17,7 +17,7 @@ namespace MTGOSDK.MSBuild.Tasks; public class GenerateReferenceAssemblies : Task { /// - /// The path to the MTGO application directory. + /// The path to the MTGO application directory. /// [Required] public string MTGOAppDir { get; set; } = string.Empty; @@ -28,10 +28,15 @@ public class GenerateReferenceAssemblies : Task [Required] public string Version { get; set; } = string.Empty; + /// + /// Whether the task has been skipped. + /// + [Output] + public bool HasSkipped { get; set; } = false; + /// /// The path to store the generated reference assemblies. /// - /// [Required] [Output] public string OutputPath { get; set; } = string.Empty; @@ -45,7 +50,9 @@ public override bool Execute() Log.LogMessage(MessageImportance.High, $"MTGOSDK.MSBuild: Reference assemblies for version {Version} already exist."); + HasSkipped = true; OutputPath = versionPath; + return true; } // Clear out previous versions' reference assemblies From ee5d56ca57bd355451da185c06b5a390ae6204bb Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 12:49:53 -0500 Subject: [PATCH 05/20] CI: (Testing) Show detailed NuGet restore --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f5f97c2..923954bf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,8 @@ env: MSBUILD_DEFAULTS: /m:2 /v:m /p:Configuration=Release /p:Platform="Any CPU" NUGET_CACHES: | ~/.nuget/packages - NUGET_DEFAULTS: -Verbosity quiet -NonInteractive -UseLockFile + # NUGET_DEFAULTS: -Verbosity quiet -NonInteractive -UseLockFile + NUGET_DEFAULTS: -Verbosity detailed -NonInteractive -UseLockFile jobs: # Runs test suite build: From 10adb9b46b4ad71239573df82b4ccb0b5c9dccf3 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 15:20:41 -0500 Subject: [PATCH 06/20] [MTGOSDK] Evaluate resource projects dynamically --- MTGOSDK/MTGOSDK.csproj | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 1da9b14c..fe78dcaf 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -31,19 +31,24 @@ - - - - - - + + + + + + + + From fb53e5cd76520c1b99632e2088ef946c3c8cc6ec Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 15:34:13 -0500 Subject: [PATCH 07/20] Revert CI logging verbosity, add resource embedding logging --- .github/workflows/build.yml | 3 +-- MTGOSDK/MTGOSDK.csproj | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 923954bf..6f5f97c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,8 +27,7 @@ env: MSBUILD_DEFAULTS: /m:2 /v:m /p:Configuration=Release /p:Platform="Any CPU" NUGET_CACHES: | ~/.nuget/packages - # NUGET_DEFAULTS: -Verbosity quiet -NonInteractive -UseLockFile - NUGET_DEFAULTS: -Verbosity detailed -NonInteractive -UseLockFile + NUGET_DEFAULTS: -Verbosity quiet -NonInteractive -UseLockFile jobs: # Runs test suite build: diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index fe78dcaf..872b44f3 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -42,6 +42,8 @@ ReferenceOutputAssembly="false" Private="false" /> + @@ -59,6 +61,8 @@ + From b4c42a8564c70966bb9541491a3da083bbfb4578 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 15:56:20 -0500 Subject: [PATCH 08/20] [MTGOSDK.Core.Remoting.Interop] Migrate ScubaDiver.API to Remoting namespace --- MTGOSDK/src/Core/Reflection/RemoteProxy.cs | 2 +- MTGOSDK/src/Core/RemoteClient.cs | 2 +- MTGOSDK/src/Core/Remoting/Bootstrapper.cs | 2 +- MTGOSDK/src/Core/Remoting/CandidateObject.cs | 2 +- MTGOSDK/src/Core/Remoting/CandidateType.cs | 2 +- .../Core/Remoting/Internal/DiverDiscovery.cs | 4 +- .../Internal/DynamicRemoteEnumerator.cs | 2 +- .../Remoting/Internal/DynamicRemoteObject.cs | 15 +- .../Internal/DynamicRemoteObjectFactory.cs | 4 +- .../ProxiedReflection/IProxiedMember.cs | 2 +- .../ProxiedReflection/ProxiedEventInfo.cs | 2 +- .../ProxiedReflection/ProxiedMemberType.cs | 2 +- .../ProxiedReflection/ProxiedMethodGroup.cs | 4 +- .../ProxiedMethodOverload.cs | 4 +- .../ProxiedValueMemberInfo.cs | 2 +- .../Internal/Reflection/DummyGenericType.cs | 2 +- .../Internal/Reflection/DynamicRemoteEnum.cs | 2 +- .../Reflection/LazyRemoteTypeResolver.cs | 2 +- .../Reflection/RemoteConstructorInfo.cs | 2 +- .../Internal/Reflection/RemoteEnum.cs | 2 +- .../Internal/Reflection/RemoteEventInfo.cs | 2 +- .../Internal/Reflection/RemoteFieldInfo.cs | 6 +- .../Reflection/RemoteFunctionsInvokeHelper.cs | 8 +- .../Internal/Reflection/RemoteMethodInfo.cs | 2 +- .../Reflection/RemoteParameterInfo.cs | 2 +- .../Internal/Reflection/RemotePropertyInfo.cs | 2 +- .../Internal/Reflection/RemoteType.cs | 2 +- .../Internal/Reflection/RemoteTypesFactory.cs | 6 +- .../Internal/Reflection/TypesResolver.cs | 2 +- .../Core/Remoting/Internal/RemoteObjectRef.cs | 8 +- .../Internal/Utils/MethodBaseExtensions.cs | 2 +- .../Remoting/Interop/CallbacksListener.cs | 352 +++++++++--------- .../Remoting/Interop/DiverCommunicator.cs | 23 +- .../Interop/Exceptions/RemoteException.cs | 54 +-- .../Exceptions/RemoteObjectMovedException.cs | 23 +- .../Remoting/Interop/Extensions/IntPtrExt.cs | 32 +- .../Interop/Extensions/WildCardType.cs | 343 +++++++++-------- .../Callbacks/CallbackInvocationRequest.cs | 26 +- .../Callbacks/EventRegistrationResults.cs | 18 +- .../Client/UnregisterClientResponse.cs | 24 +- .../Interop/Interactions/DiverError.cs | 25 +- .../Interop/Interactions/Dumps/DomainsDump.cs | 25 +- .../Interop/Interactions/Dumps/HeapDump.cs | 29 +- .../Interop/Interactions/Dumps/MemberDump.cs | 9 +- .../Interop/Interactions/Dumps/ObjectDump.cs | 61 ++- .../Interop/Interactions/Dumps/ObjectType.cs | 16 + .../Interop/Interactions/Dumps/TypeDump.cs | 315 ++++++++-------- .../Interactions/Dumps/TypeDumpRequest.cs | 18 +- .../Interop/Interactions/Dumps/TypesDump.cs | 23 +- .../Interop/Interactions/InvocationRequest.cs | 31 +- .../Interop/Interactions/InvocationResults.cs | 18 +- .../Object/CtorInvocationRequest.cs | 24 +- .../Interactions/Object/FieldGetRequest.cs | 22 +- .../Interactions/Object/FieldSetRequest.cs | 22 +- .../Object/IndexedItemAccessRequest.cs | 20 +- .../Remoting/Interop/ObjectOrRemoteAddress.cs | 12 +- .../Remoting/Interop/ReverseCommunicator.cs | 17 +- .../src/Core/Remoting/Interop/Utils/Filter.cs | 69 ++-- .../Remoting/Interop/Utils/NewtonsoftProxy.cs | 131 +++---- .../Interop/Utils/PrimitivesEncoder.cs | 274 +++++++------- .../Core/Remoting/Interop/Utils/TypeExt.cs | 291 ++++++++------- MTGOSDK/src/Core/Remoting/Logger.cs | 3 +- MTGOSDK/src/Core/Remoting/RemoteActivator.cs | 8 +- MTGOSDK/src/Core/Remoting/RemoteApp.cs | 12 +- MTGOSDK/src/Core/Remoting/RemoteObject.cs | 10 +- examples/BasicInjector/Program.cs | 2 +- third_party/RemoteNET/src/ScubaDiver/Diver.cs | 18 +- .../src/ScubaDiver/Utils/Converter.cs | 14 +- .../src/ScubaDiver/Utils/ObjectDumpFactory.cs | 6 +- 69 files changed, 1347 insertions(+), 1176 deletions(-) create mode 100644 MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectType.cs diff --git a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs index 3266e217..fba2f213 100644 --- a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs +++ b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs @@ -3,7 +3,7 @@ SPDX-License-Identifier: Apache-2.0 **/ -using RemoteNET.Internal; +using MTGOSDK.Core.Remoting.Internal; namespace MTGOSDK.Core.Reflection; diff --git a/MTGOSDK/src/Core/RemoteClient.cs b/MTGOSDK/src/Core/RemoteClient.cs index 0002735a..ff99df63 100644 --- a/MTGOSDK/src/Core/RemoteClient.cs +++ b/MTGOSDK/src/Core/RemoteClient.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; -using RemoteNET; +using MTGOSDK.Core.Remoting; using MTGOSDK.Core.Reflection; using MTGOSDK.Core.Exceptions; diff --git a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs index 9df5949d..6f51e9b2 100644 --- a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs +++ b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs @@ -12,7 +12,7 @@ using MTGOSDK.Win32.Extensions; -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; public static class Bootstrapper { diff --git a/MTGOSDK/src/Core/Remoting/CandidateObject.cs b/MTGOSDK/src/Core/Remoting/CandidateObject.cs index 083e9987..34e108b4 100644 --- a/MTGOSDK/src/Core/Remoting/CandidateObject.cs +++ b/MTGOSDK/src/Core/Remoting/CandidateObject.cs @@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; /// /// A candidate for a remote object. diff --git a/MTGOSDK/src/Core/Remoting/CandidateType.cs b/MTGOSDK/src/Core/Remoting/CandidateType.cs index cb5ca835..4ebf9716 100644 --- a/MTGOSDK/src/Core/Remoting/CandidateType.cs +++ b/MTGOSDK/src/Core/Remoting/CandidateType.cs @@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; public class CandidateType(string typeName, string assembly) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs b/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs index 730666fa..02fb4457 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DiverDiscovery.cs @@ -11,10 +11,10 @@ using MTGOSDK.Win32.Extensions; -using ScubaDiver.API; +using MTGOSDK.Core.Remoting.Interop; -namespace RemoteNET.Internal; +namespace MTGOSDK.Core.Remoting.Internal; public enum DiverState { diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs index aee01986..e22db88e 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteEnumerator.cs @@ -7,7 +7,7 @@ using System.Collections; -namespace RemoteNET.Internal; +namespace MTGOSDK.Core.Remoting.Internal; public class DynamicRemoteEnumerator(dynamic remoteEnumerator) : IEnumerator { diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs index 25d34958..b8684866 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs @@ -16,14 +16,15 @@ using Microsoft.CSharp.RuntimeBinder; using Binder = Microsoft.CSharp.RuntimeBinder.Binder; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Utils; -using RemoteNET.Internal.ProxiedReflection; -using RemoteNET.Internal.Reflection; -using RemoteNET.Internal.Utils; +using MTGOSDK.Core.Remoting.Internal.ProxiedReflection; +using MTGOSDK.Core.Remoting.Internal.Reflection; +using MTGOSDK.Core.Remoting.Internal.Utils; -namespace RemoteNET.Internal; +namespace MTGOSDK.Core.Remoting.Internal; /// /// A proxy of a remote object. @@ -544,8 +545,8 @@ public dynamic this[object key] get { - ScubaDiver.API.ObjectOrRemoteAddress ooraKey = RemoteFunctionsInvokeHelper.CreateRemoteParameter(key); - ScubaDiver.API.ObjectOrRemoteAddress item = __ro.GetItem(ooraKey); + ObjectOrRemoteAddress ooraKey = RemoteFunctionsInvokeHelper.CreateRemoteParameter(key); + ObjectOrRemoteAddress item = __ro.GetItem(ooraKey); if (item.IsNull) { return null; diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs index d695ce7d..1c01af57 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs @@ -4,10 +4,10 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -using ScubaDiver.API.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -namespace RemoteNET.Internal; +namespace MTGOSDK.Core.Remoting.Internal; public class DynamicRemoteObjectFactory { diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs index 169bdb0a..f0bf988f 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/IProxiedMember.cs @@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; public interface IProxiedMember { diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs index bb7bb8fe..94b58c33 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedEventInfo.cs @@ -10,7 +10,7 @@ using System.Reflection; -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; public class ProxiedEventInfo(RemoteObject ro, string name, List args) : IProxiedMember diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs index 0cc8708c..ead0b9e4 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMemberType.cs @@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; public enum ProxiedMemberType { diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs index 68c3e3d3..5055bf60 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodGroup.cs @@ -6,10 +6,10 @@ using System.Collections.Generic; -using RemoteNET.Internal.Reflection; +using MTGOSDK.Core.Remoting.Internal.Reflection; -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; public class ProxiedMethodGroup : List { } diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs index dece12e5..9351a639 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedMethodOverload.cs @@ -7,10 +7,10 @@ using System; using System.Collections.Generic; -using RemoteNET.Internal.Reflection; +using MTGOSDK.Core.Remoting.Internal.Reflection; -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; public class ProxiedMethodOverload { diff --git a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs index 4e49178a..43ed5bdc 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/ProxiedReflection/ProxiedValueMemberInfo.cs @@ -7,7 +7,7 @@ using System; -namespace RemoteNET.Internal.ProxiedReflection; +namespace MTGOSDK.Core.Remoting.Internal.ProxiedReflection; /// /// Info of proxied field or property diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs index 092d94fa..562b28ad 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DummyGenericType.cs @@ -9,7 +9,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class DummyGenericType(string name) : Type { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs index 1ef31da7..7a0c7aa0 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs @@ -7,7 +7,7 @@ using System.Dynamic; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class DynamicRemoteEnum(RemoteEnum remoteEnum) : DynamicObject { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs index b85362ea..0124cf57 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/LazyRemoteTypeResolver.cs @@ -7,7 +7,7 @@ using System; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class LazyRemoteTypeResolver { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs index d76cf6b0..7e6cc6dd 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs @@ -10,7 +10,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteConstructorInfo(Type declaringType, ParameterInfo[] paramInfos) : ConstructorInfo diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs index 45e0e14b..ec073e7f 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs @@ -4,7 +4,7 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteEnum(RemoteType remoteType) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs index 1623d6ce..d0c8e80f 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEventInfo.cs @@ -8,7 +8,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteEventInfo( RemoteType declaringType, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs index 062f372b..5cb2e43b 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs @@ -8,11 +8,11 @@ using System.Globalization; using System.Reflection; -using ScubaDiver.API; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Utils; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteFieldInfo( Type declaringType, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs index e7c53ea9..48a04375 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs @@ -7,12 +7,12 @@ using System; using System.Linq; -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Utils; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; /// /// In this context: "function" = Methods + Constructors. diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs index ad78a327..e5b81e9c 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs @@ -10,7 +10,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteMethodInfo( Type declaringType, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs index 15b2c75b..ab1d781e 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteParameterInfo.cs @@ -8,7 +8,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; /// /// A parameter of a remote method. The parameter's type itself might be a remote type (but can also be local) diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs index 44364111..264711b8 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs @@ -9,7 +9,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemotePropertyInfo(Type declaringType, Lazy propType, string name) : PropertyInfo { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs index 83217624..49921088 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs @@ -11,7 +11,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; internal class RemoteAssemblyDummy(string assemblyName) : Assembly { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs index 7025c9da..eca4bdbf 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs @@ -11,11 +11,11 @@ using System.Reflection; using System.Text.RegularExpressions; -using ScubaDiver.API; -using ScubaDiver.API.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteTypesFactory(TypesResolver resolver, DiverCommunicator communicator) diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs index 21536393..b0be05d1 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/TypesResolver.cs @@ -10,7 +10,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Reflection; +namespace MTGOSDK.Core.Remoting.Internal.Reflection; /// /// Resolves local and remote types. Contains a cache so the same TypeFullName diff --git a/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs b/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs index 544895cf..74723962 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/RemoteObjectRef.cs @@ -7,12 +7,12 @@ using System; using System.Linq; -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -namespace RemoteNET.Internal; +namespace MTGOSDK.Core.Remoting.Internal; internal class RemoteObjectRef( ObjectDump remoteObjectInfo, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs b/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs index 717b1a6c..9f61cf27 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Utils/MethodBaseExtensions.cs @@ -7,7 +7,7 @@ using System.Reflection; -namespace RemoteNET.Internal.Utils; +namespace MTGOSDK.Core.Remoting.Internal.Utils; public static class MethodBaseExtensions { diff --git a/MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs b/MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs index 51da9dff..315669ec 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/CallbacksListener.cs @@ -1,3 +1,9 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + using System; using System.Collections.Generic; using System.IO; @@ -6,235 +12,235 @@ using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Callbacks; -using ScubaDiver.API.Utils; -using static ScubaDiver.API.DiverCommunicator; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; +using MTGOSDK.Core.Remoting.Interop.Utils; +using static MTGOSDK.Core.Remoting.Interop.DiverCommunicator; + + +namespace MTGOSDK.Core.Remoting.Interop; -namespace ScubaDiver.API +/// +/// Listens for remote event callback invocations from the Diver +/// +public class CallbacksListener { - /// - /// Listens for remote event callback invocations from the Diver - /// - public class CallbacksListener - { - private HttpListener _listener = null; - Task _listenTask = null; - CancellationTokenSource _src = null; + private HttpListener _listener = null; + Task _listenTask = null; + CancellationTokenSource _src = null; - public IPAddress IP { get; set; } - public int Port { get; set; } - readonly object _withErrors = NewtonsoftProxy.JsonSerializerSettingsWithErrors; - private readonly Dictionary _tokensToEventHandlers = new(); - private readonly Dictionary _eventHandlersToToken = new(); + public IPAddress IP { get; set; } + public int Port { get; set; } + readonly object _withErrors = NewtonsoftProxy.JsonSerializerSettingsWithErrors; + private readonly Dictionary _tokensToEventHandlers = new(); + private readonly Dictionary _eventHandlersToToken = new(); - DiverCommunicator _communicator; + DiverCommunicator _communicator; - public CallbacksListener(DiverCommunicator communicator) + public CallbacksListener(DiverCommunicator communicator) + { + _communicator = communicator; + // Generate a random port with a temporary TcpListener + int GetRandomUnusedPort() { - _communicator = communicator; - // Generate a random port with a temporary TcpListener - int GetRandomUnusedPort() - { - var listener = new TcpListener(IPAddress.Any, 0); - listener.Start(); - var port = ((IPEndPoint)listener.LocalEndpoint).Port; - listener.Stop(); - return port; - } - - Port = GetRandomUnusedPort(); - IP = IPAddress.Parse("127.0.0.1"); + var listener = new TcpListener(IPAddress.Any, 0); + listener.Start(); + var port = ((IPEndPoint)listener.LocalEndpoint).Port; + listener.Stop(); + return port; } - public bool IsOpen { get; private set; } - public bool HasActiveCallbacks => _tokensToEventHandlers.Count > 0; + Port = GetRandomUnusedPort(); + IP = IPAddress.Parse("127.0.0.1"); + } - public void Open() + public bool IsOpen { get; private set; } + public bool HasActiveCallbacks => _tokensToEventHandlers.Count > 0; + + public void Open() + { + if (!IsOpen) { - if (!IsOpen) + // Need to create HTTP listener and send the Diver it's info + _listener = new HttpListener(); + string listeningUrl = $"http://{IP}:{Port}/"; + _listener.Prefixes.Add(listeningUrl); + _listener.Start(); + _src = new CancellationTokenSource(); + _listenTask = Task.Run(() => Dispatcher(_listener), _src.Token); + _listenTask = Task.Factory.StartNew(() => + Dispatcher(_listener), + _src.Token, + TaskCreationOptions.AttachedToParent, + TaskScheduler.Default); + IsOpen = true; + } + } + + public void Close() + { + if (IsOpen) + { + _src.Cancel(); + try { - // Need to create HTTP listener and send the Diver it's info - _listener = new HttpListener(); - string listeningUrl = $"http://{IP}:{Port}/"; - _listener.Prefixes.Add(listeningUrl); - _listener.Start(); - _src = new CancellationTokenSource(); - _listenTask = Task.Run(() => Dispatcher(_listener), _src.Token); - _listenTask = Task.Factory.StartNew(() => - Dispatcher(_listener), - _src.Token, - TaskCreationOptions.AttachedToParent, - TaskScheduler.Default); - IsOpen = true; + _listenTask.Wait(); } + catch { } + _listener.Close(); + _src = null; + _listener = null; + _listenTask = null; + + IsOpen = false; } + } - public void Close() + private void Dispatcher(HttpListener listener) + { + while (_src != null && !_src.IsCancellationRequested) { - if (IsOpen) + void ListenerCallback(IAsyncResult result) { - _src.Cancel(); + HttpListener listener = (HttpListener)result.AsyncState; + HttpListenerContext context; try { - _listenTask.Wait(); + context = listener.EndGetContext(result); + } + catch (ObjectDisposedException) + { + return; + } + catch (System.Net.HttpListenerException) + { + // Sometimes happen at teardown. Maybe there's a race condition here and waiting on something + // can prevent this but I don't really care + return; } - catch { } - _listener.Close(); - _src = null; - _listener = null; - _listenTask = null; - IsOpen = false; + try + { + HandleDispatchedRequest(context); + } + catch + { + } } - } + IAsyncResult asyncOperation = listener.BeginGetContext(ListenerCallback, listener); - private void Dispatcher(HttpListener listener) - { - while (_src != null && !_src.IsCancellationRequested) + while (true) { - void ListenerCallback(IAsyncResult result) + if (asyncOperation.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(100))) { - HttpListener listener = (HttpListener)result.AsyncState; - HttpListenerContext context; - try - { - context = listener.EndGetContext(result); - } - catch (ObjectDisposedException) - { - return; - } - catch (System.Net.HttpListenerException) - { - // Sometimes happen at teardown. Maybe there's a race condition here and waiting on something - // can prevent this but I don't really care - return; - } - - try - { - HandleDispatchedRequest(context); - } - catch - { - } + // Async operation started! We can move on to next request + break; } - IAsyncResult asyncOperation = listener.BeginGetContext(ListenerCallback, listener); - - while (true) + else { - if (asyncOperation.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(100))) + // Async event still awaiting new HTTP requests... It's a good time to check + // if we were signalled to die + if (_src.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(100))) { - // Async operation started! We can move on to next request + // Time to die. + // Leaving the inner loop will get us to the outter loop where _src is checked (again) + // and then it that loop will stop as well. break; } else { - // Async event still awaiting new HTTP requests... It's a good time to check - // if we were signalled to die - if (_src.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(100))) - { - // Time to die. - // Leaving the inner loop will get us to the outter loop where _src is checked (again) - // and then it that loop will stop as well. - break; - } - else - { - // No signal of die command. We can continue waiting - continue; - } + // No signal of die command. We can continue waiting + continue; } } } } + } - private void HandleDispatchedRequest(HttpListenerContext context) - { - HttpListenerRequest request = context.Request; + private void HandleDispatchedRequest(HttpListenerContext context) + { + HttpListenerRequest request = context.Request; - var response = context.Response; - string body = null; + var response = context.Response; + string body = null; + + if (request.Url.AbsolutePath == "/ping") + { + string pongRes = "{\"status\":\"pong\"}"; + byte[] pongResBytes = System.Text.Encoding.UTF8.GetBytes(pongRes); + // Get a response stream and write the response to it. + response.ContentLength64 = pongResBytes.Length; + response.ContentType = "application/json"; + Stream outputStream = response.OutputStream; + outputStream.Write(pongResBytes, 0, pongResBytes.Length); + // You must close the output stream. + outputStream.Close(); + return; + } - if (request.Url.AbsolutePath == "/ping") + if (request.Url.AbsolutePath == "/invoke_callback") + { + using (StreamReader sr = new(request.InputStream)) { - string pongRes = "{\"status\":\"pong\"}"; - byte[] pongResBytes = System.Text.Encoding.UTF8.GetBytes(pongRes); - // Get a response stream and write the response to it. - response.ContentLength64 = pongResBytes.Length; - response.ContentType = "application/json"; - Stream outputStream = response.OutputStream; - outputStream.Write(pongResBytes, 0, pongResBytes.Length); - // You must close the output stream. - outputStream.Close(); - return; + body = sr.ReadToEnd(); } - - if (request.Url.AbsolutePath == "/invoke_callback") + var res = JsonConvert.DeserializeObject(body, _withErrors); + if (_tokensToEventHandlers.TryGetValue(res.Token, out LocalEventCallback callbackFunction)) { - using (StreamReader sr = new(request.InputStream)) - { - body = sr.ReadToEnd(); - } - var res = JsonConvert.DeserializeObject(body, _withErrors); - if (_tokensToEventHandlers.TryGetValue(res.Token, out LocalEventCallback callbackFunction)) - { - (bool voidReturnType, ObjectOrRemoteAddress callbackRes) = callbackFunction(res.Parameters.ToArray()); - - InvocationResults ir = new() - { - VoidReturnType = voidReturnType, - ReturnedObjectOrAddress = voidReturnType ? null : callbackRes - }; + (bool voidReturnType, ObjectOrRemoteAddress callbackRes) = callbackFunction(res.Parameters.ToArray()); - body = JsonConvert.SerializeObject(ir); - } - else + InvocationResults ir = new() { - // TODO: I'm not sure the usage of 'DiverError' here is good. - // It's sent from the Communicator's side to the Diver's side... - DiverError errResults = new("Unknown Token", String.Empty); - body = JsonConvert.SerializeObject(errResults); - } + VoidReturnType = voidReturnType, + ReturnedObjectOrAddress = voidReturnType ? null : callbackRes + }; + + body = JsonConvert.SerializeObject(ir); } else { // TODO: I'm not sure the usage of 'DiverError' here is good. // It's sent from the Communicator's side to the Diver's side... - DiverError errResults = new("Unknown path in URL", String.Empty); + DiverError errResults = new("Unknown Token", String.Empty); body = JsonConvert.SerializeObject(errResults); } - - byte[] buffer = System.Text.Encoding.UTF8.GetBytes(body); - // Get a response stream and write the response to it. - response.ContentLength64 = buffer.Length; - response.ContentType = "application/json"; - Stream output = response.OutputStream; - output.Write(buffer, 0, buffer.Length); - // You must close the output stream. - output.Close(); } - - public void EventSubscribe(LocalEventCallback callback, int token) + else { - _tokensToEventHandlers[token] = callback; - _eventHandlersToToken[callback] = token; + // TODO: I'm not sure the usage of 'DiverError' here is good. + // It's sent from the Communicator's side to the Diver's side... + DiverError errResults = new("Unknown path in URL", String.Empty); + body = JsonConvert.SerializeObject(errResults); } - public int EventUnsubscribe(LocalEventCallback callback) + byte[] buffer = System.Text.Encoding.UTF8.GetBytes(body); + // Get a response stream and write the response to it. + response.ContentLength64 = buffer.Length; + response.ContentType = "application/json"; + Stream output = response.OutputStream; + output.Write(buffer, 0, buffer.Length); + // You must close the output stream. + output.Close(); + } + + public void EventSubscribe(LocalEventCallback callback, int token) + { + _tokensToEventHandlers[token] = callback; + _eventHandlersToToken[callback] = token; + } + + public int EventUnsubscribe(LocalEventCallback callback) + { + if (_eventHandlersToToken.TryGetValue(callback, out int token)) { - if (_eventHandlersToToken.TryGetValue(callback, out int token)) - { - _tokensToEventHandlers.Remove(token); - _eventHandlersToToken.Remove(callback); - return token; - } - else - { - throw new Exception($"[CallbackListener] EventUnsubscribe TryGetValue failed"); - } + _tokensToEventHandlers.Remove(token); + _eventHandlersToToken.Remove(callback); + return token; + } + else + { + throw new Exception($"[CallbackListener] EventUnsubscribe TryGetValue failed"); } } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs b/MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs index aff10bb7..36c87f37 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/DiverCommunicator.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; @@ -8,15 +14,16 @@ using System.Text; using System.Threading.Tasks; using System.Web; -using ScubaDiver.API.Exceptions; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Callbacks; -using ScubaDiver.API.Interactions.Dumps; -using ScubaDiver.API.Interactions.Object; -using ScubaDiver.API.Utils; + +using MTGOSDK.Core.Remoting.Interop.Exceptions; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop.Interactions.Object; +using MTGOSDK.Core.Remoting.Interop.Utils; -namespace ScubaDiver.API +namespace MTGOSDK.Core.Remoting.Interop { /// /// Communicates with a diver in a remote process diff --git a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs index 985bf2f1..0bdc9296 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs @@ -1,29 +1,35 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ -namespace ScubaDiver.API.Exceptions +using System; + + +namespace MTGOSDK.Core.Remoting.Interop.Exceptions; + +/// +/// Encapsulates an exception that was thrown in the remote object and catched by the Diver. +/// +public class RemoteException : Exception { - /// - /// Encapsulates an exception that was thrown in the remote object and catched by the Diver. - /// - public class RemoteException : Exception - { - public string RemoteMessage { get; private set; } - private string _remoteStackTrace; - public string RemoteStackTrace => _remoteStackTrace; - public override string StackTrace => - $"{_remoteStackTrace}\n" + - $"--- End of remote exception stack trace ---\n" + - $"{base.StackTrace}"; + public string RemoteMessage { get; private set; } + private string _remoteStackTrace; + public string RemoteStackTrace => _remoteStackTrace; + public override string StackTrace => + $"{_remoteStackTrace}\n" + + $"--- End of remote exception stack trace ---\n" + + $"{base.StackTrace}"; - public RemoteException(string msg, string remoteStackTrace) - { - RemoteMessage = msg; - _remoteStackTrace = remoteStackTrace; - } + public RemoteException(string msg, string remoteStackTrace) + { + RemoteMessage = msg; + _remoteStackTrace = remoteStackTrace; + } - public override string ToString() - { - return RemoteMessage; - } - } + public override string ToString() + { + return RemoteMessage; + } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs index d5bdf149..cbbb6fa6 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteObjectMovedException.cs @@ -1,13 +1,16 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ -namespace ScubaDiver.API.Exceptions +using System; + + +namespace MTGOSDK.Core.Remoting.Interop.Exceptions; + +internal class RemoteObjectMovedException(ulong testedAddress, + string msg) : Exception(msg) { - internal class RemoteObjectMovedException : Exception - { - public ulong TestedAddress { get; private set; } - public RemoteObjectMovedException(ulong testedAddress, string msg) : base(msg) - { - TestedAddress = testedAddress; - } - } + public ulong TestedAddress { get; private set; } = testedAddress; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs b/MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs index c698c90a..46d5b2c1 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Extensions/IntPtrExt.cs @@ -1,21 +1,27 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Runtime.InteropServices; -namespace ScubaDiver.API.Extensions + +namespace MTGOSDK.Core.Remoting.Interop.Extensions; + +public static class IntPtrExt { - public static class IntPtrExt + public static IntPtr GetMethodTable(this IntPtr o) { - public static IntPtr GetMethodTable(this IntPtr o) + try + { + IntPtr methodTable = Marshal.ReadIntPtr(o); + return methodTable; + } + catch (Exception e) { - try - { - IntPtr methodTable = Marshal.ReadIntPtr(o); - return methodTable; - } - catch (Exception e) - { - throw new AccessViolationException("Failed to read MethodTable at the object's address.", e); - } + throw new AccessViolationException("Failed to read MethodTable at the object's address.", e); } } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs b/MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs index d6a464bf..6fb6af2a 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Extensions/WildCardType.cs @@ -1,162 +1,189 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Globalization; using System.Reflection; -namespace ScubaDiver.API.Extensions + +namespace MTGOSDK.Core.Remoting.Interop.Extensions; + +/// +/// This fake type is used when the type of a parameter is unknown (if NULL was passed) +/// +public class WildCardType : Type { - /// - /// This fake type is used when the type of a parameter is unknown (if NULL was passed) - /// - public class WildCardType : Type - { - public override object[] GetCustomAttributes(bool inherit) - { - throw new NotImplementedException(); - } - - public override bool IsDefined(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - - public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetInterface(string name, bool ignoreCase) - { - throw new NotImplementedException(); - } - - public override Type[] GetInterfaces() - { - throw new NotImplementedException(); - } - - public override EventInfo GetEvent(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override EventInfo[] GetEvents(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type[] GetNestedTypes(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetNestedType(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override Type GetElementType() - { - throw new NotImplementedException(); - } - - protected override bool HasElementTypeImpl() - { - throw new NotImplementedException(); - } - - protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, - ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, - Type[] types, ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override MethodInfo[] GetMethods(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override FieldInfo GetField(string name, BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override FieldInfo[] GetFields(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - public override MemberInfo[] GetMembers(BindingFlags bindingAttr) - { - throw new NotImplementedException(); - } - - protected override TypeAttributes GetAttributeFlagsImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsArrayImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsByRefImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPointerImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsPrimitiveImpl() - { - throw new NotImplementedException(); - } - - protected override bool IsCOMObjectImpl() - { - throw new NotImplementedException(); - } - - public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, - ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) - { - throw new NotImplementedException(); - } - - public override Type UnderlyingSystemType { get; } - - protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, - Type[] types, ParameterModifier[] modifiers) - { - throw new NotImplementedException(); - } - - public override string Name { get; } - public override Guid GUID { get; } - public override Module Module { get; } - public override Assembly Assembly { get; } - public override string FullName { get; } - public override string Namespace { get; } - public override string AssemblyQualifiedName { get; } - public override Type BaseType { get; } - - public override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file + public override object[] GetCustomAttributes(bool inherit) + { + throw new NotImplementedException(); + } + + public override bool IsDefined(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } + + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetInterface(string name, bool ignoreCase) + { + throw new NotImplementedException(); + } + + public override Type[] GetInterfaces() + { + throw new NotImplementedException(); + } + + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override EventInfo[] GetEvents(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type[] GetNestedTypes(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetNestedType(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override Type GetElementType() + { + throw new NotImplementedException(); + } + + protected override bool HasElementTypeImpl() + { + throw new NotImplementedException(); + } + + protected override PropertyInfo GetPropertyImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + Type returnType, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + protected override MethodInfo GetMethodImpl( + string name, + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override FieldInfo GetField(string name, BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override FieldInfo[] GetFields(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + public override MemberInfo[] GetMembers(BindingFlags bindingAttr) + { + throw new NotImplementedException(); + } + + protected override TypeAttributes GetAttributeFlagsImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsArrayImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsByRefImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPointerImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsPrimitiveImpl() + { + throw new NotImplementedException(); + } + + protected override bool IsCOMObjectImpl() + { + throw new NotImplementedException(); + } + + public override object InvokeMember( + string name, + BindingFlags invokeAttr, + Binder binder, + object target, + object[] args, + ParameterModifier[] modifiers, + CultureInfo culture, + string[] namedParameters) + { + throw new NotImplementedException(); + } + + public override Type UnderlyingSystemType { get; } + + protected override ConstructorInfo GetConstructorImpl( + BindingFlags bindingAttr, + Binder binder, + CallingConventions callConvention, + Type[] types, + ParameterModifier[] modifiers) + { + throw new NotImplementedException(); + } + + public override string Name { get; } + public override Guid GUID { get; } + public override Module Module { get; } + public override Assembly Assembly { get; } + public override string FullName { get; } + public override string Namespace { get; } + public override string AssemblyQualifiedName { get; } + public override Type BaseType { get; } + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) + { + throw new NotImplementedException(); + } +} diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs index 4672f694..b76b89de 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs @@ -1,17 +1,17 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Callbacks -{ - public class CallbackInvocationRequest - { - public string StackTrace { get; set; } - public int Token { get; set; } - public List Parameters { get; set; } - public CallbackInvocationRequest() - { - Parameters = new(); - } - } +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; + +public class CallbackInvocationRequest() +{ + public string StackTrace { get; set; } + public int Token { get; set; } + public List Parameters { get; set; } = new(); } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs index 7fc410ab..3c85c04c 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/EventRegistrationResults.cs @@ -1,7 +1,13 @@ -namespace ScubaDiver.API.Interactions.Callbacks +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; + +public class EventRegistrationResults { - public class EventRegistrationResults - { - public int Token { get; set; } - } -} \ No newline at end of file + public int Token { get; set; } +} diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs index 5dc3f1d1..2664a35d 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs @@ -1,11 +1,17 @@ -namespace ScubaDiver.API.Interactions.Client +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Client; + +public class UnregisterClientResponse { - public class UnregisterClientResponse - { - public bool WasRemvoed { get; set; } - /// - /// Number of remaining clients, after the removal was done - /// - public int OtherClientsAmount { get; set; } - } + public bool WasRemoved { get; set; } + /// + /// Number of remaining clients, after the removal was done + /// + public int OtherClientsAmount { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs index 609ed3ef..e6c73d1d 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/DiverError.cs @@ -1,15 +1,14 @@ -namespace ScubaDiver.API.Interactions -{ - public class DiverError - { - public string Error { get; set; } - public string StackTrace { get; set; } +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + - public DiverError() {} - public DiverError(string err, string stackTrace) - { - Error = err; - StackTrace = stackTrace; - } - } +namespace MTGOSDK.Core.Remoting.Interop.Interactions; + +public class DiverError(string err, string stackTrace) +{ + public string Error { get; set; } = err; + public string StackTrace { get; set; } = stackTrace; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs index 3e24545e..0c72b751 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs @@ -1,16 +1,21 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Dumps + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +public class DomainsDump { - public class DomainsDump + public class AvailableDomain { - public class AvailableDomain - { - public string Name { get; set; } - public List AvailableModules { get; set; } - } - public string Current { get; set; } - public List AvailableDomains { get; set; } + public string Name { get; set; } + public List AvailableModules { get; set; } } + public string Current { get; set; } + public List AvailableDomains { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs index 08831c4e..26ca40a9 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs @@ -1,18 +1,23 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Dumps + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +public class HeapDump { - public class HeapDump + public class HeapObject { - public class HeapObject - { - public ulong Address { get; set; } - public string Type { get; set; } - public int HashCode { get; set; } - public ulong MethodTable { get; set; } - } - - public List Objects { get; set; } + public ulong Address { get; set; } + public string Type { get; set; } + public int HashCode { get; set; } + public ulong MethodTable { get; set; } } + + public List Objects { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs index 716a87d6..9ae0315c 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs @@ -1,4 +1,11 @@ -namespace ScubaDiver.API.Interactions.Dumps +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps { /// /// Dump of a specific member (field, property) of a specific object diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs index 35fb5de4..d79cbc4b 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs @@ -1,39 +1,34 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Dumps -{ - public enum ObjectType - { - Unknown, - Primitive, - NonPrimitive, - Array - } - public class ObjectDump - { - public ObjectType ObjectType { get; set; } - public ObjectType SubObjectsType { get; set; } +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; - /// - /// Address where the item was retrieved from - /// - public ulong RetrievalAddress { get; set; } - /// - /// Address when the item was freezed at when pinning. This address won't change until unpinning. - /// - public ulong PinnedAddress { get; set; } - public string Type { get; set; } - public string PrimitiveValue { get; set; } - /// - /// Number of elemnets in the array. This field is only meaningful if ObjectType is "Array" - /// - public int SubObjectsCount { get; set; } - public List Fields { get; set; } - public List Properties { get; set; } - public int HashCode { get; set; } +public class ObjectDump() +{ + public ObjectType ObjectType { get; set; } + public ObjectType SubObjectsType { get; set; } - public ObjectDump() {} - } + /// + /// Address where the item was retrieved from + /// + public ulong RetrievalAddress { get; set; } + /// + /// Address when the item was freezed at when pinning. This address won't change until unpinning. + /// + public ulong PinnedAddress { get; set; } + public string Type { get; set; } + public string PrimitiveValue { get; set; } + /// + /// Number of elemnets in the array. This field is only meaningful if ObjectType is "Array" + /// + public int SubObjectsCount { get; set; } + public List Fields { get; set; } + public List Properties { get; set; } + public int HashCode { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectType.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectType.cs new file mode 100644 index 00000000..d667d06a --- /dev/null +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectType.cs @@ -0,0 +1,16 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +public enum ObjectType +{ + Unknown, + Primitive, + NonPrimitive, + Array +} diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs index 783ed9b0..3babb394 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs @@ -1,200 +1,205 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; -namespace ScubaDiver.API.Interactions.Dumps +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +[DebuggerDisplay("TypeDump of {" + nameof(Type) + "} (Assembly: {" + nameof(Assembly) + "})")] +public class TypeDump { - [DebuggerDisplay("TypeDump of {" + nameof(Type) + "} (Assembly: {" + nameof(Assembly) + "})")] - public class TypeDump + public class TypeMethod { - public class TypeMethod + public class MethodParameter { - public class MethodParameter - { - public bool IsGenericType { get; set; } - public bool IsGenericParameter { get; set; } - public string Type { get; set; } - public string Name { get; set; } - public string Assembly { get; set; } - - public MethodParameter() {} + public bool IsGenericType { get; set; } + public bool IsGenericParameter { get; set; } + public string Type { get; set; } + public string Name { get; set; } + public string Assembly { get; set; } - public MethodParameter(ParameterInfo pi) - { - IsGenericType = pi.ParameterType.IsGenericType; - IsGenericParameter = pi.ParameterType.IsGenericParameter || pi.ParameterType.ContainsGenericParameters; - Name = pi.Name; - // For generic type parameters we need the 'Name' property - it returns something like "T" - // For non-generic we want the full name like "System.Text.StringBuilder" - Type = IsGenericParameter ? pi.ParameterType.Name : pi.ParameterType.FullName; - if (IsGenericParameter && - pi.ParameterType.GenericTypeArguments.Any() && - Type.Contains('`')) - { - Type = Type.Substring(0, Type.IndexOf('`')); - Type += '<'; - Type += String.Join(", ", (object[])pi.ParameterType.GenericTypeArguments); - Type += '>'; - } - Assembly = pi.ParameterType.Assembly.GetName().Name; - } + public MethodParameter() {} - public override string ToString() + public MethodParameter(ParameterInfo pi) + { + IsGenericType = pi.ParameterType.IsGenericType; + IsGenericParameter = pi.ParameterType.IsGenericParameter || pi.ParameterType.ContainsGenericParameters; + Name = pi.Name; + // For generic type parameters we need the 'Name' property - it returns something like "T" + // For non-generic we want the full name like "System.Text.StringBuilder" + Type = IsGenericParameter ? pi.ParameterType.Name : pi.ParameterType.FullName; + if (IsGenericParameter && + pi.ParameterType.GenericTypeArguments.Any() && + Type.Contains('`')) { - return - (string.IsNullOrEmpty(Assembly) ? string.Empty : Assembly + ".") + - (string.IsNullOrEmpty(Type) ? "UNKNOWN_TYPE" : Type) + " " + - (string.IsNullOrEmpty(Name) ? "MISSING_NAME" : Name); + Type = Type.Substring(0, Type.IndexOf('`')); + Type += '<'; + Type += String.Join(", ", (object[])pi.ParameterType.GenericTypeArguments); + Type += '>'; } + Assembly = pi.ParameterType.Assembly.GetName().Name; } - public string Visibility { get; set; } - public string Name { get; set; } - public string ReturnTypeFullName { get; set; } - // This is not a list of the PARAMETERS which are generic -> This is the list of TYPES place holders usually found between - // the "LESS THEN" and "GEATER THEN" signs so for this methods: - // void SomeMethod(T item, string item2, S item3) - // You'll get ["T", "S"] - public List GenericArgs { get; set; } - public List Parameters { get; set; } - public string ReturnTypeAssembly { get; set; } - - public TypeMethod() {} - - public TypeMethod(MethodBase methodBase) + public override string ToString() { - Visibility = methodBase.IsPublic ? "Public" : "Private"; - GenericArgs = new List(); - if (methodBase.ContainsGenericParameters && methodBase is not ConstructorInfo) - { - try - { - GenericArgs = methodBase.GetGenericArguments().Select(arg => arg.Name).ToList(); - } - catch (Exception) {} - } + return + (string.IsNullOrEmpty(Assembly) ? string.Empty : Assembly + ".") + + (string.IsNullOrEmpty(Type) ? "UNKNOWN_TYPE" : Type) + " " + + (string.IsNullOrEmpty(Name) ? "MISSING_NAME" : Name); + } + } - Name = methodBase.Name; - Parameters = methodBase.GetParameters().Select(paramInfo => new MethodParameter(paramInfo)).ToList(); - if (methodBase is MethodInfo methodInfo) - { - ReturnTypeFullName = methodInfo.ReturnType.FullName; - if (ReturnTypeFullName == null) - { - string baseType = methodInfo.ReturnType.Name; - if (baseType.Contains('`')) - baseType = baseType.Substring(0, baseType.IndexOf('`')); - ReturnTypeFullName ??= baseType + "<" + - String.Join(", ", (object[])methodInfo.ReturnType.GenericTypeArguments) + - ">"; - } - - ReturnTypeAssembly = methodInfo.ReturnType.Assembly.GetName().Name; - } - else + public string Visibility { get; set; } + public string Name { get; set; } + public string ReturnTypeFullName { get; set; } + // This is not a list of the PARAMETERS which are generic -> This is the list of TYPES place holders usually found between + // the "LESS THEN" and "GEATER THEN" signs so for this methods: + // void SomeMethod(T item, string item2, S item3) + // You'll get ["T", "S"] + public List GenericArgs { get; set; } + public List Parameters { get; set; } + public string ReturnTypeAssembly { get; set; } + + public TypeMethod() {} + + public TypeMethod(MethodBase methodBase) + { + Visibility = methodBase.IsPublic ? "Public" : "Private"; + GenericArgs = new List(); + if (methodBase.ContainsGenericParameters && methodBase is not ConstructorInfo) + { + try { - ReturnTypeFullName = "System.Void"; - ReturnTypeAssembly = "mscorlib"; + GenericArgs = methodBase.GetGenericArguments().Select(arg => arg.Name).ToList(); } + catch (Exception) {} } - public bool SignaturesEqual(TypeMethod other) + Name = methodBase.Name; + Parameters = methodBase.GetParameters().Select(paramInfo => new MethodParameter(paramInfo)).ToList(); + if (methodBase is MethodInfo methodInfo) { - if (Name != other.Name) - return false; - if (Parameters.Count != other.Parameters.Count) - return false; - var genericArgsMatches = GenericArgs.Zip(other.GenericArgs, (arg1, arg2) => + ReturnTypeFullName = methodInfo.ReturnType.FullName; + if (ReturnTypeFullName == null) { - return arg1 == arg2; - }); - var paramMatches = Parameters.Zip(other.Parameters, (param1, param2) => - { - return param1.Name == param2.Name && - param1.Type == param2.Type; - }); - return paramMatches.All(match => match == true); - } + string baseType = methodInfo.ReturnType.Name; + if (baseType.Contains('`')) + baseType = baseType.Substring(0, baseType.IndexOf('`')); + ReturnTypeFullName ??= baseType + "<" + + String.Join(", ", (object[])methodInfo.ReturnType.GenericTypeArguments) + + ">"; + } - public override string ToString() + ReturnTypeAssembly = methodInfo.ReturnType.Assembly.GetName().Name; + } + else { - return $"{ReturnTypeFullName} {Name}({string.Join(",", Parameters)})"; + ReturnTypeFullName = "System.Void"; + ReturnTypeAssembly = "mscorlib"; } } - public class TypeField - { - public string Visibility { get; set; } - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } - public TypeField() {} - - public TypeField(FieldInfo fi) + public bool SignaturesEqual(TypeMethod other) + { + if (Name != other.Name) + return false; + if (Parameters.Count != other.Parameters.Count) + return false; + var genericArgsMatches = GenericArgs.Zip(other.GenericArgs, (arg1, arg2) => { - Visibility = fi.IsPublic ? "Public" : "Private"; - Name = fi.Name; - TypeFullName = fi.FieldType.FullName; - Assembly = fi.FieldType.Assembly.GetName().Name; - } + return arg1 == arg2; + }); + var paramMatches = Parameters.Zip(other.Parameters, (param1, param2) => + { + return param1.Name == param2.Name && + param1.Type == param2.Type; + }); + return paramMatches.All(match => match == true); } - public class TypeEvent + + public override string ToString() { - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } + return $"{ReturnTypeFullName} {Name}({string.Join(",", Parameters)})"; + } + } + public class TypeField + { + public string Visibility { get; set; } + public string Name { get; set; } + public string TypeFullName { get; set; } + public string Assembly { get; set; } - public TypeEvent() {} - public TypeEvent(EventInfo ei) - { - Name = ei.Name; - TypeFullName = ei.EventHandlerType.FullName; - Assembly = ei.EventHandlerType.Assembly.GetName().Name; - } + public TypeField() {} + + public TypeField(FieldInfo fi) + { + Visibility = fi.IsPublic ? "Public" : "Private"; + Name = fi.Name; + TypeFullName = fi.FieldType.FullName; + Assembly = fi.FieldType.Assembly.GetName().Name; } + } + public class TypeEvent + { + public string Name { get; set; } + public string TypeFullName { get; set; } + public string Assembly { get; set; } - public class TypeProperty + public TypeEvent() {} + public TypeEvent(EventInfo ei) { - public string GetVisibility { get; set; } - public string SetVisibility { get; set; } - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } + Name = ei.Name; + TypeFullName = ei.EventHandlerType.FullName; + Assembly = ei.EventHandlerType.Assembly.GetName().Name; + } + } - public TypeProperty() {} + public class TypeProperty + { + public string GetVisibility { get; set; } + public string SetVisibility { get; set; } + public string Name { get; set; } + public string TypeFullName { get; set; } + public string Assembly { get; set; } - public TypeProperty(PropertyInfo pi) - { - if (pi.GetMethod != null) - { - GetVisibility = pi.GetMethod.IsPublic ? "Public" : "Private"; - } - if (pi.SetMethod != null) - { - SetVisibility = pi.SetMethod.IsPublic ? "Public" : "Private"; - } + public TypeProperty() {} - Name = pi.Name; - TypeFullName = pi.PropertyType.FullName; - Assembly = pi.PropertyType.Assembly.GetName().Name; + public TypeProperty(PropertyInfo pi) + { + if (pi.GetMethod != null) + { + GetVisibility = pi.GetMethod.IsPublic ? "Public" : "Private"; + } + if (pi.SetMethod != null) + { + SetVisibility = pi.SetMethod.IsPublic ? "Public" : "Private"; } + + Name = pi.Name; + TypeFullName = pi.PropertyType.FullName; + Assembly = pi.PropertyType.Assembly.GetName().Name; } + } - public string Type { get; set; } - public string Assembly { get; set; } + public string Type { get; set; } + public string Assembly { get; set; } - public bool IsArray { get; set; } + public bool IsArray { get; set; } - public string ParentFullTypeName { get; set; } - public string ParentAssembly { get; set; } + public string ParentFullTypeName { get; set; } + public string ParentAssembly { get; set; } - public List Methods { get; set; } - public List Constructors { get; set; } - public List Fields { get; set; } - public List Events { get; set; } - public List Properties { get; set; } - } + public List Methods { get; set; } + public List Constructors { get; set; } + public List Fields { get; set; } + public List Events { get; set; } + public List Properties { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs index c4babbfe..482044aa 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs @@ -1,8 +1,14 @@ -namespace ScubaDiver.API.Interactions.Dumps +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +public class TypeDumpRequest { - public class TypeDumpRequest - { - public string Assembly { get; set; } - public string TypeFullName { get; set; } - } + public string Assembly { get; set; } + public string TypeFullName { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs index dca106e7..39575944 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs @@ -1,15 +1,20 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Dumps + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +public class TypesDump { - public class TypesDump + public class TypeIdentifiers { - public class TypeIdentifiers - { - public string TypeName { get; set; } - } - public string AssemblyName { get; set; } - public List Types { get; set; } + public string TypeName { get; set; } } + public string AssemblyName { get; set; } + public List Types { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs index 00865085..0b20e74e 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs @@ -1,20 +1,19 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions -{ - public class InvocationRequest - { - public ulong ObjAddress { get; set; } - public string MethodName { get; set; } - public string TypeFullName { get; set; } - public string[] GenericArgsTypeFullNames { get; set; } - public List Parameters { get; set; } - public InvocationRequest() - { - GenericArgsTypeFullNames = new string[0]; - Parameters = new(); - } - } +namespace MTGOSDK.Core.Remoting.Interop.Interactions; + +public class InvocationRequest() +{ + public ulong ObjAddress { get; set; } + public string MethodName { get; set; } + public string TypeFullName { get; set; } + public string[] GenericArgsTypeFullNames { get; set; } = new string[0]; + public List Parameters { get; set; } = new(); } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs index 753b2b60..bd254200 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationResults.cs @@ -1,8 +1,14 @@ -namespace ScubaDiver.API.Interactions +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions; + +public class InvocationResults { - public class InvocationResults - { - public bool VoidReturnType { get; set; } - public ObjectOrRemoteAddress? ReturnedObjectOrAddress { get; set; } - } + public bool VoidReturnType { get; set; } + public ObjectOrRemoteAddress? ReturnedObjectOrAddress { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs index 9d80a52a..60a83ac5 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs @@ -1,16 +1,16 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ +using System.Collections.Generic; -namespace ScubaDiver.API.Interactions.Object -{ - public class CtorInvocationRequest - { - public string TypeFullName { get; set; } - public List Parameters { get; set; } - public CtorInvocationRequest() - { - Parameters = new(); - } - } +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; + +public class CtorInvocationRequest() +{ + public string TypeFullName { get; set; } + public List Parameters { get; set; } = new(); } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs index bd21c39e..ed0d7f28 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs @@ -1,9 +1,15 @@ -namespace ScubaDiver.API.Interactions.Object +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; + +public class FieldGetRequest { - public class FieldGetRequest - { - public ulong ObjAddress { get; set; } - public string TypeFullName { get; set; } - public string FieldName { get; set; } - } -} \ No newline at end of file + public ulong ObjAddress { get; set; } + public string TypeFullName { get; set; } + public string FieldName { get; set; } +} diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs index 98bd1f78..7e474d5d 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs @@ -1,10 +1,16 @@ -namespace ScubaDiver.API.Interactions.Object +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; + +public class FieldSetRequest { - public class FieldSetRequest - { - public ulong ObjAddress { get; set; } - public string TypeFullName { get; set; } - public string FieldName { get; set; } - public ObjectOrRemoteAddress Value { get; set; } - } + public ulong ObjAddress { get; set; } + public string TypeFullName { get; set; } + public string FieldName { get; set; } + public ObjectOrRemoteAddress Value { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs index 9473d3e2..fc483777 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs @@ -1,9 +1,15 @@ -namespace ScubaDiver.API.Interactions.Object +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + + +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; + +public class IndexedItemAccessRequest { - public class IndexedItemAccessRequest - { - public ulong CollectionAddress { get; set; } - public bool PinRequest { get; set; } - public ObjectOrRemoteAddress Index { get; set; } - } + public ulong CollectionAddress { get; set; } + public bool PinRequest { get; set; } + public ObjectOrRemoteAddress Index { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs b/MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs index 987f4175..0707d6b8 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/ObjectOrRemoteAddress.cs @@ -1,9 +1,15 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ -using ScubaDiver.API.Utils; +using System; +using MTGOSDK.Core.Remoting.Interop.Utils; -namespace ScubaDiver.API + +namespace MTGOSDK.Core.Remoting.Interop { /// /// Either an encoded object (for primitive types like int, string, primitibe arrays...) or info of a remote object diff --git a/MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs b/MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs index 746b1638..cda213f9 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/ReverseCommunicator.cs @@ -1,12 +1,19 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Callbacks; -using ScubaDiver.API.Utils; -namespace ScubaDiver.API +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; +using MTGOSDK.Core.Remoting.Interop.Utils; + +namespace MTGOSDK.Core.Remoting.Interop { /// /// The reverse communicator is used by the Diver to communicate back with its diff --git a/MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs index a36ffec3..889df0eb 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Utils/Filter.cs @@ -1,48 +1,53 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; -namespace ScubaDiver.API.Utils +namespace MTGOSDK.Core.Remoting.Interop.Utils; + +public class Filter { - public class Filter + /// + /// Turn a "simple filter string" into a regex + /// + /// A string that only allow '*' as a wild card meaning "0 or more characters" + private static Regex SimpleFilterToRegex(string simpleFilter) { - /// - /// Turn a "simple filter string" into a regex - /// - /// A string that only allow '*' as a wild card meaning "0 or more characters" - private static Regex SimpleFilterToRegex(string simpleFilter) + StringBuilder sb = new StringBuilder(); + sb.Append("^"); // Begining of string + foreach (char c in simpleFilter) { - StringBuilder sb = new StringBuilder(); - sb.Append("^"); // Begining of string - foreach (char c in simpleFilter) + if (c == '*') + { + sb.Append(".*"); + } + else { - if (c == '*') - { - sb.Append(".*"); - } - else - { - string asEscaped = Regex.Escape(c.ToString()); - sb.Append(asEscaped); - } + string asEscaped = Regex.Escape(c.ToString()); + sb.Append(asEscaped); } - sb.Append("$"); // End of string - return new Regex(sb.ToString()); } + sb.Append("$"); // End of string + return new Regex(sb.ToString()); + } - public static Predicate CreatePredicate(string filter) + public static Predicate CreatePredicate(string filter) + { + Predicate matchesFilter = (testee) => true; + if (filter != null) { - Predicate matchesFilter = (testee) => true; - if (filter != null) - { - Regex r = SimpleFilterToRegex(filter); - string noStartsFilter = filter.Trim('*'); - // Filter has no wildcards - looking for specific type - matchesFilter = r.IsMatch; - } - return matchesFilter; + Regex r = SimpleFilterToRegex(filter); + string noStartsFilter = filter.Trim('*'); + // Filter has no wildcards - looking for specific type + matchesFilter = r.IsMatch; } + return matchesFilter; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs index 5dfeb076..b10f4075 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Utils/NewtonsoftProxy.cs @@ -1,88 +1,93 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace ScubaDiver.API.Utils +namespace MTGOSDK.Core.Remoting.Interop.Utils; + +public static class JsonConvert { - public static class JsonConvert + public static T DeserializeObject( + string body, + object _withErrors = null) where T : class { - public static T DeserializeObject( - string body, - object _withErrors = null) where T : class - { - Type convert = NewtonsoftProxy.JsonConvert; + Type convert = NewtonsoftProxy.JsonConvert; - List args = new List(); - args.Add(body); - if(_withErrors != null) - args.Add(_withErrors); + List args = new List(); + args.Add(body); + if(_withErrors != null) + args.Add(_withErrors); - var DeserializeObject = convert.GetMethods((BindingFlags)0xffff) - .Where(mi => mi.Name=="DeserializeObject") - .Where(mi => mi.IsGenericMethod) - .Where(mi => mi.GetParameters().Length == args.Count) - .Where(mi => !mi.GetParameters().Last().ParameterType.IsArray) - .Single(); + var DeserializeObject = convert.GetMethods((BindingFlags)0xffff) + .Where(mi => mi.Name=="DeserializeObject") + .Where(mi => mi.IsGenericMethod) + .Where(mi => mi.GetParameters().Length == args.Count) + .Where(mi => !mi.GetParameters().Last().ParameterType.IsArray) + .Single(); - try - { - var x = DeserializeObject - .MakeGenericMethod(typeof(T)) - .Invoke(null, args.ToArray()); - return (T)x; - } - catch(TargetInvocationException ex) - { - throw ex.InnerException; - } + try + { + var x = DeserializeObject + .MakeGenericMethod(typeof(T)) + .Invoke(null, args.ToArray()); + return (T)x; } - - public static string SerializeObject(object o) + catch(TargetInvocationException ex) { - Type convert = NewtonsoftProxy.JsonConvert; + throw ex.InnerException; + } + } + + public static string SerializeObject(object o) + { + Type convert = NewtonsoftProxy.JsonConvert; - List args = new List() {o}; + List args = new List() {o}; - var SerializeObject = convert.GetMethods((BindingFlags)0xffff) - .Where(mi => mi.Name == "SerializeObject") - .Where(mi => mi.GetParameters().Length == 1) - .Single(); + var SerializeObject = convert.GetMethods((BindingFlags)0xffff) + .Where(mi => mi.Name == "SerializeObject") + .Where(mi => mi.GetParameters().Length == 1) + .Single(); - try - { - var x = SerializeObject.Invoke(null, args.ToArray()); - return (string)x; - } - catch (TargetInvocationException ex) - { - throw ex.InnerException; - } + try + { + var x = SerializeObject.Invoke(null, args.ToArray()); + return (string)x; + } + catch (TargetInvocationException ex) + { + throw ex.InnerException; } } +} - public static class NewtonsoftProxy +public static class NewtonsoftProxy +{ + public static object JsonSerializerSettingsWithErrors { - public static object JsonSerializerSettingsWithErrors + get { - get - { - Type MissingMemberHandlingEnum = typeof(Newtonsoft.Json.MissingMemberHandling); - var MissingMemberHandling_Error = Enum - .GetValues(MissingMemberHandlingEnum) - .Cast() - .Single(val => val.ToString() == "Error"); + Type MissingMemberHandlingEnum = typeof(Newtonsoft.Json.MissingMemberHandling); + var MissingMemberHandling_Error = Enum + .GetValues(MissingMemberHandlingEnum) + .Cast() + .Single(val => val.ToString() == "Error"); - Type t = typeof(Newtonsoft.Json.JsonSerializerSettings); - var inst = Activator.CreateInstance(t); - t.GetProperty("MissingMemberHandling") - .SetValue(inst, MissingMemberHandling_Error); + Type t = typeof(Newtonsoft.Json.JsonSerializerSettings); + var inst = Activator.CreateInstance(t); + t.GetProperty("MissingMemberHandling") + .SetValue(inst, MissingMemberHandling_Error); - return inst; - } + return inst; } - - public static Type JsonConvert => typeof(Newtonsoft.Json.JsonConvert); } + + public static Type JsonConvert => typeof(Newtonsoft.Json.JsonConvert); } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs index 9133b5b8..f6501745 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Utils/PrimitivesEncoder.cs @@ -1,178 +1,184 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Linq; -using ScubaDiver.API.Extensions; + +using MTGOSDK.Core.Remoting.Interop.Extensions; -namespace ScubaDiver.API.Utils +namespace MTGOSDK.Core.Remoting.Interop.Utils; + +public static class PrimitivesEncoder { - public static class PrimitivesEncoder + /// + /// Encodes a primitive or array of primitives + /// + /// Object or array to encode + /// Encoded value as a string + public static string Encode(object toEncode) { - /// - /// Encodes a primitive or array of primitives - /// - /// Object or array to encode - /// Encoded value as a string - public static string Encode(object toEncode) - { - if (toEncode == null) // This is specific for the String case, but I can't guarantee it here... - return string.Empty; + if (toEncode == null) // This is specific for the String case, but I can't guarantee it here... + return string.Empty; - Type t = toEncode.GetType(); - if (t == typeof(string)) - { - return $"\"{toEncode}\""; - } + Type t = toEncode.GetType(); + if (t == typeof(string)) + { + return $"\"{toEncode}\""; + } - if (t.IsPrimitiveEtc() || t.IsStringCoercible()) - { - // These types can just be ".Parse()"-ed back - return toEncode.ToString(); - } + if (t.IsPrimitiveEtc() || t.IsStringCoercible()) + { + // These types can just be ".Parse()"-ed back + return toEncode.ToString(); + } - if (toEncode is not Array enumerable) - { - throw new ArgumentException( - $"Object to encode was not a primitive or an array. TypeFullName: {t}"); - } + if (toEncode is not Array enumerable) + { + throw new ArgumentException( + $"Object to encode was not a primitive or an array. TypeFullName: {t}"); + } - if (!t.IsPrimitiveEtcArray()) - { - // TODO: Support arrays of RemoteObjects/DynamicRemoteObject - throw new Exception("At least one element in the array is not primitive"); - } + if (!t.IsPrimitiveEtcArray()) + { + // TODO: Support arrays of RemoteObjects/DynamicRemoteObject + throw new Exception("At least one element in the array is not primitive"); + } - // Otherwise - this is an array of primitives. - string output = string.Empty; - object[] objectsEnumerable = enumerable.Cast().ToArray(); - foreach (object o in objectsEnumerable) + // Otherwise - this is an array of primitives. + string output = string.Empty; + object[] objectsEnumerable = enumerable.Cast().ToArray(); + foreach (object o in objectsEnumerable) + { + string currObjectValue = Encode(o); + // Escape commas + currObjectValue = currObjectValue.Replace(",", "\\,"); + if (output != string.Empty) { - string currObjectValue = Encode(o); - // Escape commas - currObjectValue = currObjectValue.Replace(",", "\\,"); - if (output != string.Empty) - { - output += ","; - } - - output += $"\"{currObjectValue}\""; + output += ","; } - return output; + output += $"\"{currObjectValue}\""; } - public static bool TryEncode(object toEncode, out string res) + return output; + } + + public static bool TryEncode(object toEncode, out string res) + { + res = default; + if (!(toEncode.GetType().IsPrimitiveEtc())) { - res = default; - if (!(toEncode.GetType().IsPrimitiveEtc())) + if (toEncode is Array) { - if (toEncode is Array) + Type elementsType = toEncode.GetType().GetElementType(); + if (!elementsType.IsPrimitiveEtc()) { - Type elementsType = toEncode.GetType().GetElementType(); - if (!elementsType.IsPrimitiveEtc()) - { - // Array of non-primitives --> not primitive - return false; - } - else - { - // It's a primitives array, All go exit if clauses and encode - } + // Array of non-primitives --> not primitive + return false; } else { - // Not primitive ETC nor array --> not primitive - return false; + // It's a primitives array, All go exit if clauses and encode } } - - // All good, can encode with no exceptions: - res = Encode(toEncode); - return true; + else + { + // Not primitive ETC nor array --> not primitive + return false; + } } - public static object Decode(ObjectOrRemoteAddress oora) + // All good, can encode with no exceptions: + res = Encode(toEncode); + return true; + } + + public static object Decode(ObjectOrRemoteAddress oora) + { + if (oora.IsRemoteAddress) + throw new ArgumentException("Can not decode ObjectOrRemoteAddress object which represents a remote address."); + return Decode(oora.EncodedObject, oora.Type); + } + public static object Decode(string toDecode, Type resultType) + { + // Easiest case - strings are encoded to themselves + if (resultType == typeof(string)) { - if (oora.IsRemoteAddress) - throw new ArgumentException("Can not decode ObjectOrRemoteAddress object which represents a remote address."); - return Decode(oora.EncodedObject, oora.Type); + if (toDecode == "null") + return null; + else if (toDecode[0] == '"' && toDecode[toDecode.Length-1] == '"') + return toDecode.Substring(1, toDecode.Length - 2); + else + throw new Exception("Missing qoutes on encoded string"); } - public static object Decode(string toDecode, Type resultType) - { - // Easiest case - strings are encoded to themselves - if (resultType == typeof(string)) - { - if (toDecode == "null") - return null; - else if (toDecode[0] == '"' && toDecode[toDecode.Length-1] == '"') - return toDecode.Substring(1, toDecode.Length - 2); - else - throw new Exception("Missing qoutes on encoded string"); - } - if (resultType.IsPrimitiveEtc() || resultType.IsStringCoercible()) - { - var parseMethod = resultType.GetMethod("Parse", new Type[1] { typeof(string) }); - return parseMethod.Invoke(null, new object[] { toDecode }); - } + if (resultType.IsPrimitiveEtc() || resultType.IsStringCoercible()) + { + var parseMethod = resultType.GetMethod("Parse", new Type[1] { typeof(string) }); + return parseMethod.Invoke(null, new object[] { toDecode }); + } - if (resultType.IsArray) + if (resultType.IsArray) + { + List commas = new(); + commas.Add(0); // To capture the first item we need to "imagine a comma" right before it. + for (int i = 1; i < toDecode.Length; i++) { - List commas = new(); - commas.Add(0); // To capture the first item we need to "imagine a comma" right before it. - for (int i = 1; i < toDecode.Length; i++) - { - if (toDecode[i] == ',' && toDecode[i - 1] != '\\') - { - commas.Add(i); - } - } - - List encodedElements = new(); - for (int i = 0; i < commas.Count; i++) + if (toDecode[i] == ',' && toDecode[i - 1] != '\\') { - int currCommaIndex = commas[i]; - int nextCommandIndex = toDecode.Length; - if (i != commas.Count - 1) - { - nextCommandIndex = commas[i + 1]; - } - encodedElements.Add(toDecode.Substring(currCommaIndex + 1, nextCommandIndex - currCommaIndex - 1).Trim('\"')); + commas.Add(i); } + } - Type elementType = resultType.GetElementType(); - List decodedObjects = new(); - foreach (string encodedElement in encodedElements) + List encodedElements = new(); + for (int i = 0; i < commas.Count; i++) + { + int currCommaIndex = commas[i]; + int nextCommandIndex = toDecode.Length; + if (i != commas.Count - 1) { - var unescapedEncElement = encodedElement.Replace("\\,", ","); - object decodedObject = Decode(unescapedEncElement, elementType); - decodedObjects.Add(decodedObject); + nextCommandIndex = commas[i + 1]; } + encodedElements.Add(toDecode.Substring(currCommaIndex + 1, nextCommandIndex - currCommaIndex - 1).Trim('\"')); + } - // Create a runtime array of the specific element type then copying from the list to it - Array arr = Array.CreateInstance(elementType, decodedObjects.Count); - for (int i = 0; i < decodedObjects.Count; i++) - { - arr.SetValue(decodedObjects[i], i); - } + Type elementType = resultType.GetElementType(); + List decodedObjects = new(); + foreach (string encodedElement in encodedElements) + { + var unescapedEncElement = encodedElement.Replace("\\,", ","); + object decodedObject = Decode(unescapedEncElement, elementType); + decodedObjects.Add(decodedObject); + } - return arr; + // Create a runtime array of the specific element type then copying from the list to it + Array arr = Array.CreateInstance(elementType, decodedObjects.Count); + for (int i = 0; i < decodedObjects.Count; i++) + { + arr.SetValue(decodedObjects[i], i); } - throw new ArgumentException( - $"Result type was not a primitive or an array. TypeFullName: {resultType}"); + return arr; } - public static object Decode(string toDecode, string fullTypeName) - { - // NOTE: I'm allowing this decode to be restricted to the current domain (Instead of searching in all domains) - // because I want to believe only primitive types will be handed here and those - // should all be available in all domains. (hopefully) - Type t = AppDomain.CurrentDomain.GetType(fullTypeName); - if (t != null) - return Decode(toDecode, t); - - throw new Exception($"Could not resolve type name \"{fullTypeName}\" in the current AppDomain"); - } + throw new ArgumentException( + $"Result type was not a primitive or an array. TypeFullName: {resultType}"); + } + + public static object Decode(string toDecode, string fullTypeName) + { + // NOTE: I'm allowing this decode to be restricted to the current domain (Instead of searching in all domains) + // because I want to believe only primitive types will be handed here and those + // should all be available in all domains. (hopefully) + Type t = AppDomain.CurrentDomain.GetType(fullTypeName); + if (t != null) + return Decode(toDecode, t); + + throw new Exception($"Could not resolve type name \"{fullTypeName}\" in the current AppDomain"); } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs b/MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs index c15a73e1..09e87d26 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Utils/TypeExt.cs @@ -1,180 +1,187 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using ScubaDiver.API.Extensions; -namespace ScubaDiver.API.Utils +using MTGOSDK.Core.Remoting.Interop.Extensions; + + +namespace MTGOSDK.Core.Remoting.Interop.Utils; + +public static class TypeExt { - public static class TypeExt + public class WildCardEnabledTypesComparer : IEqualityComparer { - public class WildCardEnabledTypesComparer : IEqualityComparer + public bool Equals(Type x, Type y) { - public bool Equals(Type x, Type y) - { - if (x is WildCardType || y is WildCardType) - return true; - return x.IsAssignableFrom(y); - } - - public int GetHashCode(Type obj) => obj.GetHashCode(); + if (x is WildCardType || y is WildCardType) + return true; + return x.IsAssignableFrom(y); } - private static readonly WildCardEnabledTypesComparer _wildCardTypesComparer = new(); - - /// - /// Searches a type for a specific method. If not found searches its ancestors. - /// - /// TypeFullName to search - /// Method name - /// Types of parameters in the function, in order. - /// - public static MethodInfo GetMethodRecursive( - this Type t, - string methodName, - Type[]? parameterTypes = null) - => GetMethodRecursive(t, methodName, null, parameterTypes); - - public static MethodInfo GetMethodRecursive( - this Type t, - string methodName, - Type[]? genericArgumentTypes, - Type[]? parameterTypes) - { - var methods = t.GetMethods((BindingFlags)0xffff) - .Where(m => m.Name == methodName); - if (genericArgumentTypes != null && genericArgumentTypes.Length > 0) - { - methods = methods - .Where(m => m.ContainsGenericParameters == true) - .Where(m => m.GetGenericArguments().Length == genericArgumentTypes.Length) - .Select(m => m.MakeGenericMethod(genericArgumentTypes)); - } - - MethodInfo method; - if (parameterTypes == null) - { - method = methods.SingleOrDefault(); - } - else - { - MethodInfo[]? exactMatches = methods.Where(m => - m.GetParameters() - .Select(pi => pi.ParameterType) - .SequenceEqual(parameterTypes)) - .ToArray(); - if (exactMatches != null && exactMatches.Length == 1) - { - method = exactMatches.First(); - } - else - { - // Do a less strict search - method = methods.SingleOrDefault(m => - m.GetParameters() - .Select(pi => pi.ParameterType) - .SequenceEqual(parameterTypes, _wildCardTypesComparer)); - } - } - - if (method != null) - return method; - - // Not found in this type... - if (t == typeof(object)) - return null; // No more parents + public int GetHashCode(Type obj) => obj.GetHashCode(); + } - // Check parent (until `object`) - return t.BaseType.GetMethodRecursive(methodName, parameterTypes); + private static readonly WildCardEnabledTypesComparer _wildCardTypesComparer = new(); + + /// + /// Searches a type for a specific method. If not found searches its ancestors. + /// + /// TypeFullName to search + /// Method name + /// Types of parameters in the function, in order. + /// + public static MethodInfo GetMethodRecursive( + this Type t, + string methodName, + Type[]? parameterTypes = null) + => GetMethodRecursive(t, methodName, null, parameterTypes); + + public static MethodInfo GetMethodRecursive( + this Type t, + string methodName, + Type[]? genericArgumentTypes, + Type[]? parameterTypes) + { + var methods = t.GetMethods((BindingFlags)0xffff) + .Where(m => m.Name == methodName); + if (genericArgumentTypes != null && genericArgumentTypes.Length > 0) + { + methods = methods + .Where(m => m.ContainsGenericParameters == true) + .Where(m => m.GetGenericArguments().Length == genericArgumentTypes.Length) + .Select(m => m.MakeGenericMethod(genericArgumentTypes)); } - public static MethodInfo GetMethodRecursive(this Type t, string methodName) - => GetMethodRecursive(t, methodName, null); - public static ConstructorInfo GetConstructor( - Type resolvedType, - Type[]? parameterTypes = null) + MethodInfo method; + if (parameterTypes == null) { - ConstructorInfo ctorInfo; - - var methods = resolvedType.GetConstructors((BindingFlags)0xffff); - ConstructorInfo[] exactMatches = methods - .Where(m => + method = methods.SingleOrDefault(); + } + else + { + MethodInfo[]? exactMatches = methods.Where(m => m.GetParameters() .Select(pi => pi.ParameterType) .SequenceEqual(parameterTypes)) .ToArray(); - if (exactMatches.Length == 1) + if (exactMatches != null && exactMatches.Length == 1) { - ctorInfo = exactMatches.First(); + method = exactMatches.First(); } else { // Do a less strict search - ctorInfo = methods.SingleOrDefault(m => - m.GetParameters() - .Select(pi => pi.ParameterType) - .SequenceEqual(parameterTypes, - new TypeExt.WildCardEnabledTypesComparer())); + method = methods.SingleOrDefault(m => + m.GetParameters() + .Select(pi => pi.ParameterType) + .SequenceEqual(parameterTypes, _wildCardTypesComparer)); } - - return ctorInfo; } - /// - /// Searches a type for a specific field. If not found searches its ancestors. - /// - /// TypeFullName to search - /// Field name to search - public static FieldInfo GetFieldRecursive(this Type t, string fieldName) - { - var field = t.GetFields((BindingFlags)0xffff) - .SingleOrDefault(fi => fi.Name == fieldName); - if (field != null) - return field; + if (method != null) + return method; - // Not found in this type... - if (t == typeof(object)) - return null; // No more parents + // Not found in this type... + if (t == typeof(object)) + return null; // No more parents - // Check parent (until `object`) - return t.BaseType.GetFieldRecursive(fieldName); - } + // Check parent (until `object`) + return t.BaseType.GetMethodRecursive(methodName, parameterTypes); + } + public static MethodInfo GetMethodRecursive(this Type t, string methodName) + => GetMethodRecursive(t, methodName, null); - public static bool IsPrimitiveEtcArray(this Type realType) + public static ConstructorInfo GetConstructor( + Type resolvedType, + Type[]? parameterTypes = null) + { + ConstructorInfo ctorInfo; + + var methods = resolvedType.GetConstructors((BindingFlags)0xffff); + ConstructorInfo[] exactMatches = methods + .Where(m => + m.GetParameters() + .Select(pi => pi.ParameterType) + .SequenceEqual(parameterTypes)) + .ToArray(); + if (exactMatches.Length == 1) { - if (!realType.IsArray) - return false; - - Type elementsType = realType.GetElementType(); - return elementsType.IsPrimitiveEtc(); + ctorInfo = exactMatches.First(); } - - public static bool IsPrimitiveEtc(this Type realType) + else { - return realType.IsPrimitive || - realType == typeof(string) || - realType == typeof(decimal) || - realType == typeof(DateTime); + // Do a less strict search + ctorInfo = methods.SingleOrDefault(m => + m.GetParameters() + .Select(pi => pi.ParameterType) + .SequenceEqual(parameterTypes, + new TypeExt.WildCardEnabledTypesComparer())); } - public static bool IsStringCoercible(this Type realType) - { - // TODO: Apply more comprehensive check to ensure that these types are - // present in the consumer AppDomain and have `ToString` and `Parse` - // methods. - return realType == typeof(Guid); - } + return ctorInfo; + } - public static Type GetType(this AppDomain domain, string typeFullName) + /// + /// Searches a type for a specific field. If not found searches its ancestors. + /// + /// TypeFullName to search + /// Field name to search + public static FieldInfo GetFieldRecursive(this Type t, string fieldName) + { + var field = t.GetFields((BindingFlags)0xffff) + .SingleOrDefault(fi => fi.Name == fieldName); + if (field != null) + return field; + + // Not found in this type... + if (t == typeof(object)) + return null; // No more parents + + // Check parent (until `object`) + return t.BaseType.GetFieldRecursive(fieldName); + } + + public static bool IsPrimitiveEtcArray(this Type realType) + { + if (!realType.IsArray) + return false; + + Type elementsType = realType.GetElementType(); + return elementsType.IsPrimitiveEtc(); + } + + public static bool IsPrimitiveEtc(this Type realType) + { + return realType.IsPrimitive || + realType == typeof(string) || + realType == typeof(decimal) || + realType == typeof(DateTime); + } + + public static bool IsStringCoercible(this Type realType) + { + // TODO: Apply more comprehensive check to ensure that these types are + // present in the consumer AppDomain and have `ToString` and `Parse` + // methods. + return realType == typeof(Guid); + } + + public static Type GetType(this AppDomain domain, string typeFullName) + { + var assemblies = domain.GetAssemblies(); + foreach (Assembly assm in assemblies) { - var assemblies = domain.GetAssemblies(); - foreach (Assembly assm in assemblies) - { - Type t = assm.GetType(typeFullName); - if (t != null) - return t; - } - return null; + Type t = assm.GetType(typeFullName); + if (t != null) + return t; } + return null; } } diff --git a/MTGOSDK/src/Core/Remoting/Logger.cs b/MTGOSDK/src/Core/Remoting/Logger.cs index 1e48b74c..ed4c2094 100644 --- a/MTGOSDK/src/Core/Remoting/Logger.cs +++ b/MTGOSDK/src/Core/Remoting/Logger.cs @@ -8,8 +8,9 @@ using System.Diagnostics; -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; +#TODO: Refactor this to use the Microsoft.Extensions.Logging abstractions. internal class Logger { public static Lazy DebugInRelease = new Lazy(() => diff --git a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs index 296e2cc1..4fb1d7a0 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs @@ -7,13 +7,13 @@ using System; using System.Linq; -using ScubaDiver.API; -using ScubaDiver.API.Interactions; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions; -using RemoteNET.Internal.Reflection; +using MTGOSDK.Core.Remoting.Internal.Reflection; -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; public class RemoteActivator(DiverCommunicator communicator, RemoteApp app) { diff --git a/MTGOSDK/src/Core/Remoting/RemoteApp.cs b/MTGOSDK/src/Core/Remoting/RemoteApp.cs index 96b4838a..d1627cfa 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteApp.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteApp.cs @@ -11,15 +11,15 @@ using System.Linq; using System.Reflection; -using ScubaDiver.API; -using ScubaDiver.API.Interactions.Dumps; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop.Utils; -using RemoteNET.Internal; -using RemoteNET.Internal.Reflection; +using MTGOSDK.Core.Remoting.Internal; +using MTGOSDK.Core.Remoting.Internal.Reflection; -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; public class RemoteApp : IDisposable { diff --git a/MTGOSDK/src/Core/Remoting/RemoteObject.cs b/MTGOSDK/src/Core/Remoting/RemoteObject.cs index a34304bd..6ab8407c 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteObject.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteObject.cs @@ -7,14 +7,14 @@ using System; using System.Collections.Generic; -using ScubaDiver.API; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -using RemoteNET.Internal; +using MTGOSDK.Core.Remoting.Internal; -namespace RemoteNET; +namespace MTGOSDK.Core.Remoting; public class RemoteObject { diff --git a/examples/BasicInjector/Program.cs b/examples/BasicInjector/Program.cs index 38496888..767e77a5 100644 --- a/examples/BasicInjector/Program.cs +++ b/examples/BasicInjector/Program.cs @@ -8,7 +8,7 @@ using MTGOSDK.API; // using MTGOInjector; -// using ScubaDiver.API.Hooking; +// using MTGOSDK.Core.Remoting.Interop.Hooking; // diff --git a/third_party/RemoteNET/src/ScubaDiver/Diver.cs b/third_party/RemoteNET/src/ScubaDiver/Diver.cs index 1c1c0796..1eef2fbb 100644 --- a/third_party/RemoteNET/src/ScubaDiver/Diver.cs +++ b/third_party/RemoteNET/src/ScubaDiver/Diver.cs @@ -18,14 +18,14 @@ using MTGOSDK.Win32.API; -using ScubaDiver.API; -using ScubaDiver.API.Extensions; -using ScubaDiver.API.Interactions; -using ScubaDiver.API.Interactions.Callbacks; -using ScubaDiver.API.Interactions.Client; -using ScubaDiver.API.Interactions.Dumps; -using ScubaDiver.API.Interactions.Object; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop; +using MTGOSDK.Core.Remoting.Interop.Extensions; +using MTGOSDK.Core.Remoting.Interop.Interactions; +using MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; +using MTGOSDK.Core.Remoting.Interop.Interactions.Client; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop.Interactions.Object; +using MTGOSDK.Core.Remoting.Interop.Utils; using ScubaDiver.Utils; @@ -696,7 +696,7 @@ private string MakeUnregisterClientResponse(HttpListenerRequest arg) UnregisterClientResponse ucResponse = new() { - WasRemvoed = removed, + WasRemoved = removed, OtherClientsAmount = remaining }; diff --git a/third_party/RemoteNET/src/ScubaDiver/Utils/Converter.cs b/third_party/RemoteNET/src/ScubaDiver/Utils/Converter.cs index 0991da85..73afebd8 100644 --- a/third_party/RemoteNET/src/ScubaDiver/Utils/Converter.cs +++ b/third_party/RemoteNET/src/ScubaDiver/Utils/Converter.cs @@ -1,12 +1,12 @@ using System; using System.Reflection.Emit; -using ScubaDiver.API.Extensions; +using MTGOSDK.Core.Remoting.Interop.Extensions; namespace ScubaDiver; /// -/// The dynamic method trick is originally by Alois Kraus here: +/// The dynamic method trick is originally by Alois Kraus here: /// https://social.microsoft.com/Forums/windows/en-US/06ac44b0-30d8-44a1-86a4-1716dc431c62/how-to-convert-an-intptr-to-an-object-in-c?forum=clr /// Method Table comparison was added in RemoteNET /// @@ -15,8 +15,8 @@ public class Converter delegate U Void2ObjectConverter(IntPtr pManagedObject); static Void2ObjectConverter myConverter; - // The type initializer is run every time the converter is instantiated with a different - // generic argument. + // The type initializer is run every time the converter is instantiated with a different + // generic argument. static Converter() { GenerateDynamicMethod(); @@ -32,10 +32,10 @@ static void GenerateDynamicMethod() typeof(IntPtr), true); var gen = method.GetILGenerator(); - // Load first argument + // Load first argument gen.Emit(OpCodes.Ldarg_0); // return it directly. The Clr will take care of the cast! - // this construct is unverifiable so we need to plug this into an assembly with + // this construct is unverifiable so we need to plug this into an assembly with // IL Verification disabled gen.Emit(OpCodes.Ret); myConverter = (Void2ObjectConverter)method @@ -45,7 +45,7 @@ static void GenerateDynamicMethod() public T ConvertFromIntPtr(IntPtr pObj, IntPtr expectedMethodTable) { - // Reading Method Table (MT) of the object to make sure we + // Reading Method Table (MT) of the object to make sure we // aren't mistakenly pointing at another type by now (could be caused by the GC) IntPtr actualMethodTable = pObj.GetMethodTable(); if (actualMethodTable != expectedMethodTable) diff --git a/third_party/RemoteNET/src/ScubaDiver/Utils/ObjectDumpFactory.cs b/third_party/RemoteNET/src/ScubaDiver/Utils/ObjectDumpFactory.cs index e5a91a6c..71dd09a9 100644 --- a/third_party/RemoteNET/src/ScubaDiver/Utils/ObjectDumpFactory.cs +++ b/third_party/RemoteNET/src/ScubaDiver/Utils/ObjectDumpFactory.cs @@ -3,8 +3,8 @@ using System.Linq; using System.Reflection; -using ScubaDiver.API.Interactions.Dumps; -using ScubaDiver.API.Utils; +using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; +using MTGOSDK.Core.Remoting.Interop.Utils; namespace ScubaDiver; @@ -130,7 +130,7 @@ public static ObjectDump Create( // // Property dumping is disabled. It should be accessed using the 'get_' function. // - + //var propValue = propInfo.GetValue(instance); //bool hasEncValue = false; //string encValue = null; From c120cf7ba6489bd5b8228f683a8b954d1d9cd893 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 16:21:26 -0500 Subject: [PATCH 09/20] [MTGOSDK/Core/Remoting] Remove Logger stub --- MTGOSDK/src/Core/Remoting/Logger.cs | 38 ----------------------------- 1 file changed, 38 deletions(-) delete mode 100644 MTGOSDK/src/Core/Remoting/Logger.cs diff --git a/MTGOSDK/src/Core/Remoting/Logger.cs b/MTGOSDK/src/Core/Remoting/Logger.cs deleted file mode 100644 index ed4c2094..00000000 --- a/MTGOSDK/src/Core/Remoting/Logger.cs +++ /dev/null @@ -1,38 +0,0 @@ -/** @file - Copyright (c) 2021, Xappy. - Copyright (c) 2024, Cory Bennett. All rights reserved. - SPDX-License-Identifier: Apache-2.0 and MIT -**/ - -using System; -using System.Diagnostics; - - -namespace MTGOSDK.Core.Remoting; - -#TODO: Refactor this to use the Microsoft.Extensions.Logging abstractions. -internal class Logger -{ - public static Lazy DebugInRelease = new Lazy(() => - !string.IsNullOrWhiteSpace( - Environment.GetEnvironmentVariable("REMOTE_NET_DIVER_MAGIC_DEBUG"))); - -#if DEBUG - public static bool IsDebug = true; -#else - public static bool IsDebug = false; -#endif - - internal static void Debug(string s) - { - if (IsDebug || Debugger.IsAttached) - { - System.Diagnostics.Debug.WriteLine(s); - } - // Allow debug logging in release only if the environment variable is set. - else if(DebugInRelease.Value) - { - Console.WriteLine(s); - } - } -} From 4a77262cd51257e908454ac0ffa966d49c165c17 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:06:54 -0500 Subject: [PATCH 10/20] [MTGOSDK/Core/Remoting/Interop] Use smaller struct object footprint --- MTGOSDK/src/Core/Remoting/CandidateObject.cs | 3 +- MTGOSDK/src/Core/Remoting/CandidateType.cs | 3 +- .../Interop/Exceptions/RemoteException.cs | 22 ++---- .../Callbacks/CallbackInvocationRequest.cs | 2 +- .../Client/UnregisterClientResponse.cs | 3 +- .../Interop/Interactions/Dumps/DomainsDump.cs | 2 +- .../Interop/Interactions/Dumps/HeapDump.cs | 2 +- .../Interop/Interactions/Dumps/MemberDump.cs | 21 +++-- .../Interop/Interactions/Dumps/ObjectDump.cs | 2 +- .../Interop/Interactions/Dumps/TypeDump.cs | 76 ++++++------------- .../Interactions/Dumps/TypeDumpRequest.cs | 2 +- .../Interop/Interactions/Dumps/TypesDump.cs | 3 +- .../Interop/Interactions/InvocationRequest.cs | 2 +- .../Object/CtorInvocationRequest.cs | 2 +- .../Interactions/Object/FieldGetRequest.cs | 2 +- .../Interactions/Object/FieldSetRequest.cs | 2 +- .../Object/IndexedItemAccessRequest.cs | 2 +- MTGOSDK/src/Core/Remoting/RemoteActivator.cs | 1 - 18 files changed, 58 insertions(+), 94 deletions(-) diff --git a/MTGOSDK/src/Core/Remoting/CandidateObject.cs b/MTGOSDK/src/Core/Remoting/CandidateObject.cs index 34e108b4..5c40c539 100644 --- a/MTGOSDK/src/Core/Remoting/CandidateObject.cs +++ b/MTGOSDK/src/Core/Remoting/CandidateObject.cs @@ -4,13 +4,14 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ + namespace MTGOSDK.Core.Remoting; /// /// A candidate for a remote object. /// Holding this item does not mean having a meaningful hold of the remote object. To gain one use /// -public class CandidateObject(ulong address, string typeFullName, int hashCode) +public struct CandidateObject(ulong address, string typeFullName, int hashCode) { public ulong Address = address; public string TypeFullName = typeFullName; diff --git a/MTGOSDK/src/Core/Remoting/CandidateType.cs b/MTGOSDK/src/Core/Remoting/CandidateType.cs index 4ebf9716..11bfa1b6 100644 --- a/MTGOSDK/src/Core/Remoting/CandidateType.cs +++ b/MTGOSDK/src/Core/Remoting/CandidateType.cs @@ -4,9 +4,10 @@ SPDX-License-Identifier: Apache-2.0 and MIT **/ + namespace MTGOSDK.Core.Remoting; -public class CandidateType(string typeName, string assembly) +public struct CandidateType(string typeName, string assembly) { public string TypeFullName = typeName; public string Assembly = assembly; diff --git a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs index 0bdc9296..2d486ef3 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Exceptions/RemoteException.cs @@ -12,24 +12,16 @@ namespace MTGOSDK.Core.Remoting.Interop.Exceptions; /// /// Encapsulates an exception that was thrown in the remote object and catched by the Diver. /// -public class RemoteException : Exception +public class RemoteException(string msg, string remoteStackTrace) : Exception { - public string RemoteMessage { get; private set; } - private string _remoteStackTrace; - public string RemoteStackTrace => _remoteStackTrace; + public string RemoteMessage { get; private set; } = msg; + + public string RemoteStackTrace => remoteStackTrace; + public override string StackTrace => - $"{_remoteStackTrace}\n" + + $"{remoteStackTrace}\n" + $"--- End of remote exception stack trace ---\n" + $"{base.StackTrace}"; - public RemoteException(string msg, string remoteStackTrace) - { - RemoteMessage = msg; - _remoteStackTrace = remoteStackTrace; - } - - public override string ToString() - { - return RemoteMessage; - } + public override string ToString() => RemoteMessage; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs index b76b89de..062ad3a3 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Callbacks/CallbackInvocationRequest.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Callbacks; -public class CallbackInvocationRequest() +public class CallbackInvocationRequest { public string StackTrace { get; set; } public int Token { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs index 2664a35d..80c144fc 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Client/UnregisterClientResponse.cs @@ -7,9 +7,10 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Client; -public class UnregisterClientResponse +public struct UnregisterClientResponse { public bool WasRemoved { get; set; } + /// /// Number of remaining clients, after the removal was done /// diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs index 0c72b751..956c1dd7 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/DomainsDump.cs @@ -11,7 +11,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; public class DomainsDump { - public class AvailableDomain + public struct AvailableDomain { public string Name { get; set; } public List AvailableModules { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs index 26ca40a9..784ab89a 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/HeapDump.cs @@ -11,7 +11,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; public class HeapDump { - public class HeapObject + public struct HeapObject { public ulong Address { get; set; } public string Type { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs index 9ae0315c..1e594dea 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/MemberDump.cs @@ -5,16 +5,15 @@ **/ -namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps +namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; + +/// +/// Dump of a specific member (field, property) of a specific object +/// +public struct MemberDump { - /// - /// Dump of a specific member (field, property) of a specific object - /// - public class MemberDump - { - public string Name { get; set; } - public bool HasEncodedValue { get; set; } - public string EncodedValue { get; set; } - public string RetrievalError { get; set; } - } + public string Name { get; set; } + public bool HasEncodedValue { get; set; } + public string EncodedValue { get; set; } + public string RetrievalError { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs index d79cbc4b..92289353 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/ObjectDump.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -public class ObjectDump() +public class ObjectDump { public ObjectType ObjectType { get; set; } public ObjectType SubObjectsType { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs index 3babb394..63d7e5c3 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDump.cs @@ -16,9 +16,9 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; [DebuggerDisplay("TypeDump of {" + nameof(Type) + "} (Assembly: {" + nameof(Assembly) + "})")] public class TypeDump { - public class TypeMethod + public struct TypeMethod { - public class MethodParameter + public struct MethodParameter { public bool IsGenericType { get; set; } public bool IsGenericParameter { get; set; } @@ -130,63 +130,33 @@ public override string ToString() return $"{ReturnTypeFullName} {Name}({string.Join(",", Parameters)})"; } } - public class TypeField - { - public string Visibility { get; set; } - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } - public TypeField() {} - - public TypeField(FieldInfo fi) - { - Visibility = fi.IsPublic ? "Public" : "Private"; - Name = fi.Name; - TypeFullName = fi.FieldType.FullName; - Assembly = fi.FieldType.Assembly.GetName().Name; - } - } - public class TypeEvent + public struct TypeField(FieldInfo fi) { - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } - - public TypeEvent() {} - public TypeEvent(EventInfo ei) - { - Name = ei.Name; - TypeFullName = ei.EventHandlerType.FullName; - Assembly = ei.EventHandlerType.Assembly.GetName().Name; - } + public string Visibility = fi.IsPublic ? "Public" : "Private"; + public string Name = fi.Name; + public string TypeFullName = fi.FieldType.FullName; + public string Assembly = fi.FieldType.Assembly.GetName().Name; } - public class TypeProperty + public struct TypeEvent(EventInfo ei) { - public string GetVisibility { get; set; } - public string SetVisibility { get; set; } - public string Name { get; set; } - public string TypeFullName { get; set; } - public string Assembly { get; set; } - - public TypeProperty() {} - - public TypeProperty(PropertyInfo pi) - { - if (pi.GetMethod != null) - { - GetVisibility = pi.GetMethod.IsPublic ? "Public" : "Private"; - } - if (pi.SetMethod != null) - { - SetVisibility = pi.SetMethod.IsPublic ? "Public" : "Private"; - } + public string Name = ei.Name; + public string TypeFullName = ei.EventHandlerType.FullName; + public string Assembly = ei.EventHandlerType.Assembly.GetName().Name; + } - Name = pi.Name; - TypeFullName = pi.PropertyType.FullName; - Assembly = pi.PropertyType.Assembly.GetName().Name; - } + public struct TypeProperty(PropertyInfo pi) + { + public string Name = pi.Name; + public string TypeFullName = pi.PropertyType.FullName; + public string Assembly = pi.PropertyType.Assembly.GetName().Name; + public string GetVisibility = pi.GetMethod != null + ? (pi.GetMethod.IsPublic ? "Public" : "Private") + : null!; + public string SetVisibility = pi.SetMethod != null + ? (pi.SetMethod.IsPublic ? "Public" : "Private") + : null!; } public string Type { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs index 482044aa..c2cde46b 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -public class TypeDumpRequest +public struct TypeDumpRequest { public string Assembly { get; set; } public string TypeFullName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs index 39575944..692c96e3 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypesDump.cs @@ -11,10 +11,11 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; public class TypesDump { - public class TypeIdentifiers + public struct TypeIdentifiers { public string TypeName { get; set; } } + public string AssemblyName { get; set; } public List Types { get; set; } } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs index 0b20e74e..8c719cdc 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions; -public class InvocationRequest() +public struct InvocationRequest() { public ulong ObjAddress { get; set; } public string MethodName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs index 60a83ac5..45c9365a 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public class CtorInvocationRequest() +public struct CtorInvocationRequest() { public string TypeFullName { get; set; } public List Parameters { get; set; } = new(); diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs index ed0d7f28..a8189091 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public class FieldGetRequest +public struct FieldGetRequest { public ulong ObjAddress { get; set; } public string TypeFullName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs index 7e474d5d..2ef6cefa 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public class FieldSetRequest +public struct FieldSetRequest { public ulong ObjAddress { get; set; } public string TypeFullName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs index fc483777..3458585c 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public class IndexedItemAccessRequest +public struct IndexedItemAccessRequest { public ulong CollectionAddress { get; set; } public bool PinRequest { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs index 4fb1d7a0..bbec0e95 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs @@ -9,7 +9,6 @@ using MTGOSDK.Core.Remoting.Interop; using MTGOSDK.Core.Remoting.Interop.Interactions; - using MTGOSDK.Core.Remoting.Internal.Reflection; From d92354f0699e987f6521d56a508438506113e34d Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:09:42 -0500 Subject: [PATCH 11/20] [MTGOSDK] Remove nullability warnings from exclusion list --- MTGOSDK/MTGOSDK.csproj | 9 +-------- MTGOSDK/MTGOSDK.ref.props | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 872b44f3..cbd2ffa8 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -7,12 +7,9 @@ enable $(NoWarn); - CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;IDE0065; + CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;CS8767;CS9113;IDE0065; CS8601;CS8608;CS8610;CS8618;CS8619;CS8620;CS8765; - - 1701;1702;8600;8602;8603;8618;8625; - CS0436;CS9113;CS8767;MSB3277 @@ -42,8 +39,6 @@ ReferenceOutputAssembly="false" Private="false" /> - @@ -61,8 +56,6 @@ - diff --git a/MTGOSDK/MTGOSDK.ref.props b/MTGOSDK/MTGOSDK.ref.props index 97a2bd33..2c2f4c7a 100644 --- a/MTGOSDK/MTGOSDK.ref.props +++ b/MTGOSDK/MTGOSDK.ref.props @@ -3,7 +3,7 @@ - $(NoWarn);NU1702; + $(NoWarn);NU1702;MSB3277; true From f2c05d4a65fd0efdc238894965da6c327c8a91ca Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:16:05 -0500 Subject: [PATCH 12/20] [MTGOSDK/Core/Remoting] Move RemoteClient to namespace, rename RemoteApp --- MTGOSDK/src/API/Client.cs | 2 +- MTGOSDK/src/API/Collection/DeckRegion.cs | 2 +- MTGOSDK/src/API/Collection/SetType.cs | 2 +- .../ViewModels/BasicToastViewModel.cs | 2 +- .../ViewModels/GenericDialogViewModel.cs | 2 +- MTGOSDK/src/API/Interface/WindowUtilities.cs | 2 +- MTGOSDK/src/API/Play/EventManager.cs | 2 +- MTGOSDK/src/API/Play/Games/Game.cs | 2 +- MTGOSDK/src/API/Users/UserManager.cs | 2 +- MTGOSDK/src/Core/Reflection/ObjectProvider.cs | 2 +- MTGOSDK/src/Core/Remoting/Bootstrapper.cs | 2 +- MTGOSDK/src/Core/Remoting/CandidateObject.cs | 2 +- .../Remoting/Internal/DynamicRemoteObject.cs | 4 ++-- .../Internal/DynamicRemoteObjectFactory.cs | 4 ++-- .../Internal/Reflection/DynamicRemoteEnum.cs | 2 +- .../Reflection/RemoteConstructorInfo.cs | 2 +- .../Remoting/Internal/Reflection/RemoteEnum.cs | 2 +- .../Internal/Reflection/RemoteFieldInfo.cs | 6 +++--- .../Reflection/RemoteFunctionsInvokeHelper.cs | 6 +++--- .../Internal/Reflection/RemoteMethodInfo.cs | 2 +- .../Internal/Reflection/RemotePropertyInfo.cs | 2 +- .../Remoting/Internal/Reflection/RemoteType.cs | 6 +++--- .../Internal/Reflection/RemoteTypesFactory.cs | 18 +++++++++--------- MTGOSDK/src/Core/Remoting/RemoteActivator.cs | 2 +- .../src/Core/{ => Remoting}/RemoteClient.cs | 14 ++++++-------- .../Remoting/{RemoteApp.cs => RemoteHandle.cs} | 18 +++++++++--------- MTGOSDK/src/Core/Remoting/RemoteObject.cs | 4 ++-- .../src/Core/Security/SecurityExtensions.cs | 1 + 28 files changed, 58 insertions(+), 59 deletions(-) rename MTGOSDK/src/Core/{ => Remoting}/RemoteClient.cs (97%) rename MTGOSDK/src/Core/Remoting/{RemoteApp.cs => RemoteHandle.cs} (94%) diff --git a/MTGOSDK/src/API/Client.cs b/MTGOSDK/src/API/Client.cs index 8d2113d6..62d6b568 100644 --- a/MTGOSDK/src/API/Client.cs +++ b/MTGOSDK/src/API/Client.cs @@ -10,9 +10,9 @@ using MTGOSDK.API.Collection; using MTGOSDK.API.Users; using MTGOSDK.API.Interface; -using MTGOSDK.Core; using MTGOSDK.Core.Exceptions; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using MTGOSDK.Core.Security; using FlsClient.Interface; diff --git a/MTGOSDK/src/API/Collection/DeckRegion.cs b/MTGOSDK/src/API/Collection/DeckRegion.cs index 3565ea37..837e7eaf 100644 --- a/MTGOSDK/src/API/Collection/DeckRegion.cs +++ b/MTGOSDK/src/API/Collection/DeckRegion.cs @@ -3,8 +3,8 @@ SPDX-License-Identifier: Apache-2.0 **/ -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using WotC.MTGO.Common; diff --git a/MTGOSDK/src/API/Collection/SetType.cs b/MTGOSDK/src/API/Collection/SetType.cs index ac7a4a36..83db4f21 100644 --- a/MTGOSDK/src/API/Collection/SetType.cs +++ b/MTGOSDK/src/API/Collection/SetType.cs @@ -3,8 +3,8 @@ SPDX-License-Identifier: Apache-2.0 **/ -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using WotC.MTGO.Common; diff --git a/MTGOSDK/src/API/Interface/ViewModels/BasicToastViewModel.cs b/MTGOSDK/src/API/Interface/ViewModels/BasicToastViewModel.cs index 016ce938..dc36e180 100644 --- a/MTGOSDK/src/API/Interface/ViewModels/BasicToastViewModel.cs +++ b/MTGOSDK/src/API/Interface/ViewModels/BasicToastViewModel.cs @@ -4,8 +4,8 @@ **/ using MTGOSDK.API.Play.Games; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using Shiny.Core; using Shiny.Core.Interfaces; diff --git a/MTGOSDK/src/API/Interface/ViewModels/GenericDialogViewModel.cs b/MTGOSDK/src/API/Interface/ViewModels/GenericDialogViewModel.cs index 292ad379..707f8d6a 100644 --- a/MTGOSDK/src/API/Interface/ViewModels/GenericDialogViewModel.cs +++ b/MTGOSDK/src/API/Interface/ViewModels/GenericDialogViewModel.cs @@ -4,8 +4,8 @@ **/ using MTGOSDK.API.Play.Games; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using Shiny.Core.Interfaces; diff --git a/MTGOSDK/src/API/Interface/WindowUtilities.cs b/MTGOSDK/src/API/Interface/WindowUtilities.cs index 0cb286dc..f7955f73 100644 --- a/MTGOSDK/src/API/Interface/WindowUtilities.cs +++ b/MTGOSDK/src/API/Interface/WindowUtilities.cs @@ -5,8 +5,8 @@ using System.Windows; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using Shiny.Core.Interfaces; diff --git a/MTGOSDK/src/API/Play/EventManager.cs b/MTGOSDK/src/API/Play/EventManager.cs index 894140c9..16081b4a 100644 --- a/MTGOSDK/src/API/Play/EventManager.cs +++ b/MTGOSDK/src/API/Play/EventManager.cs @@ -5,8 +5,8 @@ using System.Collections.Generic; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using WotC.MtGO.Client.Model.Play; diff --git a/MTGOSDK/src/API/Play/Games/Game.cs b/MTGOSDK/src/API/Play/Games/Game.cs index 3976326f..fab7f1af 100644 --- a/MTGOSDK/src/API/Play/Games/Game.cs +++ b/MTGOSDK/src/API/Play/Games/Game.cs @@ -5,8 +5,8 @@ using MTGOSDK.API.Chat; using MTGOSDK.API.Interface.ViewModels; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using WotC.MtGO.Client.Model.Play; diff --git a/MTGOSDK/src/API/Users/UserManager.cs b/MTGOSDK/src/API/Users/UserManager.cs index e820895a..ab6dbd9a 100644 --- a/MTGOSDK/src/API/Users/UserManager.cs +++ b/MTGOSDK/src/API/Users/UserManager.cs @@ -6,8 +6,8 @@ using System.Collections.Concurrent; using System.Reflection; -using MTGOSDK.Core; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; using WotC.MtGO.Client.Model; using WotC.MtGO.Client.Model.Chat; diff --git a/MTGOSDK/src/Core/Reflection/ObjectProvider.cs b/MTGOSDK/src/Core/Reflection/ObjectProvider.cs index 7a24d327..57a50074 100644 --- a/MTGOSDK/src/Core/Reflection/ObjectProvider.cs +++ b/MTGOSDK/src/Core/Reflection/ObjectProvider.cs @@ -3,7 +3,7 @@ SPDX-License-Identifier: Apache-2.0 **/ -using MTGOSDK.Core; +using MTGOSDK.Core.Remoting; namespace MTGOSDK.Core.Reflection; diff --git a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs index 6f51e9b2..7015b919 100644 --- a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs +++ b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs @@ -22,7 +22,7 @@ public static class Bootstrapper ExtractDir ); - public static string ExtractDir = typeof(RemoteApp).Assembly.GetName().Name; + public static string ExtractDir = typeof(RemoteClient).Assembly.GetName().Name; public static void Inject(Process target, ushort diverPort) { diff --git a/MTGOSDK/src/Core/Remoting/CandidateObject.cs b/MTGOSDK/src/Core/Remoting/CandidateObject.cs index 5c40c539..28268e2e 100644 --- a/MTGOSDK/src/Core/Remoting/CandidateObject.cs +++ b/MTGOSDK/src/Core/Remoting/CandidateObject.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting; /// /// A candidate for a remote object. -/// Holding this item does not mean having a meaningful hold of the remote object. To gain one use +/// Holding this item does not mean having a meaningful hold of the remote object. To gain one use /// public struct CandidateObject(ulong address, string typeFullName, int hashCode) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs index b8684866..fa693d99 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObject.cs @@ -168,7 +168,7 @@ public override int GetHashCode() this[t1, t2, t3, t4][t5]; } - public RemoteApp __ra; + public RemoteHandle __ra; public RemoteObject __ro; public RemoteType __type; @@ -177,7 +177,7 @@ public override int GetHashCode() private List __membersInner = null; public IEnumerable __members => MindFuck(); - public DynamicRemoteObject(RemoteApp ra, RemoteObject ro) + public DynamicRemoteObject(RemoteHandle ra, RemoteObject ro) { __ra = ra; __ro = ro; diff --git a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs index 1c01af57..2128c418 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/DynamicRemoteObjectFactory.cs @@ -11,10 +11,10 @@ namespace MTGOSDK.Core.Remoting.Internal; public class DynamicRemoteObjectFactory { - private RemoteApp _app; + private RemoteHandle _app; public DynamicRemoteObject Create( - RemoteApp rApp, + RemoteHandle rApp, RemoteObject remoteObj, TypeDump typeDump) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs index 7a0c7aa0..f56a3990 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/DynamicRemoteEnum.cs @@ -11,7 +11,7 @@ namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class DynamicRemoteEnum(RemoteEnum remoteEnum) : DynamicObject { - public RemoteApp App => remoteEnum.App; + public RemoteHandle App => remoteEnum.App; public override bool TryGetMember(GetMemberBinder binder, out dynamic result) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs index 7e6cc6dd..ef07223f 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteConstructorInfo.cs @@ -25,7 +25,7 @@ public class RemoteConstructorInfo(Type declaringType, public override Type ReflectedType => throw new NotImplementedException(); - private RemoteApp App => (DeclaringType as RemoteType)?.App; + private RemoteHandle App => (DeclaringType as RemoteType)?.App; public RemoteConstructorInfo(RemoteType declaringType, ConstructorInfo ci) : this(declaringType, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs index ec073e7f..5bf4bf52 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteEnum.cs @@ -8,7 +8,7 @@ namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemoteEnum(RemoteType remoteType) { - public RemoteApp App => remoteType?.App; + public RemoteHandle App => remoteType?.App; public object GetValue(string valueName) { diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs index 5cb2e43b..1599efb8 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFieldInfo.cs @@ -19,7 +19,7 @@ public class RemoteFieldInfo( Lazy fieldType, string name) : FieldInfo { - private RemoteApp App => (DeclaringType as RemoteType)?.App; + private RemoteHandle App => (DeclaringType as RemoteType)?.App; public override Type FieldType => fieldType.Value; public override Type DeclaringType { get; } = declaringType; @@ -61,7 +61,7 @@ public override object GetValue(object obj) throw new InvalidOperationException( $"Trying to get a static field (null target object) " + $"on a {nameof(RemoteFieldInfo)} but it's associated " + - $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + + $"Declaring Type ({DeclaringType}) does not have a RemoteHandle associated. " + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); } @@ -134,7 +134,7 @@ public override void SetValue( throw new InvalidOperationException( $"Trying to get a static field (null target object) " + $"on a {nameof(RemoteFieldInfo)} but it's associated " + - $"Declaring Type ({DeclaringType}) does not have a RemoteApp associated. " + + $"Declaring Type ({DeclaringType}) does not have a RemoteHandle associated. " + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); } diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs index 48a04375..e417a9fc 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteFunctionsInvokeHelper.cs @@ -56,7 +56,7 @@ public static ObjectOrRemoteAddress CreateRemoteParameter(object parameter) } public static object Invoke( - RemoteApp app, + RemoteHandle app, Type declaringType, string funcName, object obj, @@ -71,7 +71,7 @@ public static object Invoke( parameters); public static object Invoke( - RemoteApp app, + RemoteHandle app, Type declaringType, string funcName, object obj, @@ -109,7 +109,7 @@ public static object Invoke( throw new InvalidOperationException( $"Trying to invoke a static call (null target object) " + $"on a {nameof(RemoteMethodInfo)} but it's associated " + - $"Declaring Type ({declaringType}) does not have a RemoteApp associated. " + + $"Declaring Type ({declaringType}) does not have a RemoteHandle associated. " + $"The type was either mis-constructed or it's not a {nameof(RemoteType)} object"); } diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs index e5b81e9c..276dfdd2 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteMethodInfo.cs @@ -53,7 +53,7 @@ public override Type[] GetGenericArguments() => public Type[] AssignedGenericArgs { get; } = genericArgs ?? Type.EmptyTypes; - private RemoteApp App => (DeclaringType as RemoteType)?.App; + private RemoteHandle App => (DeclaringType as RemoteType)?.App; public RemoteMethodInfo(RemoteType declaringType, MethodInfo mi) : this(declaringType, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs index 264711b8..8335d450 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemotePropertyInfo.cs @@ -13,7 +13,7 @@ namespace MTGOSDK.Core.Remoting.Internal.Reflection; public class RemotePropertyInfo(Type declaringType, Lazy propType, string name) : PropertyInfo { - private RemoteApp App => (DeclaringType as RemoteType)?.App; + private RemoteHandle App => (DeclaringType as RemoteType)?.App; public override PropertyAttributes Attributes => throw new NotImplementedException(); diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs index 49921088..69c53ace 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteType.cs @@ -36,14 +36,14 @@ public class RemoteType : Type private readonly bool _isArray; private readonly bool _isGenericParameter; - public RemoteApp App { get; set; } + public RemoteHandle App { get; set; } public override bool IsGenericParameter => _isGenericParameter; private Lazy _parent; public override Type BaseType => _parent?.Value; - public RemoteType(RemoteApp app, Type localType) + public RemoteType(RemoteHandle app, Type localType) : this(app, localType.FullName, localType.Assembly.GetName().Name, localType.IsArray, localType.IsGenericParameter) { if (localType is RemoteType) @@ -73,7 +73,7 @@ public RemoteType(RemoteApp app, Type localType) } public RemoteType( - RemoteApp app, + RemoteHandle app, string fullName, string assemblyName, bool isArray, diff --git a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs index eca4bdbf..c625a098 100644 --- a/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs +++ b/MTGOSDK/src/Core/Remoting/Internal/Reflection/RemoteTypesFactory.cs @@ -29,7 +29,7 @@ public class RemoteTypesFactory(TypesResolver resolver, new Dictionary, Type>(); public Type ResolveTypeWhileCreating( - RemoteApp app, + RemoteHandle app, string typeInProgress, string methodName, string assembly, @@ -66,7 +66,7 @@ public Type ResolveTypeWhileCreating( paramType = new RemoteType(app, paramType); // TODO: Registring here in the cache is a hack but we couldn't // register within "TypesResolver.Resolve" because we don't have the - // RemoteApp to associate the fake remote type with. + // RemoteHandle to associate the fake remote type with. // // Maybe this should move somewhere else... resolver.RegisterType(paramType); @@ -98,7 +98,7 @@ public Type ResolveTypeWhileCreating( return paramType; } - private Type Create(RemoteApp app, string fullTypeName, string assembly) + private Type Create(RemoteHandle app, string fullTypeName, string assembly) { Type shortOutput = resolver.Resolve(assembly, fullTypeName); if (shortOutput != null) @@ -113,7 +113,7 @@ private Type Create(RemoteApp app, string fullTypeName, string assembly) return Create(app, parentDump); } - public Type Create(RemoteApp app, TypeDump typeDump) + public Type Create(RemoteHandle app, TypeDump typeDump) { Type shortOutput = resolver.Resolve(typeDump.Assembly, typeDump.Type); if (shortOutput != null) @@ -155,7 +155,7 @@ public Type Create(RemoteApp app, TypeDump typeDump) return output; } - private void AddMembers(RemoteApp app, TypeDump typeDump, RemoteType output) + private void AddMembers(RemoteHandle app, TypeDump typeDump, RemoteType output) { AddGroupOfFunctions(app, typeDump, typeDump.Methods, output, areConstructors: false); AddGroupOfFunctions(app, typeDump, typeDump.Constructors, output, areConstructors: true); @@ -183,7 +183,7 @@ private void AttachAccessorsToProperties(RemoteType output) } } - private void AddProperties(RemoteApp app, TypeDump typeDump, RemoteType output) + private void AddProperties(RemoteHandle app, TypeDump typeDump, RemoteType output) { foreach (TypeDump.TypeProperty propDump in typeDump.Properties) { @@ -220,7 +220,7 @@ private void AttachAddAndRemoveToEvents(RemoteType output) } } - private void AddEvents(RemoteApp app, TypeDump typeDump, RemoteType output) + private void AddEvents(RemoteHandle app, TypeDump typeDump, RemoteType output) { foreach (TypeDump.TypeEvent eventType in typeDump.Events) { @@ -243,7 +243,7 @@ private void AddEvents(RemoteApp app, TypeDump typeDump, RemoteType output) } } - private void AddFields(RemoteApp app, TypeDump typeDump, RemoteType output) + private void AddFields(RemoteHandle app, TypeDump typeDump, RemoteType output) { foreach (TypeDump.TypeField fieldDump in typeDump.Fields) { @@ -267,7 +267,7 @@ private void AddFields(RemoteApp app, TypeDump typeDump, RemoteType output) } } - private void AddGroupOfFunctions(RemoteApp app, TypeDump typeDump, List functions, RemoteType declaringType, bool areConstructors) + private void AddGroupOfFunctions(RemoteHandle app, TypeDump typeDump, List functions, RemoteType declaringType, bool areConstructors) { foreach (TypeDump.TypeMethod func in functions) { diff --git a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs index bbec0e95..4e5ae0ea 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteActivator.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteActivator.cs @@ -14,7 +14,7 @@ namespace MTGOSDK.Core.Remoting; -public class RemoteActivator(DiverCommunicator communicator, RemoteApp app) +public class RemoteActivator(DiverCommunicator communicator, RemoteHandle app) { public RemoteObject CreateInstance(Type t) => CreateInstance(t, new object[0]); diff --git a/MTGOSDK/src/Core/RemoteClient.cs b/MTGOSDK/src/Core/Remoting/RemoteClient.cs similarity index 97% rename from MTGOSDK/src/Core/RemoteClient.cs rename to MTGOSDK/src/Core/Remoting/RemoteClient.cs index ff99df63..4c61bf7f 100644 --- a/MTGOSDK/src/Core/RemoteClient.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteClient.cs @@ -9,14 +9,12 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; -using MTGOSDK.Core.Remoting; - using MTGOSDK.Core.Reflection; using MTGOSDK.Core.Exceptions; using MTGOSDK.Win32.Utilities; -namespace MTGOSDK.Core; +namespace MTGOSDK.Core.Remoting; using static MTGOSDK.Win32.Constants; /// @@ -30,7 +28,7 @@ public sealed class RemoteClient : DLRWrapper private static readonly Lazy s_instance = new(() => new RemoteClient()); public static RemoteClient @this => s_instance.Value; - public static RemoteApp @client => @this._clientHandle; + public static RemoteHandle @client => @this._clientHandle; public static Process @process => @this._clientProcess; /// @@ -193,7 +191,7 @@ public static bool MinimizeWindow() /// /// The RemoteNET handle to interact with the client. /// - private readonly RemoteApp _clientHandle; + private readonly RemoteHandle _clientHandle; /// /// The native process handle to the MTGO client. @@ -206,11 +204,11 @@ public static bool MinimizeWindow() /// Connects to the target process and returns a RemoteNET client handle. /// /// A RemoteNET client handle. - private RemoteApp GetClientHandle() + private RemoteHandle GetClientHandle() { // Connect to the target process var port = RemoteClient.Port ??= (ushort)_clientProcess.Id; - var client = RemoteApp.Connect(_clientProcess, port); + var client = RemoteHandle.Connect(_clientProcess, port); // Teardown on exception. AppDomain.CurrentDomain.UnhandledException += (s, e) => Dispose(); @@ -236,7 +234,7 @@ internal static void Dispose() ~RemoteClient() => Dispose(); // - // RemoteApp wrapper methods + // RemoteHandle wrapper methods // /// diff --git a/MTGOSDK/src/Core/Remoting/RemoteApp.cs b/MTGOSDK/src/Core/Remoting/RemoteHandle.cs similarity index 94% rename from MTGOSDK/src/Core/Remoting/RemoteApp.cs rename to MTGOSDK/src/Core/Remoting/RemoteHandle.cs index d1627cfa..27df55b5 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteApp.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteHandle.cs @@ -21,7 +21,7 @@ namespace MTGOSDK.Core.Remoting; -public class RemoteApp : IDisposable +public class RemoteHandle : IDisposable { internal class RemoteObjectsCollection { @@ -29,9 +29,9 @@ internal class RemoteObjectsCollection private readonly Dictionary> _pinnedAddressesToRemoteObjects; private readonly object _lock = new object(); - private readonly RemoteApp _app; + private readonly RemoteHandle _app; - public RemoteObjectsCollection(RemoteApp app) + public RemoteObjectsCollection(RemoteHandle app) { _app = app; _pinnedAddressesToRemoteObjects = new Dictionary>(); @@ -120,7 +120,7 @@ public RemoteObject GetRemoteObject( public DiverCommunicator Communicator => _communicator; public static bool IsReconnected = false; - internal RemoteApp(Process procWithDiver, DiverCommunicator communicator) + internal RemoteHandle(Process procWithDiver, DiverCommunicator communicator) { _procWithDiver = procWithDiver; _communicator = communicator; @@ -137,12 +137,12 @@ internal RemoteApp(Process procWithDiver, DiverCommunicator communicator) /// /// Process to create the provider for /// A provider for the given process - public static RemoteApp Connect(Process target) + public static RemoteHandle Connect(Process target) { return Connect(target, (ushort)target.Id); } - public static RemoteApp Connect(Process target, ushort diverPort) + public static RemoteHandle Connect(Process target, ushort diverPort) { // Use discovery to check for existing diver string diverAddr = "127.0.0.1"; @@ -174,7 +174,7 @@ public static RemoteApp Connect(Process target, ushort diverPort) if (com.RegisterClient() == false) throw new Exception("Registering as a client in the Diver failed."); - return new RemoteApp(target, com); + return new RemoteHandle(target, com); } // @@ -198,7 +198,7 @@ public IEnumerable QueryTypes(string typeFullNameFilter) catch { // TODO: - Debug.WriteLine($"[{nameof(RemoteApp)}][{nameof(QueryTypes)}] Exception thrown when Dumping/Iterating assembly: {assembly}"); + Debug.WriteLine($"[{nameof(RemoteHandle)}][{nameof(QueryTypes)}] Exception thrown when Dumping/Iterating assembly: {assembly}"); continue; } foreach (TypesDump.TypeIdentifiers type in typeIdentifiers) @@ -257,7 +257,7 @@ public Type GetRemoteType(string typeFullName, string assembly = null) res = new RemoteType(this, res); // TODO: Registering here in the cache is a hack but we couldn't // register within "TypesResolver.Resolve" because we don't have the - // RemoteApp to associate the fake remote type with. + // RemoteHandle to associate the fake remote type with. // Maybe this should move somewhere else... resolver.RegisterType(res); } diff --git a/MTGOSDK/src/Core/Remoting/RemoteObject.cs b/MTGOSDK/src/Core/Remoting/RemoteObject.cs index 6ab8407c..0ff2e2f6 100644 --- a/MTGOSDK/src/Core/Remoting/RemoteObject.cs +++ b/MTGOSDK/src/Core/Remoting/RemoteObject.cs @@ -18,7 +18,7 @@ namespace MTGOSDK.Core.Remoting; public class RemoteObject { - private readonly RemoteApp _app; + private readonly RemoteHandle _app; private RemoteObjectRef _ref; private Type _type = null; @@ -26,7 +26,7 @@ public class RemoteObject public ulong RemoteToken => _ref.Token; - internal RemoteObject(RemoteObjectRef reference, RemoteApp remoteApp) + internal RemoteObject(RemoteObjectRef reference, RemoteHandle remoteApp) { _app = remoteApp; _ref = reference; diff --git a/MTGOSDK/src/Core/Security/SecurityExtensions.cs b/MTGOSDK/src/Core/Security/SecurityExtensions.cs index 5e221eb5..cf8bf23e 100644 --- a/MTGOSDK/src/Core/Security/SecurityExtensions.cs +++ b/MTGOSDK/src/Core/Security/SecurityExtensions.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using MTGOSDK.Core.Reflection; +using MTGOSDK.Core.Remoting; namespace MTGOSDK.Core.Security; From 57b9947ae0fbbc6ea574ce9c3460a2a8a310e72a Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:26:46 -0500 Subject: [PATCH 13/20] [MTGOSDK/Core/Remoting/Interop] Use classes for JSON-serialized types --- .../Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs | 2 +- .../src/Core/Remoting/Interop/Interactions/InvocationRequest.cs | 2 +- .../Interop/Interactions/Object/CtorInvocationRequest.cs | 2 +- .../Remoting/Interop/Interactions/Object/FieldGetRequest.cs | 2 +- .../Interop/Interactions/Object/IndexedItemAccessRequest.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs index c2cde46b..482044aa 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Dumps/TypeDumpRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; -public struct TypeDumpRequest +public class TypeDumpRequest { public string Assembly { get; set; } public string TypeFullName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs index 8c719cdc..af0da899 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/InvocationRequest.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions; -public struct InvocationRequest() +public class InvocationRequest { public ulong ObjAddress { get; set; } public string MethodName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs index 45c9365a..60a83ac5 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/CtorInvocationRequest.cs @@ -9,7 +9,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public struct CtorInvocationRequest() +public class CtorInvocationRequest() { public string TypeFullName { get; set; } public List Parameters { get; set; } = new(); diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs index a8189091..ed0d7f28 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldGetRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public struct FieldGetRequest +public class FieldGetRequest { public ulong ObjAddress { get; set; } public string TypeFullName { get; set; } diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs index 3458585c..fc483777 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/IndexedItemAccessRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public struct IndexedItemAccessRequest +public class IndexedItemAccessRequest { public ulong CollectionAddress { get; set; } public bool PinRequest { get; set; } From 15bf88cdfdd7a5d182889655d1c8459151db2b69 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:31:18 -0500 Subject: [PATCH 14/20] Fix missing refactors from f2c05d4 --- .../Remoting/Interop/Interactions/Object/FieldSetRequest.cs | 2 +- examples/BasicBot/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs index 2ef6cefa..7e474d5d 100644 --- a/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs +++ b/MTGOSDK/src/Core/Remoting/Interop/Interactions/Object/FieldSetRequest.cs @@ -7,7 +7,7 @@ namespace MTGOSDK.Core.Remoting.Interop.Interactions.Object; -public struct FieldSetRequest +public class FieldSetRequest { public ulong ObjAddress { get; set; } public string TypeFullName { get; set; } diff --git a/examples/BasicBot/Program.cs b/examples/BasicBot/Program.cs index 893c9935..956216a3 100644 --- a/examples/BasicBot/Program.cs +++ b/examples/BasicBot/Program.cs @@ -6,7 +6,7 @@ using System; using MTGOSDK.API; -using MTGOSDK.Core; +using MTGOSDK.Core.Remoting; using MTGOSDK.Core.Security; From 1b01a88bc5f5884f61e89a569412343e772b179d Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:41:25 -0500 Subject: [PATCH 15/20] [MTGOSDK] Exclude API from ScubaDiver compile --- MTGOSDK/MTGOSDK.csproj | 5 +++++ MTGOSDK/src/API/Interface/WindowUtilities.cs | 4 ---- MTGOSDK/src/Core/Reflection/ProxyObject.cs | 8 ++++---- MTGOSDK/src/Core/Reflection/RemoteProxy.cs | 2 ++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index cbd2ffa8..17f7dd09 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -58,6 +58,11 @@ + + + $(DefaultItemExcludes);src\API\** + + diff --git a/MTGOSDK/src/API/Interface/WindowUtilities.cs b/MTGOSDK/src/API/Interface/WindowUtilities.cs index f7955f73..3204d75f 100644 --- a/MTGOSDK/src/API/Interface/WindowUtilities.cs +++ b/MTGOSDK/src/API/Interface/WindowUtilities.cs @@ -38,9 +38,6 @@ public static class WindowUtilities /// public static ICollection GetWindows() { -#if NETSTANDARD2_0 - throw new PlatformNotSupportedException(); -#else // This is a hack that caches the dispatcher's registered windows. _ = Unbind(s_windowUtilities).AllWindows; _ = s_windowUtilities.AllWindows; @@ -60,7 +57,6 @@ public static ICollection GetWindows() } throw new InvalidOperationException("Failed to get window collection."); -#endif } /// diff --git a/MTGOSDK/src/Core/Reflection/ProxyObject.cs b/MTGOSDK/src/Core/Reflection/ProxyObject.cs index 4d8da61d..1ced8cc3 100644 --- a/MTGOSDK/src/Core/Reflection/ProxyObject.cs +++ b/MTGOSDK/src/Core/Reflection/ProxyObject.cs @@ -40,16 +40,16 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) value = @base.GetType().GetProperty(binder.Name).GetValue(@base); // Get the default value for the return type. -#if !NETSTANDARD2_0 Type returnType = binder.ReturnType; +#if !NETSTANDARD2_0 dynamic typeRef = RuntimeHelpers.GetUninitializedObject(returnType); +#else // 'GetUninitializedObject' is not available in .NET Standard 2.0. + dynamic typeRef = Activator.CreateInstance(returnType); +#endif dynamic typeDefault = typeRef .GetType() .GetConstructor(Type.EmptyTypes) .Invoke(typeRef, null); -#else - dynamic typeDefault = null; -#endif #pragma warning disable CS8601 result = (value != null || value != typeDefault) diff --git a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs index fba2f213..2ae58455 100644 --- a/MTGOSDK/src/Core/Reflection/RemoteProxy.cs +++ b/MTGOSDK/src/Core/Reflection/RemoteProxy.cs @@ -18,6 +18,8 @@ public sealed class RemoteProxy(Func c) : DLRWrapper() where I : class /// #if !NETSTANDARD2_0 internal override Lazy obj => new(() => c.Invoke()); +#else // Avoid co-variant type conversion. + internal override dynamic obj => new Lazy(() => c.Invoke()); #endif private object refLock = new(); From cd114b6d41bb97693f30fa40729d88c6c82378d6 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 30 Mar 2024 23:54:13 -0500 Subject: [PATCH 16/20] [MTGOSDK] Exclude reference assemblies from ScubaDiver builds --- MTGOSDK/MTGOSDK.csproj | 3 ++- MTGOSDK/src/{Core/Reflection => API}/ObjectProvider.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) rename MTGOSDK/src/{Core/Reflection => API}/ObjectProvider.cs (98%) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 17f7dd09..7cf223af 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -67,6 +67,7 @@ - + \ No newline at end of file diff --git a/MTGOSDK/src/Core/Reflection/ObjectProvider.cs b/MTGOSDK/src/API/ObjectProvider.cs similarity index 98% rename from MTGOSDK/src/Core/Reflection/ObjectProvider.cs rename to MTGOSDK/src/API/ObjectProvider.cs index 57a50074..576306de 100644 --- a/MTGOSDK/src/Core/Reflection/ObjectProvider.cs +++ b/MTGOSDK/src/API/ObjectProvider.cs @@ -4,9 +4,10 @@ **/ using MTGOSDK.Core.Remoting; +using MTGOSDK.Core.Reflection; -namespace MTGOSDK.Core.Reflection; +namespace MTGOSDK.API; /// /// Global manager for all singleton objects registered with the client. From 59cfb00fa2ddf5d1bda4630881179229bca1b29d Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sun, 31 Mar 2024 01:31:42 -0500 Subject: [PATCH 17/20] [MTGOSDK] Use netstandard2.0 TFM for core build --- MTGOSDK/MTGOSDK.csproj | 41 +++++++++++------------ MTGOSDK/packages.lock.json | 6 ---- MTGOSDK/src/Core/Remoting/Bootstrapper.cs | 10 +++--- 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 7cf223af..6abead49 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -13,13 +13,17 @@ + + + + Version="1.0.37" + Condition="'$(TargetFramework)' == 'netstandard2.0'" /> - + + + $(DefaultItemExcludes);src\API\** + + + + + + @@ -41,33 +54,19 @@ - + - - - - - + + + + LogicalName="Resources\%(Filename)%(Extension)" /> - - - $(DefaultItemExcludes);src\API\** - - - - - - - - \ No newline at end of file diff --git a/MTGOSDK/packages.lock.json b/MTGOSDK/packages.lock.json index 195304fd..6e021ebd 100644 --- a/MTGOSDK/packages.lock.json +++ b/MTGOSDK/packages.lock.json @@ -238,12 +238,6 @@ "System.Reflection.Emit": "4.7.0" } }, - "Meziantou.Polyfill": { - "type": "Direct", - "requested": "[1.0.37, )", - "resolved": "1.0.37", - "contentHash": "kFlH4Ye5lEK9AjViSWm32JrH3Ee42jd15FNnv4X4fK4JzdSlkMR7mqzsgRCBgZzszWLr0ioIA78dsMNxRoouSw==" - }, "Microsoft.CSharp": { "type": "Direct", "requested": "[4.7.0, )", diff --git a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs index 7015b919..73a0daff 100644 --- a/MTGOSDK/src/Core/Remoting/Bootstrapper.cs +++ b/MTGOSDK/src/Core/Remoting/Bootstrapper.cs @@ -79,21 +79,21 @@ private static void GetInjectionToolkit( remoteNetAppDataDirInfo.Create(); byte[] launcherResource = target.Is64Bit() - ? ExtractResource(@"Resources\Launcher_x64") - : ExtractResource(@"Resources\Launcher"); + ? ExtractResource(@"Resources\Launcher_x64.exe") + : ExtractResource(@"Resources\Launcher.exe"); launcherPath = target.Is64Bit() ? Path.Combine(AppDataDir, "Launcher_x64.exe") : Path.Combine(AppDataDir, "Launcher.exe"); byte[] adapterResource = target.Is64Bit() - ? ExtractResource(@"Resources\Bootstrapper_x64") - : ExtractResource(@"Resources\Bootstrapper"); + ? ExtractResource(@"Resources\Bootstrapper_x64.dll") + : ExtractResource(@"Resources\Bootstrapper.dll"); var adapterPath = target.Is64Bit() ? Path.Combine(AppDataDir, "Bootstrapper_x64.dll") : Path.Combine(AppDataDir, "Bootstrapper.dll"); // Get the .NET diver assembly to inject into the target process - byte[] diverResource = ExtractResource(@"Resources\Microsoft.Diagnostics.Runtime"); + byte[] diverResource = ExtractResource(@"Resources\Microsoft.Diagnostics.Runtime.dll"); diverPath = Path.Combine(AppDataDir, "Microsoft.Diagnostics.Runtime.dll"); // Check if injector or bootstrap resources differ from copies on disk From dff8e99c6564de3bee23374882f07e1db16f4587 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sun, 31 Mar 2024 01:54:07 -0500 Subject: [PATCH 18/20] [third_party/ScubaDiver] Move project directory --- MTGOSDK/MTGOSDK.csproj | 2 +- SDK.sln | 2 +- third_party/{RemoteNET => ScubaDiver}/LICENSE | 0 third_party/{RemoteNET/src => }/ScubaDiver/ScubaDiver.csproj | 0 third_party/{RemoteNET/src => }/ScubaDiver/app.config | 0 third_party/{RemoteNET/src => }/ScubaDiver/packages.lock.json | 0 .../{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Diver.cs | 0 .../{RemoteNET/src/ScubaDiver => ScubaDiver/src}/DllEntry.cs | 0 .../{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Logger.cs | 0 .../ScubaDiver => ScubaDiver/src}/RegisteredEventHandlerInfo.cs | 0 .../src/ScubaDiver => ScubaDiver/src}/Utils/ClrExt.cs | 0 .../src/ScubaDiver => ScubaDiver/src}/Utils/Converter.cs | 0 .../ScubaDiver => ScubaDiver/src}/Utils/FreezeFuncsFactory.cs | 0 .../src}/Utils/FrozenObjectsCollection.cs | 0 .../ScubaDiver => ScubaDiver/src}/Utils/ObjectDumpFactory.cs | 0 .../src/ScubaDiver => ScubaDiver/src}/Utils/Pinnable.cs | 0 .../src/ScubaDiver => ScubaDiver/src}/Utils/SmartLocksDict.cs | 0 .../src/ScubaDiver => ScubaDiver/src}/Utils/UnifiedAppDomain.cs | 0 18 files changed, 2 insertions(+), 2 deletions(-) rename third_party/{RemoteNET => ScubaDiver}/LICENSE (100%) rename third_party/{RemoteNET/src => }/ScubaDiver/ScubaDiver.csproj (100%) rename third_party/{RemoteNET/src => }/ScubaDiver/app.config (100%) rename third_party/{RemoteNET/src => }/ScubaDiver/packages.lock.json (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Diver.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/DllEntry.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Logger.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/RegisteredEventHandlerInfo.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/ClrExt.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/Converter.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/FreezeFuncsFactory.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/FrozenObjectsCollection.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/ObjectDumpFactory.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/Pinnable.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/SmartLocksDict.cs (100%) rename third_party/{RemoteNET/src/ScubaDiver => ScubaDiver/src}/Utils/UnifiedAppDomain.cs (100%) diff --git a/MTGOSDK/MTGOSDK.csproj b/MTGOSDK/MTGOSDK.csproj index 6abead49..c8fafee4 100644 --- a/MTGOSDK/MTGOSDK.csproj +++ b/MTGOSDK/MTGOSDK.csproj @@ -45,7 +45,7 @@ BeforeTargets="ResolveProjectReferences" Condition="'$(TargetFramework)' != 'netstandard2.0'"> - + Date: Sun, 31 Mar 2024 02:04:40 -0500 Subject: [PATCH 19/20] [third_party/ScubaDiver] Fix project relative paths --- third_party/ScubaDiver/ScubaDiver.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/ScubaDiver/ScubaDiver.csproj b/third_party/ScubaDiver/ScubaDiver.csproj index 5b5edd23..39151847 100644 --- a/third_party/ScubaDiver/ScubaDiver.csproj +++ b/third_party/ScubaDiver/ScubaDiver.csproj @@ -26,8 +26,8 @@ - - + + From 10974018580d66c6604427d88d6744c29882b564 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sun, 31 Mar 2024 02:17:57 -0500 Subject: [PATCH 20/20] [third_party/ScubaDiver] Add SPDX license headers --- third_party/ScubaDiver/LICENSE | 1 - third_party/ScubaDiver/src/Diver.cs | 7 +++++ third_party/ScubaDiver/src/DllEntry.cs | 8 +++++- third_party/ScubaDiver/src/Logger.cs | 8 +++++- .../src/RegisteredEventHandlerInfo.cs | 10 +++++-- third_party/ScubaDiver/src/Utils/ClrExt.cs | 27 ++++++++++++------ third_party/ScubaDiver/src/Utils/Converter.cs | 8 +++++- .../src/Utils/FreezeFuncsFactory.cs | 16 +++++++---- .../src/Utils/FrozenObjectsCollection.cs | 25 ++++++++--------- .../ScubaDiver/src/Utils/ObjectDumpFactory.cs | 8 +++++- third_party/ScubaDiver/src/Utils/Pinnable.cs | 8 +++++- .../ScubaDiver/src/Utils/SmartLocksDict.cs | 28 +++++++++++-------- .../ScubaDiver/src/Utils/UnifiedAppDomain.cs | 25 +++++++---------- 13 files changed, 117 insertions(+), 62 deletions(-) diff --git a/third_party/ScubaDiver/LICENSE b/third_party/ScubaDiver/LICENSE index 501c6b0b..4947679d 100644 --- a/third_party/ScubaDiver/LICENSE +++ b/third_party/ScubaDiver/LICENSE @@ -1,7 +1,6 @@ MIT License Copyright (c) 2021, Xappy -Copyright (C) 2023, Cory Bennett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/third_party/ScubaDiver/src/Diver.cs b/third_party/ScubaDiver/src/Diver.cs index 1eef2fbb..c00a8921 100644 --- a/third_party/ScubaDiver/src/Diver.cs +++ b/third_party/ScubaDiver/src/Diver.cs @@ -1,3 +1,9 @@ +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + using System; using System.Collections; using System.Collections.Concurrent; @@ -26,6 +32,7 @@ using MTGOSDK.Core.Remoting.Interop.Interactions.Dumps; using MTGOSDK.Core.Remoting.Interop.Interactions.Object; using MTGOSDK.Core.Remoting.Interop.Utils; + using ScubaDiver.Utils; diff --git a/third_party/ScubaDiver/src/DllEntry.cs b/third_party/ScubaDiver/src/DllEntry.cs index e1e8bb8a..90c8e936 100644 --- a/third_party/ScubaDiver/src/DllEntry.cs +++ b/third_party/ScubaDiver/src/DllEntry.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Threading; diff --git a/third_party/ScubaDiver/src/Logger.cs b/third_party/ScubaDiver/src/Logger.cs index 78686402..b6a5dcb1 100644 --- a/third_party/ScubaDiver/src/Logger.cs +++ b/third_party/ScubaDiver/src/Logger.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Diagnostics; diff --git a/third_party/ScubaDiver/src/RegisteredEventHandlerInfo.cs b/third_party/ScubaDiver/src/RegisteredEventHandlerInfo.cs index 16534b84..bc950786 100644 --- a/third_party/ScubaDiver/src/RegisteredEventHandlerInfo.cs +++ b/third_party/ScubaDiver/src/RegisteredEventHandlerInfo.cs @@ -1,11 +1,17 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Net; using System.Reflection; namespace ScubaDiver; -public class RegisteredEventHandlerInfo +public class RegisteredEventHandlerInfo { /// /// Event handler that was registered on the event diff --git a/third_party/ScubaDiver/src/Utils/ClrExt.cs b/third_party/ScubaDiver/src/Utils/ClrExt.cs index b1a42726..ba5f5a08 100644 --- a/third_party/ScubaDiver/src/Utils/ClrExt.cs +++ b/third_party/ScubaDiver/src/Utils/ClrExt.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections; using System.Collections.Generic; using Microsoft.Diagnostics.Runtime; @@ -6,6 +12,13 @@ namespace ScubaDiver; + +public struct TypeDefToMethod +{ + public ulong MethodTable { get; set; } + public int Token { get; set; } +} + public static class ClrExt { public static byte[] ToByteArray(this ClrArray arr) @@ -16,7 +29,6 @@ public static byte[] ToByteArray(this ClrArray arr) } catch (Exception ex) { - // ??? throw new ArgumentException("Not a byte array", ex); } @@ -25,6 +37,7 @@ public static byte[] ToByteArray(this ClrArray arr) { res[i] = arr.GetValue(i); } + return res; } @@ -33,12 +46,6 @@ public static byte[] ToByteArray(this ClrObject obj) return obj.AsArray().ToByteArray(); } - - public class TypeDefToMethod - { - public ulong MethodTable { get; set; } - public int Token { get; set; } - } public static IEnumerable EnumerateTypeDefToMethodTableMap(this ClrModule mod) { // EnumerateTypeDefToMethodTableMap wants to return an IEnumerable<(ulong,int)> @@ -46,12 +53,14 @@ public static IEnumerable EnumerateTypeDefToMethodTableMap(this IEnumerable unresolvedEnumerable = typeof(ClrModule) .GetMethod("EnumerateTypeDefToMethodTableMap") .Invoke(mod, new object[0]) as IEnumerable; + foreach (object o in unresolvedEnumerable) { var type = o.GetType(); ulong mt = (ulong)type.GetField("Item1").GetValue(o); int token = (int)type.GetField("Item2").GetValue(o); + yield return new TypeDefToMethod() { MethodTable = mt, Token = token }; } } -} \ No newline at end of file +} diff --git a/third_party/ScubaDiver/src/Utils/Converter.cs b/third_party/ScubaDiver/src/Utils/Converter.cs index 73afebd8..255c6ab7 100644 --- a/third_party/ScubaDiver/src/Utils/Converter.cs +++ b/third_party/ScubaDiver/src/Utils/Converter.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Reflection.Emit; using MTGOSDK.Core.Remoting.Interop.Extensions; diff --git a/third_party/ScubaDiver/src/Utils/FreezeFuncsFactory.cs b/third_party/ScubaDiver/src/Utils/FreezeFuncsFactory.cs index ad3d517e..efacdae2 100644 --- a/third_party/ScubaDiver/src/Utils/FreezeFuncsFactory.cs +++ b/third_party/ScubaDiver/src/Utils/FreezeFuncsFactory.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Reflection.Emit; using System.Runtime.CompilerServices; @@ -35,10 +41,10 @@ private static FreezeFunc GenerateInternal(int numArguments) typeof(void), new[] { - typeof(object[]), // objs - typeof(ulong[]), // addr_param + typeof(object[]), // objs + typeof(ulong[]), // addr_param typeof(ManualResetEvent), // frozenFeedback - typeof(ManualResetEvent) // unfreezeRequested + typeof(ManualResetEvent) // unfreezeRequested }, typeof(FreezeFuncsFactory) ); @@ -111,7 +117,7 @@ private static FreezeFunc GenerateInternal(int numArguments) // 🠗 // [ Method Table ][ Field 1 ][ Field 2 ]... // - // And we want: + // And we want: // 🠗 // [ Method Table ][ Field 1 ][ Field 2 ]... // diff --git a/third_party/ScubaDiver/src/Utils/FrozenObjectsCollection.cs b/third_party/ScubaDiver/src/Utils/FrozenObjectsCollection.cs index 75346961..214d9194 100644 --- a/third_party/ScubaDiver/src/Utils/FrozenObjectsCollection.cs +++ b/third_party/ScubaDiver/src/Utils/FrozenObjectsCollection.cs @@ -1,4 +1,10 @@ -using System.Collections.Generic; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -8,19 +14,10 @@ namespace ScubaDiver; public class FrozenObjectsCollection { - private object _lock; - Dictionary _frozenObjects; - private Task _freezerTask; - private ManualResetEvent _unfreezeRequested; - - - public FrozenObjectsCollection() - { - _lock = new object(); - _frozenObjects = new Dictionary(); - _freezerTask = null; - _unfreezeRequested = null; - } + private object _lock = new object(); + private Dictionary _frozenObjects = new(); + private Task _freezerTask = null!; + private ManualResetEvent _unfreezeRequested = null!; /// /// Return the address where an object is pinned, otherwise returns false. diff --git a/third_party/ScubaDiver/src/Utils/ObjectDumpFactory.cs b/third_party/ScubaDiver/src/Utils/ObjectDumpFactory.cs index 71dd09a9..bf203a3c 100644 --- a/third_party/ScubaDiver/src/Utils/ObjectDumpFactory.cs +++ b/third_party/ScubaDiver/src/Utils/ObjectDumpFactory.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/third_party/ScubaDiver/src/Utils/Pinnable.cs b/third_party/ScubaDiver/src/Utils/Pinnable.cs index 388daa57..d72f77d4 100644 --- a/third_party/ScubaDiver/src/Utils/Pinnable.cs +++ b/third_party/ScubaDiver/src/Utils/Pinnable.cs @@ -1,4 +1,10 @@ -using System.Runtime.InteropServices; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System.Runtime.InteropServices; namespace ScubaDiver; diff --git a/third_party/ScubaDiver/src/Utils/SmartLocksDict.cs b/third_party/ScubaDiver/src/Utils/SmartLocksDict.cs index 129d1da1..54ab7d26 100644 --- a/third_party/ScubaDiver/src/Utils/SmartLocksDict.cs +++ b/third_party/ScubaDiver/src/Utils/SmartLocksDict.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; @@ -16,13 +22,13 @@ public class SmartLocksDict { private ConcurrentDictionary _threadStates = new(); - public class Entry + public struct LockEntry() { public object _lock = new(); public HashSet _holdersThreadIDs = new(); } - private ConcurrentDictionary _dict = new(); + private ConcurrentDictionary _dict = new(); [Flags] public enum SmartLockThreadState @@ -51,7 +57,7 @@ public void SetSpecialThreadState(int tid, SmartLockThreadState state) } } - public void Add(T item) => _dict.TryAdd(item, new Entry()); + public void Add(T item) => _dict.TryAdd(item, new LockEntry()); public void Remove(T item) => _dict.TryRemove(item, out _); @@ -77,19 +83,19 @@ public AcquireResults Acquire(T item) } } - if (!_dict.TryGetValue(item, out Entry entry)) + if (!_dict.TryGetValue(item, out LockEntry LockEntry)) return AcquireResults.NoSuchItem; AcquireResults result; - lock (entry._lock) + lock (LockEntry._lock) { - if (entry._holdersThreadIDs.Contains(currentThreadId)) + if (LockEntry._holdersThreadIDs.Contains(currentThreadId)) { result = AcquireResults.AlreadyAcquireByCurrentThread; } else { - entry._holdersThreadIDs.Add(currentThreadId); + LockEntry._holdersThreadIDs.Add(currentThreadId); result = AcquireResults.Acquired; } } @@ -99,13 +105,13 @@ public AcquireResults Acquire(T item) public void Release(T item) { - if (!_dict.TryGetValue(item, out Entry entry)) + if (!_dict.TryGetValue(item, out LockEntry LockEntry)) return; - lock (entry._lock) + lock (LockEntry._lock) { int currentThreadId = Thread.CurrentThread.ManagedThreadId; - entry._holdersThreadIDs.Remove(currentThreadId); + LockEntry._holdersThreadIDs.Remove(currentThreadId); } } } diff --git a/third_party/ScubaDiver/src/Utils/UnifiedAppDomain.cs b/third_party/ScubaDiver/src/Utils/UnifiedAppDomain.cs index 2aef0f4e..752f9998 100644 --- a/third_party/ScubaDiver/src/Utils/UnifiedAppDomain.cs +++ b/third_party/ScubaDiver/src/Utils/UnifiedAppDomain.cs @@ -1,4 +1,10 @@ -using System; +/** @file + Copyright (c) 2021, Xappy. + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 and MIT +**/ + +using System; using System.Linq; using System.Reflection; @@ -8,19 +14,8 @@ namespace ScubaDiver.Utils; /// /// Encapsulates access to all AppDomains in the process /// -public class UnifiedAppDomain +public class UnifiedAppDomain(Diver parentDiver) { - private readonly Diver _parentDiver; - - /// - /// Parent diver, which is currently running in the app - /// - /// - public UnifiedAppDomain(Diver parentDiver) - { - _parentDiver = parentDiver; - } - private AppDomain[] _domains = new[] { AppDomain.CurrentDomain }; public AppDomain[] GetDomains() @@ -30,7 +25,7 @@ public AppDomain[] GetDomains() // Using Diver's heap searching abilities to locate all 'System.AppDomain' try { - (bool anyErrors, var candidates) = _parentDiver + (bool anyErrors, var candidates) = parentDiver .GetHeapObjects(heapObjType => heapObjType == typeof(AppDomain).FullName, true); @@ -41,7 +36,7 @@ public AppDomain[] GetDomains() _domains = candidates .Select(cand => - _parentDiver + parentDiver .GetObject(cand.Address, false, cand.Type, cand.HashCode) .instance) .Cast().ToArray();