Получить тип диска с помощью SetupDiGetDeviceRegistryProperty - PullRequest
0 голосов
/ 07 июня 2010

Я хотел бы знать, могу ли я получить информацию о диске, используя

SP_DEVICE_INTERFACE_DETAIL_DATA's DevicePath

путь к моему устройству выглядит следующим образом

"\? \ USB # vid_04f2 & pid_0111 # 5 & 39fe81e & 0 & 2 # {a5dcbf10-6530-11d2-901f-00c04fb951ed}"

также, пожалуйста, сообщите мне в winapi, что они говорят: «Чтобы определить, является ли диск USB-накопителем, вызовите SetupDiGetDeviceRegistryProperty и укажите свойство SPDRP_REMOVAL_POLICY."

Я тоже использую SetupDiGetDeviceRegistryProperty, как показано ниже

while ( !SetupDiGetDeviceRegistryProperty( hDevInfo,&DeviceInfoData,
    SPDRP_REMOVAL_POLICY,&DataT,( PBYTE )buffer,buffersize,&buffersize ))

но я не знаю, как я могу получить тип привода, используя вышеуказанное ..

Пожалуйста, помогите мне встать

Ответы [ 3 ]

4 голосов
/ 27 марта 2013

Я создал метод GetMountedVolumes с необязательной маской, чтобы указать, какие типы томов должны быть включены в поиск (читаемые, записываемые, удаляемые, с возможностью горячей замены, стираемые).

Я вообще воздержался от методов настройки API и использовал только дескриптор тома нулевого доступа для вызовов DeviceIoControl (никаких административных привилегий не требуется). Я поделюсь своим кодом, может быть, это поможет другим реализовать методы определения типа диска (тома) без использования Setup API.

enum VolumesFlags {
    VolumeReadable = 1,
    VolumeWriteable = 2,
    VolumeEraseable = 4,
    VolumeRemoveable = 8,
    VolumeHotplugable = 16,
    VolumeMounted = 128
};

bool GetMountedVolumes(std::vector<std::wstring> &Volumes,
    unsigned int Flags = VolumeReadable | VolumeWriteable,
    unsigned int Mask = VolumeReadable | VolumeWriteable) {

    wchar_t Volume[MAX_PATH] = {0};
    wchar_t* VolumeEndPtr = Volume;

    Flags |= VolumeMounted;
    Mask |= VolumeMounted;
    Flags &= Mask;

    HANDLE hFind = FindFirstVolume(Volume, sizeof(Volume) / sizeof(wchar_t));
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            bool IsMatching = false;
            VolumeEndPtr = &Volume[wcslen(Volume) - 1];
            *VolumeEndPtr = L'\0';

            HANDLE hDevice = CreateFile(Volume, 0, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
            if (hDevice != INVALID_HANDLE_VALUE) {

                unsigned int CurrentFlags = 0;

                DWORD ReturnedSize;
                STORAGE_HOTPLUG_INFO Info = {0};

                if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_HOTPLUG_INFO, 0, 0, &Info, sizeof(Info), &ReturnedSize, NULL)) {
                    if (Info.MediaRemovable) {
                        CurrentFlags |= VolumeRemoveable;
                    }
                    if (Info.DeviceHotplug) {
                        CurrentFlags |= VolumeHotplugable;
                    }
                }

                DWORD MediaTypeSize = sizeof(GET_MEDIA_TYPES);
                GET_MEDIA_TYPES* MediaType = (GET_MEDIA_TYPES*) new char[MediaTypeSize];

                while (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_MEDIA_TYPES_EX, 0, 0, MediaType, MediaTypeSize, &ReturnedSize, NULL) == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                    delete [] (char*) MediaType;
                    MediaTypeSize *= 2;
                    MediaType = (GET_MEDIA_TYPES*) new char[MediaTypeSize];
                }

                if (MediaType->MediaInfoCount > 0) {
                    DWORD Characteristics = 0;
                    // Supports: Disk, CD, DVD
                    if (MediaType->DeviceType == FILE_DEVICE_DISK || MediaType->DeviceType == FILE_DEVICE_CD_ROM || MediaType->DeviceType == FILE_DEVICE_DVD) {
                        if (Info.MediaRemovable) {
                            Characteristics = MediaType->MediaInfo[0].DeviceSpecific.RemovableDiskInfo.MediaCharacteristics;
                        } else {
                            Characteristics = MediaType->MediaInfo[0].DeviceSpecific.DiskInfo.MediaCharacteristics;
                        }

                        if (Characteristics & MEDIA_CURRENTLY_MOUNTED) {
                            CurrentFlags |= VolumeMounted;
                        }
                        if (Characteristics & (MEDIA_READ_ONLY | MEDIA_READ_WRITE)) {
                            CurrentFlags |= VolumeReadable;
                        }
                        if (((Characteristics & MEDIA_READ_WRITE) != 0 || (Characteristics & MEDIA_WRITE_ONCE) != 0) && (Characteristics & MEDIA_WRITE_PROTECTED) == 0 && (Characteristics & MEDIA_READ_ONLY) == 0) {
                            CurrentFlags |= VolumeWriteable;
                        }
                        if (Characteristics & MEDIA_ERASEABLE) {
                            CurrentFlags |= VolumeEraseable;
                        }
                    }
                }

                delete [] (char*) MediaType;

                CloseHandle(hDevice);

                CurrentFlags &= Mask;

                if (CurrentFlags == Flags) {
                    *VolumeEndPtr = L'\\';                  
                    wchar_t VolumePaths[MAX_PATH] = {0};
                    if (GetVolumePathNamesForVolumeName(Volume, VolumePaths, MAX_PATH, &ReturnedSize)) {
                        if (*VolumePaths) {
                            Volumes.push_back(VolumePaths);
                        }
                    }
                }

            }
        } while (FindNextVolume(hFind, Volume, sizeof(Volume) / sizeof(wchar_t)));
        FindVolumeClose(hFind);
    }

    return Volumes.size() > 0;
}
2 голосов
/ 08 июня 2010

Вероятно, то, что вы ищете, вы найдете здесь http://support.microsoft.com/kb/264203/en. Другая ссылка http://support.microsoft.com/kb/305184/en может быть вам интересна.

ОБНОВЛЕНО : пример из http://support.microsoft.com/kb/264203/en показывает, как использовать, чтобы определить, является ли USB-накопитель съемным. Вы также можете использовать SetupDiGetDeviceRegistryProperty с SPDRP_REMOVAL_POLICY на экземпляре устройства (используйте SetupDiEnumDeviceInfo, SetupDiGetDeviceInstanceId и затем SetupDiGetDeviceRegistryProperty). Если возвращено DWORD имеет CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL или CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL в качестве значения, диск является съемным.

Кроме того, в примере кода показано, как открыть дескриптор устройства, который можно использовать с функцией DeviceIoControl, чтобы получить много полезной информации, которая может вам понадобиться. IOCTL_STORAGE_QUERY_PROPERTY (см. http://msdn.microsoft.com/en-us/library/ff566997%28v=VS.85%29.aspx) с разными QueryType и PropertyId только одним примером. Например, вы можете использовать IOCTL_STORAGE_GET_DEVICE_NUMBER для получения томов хранилища и номера их дисков.

Если у вас будет полная STORAGE_DEVICE_NUMBER информация о вашем USB-устройстве, мы сможем найти всю другую информацию о нем различными способами. Один из самых простых: просто перечислить все буквы дисков с помощью QueryDosDevice и запросить STORAGE_DEVICE_NUMBER для каждого диска. Если вы найдете полное совпадение в STORAGE_DEVICE_NUMBER, вы найдете букву диска.

0 голосов
/ 17 мая 2017

Учитывая ваш Storage Device Path:

  • Откройте устройство, используя CreateFile
  • используйте DeviceIOControl для выдачи IOCTL_STORAGE_QUERY_PROPERTY
  • это заполняет STORAGE_DEVICE_DESCRIPTOR структура
  • с перечислением STORAGE_BUS_TYPE:

    STORAGE_DEVICE_DESCRIPTOR {
      DWORD            Version;
      DWORD            Size;
      BYTE             DeviceType;
      BYTE             DeviceTypeModifier;
      BOOLEAN          RemovableMedia;
      BOOLEAN          CommandQueueing;
      DWORD            VendorIdOffset;
      DWORD            ProductIdOffset;
      DWORD            ProductRevisionOffset;
      DWORD            SerialNumberOffset;
      STORAGE_BUS_TYPE BusType;         //<---------------
      DWORD            RawPropertiesLength;
      BYTE             RawDeviceProperties[1];
    

    }

Различные шины для хранения типов:

  • BusTypeScsi : SCSI
  • BusTypeAtapi : ATAPI
  • BusTypeAta : ATA
  • BusType1394 : IEEE-1394
  • BusTypeSsa : SSA
  • BusTypeFibre : Fibre Channel
  • BusTypeUsb : USB
  • BusTypeRAID : RAID
  • BusTypeiSCSI : iSCSI
  • BusTypeSas : последовательный интерфейс SCSI (SAS)
  • BusTypeSata : SATA

Так пример псевдо-кода

STORAGE_BUS_TYPE GetStorageDeviceBusType(String StorageDevicePath)
{
   /*
   Given a storage device path of

      \?\usb#vid_04f2&pid_0111#5&39fe81e&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

   return its StorageBusType, e.g.:

      BusTypeUsb
   */

   //Open the disk for reading (must be an administrator)
   HANDLE diskHandle = CreateFile(StorageDevicePath, 
         GENERIC_READ,                        //desired access
         FILE_SHARE_READ | FILE_SHARE_WRITE,  //share mode
         null,                                //security attributes
         OPEN_EXISTING,                       //creation disposition
         FILE_ATTRIBUTE_NORMAL,               //flags and attributes
         0);           
   if (diskHandle == INVALID_HANDLE_VALUE)
      RaiseLastWin32Error();

   try
   {
      BOOL res;
      DWORD bytesReturned;

      //Set up what we want to query from the drive
      STORAGE_PROPERTY_QUERY query= {};
      query.QueryType = PropertyStandardQuery;
      query.PropertyID = StorageDeviceProperty;

      DWORD bufferSize;

      // Query for the header to get the required buffer size
      STORAGE_DESCRIPTOR_HEADER header;
      res = DeviceIoControl(diskHandle, IOCTL_STORAGE_QUERY_PROPERTY,
            ref query, sizeof(STORAGE_PROPERTY_QUERY),
            ref header, sizeof(STORAGE_DESCRIPTOR_HEADER),
            out bytesReturned, null);
      if (!res) RaiseLastWin32Error();
      bufferSize = header.Size;

      //Allocate the buffer and query for the full property
      STORAGE_DEVICE_DESCRIPTOR *deviceDescriptor = GetMem(bufferSize);
      try
      {
         //Issue IOCTL_STORAGE_QUERY_PROPERTY to get STORAGE_DEVICE_DESCRIPTOR
         res = DeviceIoControl(diskHandle, IOCTL_STORAGE_QUERY_PROPERTY,
                    @query, sizeof(STORAGE_PROPERTY_QUERY),
                    deviceDescriptor, bufferSize,
                    out bytesReturned, null));
         if (!res) 
            RaiseLastWin32Error();

         return deviceDescriptor.BusType;
      }
      finally
      {
         FreeMem(deviceDescriptor);
      }
   }
   finally
   {  
      CloseHandle(diskHandle);
   }       

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...