直接磁盘访问:WinAPI WriteFile似乎在大于2147483647(7FFF FFFF)扇区的分区上失败

时间:2017-07-15 08:29:37

标签: vb.net winapi readfile partition

我在VB .Net中编写了一个小程序,对FAT分区上的文件夹条目进行物理排序(参见http://www.public.bplaced.net)。为此,我使用对Kernel32.dll的API调用。我用CreateFileA打开分区,使用句柄用DeviceIoControl FSCTL_LOCK_VOLUME锁定驱动器,然后直接用SetFilePointer / ReadFile / WriteFile读取和写入扇区(同步,NO_BUFFERING)。

所有工作都完美无缺,除非我的程序使用大于2147483647扇区的分区(7FFF FFFF十六进制),WriteFile报告成功但返回(并且有)0字节写入。无论我尝试写哪个部门,情况都是如此。其他一切似乎仍然有效(包括正确的扇区阅读)。当我使用PartitionWizard将分区缩小到上述限制以下时,写入再次起作用。

问题:ANYBODY有什么可能导致这种奇怪行为的线索吗?我的猜测是“某些东西”可能会将大于7FFF FFFF的值解释为“已签名”?不在我的代码中,任何地方都不需要“分区的总扇区”。

一位朋友还表示,当他用“溪流”做类似的事情时,写作甚至可以使用“大”分区......

我总是N00b,我甚至无法记住所有的术语(但我仍然想要编程如此......),所以如果您有解释/提示/其他什么,请将其描述为简单尽可能多地留下来。

一些代码片段(不知道从哪里开始)...程序是为x86系统编译的。 Win7 x86和Win7 x64都出现问题。

<DllImport("kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function DeviceIoControl _
         ( _
         ByVal hDevice As IntPtr, _
         ByVal dwIoControlCode As UInteger, _
         ByVal lpInBuffer As IntPtr, _
         ByVal nInBufferSize As UInteger, _
         ByVal lpOutBuffer As IntPtr, _
         ByVal nOutBufferSize As UInteger, _
         ByRef lpBytesReturned As UInteger, _
         ByVal lpOverlapped As IntPtr _
         ) _
         As Integer
End Function

Public Declare Function CreateFile Lib "kernel32" _
    Alias "CreateFileA" ( _
                        ByVal lpFileName As String, _
                        ByVal dwDesiredAccess As Int32, _
                        ByVal dwShareMode As Int32, _
                        ByVal lpSecurityAttributes As IntPtr, _
                        ByVal dwCreationDistribution As Int32, _
                        ByVal dwFlagsAndAttributes As Int32, _
                        ByVal hTemplateFile As Int32 _
                        ) _
                        As IntPtr

Public Declare Function SetFilePointer Lib "kernel32" _
                    ( _
                    ByVal hFile As IntPtr, _
                    ByVal lpDistanceToMove As UInt32, _
                    ByRef lpDistanceToMoveHigh As Int32, _
                    ByVal dwMoveMethod As UInt32 _
                    ) _
                    As UInt32

Public Declare Function WriteFile Lib "kernel32" _
                        ( _
                        ByVal hFile As IntPtr, _
                        ByVal lpBuffer As Byte(), _
                        ByVal nNumberOfBytesToWrite As Int32, _
                        ByRef lpNumberOfBytesWritten As Int32, _
                        ByVal lpOverlapped As IntPtr _
                        ) _
                        As Boolean

'********************************************** ************

'按驱动器号

打开分区
    devicehandle = CreateFile( _
                             "\\.\" & driveletter & ":", _
                             GENERIC_READ Or GENERIC_WRITE, _
                             FILE_SHARE_READ Or FILE_SHARE_WRITE, _
                             IntPtr.Zero, _
                             OPEN_EXISTING, _
                             FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_NO_BUFFERING, _
                             0 _
                             )

'********************************************** ************

'锁定分区

    Dim unused_lv As UInteger

    Dim locked As Integer = DeviceIoControl( _
                                           devicehandle, _
                                           FSCTL_LOCK_VOLUME, _
                                           IntPtr.Zero, _
                                           0, _
                                           IntPtr.Zero, _
                                           0, _
                                           unused_lv, _
                                           IntPtr.Zero _
                                           )

'********************************************** ************

'设置文件指针,扇区=扇区读取,bytes_per_sector = 512.我使用Bitconverter获取hi和lo DWORD

    Dim s_bytes() As Byte = BitConverter.GetBytes(sector * bytes_per_sector)
    ' Hi-DWORD
    Dim byte_dist_high As Int32 = BitConverter.ToInt32(s_bytes, 4)   ' byte 4 - 7
    ' Lo-DWORD
    Dim byte_dist_low As UInt32 = BitConverter.ToUInt32(s_bytes, 0)  ' byte 0 - 3

    ' move file pointer
    Dim move As UInt32 = SetFilePointer( _
                         devicehandle, _
                         byte_dist_low, _
                         byte_dist_high, _
                         FILE_BEGIN _
                         )

'********************************************** ************

    ' write a sector
    Dim write As Boolean = WriteFile( _
                                    devicehandle, _
                                    buffer, _
                                    bytes_per_sector, _
                                    bytes_written, _
                                    IntPtr.Zero _
                                    )

    If write = False Then
        Return False
    Else
        Return True
    End If

0 个答案:

没有答案