XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWarframe

【WinUI】基于Warframe游戏本体的公开服务器以及安装器

公开
关注 0 Fork 0 Star 0
UTF-8
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);
}