sharkmouse
禁止发言
禁止发言
  • 注册日期2003-05-05
  • 最后登录2016-04-11
  • 粉丝0
  • 关注0
  • 积分1355分
  • 威望7163点
  • 贡献值1点
  • 好评度24点
  • 原创分0分
  • 专家分0分
阅读:1577回复:7

怎样在程序里格式化磁盘?

楼主#
更多 发布于:2004-11-07 22:55
用户被禁言,该主题自动屏蔽!

最新喜欢:

wdy9927wdy992...
omo
omo
驱动牛犊
驱动牛犊
  • 注册日期2002-08-07
  • 最后登录2004-11-16
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-11-14 01:39
以上是在驱动中格式化FAT32的源代码,根据FAT32规格编写的。由于NTFS Microsoft没有公布其技术细节,所以,不好做,不过你可以自己研究,如果研究出来,也告诉我一声喔。
可以给点分给我吧!
钱就是驱动,驱动就是钱。
omo
omo
驱动牛犊
驱动牛犊
  • 注册日期2002-08-07
  • 最后登录2004-11-16
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-11-14 01:33
PBOOT_SECTOR bootSector;
NTSTATUS            status = STATUS_SUCCESS;
IO_STATUS_BLOCK ioStatus;
CCHAR szVolLabel[] = "FILEBAKCUP ";
ULONG totSectorCounts;
LARGE_INTEGER curSysTime;
PUCHAR tempBuffer = NULL;
LARGE_INTEGER offset; // 格式化时,BPB, FAT分区表写入偏移量
ULONG RootDirSectors = 0;
ULONG TmpVal1, TmpVal2, FATSz, i;


DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE, ("FormatDisk -- IN \n" ) );

PAGED_CODE();
ASSERT( pdx->DiskImage != NULL );

totSectorCounts = (ULONG)(pdx->diskInfo.DiskSize.QuadPart / SECTOR_SIZE);

bootSector = (PBOOT_SECTOR)pdx->DiskImage;
memset(bootSector,0, SECTOR_SIZE);
tempBuffer = (PUCHAR)pdx->DiskImage + SECTOR_SIZE;

// 0 3
// 跳到引导代码,3个字节是根据Jmp汇编代码而来的,通常有以下两种方式
// jmpBoot[0] = 0xEB, jmpBoot[1] = 0x??, jmpBoot[2] = 0x90 and
// jmpBoot[0] = 0xE9, jmpBoot[1] = 0x??, jmpBoot[2] = 0x??
// 0x??表示一个8bit的字节,在Format时0xEB更为常用
bootSector->BS_jmpBoot[0] = 0xEB;
bootSector->BS_jmpBoot[1] = 0x58;
bootSector->BS_jmpBoot[2] = 0x90;

// 3 8
// 对于“MSWIN4.1” 通常存在误解,这个值仅仅是一个String而已,Microsoft
// 操作系统通常并不关注这个值,但是某些Driver会关注这个值,所以为了保持
// 最大的兼容,通常推荐使用“MSWIN4.1”,如果不这样填充,也许某些Driver将
// 不能识别这个文件系统
strncpy(bootSector->BS_OEMName, "MSWIN4.1", 8);

// 11 2
// 每个Sector有多少个Bytes,该字段只能填写下面的值:512、1024、2048、4096
// 但是如果你为了和老的文件系统实现保持最大兼容,你必须填充该字段512
// 有许多FAT代码硬性将此字段填为512,不要为此字段是否是512费劲疤瘌的check
// Microsoft的OS对于512、1024、2048、4096都支持
bootSector->BPB_BytsPerSec = SECTOR_SIZE;

// 13 1
// 每个镞的Sector数;该字段的值一定是2的倍速,但不能是0,可以是1、2、4、8
// 16、32、64和128,注意,无论如何不能用该值来推导“Bytes of Cluster”的值
// 大于32K((BPB_BytsPerSec * BPB_SecPerClus)),这里有个误区,即认为
// “Bytes of Cluster”的值大于32K就是OK,如果这个值大于32K,FAT表将不能正常
// 工作,有些系统支持每个镞为64K,但此时很多应用程序不能正常工作。

//if(totSectorCounts < DskTableFAT32[0])
// return; 暂时不判断,AP层已经做限制,需要自定义一个错误号

for( i = 0; i < sizeof(DskTableFAT32)/sizeof(DskTableFAT32[0]); i++)
{
if( totSectorCounts < DskTableFAT32.DiskSize )
{
bootSector->BPB_SecPerClus = DskTableFAT32.SecPerClusVal;
break;
}
}
DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "The Value of Sector Per Cluster is: %d\n", bootSector->BPB_SecPerClus ));
// 14 2
// 保留扇区数,在一个卷上的保留区域,这个数目从一个卷的第一个扇区算起.
// 这个字段的值不能为0。对于FAT12和FAT16,这个值不能大于1,对于FAT32,这个
// 字段的值通常为32。对于FAT12和FAT16,许多系统硬性规定该值为1,但Microsfot
// OS支持任何非零值
bootSector->BPB_ResvdSecCnt = 32;

// 16 1
// FAT表的个数。对于任何类型的FAT卷,这个字段的值应该总是包含2。虽然任何大于
// 1的值都是有效的,对于2以外的任何值,可能部分os和相当多的软件都能正常工作。
// Microsfof的所有文件系统driver都支持2以外的其他值,但还是强烈推荐设置该值为2。
// 原因是需要为FAT表提供冗余,以防如果有扇区坏掉则可以从备份FAT表复制原来的
// 数据。有些Flush Memory Card为了节约空间,将此值设为1,这将导致某些软体不能
// 正常工作。
bootSector->BPB_NumFATs = 2;

// 17 2
// 对于FAT12和FAT16,该字段的值是一个32Bytes的根目录入口的个数,对于FAT32,该
// 字段的值应该设置为0。为了保持最大兼容,FAT12和FAT16应该将此值设为512
bootSector->BPB_RootEntCnt = 0;

// 19 2
// 对于FAT16,这个值应该是一个16bits的数,描述该卷上的所有Sector的个数,包括
// 4个区域。这个值可以是0,但此时BPB_TotSec32必须不为0。对于FAT12和FAT16卷,
// 这个值是改卷上扇区个数,如果这个个数合适(应该少于0x10000)的话
// BPB_TotSec32值为0。
bootSector->BPB_TotSec16 = 0;

// 21 1
// 0xF8是标准的表示一个不可移动的Fixed Media。对于可移动的Media,经常设置
// 为0xF0, 这个值可以是0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE以及
// 0xFF. 重要的一点是填充的这个值必须被相同的填充到FAT[0]。Msdos1.0对这个
// 值的进行检测,但是现在已经没有什么用了。
bootSector->BPB_Media = 0xf8;

// 22 2
// 这个值描述一个FAT12和FAT16的FAT表占用的扇区数。对于FAT32这个值是0,用
// BPB_FATSz32来描述FAT32的FAT表占用的扇区数。
bootSector->BPB_FATSz16 = 0;

// 24 2
// 每个磁道上的Sector数For Int 13,这个字段只和哪些需要有磁盘物理结构的Media
// 相关。(磁盘物理结构即Disk Geometry)。磁盘卷最终被很多的磁头和柱面分解。
// 当发生Int 13时可以看见。
bootSector->BPB_SecPerTrk = 0x3f;

// 26  2
// 磁头数目 for int 13,于这个字段相关的是早期对BPB_SecPerTrk的讨论。这个
// 字段包含一个基于"Counts of Heads",比如1.44M的3.5英寸软盘的该值为2。
bootSector->BPB_NumHeads = 2/*0xff*/;

// 28 4
// 前述的包含该FAT卷的分区中的隐藏扇区数。该字段通常只为哪些希望在调用int 13
// 时可见的media。这个值总是应该被设置为0,对于没有被partitioned的Media。
// 严格的说来,什么值适合该字段由操作系统说了算。
bootSector->BPB_HiddSec = 0x3f;

//32 4
// 一个FAT32卷上的扇区个数,是个32bits值。对于FAT12和FAT16卷,该值必须为零
// 对于一个FAT32卷,该值不能为0。该值必须大于0x10000。
bootSector->BPB_TotSec32 = totSectorCounts;

// 36 4
// 一个FAT32卷上一个FAT表占用的Sector数。BPB_FATSz16必须被设置为0。
RootDirSectors = ((bootSector->BPB_RootEntCnt *32) + (bootSector->BPB_BytsPerSec -1)) / bootSector->BPB_BytsPerSec;
TmpVal1 = bootSector->BPB_TotSec32 - (bootSector->BPB_ResvdSecCnt + RootDirSectors);
TmpVal2 = (256 * bootSector->BPB_SecPerClus) + bootSector->BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
bootSector->BPB_FATSz32 = (TmpVal1 + (TmpVal2-1)) / TmpVal2;

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "The size of ONE FAT is: %d\n", bootSector->BPB_FATSz32 ));
// 40 2
// Bits 0-3 -- 从0起的描述被激活的FAT。只有在镜像被禁止时有效
// Bits 4-6 -- 保留.
// Bit 7 -- 0 表示一个FAT被镜像到所有所有FAT,当在运行时。
// -- 1 表示一个FAT被激活。该值作为1-3位的一个参考值。
// Bits 8-15 -- 保留 //
bootSector->BPB_ExtFlags = 0;

// 42 2
// FAT32卷的版本号,高字节位用来表示主版本,低字节表示副版本号。该值在FAT12
// 和FAT16上没有意义。该字段的设置是为了进行FAT32扩展时不出错。本文档定义0:0
// 如果该值为一个非0值,那么Back-level Windows Version将不会mount该卷。
// 注意: 磁盘应用设计时应尊重该值,不要去设置主副版本,如果在设计FAT32文件
// 系统Driver时没有版本号被定义,FAT32文件系统Driver必须Check该字段的值并且
// 不会Mount该卷,
bootSector->BPB_FSVer = 0;

// 44 4
// 根目录所在的第一个镞的镞号,通常为2,但不一定是2。在FAT12和FAT16上没有意义。
bootSector->BPB_RootClus = 2;

//48 2
// 保存在该FAT32卷的保留区域的Info Sector占用的Sector数。通常为1。
// 该字段在FAT12和FAT16上没有意义。
bootSector->BPB_FSInfo = 1;

//50 2
// 保存在该FAT32卷上的保留区域中的备份Boot Sector的扇区号。通常为6,不推荐
// 使用6以外的其他值。 在FAT12和FAT16上没有意义。
bootSector->BPB_BkBootSec = 6;

//52 12
// 为未来扩展保留的,Code for Format FAT32应该总是填该区域为0。
// 在FAT12和FAT16上没有意义。
memset(bootSector->BPB_Reserved, 0, 12 );

//64 1
// 该字段与FAT12和FAT16上定义一样。Int 13 Drive Number(0x80)。该字段通常为
// 操作系统指定。0x00为Floppy,0x80为harddisk。与FAT12和FAT16唯一不一样的是
// 在bootSEctor中的偏移量不一样。
bootSector->BS_DrvNum = 0x80;

//65 1
// 保留为Windows NT使用, Code for Format FAT32应该填0。
bootSector->BS_Reserved1 = 0;

//66 1
// 扩展的Boot标志(0x29),该字段作为一个标志标识(indetify)接下来的3个字段。
bootSector->BS_BootSig = 0x29;

//67 4
// 该卷的Serial Number,和下面一个字段结合使用,用来支持Removeable-Media的
// Volume Tracking。该字段通常被当前日期和时间填充。
bootSector->BS_VolID = 0x87654321;

//71 11
// 该字段表示卷标,匹配11个字节。如果没有卷标时,填充"NO LABLE   ".
strncpy(bootSector->BS_VolLab, "NO NAME    ",11 );

//82 8
// 对于FAT12和FAT16通常是“FAT12   ”, “FAT16   ”, or “FAT     ”中的一个,对于
// FAT32,总是被设置为"FAT32   ",microsoft的文件 系统通常不用该字段来检测卷的
// FAT类型。但其他文件系统可能用该字段来检测。
strncpy(bootSector->BS_FilSysType, "FAT32   ", 8);

//90 420
memset(bootSector->BS_Reserved2, 0, 420);

//510 2
// 如果我们认为我们的Sector是按照Bytes排列,那么我们应该在bootsector[510]
// 设置0x55,在bootsector[511]设置0xAA。
// 注意: 许多文档犯了一个错误,就是认为0xAA55占用了“Last 2 bytes of bootsector”
// 这个说法只有在而起仅仅只有当BPB_BytsPerSec为512时成立。因为当设置512以外的
// 其他值时,0xAA55标志被设置的位置不会被改变,还是在510和511。
bootSector->BS_BootSig2 = 0xAA55;

// 清零所有保留扇区
memset(tempBuffer, 0 , SECTOR_SIZE);
for(i = 0; i < bootSector->BPB_ResvdSecCnt; i++)  // BPB_ResvdSecCnt = 32;
{
offset.QuadPart = i * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Clear reserved sector failed, status: %lx\n", status ));
return status;
}
}

// 写入BootSector
offset.QuadPart = 0;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
bootSector,
SECTOR_SIZE,
&offset
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write Boot Sector Failed, status: %lx\n", status ));
return status;
}

// 写入备份BootSector
offset.QuadPart = bootSector->BPB_BkBootSec * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
bootSector,
SECTOR_SIZE,
&offset
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write Backup Boot Sector Failed, status: %lx\n", status ));
return status;
}

//////////////////////////////////////////////////////////////////////////
//
// TODO: Init Info Sector

memset(tempBuffer, 0, SECTOR_SIZE);

*(LONG *)(&tempBuffer[0]) = 0x41615252;
*(LONG *)(&tempBuffer[484]) = 0x61417272;
*(LONG *)(&tempBuffer[488]) = 0xFFFFFFFF;
*(LONG *)(&tempBuffer[492]) = 0xFFFFFFFF;
*(LONG *)(&tempBuffer[508]) = 0xAA550000;

// 写入InfoSector

offset.QuadPart = bootSector->BPB_FSInfo*SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write info Sector Failed, status: %lx\n", status ));
return status;
}
// 备份Infor Sector
offset.QuadPart = (bootSector->BPB_BkBootSec+ bootSector->BPB_FSInfo)*SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write info Sector Failed, status: %lx\n", status ));
return status;
}

// 填写Info Sector后面一个Sector,只最后结束标志
memset(tempBuffer, 0, SECTOR_SIZE);
((PUCHAR)tempBuffer)[510] = 0x55;
((PUCHAR)tempBuffer)[511] = 0xAA;

offset.QuadPart = (bootSector->BPB_FSInfo + 1) * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset
);

if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write Backup Boot Sector Failed, status: %lx\n", status ));
return status;
}

// 在备份Info Sector后面的,备份一个同样的Sector

offset.QuadPart = (bootSector->BPB_BkBootSec + bootSector->BPB_FSInfo + 1) * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset
);

if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write Backup Boot Sector Failed, status: %lx\n", status ));
return status;
}




//////////////////////////////////////////////////////////////////////////
//
// TODO: 填写FAT表

memset( tempBuffer, 0, SECTOR_SIZE);
*(ULONG *)(&tempBuffer[0]) = 0x0ffffff8; // FAT[0]应该和MediaType一样F8
*(ULONG *)(&tempBuffer[4]) = 0xFFFFFFFF;
*(ULONG *)(&tempBuffer[8]) = 0X0FFFFFFF; //root dir;

// 写入FAT表1,偏移量为保留扇区数乘以SECTOR_SIZE

offset.QuadPart = bootSector->BPB_ResvdSecCnt*SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write FAT1 failed, status: %x\n", status ));
return status;
}

// 将FAT1+1到FAT2之间的区域填0

memset(tempBuffer, 0, SECTOR_SIZE);
for(i = bootSector->BPB_ResvdSecCnt + 1; i < bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32; i++)
{
offset.QuadPart = i*SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Clean FAT1 failed, status: %x\n", status ));
return status;
}

}
// 写入FAT表2,偏移量为(保留扇区数 + FAT表大小) * SECTOR_SIZE

memset( tempBuffer, 0, SECTOR_SIZE);
*(ULONG *)(&tempBuffer[0]) = 0x0ffffff8; // FAT[0]应该和MediaType一样F8
*(ULONG *)(&tempBuffer[4]) = 0xFFFFFFFF;
*(ULONG *)(&tempBuffer[8]) = 0X0FFFFFFF; //root dir;

offset.QuadPart = (bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32) * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write FAT2 failed, status: %x\n", status ));
return status;
}

// 将FAT2+1到RootEntry之间的区域填0
memset(tempBuffer, 0, SECTOR_SIZE);
for(i = bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32 + 1;
i < bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32*2+1; i++)
{
offset.QuadPart = i*SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Clean FAT2 failed, status: %x\n", status ));
return status;
}

}
//////////////////////////////////////////////////////////////////////////
//
// TODO: 填写根目录

memset( tempBuffer, 0, SECTOR_SIZE);
strncpy(((PDIR_ENTRY)tempBuffer)->DIR_Name, "FILEBACKUP ", 11);
((PDIR_ENTRY)tempBuffer)->DIR_Attr = 0x08;

// 写入根目录结构
offset.QuadPart = (bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32*bootSector->BPB_NumFATs) * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Write dir failed, status: %x\n", status ));
return status;
}

memset(tempBuffer, 0, SECTOR_SIZE);
for(i = bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32*bootSector->BPB_NumFATs + 1;
i < bootSector->BPB_ResvdSecCnt + bootSector->BPB_FATSz32*bootSector->BPB_NumFATs + bootSector->BPB_SecPerClus + 1;
i++ )
{
offset.QuadPart = i * SECTOR_SIZE;
status = ExdiskWriteFile(
pdx->DiskPerfDeviceObject,
&ioStatus,
tempBuffer,
SECTOR_SIZE,
&offset // FAT 1 offset, from reserved sectors end.
);
if(!NT_SUCCESS(status)) {

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_VERBOSE,
( "Clear dir failed, status: %x\n", status ));
return status;
}
}

return STATUS_SUCCESS;
钱就是驱动,驱动就是钱。
delux9704
驱动牛犊
驱动牛犊
  • 注册日期2002-11-14
  • 最后登录2010-11-15
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-11-09 10:10
偶比较笨的做法是自己按规范算~~~
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-11-08 14:26
自己实现应该比较麻烦
dos下就简单好多了,调用磁盘中断
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
sharkmouse
禁止发言
禁止发言
  • 注册日期2003-05-05
  • 最后登录2016-04-11
  • 粉丝0
  • 关注0
  • 积分1355分
  • 威望7163点
  • 贡献值1点
  • 好评度24点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-11-08 13:00
用户被禁言,该主题自动屏蔽!
Ares
驱动小牛
驱动小牛
  • 注册日期2001-03-28
  • 最后登录2020-04-09
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望114点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2004-11-08 09:51
做病毒?研究文件系统吧
易水
nustzhua
驱动中牛
驱动中牛
  • 注册日期2002-06-19
  • 最后登录2015-09-27
  • 粉丝0
  • 关注0
  • 积分18分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-11-08 09:29
这个我以前也考虑去做得,不过比较复杂。
一直也没成功。
不限容量的免费邮箱 www.k65.net
游客

返回顶部