public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
public IntPtr MapView(FileMapAccessType access, ref long offset, ref long mapSize) { if (!IsOpen) { throw new ObjectDisposedException("Memory file already closed"); } // Grab system info to get the allocation granularity. SYSTEM_INFO pSI = new SYSTEM_INFO(); Win32MapApis.GetSystemInfo(ref pSI); // Make sure the offset is aligned. offset -= offset % pSI.dwAllocationGranularity; // Find the largest contiguous virtual address space. MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); long address = 0; const uint MEM_FREE = 0x10000; long freestart = 0, largestFreestart = 0; long free = 0, largestFree = 0; bool recording = false; while (true) { int numBytes = Win32MapApis.VirtualQueryEx(System.Diagnostics.Process.GetCurrentProcess().Handle, (IntPtr)address, out mbi, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); if (numBytes != Marshal.SizeOf(mbi)) { break; } if (mbi.State == MEM_FREE) { if (!recording) { freestart = address; } free += mbi.RegionSize.ToInt64(); recording = true; } else { if (recording) { if (free > largestFree) { largestFree = free; largestFreestart = freestart; } } free = 0; recording = false; } address += mbi.RegionSize.ToInt64(); } // Make sure the address is aligned if (largestFreestart % pSI.dwAllocationGranularity != 0) { long diff = pSI.dwAllocationGranularity - (largestFreestart % pSI.dwAllocationGranularity); largestFreestart += diff; largestFree -= diff; } // Cap map size if (mapSize > largestFree) { mapSize = largestFree; } // Edge case if (offset + mapSize > _fileSize) { long diff = offset + mapSize - _fileSize; if (diff % pSI.dwAllocationGranularity != 0) { diff -= diff % pSI.dwAllocationGranularity; diff += pSI.dwAllocationGranularity; } offset -= diff; } IntPtr baseAddress = Win32MapApis.MapViewOfFileEx( _hMap, (int)access, (int)((offset >> 32) & 0xFFFFFFFF), (int)(offset & 0xFFFFFFFF), (IntPtr)mapSize, (IntPtr)largestFreestart); if (baseAddress == IntPtr.Zero) { throw new MMException(Marshal.GetLastWin32Error()); } return(baseAddress); }
public static extern IntPtr VirtualQuery(ref IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);