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(); var path = new StringBuilder(32768); nuint address = 0; while (true) { cancellation.ThrowIfCancellationRequested(); if (VirtualQueryEx(process, (nint)address, out var region, (nuint)Marshal.SizeOf()) == 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); }