比较来自世界各地的卖家的域名和 IT 服务价格

查找并提取设备 USB 基于它 VID/PID

我想向特定设备发送提取命令 USB, 由它识别 VID 和 PID. 我可以找到一个设备 SetupDiEnumDeviceInfo// 和 SetupDiGetDeviceRegistryProperty// 并比较数字 VID/PID 排队 HARDWAREID, 但这就是我所拥有的。

我有一个结构 SP_DEVINFO_DATA 和描述符 HDEVINFO. 如何将它们与磁盘的字母或卷相关联,以向他发送提取命令?
已邀请:

奔跑吧少年

赞同来自:

好吧,我猜。 文章 CodeProject, 由舱口盖引用显示如何将驱动器号与设备界面匹配,即在那里,所以我会的 +1 这个答案,但它没有解决整个问题。

我需要了解如何为我的设备找到设备的实例 USB 并找到一种与设备接口匹配的方法。 功能 CM_Locate_DevNode// 和 CM_Get_Child// 是这个关键。 最后,我可以使用 IOCTL 提取设备。

我正在处理的设备是CD-ROM驱动器 USB, 因此,我刚性地编码了设备的类型 CDROM. 我无法相信需要多少代码来做我的想法是一个非常简单的任务 /我引用了我的客户 2 一个小时才能写这个代码,我需要四天来了解这一切!/. 这是最终的工作代码,我希望,它将拯救你们一个人,因为我只是:


#include <setupapi.h>
#include <cfgmgr32.h>
#include <winioctl.h>

// Finds the device interface for the CDROM drive with the given interface number.
DEVINST GetDrivesDevInstByDeviceNumber/long DeviceNumber/
{
const GUID *guid = &amp;GUID_DEVINTERFACE_CDROM;

// Get device interface info set handle
// for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs/guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE/;
if/hDevInfo == INVALID_HANDLE_VALUE/
return 0;

// Retrieve a context structure for a device interface of a device information set.
BYTE buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = /PSP_DEVICE_INTERFACE_DETAIL_DATA/buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;

spdid.cbSize = sizeof/spdid/;

// Iterate through all the interfaces and try to match one based on
// the device number.
for/DWORD i = 0; SetupDiEnumDeviceInterfaces/hDevInfo, NULL,guid, i, &amp;spdid/; i++/
{
// Get the device path.
dwSize = 0;
SetupDiGetDeviceInterfaceDetail/hDevInfo, &amp;spdid, NULL, 0, &amp;dwSize, NULL/;
if/dwSize == 0 || dwSize &gt; sizeof/buf//
continue;

pspdidd-&gt;cbSize = sizeof/*pspdidd/;
ZeroMemory//PVOID/&amp;spdd, sizeof/spdd//;
spdd.cbSize = sizeof/spdd/;
if/!SetupDiGetDeviceInterfaceDetail/hDevInfo, &amp;spdid, pspdidd,
dwSize, &amp;dwSize, &amp;spdd//
continue;

// Open the device.
HANDLE hDrive = CreateFile/pspdidd-&gt;DevicePath,0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL/;
if/hDrive == INVALID_HANDLE_VALUE/
continue;

// Get the device number.
STORAGE_DEVICE_NUMBER sdn;
dwSize = 0;
if/DeviceIoControl/hDrive,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &amp;sdn, sizeof/sdn/,
&amp;dwSize, NULL//
{
// Does it match?
if/DeviceNumber == /long/sdn.DeviceNumber/
{
CloseHandle/hDrive/;
SetupDiDestroyDeviceInfoList/hDevInfo/;
return spdd.DevInst;
}
}
CloseHandle/hDrive/;
}

SetupDiDestroyDeviceInfoList/hDevInfo/;
return 0;
}


// Returns true if the given device instance belongs to the USB device with the given VID and PID.
bool matchDevInstToUsbDevice/DEVINST device, DWORD vid, DWORD pid/
{
// This is the string we will be searching for in the device harware IDs.
TCHAR hwid[64];
_stprintf/hwid, _T/"VID_X&amp;PID_X"/, vid, pid/;

// Get a list of hardware IDs for all USB devices.
ULONG ulLen;
CM_Get_Device_ID_List_Size/&amp;ulLen, NULL, CM_GETIDLIST_FILTER_NONE/;
TCHAR *pszBuffer = new TCHAR[ulLen];
CM_Get_Device_ID_List/NULL, pszBuffer, ulLen, CM_GETIDLIST_FILTER_NONE/;

// Iterate through the list looking for our ID.
for/LPTSTR pszDeviceID = pszBuffer; *pszDeviceID; pszDeviceID += _tcslen/pszDeviceID/ + 1/
{
// Some versions of Windows have the string in upper case and other versions have it
// in lower case so just make it all upper.
for/int i = 0; pszDeviceID[i]; i++/
pszDeviceID[i] = toupper/pszDeviceID[i]/;

if/_tcsstr/pszDeviceID, hwid//
{
// Found the device, now we want the grandchild device, which is the "generic volume"
DEVINST MSDInst = 0;
if/CR_SUCCESS == CM_Locate_DevNode/&amp;MSDInst, pszDeviceID, CM_LOCATE_DEVNODE_NORMAL//
{
DEVINST DiskDriveInst = 0;
if/CR_SUCCESS == CM_Get_Child/&amp;DiskDriveInst, MSDInst, 0//
{
// Now compare the grandchild node against the given device instance.
if/device == DiskDriveInst/
return true;
}
}
}
}

return false;
}

// Eject the given drive.
void ejectDrive/TCHAR driveletter/
{
TCHAR devicepath[16];
_tcscpy/devicepath, _T/"\\\\.\\?:"//;
devicepath[4] = driveletter;

DWORD dwRet = 0;
HANDLE hVol = CreateFile/devicepath, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL/;
if/hVol == INVALID_HANDLE_VALUE/
return;

if/!DeviceIoControl/hVol, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &amp;dwRet, 0//
return;

if/!DeviceIoControl/hVol, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &amp;dwRet, 0//
return;

DeviceIoControl/hVol, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &amp;dwRet, 0/;

CloseHandle/hVol/;
}

// Find a USB device by it's Vendor and Product IDs. When found, eject it.
void usbEjectDevice/unsigned vid, unsigned pid/
{
TCHAR devicepath[8];
_tcscpy/devicepath, _T/"\\\\.\\?:"//;

TCHAR drivepath[4];
_tcscpy/drivepath, _T/"?:\\"//;

// Iterate through every drive letter and check if it is our device.
for/TCHAR driveletter = _T/'A'/; driveletter &lt;= _T/'Z'/; driveletter++/
{
// We are only interested in CDROM drives.
drivepath[0] = driveletter;
if/DRIVE_CDROM != GetDriveType/drivepath//
continue;

// Get the "storage device number" for the current drive.
long DeviceNumber = -1;
devicepath[4] = driveletter;
HANDLE hVolume = CreateFile/devicepath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL/;
if/INVALID_HANDLE_VALUE == hVolume/
continue;

STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
if/DeviceIoControl/hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &amp;sdn, sizeof/sdn/, &amp;dwBytesReturned, NULL//
DeviceNumber = sdn.DeviceNumber;
CloseHandle/hVolume/;
if/DeviceNumber &lt; 0/
continue;

// Use the data we have collected so far on our drive to find a device instance.
DEVINST DevInst = GetDrivesDevInstByDeviceNumber/DeviceNumber/;

// If the device instance corresponds to the USB device we are looking for, eject it.
if/DevInst/
{
if/matchDevInstToUsbDevice/DevInst, vid, pid//
ejectDrive/driveletter/;
}
}
}


</winioctl.h></cfgmgr32.h></setupapi.h>

要回复问题请先登录注册