using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
namespace XFEWarframe.Client;
[SupportedOSPlatform("windows")]
internal static class RemoteModules
{
internal static nint FindImageBase(nint process, string name, CancellationToken cancellation = default)
{
// A CREATE_SUSPENDED process has mapped images but no initialized loader list.
// Query image mappings directly; Process.Modules fails with ERROR_PARTIAL_COPY here.
var visited = new HashSet<nint>();
var path = new StringBuilder(32768);
nuint address = 0;
while (true)
{
cancellation.ThrowIfCancellationRequested();
if (VirtualQueryEx(process, (nint)address, out var region, (nuint)Marshal.SizeOf<MemoryInformation>()) == 0)
{
var error = Marshal.GetLastWin32Error();
if (error == 87) break; // End of the process address space.
throw new Win32Exception(error, "无法查询客户端的模块映射。");
}
if (region.State == 0x1000 && region.Type == 0x1000000 && visited.Add(region.AllocationBase))
{
path.Clear();
var length = GetMappedFileName(process, region.BaseAddress, path, (uint)path.Capacity);
if (length > 0 && length < path.Capacity &&
string.Equals(Path.GetFileName(path.ToString()), name, StringComparison.OrdinalIgnoreCase))
return region.AllocationBase;
}
var next = checked((nuint)region.BaseAddress + region.RegionSize);
if (next <= address) throw new InvalidDataException("客户端模块映射没有前进。");
address = next;
}
throw new IOException("客户端模块尚未映射:" + name);
}
[StructLayout(LayoutKind.Sequential)]
private struct MemoryInformation
{
public nint BaseAddress, AllocationBase;
public uint AllocationProtect;
public ushort PartitionId;
public nuint RegionSize;
public uint State, Protect, Type;
}
[DllImport("kernel32", SetLastError = true)]
private static extern nuint VirtualQueryEx(nint process, nint address, out MemoryInformation information, nuint size);
[DllImport("psapi", EntryPoint = "GetMappedFileNameW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern uint GetMappedFileName(nint process, nint address, StringBuilder fileName, uint size);
}
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
namespace XFEWarframe.Client;
[SupportedOSPlatform("windows")]
internal static class RemoteModules
{
internal static nint FindImageBase(nint process, string name, CancellationToken cancellation = default)
{
// A CREATE_SUSPENDED process has mapped images but no initialized loader list.
// Query image mappings directly; Process.Modules fails with ERROR_PARTIAL_COPY here.
var visited = new HashSet<nint>();
var path = new StringBuilder(32768);
nuint address = 0;
while (true)
{
cancellation.ThrowIfCancellationRequested();
if (VirtualQueryEx(process, (nint)address, out var region, (nuint)Marshal.SizeOf<MemoryInformation>()) == 0)
{
var error = Marshal.GetLastWin32Error();
if (error == 87) break; // End of the process address space.
throw new Win32Exception(error, "无法查询客户端的模块映射。");
}
if (region.State == 0x1000 && region.Type == 0x1000000 && visited.Add(region.AllocationBase))
{
path.Clear();
var length = GetMappedFileName(process, region.BaseAddress, path, (uint)path.Capacity);
if (length > 0 && length < path.Capacity &&
string.Equals(Path.GetFileName(path.ToString()), name, StringComparison.OrdinalIgnoreCase))
return region.AllocationBase;
}
var next = checked((nuint)region.BaseAddress + region.RegionSize);
if (next <= address) throw new InvalidDataException("客户端模块映射没有前进。");
address = next;
}
throw new IOException("客户端模块尚未映射:" + name);
}
[StructLayout(LayoutKind.Sequential)]
private struct MemoryInformation
{
public nint BaseAddress, AllocationBase;
public uint AllocationProtect;
public ushort PartitionId;
public nuint RegionSize;
public uint State, Protect, Type;
}
[DllImport("kernel32", SetLastError = true)]
private static extern nuint VirtualQueryEx(nint process, nint address, out MemoryInformation information, nuint size);
[DllImport("psapi", EntryPoint = "GetMappedFileNameW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern uint GetMappedFileName(nint process, nint address, StringBuilder fileName, uint size);
}