[原创] 磁盘底层

[复制链接]

该用户从未签到

9

主题

9

回帖

31

积分

[INTOHARD]工兵

Rank: 1

积分
31
发表于 2008-10-7 13:30:46 | 显示全部楼层 |阅读模式
在VB中对硬盘的底层操作大全(二)

在VB中对硬盘的底层操作大全
   
  第一篇中讲到怎样读取物理硬盘的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
  • TA的每日心情
    开心
    2013-5-8 15:42
  • 签到天数: 2 天

    [LV.1]布衣百姓

    9

    主题

    64

    回帖

    168

    积分

    [INTOHARD]班长

    Rank: 2

    积分
    168
    发表于 2008-10-7 13:58:21 | 显示全部楼层
    看了头晕[s:199] [s:199] [s:199]

    该用户从未签到

    17

    主题

    411

    回帖

    679

    积分

    [INTOHARD]连长

    Rank: 4

    积分
    679
    QQ
    发表于 2008-10-7 17:08:45 | 显示全部楼层
    [s:166] [s:48] 太复杂了……

    该用户从未签到

    0

    主题

    9

    回帖

    19

    积分

    [INTOHARD]工兵

    Rank: 1

    积分
    19
    发表于 2008-10-16 20:49:38 | 显示全部楼层
    就不能来点通俗易懂的东西吗?

    该用户从未签到

    0

    主题

    34

    回帖

    118

    积分

    [INTOHARD]班长

    Rank: 2

    积分
    118
    发表于 2008-11-1 21:15:04 | 显示全部楼层
    谢谢楼主!
    一起学习了!

    该用户从未签到

    4

    主题

    59

    回帖

    108

    积分

    [INTOHARD]班长

    Rank: 2

    积分
    108
    发表于 2008-12-28 17:57:57 | 显示全部楼层
    不错,好东西不一定简单

    该用户从未签到

    0

    主题

    14

    回帖

    39

    积分

    [INTOHARD]工兵

    Rank: 1

    积分
    39
    发表于 2009-2-22 11:04:12 | 显示全部楼层
    好文章,感谢楼主.

    该用户从未签到

    1

    主题

    63

    回帖

    39

    积分

    [INTOHARD]工兵

    Rank: 1

    积分
    39
    发表于 2009-2-23 14:03:12 | 显示全部楼层
    好像有点难,先收藏下,谢谢

    该用户从未签到

    2

    主题

    487

    回帖

    848

    积分

    [INTOHARD]连长

    Rank: 4

    积分
    848
    QQ
    发表于 2009-6-4 12:31:39 | 显示全部楼层
    good good study !day day up!!!

    该用户从未签到

    15

    主题

    82

    回帖

    66

    积分

    [INTOHARD]班长

    Rank: 2

    积分
    66
    发表于 2009-7-18 20:59:59 | 显示全部楼层
    确实是好东西~~~~~~~多谢了。
    请教个问题。输出只能一个字节字节的输出么
    要是读取的字节数比较多。比如32K。那不是输出结果时的那个循环不是要循环32768次。如果读的更多那不是要循环N次。不知道有没有更好的办法
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表