Всем привет, пишу программу, которая при включении смотрит подключенные съемные USB устройства хранения. И в результате, список устройств с именами я получаю (использую SetupApi) и кроме флэшек я, также, нахожу еще два картридера (которые пустые), как программно отличить пустой картридер от флэшки? Самый банальный путь я знаю - попробовать считать или записать что-то, но он мне не нравится. Наверняка должно быть более красивое решение.
Что бы не плодить дополнительных тем... В общем я написал сканер устройств и который проверяет, что это накопитель, и что его можно извлечь, но работает все очень странно... Моя флэшка определяется как не извлекаемое устройство, да и картридеры определяются один как извлекаемый, а второй нет. Написал вот такую большую функцию Код (C): bool FindConnectedRemovableUsbstorDevices(std::list<std::wstring>& UsbList) { std::wstring ClassGuidString(L"{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"); GUID ClassGuid; BYTE buf[1024]; PSP_DEVICE_INTERFACE_DETAIL_DATA_W pspdidd = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buf); SP_DEVICE_INTERFACE_DATA spdid; SP_DEVINFO_DATA spdd; DWORD size; SP_DEVINFO_DATA dev_data; DWORD properties; if(NOERROR != CLSIDFromString(ClassGuidString.c_str(), &ClassGuid)) return false; HDEVINFO dev_info = INVALID_HANDLE_VALUE; dev_info = SetupDiGetClassDevs(&ClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) return false; DWORD index = 0; BOOL ret = FALSE; spdid.cbSize = sizeof(spdid); while (true) { ret = SetupDiEnumDeviceInterfaces(dev_info, NULL, &ClassGuid, index, &spdid); if (!ret) break; size = 0; SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, NULL, 0, &size, NULL); //Get required size if (size == 0 || size >= sizeof(buf)) continue; //prepare structs ZeroMemory(reinterpret_cast<PVOID>(pspdidd), 1024); pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes! ZeroMemory(reinterpret_cast<PVOID>(&spdd), sizeof(spdd)); spdd.cbSize = sizeof(spdd); BOOL res = SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, pspdidd, size, &size, &spdd); //Get info if (!res) continue; HANDLE drive = CreateFileW(pspdidd->DevicePath, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);//open device if (drive == INVALID_HANDLE_VALUE) continue; printf("\n%S\r\n", pspdidd->DevicePath); DWORD bytes_returned = 0; BOOL b = DeviceIoControl(drive, IOCTL_STORAGE_CHECK_VERIFY2, NULL, 0, NULL, 0, &bytes_returned, NULL); if (!b) //check is card reader? { printf("IOCTL_STORAGE_CHECK_VERIFY2 error = %d\r\n", GetLastError()); goto stop_process_device; } bytes_returned = 0; STORAGE_DEVICE_NUMBER sdn; //Get Drive number b = DeviceIoControl(drive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL); if (!b) goto stop_process_device; RtlZeroMemory(&dev_data, sizeof(SP_DEVINFO_DATA)); dev_data.cbSize = sizeof(dev_data); if (SetupDiEnumDeviceInfo(dev_info, sdn.DeviceNumber, &dev_data)) { //check property b = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_REMOVAL_POLICY, NULL, reinterpret_cast<PBYTE>(&properties), sizeof(properties), NULL); if (b && properties != CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL) { UsbList.push_back(pspdidd->DevicePath); printf("REMOVAL\r\n"); } } stop_process_device: CloseHandle(drive); index++; } SetupDiDestroyDeviceInfoList(dev_info); return true; } И вот такой вывод она дает Мне кажется я фундаментально чего то не понимаю, и прошу подсказать, в чем я косячнул...
GetDriveType для подобных имен возвращает DRIVE_NO_ROOT_DIR. Мне подсказали правильный способ обработать накопители. Надо вызвать DeviceIoControl с параметром IOCTL_STORAGE_QUERY_PROPERTY и посмотреть StorageDeviceProperty, в вернувшемся буфере смотреть параметр STORAGE_DEVICE_DESCRIPTOR.RemovableMedia. Так все распознаклось корректно