自制程序读取FAT32文件系统上的文件

winxp上无法识别大容量的FAT32分区,这时候需要自己写个小程序来获取分区中的文件。

一、FAT32文件系统简介

(一)硬盘主引导扇区

硬盘主引导扇区 = 硬盘主引导记录(MBR+ 硬盘分区表(DPT

 

硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等。每个盘片有两面,都可记录信息。盘片被分成许多扇形的区域,每个区域叫一个扇区,每个扇区可存储128×2N次方(N0.1.2.3)字节信息。在DOS中每扇区是128×22次方=512字节,盘片表面上以盘片中心为圆心,不同半径的同心圆称为磁道。硬盘中,不同盘片相同半径的磁道所组成的圆柱称为柱面。磁道与柱面都是表示不同半径的圆,在许多场合,磁道和柱面可以互换使用,我们知道,每个磁盘有两个面,每个面都有一个磁头,习惯用磁头号来区分。扇区,磁道(或柱面)和磁头数构成了硬盘结构的基本参数,帮这些参数可以得到硬盘的容量,基计算公式为:
存储容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数

要点:(1)硬盘有数个盘片,每盘片两个面,每个面一个磁头

2)盘片被划分为多个扇形区域即扇区

3)同一盘片不同半径的同心圆为磁道

4)不同盘片相同半径构成的圆柱面即柱面

5)公式: 存储容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数

6)信息记录可表示为:××磁道(柱面),××磁头,××扇区

 

物理位置:001扇区(clindyer 0, side 0, sector 1)

大小: 512字节0

其中:MBR 446字节(0000--01BD),DPT 64字节(01BE--01FD),结束标志2字节(55 AA

功能:MBR通过检查DPT分区信息引导系统跳转至DBR

读取: 使用NORTON DISKEDIT, OBJECT菜单中选择DRIVE——>PHYSICAL DISK-HARD DISK,

然后, OBJECT菜单中选择DISK PARTITION TABLE即可读取, 并使用TOOLS菜单中的WRITE OBJECT TO 选项存入指定文件备份;

写入: 使用NORTON DISKEDIT, OBJECT菜单中选择DRIVE——>FLOOPY DISK, 选择备份的DPT

文件, 然后使用TOOLS菜单中的WRITE OBJECT TO——>PHYSICAL SECTOR 选项写入001

(clindyer 0, side 0, sector 1);

 

详解:

000H--08AH MBR启动程序(寻找开机分区)

08BH--0D9H MBR启动字符串

0DAH--1BCH 保留("0")

1BEH--1FDH 硬盘分区表

1FEH--1FFH 结束标志(55AA)

 

 

活动分区主引导扇区(DBR

--------------------------

物理位置:101扇区(clindyer 0, side 1, sector 1)

大小: **T16 1扇区 512字节

**T32 3扇区 1536字节

功能:包含机器CMOS等信息(0000--0059, 核对该信息并引导指定的系统文件, NTLDR等;

读取: 使用NORTON DISKEDIT, OBJECT菜单中选择DRIVE——>LOGICAL DISK-DISK C,

然后, OBJECT菜单中选择BOOT RECORD即可读取, 并使用TOOLS菜单中的

WRITE OBJECT TO 选项存入指定文件备份;

写入: 使用NORTON DISKEDIT, OBJECT菜单中选择DRIVE——>FLOOPY DISK, 选择备份的DBR

文件, 然后使用TOOLS菜单中的WRITE OBJECT TO——>PHYSICAL SECTOR 选项写入011

(clindyer 0, side 1, sector 1);

 

 

详解:

 

000H--002H 3 BYTE的跳转指令(去启动程序, 跳到03EH)

003H--03DH BIOS参数区

03EH--19DH DOS启动程序

19EH--1E5H 开机字符串

1E6H--1FDH 文件名(IO.SYS, MSDOS.SYS)

1FEH--1FFH 结束标记(55AA)

 

硬盘分区表(DPT

---------------------

01BE 1 分区类型:00表示非活动分区:80表示活动分区;其他为无效分区。

01BF~01C1 3 *分区的起始地址(面/扇区/磁道),通常第一分区的起始地址开始

101扇区,因此这三个字节应为010100

01C2 1 #分区的操作系统的类型。

01C3~01C5 3 *该分区的结束地址(面//道)

01C6~01C9 4 该分区起始逻辑扇区

01CA~01CD 4 该分区占用的总扇区数 

 

1:此处第一个字节存放磁头号(010B),第二字节低六位存放扇区号01=0000 0001=0001)、FE=1111 1110=113F),第二字节高2+第三字节为柱面号0000=000117F=37F

 

(磁头) 8 ,扇区 6 ,磁道 10

 

还需要说明的是01BF01C13个字节在分区表里面,视后面01C2字节所示分区类型的不同而代表不同的含义。如果01C2是代表主分区的01 04060B,那么01BF01C1所表示的就是该分区DBR所在的位置,如果01C2是代表扩展分区的050F,那么01BF01C1所表示 的就是该分区MBR所在的位置。第一个分区表项(01BE01CD)描述的是C:盘的信息,第二个分区表项(01CE01DD)描述的是整个扩展分区的信息,它把剩下的D:、E:全部包含在里面了!第二个分区表项的分区类型符为0F,也就是说是扩展分区,那么分区类型符前面3个字节所代表的应该是扩展分区MBR所在的位置。可见不光是全盘最前面的0磁头0柱面1扇区有一份主MBR,扩展分区的最前面也有一份MBR

 

分区文件系统标志:

分区未用: 0x00H.

扩展分区: 0x05H, 0x0FH.

FAT16分区: 0x06H.

FAT32分区: 0x0BH, 0x1BH, 0x0CH, 0x1CH.

NTFS分区: 0x07H.

 

DPT 总共64字节(01BE--01FD, 如上所示每个分区占16个字节, 所以可以表示四个分区, 这也

就是为什么一个磁盘的主分区和扩展分区之和总共只能有四个的原因.

 

逻辑驱动器

-----------

扩展分区的信息位于以上所示的硬盘分区表(DPT)中, 而逻辑驱动器的信息则位于扩展分区的

起始扇区, 即该分区的起始地址(面/扇区/磁道)所对应的扇区, 该扇区中的信息与硬盘主引导

扇区的区别是不包含MBR, 16字节的分区信息则表示的是逻辑驱动器的起始和结束地址等.

 

 

所以, 在磁盘仅含有一个主分区, 一个扩展分区(包含多个逻辑驱动器)的情况下, 即使由于病毒

或其他原因导致硬盘主引导扇区的数据丢失(包括DPT), 也可以通过逻辑驱动器的数据来恢复整个硬盘.

 

例如: 以下是一个硬盘的分区情况.

 

起始扇(逻辑) 结束扇 总共扇区

MBR 0 0 1 - - - - - -

C 0 1 1 276 239 63 63 4,188,239 4,188,177

277 0 1 554 239 63 4,188,240 8,391,599 4,203,360

D 277 1 1 554 239 63 4,188,303 8,391,599 4,203,297

 

 

如果主分区表损坏, 则可以通过手工查找扩展分区表中所包含的逻辑驱动器数据, 在本例中就是D盘所对应的数据, 然后将其起始扇(逻辑)减去63就是所对应的扩展分区的起始扇(逻辑), 将其起始地址(面/扇区/磁道)改为0面就是扩展分区的起始地址. 然后通过扩展分区就可以得到主分区C的信息, 然后就可以使用FDISK/MBR命令和手工填写分区表恢复整个硬盘.

 

实际使用这种方法比较麻烦, 如果知道每个分区的大小, 则可以通过使用PQ MAGIC 5 将磁盘重新分区为原来大小(注意: 千万不能应用, 我们只是通过它来获得数据), 并查看INFO来获得以上

数据, 记录以后取消该分区操作, 然后使用NORTON DISK2000手工修改DPT, 恢复整个硬盘.

 

该例所对应的分区表数据:

 

80 01

01 00 06 EF 7F 14 3F 00 00 00 11 E8 3F 00 00 00

41 15 05 EF BF 2A 50 E8 3F 00 60 23 40 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

 

例如:

分区表:

00 01 01 00 83 FE FF FF 3F 00 00 00 42 45 1C 1D

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

55 AA

 

扩展分区表数据:

00 01

41 15 07 EF BF 2A 8F E8 3F 00 21 23 40 00

 

 

注意: 逻辑起始扇区和总共分区数是左边为低位, 如该例的扩展分区的起始地址为50 E8 3F 00转换十进制时要先变为00 3F E8 50, 总共占用分区数60 23 40 00要先变为00 40 23 60, 同理当手工填写该值时也要进行高低位转换.

 

(二)引导扇区(Boot   sector)的结构:    

  当主引导程序找到了带有引导标识为80H的分区后,就会将该分区的引导扇区读入到内存地址为00007C00处,并把控制权交给引导扇区中的引导程序,让我们来看看其中一些需要了解的地方    

  10H~02H   一条跳转指令,指针指向后面的引导程序    

  203H~0AH   厂商名和系统版本    

  30BH~0CH   每扇字节数,一般为512字节    

  40DH   每簇扇区数(有关簇的概念我们在后面会详细介绍),对于FAT32的磁盘该字节一般为08H,既每簇为8H*512B=4K    

  50EH~0FH   保留扇区数    

  610H   磁盘FAT的个数,一般为2    

  711H~12H   对于FAT16的磁盘为根目录的最大目录项,对于FAT32的磁盘该值总为“00H   00H    

  813H~14H   对于软盘或早期小硬盘该处为分区总扇区数,对于硬盘一般此值为“00H   00H    

  915H   介质描述,对于1.44软盘此处长为“F0H”,对于硬盘此处长为“F8H    

  1016H~17H   对于软盘或早期小硬盘该处为每个FAT占用的扇区数,对于硬盘一般此值为“00H   00H    

  1118H~19H   每道扇区数,一般为“3FH   00H”,即每道有63个扇区    

  121AH~1BH   磁头数,一般为“FFH   00H”,即每个柱面有255个磁头    

  131CH~1FH   隐含扇区数    

  1420H~23H   对于大硬盘来说该处存放的是该分区占用的扇区数    

  1524H~27H   对于大硬盘来说该处存放的是每个FAT占用的扇区数    

      28H~29H   FAT表同步标识,最左端二进制位为零则所有FAT表是同步的,为1则有损坏的FAT表。低4位表示在用的FAT表编号,从零开始计。

      2AH~2BH   文件系统版本,文件系统格式版本号。 仅用于FAT32文件系统格式

      2CH~2FH   根目录起始簇,根目录起始簇之簇号

      30H~31H   文件系统信息扇区,存放文件系统格式信息的扇区号

      32H~33H   引导扇区备份,引导扇区备份所在的扇区号

      34H~39H   保留,用于未来待添加的内容

  1640H   该处为磁盘BIOS信息,第一块硬盘为“80H”,一般软盘为“00H    

 

  1747H~51H   用户设置的卷标,如果没有卷标此处常为字符串“NO   NAME    

  1852H~59H   文件系统,对于FAT32文件系统此处常为“FAT32    

  191FEH~1FFH   结束标识,和上文提到的主引导区的结束标识一样为“55H   AAH  

 

例如:

c盘逻辑扇区0:

EB 58 90

4D 53 44 4F 53 35 2E 30

00 02

20   //扇区数/

22 00 //预约扇区数

02   //fat的个数

00 00 //根目录项数

00 00

F8

00 00 //fat扇区数

3F 00 //每道扇区数

FF 00 //磁头数

3F 00 00 00 //隐含扇区数

B1 62 A9 03 //该分区占用的扇区数

8F 3A 00 00 //每个FAT占用的扇区数

00 00

00 00

02 00 00 00 //根目录起始簇

01 00

06 00

00 00 00 00 00 00 00 00 00 00 00 00

80 01

29

B2 A6 30 98

4E 4F 20 4E 41 4D 45 20 20 20 20     //卷标 NO   NAME

46 41 54 33 32 20 20 20 33 C9 8E D1 BC F4 7B 8E C1 8E D9 BD 00 7C 88  //    FAT32

 

(三)FAT

FAT32表:

序号为01的表项为保留表项值为:0FFFFFF8FFFFFFFF

0FFFFFFF:标记表示不再有后续的表项

00000000:表示该簇没有使用。

 

文件已使用的簇:   00000001H~0FFFFFEFH 

系统保留簇:   0FFFFFF0H~0FFFFFF6H 

坏簇:             0FFFFFF7H 

文件的最后一簇:   0FFFFFF8H~0FFFFFFFH

 

例如:

fat表内容:

F8 FF FF 0F FF FF FF FF F8 FF FF 0F 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

16 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 00 00 00 00 13 00 00 00 00 00 00 00 23 00 00 00

00 00 00 00 00 00 00 00 1B 00 00 00 15 00 00 00 00 00 00 00 19 00 00 00 26 00 00 00 00 00 00 00

00 00 00 00 21 00 00 00 00 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 2A 00 00 00 00 00 00 00

00 00 00 00 24 00 00 00 00 00 00 00 2E 00 00 00 29 00 00 00 00 00 00 00 36 00 00 00 00 00 00 00

 

 

(四)FDT

目录区中的目录项变化较多,一个目录项仍占32字节,可以是文件目录项、子目录项、卷标项(仅跟目录有)、已删除目录项、长文件名目录项等。

目录项中原来在DOS下保留未用的10个字节都有了新的定义,全部32字节的定义如下:

 

  (1) 0-- 7字节 文件正名。

 

  (2) 8--10字节 文件扩展名。

 

  (3) 11字节 文件属性,按二进制位定义,最高两位保留未用,05位分别是只读位、隐藏位、系统位、卷标位、子目录位、归档位。

 

  (4) 11--13字节 仅长文件名目录项用,用来存储其对应的短文件名目录项的文件名字节校验和等。

 

  (5) 13--15字节 24位二进制的文件建立时间,其中的高5位为小时,次6位为分钟。

 

  (6) 16--17字节 16位二进制的文件建立日期,其中的高7位为相对于1980年的年份值,次4位为月份,后5位为月内日期。

 

  (7) 18--19字节 16位二进制的文件最新访问日期,定义同(6)

 

  (8) 20--21字节 起始簇号的高16位。

 

  (9) 22--23字节 16位二进制的文件最新修改时间,其中的高5位为小时,次6位为分钟,后5位的二倍为秒数。

 

  (10)24--25字节 16位二进制的文件最新修改日期,定义同(6)

 

  (11)26--27字节 起始簇号的低16位。

 

  (12)28--31字节 32位的文件字节长度。

 

1、定位FDT

2、搜索文件在FDT的目录项

3、计算文件的开始扇区

FAT16的:文件的逻辑扇区号=保留扇区数+2*FAT占用的扇区数+DIR占用的扇区数+(起始簇号-2*每簇扇区数。

FAT32的:文件的逻辑扇区号=保留扇区数+2*FAT占用扇区数+(起始簇号-2*每簇扇区数。

         文件的逻辑扇区号=DBR和其后的保留扇区数+2*FAT占用扇区数+(起始簇号-2*每簇扇区数

 

长文件名的规则:

FAT32的一个重要的特点是完全支持长文件名。长文件名依然是记录在目录项中的。为了低版本的OS或程序能正确读取长文件名文件,系统自动为所有长文件名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,也可以用短文件名寻址。不支持长文件名的OS或程序会忽略它认为不合法的长文件名字段,而支持长文件名的OS或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。

    当创建一个长文件名文件时,系统会自动加上对应的短文件名,其一般有的原则:

    (1)、取长文件名的前6个字符加上"~1"形成短文件名,扩展名不变。

    (2)、如果已存在这个文件名,则符号"~"后的数字递增,直到5

    (3)、如果文件名中"~"后面的数字达到5,则短文件名只使用长文件名的前两个字母。通过数学操纵长文件名的剩余字母生成短文件名的后四个字母,然后加后缀"~1"直到最后(如果有必要,或是其他数字以避免重复的文件名)

    (4)、如果存在老OS或程序无法读取的字符,换以"_"

    长文件名的实现有赖于目录项偏移为0xB的属性字节,当此字节的属性为:只读、隐藏、系统、卷标,即其值为0FH时,DOSWIN32会认为其不合法而忽略其存在。这正是长文件名存在的依据。将目录项的0xB置为0F,其他就任由系统定义了,Windows9xWindows 2000XP通常支持不超过255个字符的长文件名。系统将长文件名以13个字符为单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录项,这时长文件名的各个目录项按倒序排列在目录表中,以防与其他文件名混淆。

    长文件名中的字符采用unicode形式编码(一个巨大的进步哦),每个字符占据2字节的空间。其目录项定义如表15

 

15   FAT32长文件目录项32个字节的表示定义

字节偏移

(16进制)       字节数                        定义

0x0               1            属性字节位意义   7 保留未用

                                          6 1表示长文件最后一个目录项

                                          5 保留未用

                                          4 顺序号数值

                                          3

                                          2

                                          1

                                          0

0x1~0xA        10                        长文件名unicode码①

0xB               1                          长文件名目录项标志,取值0FH

0xC               1                          系统保留

0xD              1                          校验值(根据短文件名计算得出)

0xE~0x19      12                        长文件名unicode码②

0x1A~0x1B  2                          文件起始簇号(目前常置0) 

0x1C~0x1F    4                          长文件名unicode码③

 

   系统在存储长文件名时,总是先按倒序填充长文件名目录项,然后紧跟其对应的短文件名。从表15可以看出,长文件名中并不存储对应文件的文件开始簇、文件大小、各种时间和日期属性。文件的这些属性还是存放在短文件名目录项中,一个长文件名总是和其相应的短文件名一一对应,短文件名没有了长文件名还可以读,但长文件名如果没有对应的短文件名,不管什么系统都将忽略其存在。所以短文件名是至关重要的。在不支持长文件名的环境中对短文件名中的文件名和扩展名字段作更改(包括删除,因为删除是对首字符改写E5H),都会使长文件名形同虚设。长文件名和短文件名之间的联系光靠他们之间的位置关系维系显然远远不够。其实,长文件名的0xD字节的校验和起很重要的作用,此校验和是用短文件名的11个字符通过一种运算方式来得到的。系统根据相应的算法来确定相应的长文件名和短文件名是否匹配。这个算法不太容易用公式说明,我们用一段c程序来加以说明。

    假设文件名11个字符组成字符串shortname[],校验和用chknum表示。得到过程如下:

 

    int ij,chknum=0;

    for (i=11; i>0; i--)

        chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];

 

    如果通过短文件名计算出来的校验和与长文件名中的0xD偏移处数据不相等。系统无论如何都不会将它们配对的。

    依据长文件名和短文件名对目录项的定义,加上对簇的编号和链接,FAT32上数据的读取便游刃有余了。

件名的例子:

 

42 2D 00 30 00 30 00 34 00 39 00 0F 00 7A 30 00 31 00 2E 00 32 00 36 00 34 00 00 00 00 00 FF FF //-0049  01.264

01 30 00 31 00 2D 00 31 00 2D 00 0F 00 7A 32 00 30 00 30 00 39 00 30 00 38 00 00 00 30 00 35 00 //01-1-  200908   05

30 31 2D 31 2D 32 7E 32 32 36 34 20 00 00 6B 0A 05 3B 50 3B 30 00 6B 0A 05 3B 4E CA 02 3B 38 0B //01-1-2~2.264

 

二、示例代码如下

struct T_DIR_Info
{
 CString strName;     //目录或文件名
 bool B_IsOnlyRead:1;    //是否是只读的
 bool B_IsHide:1;     //是否是隐藏的
 bool B_IsSystem:1;     //是否是系统的
 bool B_IsVolumn:1;     //是否是卷标
 bool B_IsDir:1;      //是否是目录
 bool B_IsArchive:1;     //是否是存档的
 DWORD n_start_cluster_num;   //目录或文件起始簇号
 DWORD nSize;      //目录或文件的大小(byte)
 CString strDateTime;    //最终修改日期时间
 T_DIR_Info *pChildDir;    //子目录指针
 T_DIR_Info *pParentDir;    //父目录指针
 T_DIR_Info *pBrotherDir;   //兄弟目录指针
 T_DIR_Info()
 {
  strName = _T("");
  B_IsOnlyRead = false;
  B_IsHide = false;
  B_IsSystem = false;
  B_IsVolumn = false;
  B_IsDir = false;
  B_IsArchive = false;
  n_start_cluster_num = 2;
  nSize = 0;
  strDateTime = _T("");
  pChildDir = NULL;
  pParentDir = NULL;
  pBrotherDir = NULL;
 }
};

struct T_PartitionInfo
{
 DWORD n_ByteNumPerSector;   //每扇区字节数
 DWORD n_cluster_sector_num;   //每簇扇区数
 DWORD n_fat_sector_start;   //fat1起始扇区号
 DWORD n_fat_sector_num;    //fat扇区数
 DWORD n_Dir_start_Cluster_Num;  //根目录起始簇号
 DWORD n_data_sector_start;   //数据区的起始扇区号
 DWORD n_ByteNumPerCluster;   //每簇的字节数
 T_DIR_Info *pDirInfo;
 T_PartitionInfo()
 {
  n_ByteNumPerSector = 512;
  n_cluster_sector_num = 32;
  n_fat_sector_start = 32;
  n_fat_sector_num = 2;
  n_Dir_start_Cluster_Num = 2;
  n_data_sector_start = 0xFFFFFFFF;
  n_ByteNumPerCluster = 0x4000; //32*512
  pDirInfo = NULL;
 }
};

struct T_PartitionTable
{
 DWORD D_start_sector;    //分区的起始扇区号
 T_PartitionInfo *pPartitionInfo;
 T_PartitionTable *pNextPT;
 T_PartitionTable()
 {
  D_start_sector = 63;
  pPartitionInfo = NULL;
  pNextPT = NULL;
 }
};

const int ACTION_READ_DIR = 0;
const int ACTION_PLAY_FILE = 1;
const int ACTION_WRITE_FILE = 2;

#define VWIN32_DIOC_DOS_INT25     2
#define VWIN32_DIOC_DOS_INT26     3


class CDiskOpr
{
public:
 CDiskOpr();
 ~CDiskOpr();
 int GetSectorData(UINT sector_num, UINT sector_sum, byte* buf);
 int DelFile(CString FileName);
 int DelDir(CString Dir);
 BOOL SearchAndDisplayDiskDir();
 int SearchDiskDriver();

 BOOL CopyToDstDisk(CString strSrcDirName, CString strDstPath);
 BOOL OpenHD(int DiskNum);
 void GetLogicalPartition();
 CString GetCopyFileName()
 {
  return m_strCopyFileName;
 }
 void ClearFileName()
 {
  m_strCopyFileName = _T("");
 }
 T_DIR_Info* GetRootDir()
 {
  if(m_pCurPartition && m_pCurPartition->pPartitionInfo && m_pCurPartition->pPartitionInfo->pDirInfo)
  {
   m_pCurDir = m_pCurPartition->pPartitionInfo->pDirInfo;
   return m_pCurDir;
  }
  else
   return NULL;
 }
 
 T_DIR_Info* GetChildDir(T_DIR_Info* pDir)
 {
  if(pDir && pDir->pChildDir)
  {
   T_DIR_Info* pChildDir = pDir->pChildDir;
   return pChildDir;
  }
  else
   return NULL;
 }

 T_DIR_Info* GetNextChildDir(T_DIR_Info* pDir)
 {
  if(pDir && pDir->pBrotherDir)
  {
   T_DIR_Info* pBrotherDir = pDir->pBrotherDir;
   return pBrotherDir;
  }
  else
   return NULL;
 }

 T_DIR_Info* GetParentDir()
 {
  if(m_pCurDir && m_pCurDir->pParentDir)
  {
   m_pCurDir = m_pCurDir->pParentDir;
   return m_pCurDir;
  }
  else
   return NULL;
 }

 T_DIR_Info* SetChildDirToCurDir(CString strDirName);


private:
 HANDLE GetHDHandle()
 {
  return m_HDevice;
 }
 void SetHDHandle(HANDLE h_Handle)
 {
  m_HDevice = h_Handle;
 }

 BOOL SetPartitionTable(DWORD StartSector);
 BOOL SetPartitionInfo(DWORD ByteNumPerSector, DWORD ClusterSectorNum, DWORD FATSectorStart, DWORD FATSectorNum, DWORD DirStartClusterNum);
 BOOL AppendBrotherDir(CString strName, byte nAttribute, CString strDateTime, DWORD n_start_cluster_num, DWORD nDirSize);
 BOOL AppendChildDir(CString strName, byte nAttribute, CString strDateTime, DWORD n_start_cluster_num, DWORD nDirSize);
 BOOL FinishAppendBrotherDir();
 BOOL SearchNextDir();
 BOOL GetDirFormBuf(byte *pBuf, UINT BufLen);

 BOOL MakeDirTree();
 BOOL GetDirData(UINT ClusterNum, BOOL f_IsDir, int nAction, HANDLE hFile = INVALID_HANDLE_VALUE);
 BOOL GetNextClusterNum(DWORD *ClusterNum);
 BOOL GetChildDirData();
 BOOL ReadOneCluster(UINT ClusterNum, BOOL f_IsDir);

 BOOL Play();

 BOOL readsectors(HANDLE hfile, __int64 logical_lba, short nsectors, unsigned char *buff);
 BOOL WriteDataToDisk(HANDLE hfile, __int64 logical_lba, short sector_offset, byte *buff, UINT buff_len);
 __int64 myFileSeek(HANDLE hfile, __int64 distance, DWORD MoveMethod);
 BOOL IsIPCSrcDisk(HANDLE hDevice);

 void ReleasePT();
 void ReleaseDir(T_DIR_Info *pDirInfo);

 byte* MallocClusterBuf();
 void ReleaseClusterBuf();

 bool GetReadOnlyAttribute(byte nAttribute)
 {
  if(nAttribute & 0x01)
   return true;
  else
   return false;
 }
 bool GetHideAttribute(byte nAttribute)
 {
  if(nAttribute & 0x02)
   return true;
  else
   return false;
 }
 bool GetSystemAttribute(byte nAttribute)
 {
  if(nAttribute & 0x04)
   return true;
  else
   return false;
 }
 bool GetVolumnAttribute(byte nAttribute)
 {
  if(nAttribute & 0x08)
   return true;
  else
   return false;
 }
 bool GetDirAttribute(byte nAttribute)
 {
  if(nAttribute & 0x10)
   return true;
  else
   return false;
 }
 bool GetArchiveAttribute(byte nAttribute)
 {
  if(nAttribute & 0x20)
   return true;
  else
   return false;
 }

 CString DateTimeToStr(WORD WDate, WORD WTime);


 T_PartitionTable *m_pPTHead;
 T_PartitionTable *m_pCurPartition;
 T_DIR_Info *m_pCurDir;
 byte *m_pClusterBuf;

 int m_Driver_array[10];
 CString m_strCopyFileName;

 HANDLE m_HDevice;
};

 

 

 

 

 

 

 

 

#include "StdAfx.h"
#include "DiskOpr.h"
//#include "winbase.h"

CDiskOpr::CDiskOpr()
{
 m_strCopyFileName = _T("");
 m_pPTHead = NULL;
 m_pCurPartition = NULL;
 m_pCurDir = NULL;
 m_pClusterBuf = NULL;
 m_HDevice = INVALID_HANDLE_VALUE;
 memset(m_Driver_array, 0, sizeof(m_Driver_array));
}

CDiskOpr::~CDiskOpr()
{
 ReleaseClusterBuf();
 ReleasePT();
 if(m_HDevice != INVALID_HANDLE_VALUE)
 {
  CloseHandle(m_HDevice);
  m_HDevice = INVALID_HANDLE_VALUE;
 }
}

byte* CDiskOpr::MallocClusterBuf()
{
 if(!m_pCurPartition && !m_pCurPartition->pPartitionInfo)
  return NULL;

 if(!m_pClusterBuf)
 {
  m_pClusterBuf = new byte[m_pCurPartition->pPartitionInfo->n_ByteNumPerCluster];
 }

 return m_pClusterBuf;
}

void CDiskOpr::ReleaseClusterBuf()
{
 if(m_pClusterBuf)
 {
  delete m_pClusterBuf;
  m_pClusterBuf = NULL;
 }
}

void CDiskOpr::ReleaseDir(T_DIR_Info *pDirInfo)
{
 if(!pDirInfo)
  return;
 if(pDirInfo->pChildDir)
  ReleaseDir(pDirInfo->pChildDir);
 T_DIR_Info *p = pDirInfo;
 pDirInfo = pDirInfo->pBrotherDir;
 delete p;
 ReleaseDir(pDirInfo);
}

void CDiskOpr::ReleasePT()
{
 T_PartitionTable *pPT = NULL;
 while(m_pPTHead)
 {
  pPT = m_pPTHead;
  T_PartitionInfo *pPTInfo = pPT->pPartitionInfo;
  T_DIR_Info *pDirInfo = NULL;
  if(pPTInfo)
  {
   pDirInfo = pPTInfo->pDirInfo;
   ReleaseDir(pDirInfo);
  }
  m_pPTHead = m_pPTHead->pNextPT;
  delete pPT;
 }
 m_pCurDir = NULL;
 m_pCurPartition = NULL;
 m_pPTHead = NULL;
}

 

__int64 CDiskOpr::myFileSeek(HANDLE hfile, __int64 distance, DWORD MoveMethod)
{  
 LARGE_INTEGER li;  
 li.QuadPart = distance;
 li.LowPart = SetFilePointer(hfile, li.LowPart, &li.HighPart, MoveMethod);  
 if(li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)  
 {
  li.QuadPart = -1;  
 }  
 return li.QuadPart;  
}

BOOL CDiskOpr::readsectors(HANDLE hfile, __int64 logical_lba, short nsectors, byte *buff)  
{
 if(hfile == INVALID_HANDLE_VALUE || !buff)  return FALSE;

 DWORD cb;
 UINT nByteNumPerSector = 512;
 if(m_pCurPartition && m_pCurPartition->pPartitionInfo)
  nByteNumPerSector = m_pCurPartition->pPartitionInfo->n_ByteNumPerSector;
 __int64 posi;  
 posi = logical_lba * nByteNumPerSector;  
 myFileSeek(hfile, posi, FILE_BEGIN);  
 ReadFile(hfile, buff, (DWORD)(nsectors * nByteNumPerSector), &cb, NULL);
 if(cb < (DWORD)(nsectors * nByteNumPerSector))
  return FALSE;  
 return TRUE;  
}

BOOL CDiskOpr::WriteDataToDisk(HANDLE hfile, __int64 logical_lba, short sector_offset, byte *buff, UINT buff_len)  
{
 if(hfile == INVALID_HANDLE_VALUE || !buff)  return FALSE;
 DWORD cb = buff_len;
 UINT nByteNumPerSector = 512;
 if(m_pCurPartition && m_pCurPartition->pPartitionInfo)
  nByteNumPerSector = m_pCurPartition->pPartitionInfo->n_ByteNumPerSector;
 __int64 posi;  
 posi = logical_lba * nByteNumPerSector;  
 myFileSeek(hfile, posi, FILE_BEGIN);  
 
// WriteFile(hfile, buff, (DWORD)nsectors*512, &cb, NULL);
 if(WriteFile(hfile, buff, buff_len, &cb, NULL))
 {
  if(cb < buff_len)
   return FALSE;
  else
   return TRUE; 
 }
 DWORD err_code = GetLastError();
   return FALSE;
}

//驱动器号从1开始最大为10
BOOL CDiskOpr::OpenHD(int DiskNum)
{
 BOOL f_Ret = FALSE;
 HANDLE hDevice = INVALID_HANDLE_VALUE;
//初始化硬盘读写句柄   physicalDrive   PHYSICALDRIVE  
//  hDevice   =   CreateFile("////.//PHYSICALDRIVE0",         //物理硬盘0   FILE_SHARE_READ | FILE_SHARE_WRITE
// hDevice   =   CreateFile("////.//D:",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);         //C盘
//  hDevice = CreateFile("////.//PHYSICALDRIVE1", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
//          (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
// hDevice = CreateFile("////.//PHYSICALDRIVE1", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
//          (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); 
 char chBuf[50] = {0};
 sprintf(chBuf,"////.//PHYSICALDRIVE%d", m_Driver_array[DiskNum - 1]);
 hDevice = CreateFile(chBuf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
          (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
 if(hDevice != INVALID_HANDLE_VALUE)
 {
  HANDLE hDevice1 = INVALID_HANDLE_VALUE;
  hDevice1 = GetHDHandle();
  if(hDevice1 != INVALID_HANDLE_VALUE)
  {
   CloseHandle(hDevice1);
  }
  f_Ret = TRUE;
  SetHDHandle(hDevice);
 }
 else
 {
  DWORD err_code;
  err_code= GetLastError();
 }
 return f_Ret;
}

int CDiskOpr::SearchDiskDriver()
{
 HANDLE hDevice = INVALID_HANDLE_VALUE;
 char chBuf1[50] = {"////.//PHYSICALDRIVE0"};
 char chBuf[50] = {0};
 int count = 0;
 for(int i = 0; i < 10; i++)
 {
  sprintf(chBuf,"////.//PHYSICALDRIVE%d", i) ;
  hDevice = CreateFile(chBuf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
           (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
  if(hDevice != INVALID_HANDLE_VALUE)
  {
   if(IsIPCSrcDisk(hDevice))
   {
    m_Driver_array[count++] = i;
   }
   CloseHandle(hDevice);
   hDevice = INVALID_HANDLE_VALUE;
  }
  else
   break;
 }
 return count;
}

BOOL CDiskOpr::SetPartitionTable(DWORD StartSector)
{
 T_PartitionTable *pPT = NULL;
 pPT = new T_PartitionTable;
 if(!pPT)
  return FALSE;
 pPT->D_start_sector = StartSector;
 if(!m_pPTHead)
 {
  m_pPTHead = pPT;
  m_pCurPartition = pPT;
 }
 else
 {
  T_PartitionTable *p = m_pPTHead;
  while(p->pNextPT)
  {
   p = p->pNextPT;
  }
  p->pNextPT = pPT;
 }

 return TRUE;
}

BOOL CDiskOpr::SetPartitionInfo(DWORD ByteNumPerSector, DWORD ClusterSectorNum, DWORD FATSectorStart,
        DWORD FATSectorNum, DWORD DirStartClusterNum)
{
 if(!m_pPTHead)
  return FALSE;
 
 T_PartitionInfo *pPInfo = new T_PartitionInfo;
 pPInfo->n_ByteNumPerSector = ByteNumPerSector;
 pPInfo->n_cluster_sector_num = ClusterSectorNum;
 pPInfo->n_fat_sector_start = FATSectorStart;
 pPInfo->n_fat_sector_num = FATSectorNum;
 pPInfo->n_Dir_start_Cluster_Num = DirStartClusterNum;
 pPInfo->n_data_sector_start = FATSectorStart + FATSectorNum * 2;
 pPInfo->n_ByteNumPerCluster = ClusterSectorNum * ByteNumPerSector;

 T_PartitionTable *p = m_pPTHead;
 while(p->pNextPT)
 {
  p = p->pNextPT;
 }
 p->pPartitionInfo = pPInfo;
 return TRUE;
}

BOOL CDiskOpr::AppendBrotherDir(CString strName, byte nAttribute, CString strDateTime, DWORD n_start_cluster_num, DWORD nDirSize)
{
 if(!m_pCurPartition || !m_pCurDir)
  return FALSE;
 
 T_DIR_Info *pDir = new T_DIR_Info;
 pDir->strName = strName;
 pDir->B_IsOnlyRead = GetReadOnlyAttribute(nAttribute);
 pDir->B_IsHide = GetHideAttribute(nAttribute);
 pDir->B_IsSystem = GetSystemAttribute(nAttribute);
 pDir->B_IsVolumn = GetVolumnAttribute(nAttribute);
 pDir->B_IsDir = GetDirAttribute(nAttribute);
 pDir->B_IsArchive = GetArchiveAttribute(nAttribute);
 pDir->strDateTime = strDateTime;
 pDir->n_start_cluster_num = n_start_cluster_num;
 pDir->nSize = nDirSize;
 if(!m_pCurPartition->pPartitionInfo->pDirInfo)
 {
  m_pCurPartition->pPartitionInfo->pDirInfo = pDir;
  m_pCurDir = pDir;
 }
 else
 {
  pDir->pParentDir = m_pCurDir->pParentDir;
  m_pCurDir->pBrotherDir = pDir;
  m_pCurDir = m_pCurDir->pBrotherDir;
 }

 return TRUE; 
}

BOOL CDiskOpr::FinishAppendBrotherDir()
{
 if(!m_pCurDir)
  return FALSE;

 m_pCurDir = m_pCurDir->pParentDir->pChildDir;
 return TRUE;
}

BOOL CDiskOpr::AppendChildDir(CString strName, byte nAttribute, CString strDateTime, DWORD n_start_cluster_num, DWORD nDirSize)
{
 if(!m_pCurPartition)
  return FALSE;
 
 T_DIR_Info *pDir = new T_DIR_Info;
 pDir->strName = strName;
 pDir->B_IsOnlyRead = GetReadOnlyAttribute(nAttribute);
 pDir->B_IsHide = GetHideAttribute(nAttribute);
 pDir->B_IsSystem = GetSystemAttribute(nAttribute);
 pDir->B_IsVolumn = GetVolumnAttribute(nAttribute);
 pDir->B_IsDir = GetDirAttribute(nAttribute);
 pDir->B_IsArchive = GetArchiveAttribute(nAttribute);
 pDir->strDateTime = strDateTime;
 pDir->n_start_cluster_num = n_start_cluster_num;
 pDir->nSize = nDirSize;
 if(!m_pCurPartition->pPartitionInfo->pDirInfo)
 {
  T_DIR_Info *pRootDir = new T_DIR_Info;
  pRootDir->strName = _T("//");
  pRootDir->B_IsDir = true;
  pRootDir->B_IsVolumn = true;
  pRootDir->B_IsSystem = true;
  pRootDir->n_start_cluster_num = 0;
  m_pCurPartition->pPartitionInfo->pDirInfo = pRootDir;
  m_pCurDir = pRootDir;
 }

 m_pCurDir->pChildDir = pDir;
 pDir->pParentDir = m_pCurDir;
 m_pCurDir = m_pCurDir->pChildDir;

 return TRUE;
}

//返回FALSE时说明所有目录都已经搜索过了
BOOL CDiskOpr::SearchNextDir()
{
 if(m_pCurDir->strName == _T("//"))
  return FALSE;

 while(m_pCurDir->strName != _T("//") && !m_pCurDir->pBrotherDir)
 {
  m_pCurDir = m_pCurDir->pParentDir;
 }

 if(m_pCurDir->strName == _T("//"))
  return FALSE;
 m_pCurDir = m_pCurDir->pBrotherDir;
 return TRUE;
}

BOOL CDiskOpr::GetDirFormBuf(byte *pBuf, UINT BufLen)
{
 if(!pBuf || BufLen % 32 != 0)
  return FALSE;

 CString str_DirName;
 UINT nStartClusterNum = 0;
 UINT nValue = 0;
 byte nAttribute = 0;
 BOOL f_First = TRUE;
 byte Short_filename[15] = {0};
 byte Long_filename[12][26];
 int iRow_Get = 0;
 int iRow_Real = 0;
 int i = 0;
 CString strDateTime;
 for(UINT pos = 0; pos < BufLen; pos = pos + 32)
 {
  nValue = 0;
  for(i = 0; i < 32; i++)
   nValue += pBuf[i + pos];
  if(nValue == 0)
  {
   FinishAppendBrotherDir();
   break;
  }
  
  if(0xE5 == pBuf[pos] || 0x2E == pBuf[pos])
   continue;

  if(pBuf[pos + 0x0B] == 0x0F)  //长文件名
  {
   int iRowNum = 0;
   if(pBuf[pos] & 0x40)
   {
    iRow_Get = pBuf[pos] & 0x1F;
    iRowNum = iRow_Get - 1;
   }
   else
   {
    iRowNum = (pBuf[pos] & 0x1F) - 1;
   }
   memcpy(&Long_filename[iRowNum][0], &pBuf[pos + 0x01], 10);
   memcpy(&Long_filename[iRowNum][10], &pBuf[pos + 0x0E], 12);
   memcpy(&Long_filename[iRowNum][22], &pBuf[pos + 0x1C], 4);
   iRow_Real++;
   continue;
  }
  else
  {
   if(iRow_Get > 0 && iRow_Get == iRow_Real)
   {
    str_DirName = _T("");
    WCHAR *wch = NULL;
    wch = (WCHAR*)Long_filename;
    str_DirName = str_DirName + CString(wch);
    str_DirName.TrimRight();
    memset(Long_filename, 0, sizeof(Long_filename));
    iRow_Get = 0;
    iRow_Real = 0;
   }
   else
   {
    memcpy(Short_filename, pBuf + pos, 11);
    str_DirName = CString(Short_filename);
    str_DirName.TrimRight();
    memset(Short_filename, 0, sizeof(Short_filename));
   }

  }

  nAttribute = pBuf[0x0B + pos];

  WORD wDate = 0, wTime = 0;
  wTime = pBuf[0x17 + pos] * 0x100 + pBuf[0x16 + pos];
  wDate = pBuf[0x19 + pos] * 0x100 + pBuf[0x18 + pos];
  strDateTime = DateTimeToStr(wDate, wTime);

  //目录或文件的起始簇号
  nStartClusterNum = ((pBuf[0x15 + pos] * 0x100 + pBuf[0x14 + pos]) * 0x100 + pBuf[0x1B + pos]) * 0x100 + pBuf[0x1A + pos];

  DWORD nDirsize = 0;
  nDirsize = ((pBuf[0x1F + pos] * 0x100 + pBuf[0x1E + pos]) * 0x100 + pBuf[0x1D + pos]) * 0x100 + pBuf[0x1C + pos];

  if(f_First)
  {
   AppendChildDir(str_DirName, nAttribute, strDateTime, nStartClusterNum, nDirsize);
   f_First = FALSE;
  }
  else
  {
   AppendBrotherDir(str_DirName, nAttribute, strDateTime, nStartClusterNum, nDirsize);
  }
 }

 return TRUE;
}

BOOL CDiskOpr::ReadOneCluster(UINT ClusterNum, BOOL f_IsDir)
{
 BOOL f_Ret = FALSE;
 HANDLE hDevice = GetHDHandle();

 if(!m_pCurPartition || !m_pCurPartition->pPartitionInfo || hDevice == INVALID_HANDLE_VALUE)
  return f_Ret;

 byte *pClusterBuf = NULL;
 pClusterBuf = MallocClusterBuf();
 if(!pClusterBuf)
  return f_Ret;

 UINT nSectorStart = 0;
 //簇对应的其始扇区号
 nSectorStart = m_pCurPartition->pPartitionInfo->n_data_sector_start + (ClusterNum - 2) * m_pCurPartition->pPartitionInfo->n_cluster_sector_num;
 //从磁盘数据区读一簇数据
 if(readsectors(hDevice, (__int64)nSectorStart, (short)(m_pCurPartition->pPartitionInfo->n_cluster_sector_num), pClusterBuf))
 {
//byte buf[5]={0x33,0x32,0x32,0x32,0x33};
//WriteDataToDisk(hDevice, nSectorStart, 0, buf, 5);
  if(f_IsDir)
   GetDirFormBuf(pClusterBuf, m_pCurPartition->pPartitionInfo->n_ByteNumPerCluster);
  f_Ret = TRUE;  
 }

 return f_Ret;
}

BOOL CDiskOpr::GetNextClusterNum(DWORD *ClusterNum)
{
 BOOL f_Ret = FALSE;
 HANDLE hDevice = GetHDHandle();
 if(!m_pCurPartition || !m_pCurPartition->pPartitionInfo || hDevice == INVALID_HANDLE_VALUE)
  return f_Ret;
 
 byte sectorbuf[512] = {0};
 UINT SectorNum = 0;
 UINT n_offset = 0;
 UINT n_cluster_num = *ClusterNum * 4;
 SectorNum = n_cluster_num / 512 + m_pCurPartition->pPartitionInfo->n_fat_sector_start;
 n_offset = n_cluster_num % 512;
 if(readsectors(hDevice, (__int64)SectorNum, (short)1, sectorbuf))  //读FAT表的一个扇区
 {  
  n_cluster_num = ((sectorbuf[n_offset + 3] * 0x100 + sectorbuf[n_offset + 2]) * 0x100 + sectorbuf[n_offset + 1]) * 0x100 + sectorbuf[n_offset];
  if(n_cluster_num != 0x0FFFFFFF && n_cluster_num != 0 && n_cluster_num != 0x0FFFFFF8 && n_cluster_num != 0xFFFFFFFF)
  {
   *ClusterNum = n_cluster_num;
   f_Ret = TRUE;
  }
 }
 return f_Ret;
}

BOOL CDiskOpr::GetDirData(UINT ClusterNum, BOOL f_IsDir, int nAction, HANDLE hFile)
{
 BOOL f_Ret = FALSE;
 if(!m_pCurPartition || !m_pCurPartition->pPartitionInfo)
  return f_Ret;
 DWORD n_Cluster_Num = ClusterNum;
 DWORD cb = 0;
 if(ReadOneCluster(n_Cluster_Num, f_IsDir))
 {
  f_Ret = TRUE;
  if(!f_IsDir && nAction == ACTION_PLAY_FILE)
  {
   Play();
  }
  else if(!f_IsDir && nAction == ACTION_WRITE_FILE)
  {
   if(hFile != INVALID_HANDLE_VALUE)
   {
    WriteFile(hFile, m_pClusterBuf, m_pCurPartition->pPartitionInfo->n_ByteNumPerCluster, &cb, NULL);
    cb = 0;
   }
  }
  while(GetNextClusterNum(&n_Cluster_Num))
  {
   f_Ret &= ReadOneCluster(n_Cluster_Num, f_IsDir);
   if(!f_IsDir && nAction == ACTION_PLAY_FILE)
   {
    Play();
   }
   else if(!f_IsDir && nAction == ACTION_WRITE_FILE)
   {
    if(hFile != INVALID_HANDLE_VALUE)
    {
     WriteFile(hFile, m_pClusterBuf, m_pCurPartition->pPartitionInfo->n_ByteNumPerCluster, &cb, NULL);
     cb = 0;
    }
   }
  }
 }
 return f_Ret;
}

BOOL CDiskOpr::GetChildDirData()
{
 BOOL f_Ret = FALSE;
 if(!m_pCurPartition || !m_pCurPartition->pPartitionInfo)
  return f_Ret;
 while(m_pCurDir && !m_pCurDir->B_IsDir && m_pCurDir->pBrotherDir)
 {
  m_pCurDir = m_pCurDir->pBrotherDir;
 }
 if(m_pCurDir && !m_pCurDir->B_IsDir)
 {
  if(!SearchNextDir())
   return FALSE;
 }

 DWORD n_Cluster_Num = m_pCurDir->n_start_cluster_num;
 if(ReadOneCluster(n_Cluster_Num, TRUE))
 {
  f_Ret = TRUE;
  while(GetNextClusterNum(&n_Cluster_Num))
  {
   f_Ret &= ReadOneCluster(n_Cluster_Num, TRUE);
  }
 }
 if(f_Ret)
 {
  GetChildDirData();
 }

 return f_Ret;
}

BOOL CDiskOpr::MakeDirTree()
{
 BOOL f_Ret = FALSE;
 if(!m_pCurPartition || !m_pCurPartition->pPartitionInfo)
  return f_Ret;
 
 GetDirData(m_pCurPartition->pPartitionInfo->n_Dir_start_Cluster_Num, TRUE, ACTION_READ_DIR);
 GetChildDirData();

 return f_Ret;
}

void CDiskOpr::GetLogicalPartition()
{
 DWORD mask = 0;
 mask = GetLogicalDrives();
 
 char buf[50] = {0};
 DWORD buflen = sizeof(buf);

 buflen = GetLogicalDriveStrings(buflen, buf);
}

BOOL CDiskOpr::IsIPCSrcDisk(HANDLE hDevice)
{
 BOOL f_Ret = FALSE;
 if(hDevice != INVALID_HANDLE_VALUE)
 {
  byte sectorbuf[512] = {0};
  if(readsectors(hDevice, (__int64)0, (short)1, sectorbuf))    //读磁盘第一个扇区
  {
   if(sectorbuf[0x1BE + 0x04] == 0x83)  //system ID
    f_Ret = TRUE;      
  }
 }
 return f_Ret;
}

BOOL CDiskOpr::SearchAndDisplayDiskDir()
{
 HANDLE hDevice = INVALID_HANDLE_VALUE; 
 hDevice = GetHDHandle();
 if(hDevice != INVALID_HANDLE_VALUE)
 {
  byte sectorbuf[512] = {0};
  if(!readsectors(hDevice, (__int64)0, (short)1, sectorbuf))    //读磁盘第一个扇区
  {
   return FALSE;      
  }
  UINT n_PartitionHead = 0;
  for(int i = 3; i >= 0; i--)
  {
   n_PartitionHead = (n_PartitionHead << 8) + sectorbuf[0x1BE + 8 + i]; //第一个分区的起始扇区号
  }
  SetPartitionTable(n_PartitionHead);

  memset(sectorbuf, 0, sizeof(sectorbuf));
  if(!readsectors(hDevice, (__int64)n_PartitionHead, (short)1, sectorbuf))  //读第一个分区的1扇区
  {  
   return FALSE;  
  }

  UINT n_ByteNumPerSector = sectorbuf[0x0C] * 0x100 + sectorbuf[0x0B];  //每扇区字节数
  UINT n_cluster_sector_num = sectorbuf[0x0D];  //每簇扇区数
  UINT n_fat_sector_start = n_PartitionHead + sectorbuf[0x0f] * 0x100 + sectorbuf[0x0e]; //fat起始扇区号

  UINT n_fat_sector_num = 0;
  for(i = 3; i >= 0; i--)
  {
   n_fat_sector_num = (n_fat_sector_num << 8) + sectorbuf[0x24 + i]; //fat扇区数
  }
  
  UINT n_Dir_start_Cluster_Num = 0;
  for(i = 3; i >= 0; i--)
  {
   n_Dir_start_Cluster_Num = (n_Dir_start_Cluster_Num << 8) + sectorbuf[0x2C + i];  //根目录起始簇号
  }
  
  SetPartitionInfo(n_ByteNumPerSector, n_cluster_sector_num, n_fat_sector_start, n_fat_sector_num, n_Dir_start_Cluster_Num);
  MakeDirTree();
  
 }
 return TRUE;
}

T_DIR_Info* CDiskOpr::SetChildDirToCurDir(CString strDirName)
{
 if(m_pCurDir)
 {
  T_DIR_Info* pDir = m_pCurDir->pChildDir;
  while(pDir && pDir->strName != strDirName)
  {
   pDir = pDir->pBrotherDir;
  }
  if(pDir)
  {
   if(pDir->B_IsDir)
    m_pCurDir = pDir;
   else
   {
    GetDirData(pDir->n_start_cluster_num, FALSE, ACTION_PLAY_FILE);
    return NULL;
   }
  }
  return pDir;
 }
 else
  return NULL;
}

CString CDiskOpr::DateTimeToStr(WORD WDate, WORD WTime)
{
 int nDay = WDate & 0x001F;
 int nMonth = (WDate >> 5) & 0x0F;
 int nYear = (WDate >> 9) & 0x7F;
 nYear += 1980;

 int nSecond = WTime & 0x001F;
 int nMinute = (WTime >> 5) & 0x3F;
 int nHour = (WTime >> 11) & 0x1F;
 CString strDateTime;
 strDateTime.Format(_T("%d-%02d-%02d %02d:%02d"), nYear, nMonth, nDay, nHour, nMinute);
 return strDateTime;
}

BOOL CDiskOpr::Play()
{
 return TRUE;
}

BOOL CDiskOpr::CopyToDstDisk(CString strSrcDirName, CString strDstPath)
{
 if(m_pCurDir)
 {
  m_strCopyFileName = _T("");
  CString strPath, strFile;
  CString strCurDir;
  char Buffer[400] = {0};
  DWORD nBufferLength = sizeof(Buffer);
  GetCurrentDirectory(nBufferLength, Buffer);
  strCurDir = CString(Buffer);
  HANDLE hFile = INVALID_HANDLE_VALUE;
  T_DIR_Info* pDir = m_pCurDir->pChildDir;
  while(pDir && pDir->strName != strSrcDirName)
  {
   pDir = pDir->pBrotherDir;
  }
  if(pDir)
  {
   BOOL  flag = FALSE;
   CString str;
   T_DIR_Info* pDir2 = pDir;
   if(pDir->B_IsDir)
   {
    strPath = pDir->strName;
    pDir = pDir->pChildDir;
    str = strDstPath + _T("//") + strPath;
    flag = CreateDirectory(str, NULL);
    flag = SetCurrentDirectory(str);
    while(pDir && pDir != pDir2)
    {
     if(pDir->B_IsDir)
     {
      strPath = strPath + _T("//") + pDir->strName;
      str = strDstPath + _T("//") + strPath;
      flag = CreateDirectory(str, NULL);
     }
     else
     {
      strFile = strDstPath + _T("//") + strPath;
      flag = SetCurrentDirectory(strFile);
      strFile = pDir->strName;
      m_strCopyFileName = strPath + _T("//") + strFile;
      hFile = CreateFile(strFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
      GetDirData(pDir->n_start_cluster_num, FALSE, ACTION_WRITE_FILE, hFile);
      CloseHandle(hFile);
      hFile = INVALID_HANDLE_VALUE;
     }
     if(pDir->pChildDir)
     {
      pDir = pDir->pChildDir;
     }
     else if(pDir->pBrotherDir)
     {
      if(pDir->B_IsDir)
      {
       strPath = strPath.Left(strPath.GetLength() - pDir->strName.GetLength() - 1);
      }
      pDir = pDir->pBrotherDir;
     }
     else
     {
      if(pDir->B_IsDir)
      {
       strPath = strPath.Left(strPath.GetLength() - pDir->strName.GetLength() - 1); 
      }
      pDir = pDir->pParentDir;
      while(!pDir->pBrotherDir && pDir != pDir2)
      {
       if(pDir->B_IsDir)
       {
        strPath = strPath.Left(strPath.GetLength() - pDir->strName.GetLength() - 1);
       }
       pDir = pDir->pParentDir;
      }
      if(pDir != pDir2)
      {
       if(pDir->B_IsDir)
       {
        strPath = strPath.Left(strPath.GetLength() - pDir->strName.GetLength() - 1);
       }
       pDir = pDir->pBrotherDir;
      }
     }
    }
   }
   else
   {
    flag = SetCurrentDirectory(strDstPath);
    strFile = pDir->strName;
    m_strCopyFileName = strSrcDirName + _T("//") + strFile;
    hFile = CreateFile(strFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    GetDirData(pDir->n_start_cluster_num, FALSE, ACTION_WRITE_FILE, hFile);
    CloseHandle(hFile);
    hFile = INVALID_HANDLE_VALUE;
   }
  }
  SetCurrentDirectory(strCurDir);
 }
 return TRUE;
}

 

暂时就写这么多吧,如需要代码可与我联系。

 

你可能感兴趣的:(2010年)