Differentiating between USB flash drive and USB hard drive on Windows
I'm trying to differentiate betwe开发者_运维问答en a USB flash drive and a USB hard drive on Windows using the Win32 API.
The GetDriveType() function will return DRIVE_REMOVABLE if the drive is removable, and USB flash drives are of course removable. But I'm thinking that Windows probably considers USB hard drives removable as well (unfortunately I don't have access to a USB hard drive to test it out).
Thanks in advance.
If you want to determine that a device is USB device, you can open its handle and send IOCTL queries using DeviceIoControl() to get bus type a device is connected to.
EnumUsbDrivesLetters - the post is in Russian but it contains C++ source code, so the matter could be understood easily.
Cheers, Andriy
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Method OpenVolume
// Purpose: Open volume for removal. Change to ::CreateFile(volumeName, 0, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
// if you just want to inquire if it's removable.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HANDLE OpenVolume(const char& driveLetter)
{
char volumeName[8] = "";
char* volumeFormat = "\\\\.\\%c:";
sprintf(volumeName, volumeFormat, driveLetter);
HANDLE volume = ::CreateFile(volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (volume == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
DWORD bytesReturned = 0;
STORAGE_HOTPLUG_INFO Info = {0};
if (::DeviceIoControl(volume, IOCTL_STORAGE_GET_HOTPLUG_INFO, 0, 0, &Info, sizeof(Info), &bytesReturned, NULL))
{
if (!(Info.MediaRemovable || Info.DeviceHotplug))
{
::CloseHandle(volume);
::SetLastError(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
}
return volume;
}
Actually windows doesn't, GetDriveType returns 3 (DRIVE_FIXED) for both my usb hard-drives.
Windows returns DRIVE_FIXED for external USB hard drives and usually returns DRIVE_REMOVABLE for USB flash sticks. For this reason if you want to access multiple partitions on a flash memory you have to install a filter driver to tell windows it's not a DRIVE_REMOVABLE but a DRIVE_FIXED instead. Windows only "sees" the first partition on flash sticks causing a lot of trouble for ESXi boot usb stick users ;-)
I thinks the key is drive properties, eg Cylinder count. You can use WMI interface to determine such information. Here is an example http://www.computerperformance.co.uk/vbscript/wmi_disks_physical.htm
The drive type is ultimately determined by the drivers; there's no fail-safe way to make the sort of determination that you're looking for.
I can say, however, that while I have seen a USB flash stick return DRIVE_FIXED
, I have never seen a normal hard drive return DRIVE_REMOVEABLE
. That's not to say that it's completely impossible for that to happen, but I've never seen it.
I'd say relying on those two values is probably the closest that you're going to get.
http://en.wikipedia.org/wiki/SCSI_Pass_Through_Interface will let you send raw SCSI commands to the device - you want to send down either INQUIRY or MODE SENSE to find out what you're looking for. However, a far better alternative may be the VDS APIs, if it will provide you correct information (I'm not sure whether it will in this case)
精彩评论