关于IOCTL_STORAGE_QUERY_PROPERTY控制码在Vista下的一个奇怪问题

本文介绍了在Visual Studio 2008环境下使用 IOCTL_STORAGE_QUERY_PROPERTY 控制码进行存储设备查询时遇到的问题及解决办法,并讨论了在不同操作系统上出现的数据结构变化情况。

众所周知,IOCTL_STORAGE_QUERY_PROPERTY控制码是用于列举系统中已安装的存储设备,在通过CreateFile打开设备后,通常的调用方式如下:

这段代码在VC 6.0中运行没有问题,但是当移植到VS 2008中运行时,DeviceIoControl将失败,返回错误代码为ERROR_BAD_LENGTH,令人百思不得其解,查了MSDN也没提到这样的问题,只好自己动手实验,结果发现把sizeof(query)这个参数加上3以上的数的时候,在Vista+VS 2008的平台上运行就正常了,具体原因为何会这样,还需要进一步的研究。

 

[后续研究]

2010年4月,我们发现在Vista/Win 7等系统中,VS 2008编译的版本会导致采用这种方法获取到硬盘的某个数据结构发生变化,主要是DISK_INT13_INFO这个结构,原本应该记录在SectorsPerTrack中的数据跑到了MaxHeads中,根据测试的情况,可能是MS修改了数据结构但是没有改头文件,如果真是这样,真的让人很无语啊。

### IOCTL_VIDEO_QUERY_DISPLAY_CONFIG 的使用方法 `IOCTL_VIDEO_QUERY_DISPLAY_CONFIG` 是用于查询显示配置的 Windows 设备 I/O 控制代码。此控制码允许应用程序获取有关当前显示器连接状态及其模式设置的信息。 #### 函数原型 ```c DWORD WINAPI DeviceIoControl( (HANDLE) hDevice, IOCTL_VIDEO_QUERY_DISPLAY_CONFIG, NULL, 0, lpOutBuffer, nOutBufferSize, lpBytesReturned, (LPOVERLAPPED) lpOverlapped ); ``` 参数说明如下: - `hDevice`: 调用 CreateFile 打开的目标设备句柄。 - `lpOutBuffer`: 输出缓冲区指针,指向接收返回数据结构体数组的位置。 - `nOutBufferSize`: 输出缓冲区大小(字节)。 - `lpBytesReturned`: 返回实际写入到输出缓冲区的数据量。 - `lpOverlapped`: 指向 OVERLAPPED 结构的指针;如果操作是非重叠同步调用,则该值应为NULL[^1]。 #### 数据结构定义 为了处理 `IOCTL_VIDEO_QUERY_DISPLAY_CONFIG` 请求的结果,需定义相应的数据结构。主要涉及两个结构体:`VIDEO_DISPLAYCONFIG_PATH_INFO` 和 `DISPLAYCONFIG_RATIONAL`。 ##### VIDEO_DISPLAYCONFIG_PATH_INFO 描述路径信息,包括源和目标适配器索引以及对应的模式信息等字段。 ##### DISPLAYCONFIG_RATIONAL 表示有理数形式的时间间隔,通常用来表达刷新率。 #### 示例代码 下面是一个简单的 C++ 示例程序片段展示如何使用这个 ioctl 来枚举所有可用的显示设备并打印其基本信息。 ```cpp #include <windows.h> #include <stdio.h> void QueryDisplayConfig() { DWORD result; UINT32 numPathElements = 0; UINT32 numModeInfoElements = 0; // First call to get required buffer sizes. DisplayConfigGetDeviceInfo(&numPathElements, &numModeInfoElements); PDISPLAYCONFIG_PATH_INFO pathArray = (PDISPLAYCONFIG_PATH_INFO)new BYTE[numPathElements * sizeof(DISPLAYCONFIG_PATH_INFO)]; PDISPLAYCONFIG_MODE_INFO modeInfoArray = (PDISPLAYCONFIG_MODE_INFO)new BYTE[numModeInfoElements * sizeof(DISPLAYCONFIG_MODE_INFO)]; try { result = DisplayConfigGetDeviceInfo(pathArray, modeInfoArray); for(UINT i = 0; i < numPathElements ; ++i){ printf("Source Adapter ID:%d\n",pathArray[i].sourceInfo.adapterId); printf("Target Adapter ID:%d\n",pathArray[i].targetInfo.adapterId); } } catch (...) { wprintf(L"Error occurred.\n"); } delete[] pathArray; delete[] modeInfoArray; } ``` 上述代码展示了通过两次调用 `DisplayConfigGetDeviceInfo()` 获取所需内存空间大小后再分配适当的空间存储结果的方式。第一次调用仅是为了获得必要的输入参数数目以便后续动态创建合适的缓存区域。第二次则是真正执行查询并将结果显示出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值