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币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
通过CreateFile来读取磁盘扇区的方法
测试程序包括两个测试方法,以#define SECTOR 开关进行相应的程序段测试,程序在XP + vc6 环境下测试通过,程序如下: #include "stdafx.h"/* -------------------------------------------------------------------------- ** * *    1   读取磁盘扇区* ** ------
ReadFile 函数
函数原型   BOOL ReadFile(  HANDLE hFile, //文件的句柄  LPVOID lpBuffer, //用于保存读入数据的一个缓冲区  DWORD nNumberOfBytesToRead, //要读入的字符数  LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针  LPOVERLAPPED lpOverlapped
windows 无法安装到这个磁盘。选中的磁盘采用GPT 分区形式
有时候用原版系统镜像安装windows系统时,会提示“windows无法安装到这个磁盘。选中的磁盘采用GPT分区形式”,导致安装失败,下面就来讲解一下如何解决。 工具/原料 电脑 键盘 方法/步骤 在系统提示无法安装的那一步,按住“shift+f10”,呼出“c
ReadFile异步读设备
#include #include int main (void) { HANDLE hDevice=CreateFile(TEXT("C:\\1.txt"), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, ///此处设置F
使用createfile window下读写硬盘数据
CreateFile( "\\\\.\\PhysicalDrive1", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ); 文件名中的\\.表示window NT中的一个特殊目录。 硬盘的文件名可以用winobj查找到。  打开winobj软件查看GLOBAL目录。   ReadFile()读
解决串口通讯中部分串口ReadFile使用SetCommTimeouts设置超时无效的问题
在串口通讯中(笔者系统为32位win7),为简单起见,经常采用同步方式读取串口数据。即调用CreateFile函数打开串口时,不设置其倒数第二个参数为FILE_FLAG_OVERLAPPED。       此时,一般需要设置ReadFile读取数据的超时时间,或者直接设置其不论是否读取到数据,都立即返回。否则,可能由于ReadFile无限期等待读取数据而造成线程阻塞。       设置串口读取
使用InternetReadFile时要注意读取完整数据
使用这个api读取数据后,即使数据不完整,该函数不会报任何错,GetLastError也显示操作成功。使用时要注意通过其参数判断是否读取完毕void InternetReadFileEx(HINTERNET request, std::string& data) { DWORD readed = 0; char buffer[1025]; do { ZeroM
【java】读写磁盘文件
一、读txt文件public static String readFile(File file, String charset){ //设置默认编码 if(charset == null){ charset = &quot;UTF-8&quot;; } if(file.isFile() &amp;amp;&amp;amp; f...
串口通信中ReadFile和WriteFile的超时详解!
在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。 有两种超时:间隔超时和
InternetReadFile如何正确读取二进制文件
手上的一个VB项目(过程中发现,.Net果然是好啊),需要在一个ActiveX中实现HTTP下载功能,我是采用InternetreadFile这个API来实现,一开始的代码我是这么写的 Function Gethttpdownload(sUrl As String) As boolen Dim s As StringDim hOpen As LongDim hOpenUrl As