加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

为什么C#中的原始磁盘读取从略微偏移的偏移读取?

发布时间:2020-12-15 21:48:30 所属栏目:百科 来源:网络整理
导读:我正在尝试读取原始磁盘.我已成功打开驱动器并获得有效句柄(CreateFile),将该句柄的偏移量设置为零(SetFilePointerEx)并将数据读取到缓冲区Byte [](ReadFile).到现在为止还挺好.但是由于某些未知的原因,当我将缓冲区(实际上花了我一段时间才弄清楚)与第三方
我正在尝试读取原始磁盘.我已成功打开驱动器并获得有效句柄(CreateFile),将该句柄的偏移量设置为零(SetFilePointerEx)并将数据读取到缓冲区Byte [](ReadFile).到现在为止还挺好.但是由于某些未知的原因,当我将缓冲区(实际上花了我一段时间才弄清楚)与第三方实用程序(Disk Investigator)显示的内容进行比较时.它不包含引导信息(跳转指令),但是包含正确的磁盘数据,但是从偏移量85 = 0x55开始.所以在卷启动信息的中间某处.

这是为什么?有什么东西,我很想念(显然我是)?

系统:Windows 8(在VmWare工作站中)

码:

// moves the pointer to a given offset
Int64 offset = 0; 
Int64 newOffset;
Int32 bufferSize = (Int32) clusterSizeInBytes; 
SetFilePointerEx(driveHandle.Handle,offset,out newOffset,WinMoveMethod.Begin);
Int32 error = Marshal.GetLastWin32Error();

// reads the raw buffer
Int32 numberOfBytesRead;
rawData = new Byte[bufferSize];
Boolean result = ReadFile(driveHandle.Handle,rawData,bufferSize,out numberOfBytesRead,IntPtr.Zero);

CreateFile(其他地方)

driveHandle = CreateFile(".PhysicalDrive1",WinFileAccessMode.GenericRead,WinFileSharedAccess.All,IntPtr.Zero,WinFileMode.OpenExisting,WinFileAttribute.None,IntPtr.Zero);

PInvoke方法:

[DllImport("kernel32.dll",SetLastError = true)]
public static extern Boolean SetFilePointerEx(
    [In] SafeFileHandle fileHandle,[In] Int64 distanceToMove,[Out] out Int64 newOffset,[In] WinMoveMethod moveMethod);

[DllImport("kernel32",SetLastError = true)]
public extern static Boolean ReadFile(
    [In] SafeFileHandle handle,[Out] Byte[] buffer,[In] Int32 numBytesToRead,[Out] out Int32 numBytesRead,[In] IntPtr overlapped);

枚举:

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

解决方法

使用命名空间“DiskLib”找不到库.我现在无法测试或完全上传,即使我不知道谁写了那段代码,但你可能会发现有趣的线条是

public class DiskStream : Stream
{
    public const int DEFAULT_SECTOR_SIZE = 512;
    private const int BUFFER_SIZE = 4096;

    private string diskID;
    private DiskInfo diskInfo;
    private FileAccess desiredAccess;
    private SafeFileHandle fileHandle;

    public DiskInfo DiskInfo
    {
        get { return this.diskInfo; }
    }
    public uint SectorSize
    {
        get { return this.diskInfo.BytesPerSector; }
    }

    public DiskStream(string diskID,FileAccess desiredAccess)
    {
        this.diskID = diskID;
        this.diskInfo = new DiskInfo(diskID);
        this.desiredAccess = desiredAccess;

        // if desiredAccess is Write or Read/Write
        //   find volumes on this disk
        //   lock the volumes using FSCTL_LOCK_VOLUME
        //     unlock the volumes on Close() or in destructor


        this.fileHandle = this.openFile(diskID,desiredAccess);
    }

    private SafeFileHandle openFile(string id,FileAccess desiredAccess)
    {
        uint access;
        switch (desiredAccess)
        {
            case FileAccess.Read:
                access = DeviceIO.GENERIC_READ;
                break;
            case FileAccess.Write:
                access = DeviceIO.GENERIC_WRITE;
                break;
            case FileAccess.ReadWrite:
                access = DeviceIO.GENERIC_READ | DeviceIO.GENERIC_WRITE;
                break;
            default:
                access = DeviceIO.GENERIC_READ;
                break;
        }

        SafeFileHandle ptr = DeviceIO.CreateFile(
            id,access,DeviceIO.FILE_SHARE_READ,DeviceIO.OPEN_EXISTING,DeviceIO.FILE_FLAG_NO_BUFFERING | DeviceIO.FILE_FLAG_WRITE_THROUGH,IntPtr.Zero);

        if (ptr.IsInvalid)
        {
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }

        return ptr;
    }

    public override bool CanRead
    {
        get
        {
            return (this.desiredAccess == FileAccess.Read || this.desiredAccess == FileAccess.ReadWrite) ? true : false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return (this.desiredAccess == FileAccess.Write || this.desiredAccess == FileAccess.ReadWrite) ? true : false;
        }
    }
    public override bool CanSeek
    {
        get
        {
            return true;
        }
    }
    public override long Length {
      get { return (long)this.Length; }
    }

    public ulong LengthU
    {
        get { return this.diskInfo.Size; }
    }

    public override long Position {
      get {
        return (long)PositionU;
      }
      set {
        PositionU = (ulong)value;
      }
    }

    public ulong PositionU
    {
        get
        {
            ulong n = 0;
            if (!DeviceIO.SetFilePointerEx(this.fileHandle,out n,(uint)SeekOrigin.Current))
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            return n;
        }
        set
        {
            if (value > (this.LengthU - 1))
                throw new EndOfStreamException("Cannot set position beyond the end of the disk.");

            ulong n = 0;
            if (!DeviceIO.SetFilePointerEx(this.fileHandle,value,(uint)SeekOrigin.Begin))
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    }

    public override void Flush()
    {
        // not required,since FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING are used
        //if (!Unmanaged.FlushFileBuffers(this.fileHandle))
        //    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    }
    public override void Close()
    {
      if (this.fileHandle != null) {
        DeviceIO.CloseHandle(this.fileHandle);
        this.fileHandle.SetHandleAsInvalid();
        this.fileHandle = null;
      }
      base.Close();
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException("Setting the length is not supported with DiskStream objects.");
    }
    public override int Read(byte[] buffer,int offset,int count) {
      return (int)Read(buffer,(uint)offset,(uint)count);
    }

    public unsafe uint Read(byte[] buffer,uint offset,uint count)
    {
        uint n = 0;
        fixed (byte* p = buffer)
        {
            if (!DeviceIO.ReadFile(this.fileHandle,p + offset,count,&n,IntPtr.Zero))
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
        return n;
    }
    public override void Write(byte[] buffer,int count) {
      Write(buffer,(uint)count);
    }
    public unsafe void Write(byte[] buffer,uint count)
    {
        uint n = 0;
        fixed (byte* p = buffer)
        {
            if (!DeviceIO.WriteFile(this.fileHandle,IntPtr.Zero))
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    }
    public override long Seek(long offset,SeekOrigin origin) {
      return (long)SeekU((ulong)offset,origin);
    }
    public ulong SeekU(ulong offset,SeekOrigin origin)
    {
        ulong n = 0;
        if (!DeviceIO.SetFilePointerEx(this.fileHandle,(uint)origin))
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        return n;
    }

    public uint ReadSector(DiskSector sector)
    {
        return this.Read(sector.Data,sector.SectorSize);
    }
    public void WriteSector(DiskSector sector)
    {
        this.Write(sector.Data,sector.SectorSize);
    }
    public void SeekSector(DiskSector sector)
    {
        this.Seek(sector.Offset,SeekOrigin.Begin);
    }
}

DeviceIO类是Win32 API的p / invoke样板.

DiskInfo类是WMI Win32_DiskDrive和Win32_DiskPartition类的包装.

我使用该库一次克隆磁盘(在Win7上).希望有助于找到解决方案.

为了完整性和详细信息,DeviceIO类始终使用无符号整数:

/// <summary>
/// P/Invoke wrappers around Win32 functions and constants.
/// </summary>
internal partial class DeviceIO
{

    #region Constants used in unmanaged functions

    public const uint FILE_SHARE_READ = 0x00000001;
    public const uint FILE_SHARE_WRITE = 0x00000002;
    public const uint FILE_SHARE_DELETE = 0x00000004;
    public const uint OPEN_EXISTING = 3;

    public const uint GENERIC_READ = (0x80000000);
    public const uint GENERIC_WRITE = (0x40000000);

    public const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
    public const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
    public const uint FILE_READ_ATTRIBUTES = (0x0080);
    public const uint FILE_WRITE_ATTRIBUTES = 0x0100;
    public const uint ERROR_INSUFFICIENT_BUFFER = 122;

    #endregion

    #region Unamanged function declarations

    [DllImport("kernel32.dll",SetLastError = true)]
    public static unsafe extern SafeFileHandle CreateFile(
        string FileName,uint DesiredAccess,uint ShareMode,IntPtr SecurityAttributes,uint CreationDisposition,uint FlagsAndAttributes,IntPtr hTemplateFile);

    [DllImport("kernel32.dll",SetLastError = true)]
    public static extern bool CloseHandle(SafeFileHandle hHandle);

    [DllImport("kernel32.dll",SetLastError = true)]
    public static extern bool DeviceIoControl(
        SafeFileHandle hDevice,uint dwIoControlCode,IntPtr lpInBuffer,uint nInBufferSize,[Out] IntPtr lpOutBuffer,uint nOutBufferSize,ref uint lpBytesReturned,IntPtr lpOverlapped);

    [DllImport("kernel32.dll",SetLastError = true)]
    public static extern unsafe bool WriteFile(
        SafeFileHandle hFile,byte* pBuffer,uint NumberOfBytesToWrite,uint* pNumberOfBytesWritten,IntPtr Overlapped);

    [DllImport("kernel32.dll",SetLastError = true)]
    public static extern unsafe bool ReadFile(
        SafeFileHandle hFile,uint NumberOfBytesToRead,uint* pNumberOfBytesRead,SetLastError = true)]
    public static extern bool SetFilePointerEx(
        SafeFileHandle hFile,ulong liDistanceToMove,out ulong lpNewFilePointer,uint dwMoveMethod);

    [DllImport("kernel32.dll")]
    public static extern bool FlushFileBuffers(
        SafeFileHandle hFile);

    #endregion

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读