首页 > 解决方案 > DumpSector 总是返回第一个磁盘扇区

问题描述

我从这里
得到代码 问题是无论我发送函数的扇区号是什么,它总是转储第一个扇区

DumpSector(string drive, double sector, int bytesPerSector)总是返回第一个磁盘扇区

drive = "\\.\PHYSICALDRIVE1"  
sector = from 0 to totalSectors
bytesPerSector = 512

我很抱歉大量的代码。

class LowReader
{
    #region "WMI LOW LEVEL COMMANDS"                
    public static int BytesPerSector(int drive)
    {
        int driveCounter = 0;
        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_DiskDrive");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                if (driveCounter == drive)
                {
                    var t = queryObj["BytesPerSector"];
                    return int.Parse(t.ToString());

                }
                driveCounter++;
            }
        }
        catch (ManagementException)
        {
            return -1;
        }
        return 0;
    }

    public ArrayList GetDriveList()
    {
        ArrayList drivelist = new ArrayList();

        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_DiskDrive");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                drivelist.Add(queryObj["DeviceID"].ToString());
            }
        }
        catch (ManagementException)
        {
            return null;
        }
        return drivelist;
    }

    public static long GetTotalSectors(int drive)
    {
        int driveCount = 0;
        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_DiskDrive");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                if (driveCount == drive)
                {
                    var t = queryObj["TotalSectors"];
                    return  long.Parse(t.ToString());

                }
                driveCount++;
            }
        }
        catch (ManagementException)
        {
            return -1;
        }
        return -1;
    }   

    public static int GetSectorsPerTrack(int drive)
    {
        int driveCount = 0;
        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_DiskDrive");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                if (driveCount == drive)
                {
                    var t = queryObj["SectorsPerTrack"];
                    return int.Parse(t.ToString());
                }
                driveCount++;
            }
        }
        catch (ManagementException)
        {
            return -1;
        }
        return -1;
    }

    public static int GetTotalTracks(int drive)
    {
        int DriveCount = 0;
        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_DiskDrive");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                if (DriveCount == drive)
                {
                    var t = queryObj["TotalTracks"];
                    return int.Parse((t.ToString()));
                }
                DriveCount++;
            }
        }
        catch (ManagementException)
        {
            return -1;
        }
        return -1;
    }

    #endregion
    #region "API CALLS" 

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

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

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

    [DllImport("kernel32", SetLastError = true)]
    internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes,
       int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);

    #endregion    
    public byte[] DumpSector(string drive, double sector, int bytesPerSector)
    {
        short FILE_ATTRIBUTE_NORMAL = 0x80;
        short INVALID_HANDLE_VALUE = -1;
        uint GENERIC_READ = 0x80000000;
        uint GENERIC_WRITE = 0x40000000;
        uint CREATE_NEW = 1;
        uint CREATE_ALWAYS = 2;
        uint OPEN_EXISTING = 3;

        SafeFileHandle handleValue = CreateFile(drive, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
        if (handleValue.IsInvalid)
        {
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
        double sec = sector * bytesPerSector;

        int size = int.Parse(bytesPerSector.ToString());
        byte[] buf = new byte[size];
        int read = 0;
        int moveToHigh;
        SetFilePointer(handleValue, long.Parse(sec.ToString()), out moveToHigh, EMoveMethod.Begin);
        ReadFile(handleValue, buf, size, out read, IntPtr.Zero);
        handleValue.Close();
        return buf;
    }

    private byte[] DumpTrack(string drive, double track, int bytesPerTrack, int TrackBufferSize)
    {
        short FILE_ATTRIBUTE_NORMAL = 0x80;
        short INVALID_HANDLE_VALUE = -1;
        uint GENERIC_READ = 0x80000000;
        uint GENERIC_WRITE = 0x40000000;
        uint CREATE_NEW = 1;
        uint CREATE_ALWAYS = 2;
        uint OPEN_EXISTING = 3;

        SafeFileHandle handleValue = CreateFile(drive, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
        if (handleValue.IsInvalid)
        {
            Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
        double trx = (track * bytesPerTrack * TrackBufferSize);

        int size = int.Parse(bytesPerTrack.ToString());
        byte[] buf = new byte[size * TrackBufferSize];
        int read = 0;
        int moveToHigh;
        SetFilePointer(handleValue, long.Parse(trx.ToString()), out moveToHigh, EMoveMethod.Begin);
        ReadFile(handleValue, buf, size, out read, IntPtr.Zero);
        handleValue.Close();
        return buf;
    }
}

标签: c#

解决方案


正如@HansPassant 所说

“SetFilePointer() 声明是完全错误的。在原始代码中错误,但在片段中变得更糟,看起来它被随机黑客攻击,直到它停止生成 MDA 警告。当你寻求帮助时总是提到这样的事情。喜欢SetFilePointerEx。 "

我改变了这个

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

对此

[DllImport("kernel32.dll")]
        public static extern bool SetFilePointerEx(
            SafeFileHandle hFile, 
            long liDistanceToMove,
            out long lpNewFilePointer, 
            uint dwMoveMethod);

我重构了代码中的用法。


推荐阅读