Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么用C#读取原始磁盘时偏移量略有变化?_C#_Winapi_Deviceiocontrol - Fatal编程技术网

为什么用C#读取原始磁盘时偏移量略有变化?

为什么用C#读取原始磁盘时偏移量略有变化?,c#,winapi,deviceiocontrol,C#,Winapi,Deviceiocontrol,我正在尝试读取原始磁盘。我已成功打开驱动器并获得有效句柄(CreateFile),将该句柄的偏移量设置为零(SetFilePointerEx),并将数据读取到缓冲区字节[](ReadFile)。到现在为止,一直都还不错。但不知什么原因,当我将缓冲区(我花了一段时间才真正弄清楚)与第三方实用程序(Disk Investor)显示的内容进行比较时。它不包含引导信息(跳转指令),但包含正确的磁盘数据,但从偏移量85=0x55开始。所以在某个中间的音量引导信息中, 为什么呢?是否有什么东西我遗漏了(很明

我正在尝试读取原始磁盘。我已成功打开驱动器并获得有效句柄(CreateFile),将该句柄的偏移量设置为零(SetFilePointerEx),并将数据读取到缓冲区
字节[]
ReadFile)。到现在为止,一直都还不错。但不知什么原因,当我将缓冲区(我花了一段时间才真正弄清楚)与第三方实用程序(Disk Investor)显示的内容进行比较时。它不包含引导信息(跳转指令),但包含正确的磁盘数据,但从偏移量85=0x55开始。所以在某个中间的音量引导信息中,

为什么呢?是否有什么东西我遗漏了(很明显我遗漏了)

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

代码:

创建文件(其他位置)

平沃克方法:

[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,
            IntPtr.Zero,
            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, 0, 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, out n, (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 offset, int count) {
      Write(buffer, (uint)offset, (uint)count);
    }
    public unsafe void Write(byte[] buffer, uint offset, uint count)
    {
        uint n = 0;
        fixed (byte* p = buffer)
        {
            if (!DeviceIO.WriteFile(this.fileHandle, p + offset, count, &n, 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, offset, out n, (uint)origin))
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        return n;
    }

    public uint ReadSector(DiskSector sector)
    {
        return this.Read(sector.Data, 0, sector.SectorSize);
    }
    public void WriteSector(DiskSector sector)
    {
        this.Write(sector.Data, 0, sector.SectorSize);
    }
    public void SeekSector(DiskSector sector)
    {
        this.Seek(sector.Offset, SeekOrigin.Begin);
    }
}
DeviceIO类是Win32 API的p/invoke样板文件

DiskInfo类是WMI
Win32\u DiskDrive
Win32\u DiskPartition
类的包装

我曾经用这个库克隆了一个磁盘(在Win7上)。希望这有助于找到解决办法

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

//
///围绕Win32函数和常量的P/Invoke包装器。
/// 
内部部分类设备
{
#非托管函数中使用的区域常量
公共构造文件\u共享\u读取=0x00000001;
公共构造文件共享写入=0x00000002;
公共构造文件共享删除=0x00000004;
公共警察局开放的现有人数=3人;
公共警察通用读取=(0x8000000);
公共consunt GENERIC_WRITE=(0x40000000);
公共警察文件\u标志\u无\u缓冲=0x20000000;
公共警察文件标志写入=0x8000000;
公共构造文件\u读取\u属性=(0x0080);
公共构造文件写入属性=0x0100;
公共警察错误\u缓冲区不足=122;
#端区
#区域未更改的函数声明
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态不安全外部安全文件句柄CreateFile(
字符串文件名,
您不希望访问,
uint共享模式,
IntPtr安全属性,
你的创意是什么,
uint标志和属性,
IntPtr-hTemplateFile);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部布尔闭合手柄(SafeFileHandle hHandle);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部布尔设备控制(
SafeFileHandle hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
单位尺寸,
[Out]IntPtr LPEXBUFFER,
单位无缓冲尺寸,
返回的ref uint LPBYTES,
IntPtr(重叠);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部不安全bool WriteFile(
安全文件句柄,
字节*pBuffer,
uint NumberOfBytesToWrite,
uint*p写入的字节数,
IntPtr重叠);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部不安全bool ReadFile(
安全文件句柄,
字节*pBuffer,
uint NumberOfBytesToRead,
uint*P字节数读取,
IntPtr重叠);
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部布尔SetFilePointerEx(
安全文件句柄,
ulong liDistanceToMove,
out ulong lpNewFilePointer,
uint法);
[DllImport(“kernel32.dll”)]
公共静态外部bool FlushFileBuffers(
安全文件句柄(hFile);
#端区
}

我没有得到有关启动信息的部分。你想达到什么目的?在相同的偏移量下,您的读取是否显示与磁盘util不同的数据?也许你在其中一个打开了一个分区,在另一个打开了一个卷?我只是想读取原始磁盘。它应该以NTFS引导扇区的跳转指令(偏移量0处的0xEB5290)开始。但当我从\\.\PhysicalDrive2读取句柄时,它只从偏移量85读取。所以我无法读取前84个字节。即使SetFilePointerEx设置为0,我也很难相信它读取的偏移量不均匀,因为这会移动整个磁盘。由于偏移量,您将无法读取完整的磁盘扇区(比如512字节)。那不可能是真的。你的虫子在别处。可能你误解了数据。你能展示一下你得到了什么和你期望得到什么吗?好的。我和你一样困惑。当我使用非对齐读取时,它会像人们预期的那样失败,当我从偏移量<0读取时,它也会失败(正如预期的那样)。SetFilePointerEx正确返回0(无错误)。这是个谜。我猜应该是readfile的PInvoke定义或者没有缓冲区的东西。我将添加一些代码和定义。我还添加了一些代码。抱歉,这是大型项目的一部分,所以很难将位(尤其是枚举)分开。谢谢。我已经知道怎么做了,但是它从偏移量85开始读取,而不是从0开始读取。所以我丢失了84个字节。这是问题的核心。@SmartK8听起来是一个细节。你用偏移量和长度乘以字节数吗?是的,我用。但是数据很奇怪,所以我试着将offset设置为0(当然)。并期望看到引导扇区的跳转指令。我得到的是33C0BE。。相反所以我用磁盘检查器来搜索它。它是在原始磁盘偏移量85处发现的。即使我将偏移量设置为0,它也会成功。@SmartK8注意向前读取(MBR),但需要向后解析(它是little endian)…就是这样。。(非)问题已解决。我接受你的答案,因为它基本上是正确的。问题在于输入的类型
public enum WinMoveMethod : uint
{   
    Begin   = 0,
    Current = 1,
    End     = 2
}
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,
            IntPtr.Zero,
            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, 0, 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, out n, (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 offset, int count) {
      Write(buffer, (uint)offset, (uint)count);
    }
    public unsafe void Write(byte[] buffer, uint offset, uint count)
    {
        uint n = 0;
        fixed (byte* p = buffer)
        {
            if (!DeviceIO.WriteFile(this.fileHandle, p + offset, count, &n, 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, offset, out n, (uint)origin))
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        return n;
    }

    public uint ReadSector(DiskSector sector)
    {
        return this.Read(sector.Data, 0, sector.SectorSize);
    }
    public void WriteSector(DiskSector sector)
    {
        this.Write(sector.Data, 0, sector.SectorSize);
    }
    public void SeekSector(DiskSector sector)
    {
        this.Seek(sector.Offset, SeekOrigin.Begin);
    }
}
/// <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,
        byte* pBuffer,
        uint NumberOfBytesToRead,
        uint* pNumberOfBytesRead,
        IntPtr Overlapped);

    [DllImport("kernel32.dll", 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

}