Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ScubaDiver project #14

Merged
merged 11 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
<_MTGOSDKCorePath>$(SolutionDir)\MTGOSDK\bin\$(Configuration)\$(_MTGOSDKCoreTFM)</_MTGOSDKCorePath>
</PropertyGroup>

<!-- Debugging Options -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>

<!-- Continuous Integration -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
Expand Down
2 changes: 2 additions & 0 deletions Directory.Packages.Props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<!-- MTGOSDK -->
<PackageVersion Include="Microsoft.CSharp"
Version="4.7.0" />
<PackageVersion Include="System.Reflection.Emit.Lightweight"
Version="4.7.0" />
<PackageVersion Include="Microsoft.Diagnostics.Runtime"
Version="3.1.512801" />
<PackageVersion Include="ImpromptuInterface"
Expand Down
23 changes: 12 additions & 11 deletions MTGOSDK.MSBuild/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -613,17 +613,6 @@
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Emit.Lightweight": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Reflection.Extensions": {
"type": "Transitive",
"resolved": "4.3.0",
Expand Down Expand Up @@ -1124,6 +1113,18 @@
"System.Security.Principal.Windows": "5.0.0"
}
},
"System.Reflection.Emit.Lightweight": {
"type": "CentralTransitive",
"requested": "[4.7.0, )",
"resolved": "4.3.0",
"contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
"dependencies": {
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
Expand Down
34 changes: 34 additions & 0 deletions MTGOSDK.Win32/src/API/Kernel32/ProcessShapshot/PssFreeSnapshot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/** @file
Copyright (c) 2024, Cory Bennett. All rights reserved.
SPDX-License-Identifier: Apache-2.0
**/

using System;
using System.Runtime.InteropServices;


namespace MTGOSDK.Win32.API;

public static partial class Kernel32
{
/// <summary>
/// Frees a snapshot of the address space of a process.
/// </summary>
[DllImport("kernel32")] // SetLastError=true ?
public static extern int PssFreeSnapshot(
/// <summary>
/// A handle to the process that contains the snapshot.
/// </summary>
/// <remarks>
/// The handle must have the PROCESS_VM_READ, PROCESS_VM_OPERATION,
/// and PROCESS_DUP_HANDLE rights. If the snapshot was captured from the
/// current process, or duplicated into the current process, then pass in
/// the result of <see cref="GetCurrentProcess"/>.
/// </remarks>
[In] IntPtr ProcessHandle,
/// <summary>
/// A handle to the snapshot to be freed.
/// </summary>
[In] IntPtr SnapshotHandle
);
}
9 changes: 6 additions & 3 deletions MTGOSDK/MTGOSDK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);
<!-- Disables unenforcable nullable warnings - breaks static analysis -->
CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;CS8767;CS9113;IDE0065;
CS8597;CS8600;CS8602;CS8603;CS8604;CS8625;CS8629;CS8767;CS9113;IDE0065;
<!-- Disable warnings for incompatible TFMs required for building -->
NU1702;MSB3277;
<!-- FIXME: From RemoteNET library -->
CS8601;CS8608;CS8610;CS8618;CS8619;CS8620;CS8765;
CS8601;CS8605;CS8608;CS8610;CS8618;CS8619;CS8620;CS8765;
</NoWarn>
<!-- Allows access to raw pointers for performance-critical IL building -->
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<!-- Import MTGOSDK package properties -->
Expand All @@ -23,7 +25,8 @@
Condition="'$(TargetFramework)' != '$(_MTGOSDKCoreTFM)'" />

<ItemGroup>
<PackageReference Include="Microsoft.CSharp" />
<PackageReference Include="Microsoft.CSharp" />
<PackageReference Include="System.Reflection.Emit.Lightweight" />
<PackageReference Include="Microsoft.Diagnostics.Runtime" />
<PackageReference Include="ImpromptuInterface" />
<PackageReference Include="Newtonsoft.Json" />
Expand Down
15 changes: 15 additions & 0 deletions MTGOSDK/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"System.Reflection.Emit.Lightweight": {
"type": "Direct",
"requested": "[4.7.0, )",
"resolved": "4.7.0",
"contentHash": "a4OLB4IITxAXJeV74MDx49Oq2+PsF6Sml54XAFv+2RyWwtDBcabzoxiiJRhdhx+gaohLh4hEGCLQyBozXoQPqA==",
"dependencies": {
"System.Reflection.Emit.ILGeneration": "4.7.0"
}
},
"Dynamitey": {
"type": "Transitive",
"resolved": "3.0.3",
Expand Down Expand Up @@ -394,6 +403,12 @@
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"System.Reflection.Emit.Lightweight": {
"type": "Direct",
"requested": "[4.7.0, )",
"resolved": "4.7.0",
"contentHash": "a4OLB4IITxAXJeV74MDx49Oq2+PsF6Sml54XAFv+2RyWwtDBcabzoxiiJRhdhx+gaohLh4hEGCLQyBozXoQPqA=="
},
"Dynamitey": {
"type": "Transitive",
"resolved": "3.0.3",
Expand Down
2 changes: 2 additions & 0 deletions MTGOSDK/src/Core/Reflection/DLRWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

using System.Collections.Concurrent;

using MTGOSDK.Core.Remoting;


namespace MTGOSDK.Core.Reflection;
using static Attributes;
Expand Down
107 changes: 107 additions & 0 deletions MTGOSDK/src/Core/Reflection/Emit/Converter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/** @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;


namespace MTGOSDK.Core.Reflection.Emit;

/// <summary>
/// A class that converts an IntPtr to an object reference.
/// </summary>
public class Converter<T>
{
/// <summary>
/// The delegate that converts an IntPtr to an object reference.
/// </summary>
delegate U Void2ObjectConverter<U>(IntPtr pManagedObject);

/// <summary>
/// The converter instance that converts an IntPtr to an object reference.
/// </summary>
private static Void2ObjectConverter<T> myConverter;

static Converter()
{
//
// The type initializer is run every time the converter is instantiated
// using a different generic argument.
//
GenerateDynamicMethod();
}

/// <summary>
/// Generates a dynamic method that converts an IntPtr to an object reference.
/// </summary>
/// <remarks>
/// The dynamic method trick is discussed 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
/// </remarks>
static void GenerateDynamicMethod()
{
if (myConverter == null)
{
DynamicMethod method = new("ConvertPtrToObjReference",
typeof(T),
new Type[] { typeof(IntPtr) },
typeof(IntPtr),
true);
var gen = method.GetILGenerator();
// 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 IL Verification disabled.
gen.Emit(OpCodes.Ret);
myConverter = (Void2ObjectConverter<T>)method
.CreateDelegate(typeof(Void2ObjectConverter<T>));
}
}

/// <summary>
/// Handles the conversion of an IntPtr to an object reference.
/// </summary>
/// <param name="pObj">The IntPtr to convert.</param>
/// <param name="expectedMethodTable">The expected method table of the object.</param>
/// <returns>The object reference.</returns>
/// <exception cref="ArgumentException">
/// Thrown when the actual method table value is not as expected.
/// </exception>
/// <remarks>
/// This methods reads the method table of the object to make sure we aren't
/// mistakenly pointing at another type by now (could be caused by the GC).
/// </remarks>
public T ConvertFromIntPtr(IntPtr pObj, IntPtr expectedMethodTable)
{
IntPtr actualMethodTable = pObj.GetMethodTable();
if (actualMethodTable != expectedMethodTable)
{
throw new ArgumentException("Actual Method Table value was not as expected");
}
return myConverter(pObj);
}

/// <summary>
/// Handles the conversion of an IntPtr to an object reference.
/// </summary>
/// <param name="pObj">The IntPtr to convert.</param>
/// <param name="expectedMethodTable">The expected method table of the object.</param>
/// <returns>The object reference.</returns>
/// <exception cref="ArgumentException">
/// Thrown when the actual method table value is not as expected.
/// </exception>
/// <remarks>
/// This methods reads the method table of the object to make sure we aren't
/// mistakenly pointing at another type by now (could be caused by the GC).
/// </remarks>
public T ConvertFromIntPtr(ulong pObj, ulong expectedMethodTable) =>
ConvertFromIntPtr(
new IntPtr((long) pObj),
new IntPtr((long) expectedMethodTable));
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using System.Threading;


namespace ScubaDiver;
namespace MTGOSDK.Core.Reflection.Emit;

public static class FreezeFuncsFactory
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using System.Threading.Tasks;


namespace ScubaDiver;
namespace MTGOSDK.Core.Reflection.Emit;

public class FrozenObjectsCollection
{
Expand Down Expand Up @@ -81,13 +81,13 @@ public ulong Pin(object o)
object[] objs = _frozenObjects.Keys.Concat(new object[] { o }).ToArray();
PinInternal(objs);

Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Pinned another object. Num Pinned: {_frozenObjects.Count}");
// Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Pinned another object. Num Pinned: {_frozenObjects.Count}");

return _frozenObjects[o];
}
}

public bool TryGetPinnedObject(ulong addr, out object o)
public bool TryGetPinnedObject(ulong addr, out object? o)
{
lock (_lock)
{
Expand Down Expand Up @@ -118,15 +118,16 @@ public bool Unpin(ulong objAddress)
.Select(kvp => kvp.Key)
.ToArray();

// Making sure that adress was even in the dictionary.
// Making sure that address was even in the dictionary.
// Otherwise, we don't need to re-pin all objects.
Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Unpinning another object. New Num Pinned: {objs.Length}");
// Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Unpinning another object. New Num Pinned: {objs.Length}");
if (objs.Length == _frozenObjects.Count)
return false;

// Re-pin all objects
PinInternal(objs);

Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Unpinned another object. Final Num Pinned: {_frozenObjects.Count}");
// Logger.Debug($"[{nameof(FrozenObjectsCollection)}] Unpinned another object. Final Num Pinned: {_frozenObjects.Count}");
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Runtime.InteropServices;


namespace ScubaDiver;
namespace MTGOSDK.Core.Reflection.Emit;

/// <summary>
/// This class is used to make arbitrary objects "Pinnable" in the .NET
Expand Down
25 changes: 25 additions & 0 deletions MTGOSDK/src/Core/Reflection/EventWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** @file
Copyright (c) 2024, Cory Bennett. All rights reserved.
SPDX-License-Identifier: Apache-2.0
**/

using System;


namespace MTGOSDK.Core.Reflection;

/// <summary>
/// Wraps a generic method to be used as an event handler for subscription.
/// </summary>
/// <typeparam name="T">The type of the event arguments.</typeparam>
/// <param name="handler">The method to be wrapped.</param>
public class EventWrapper<T>(EventHandler handler) where T : EventArgs
{
/// <summary>
/// The handler method to be invoked when the event is raised.
/// </summary>
public void Handle(object sender, T args)
{
handler.Invoke(sender, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@
using Microsoft.Diagnostics.Runtime;


namespace ScubaDiver;


public struct TypeDefToMethod
{
public ulong MethodTable { get; set; }
public int Token { get; set; }
}
namespace MTGOSDK.Core.Reflection.Snapshot;

public static class ClrExt
{
public struct TypeDefToMethod
{
public ulong MethodTable { get; set; }
public int Token { get; set; }
}

public static byte[] ToByteArray(this ClrArray arr)
{
try
Expand Down
Loading
Loading