Implemented: - Core: UTF-16 ReadString boundary/alignment fix, target bitness and process id on MemoryBase - function interception: PatchManager, DetourManager, InstructionAnalyzer, MainThreadDispatcher - Execution: BackgroundTaskExecutor, InProcessInvoker - High-level: Magic facade, RemotePointer, async wrappers - Discovery/external code loading/Window groundwork (PEB/TEB, pattern scanning, raw allocations, DLL external code loading, window/input) Tests: 180 passing, 4 integration/interactive tests skipped.
50 lines
1.4 KiB
C#
50 lines
1.4 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace WhiteMagic.Hooking;
|
|
|
|
/// <summary>
|
|
/// Manages named, reversible byte patches against a <see cref="MemoryBase"/>.
|
|
/// Every patch records the bytes it replaced and can restore them later.
|
|
/// </summary>
|
|
public sealed class PatchManager
|
|
{
|
|
private readonly MemoryBase _memory;
|
|
private readonly Dictionary<string, Patch> _patches = new();
|
|
|
|
/// <summary>Creates a patch manager bound to the supplied memory reader.</summary>
|
|
public PatchManager(MemoryBase memory)
|
|
{
|
|
_memory = memory;
|
|
}
|
|
|
|
/// <summary>Creates a new patch and registers it with the manager.</summary>
|
|
public Patch Create(string name, IntPtr address, byte[] patchBytes)
|
|
{
|
|
var patch = new Patch(_memory, name, address, patchBytes);
|
|
_patches[name] = patch;
|
|
return patch;
|
|
}
|
|
|
|
/// <summary>Looks up a patch by name.</summary>
|
|
public Patch? this[string name]
|
|
{
|
|
get
|
|
{
|
|
_patches.TryGetValue(name, out Patch? patch);
|
|
return patch;
|
|
}
|
|
}
|
|
|
|
/// <summary>All patches registered in this manager.</summary>
|
|
public IEnumerable<Patch> All => _patches.Values;
|
|
|
|
/// <summary>Removes every applied patch.</summary>
|
|
public void RestoreAll()
|
|
{
|
|
foreach (Patch patch in _patches.Values)
|
|
{
|
|
patch.Remove();
|
|
}
|
|
}
|
|
}
|