Get drive type with SetupDiGetDeviceRegistryProperty

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

I would like to know whether i can get the drive information using the

SP_DEVICE_INTERFACE_DETAIL_DATA's DevicePath

my device path looks like below

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

also please tell me in the winapi they say "To determine whether a drive is a USB-type drive, call SetupDiGetDeviceRegistryProperty and specify the SPDRP_REMOVAL_POLICY property."

i too use SetupDiGetDeviceRegistryProperty like below

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

but i dont know how can i get the drive type using the above..

Please help me up

回答1:

Probably what you are looking for you will be find here http://support.microsoft.com/kb/264203/en. Another link http://support.microsoft.com/kb/305184/en can be also interesting for you.

UPDATED: Example from http://support.microsoft.com/kb/264203/en shows you how to use to determine whether USB-Drive is removable. You can also use SetupDiGetDeviceRegistryProperty with SPDRP_REMOVAL_POLICY on the device instance (use SetupDiEnumDeviceInfo, SetupDiGetDeviceInstanceId and then SetupDiGetDeviceRegistryProperty). If returned DWORD has CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL or CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL as value, the drive is removable.

Moreover the code example show how to open device handle which you can use with DeviceIoControl function to retrieve a lot of useful information which you can need. IOCTL_STORAGE_QUERY_PROPERTY (see http://msdn.microsoft.com/en-us/library/ff566997%28v=VS.85%29.aspx) with different QueryType and PropertyId only one example. You can use IOCTL_STORAGE_GET_DEVICE_NUMBER for example to receive storage volumes and their disk number.

If you will have full STORAGE_DEVICE_NUMBER information about your USB device we will be able to find all other information about it with different ways. One of the easiest is: just enumerate all drive letters with QueryDosDevice and query STORAGE_DEVICE_NUMBER for every drive. If you will find full match in STORAGE_DEVICE_NUMBER you will find the drive letter.



回答2:

I've created a GetMountedVolumes method with optional mask to specify what type of volumes should be included in the search (readable, writeable, removeable, hotplugable, eraseable).

I abstained from Setup API methods at all and only used null access volume handle for DeviceIoControl calls (no administrative privileges are required). I will share my code, may be this will help others to implement methods to determine drive (volume) type without using Setup API.

enum VolumesFlags {     VolumeReadable = 1,     VolumeWriteable = 2,     VolumeEraseable = 4,     VolumeRemoveable = 8,     VolumeHotplugable = 16,     VolumeMounted = 128 };  bool GetMountedVolumes(std::vector<: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; } 


回答3:

Given your Storage Device Path:

  • Open the device using CreateFile
  • use DeviceIOControl to issue IOCTL_STORAGE_QUERY_PROPERTY
  • this populates STORAGE_DEVICE_DESCRIPTOR structure
  • which has a STORAGE_BUS_TYPE enumeration:

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

    }

The different storage bus types are

  • BusTypeScsi: SCSI
  • BusTypeAtapi: ATAPI
  • BusTypeAta: ATA
  • BusType1394: IEEE-1394
  • BusTypeSsa: SSA
  • BusTypeFibre: Fiber Channel
  • BusTypeUsb: USB
  • BusTypeRAID: RAID
  • BusTypeiSCSI: iSCSI
  • BusTypeSas: Serial Attached SCSI (SAS)
  • BusTypeSata: SATA

So example psueudo-code

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!