实战DeviceIoControl系列之三:制作磁盘镜像文件

Q DOS命令 DISKCOPY 给我很深的印象,现在也有许多“克隆”软件,可以对磁盘进行全 盘复制。我想,要制作磁盘镜像文件,DeviceIoControl 应该很有用武之地吧?

A 是的。这里举一个制作软盘镜像文件,功能类似于“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;
}

时间: 2024-11-08 18:57:52

实战DeviceIoControl系列之三:制作磁盘镜像文件的相关文章

实战DeviceIoControl 之三:制作磁盘镜像文件

Q DOS命令DISKCOPY给我很深的印象,现在也有许多"克隆"软件,可以对磁盘进行全盘复制.我想,要制作磁盘镜像文件,DeviceIoControl应该很有用武之地吧? A 是的.这里举一个制作软盘镜像文件,功能类似于"DISKCOPY"的例子. 本例实现其功能的核心代码如下: // 打开磁盘 HANDLE OpenDisk(LPCTSTR filename) {     HANDLE hDisk;       // 打开设备     hDisk = ::Cre

实战DeviceIoControl系列之一:通过API访问设备驱动程序

Q 在 NT/2000/XP 中,我想用 VC 编写应用程序访问硬件设备,如获取磁盘参数.读写绝对扇区数据.测试光驱实际速度等,该从哪里入手呢? A 在 NT/2000/XP 中,应用程序可以通过 API 函数 DeviceIoControl 来实现对设备的访问-获取信息,发送命令,交换数据等.利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就可以达到我们的目的. DeviceIoControl 的函数原型为 BOOL DeviceIoControl( HANDLE hD

实战DeviceIoControl系列之二:获取软盘/硬盘/光盘的参数

Q 在MSDN的那个demo中,将设备名换成"A:"取 A 盘参数,先用资源管理器读一下盘,再运行这个程序可以成功,但换一张盘后就失败:换成"CDROM0" 取CDROM参数,无论如何都不行.这个问题如何解决呢? A 取软盘参数是从软盘上读取格式化后的信息,也就是必须执行读操作,这一点与硬盘不同.将CreateFile中的访问方式改为GENERIC_READ就行了. IOCTL_DISK_GET_DRIVE_GEOMETRY这个 I/O 控制码,对软盘和硬盘有效,但

实战DeviceIoControl系列之四:获取硬盘的详细信息

Q 用IOCTL_DISK_GET_DRIVE_GEOMETRYIOCTL_STORAGE_GET_MEDIA_TYPES_EX只能得到很少的磁盘参数,我想获得包括硬盘序列号在内的更加详细的信息,有什么办法呀? A 确实,用你所说的I/O控 制码,只能得到最基本的磁盘参数.获取磁盘出厂信息的I/O控制码,微软在VC/MFC环境中没有开放,在DDK中可以发现一些线索.早先,Lynn McGuire写了一个很出名的获取IDE硬盘详细信息的程序DiskID32 ,下面的例子是在其基础上经过增删和改进而

LXD 2.0系列之三:你的第一个LXD容器

本文讲的是LXD 2.0系列之三:你的第一个LXD容器,[编者的话]第三方调查报告显示LXD有潜质成为一款受欢迎的第三方容器管理工具.本文是LXD核心维护者.加拿大程序员Stéphane Graber有关LXD连载博文的第三篇. [LXD 2.0系列开篇:是时候讨论LXD的一切了][LXD 2.0系列之一:LXD简介][LXD 2.0系列之二:LXD安装和配置][LXD 2.0系列之三:你的第一个LXD容器][LXD 2.0系列之四:资源管理][LXD 2.0系列之五:镜像管理][LXD 2.0

web标准实现高效开发系列之三

web|web标准 先点击这里下载Editplus CSS语法自动完成文件 先点击这里下载Editplus xHTML语法自动完成文件应版中朋友的要求我编写了一下xHtml的自动完成文件.下载后解压到EP的根目录下,然后在EP的首选项的语法中设定这个文件.然后用EP打开这个文件,看一下就清楚怎么用了. 举例:打一个"d"然后空格,然后EP就会把这个"d"变成<div></div> 先点击这里下载TopStyle 剪贴库文件 软件下载:TopS

ASP.NET企业开发框架IsLine FrameWork系列之三--七种武器

IsLine FrameWork Provider介绍 其中IsLine.Data.IsLine.AppLog是我要重点介绍的,不过现在先来简单说说各个Provider的作用. DataProvider 与其他框架一样,DataProvider为项目提供了与数据库交互的能力,它的优点在这里不再阐述,这里 只说一下它与其他框架的数据访问层不同的地方. DataProvider同时兼容SQL SERVER与ORACLE两种数据库,并开放IDBOperater接口,用户只要实现 IDBOperater

Red Gate系列之三 SQL Server 开发利器 SQL Prompt 5.3.4.1 Edition T-SQL智能感知分析器 完全破解+使用教程

原文:Red Gate系列之三 SQL Server 开发利器 SQL Prompt 5.3.4.1 Edition T-SQL智能感知分析器 完全破解+使用教程 Red Gate系列之三 SQL Server 开发利器 SQL Prompt 5.3.4.1 Edition T-SQL智能感知分析器 完全破解+使用教程 Red Gate系列文章: Red Gate系列之一 SQL Compare 10.2.0.1337 Edition 数据库比较工具 完全破解+使用教程 Red Gate系列之二

完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三

转载自 PiggyXP(小猪) 完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三 手把手叫你玩转网络编程系列之三    完成端口(Completion Port)详解                                                              ----- By PiggyXP(小猪) 前 言         本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何提笔,所以这篇文档总是在酝酿之中