[转贴] VB对磁盘的物理扇区数据读/写操作

Option Explicit

'/////////////////////////////////////////
'// 对磁盘的物理扇区数据读/写操作
'// last update: 2004-8-7
'// Kwanhong Young
'/////////////////////////////////////////


'//file system
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long '//declare has changed
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long '//declare has changed
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long

Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000

Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = 3

Private Const INVALID_HANDLE_VALUE = -1

'//file seek
Private Const FILE_BEGIN = 0
Private Const FILE_CURRENT = 1
Private Const FILE_END = 2

Private Const ERROR_SUCCESS = 0&

'//device io control
Private Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, ByVal lpOverlapped As Long) As Long

Private Const IOCTL_DISK_GET_DRIVE_GEOMETRY As Long = &H70000 '458752
Private Const IOCTL_STORAGE_GET_MEDIA_TYPES_EX As Long = &H2D0C04
Private Const IOCTL_DISK_FORMAT_TRACKS As Long = &H7C018
Private Const FSCTL_LOCK_VOLUME As Long = &H90018
Private Const FSCTL_UNLOCK_VOLUME As Long = &H9001C
Private Const FSCTL_DISMOUNT_VOLUME As Long = &H90020
Private Const FSCTL_GET_VOLUME_BITMAP = &H9006F

'//type
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type

Private Enum MEDIA_TYPE
Unknown
F5_1Pt2_512
F3_1Pt44_512
F3_2Pt88_512
F3_20Pt8_512
F3_720_512
F5_360_512
F5_320_512
F5_320_1024
F5_180_512
F5_160_512
RemovableMedia
FixedMedia
End Enum

Private Type DISK_GEOMETRY
Cylinders As LARGE_INTEGER
MediaType As MEDIA_TYPE
TracksPerCylinder As Long
SectorsPerTrack As Long
BytesPerSector As Long
End Type

'//private vars
Private hDisk As Long 'disk handle
Private lpGeometry As DISK_GEOMETRY 'disk info
Private lBufferSize As Long 'the buffer size of read/write

Public Function OpenDisk(ByVal FileName As String) As Boolean
'// 打开磁盘
hDisk = CreateFile(FileName, _
GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
ByVal 0&, _
OPEN_EXISTING, _
0, _
0)
OpenDisk = Not (hDisk = INVALID_HANDLE_VALUE)
End Function

Public Function CloseDisk() As Boolean
'//关闭磁盘
CloseDisk = CloseHandle(hDisk)
End Function

Public Function GetDiskGeometry() As Boolean
'//获取磁盘参数
Dim dwOutBytes As Long
Dim bResult As Boolean

bResult = DeviceIoControl(hDisk, _
IOCTL_DISK_GET_DRIVE_GEOMETRY, _
ByVal 0&, 0, _
lpGeometry, Len(lpGeometry), _
dwOutBytes, _
ByVal 0&)

If bResult Then lBufferSize = lpGeometry.BytesPerSector * lpGeometry.SectorsPerTrack
GetDiskGeometry = bResult
End Function

Public Sub GetDiskInfo(MediaType As Long, _
Cylinders As Long, _
TracksPerCylinder As Long, _
SectorsPerTrack As Long, _
BytesPerSector As Long)
'//返回磁盘的参数
MediaType = lpGeometry.MediaType
Cylinders = lpGeometry.Cylinders.lowpart
TracksPerCylinder = lpGeometry.TracksPerCylinder
SectorsPerTrack = lpGeometry.SectorsPerTrack
BytesPerSector = lpGeometry.BytesPerSector

End Sub

Public Property Get BufferSize() As Long
'//返回每次读/写的缓冲大小
BufferSize = lBufferSize
End Property


Public Function LockVolume() As Boolean
'// 将卷锁定
Dim dwOutBytes As Long
Dim bResult As Boolean

bResult = DeviceIoControl(hDisk, _
FSCTL_LOCK_VOLUME, _
ByVal 0&, 0, _
ByVal 0&, 0, _
dwOutBytes, _
ByVal 0&)
LockVolume = bResult
End Function


Public Function UnlockVolume() As Boolean
'// 将卷解锁
Dim dwOutBytes As Long
Dim bResult As Boolean

bResult = DeviceIoControl(hDisk, _
FSCTL_UNLOCK_VOLUME, _
ByVal 0&, 0, _
ByVal 0&, 0, _
dwOutBytes, _
ByVal 0&)
UnlockVolume = bResult
End Function


Public Function DismountVolume() As Boolean
'// 将卷卸下,使系统重新辨识磁盘,等效于重新插盘
Dim dwOutBytes As Long
Dim bResult As Boolean

bResult = DeviceIoControl(hDisk, _
FSCTL_DISMOUNT_VOLUME, _
ByVal 0&, 0, _
ByVal 0&, 0, _
dwOutBytes, _
ByVal 0&)
DismountVolume = bResult
End Function


Public Function ReadDisk(ByVal Cylinders As Long, _
ByVal Tracks As Long, _
db() As Byte) As Boolean
'//按柱面和磁道来读取磁盘数据
Dim iPos As Long
Dim lRead As Long

iPos = Cylinders * Tracks * lBufferSize

If SeekAbsolute(0, iPos) Then
ReadDisk = ReadBytes(lBufferSize, db(), lRead)
End If
End Function

Public Function WriteDisk(ByVal Cylinders As Long, _
ByVal Tracks As Long, _
db() As Byte) As Boolean
'//按柱面和磁道来写磁盘数据
Dim iPos As Long
Dim lRead As Long

iPos = Cylinders * Tracks * lBufferSize

If SeekAbsolute(0, iPos) Then
WriteDisk = WriteBytes(lBufferSize, db())
End If
End Function


'/////////////////////////////////////////////////////////////////////////////////////
'//file system

Private Function SeekAbsolute(ByVal HighPos As Long, ByVal LowPos As Long) As Boolean
'//seek file
'//Notice: when you set LowPos=5, the read/write will begin with the 6th(LowPos+1) byte

LowPos = SetFilePointer(hDisk, LowPos, HighPos, FILE_BEGIN)
If LowPos = -1 Then
SeekAbsolute = (Err.LastDllError = ERROR_SUCCESS)
Else
SeekAbsolute = True
End If

End Function


Private Function ReadBytes(ByVal ByteCount As Long, ByRef DataBytes() As Byte, ByRef ActuallyReadByte As Long) As Boolean
'//read data to array
Dim RetVal As Long
RetVal = ReadFile(hDisk, DataBytes(0), ByteCount, ActuallyReadByte, 0)
'ActuallyReadByte =>> if the bytesRead=0 mean EOF
ReadBytes = Not (RetVal = 0)

End Function

Private Function WriteBytes(ByVal ByteCount As Long, ByRef DataBytes() As Byte) As Boolean
'//write data from array
Dim RetVal As Long
Dim BytesToWrite As Long
Dim BytesWritten As Long

RetVal = WriteFile(hDisk, DataBytes(0), ByteCount, BytesWritten, 0)

WriteBytes = Not (RetVal = 0)
End Function

展开阅读全文

如何实现对u盘物理扇区写操作

06-03

rn我有一个u盘。有一次我从计算机拔下u盘时没有采用安全方式,结果第二天就出问题了,插上u盘后报rnrn告“驱动器H中的磁盘未被格式化。”。我判断是u盘上的格式化信息被损坏了。于是我找来winhex对urnrn盘进行查看。发现我原来存储的文件都还在,而且0磁道、0柱面、1扇区的MBR数据有问题。我首先查看rnrn了一个正常的优盘的MBR,再比较有问题的优盘,发现:正常的MBR应该是一堆00 00 00 00 00 00 00 rnrn00 00 之后跟着一些不知意的十六进制数据,最后是MBR结束符号“55 aa”;而坏优盘是一堆FF FF FF rnrnFF FF FF FF FF FF FF FF FF FF FF FF FF FF FF(整个512个字节都是FF),只有最后两个字节是rnrn“55 aa”。rnrn于是我就想把这个优盘的MBR试着恢复一下。利用winhex的磁盘编辑功能,把好优盘的MBR复制,然后粘rnrn贴给坏优盘的同样位置。没想到winhex报告:只有Full版本(完整版本)才能使用物理扇区的写功能。rnrn郁闷,还得花钱买winhex的全版本。rnrn于是我又下载了另一个工具“DiskExplorer.exe”。用它可以修改坏优盘上的数据,提示改写成该。很rnrn高兴的再次查看坏优盘,发现根本错误的mbr根本就没有改变过来。rnrn于是,我又翻箱倒柜地找出以前曾经写过的一段改写物理扇区的代码,先读取512字节的好优盘mbr,再rnrn将其写回到坏优盘上。退出我的程序再次查看,还是不正确。后来我又想会不会是优盘的写入需要“安rnrn全删除硬件”才行,我就又试验了一次,可还是不行。rnrn我的代码是通过CreateFile("\\\\.\\H:", ... );的方式打开优盘,用ReadFile (hDevice, buffer, rnrn512*numberofsectors, &bytesread, NULL)读取好优盘数据,读取后数据也很正确,然后用WriteFile( rnrnhDevice, buffer, 512, &bytesread, NULL );返回值也是true。一切好像都没问题,可就是不能让坏rnrn优盘上的坏mbr改写成正确的。rnrn真是奇怪,我是在VC 6.0 WINDOWS XP环境下测试的,我怀疑是不是windows不允许直接写物理扇区啊?rnrn看其他文章说Windows禁止了int 13中断,不知道跟我的操作有没有影响。各位,哪个知道啊?我希望rnrn找回我优盘的数据,谁能帮助我呀?最好能给个能实现的代码,或者有哪个工具软件可以实现也行啊,rnrn最好发邮件给我。谢谢了。 论坛

没有更多推荐了,返回首页