Показаны сообщения с ярлыком WinAPI. Показать все сообщения
Показаны сообщения с ярлыком WinAPI. Показать все сообщения

вторник, 7 июня 2011 г.

Получение букв дисков приаттаченых к USB девайсам (Enum drive letters attached to USB devices)

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;
 }