Skip to content

Commit

Permalink
Changed: API Moved from IntPtr to nuint for addresses.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sewer56 committed Jun 18, 2022
1 parent 11b672d commit 6e8d5da
Show file tree
Hide file tree
Showing 33 changed files with 329 additions and 175 deletions.
2 changes: 1 addition & 1 deletion Source/Reloaded.Memory.Benchmark/Memory/StructGetBytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public byte[] GetBytesOldFn<T>(ref T item, bool marshalElement = false)

fixed (byte* arrayPtr = array)
{
Reloaded.Memory.Struct.ToPtr((IntPtr)arrayPtr, ref item, Memory.Write, marshalElement);
Reloaded.Memory.Struct.ToPtr((nuint)arrayPtr, ref item, Memory.Write, marshalElement);
}

return array;
Expand Down
20 changes: 10 additions & 10 deletions Source/Reloaded.Memory.Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static void Main(string[] args)
var memory = Sources.Memory.CurrentProcess; // Static/Preinitialized access to current process' memory.

// Tutorial 0: Allocate/Free Memory
IntPtr memoryLocation = memory.Allocate(65535); // Did you think it would be harder?
nuint memoryLocation = memory.Allocate(65535); // Did you think it would be harder?
// Here's 65535 bytes at memoryLocation.
// You would free it with memory.Free(memoryLocation);

Expand Down Expand Up @@ -57,7 +57,7 @@ static void Main(string[] args)
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void PrimitivesExample(Sources.Memory memory, IntPtr memoryLocation)
private static void PrimitivesExample(Sources.Memory memory, nuint memoryLocation)
{
// You can use the Memory Option to write any arbitrary generic primitive to memory.
// Here is an example:
Expand Down Expand Up @@ -96,7 +96,7 @@ private static void PrimitivesExample(Sources.Memory memory, IntPtr memoryLocati
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void WriteStructsExample(IMemory memory, IntPtr memoryLocation)
private static void WriteStructsExample(IMemory memory, nuint memoryLocation)
{
// Note: Vector3 is just a struct composed of 3 floats.
// Writing structs is no different to writing primitives; at all.
Expand All @@ -112,7 +112,7 @@ private static void WriteStructsExample(IMemory memory, IntPtr memoryLocation)
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void MemorySourceExample(IMemory memory, IntPtr memoryLocation)
private static void MemorySourceExample(IMemory memory, nuint memoryLocation)
{
// Earlier in the program; we have been writing generics to the program's memory using the 'Memory' class
// implementing the IMemory interface. Well... that isn't the only stock class that implements this interface.
Expand Down Expand Up @@ -145,7 +145,7 @@ private static void MemorySourceExample(IMemory memory, IntPtr memoryLocation)
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void StructArrayExample(IMemory memory, IntPtr memoryLocation)
private static void StructArrayExample(IMemory memory, nuint memoryLocation)
{
// Let's load a binary file from the disk and write it to memory.
const int itemCount = 40; // Number of items in struct array (known).
Expand All @@ -157,19 +157,19 @@ private static void StructArrayExample(IMemory memory, IntPtr memoryLocation)
memory.Write(memoryLocation, adventurePhysicsData);

// Pointer to array in memory. Provides enhanced functionality over a standard pointer.
var adventurePhysics = new ArrayPtr<AdventurePhysics>((ulong)memoryLocation);
var adventurePhysics = new ArrayPtr<AdventurePhysics>(memoryLocation);
adventurePhysics.Get(out AdventurePhysics value, 0); // And of course read/writes work..
// Uh? Yeah, for performance the indexer is not overwritten.
float speedCap = value.HorizontalSpeedCap;

// Pointer to array in memory with known length. Provides even extra functionality. (Like foreach, LINQ)
var adventurePhysicsFixed = new FixedArrayPtr<AdventurePhysics>((ulong)memoryLocation, itemCount);
var adventurePhysicsFixed = new FixedArrayPtr<AdventurePhysics>(memoryLocation, itemCount);
float averageAirAcceleration = adventurePhysicsFixed.Average(physics => physics.AirAcceleration); // LINQ

// All of these classes support read/writes from arbitrary memory of course...
// this is where `IMemory` comes in after all.
IMemory anotherProcessMemory = new ExternalMemory(Process.GetCurrentProcess());
var physicsFixedOtherProcess = new FixedArrayPtr<AdventurePhysics>((ulong)memoryLocation, itemCount, false, anotherProcessMemory);
var physicsFixedOtherProcess = new FixedArrayPtr<AdventurePhysics>(memoryLocation, itemCount, false, anotherProcessMemory);
float averageAirAcceleration2 = physicsFixedOtherProcess.Average(physics => physics.AirAcceleration);

// What you just witnessed was LINQ over arbitrary structs inside memory of another process.
Expand All @@ -195,7 +195,7 @@ private static void StructArrayExample(IMemory memory, IntPtr memoryLocation)
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void MarshallingExample(IMemory memory, IntPtr memoryLocation)
private static void MarshallingExample(IMemory memory, nuint memoryLocation)
{
// Marshalling is yet another feature that is supported when reading and writing from ANY IMemory source.
// Consequently; this also means that classes based on IMemory - such as ArrayPtr or FixedArrayPtr support it under the hood.
Expand All @@ -217,7 +217,7 @@ private static void MarshallingExample(IMemory memory, IntPtr memoryLocation)
/// </summary>
/// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param>
/// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param>
private static void StructUtilityExample(IMemory memory, IntPtr memoryLocation)
private static void StructUtilityExample(IMemory memory, nuint memoryLocation)
{
// Under the hood; the IMemory implementations may use a certain struct utility classes known as Struct
// and StructArray which provide various methods for struct conversions and general work with structs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
66 changes: 66 additions & 0 deletions Source/Reloaded.Memory.Tests.x86/LargeAddressAwareTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Runtime.InteropServices;
using Xunit;

namespace Reloaded.Memory.Tests.x86
{
public class LargeAddressAwareTests
{
// TODO: Bring a new version of Reloaded.Memory.Buffers in.
// once we make it large address aware using this latest Memory patch.

#region P/Invoke
void AssertLargeAddressAware()
{
var maxAddress = GetMaxAddress();
if ((long)maxAddress <= int.MaxValue)
Assert.False(true, "Test host is not large address aware!!");
}

/// <summary>
/// Contains information about the current computer system. This includes the architecture and type of the processor, the number of
/// processors in the system, the page size, and other such information.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct SYSTEM_INFO
{
public int wProcessorArchitecture;
public ushort wReserved;
public uint dwPageSize;
public nuint lpMinimumApplicationAddress;
public nuint lpMaximumApplicationAddress;
public UIntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort wProcessorLevel;
public ushort wProcessorRevision;
}

/// <summary>
/// <para>Retrieves information about the current system.</para>
/// <para>To retrieve accurate information for an application running on WOW64, call the <c>GetNativeSystemInfo</c> function.</para>
/// </summary>
/// <param name="lpSystemInfo">A pointer to a <c>SYSTEM_INFO</c> structure that receives the information.</param>
/// <returns>This function does not return a value.</returns>
[DllImport("kernel32.dll")]
public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);

/// <summary>
/// Returns the max addressable address of the process sitting behind the <see cref="MemoryBufferHelper"/>.
/// </summary>
private nuint GetMaxAddress()
{
// Is this Windows on Windows 64? (x86 app running on x64 Windows)
GetSystemInfo(out SYSTEM_INFO systemInfo);
long maxAddress = 0x7FFFFFFF;

// Check for large address aware
if (IntPtr.Size == 4 && (uint)systemInfo.lpMaximumApplicationAddress > maxAddress)
maxAddress = (uint)systemInfo.lpMaximumApplicationAddress;

return (nuint)maxAddress;
}
#endregion
}
}
80 changes: 80 additions & 0 deletions Source/Reloaded.Memory.Tests.x86/Reloaded.Memory.Tests.x86.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Reloaded.Memory.Tests\Memory\Endian.cs" Link="AnyCPU\Endian.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Helpers\IArrayPtrGenerator.cs" Link="AnyCPU\Helpers\IArrayPtrGenerator.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Helpers\IMemoryTools.cs" Link="AnyCPU\Helpers\IMemoryTools.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Interop\Pinnable.cs" Link="AnyCPU\Interop\Pinnable.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Interop\PinnableDisposable.cs" Link="AnyCPU\Interop\PinnableDisposable.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\BlittablePointer.cs" Link="AnyCPU\Pointers\BlittablePointer.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\FixedArrayPtr.cs" Link="AnyCPU\Pointers\FixedArrayPtr.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\IArrayPtr.cs" Link="AnyCPU\Pointers\IArrayPtr.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\Pointer.cs" Link="AnyCPU\Pointers\Pointer.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\RefArrayPtr.cs" Link="AnyCPU\Pointers\RefArrayPtr.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\RefFixedArrayPtr.cs" Link="AnyCPU\Pointers\RefFixedArrayPtr.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Pointers\RefPointer.cs" Link="AnyCPU\Pointers\RefPointer.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Sources\ExternalMemory.cs" Link="AnyCPU\Sources\ExternalMemory.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Sources\IMemory.cs" Link="AnyCPU\Sources\IMemory.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Sources\MemoryExtensions.cs" Link="AnyCPU\Sources\MemoryExtensions.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Streams\BigEndianBufferedStreamReader.cs" Link="AnyCPU\Streams\BigEndianBufferedStreamReader.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Streams\BigEndianExtendedMemoryStream.cs" Link="AnyCPU\Streams\BigEndianExtendedMemoryStream.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Streams\BufferedStreamReader.cs" Link="AnyCPU\Streams\BufferedStreamReader.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\Streams\ExtendedMemoryStream.cs" Link="AnyCPU\Streams\ExtendedMemoryStream.cs" />
<Compile Include="..\Reloaded.Memory.Tests\Memory\StructArray.cs" Link="AnyCPU\StructArray.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.5.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Reloaded.Memory.Shared\Reloaded.Memory.Shared.csproj" />
<ProjectReference Include="..\Reloaded.Memory\Reloaded.Memory.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="AnyCPU\Helpers\" />
<Folder Include="AnyCPU\Interop\" />
<Folder Include="AnyCPU\Utilities\" />
<Folder Include="AnyCPU\Streams\" />
<Folder Include="AnyCPU\Sources\" />
<Folder Include="AnyCPU\Pointers\" />
<Folder Include="Properties\" />
</ItemGroup>

<ItemGroup>
<None Include="..\Reloaded.Memory.Tests\HelloWorld.exe" Link="HelloWorld.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\Reloaded.Memory.Tests\phys.bin" Link="phys.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<None Update="HelloWorld.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="phys.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp90</s:String></wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Reloaded.Memory.Tests.Memory.Helpers
public class IArrayPtrGenerator : IEnumerable<object[]>, IDisposable
{
public static Reloaded.Memory.Sources.Memory CurrentProcess = Reloaded.Memory.Sources.Memory.CurrentProcess;
public static IntPtr AdventurePhysicsArray;
public static nuint AdventurePhysicsArray;

/// <summary>
/// The amount of elements in phys.bin. When we go test <see cref="StructArray"/>, we will test for autodetection of this value.
Expand All @@ -32,8 +32,8 @@ public IArrayPtrGenerator()

_data = new List<object[]>
{
new object[] { new Reloaded.Memory.Pointers.ArrayPtr <AdventurePhysics>((ulong) AdventurePhysicsArray, false, CurrentProcess) },
new object[] { new Reloaded.Memory.Pointers.FixedArrayPtr<AdventurePhysics>((ulong) AdventurePhysicsArray, 10, false, CurrentProcess) }
new object[] { new Reloaded.Memory.Pointers.ArrayPtr <AdventurePhysics>(AdventurePhysicsArray, false, CurrentProcess) },
new object[] { new Reloaded.Memory.Pointers.FixedArrayPtr<AdventurePhysics>(AdventurePhysicsArray, 10, false, CurrentProcess) }
};
}

Expand Down
14 changes: 7 additions & 7 deletions Source/Reloaded.Memory.Tests/Memory/Pointers/FixedArrayPtr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Reloaded.Memory.Tests.Memory.Pointers
public class FixedArrayPtr : IDisposable
{
Reloaded.Memory.Sources.Memory _currentProcess;
IntPtr _adventurePhysicsArray;
nuint _adventurePhysicsArray;
FixedArrayPtr<AdventurePhysics> _fixedArrayPtr;

/// <summary>
Expand All @@ -30,7 +30,7 @@ public FixedArrayPtr()
_currentProcess = new Reloaded.Memory.Sources.Memory();
_adventurePhysicsArray = _currentProcess.Allocate(bytes.Length);
_currentProcess.WriteRaw(_adventurePhysicsArray, bytes);
_fixedArrayPtr = new FixedArrayPtr<AdventurePhysics>((ulong)_adventurePhysicsArray, PhysicsArrayLength);
_fixedArrayPtr = new FixedArrayPtr<AdventurePhysics>(_adventurePhysicsArray, PhysicsArrayLength);
}

public void Dispose() => _currentProcess.Free(_adventurePhysicsArray);
Expand Down Expand Up @@ -71,7 +71,7 @@ public unsafe void UseEnumerator()
int[] numbers = { 0, 2, 3, 5, 7, 8, 88, 442 };
fixed (int* numbersPtr = numbers)
{
var arrayPtr = new FixedArrayPtr<int>((ulong) numbersPtr, numbers.Length);
var arrayPtr = new FixedArrayPtr<int>((nuint)numbersPtr, numbers.Length);
var numbersFromEnumerator = arrayPtr.Select(x => x).ToArray();

Assert.Equal(numbers.Length, numbersFromEnumerator.Length);
Expand All @@ -90,8 +90,8 @@ public unsafe void IndexOf()

// Fill in byte array with ascending numbers.
int upperBound = 1000;
IntPtr ptr = _currentProcess.Allocate(upperBound * sizeof(int));
var arrayPtr = new FixedArrayPtr<int>((ulong) ptr, upperBound);
nuint ptr = _currentProcess.Allocate(upperBound * sizeof(int));
var arrayPtr = new FixedArrayPtr<int>(ptr, upperBound);

for (int x = 0; x < upperBound; x++)
arrayPtr.Set(ref x, x);
Expand Down Expand Up @@ -129,8 +129,8 @@ public unsafe void ArraySize()
public unsafe void CopyFromCopyTo()
{
// Allocate array space for a copy and create a new fixed pointer to it.
IntPtr copyPtr = _currentProcess.Allocate(_fixedArrayPtr.ArraySize);
var arrayCopyPtr = new FixedArrayPtr<AdventurePhysics>((ulong) copyPtr, _fixedArrayPtr.Count);
nuint copyPtr = _currentProcess.Allocate(_fixedArrayPtr.ArraySize);
var arrayCopyPtr = new FixedArrayPtr<AdventurePhysics>(copyPtr, _fixedArrayPtr.Count);

// Copy from original to new array.
AdventurePhysics[] physicsArray = new AdventurePhysics[_fixedArrayPtr.Count];
Expand Down
2 changes: 1 addition & 1 deletion Source/Reloaded.Memory.Tests/Memory/Pointers/Pointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class Pointer
public unsafe void GetSetValue()
{
int number = 5;
var numberPtr = new Reloaded.Memory.Pointers.Pointer<int>((ulong) &number, false, new Reloaded.Memory.Sources.Memory()); // Last parameter only for coverage.
var numberPtr = new Reloaded.Memory.Pointers.Pointer<int>((nuint)(&number), false, new Reloaded.Memory.Sources.Memory()); // Last parameter only for coverage.

// Change value normally and try picking up new change.
number = 10;
Expand Down
Loading

0 comments on commit 6e8d5da

Please sign in to comment.