protected override nint AllocateChunk(nint hint)
    {
        while (true)
        {
            var mbi = new WinApi.MEMORY_BASIC_INFORMATION();
            if (WinApi.VirtualQuery(hint, ref mbi, Marshal.SizeOf <WinApi.MEMORY_BASIC_INFORMATION>()) == 0)
            {
                Logger.Log(LogLevel.Debug,
                           $"Skipping analysing 0x{(long) hint:X8} because VirtualQuery failed: {Win32Error()}");
                goto next;
            }

            if (mbi.State == WinApi.PageState.MEM_FREE)
            {
                var nextAddress = RoundUp(mbi.BaseAddress, ALLOCATION_UNIT);
                var d           = nextAddress - mbi.BaseAddress;
                if (d >= 0 && mbi.RegionSize - d >= ALLOCATION_UNIT)
                {
                    hint = nextAddress;
                    break;
                }
            }

next:
            hint = mbi.BaseAddress + mbi.RegionSize;
        }

        var chunk = WinApi.VirtualAlloc(hint, ALLOCATION_UNIT, WinApi.AllocationType.MEM_RESERVE,
                                        WinApi.ProtectConstant.PAGE_NOACCESS);

        if (chunk == 0)
        {
            throw Win32Error($"Failed to reserve address: 0x{(long) hint:X8}");
        }
        var addr = WinApi.VirtualAlloc(chunk, PAGE_SIZE, WinApi.AllocationType.MEM_COMMIT,
                                       WinApi.ProtectConstant.PAGE_READWRITE);

        if (addr == 0)
        {
            var error = Marshal.GetLastWin32Error();
            WinApi.VirtualFree(chunk, 0, WinApi.FreeType.MEM_RELEASE);
            throw
                Win32Error($"Failed to commit memory 0x{(long) addr:X8} for read-write access for 0x{(long) chunk:X8}",
                           error);
        }

        return(chunk);
    }
Exemple #2
0
 public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);