Differentiating between USB flash drive and USB hard drive on Windows
Asked Answered
H

7

7

I'm trying to differentiate between 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.

Hartebeest answered 2/8, 2010 at 18:56 Comment(2)
Just out of curiosity, why do you want to do this? Are you going to do something different depending on what type of drive it is? As others have said, the DriveType is not very consistent (though it is probably "good enough").Boyt
macOS equivalent of this same problemHenrion
M
3

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

Maddis answered 10/6, 2011 at 7:28 Comment(2)
Please do not copy-paste answers over a number of questions, linking to your own blogspot. This will be considered spamming.Balanced
The answer was useful. In case the link ever goes down, the tldr is querying IOCTL_STORAGE_QUERY_PROPERTY and looking for BusType == BusTypeUsb. Using this, along with the hot plug info from Marty, gave the best coverage.Matriculate
C
3
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  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;
}
Clayberg answered 6/10, 2014 at 15:6 Comment(0)
P
2

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

Pentane answered 22/11, 2010 at 17:21 Comment(0)
M
1

Actually windows doesn't, GetDriveType returns 3 (DRIVE_FIXED) for both my usb hard-drives.

Monopetalous answered 2/8, 2010 at 19:4 Comment(2)
No kidding, thanks. And your USB hard drives are run-of-the-mill, and there are no special driver settings or anything like that that might cause Windows to consider them DRIVE_FIXED instead of DRIVE_REMOVABLE?Hartebeest
They're just standard western digital drives and my windows installation is pretty fresh so nothing on the driver front has changed from the default settings.Monopetalous
G
1

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

Gapeworm answered 10/6, 2011 at 7:57 Comment(0)
P
0

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.

Pella answered 2/8, 2010 at 19:12 Comment(2)
Interesting you say you've seen a flash stick return DRIVE_FIXED, as I found this a few minutes before reading your comment: social.msdn.microsoft.com/forums/en-US/…Hartebeest
It's not ultimately determined by the drivers, because the drivers determine it based on what the device reports back, which isn't always consistent.Hailstorm
H
0

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)

Hailstorm answered 22/11, 2010 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.