Memory.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System;
  2. using System.ComponentModel;
  3. using System.Runtime.InteropServices;
  4. using System.Windows.Forms;
  5. namespace SmartCoalApplication.SystemLayer
  6. {
  7. public unsafe static class Memory
  8. {
  9. private static IntPtr hHeap;
  10. static Memory()
  11. {
  12. hHeap = SafeNativeMethods.HeapCreate(0, IntPtr.Zero, IntPtr.Zero);
  13. uint info = 2;
  14. try
  15. {
  16. SafeNativeMethods.HeapSetInformation(hHeap,
  17. NativeConstants.HeapCompatibilityInformation,
  18. (void*)&info,
  19. sizeof(uint));
  20. }
  21. catch (Exception)
  22. {
  23. }
  24. Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
  25. }
  26. private static void DestroyHeap()
  27. {
  28. IntPtr hHeap2 = hHeap;
  29. hHeap = IntPtr.Zero;
  30. SafeNativeMethods.HeapDestroy(hHeap2);
  31. }
  32. private static void Application_ApplicationExit(object sender, EventArgs e)
  33. {
  34. DestroyHeap();
  35. }
  36. public static IntPtr Allocate(ulong bytes)
  37. {
  38. if (hHeap == IntPtr.Zero)
  39. {
  40. throw new InvalidOperationException("heap has already been destroyed");
  41. }
  42. else
  43. {
  44. IntPtr block = SafeNativeMethods.HeapAlloc(hHeap, 0, new UIntPtr(bytes));
  45. if (block == IntPtr.Zero)
  46. {
  47. throw new OutOfMemoryException("HeapAlloc returned a null pointer");
  48. }
  49. if (bytes > 0)
  50. {
  51. GC.AddMemoryPressure((long)bytes);
  52. }
  53. return block;
  54. }
  55. }
  56. public static IntPtr AllocateLarge(ulong bytes)
  57. {
  58. IntPtr block = SafeNativeMethods.VirtualAlloc(IntPtr.Zero, new UIntPtr(bytes),
  59. NativeConstants.MEM_COMMIT, NativeConstants.PAGE_READWRITE);
  60. if (block == IntPtr.Zero)
  61. {
  62. throw new OutOfMemoryException("VirtualAlloc returned a null pointer");
  63. }
  64. if (bytes > 0)
  65. {
  66. GC.AddMemoryPressure((long)bytes);
  67. }
  68. return block;
  69. }
  70. public static IntPtr AllocateBitmap(int width, int height, out IntPtr handle)
  71. {
  72. NativeStructs.BITMAPINFO bmi = new NativeStructs.BITMAPINFO();
  73. bmi.bmiHeader.biSize = (uint)sizeof(NativeStructs.BITMAPINFOHEADER);
  74. bmi.bmiHeader.biWidth = width;
  75. bmi.bmiHeader.biHeight = -height;
  76. bmi.bmiHeader.biPlanes = 1;
  77. bmi.bmiHeader.biBitCount = 32;
  78. bmi.bmiHeader.biCompression = NativeConstants.BI_RGB;
  79. bmi.bmiHeader.biSizeImage = 0;
  80. bmi.bmiHeader.biXPelsPerMeter = 96;
  81. bmi.bmiHeader.biYPelsPerMeter = 96;
  82. bmi.bmiHeader.biClrUsed = 0;
  83. bmi.bmiHeader.biClrImportant = 0;
  84. IntPtr pvBits;
  85. IntPtr hBitmap = SafeNativeMethods.CreateDIBSection(
  86. IntPtr.Zero,
  87. ref bmi,
  88. NativeConstants.DIB_RGB_COLORS,
  89. out pvBits,
  90. IntPtr.Zero,
  91. 0);
  92. if (hBitmap == IntPtr.Zero)
  93. {
  94. throw new OutOfMemoryException("CreateDIBSection returned NULL (" + Marshal.GetLastWin32Error().ToString() + ") while attempting to allocate " + width + "x" + height + " bitmap");
  95. }
  96. handle = hBitmap;
  97. long bytes = (long)width * (long)height * 4;
  98. if (bytes > 0)
  99. {
  100. GC.AddMemoryPressure(bytes);
  101. }
  102. return pvBits;
  103. }
  104. /// <summary>
  105. /// Frees a bitmap previously allocated with AllocateBitmap.
  106. /// </summary>
  107. /// <param name="handle">The handle that was returned from a previous call to AllocateBitmap.</param>
  108. /// <param name="width">The width of the bitmap, as specified in the original call to AllocateBitmap.</param>
  109. /// <param name="height">The height of the bitmap, as specified in the original call to AllocateBitmap.</param>
  110. public static void FreeBitmap(IntPtr handle, int width, int height)
  111. {
  112. long bytes = (long)width * (long)height * 4;
  113. bool bResult = SafeNativeMethods.DeleteObject(handle);
  114. if (!bResult)
  115. {
  116. throw new Win32Exception("DeleteObject returned false");
  117. }
  118. if (bytes > 0)
  119. {
  120. GC.RemoveMemoryPressure(bytes);
  121. }
  122. }
  123. /// <summary>
  124. /// Frees a block of memory previously allocated with Allocate().
  125. /// </summary>
  126. /// <param name="block">The block to free.</param>
  127. /// <exception cref="InvalidOperationException">There was an error freeing the block.</exception>
  128. public static void Free(IntPtr block)
  129. {
  130. if (Memory.hHeap != IntPtr.Zero)
  131. {
  132. long bytes = (long)SafeNativeMethods.HeapSize(hHeap, 0, block);
  133. bool result = SafeNativeMethods.HeapFree(hHeap, 0, block);
  134. if (!result)
  135. {
  136. int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
  137. throw new InvalidOperationException("HeapFree returned an error: " + error.ToString());
  138. }
  139. if (bytes > 0)
  140. {
  141. GC.RemoveMemoryPressure(bytes);
  142. }
  143. }
  144. }
  145. /// <summary>
  146. /// Frees a block of memory previous allocated with AllocateLarge().
  147. /// </summary>
  148. /// <param name="block">The block to free.</param>
  149. /// <param name="bytes">The size of the block.</param>
  150. public static void FreeLarge(IntPtr block, ulong bytes)
  151. {
  152. bool result = SafeNativeMethods.VirtualFree(block, UIntPtr.Zero, NativeConstants.MEM_RELEASE);
  153. if (!result)
  154. {
  155. int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
  156. throw new InvalidOperationException("VirtualFree returned an error: " + error.ToString());
  157. }
  158. if (bytes > 0)
  159. {
  160. GC.RemoveMemoryPressure((long)bytes);
  161. }
  162. }
  163. public static void Copy(void* dst, void* src, ulong length)
  164. {
  165. SafeNativeMethods.memcpy(dst, src, new UIntPtr(length));
  166. }
  167. public static void SetToZero(void* dst, ulong length)
  168. {
  169. SafeNativeMethods.memset(dst, 0, new UIntPtr(length));
  170. }
  171. }
  172. }