======〉〉在VB中对硬盘的底层操作大全(二)〈〈======

viperstorm 2002-07-23 11:39:38

接小生昨天写的《在VB中对硬盘的底层操作大全(一)》,见http://www.csdn.net/Expert/TopicView1.asp?id=893191。

第一篇中讲到怎样读取物理硬盘的BootRecord的数据,用了如下的方法:

Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const OPEN_EXISTING = 3

'//为了简单起见,注意下面的声明语句部分地方已经改动过
Public 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
Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, _
ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Long) As Long
Public Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, _
ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Dim Buffer(1 To 512) As Byte
Dim hDevice As Long
Dim hadRead As Long
hDevice = CreateFile("\\.\PHYSICALDRIVE0", GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0&, 0&)

Call ReadFile(hDevice, Buffer(1), 512, hadRead, ByVal 0&) '//(****)

Dim i As Long
For i = 1 To 512
Debug.Print Hex$(Buffer(i));
Next

Call CloseHandle(hDevice)

这样数组buffer()里的512Byte的数据即为第一个物理硬盘的BootRecord数据了。我们可以将它保存在另外一个文件里,这样当万一我们的硬盘受到病毒的破坏导致分区不见了,就可以从这个文件恢复BootRecord,从而修复硬盘。

啊,那么怎样写数据入BootRecord呢?
MSDN里没有怎么讲,凭着我不入地狱谁入地狱的精神,我试过用WriteFile API函数就可以了,
首先看看怎样在瞬间“清空”硬盘的BootRecord。

将上面带 (****) 号的一句换成:

'//注意!千万不要调试/运行本段程序,除非你不想要你的硬盘了(在别人的机上除外哦 :)))
Call WriteFile(hDevice,Buffer(1),512,hadRead,Byval 0&)

由于Buffer()里面的数据都是00000……,这样,机器上的第一个物理硬盘的BootRecord数据全部变成0…000了,换句话说,MBR和主分区表DPT都被破坏了。如果想破坏硬盘上的所有数据,那也是很简单的事,只要不断地 WriteFile,用0000填充硬盘上的所有数据就可以了,这样硬盘上的其他部分(DBR、FAT、DIR、DATA)都会被清空。(哎呀,怎么越讲越离题了!都教人搞破坏去了,该批斗!)

言归正传了,如果首先在Buffer()存有原来硬盘的BootRecord数据,再调用WriteFile,那么就是变成恢复硬盘的BootRecord了,(要是少了这一步,那真是一失足成千古恨)。

下面开始今天的新内容。

一、我们知道一个物理硬盘可以分成多个区的,从而形成多个逻辑盘。那么逻辑盘的信息是保存在哪里的呢?例如一个逻辑盘的卷标、序列号、大小等。其实每个逻辑盘也有类似的BootRecord。而且根据文件系统的不同,其BootRecord的数据结构都不太相同。下面就列出几种常见的文件系统的BootRecord的数据结构。

(1)NTFS的:
Private Type NTFSBOOTRECORD
JumpCodeAndNop(1 To 3) As Byte
OEMName(1 To 8) As Byte
BytesPerSector As Integer
SectorsPerCluster As Byte
Unused(1 To 7) As Byte
MediaDescriptor As Byte
Unused2 As Integer
SectorsPerTrack As Integer
HeadCount As Integer
Unused3(1 To 8) As Byte
DontKnow1 As Integer
DontKnow2 As Integer
SectorsInStorageUnit As Currency
LCNMFTData As Currency
LCNMFTMirrorData As Currency
FileRecordClusters As Long
IndexBufferClusters As Long
SerialNumber As Long
End Type

(2)FAT16的:
Private Type FAT12FAT16BOOTRECORD
JumpCodeAndNop(1 To 3) As Byte
OEMName(1 To 8) As Byte
BytesPerSector As Integer
SectorsPerCluster As Byte
ReservedSectors As Integer
NumberOfFATCopies As Byte
MaxRootDirEntries As Integer 'N/A on FAT32
SectorsSmallerThan32MB As Integer 'N/A on FAT32
MediaDescriptor As Byte 'F8h for Hard Disks
SectorsPerFATOld As Integer 'N/A on FAT32
SectorsPerTrack As Integer
NumberOfHeads As Integer
HiddenSectors As Long
Sectors As Long

DriveNum As Byte
Reserved As Byte
BootSignature As Byte
VolumeID As Long
VolumeLabel(1 To 11) As Byte
FileSystemType(1 To 8) As Byte
End Type

(3)FAT32的:
Private Type FAT32BOOTRECORD
JumpCodeAndNop(1 To 3) As Byte
OEMName(1 To 8) As Byte
BytesPerSector As Integer
SectorsPerCluster As Byte
ReservedSectors As Integer
NumberOfFATCopies As Byte
MaxRootDirEntries As Integer 'N/A on FAT32
SectorsSmallerThan32MB As Integer 'N/A on FAT32
MediaDescriptor As Byte 'F8h for Hard Disks
SectorsPerFATOld As Integer 'N/A on FAT32
SectorsPerTrack As Integer
NumberOfHeads As Integer
HiddenSectors As Long
Sectors As Long

SectorsPerFAT As Long
Flags As Integer
Version As Integer
RootDirectoryCluster As Long
FileSystemInformationSector As Integer
BackupBootSector As Integer
Reserved(1 To 12) As Byte
LogicalDriveNumber As Byte
Unused As Byte
ExtendedSignature As Byte '29h
SerialNumber As Long
VolumeName(1 To 11) As Byte
FATName(1 To 8) As Byte
ExecutableCode(1 To 420) As Byte
BootRecordSignature(1 To 2) As Byte '55h AAh
End Type

我们怎样知道一个逻辑盘(如C:\;D:\;G:\)的文件系统是什么呢?方法有很多,例如在“我的电脑”中对着逻辑盘右击鼠标,选择“属性”,就可以看到它的文件系统了。(只见一大堆烂番茄飞向小生,“我们要的是用编程方法呀!!SB……”)

用 GetVolumeInformation API函数即可轻松搞定了,下面是个获取一个盘的文件系统的自定义函数。其中参数Drive为盘符,如“C:”、“D:”、“I:”

Public Function GetFileSystem(Drive As String) As String
Dim VolName As String, FileSystem As String, SerialNum As Long
Dim MaxFileLen As Long, Flags As Long
VolName = String(16,chr$(0))
FileSystem = String(16,chr$(0))
GetVolumeInformation Drive & "\", VolName, Len(VolName) - 1, _
SerialNum, MaxFileLen, Flags, FileSystem, Len(FileSystem) - 1

Dim Pos As Integer
Pos = InStr(FileSystem, Chr(0))
If Pos Then
GetFileSystem = UCase(Left(FileSystem, Pos - 1))
Else
GetFileSystem = UCase(FileSystem)
End If

End Function

好了,最后,怎样读取逻辑盘的BootRecord呢?方法跟读取物理硬盘的BootRecord基本相同。各个逻辑盘的名称为在盘符前面添加"\\.\",如C盘即为"\\.\C:",H盘即为"\\.\H:"
下面例子我们打开D:盘,并读取BootRecord的数据。

Dim hDrive as long
Dim Buffer(1 To 512) As Byte, Read As Long
Dim RetVal As Long
Dim i AS long

hDrive = CreateFile("\\.\D:", GENERIC_READ, FILE_SHARE_READ Or _
FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0, 0)
If hDrive = INVALID_HANDLE_VALUE Then
MsgBox "Error opening the drive."
Else
RetVal = ReadFile(hDrive, Buffer(1), 512, Read, byval 0&)
If RetVal And (Read = UBound(Buffer)) Then
'//在此打印Buffer里的数据内容
For i=1 to 512
Debug.print Hex$(Buffer(i));
Next
Else
MsgBox "Error reading the drive."
End If
End If
CloseHandle hDrive

晚上的蚊子特别多,受不了啦。第二篇就先写到此了。敬请留意第三篇:
“在VB中对硬盘的底层操作大全(三)未解问题一堆(高分征解)”
...全文
194 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
bitcat 2002-10-01
  • 打赏
  • 举报
回复
收藏,关注!
zhangxu421 2002-10-01
  • 打赏
  • 举报
回复
神奇!
本来我以为自己够狠了
没想到比我更狠的还大有人在
现在真是自叹不如了

楼上的老兄们思路的确很高明,让我大开眼界

叹,原来VB写恶意代码还真很方便.
以后一定要好好学习
NowCan 2002-10-01
  • 打赏
  • 举报
回复
太厉害了。看不懂。
crystal_heart 2002-10-01
  • 打赏
  • 举报
回复
前提条件:操作系统win2000以上。
读取硬盘物理ID是可以的,不过你要自己去翻很多structure,很多是在VC那里的。
skydg 2002-10-01
  • 打赏
  • 举报
回复
good
4_Eye_Cat 2002-08-28
  • 打赏
  • 举报
回复
qb可以
调用interruopt......什么lib就可以了
要回去找找"笔记"才知道~


以前用qb做过自己的 fdisk 呵呵
还得去找找有没有源马
_stone 2002-07-25
  • 打赏
  • 举报
回复
gz
Greaitm 2002-07-25
  • 打赏
  • 举报
回复
mask
Greaitm 2002-07-25
  • 打赏
  • 举报
回复
mark
hyryxgs 2002-07-25
  • 打赏
  • 举报
回复
up
viperstorm 2002-07-25
  • 打赏
  • 举报
回复
在VB中对硬盘的底层操作大全(三)及未解难题100分征解出来了,
请见:
http://www.csdn.net/Expert/TopicView1.asp?id=902136
dsclub 2002-07-24
  • 打赏
  • 举报
回复
再收
viperstorm 2002-07-23
  • 打赏
  • 举报
回复
gz!!
YHeng 2002-07-23
  • 打赏
  • 举报
回复
VB能否直接读取硬盘的物理序列号呢??????
笨笨2011 2002-07-23
  • 打赏
  • 举报
回复
up
tgc99 2002-07-23
  • 打赏
  • 举报
回复
接着说呀。
golden24kcn 2002-07-23
  • 打赏
  • 举报
回复
你是说QB可以读到硬盘的分区表了??
wgku 2002-07-23
  • 打赏
  • 举报
回复
UP
fontz 2002-07-23
  • 打赏
  • 举报
回复
做个标记,也许将来有用。
Fnems 2002-07-23
  • 打赏
  • 举报
回复
傻瓜!如果硬盘真的坏了,Windows系统都进不去,还怎么执行你的程序?还是学学QuickBasic吧。
加载更多回复(1)

7,785

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧