You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
4.2 KiB

  1. #if NET40 || NET461
  2. using Apewer.Internals.Interop;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. namespace Apewer.Surface
  9. {
  10. /// <summary></summary>
  11. internal class FileMapping
  12. {
  13. /// <summary>创建内存映射。</summary>
  14. /// <param name="argPath">文件路径。</param>
  15. /// <param name="argHandle">内存映射句柄。</param>
  16. /// <param name="argBlock">块大小。</param>
  17. /// <returns>映射成功。</returns>
  18. internal bool Create(string argPath, ref IntPtr argHandle, ref UInt32 argBlock)
  19. {
  20. var DesiredAccess = Constant.GENERIC_READ | Constant.GENERIC_WRITE;
  21. var ShareMode = FileShare.ReadWrite;
  22. var CreationDesposition = FileMode.OpenOrCreate;
  23. var FlagsAndAttributes = Constant.FILE_ATTRIBUTE_NORMAL | Constant.FILE_FLAG_SEQUENTIAL_SCAN;
  24. if (File.Exists(argPath))
  25. {
  26. try
  27. {
  28. var fh = Kernel32.CreateFile(argPath, DesiredAccess, ShareMode, IntPtr.Zero, CreationDesposition, FlagsAndAttributes, IntPtr.Zero);
  29. if (Constant.INVALID_HANDLE_VALUE != (int)fh)
  30. {
  31. // 创建内存句柄。
  32. var mh = Kernel32.CreateFileMapping(fh, IntPtr.Zero, Constant.PAGE_READWRITE, 0, 0, Guid.NewGuid().ToString());
  33. // 获取系统信息。
  34. var si = new SystemInfo();
  35. Kernel32.GetSystemInfo(ref si);
  36. // 得到系统页分配粒度。
  37. uint vag = si.dwAllocationGranularity;
  38. uint vflh = 0;
  39. // 获取文件长度。
  40. uint vfl = Kernel32.GetFileSize(fh, out vflh);
  41. vfl |= (((uint)vflh) << 32);
  42. // 关闭文件句柄 。
  43. Kernel32.CloseHandle(fh);
  44. uint vbl = 1000 * vag;
  45. if (vfl < 1000 * vag) vbl = vfl;
  46. // 返回。
  47. argHandle = mh;
  48. argBlock = vbl;
  49. return true;
  50. }
  51. }
  52. catch { }
  53. }
  54. argHandle = IntPtr.Zero;
  55. argBlock = 0;
  56. return false;
  57. }
  58. /// <summary>从内存映射中读取数据。</summary>
  59. /// <param name="argHandle">内存映射句柄。</param>
  60. /// <param name="argBlock">块大小。</param>
  61. /// <param name="argOffset">读取的位置。</param>
  62. /// <param name="argLength">读取的长度。</param>
  63. /// <returns>读取的结果。</returns>
  64. internal byte[] Read(IntPtr argHandle, UInt32 argBlock, Int32 argOffset, Int32 argLength)
  65. {
  66. var DesiredAccess = (uint)(Constant.FILE_MAP_COPY | Constant.FILE_MAP_READ | Constant.FILE_MAP_WRITE);
  67. if ((argHandle != IntPtr.Zero) && (argBlock > 0) && (argOffset > 0) && (argLength > 0))
  68. {
  69. try
  70. {
  71. // 映射视图,得到地址 。
  72. var mapaddress = Kernel32.MapViewOfFile(argHandle, DesiredAccess, (uint)(argOffset >> 32), (uint)(argOffset & 0xFFFFFFFF), argBlock);
  73. if (mapaddress != IntPtr.Zero)
  74. {
  75. // 从非托管的内存中复制内容到托管的内存中。
  76. var start = argOffset;
  77. var length = argLength;
  78. var buffer = new byte[argBlock];
  79. Marshal.Copy(mapaddress, buffer, start, length);
  80. return buffer;
  81. }
  82. }
  83. catch { }
  84. }
  85. return new byte[0];
  86. }
  87. /// <summary>关闭内存映射。</summary>
  88. /// <param name="argHandle">内存映射句柄。</param>
  89. internal static void Close(IntPtr argHandle)
  90. {
  91. if (argHandle == IntPtr.Zero) return;
  92. try { Kernel32.CloseHandle(argHandle); } catch { }
  93. }
  94. }
  95. }
  96. #endif