Direct Disk Access: WinAPI WriteFile seems to fail on partitions larger than 2147483647 (7FFF FFFF) sectors

与世无争的帅哥 提交于 2019-12-23 05:29:36

问题


I wrote a small program in VB .Net to physically sort folder entries on FAT partitions (see http://www.public.bplaced.net). To do this, I use API calls to Kernel32.dll. I open the partition with CreateFileA, use the handle to lock the drive with DeviceIoControl FSCTL_LOCK_VOLUME and then read and write sectors directly with SetFilePointer / ReadFile / WriteFile (synchronous, with NO_BUFFERING).

All works PERFECTLY, except when I use my program with partitions larger than 2147483647 sectors (7FFF FFFF hex), WriteFile reports success but returns (and has) 0 byte written. This is the case no matter which sector I try to write. EVERYTHING else seems to still work as it should (including correct sector reading). When I use PartitionWizard to shrink the partition below the above limit, writing works again.

Question: does ANYBODY have a clue what could cause this strange behavior? My wild guess is that 'something' might interpret a value greater than 7FFF FFFF as 'signed'? Not within my code, the 'total sectors of partition' is not needed anywhere.

A friend also said that when he did something similar with 'streams', writing worked even with a 'large' partition...

I'm a total N00b, I can't even memorize all the terminology (but I still want to program so dearly...), so if you might have an explanation / hint / whatever, please describe it as simple-worded and detailled as possible.

Some code snippets (don't know where to start)... program is compiled for x86 systems. Problem occurs on both Win7 x86 and 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

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

' open the partition by drive letter

    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 _
                             )

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

' lock the partition

    Dim unused_lv As UInteger

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

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

' set the file pointer, sector = sector to read, bytes_per_sector = 512. I use Bitconverter to get the hi and lo DWORDs

    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

来源:https://stackoverflow.com/questions/45116162/direct-disk-access-winapi-writefile-seems-to-fail-on-partitions-larger-than-214

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!