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); }
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);