2 redcamel RedCamel 于 2016.01.21 07:39 提问

windows10下采用ReadFile读磁盘失败

求高手解答,给出解决方法,谢谢先!
我的小段程序原来可以读整个500G磁盘,XP,WIN7,WIN8下无论32位还是64位,
测试都OK,但在WIN10下失败,只能读到4G。
程序如下:
Public Class Form1
Public hDisk As Integer

Public Declare Function CreateFileA Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As Integer
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
Public Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Integer, ByVal lDistanceToMove As Integer, ByRef lpDistanceToMoveHigh As Integer, ByVal dwMoveMethod As Integer) As Integer
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Integer, ByVal lpBuffer() As Byte, ByVal nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer, ByVal lpOverLapped As Integer) As Integer

Public Enum DesiredAccess
    Read = &H80000000
    Write = &H40000000
    Execute = &H20000000
    All = &H10000000
End Enum

Public Enum ShareMode
    Delete = &H4
    Write = &H2
    Read = &H1
    None = 0
End Enum

Public Enum CreateMode
    CreateNew = 1
    CreateAlways = 2
    OpenExisting = 3
    OpenAlways = 4
    TruncateExisting = 5
End Enum

Public Enum OpResult
    ERROR_SUCCESS = 0
    INVALID_HANDLE_VALUE = -1
End Enum

Public Enum FileSeek
    FILE_BEGIN = 0
    FILE_CURRENT = 1
    FILE_END = 2
End Enum

Public Function OpenDisk(ByVal fileName As String) As Boolean
    Try
        hDisk = CreateFileA(fileName, DesiredAccess.Read Or DesiredAccess.Write, ShareMode.Read Or ShareMode.Write, IntPtr.Zero, CreateMode.OpenExisting, 0, IntPtr.Zero)
        OpenDisk = Not (hDisk = OpResult.INVALID_HANDLE_VALUE)
    Catch ex As Exception
        hDisk = False
    End Try
    Return hDisk
End Function

Public Function CloseDisk() As Boolean
    Try
        CloseDisk = CType(CloseHandle(hDisk), Boolean)
    Catch ex As Exception
        CloseDisk = False
    End Try
    Return CloseDisk
End Function

Public Function FxSetFilePointer(ByVal hFile As Integer, ByVal lDistanceToMove As Long, ByVal dwMoveMethod As Integer) As Boolean
    Try
        Dim PosL As Integer
        Dim PosH As Integer
        Dim ret As Integer

        Size2Long(lDistanceToMove, PosL, PosH)
        ret = SetFilePointer(hFile, PosL, PosH, dwMoveMethod)
        If ret = PosL Then
            FxSetFilePointer = True
        Else
            FxSetFilePointer = False
        End If
    Catch ex As Exception
        FxSetFilePointer = False
    End Try
    Return FxSetFilePointer
End Function

Private Sub Size2Long(ByVal FileSize As Long, ByRef IntLow As Integer, ByRef IntHigh As Integer)
    Try
        '&HFFFFFFFF unsigned = 4294967295
        Dim Cutoff As Long

        Cutoff = 2147483647
        Cutoff = Cutoff + 2147483647
        Cutoff = Cutoff + 1 ' now we hold the value of 4294967295 and not -1
        IntHigh = 0
        Do Until FileSize < Cutoff
            IntHigh = IntHigh + 1
            FileSize = FileSize - Cutoff
        Loop
        If FileSize > 2147483647 Then
            IntLow = CType(-Cutoff + (FileSize - 1), Integer)
        Else
            IntLow = CType(FileSize, Integer)
        End If
    Catch ex As Exception
        Throw ex
    End Try
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim a(512 - 1) As Byte

    If OpenDisk("\\.\PhysicalDrive0") = False Then
        MessageBox.Show("Cannot access disk", "Warnning", MessageBoxButtons.OK, MessageBoxIcon.Stop)
        End
    End If

    If FxSetFilePointer(hDisk, 0L * 512, FileSeek.FILE_BEGIN) = False Then
        Exit Sub
    End If

    If ReadFile(hDisk, a, 512, 0, 0) = 0 Then
        Exit Sub
    End If

    If FxSetFilePointer(hDisk, 8388607L * 512, FileSeek.FILE_BEGIN) = False Then
        Exit Sub
    End If

    If ReadFile(hDisk, a, 512, 0, 0) = 0 Then
        Exit Sub
    End If

    If FxSetFilePointer(hDisk, 8388608L * 512, FileSeek.FILE_BEGIN) = False Then
        Exit Sub
    End If

    'when sectors number>8388607, ReadFile failed, why, what can I do
    If ReadFile(hDisk, a, 512, 0, 0) = 0 Then
        Exit Sub
    End If

    If CloseDisk() = False Then
        MessageBox.Show("Some errors have been occured", "Warnning", MessageBoxButtons.OK, MessageBoxIcon.Stop)
        End
    End If
End Sub

End Class

3个回答

91program
91program   Ds   Rxr 2016.01.21 08:31

建议你设个断点测试一下,看看哪个函数失败了?再从失败的函数处,获取失败码,再来分析原因。

RedCamel
RedCamel 是ReadFile出错了,错误码87,查阅属于参数错误,问题是在XP,WIN7,WIN8下都正确的,在WIN10下出错,你觉得啥问题
接近 2 年之前 回复
RedCamel
RedCamel   2016.01.21 08:47

设置断点是肯定的,就是读扇区号大于8388608时,无法获得扇区内容了,如何获得失败码,请用代码片段告诉我,谢谢
If FxSetFilePointer(hDisk, 8388608L * 512, FileSeek.FILE_BEGIN) = False Then
Exit Sub
End If

If ReadFile(hDisk, a, 512, 0, 0) = 0 Then
Exit Sub
End If

RedCamel
RedCamel   2016.01.21 12:02

非常期待大牛不吝赐教,一直没有解决问题,在线等,谢谢先!

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!