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

#if NET40 || NET461
using Apewer.Internals.Interop;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Apewer.Surface
{
/// <summary></summary>
internal class FileMapping
{
/// <summary>创建内存映射。</summary>
/// <param name="argPath">文件路径。</param>
/// <param name="argHandle">内存映射句柄。</param>
/// <param name="argBlock">块大小。</param>
/// <returns>映射成功。</returns>
internal bool Create(string argPath, ref IntPtr argHandle, ref UInt32 argBlock)
{
var DesiredAccess = Constant.GENERIC_READ | Constant.GENERIC_WRITE;
var ShareMode = FileShare.ReadWrite;
var CreationDesposition = FileMode.OpenOrCreate;
var FlagsAndAttributes = Constant.FILE_ATTRIBUTE_NORMAL | Constant.FILE_FLAG_SEQUENTIAL_SCAN;
if (File.Exists(argPath))
{
try
{
var fh = Kernel32.CreateFile(argPath, DesiredAccess, ShareMode, IntPtr.Zero, CreationDesposition, FlagsAndAttributes, IntPtr.Zero);
if (Constant.INVALID_HANDLE_VALUE != (int)fh)
{
// 创建内存句柄。
var mh = Kernel32.CreateFileMapping(fh, IntPtr.Zero, Constant.PAGE_READWRITE, 0, 0, Guid.NewGuid().ToString());
// 获取系统信息。
var si = new SystemInfo();
Kernel32.GetSystemInfo(ref si);
// 得到系统页分配粒度。
uint vag = si.dwAllocationGranularity;
uint vflh = 0;
// 获取文件长度。
uint vfl = Kernel32.GetFileSize(fh, out vflh);
vfl |= (((uint)vflh) << 32);
// 关闭文件句柄 。
Kernel32.CloseHandle(fh);
uint vbl = 1000 * vag;
if (vfl < 1000 * vag) vbl = vfl;
// 返回。
argHandle = mh;
argBlock = vbl;
return true;
}
}
catch { }
}
argHandle = IntPtr.Zero;
argBlock = 0;
return false;
}
/// <summary>从内存映射中读取数据。</summary>
/// <param name="argHandle">内存映射句柄。</param>
/// <param name="argBlock">块大小。</param>
/// <param name="argOffset">读取的位置。</param>
/// <param name="argLength">读取的长度。</param>
/// <returns>读取的结果。</returns>
internal byte[] Read(IntPtr argHandle, UInt32 argBlock, Int32 argOffset, Int32 argLength)
{
var DesiredAccess = (uint)(Constant.FILE_MAP_COPY | Constant.FILE_MAP_READ | Constant.FILE_MAP_WRITE);
if ((argHandle != IntPtr.Zero) && (argBlock > 0) && (argOffset > 0) && (argLength > 0))
{
try
{
// 映射视图,得到地址 。
var mapaddress = Kernel32.MapViewOfFile(argHandle, DesiredAccess, (uint)(argOffset >> 32), (uint)(argOffset & 0xFFFFFFFF), argBlock);
if (mapaddress != IntPtr.Zero)
{
// 从非托管的内存中复制内容到托管的内存中。
var start = argOffset;
var length = argLength;
var buffer = new byte[argBlock];
Marshal.Copy(mapaddress, buffer, start, length);
return buffer;
}
}
catch { }
}
return new byte[0];
}
/// <summary>关闭内存映射。</summary>
/// <param name="argHandle">内存映射句柄。</param>
internal static void Close(IntPtr argHandle)
{
if (argHandle == IntPtr.Zero) return;
try { Kernel32.CloseHandle(argHandle); } catch { }
}
}
}
#endif