利用Win32 api 读写硬盘扇区

调用API函数即可完成对扇区的读写操作


[DllImport("Kernel32.dll")]
extern static IntPtr CreateFile(string fileName, uint accessFlag, uint shareMode, IntPtr security, uint createFlag, uint attributeFlag, IntPtr tempfile);

首先要创建文件

[DllImport("Kernel32.dll", SetLastError = true)]
extern static uint SetFilePointer(IntPtr handle, uint offset, [In, Out] ref uint lpDistanceToMoveHigh, uint flag);

设置文件指针
如果不设置第三个参数(null),系统会把第二个参数offset当作一个有符号整数(32位),最多偏移2GB。
设置后会把第三个参数当作64有符号数的高32位,第二个参数当作低32位。
(要注意的是第三个参数是引用类型)

[DllImport("Kernel32.dll")]
extern static bool WriteFile(IntPtr handle, [In] byte[] buffer, uint bufferLength, ref uint length, IntPtr overLapped);
[DllImport("Kernel32.dll")]
extern static bool ReadFile(IntPtr handle, [Out] byte[] buffer, uint bufferLength, ref uint length, IntPtr overLapped);

然后开始你的操作。
Win32 api中返回值为为零写入成功,不为零错误。对应到这里就是返回false和true
第三个参数保存的是写入了多少字节。

[DllImport("Kernel32.dll")]
extern static bool CloseHandle(IntPtr handle);

最后要记得关闭句柄


参数设置,具体含义见MSDN: CreateFile

public const uint FILE_ATTRIBUTE_NORMAL = 0x80;
public const short INVALID_HANDLE_VALUE = -1;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
public const uint FILE_BEGIN = 0;
public const uint FILE_CURRENT = 1;
public const uint FILE_END = 2;

例子:

        /// 
        /// 写入内容 需为扇区整数倍,不然写不进去
        /// 
        /// 驱动器名
        /// 扇区
        /// 写入内容
        /// 
        static public bool write(string drivename, UInt32 sector, byte[] buffer)
        {
            IntPtr DiskHandle = CreateFile(drivename, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            uint length = 0;
            UInt64 distance = sector ;//偏移量
            distance = distance << 9;
            UInt32 distancehigh = (UInt32)(distancehigh>> 32);
            var i=SetFilePointer(DiskHandle, (uint)distance, ref distancehigh, FILE_BEGIN);
            if (i == 0xffffffff)//返回值是低32位地址,返回-1时getlastwin32error查看错误
            {
                var errCode=Marshal.GetLastWin32Error();
                IntPtr tempptr = IntPtr.Zero;
                string msg = null;
                FormatMessage(0x1300, ref tempptr, errCode, 0, ref msg, 255, ref tempptr);
            }
            var res=WriteFile(DiskHandle, buffer, (uint)buffer.Length, ref length, IntPtr.Zero);
            CloseHandle(DiskHandle);
            return res;
        }

你可能感兴趣的:(利用Win32 api 读写硬盘扇区)