Моя цель — написать c-dll (скомпилированную с помощью MinGW), которая способна искать определенные модели USB-накопителей, подключенных к компьютеру, и выдавать серийный номер, идентификатор поставщика, идентификатор продукта и букву диска. Я искал в Интернете несколько часов, но не смог найти подход, который работает для меня.
Я использую Setup Api, чтобы получить список всех подключенных USB-устройств. Для каждого USB-устройства я получаю путь, который выглядит следующим образом: \?\usb#vid_048d&pid_1172#00000020370220#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Из этой строки я могу получить идентификатор поставщика, идентификатор продукта и серийный номер, который мне нужен.
Теперь моя проблема заключается в том, чтобы определить букву диска USB-накопителя, связанного с этим путем к устройству. Во время моего интернет-исследования я несколько раз находил следующий подход (например, здесь http://oroboro.com/usb-serial-number/): как только путь к устройству найден, USB-накопитель должен быть открыт CreateFile
. Дескриптор, возвращаемый этой функцией, можно использовать для получения номера устройства функцией DeviceIOControl
с IOCTL_STORAGE_GET_DEVICE_NUMBER
. После этого можно использовать функцию CreateFile
, чтобы открыть каждую букву диска (начиная с a:) и попытаться получить номер устройства так же, как описано выше. Как только тот же номер устройства будет найден снова, устанавливается связь между путем к устройству и буквой диска.
Моя проблема в том, что вызов IOCTL_STORAGE_GET_DEVICE_NUMBER
не работает. Функция DeviceIOControl
возвращает код ошибки 50, что означает «Запрос не поддерживается».
Я не могу создать связь между путем устройства USB-накопителя и буквой диска. Я пробовал несколько вызовов IOCTL_STORAGE and IOCTL_VOLUME
, но ни один из них не работал для USB-накопителей, которые я пробовал. Я также читал на другом форуме, что у людей были проблемы с результатами функции DeviceIOControl
. На одних компьютерах он возвращал желаемый результат, а на других создавал проблемы. Есть ли другой способ достичь моей цели?
Я уже заглянул в реестр, где тоже могу найти нужные данные. Но снова у меня возникла проблема с созданием связи между путем к устройству и буквой диска. Я не хотел бы использовать WMI. Я читал, что он до сих пор не поддерживается MinGW. У меня есть реализация для всего этого на C#, где очень легко получить нужную информацию, но теперь мне также нужен тот, который создан с неуправляемым кодом и может использоваться для замены c-dll, также включенного в проекты Delphi.
Буду признателен за любые предложения по решению моей проблемы.
С уважением, Флориан
А вот код, если кому интересно. Позиция с таким комментарием "//ВОТ ГДЕ Я ХОЧУ ПОЛУЧИТЬ НОМЕР УСТРОЙСТВА!!!" где запрос номера устройства будет использоваться, если он будет работать.
typedef struct ty_TUSB_Device
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData;
char devicePath[300];
}TUSB_Device;
int
GetUSBDevices (TUSB_Device *devList[], int size)
{
HANDLE hHCDev;
HDEVINFO deviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInfoData;
ULONG index;
ULONG requiredLength;
int devCount = 0;
//SP_DEVINFO_DATA DevInfoData;
// Now iterate over host controllers using the new GUID based interface
//
deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
if (deviceInfo != INVALID_HANDLE_VALUE)
{
deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (index=0;
SetupDiEnumDeviceInterfaces(deviceInfo,
0,
(LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,
index,
&deviceInfoData);
index++)
{
SetupDiGetDeviceInterfaceDetail(deviceInfo,
&deviceInfoData,
NULL,
0,
&requiredLength,
NULL);
//allocate memory for pointer to TUSB_Device structure
devList[devCount] = malloc(sizeof(TUSB_Device));
devList[devCount]->deviceDetailData = GlobalAlloc(GPTR, requiredLength);
devList[devCount]->deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(deviceInfo,
&deviceInfoData,
devList[devCount]->deviceDetailData,
requiredLength,
&requiredLength,
NULL);
//open the usb device
hHCDev = CreateFile(devList[devCount]->deviceDetailData->DevicePath,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
// If the handle is valid, then we've successfully found a usb device
//
if (hHCDev != INVALID_HANDLE_VALUE)
{
strncpy(devList[devCount]->devicePath, devList[devCount]->deviceDetailData->DevicePath, sizeof(devList[devCount]->devicePath));
//HERE IS WHERE I WOULD LIKE TO GET THE DEVICE NUMBER!!!
CloseHandle(hHCDev);
devCount++;
}
//GlobalFree(devList[devCount]->deviceDetailData);
}
SetupDiDestroyDeviceInfoList(deviceInfo);
}
return devCount;
}