首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

【DeviceIoControl】 3、制作磁盘镜像文件与磁盘格式化

2012-09-10 
【DeviceIoControl】 三、制作磁盘镜像文件与磁盘格式化现在有许多“克隆”软件,可以对磁盘进行全盘复制。如果要

【DeviceIoControl】 三、制作磁盘镜像文件与磁盘格式化
现在有许多“克隆”软件,可以对磁盘进行全盘复制。如果要制作磁盘镜像文件,DeviceIoControl就有了用武之地了。这里举一个制作软盘镜像文件,功能类似于“DISKCOPY”的例子。
本例实现其功能的核心代码如下:

// 打开磁盘HANDLE OpenDisk(LPCTSTR filename){HANDLE hDisk;// 打开设备hDisk = ::CreateFile(filename,    // 文件名   GENERIC_READ | GENERIC_WRITE,   // 读写方式   FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式   NULL,      // 默认的安全描述符   OPEN_EXISTING,     // 创建方式   0,      // 不需设置文件属性   NULL);      // 不需参照模板文件return hDisk;}// 获取磁盘参数BOOL GetDiskGeometry(HANDLE hDisk, PDISK_GEOMETRY lpGeometry){     DWORD dwOutBytes;BOOL bResult;// 用IOCTL_DISK_GET_DRIVE_GEOMETRY取磁盘参数bResult = ::DeviceIoControl(hDisk,   // 设备句柄   IOCTL_DISK_GET_DRIVE_GEOMETRY,   // 取磁盘参数   NULL, 0,     // 不需要输入数据   lpGeometry, sizeof(DISK_GEOMETRY), // 输出数据缓冲区   &dwOutBytes,     // 输出数据长度   (LPOVERLAPPED)NULL);    // 用同步I/Oreturn bResult;}// 从指定磁道开始读磁盘BOOL ReadTracks(HANDLE hDisk, PDISK_GEOMETRY lpGeometry, LPVOID pBuf, DWORD dwStartCylinder, DWORD dwCylinderNumber){     DWORD VirtBufSize;     DWORD BytesRead;                // 大小VirtBufSize =   lpGeometry->TracksPerCylinder * lpGeometry->SectorsPerTrack * lpGeometry->BytesPerSector;// 偏移::SetFilePointer(hDisk, VirtBufSize*dwStartCylinder, NULL, FILE_BEGIN);return ::ReadFile(hDisk, pBuf, VirtBufSize*dwCylinderNumber, &BytesRead, NULL);}// 从指定磁道开始写磁盘BOOL WriteTracks(HANDLE hDisk, PDISK_GEOMETRY lpGeometry, LPVOID pBuf, DWORD dwStartCylinder, DWORD dwCylinderNumber){     DWORD VirtBufSize;     DWORD BytesWritten;// 大小VirtBufSize =   lpGeometry->TracksPerCylinder * lpGeometry->SectorsPerTrack * lpGeometry->BytesPerSector;// 偏移::SetFilePointer(hDisk, VirtBufSize*dwStartCylinder, NULL, FILE_BEGIN);     return ::WriteFile(hDisk, pBuf, VirtBufSize*dwCylinderNumber, &BytesWritten, NULL);}// 从指定磁道开始格式化磁盘BOOL LowLevelFormatTracks(HANDLE hDisk, PDISK_GEOMETRY lpGeometry, DWORD dwStartCylinder, DWORD dwCylinderNumber){     FORMAT_PARAMETERS FormatParameters;     PBAD_TRACK_NUMBER lpBadTrack;     DWORD dwOutBytes;     DWORD dwBufSize;     BOOL bResult;     FormatParameters.MediaType = lpGeometry->MediaType;     FormatParameters.StartCylinderNumber = dwStartCylinder;     FormatParameters.EndCylinderNumber = dwStartCylinder + dwCylinderNumber - 1;     FormatParameters.StartHeadNumber = 0;     FormatParameters.EndHeadNumber = lpGeometry->TracksPerCylinder - 1;     dwBufSize = lpGeometry->TracksPerCylinder * sizeof(BAD_TRACK_NUMBER);     lpBadTrack = (PBAD_TRACK_NUMBER) new BYTE[dwBufSize];                // 用IOCTL_DISK_FORMAT_TRACKS对连续磁道进行低级格式化bResult = ::DeviceIoControl(hDisk,    // 设备句柄   IOCTL_DISK_FORMAT_TRACKS,    // 低级格式化   &FormatParameters, sizeof(FormatParameters), // 输入数据缓冲区   lpBadTrack, dwBufSize,     // 输出数据缓冲区   &dwOutBytes,      // 输出数据长度   (LPOVERLAPPED)NULL);     // 用同步I/O     delete lpBadTrack;     return bResult;}// 将卷锁定BOOL LockVolume(HANDLE hDisk){     DWORD dwOutBytes;     BOOL bResult;// 用FSCTL_LOCK_VOLUME锁卷bResult = ::DeviceIoControl(hDisk,   // 设备句柄   FSCTL_LOCK_VOLUME,    // 锁卷   NULL, 0,     // 不需要输入数据   NULL, 0,     // 不需要输出数据   &dwOutBytes,     // 输出数据长度   (LPOVERLAPPED)NULL);    // 用同步I/O     return bResult;}// 将卷解锁BOOL UnlockVolume(HANDLE hDisk){     DWORD dwOutBytes;     BOOL bResult;// 用FSCTL_UNLOCK_VOLUME开卷锁bResult = ::DeviceIoControl(hDisk,   // 设备句柄   FSCTL_UNLOCK_VOLUME,    // 开卷锁   NULL, 0,     // 不需要输入数据   NULL, 0,     // 不需要输出数据   &dwOutBytes,     // 输出数据长度   (LPOVERLAPPED)NULL);    // 用同步I/O     return bResult;}// 将卷卸下// 该操作使系统重新辨识磁盘,等效于重新插盘BOOL DismountVolume(HANDLE hDisk){     DWORD dwOutBytes;     BOOL bResult;// 用FSCTL_DISMOUNT_VOLUME卸卷bResult = ::DeviceIoControl(hDisk,   // 设备句柄   FSCTL_DISMOUNT_VOLUME,    // 卸卷   NULL, 0,     // 不需要输入数据   NULL, 0,     // 不需要输出数据   &dwOutBytes,     // 输出数据长度   (LPOVERLAPPED)NULL);    // 用同步I/O     return bResult;}


将软盘保存成镜像文件的步骤简单描述为:
1、创建空的镜像文件。
2、调用OpenDisk打开软盘。成功转3,失败转8。
3、调用LockVolume将卷锁定。成功转4,失败转7。
4、调用GetDiskGeometry获取参数。成功转5,失败转6。
5、将磁盘参数写入镜像文件作为文件头。调用ReadTracks按柱面读出数据,保存在镜像文件中。循环次数等于柱面数。
6、调用UnlockVolume将卷解锁。
7、调用CloseDisk关闭软盘。
8、关闭镜像文件。

将镜像文件载入软盘的步骤简单描述为:
1、打开镜像文件。
2、调用OpenDisk打开软盘。成功转3,失败转11。
3、调用LockVolume将卷锁定。成功转4,失败转10。
4、调用GetDiskGeometry获取参数。成功转5,失败转9。
5、从镜像文件中读出文件头,判断两个磁盘参数是否一致。不一致转6,否则转7。
6、调用LowLevelFormatTracks按柱面格式化软盘。循环次数等于柱面数。成功转7,失败转8。
7、从镜像文件中读出数据,并调用WriteTracks按柱面写入磁盘。循环次数等于柱面数。
8、调用DismountVolume将卷卸下。
9、调用UnlockVolume将卷解锁。
10、调用CloseDisk关闭软盘。
11、关闭镜像文件。


注意到,磁盘读写和格式化是按柱面进行的,这是为了在例子中可以方便地显示处理进度。

有一点需要特别提及,按绝对地址读写磁盘数据时,“最小单位”是扇区,地址一定要与扇区对齐,长度也要等于扇区长度的整数倍。比如,每扇区512字节,那么起始地址和数据长度都应能被512整除才行。

如果你想测试光驱的传输速度了,就用上面的方法,读出一定长度数据,除以所需时间,不过取光盘参数时要用IOCTL_STORAGE_GET_MEDIA_TYPES_EX。

热点排行