枚举所有设备路径
Enumerate all device paths
我正在尝试获取所有具有设备接口的设备的路径,但是当我调用 SetupDiEnumDeviceInterfaces
时,我得到 ERROR_NO_MORE_ITEMS
.
#include <windows.h>
#include <setupapi.h>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, const char **argv)
{
HDEVINFO hdevinfo = SetupDiGetClassDevs(0, 0, 0, DIGCF_ALLCLASSES |
DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
if (hdevinfo == INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to get device information set" << std::endl;
return -1;
}
SP_DEVINFO_DATA devinfoData{sizeof(SP_DEVINFO_DATA)};
SP_DEVICE_INTERFACE_DATA deviceInterfaceData{sizeof(SP_DEVICE_INTERFACE_DATA)};
std::vector<std::string> devicePaths{};
devicePaths.reserve(512);
DWORD index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, &devinfoData))
{
if (!SetupDiEnumDeviceInterfaces(hdevinfo, &devinfoData, &devinfoData.ClassGuid, index, &deviceInterfaceData))
{
DWORD error = GetLastError();
std::cout << "Error: " << error << std::endl; // always get 259
++index;
continue;
}
DWORD reqSize = 0;
SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, 0, 0, &reqSize, 0);
PSP_INTERFACE_DEVICE_DETAIL_DATA pDetailData = PSP_INTERFACE_DEVICE_DETAIL_DATA(new char[reqSize]);
pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, pDetailData, reqSize, 0, 0));
devicePaths.push_back(pDetailData->DevicePath);
delete [] pDetailData;
++index;
}
SetupDiDestroyDeviceInfoList(hdevinfo);
return 0;
}
我已经研究过 this answer,但它对我不起作用,因为它使用 GUID 用于 USB 设备。在我的例子中,所需的设备不仅可以通过 USB 连接,还可以通过 PCI 和 PCI express 连接。
我需要在 CreateFile
中使用这些路径。
我采取了不适当的方法吗?有其他选择吗?
我们可以检索设备列表 instance IDs for the local computer's device instances with CM_Get_Device_ID_ListW
函数
为每个 ID 获取设备的设备实例句柄
然后使用 CM_Get_DevNode_PropertyW
. for example DEVPKEY_NAME
and DEVPKEY_Device_PDOName
- name of the physical device object (PDO). this name we can use inside NtOpenFile
检索设备实例 属性
volatile UCHAR guz = 0;
void ProcessList(PZZWSTR pDeviceID)
{
ULONG cb = 0, rcb = 0x80;
CONFIGRET cr;
PVOID stack = alloca(guz);
union {
PVOID buf;
PBYTE PropertyBuffer;
};
HANDLE hFile;
IO_STATUS_BLOCK iosb;
UNICODE_STRING ObjectName;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
do
{
DEVINST dnDevInst;
if (CM_Locate_DevNodeW(&dnDevInst, pDeviceID, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS)
{
DbgPrint("\n%S:\t", pDeviceID);
DEVPROPTYPE PropertyType;
static const DEVPROPKEY PropertyKeys[] = { DEVPKEY_Device_PDOName, DEVPKEY_NAME };
static const PCSTR Names[] = { "PDOName", "FriendlyName" };
ULONG i = _countof(PropertyKeys);
do
{
const DEVPROPKEY* PropertyKey = &PropertyKeys[--i];
PCSTR Name = Names[i];
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
cr = CM_Get_DevNode_PropertyW(dnDevInst, PropertyKey,
&PropertyType, PropertyBuffer, &(rcb = cb), 0);
if (cr == CR_SUCCESS && PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("[%s=%S]\t", Name, PropertyBuffer);
if (!i)
{
RtlInitUnicodeString(&ObjectName, (PWSTR)PropertyBuffer);
NTSTATUS status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0);
if (0 <= status)
{
NtClose(hFile);
}
DbgPrint("=%x", status);
}
}
} while (cr == CR_BUFFER_SMALL);
} while (i);
}
} while (*(pDeviceID += wcslen(pDeviceID) + 1));
}
void cccm()
{
CONFIGRET cr;
PZZWSTR pDeviceID;
ULONG ulLen;
do
{
if (CM_Get_Device_ID_List_SizeW(&ulLen, 0, CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS || ulLen <= 1)
{
break;
}
if (pDeviceID = new WCHAR[ulLen])
{
if ((cr = CM_Get_Device_ID_ListW(0, pDeviceID, ulLen, CM_GETIDLIST_FILTER_PRESENT)) == CR_SUCCESS)
{
if (*pDeviceID) ProcessList(pDeviceID);
}
delete [] pDeviceID;
}
else
{
break;
}
} while (cr == CR_BUFFER_SMALL);
}
我正在尝试获取所有具有设备接口的设备的路径,但是当我调用 SetupDiEnumDeviceInterfaces
时,我得到 ERROR_NO_MORE_ITEMS
.
#include <windows.h>
#include <setupapi.h>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, const char **argv)
{
HDEVINFO hdevinfo = SetupDiGetClassDevs(0, 0, 0, DIGCF_ALLCLASSES |
DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
if (hdevinfo == INVALID_HANDLE_VALUE)
{
std::cerr << "Failed to get device information set" << std::endl;
return -1;
}
SP_DEVINFO_DATA devinfoData{sizeof(SP_DEVINFO_DATA)};
SP_DEVICE_INTERFACE_DATA deviceInterfaceData{sizeof(SP_DEVICE_INTERFACE_DATA)};
std::vector<std::string> devicePaths{};
devicePaths.reserve(512);
DWORD index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, &devinfoData))
{
if (!SetupDiEnumDeviceInterfaces(hdevinfo, &devinfoData, &devinfoData.ClassGuid, index, &deviceInterfaceData))
{
DWORD error = GetLastError();
std::cout << "Error: " << error << std::endl; // always get 259
++index;
continue;
}
DWORD reqSize = 0;
SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, 0, 0, &reqSize, 0);
PSP_INTERFACE_DEVICE_DETAIL_DATA pDetailData = PSP_INTERFACE_DEVICE_DETAIL_DATA(new char[reqSize]);
pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &deviceInterfaceData, pDetailData, reqSize, 0, 0));
devicePaths.push_back(pDetailData->DevicePath);
delete [] pDetailData;
++index;
}
SetupDiDestroyDeviceInfoList(hdevinfo);
return 0;
}
我已经研究过 this answer,但它对我不起作用,因为它使用 GUID 用于 USB 设备。在我的例子中,所需的设备不仅可以通过 USB 连接,还可以通过 PCI 和 PCI express 连接。
我需要在 CreateFile
中使用这些路径。
我采取了不适当的方法吗?有其他选择吗?
我们可以检索设备列表 instance IDs for the local computer's device instances with CM_Get_Device_ID_ListW
函数
然后使用 CM_Get_DevNode_PropertyW
. for example DEVPKEY_NAME
and DEVPKEY_Device_PDOName
- name of the physical device object (PDO). this name we can use inside NtOpenFile
volatile UCHAR guz = 0;
void ProcessList(PZZWSTR pDeviceID)
{
ULONG cb = 0, rcb = 0x80;
CONFIGRET cr;
PVOID stack = alloca(guz);
union {
PVOID buf;
PBYTE PropertyBuffer;
};
HANDLE hFile;
IO_STATUS_BLOCK iosb;
UNICODE_STRING ObjectName;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
do
{
DEVINST dnDevInst;
if (CM_Locate_DevNodeW(&dnDevInst, pDeviceID, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS)
{
DbgPrint("\n%S:\t", pDeviceID);
DEVPROPTYPE PropertyType;
static const DEVPROPKEY PropertyKeys[] = { DEVPKEY_Device_PDOName, DEVPKEY_NAME };
static const PCSTR Names[] = { "PDOName", "FriendlyName" };
ULONG i = _countof(PropertyKeys);
do
{
const DEVPROPKEY* PropertyKey = &PropertyKeys[--i];
PCSTR Name = Names[i];
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
cr = CM_Get_DevNode_PropertyW(dnDevInst, PropertyKey,
&PropertyType, PropertyBuffer, &(rcb = cb), 0);
if (cr == CR_SUCCESS && PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("[%s=%S]\t", Name, PropertyBuffer);
if (!i)
{
RtlInitUnicodeString(&ObjectName, (PWSTR)PropertyBuffer);
NTSTATUS status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0);
if (0 <= status)
{
NtClose(hFile);
}
DbgPrint("=%x", status);
}
}
} while (cr == CR_BUFFER_SMALL);
} while (i);
}
} while (*(pDeviceID += wcslen(pDeviceID) + 1));
}
void cccm()
{
CONFIGRET cr;
PZZWSTR pDeviceID;
ULONG ulLen;
do
{
if (CM_Get_Device_ID_List_SizeW(&ulLen, 0, CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS || ulLen <= 1)
{
break;
}
if (pDeviceID = new WCHAR[ulLen])
{
if ((cr = CM_Get_Device_ID_ListW(0, pDeviceID, ulLen, CM_GETIDLIST_FILTER_PRESENT)) == CR_SUCCESS)
{
if (*pDeviceID) ProcessList(pDeviceID);
}
delete [] pDeviceID;
}
else
{
break;
}
} while (cr == CR_BUFFER_SMALL);
}