`

【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/O

return 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。
分享到:
评论

相关推荐

    API格式化磁盘.rar

    2. **找到相关API函数**:在Kernel32.dll中,有两个重要的函数与磁盘格式化相关:`CreateFile()` 和 `DeviceIoControl()`。`CreateFile()` 用于打开一个设备文件,如磁盘驱动器;`DeviceIoControl()` 则可以发送控制...

    C++ 磁盘格式化类+示例.

    "C++ 磁盘格式化类+示例"可能是一个第三方库或者自定义的类设计,用于封装这些系统调用,使得开发者能够更加方便地对磁盘进行格式化操作。下面我们将详细讨论相关的知识点。 首先,我们需要理解磁盘格式化的概念。...

    易语言源码磁盘格式化模块 1.0.7z

    这个函数可能包含与系统API的交互,调用如`CreateFile`、`DeviceIoControl`等低级函数来完成格式化任务。 3. **错误处理**:在格式化过程中可能会遇到各种问题,如磁盘被占用、权限不足等,模块需要有良好的错误...

    易语言DeviceIoControl取硬盘序列号源码

    在Windows操作系统中,我们可以利用设备I/O控制(DeviceIoControl)函数来与硬件设备进行交互,包括获取硬盘的序列号。DeviceIoControl函数是Windows API提供的一种功能强大的接口,允许应用程序发送自定义的控制...

    VC 格式化磁盘的源代码.rar

    `CreateFile`用于打开设备(如磁盘驱动器),`DeviceIoControl`则用于发送控制请求到设备,比如执行格式化操作。`CloseHandle`则用于在操作完成后关闭设备句柄,释放资源。 以下是这些API的基本用法: 1. `...

    vb编写磁盘格式化

    在这个"vb编写磁盘格式化"的项目中,我们看到的三个文件是VB应用程序的基本组成部分: 1. **磁盘格式化.frm**:这是窗体文件,它包含了程序的用户界面设计。在该文件中,开发者可能定义了各种控件,如按钮、文本框...

    格式化磁盘工具

    在IT领域,格式化磁盘是一项常见的操作,用于清理磁盘数据、修复文件系统错误或为新操作系统安装做准备。本文将深入探讨“格式化磁盘工具”的创建过程,涉及如何调用系统的API函数,以及相关的核心知识点。 首先,...

    磁盘格式化演示程序(2KB)...

    这可能意味着这个文件与浏览或管理文件夹有关,或者是磁盘格式化过程中的一个步骤。 综合以上信息,我们可以预想这个压缩包的内容可能包含了一个演示如何格式化磁盘的源代码程序,可能涉及以下知识点: 1. 文件...

    格式化磁盘模块源码和例程

    2. 初始化文件系统:格式化过程中,会创建一个新的文件系统结构,比如FAT、NTFS、EXT等,这一步通常涉及MBR(主引导记录)或GPT(GUID分区表)的编写。 3. 分配空间:根据用户选择的分区大小,分配磁盘空间,并创建...

    windows如何创建虚拟磁盘 建立一个虚拟磁盘方法

    这涉及到Windows API(应用程序接口)的使用,尤其是与磁盘管理和文件系统相关的函数,例如CreateFile、DeviceIoControl等。这些API允许程序员直接与硬件交互,创建和操作虚拟磁盘。 在提供的压缩文件“29782204...

    易语言源码易语言API格式化磁盘源码.rar

    4. `CreateFile` 和 `DeviceIoControl`:这两个函数可以用来向磁盘发送特定的控制命令,例如初始化磁盘或者执行低级格式化。 5. `CloseHandle`:格式化完成后,关闭打开的磁盘句柄,释放系统资源。 6. 错误处理:...

    用VC进行磁盘格式化操作

    在Windows操作系统中,VC++(Visual C++)是一种强大的开发环境,可以用来编写各种应用程序,包括与硬件交互的低级操作,比如磁盘格式化。本文将深入探讨如何使用VC++进行磁盘格式化操作。 首先,理解磁盘格式化的...

    开源(VB代码):VB实现格式化磁盘.zip

    快速格式化只删除文件系统,不检查磁盘错误;而完全格式化会检查磁盘的物理错误并修复。 在VB中,我们可以使用Windows API(应用程序接口)来执行磁盘格式化操作,因为VB本身并不直接支持这一功能。API函数通常需要...

    格式化u盘,移动硬盘

    对于U盘和移动硬盘来说,格式化也常常用于改变其文件系统的类型,例如从FAT32转换为NTFS,以支持更大的单个文件大小或提供更好的安全性。 在编程角度,实现格式化功能通常涉及到操作系统提供的API调用。例如,在...

    易语言DeviceIoControl取硬盘序列号

    易语言DeviceIoControl取硬盘序列号源码,DeviceIoControl取硬盘序列号,倒序排列,DeviceIoControl,CreateFileA,CloseHandle,GetLastError,LocalAlloc,LocalFree

    FAT32 格式化源代码

    这意味着源代码会依赖于微软的 Windows API(应用程序接口),这是一个允许开发者与操作系统交互的库,包括进行磁盘操作如格式化的功能。 C/C++ 是一种强大的编程语言,它提供了低级别的硬件访问能力,使得直接操作...

    DeviceIoControl取硬盘序列号.rar

    DeviceIoControl取硬盘序列号.rar

    自动格式化U盘小工具

    在IT领域,自动格式化U盘的小工具是一种实用程序,旨在简化用户对USB闪存驱动器的格式化过程。这个小工具特别适用于那些在尝试格式化U盘时遇到权限问题的用户。它采用了一种双层策略来确保格式化操作能够顺利完成。 ...

    Ring3层直接扇区读写修改文件,用到DeviceIoControl和FSCTL_GET_RETRIEVAL_POINTERS

    使用DeviceIoControl和FSCTL_GET_RETRIEVAL_POINTERS结合,开发者可以在用户空间(Ring3层)实现类似于“机器狗”这样的功能,即绕过操作系统常规的文件操作机制,直接读写磁盘扇区,这对于分析病毒行为、数据恢复...

    软盘扇区读写工具,软盘镜像文件生成器

    软盘扇区读写工具与软盘镜像文件生成器是一种专门用于操作软盘数据的软件,主要功能包括创建和编辑软盘的镜像文件。在这个项目中,开发者使用了经典的编程环境 VC++6(Visual C++ 6.0)来实现这个功能,这是一款在...

Global site tag (gtag.js) - Google Analytics