MemoryManagementWindows.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. namespace ARMeilleure.Memory
  5. {
  6. static class MemoryManagementWindows
  7. {
  8. [Flags]
  9. private enum AllocationType : uint
  10. {
  11. Commit = 0x1000,
  12. Reserve = 0x2000,
  13. Decommit = 0x4000,
  14. Release = 0x8000,
  15. Reset = 0x80000,
  16. Physical = 0x400000,
  17. TopDown = 0x100000,
  18. WriteWatch = 0x200000,
  19. LargePages = 0x20000000
  20. }
  21. [Flags]
  22. private enum MemoryProtection : uint
  23. {
  24. NoAccess = 0x01,
  25. ReadOnly = 0x02,
  26. ReadWrite = 0x04,
  27. WriteCopy = 0x08,
  28. Execute = 0x10,
  29. ExecuteRead = 0x20,
  30. ExecuteReadWrite = 0x40,
  31. ExecuteWriteCopy = 0x80,
  32. GuardModifierflag = 0x100,
  33. NoCacheModifierflag = 0x200,
  34. WriteCombineModifierflag = 0x400
  35. }
  36. private enum WriteWatchFlags : uint
  37. {
  38. None = 0,
  39. Reset = 1
  40. }
  41. [DllImport("kernel32.dll")]
  42. private static extern IntPtr VirtualAlloc(
  43. IntPtr lpAddress,
  44. IntPtr dwSize,
  45. AllocationType flAllocationType,
  46. MemoryProtection flProtect);
  47. [DllImport("kernel32.dll")]
  48. private static extern bool VirtualProtect(
  49. IntPtr lpAddress,
  50. IntPtr dwSize,
  51. MemoryProtection flNewProtect,
  52. out MemoryProtection lpflOldProtect);
  53. [DllImport("kernel32.dll")]
  54. private static extern bool VirtualFree(
  55. IntPtr lpAddress,
  56. IntPtr dwSize,
  57. AllocationType dwFreeType);
  58. [DllImport("kernel32.dll")]
  59. private static extern int GetWriteWatch(
  60. WriteWatchFlags dwFlags,
  61. IntPtr lpBaseAddress,
  62. IntPtr dwRegionSize,
  63. IntPtr[] lpAddresses,
  64. ref ulong lpdwCount,
  65. out uint lpdwGranularity);
  66. public static IntPtr Allocate(IntPtr size)
  67. {
  68. const AllocationType flags =
  69. AllocationType.Reserve |
  70. AllocationType.Commit;
  71. IntPtr ptr = VirtualAlloc(IntPtr.Zero, size, flags, MemoryProtection.ReadWrite);
  72. if (ptr == IntPtr.Zero)
  73. {
  74. throw new OutOfMemoryException();
  75. }
  76. return ptr;
  77. }
  78. public static IntPtr AllocateWriteTracked(IntPtr size)
  79. {
  80. const AllocationType flags =
  81. AllocationType.Reserve |
  82. AllocationType.Commit |
  83. AllocationType.WriteWatch;
  84. IntPtr ptr = VirtualAlloc(IntPtr.Zero, size, flags, MemoryProtection.ReadWrite);
  85. if (ptr == IntPtr.Zero)
  86. {
  87. throw new OutOfMemoryException();
  88. }
  89. return ptr;
  90. }
  91. public static bool Reprotect(IntPtr address, IntPtr size, Memory.MemoryProtection protection)
  92. {
  93. MemoryProtection prot = GetProtection(protection);
  94. return VirtualProtect(address, size, prot, out _);
  95. }
  96. private static MemoryProtection GetProtection(Memory.MemoryProtection protection)
  97. {
  98. switch (protection)
  99. {
  100. case Memory.MemoryProtection.None: return MemoryProtection.NoAccess;
  101. case Memory.MemoryProtection.Read: return MemoryProtection.ReadOnly;
  102. case Memory.MemoryProtection.ReadAndWrite: return MemoryProtection.ReadWrite;
  103. case Memory.MemoryProtection.ReadAndExecute: return MemoryProtection.ExecuteRead;
  104. case Memory.MemoryProtection.ReadWriteExecute: return MemoryProtection.ExecuteReadWrite;
  105. case Memory.MemoryProtection.Execute: return MemoryProtection.Execute;
  106. default: throw new ArgumentException($"Invalid permission \"{protection}\".");
  107. }
  108. }
  109. public static bool Free(IntPtr address)
  110. {
  111. return VirtualFree(address, IntPtr.Zero, AllocationType.Release);
  112. }
  113. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  114. public static bool GetModifiedPages(
  115. IntPtr address,
  116. IntPtr size,
  117. IntPtr[] addresses,
  118. out ulong count)
  119. {
  120. ulong pagesCount = (ulong)addresses.Length;
  121. int result = GetWriteWatch(
  122. WriteWatchFlags.Reset,
  123. address,
  124. size,
  125. addresses,
  126. ref pagesCount,
  127. out uint granularity);
  128. count = pagesCount;
  129. return result == 0;
  130. }
  131. }
  132. }