如何使用GUID_DEVINTERFACE_DISK过滤CM_Get_Device_Interface_List结果
正确调用CM_Get_Device_Interface_List获取GUID_DEVINTERFACE_DISK设备的方法
报错原因说明
你遇到的类型不兼容报错是正确的,你看到的示例代码存在根本性错误:CM_Get_Device_Interface_List的第一个参数要求传入设备接口类GUID的字符串表示,不是GUID结构体的指针,强制将LPGUID类型转为PCWSTR属于非法内存访问,必然触发异常。
方法1:直接获取所有当前存在的磁盘设备接口
无需额外调用SetupDi系列函数,仅通过CM_Get_Device_Interface_List即可完成需求,步骤如下:
- 调用系统API
StringFromGUID2将GUID_DEVINTERFACE_DISK结构体转换为符合要求的带大括号的GUID字符串格式。 - 第一次调用
CM_Get_Device_Interface_List,传入空缓冲区获取所需的缓冲区长度。 - 分配足够内存后,第二次调用获取实际的磁盘设备接口列表,返回的缓冲区为多字符串结构,每个设备接口路径以
\0分隔,末尾以连续两个\0结束。
示例代码
需包含头文件并链接对应库:
#include <windows.h> #include <initguid.h> #include <ntdddisk.h> #include <cfgmgr32.h> #include <tchar.h> #pragma comment(lib, "Cfgmgr32.lib")
功能实现代码:
CONFIGRET cr; WCHAR szGuidBuf[GUID_STRING_LENGTH] = {0}; ULONG ulBufLen = 0; PWSTR pDeviceList = NULL; // 将GUID结构体转为系统要求的字符串格式 if (StringFromGUID2(GUID_DEVINTERFACE_DISK, szGuidBuf, GUID_STRING_LENGTH) == 0) { // 转换失败处理逻辑 return; } // 第一次调用获取所需缓冲区长度 cr = CM_Get_Device_Interface_ListW(szGuidBuf, NULL, NULL, &ulBufLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr != CR_SUCCESS) { // 错误处理逻辑 return; } // 分配缓冲区内存 pDeviceList = (PWSTR)HeapAlloc(GetProcessHeap(), 0, ulBufLen * sizeof(WCHAR)); if (!pDeviceList) { // 内存分配失败处理逻辑 return; } // 第二次调用获取实际设备接口列表 cr = CM_Get_Device_Interface_ListW(szGuidBuf, NULL, pDeviceList, ulBufLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr == CR_SUCCESS) { PWSTR pCur = pDeviceList; // 遍历多字符串结构 while (*pCur) { // pCur即为当前磁盘的设备接口路径,可直接传入CreateFile访问设备 wprintf(L"磁盘接口路径:%s\n", pCur); pCur += wcslen(pCur) + 1; } } // 释放内存 HeapFree(GetProcessHeap(), 0, pDeviceList);
方法2:过滤指定磁盘设备的接口
如果需要获取单个磁盘对应的关联卷等信息,可结合DEVINST过滤:
- 调用
SetupDiGetClassDevs时需传入DIGCF_PRESENT | DIGCF_DEVICEINTERFACE标志,避免仅获取到设备安装类信息。 - 调用
CM_Get_Device_ID将你拿到的DEVINST转为字符串形式的设备实例ID。 - 调用
CM_Get_Device_Interface_List时,将第二个参数pwszDeviceID设置为上述设备实例ID,即可过滤出仅属于该磁盘的接口列表。
常见注意事项
- 不要混淆
CM_Get_Device_Interface_List和CM_Get_Device_ID_List,前者用于获取可直接访问的设备接口路径,后者用于获取设备实例ID列表。 - 遍历返回的多字符串缓冲区时,必须以连续两个
\0作为结束标志,避免内存越界。 - 你拿到的DEVINST值为1、2属于正常情况,DEVINST是系统分配的设备编号,数值本身不代表设备属性,只要能正常通过API调用即可。
内容的提问来源于stack exchange,提问作者Damn Vegetables
相关产品推荐
相关产品推荐

