WinAPI-шная функция GetDriveType() имеет существенный недостаток - она определяет USB hard drive'ы как фиксированные диски DRIVE_FIXED. Недавно мне понадобился функционал, который бы отличал настоящие жесткие диски от USB. Как оказалось, задача почему-то решается нетривиально - либо через WMI, либо через SetupAPI. WMI не подходил всвязи со спецификой проекта, оставался SetupAPI. Полдня изучения основ SetupApi и полдня гугления, изучения экзэмплов и чтения форумов привели меня на CodeProject, где я и нашел решение. Так вот хочу я вам сказать, мои дорогие друзья, я бы в жизни не подумал, что эта задача решается настолько через жопу!
Но нашелся у меня в тиме человек, который буквально за полтора часа родил компактное и лаконичное решение. Собственно, не могу не поделится.
Но нашелся у меня в тиме человек, который буквально за полтора часа родил компактное и лаконичное решение. Собственно, не могу не поделится.
bool IsUsbDevice( wchar_t letter )
{
wchar_t volumeAccessPath[] = L"\\\\.\\X:";
volumeAccessPath[4] = letter;
HANDLE deviceHandle = CreateFileW(
volumeAccessPath,
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
// setup query
STORAGE_PROPERTY_QUERY query;
memset(&query, 0, sizeof(query));
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
// issue query
DWORD bytes;
STORAGE_DEVICE_DESCRIPTOR devd;
STORAGE_BUS_TYPE busType = BusTypeUnknown;
if (DeviceIoControl(deviceHandle,
IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(query),
&devd, sizeof(devd),
&bytes, NULL))
{
busType = devd.BusType;
}
else
{
std::wcout << L"Failed to define bus type for: " << letter;
}
CloseHandle(deviceHandle);
return BusTypeUsb == busType;
}
