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.
111 lines
4.0 KiB
111 lines
4.0 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="path">文件路径。</param>
|
|
/// <param name="handle">内存映射句柄。</param>
|
|
/// <param name="block">块大小。</param>
|
|
/// <returns>映射成功。</returns>
|
|
internal bool Create(string path, ref IntPtr handle, ref UInt32 block)
|
|
{
|
|
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(path))
|
|
{
|
|
try
|
|
{
|
|
var fh = Kernel32.CreateFile(path, 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 ag = si.dwAllocationGranularity;
|
|
uint flh = 0;
|
|
|
|
// 获取文件长度。
|
|
uint fl = Kernel32.GetFileSize(fh, out flh);
|
|
fl |= (((uint)flh) << 32);
|
|
|
|
// 关闭文件句柄 。
|
|
Kernel32.CloseHandle(fh);
|
|
uint bl = 1000 * ag;
|
|
if (fl < 1000 * ag) bl = fl;
|
|
|
|
// 返回。
|
|
handle = mh;
|
|
block = bl;
|
|
return true;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
handle = IntPtr.Zero;
|
|
block = 0;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>从内存映射中读取数据。</summary>
|
|
/// <param name="handle">内存映射句柄。</param>
|
|
/// <param name="block">块大小。</param>
|
|
/// <param name="offset">读取的位置。</param>
|
|
/// <param name="length">读取的长度。</param>
|
|
/// <returns>读取的结果。</returns>
|
|
internal byte[] Read(IntPtr handle, UInt32 block, Int32 offset, Int32 length)
|
|
{
|
|
var DesiredAccess = (uint)(Constant.FILE_MAP_COPY | Constant.FILE_MAP_READ | Constant.FILE_MAP_WRITE);
|
|
|
|
if ((handle != IntPtr.Zero) && (block > 0) && (offset > 0) && (length > 0))
|
|
{
|
|
try
|
|
{
|
|
// 映射视图,得到地址 。
|
|
var address = Kernel32.MapViewOfFile(handle, DesiredAccess, (uint)(offset >> 32), (uint)(offset & 0xFFFFFFFF), block);
|
|
if (address != IntPtr.Zero)
|
|
{
|
|
// 从非托管的内存中复制内容到托管的内存中。
|
|
var start = offset;
|
|
var buffer = new byte[block];
|
|
Marshal.Copy(address, buffer, start, (int)length);
|
|
return buffer;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
return new byte[0];
|
|
}
|
|
|
|
/// <summary>关闭内存映射。</summary>
|
|
/// <param name="handle">内存映射句柄。</param>
|
|
internal static void Close(IntPtr handle)
|
|
{
|
|
if (handle == IntPtr.Zero) return;
|
|
try { Kernel32.CloseHandle(handle); } catch { }
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|