博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用C#访问硬盘物理扇区和逻辑扇区的方法

Posted on 2010-10-28 21:25  TINZ  阅读(2555)  评论(2编辑  收藏  举报
因为API要用到一些宏定义和枚举变量,所以这里先定义一下:
        private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;

private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;

private const uint OPEN_EXISTING = 3;

public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}


导入需要用到的API函数:

       [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] int lDistanceToMove,
IntPtr lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);


        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool ReadFile(
[In] SafeFileHandle hFile,
[Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);


        [DllImport("kernel32.dll")]
        static extern bool WriteFile(
[In] SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
IntPtr lpOverlapped);


        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);


读写<逻辑>扇区:
        public void ReadSector([Out] byte[] ReturnByte, int SectorIndex)
{
uint dwCB;
if (SectorIndex > _SectorLength) return;
SafeFileHandle  DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
ReadFile(DirverHandle, ReturnByte, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
        public void WritSector(byte[] SectorBytes, int SectorIndex)
{
uint dwCB;
if (SectorBytes.Length != 512) return;
if (SectorIndex > _SectorLength) return;
SafeFileHandle  DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
WriteFile(DirverHandle, SectorBytes, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}


上面用到的 DirverName 就是盘符,例如"C:"或者"D:"之类。读写到的是逻辑扇区,假如你要读写MRB,那就要使用下面的方法读写磁盘的物理扇区。

读写物理扇区:

先看下面这幅图(硬盘管理器可以看到):


红色框里的数字表示:磁盘序号(不是序列号);
天蓝色框表示:盘符;
黄色框表示:分区,分区的序号是从0开始,每个物理磁盘的分区序号都是从0开始计算。

在读写物理扇区时,需要用到磁盘序号,下一节记录怎样通过盘符获取磁盘序号的,因为一般网上找到的都是获取盘符的办法,之前这个问题差点搞疯了。

程序提到的PhysicalDrive2里的2就是磁盘序号。

创建句柄:
            SafeFileHandle hdnl = CreateFile("\\\\.\\PhysicalDrive2", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

创建完句柄后读写就和操作逻辑扇区一样了,调用ReadFile/WriteFile,然后传入这个句柄就可以。