我在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