QT(C++)DeviceIoControl()函数的相关使用

10 篇文章 0 订阅
4 篇文章 0 订阅

Microsoft官网中有这个函数的介绍,对,仅仅就是介绍,有时候官网的查询结果也就只能看看……

在我写过的一个软件中,我曾经多次使用该函数获取相关结果,现将我的使用经验分享给大家!


DeviceIoControl()函数将控制代码直接发送到指定的设备驱动,使相应的设备执行指定的操作。函数原型如下:

BOOL DeviceIoControl(
    HANDLE hDevice,               //设备句柄
    DWORD dwIoControlCode,        //欲执行操作类型
    LPVOID lpInBuffer,            //操作输入的数据缓冲区,不需要输入数据时可为NULL
    DWORD nInBufferSize,          //输入缓冲区的大小,不需要输入数据时可为0
    LPVOID lpOutBuffer,           //接收操作返回数据的缓冲区,没有数据输出时可为NULL
    DWORD nOutBufferSize,         //接收缓冲区的大小,没有数据输出时可为0
    LPDWORD lpBytesReturned,      //实际返回数据的大小,没有数据输出时可为NULL
    LPOVERLAPPER lpOverlapped     //忽略此项,直接设置成NULL
);

返回值非0表示函数使用成功;0表示失败,失败信息可以通过GetLastError()函数获得。


(1)对非系统盘加锁、解锁

DeviceIoControl(file, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, NULL, NULL);

DeviceIoControl(file, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, NULL, NULL);

//这里的非系统盘指的是U盘,系统盘加锁是不会成功的,因为操作系统本身时刻都对系统盘有操作。

//file如果是驱动器句柄,那么就是将整个驱动器锁起来;如果是驱动器的某个分盘句柄,则将这个分盘锁起来。

(2)获取磁盘所在的物理驱动器号

string PhysicalDrive = "\\\\.\\PhysicalDrive";        

STORAGE_DEVICE_NUMBER Number;

DeviceIoControl(file, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &Number, sizeof(Number), NULL, (LPOVERLAPPED)NULL);

PhysicalDrive += to_string(Number.DeviceNumber);  

//这里使用PhysicalDrive是为了后续方便直接获取驱动器句柄,获取驱动器句柄的CreateFile()函数中的第一个参数便是类似 \\.\PhysicalDrive0 的参数
//详情可以查阅Microsoft官网CreateFile关于物理驱动器句柄的获取

//file为磁盘句柄

//Number的DeviceNumber返回的便是当前磁盘所在的驱动器号

(3)获取磁盘总字节数

GET_LENGTH_INFORMATION available;

DeviceIoControl(file, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &available, sizeof(available), 0, NULL);

UINT64 DiskSize = available.Length.QuadPart;

//file为磁盘(驱动器)句柄,获取对应类别的总字节数

//DiskSize则为磁盘总字节数

//为什么会使用这种方法获取磁盘总字节数呢?
//使用过DiskGenius的朋友会发现 柱面数 × 磁道数 × 扇区数 × 每扇区字节数 != 磁盘总字节数
//这是因为有多余的字节数并不能凑够一个柱面,所以通过正常的获取磁头数等信息并不能正确获取总字节数

//获取了总字节数后,便可以通过(4)的函数获取每个扇区的字节数,从而计算整个磁盘的扇区总数

(4)获取磁盘的磁头数、柱面数、扇区数、每扇区字节数

DISK_GEOMETRY pdg;

DeviceIoControl(DiskHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &pdg, sizeof(pdg), NULL, (LPOVERLAPPED)NULL);


//DiskHandle可以为磁盘句柄、驱动器句柄,则此函数获取对应的数据

//pdg.Cylinders.QuadPart为柱面数
//pdg.TracksPerCylinder为每个柱面磁道数
//pdg.SectorsPerTrack为每个磁道扇区数
//pdg.BytesPerSector为每个扇区的字节数

//用此方法得出的 柱面数 × 磁道数 × 扇区数 × 每扇区字节数 = 总字节数,一般研究这种情况下的数据
//特殊情况区别对待
//此时的总字节数会比实际字节数少,实际字节数可以用(3)的方法获取
//此方法主要是获取磁盘(驱动器)的标准数据

//实际总扇区数 = (3)获取的总字节数 / 每扇区字节数

在我写过的软件中,这四种方法都使用过,读者可以根据需要复制代码,请仔细理解每个方法中的注释内容!

最后,有帮助的话可以给我一丢丢赞赏嚯!(记得备注CSDN,我会更有动力更新文章嚯!)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值