Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to enumerate USB Mass Storage devices?

311 views
Skip to first unread message

Wan-Hi

unread,
May 27, 2005, 5:43:02 AM5/27/05
to
hello.

i'm working on a hobby project for my own mp3 (usb mass storage) player and
try to enumerate all usb mass storage devices currently connected to my
computer. i've been working on this quite a while because i can't get through
the msdn efficiently enough. i planned to identify my player like this:

1) enumerate all disks (by SetupDiEnumDeviceInterfaces in conjunction with
guid GUID_DEVINTERFACE_DISK)
2) find out those who are mass storage devices
(IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
3) get each mass storage device's partition info
4) get a handle to the volume

i chose the method above because i wanted to avoid a low level enumeration
through the usb hubs. now i'm stuck with step 2 because i don't know how to
find out the correct buffer size, needed by DeviceIoControl for the
IOCTL_STORAGE_GET_MEDIA_TYPES_EX flag. the documentation didn't explain a
proper use any further. so i wonder if any veteran can give me a hint, how to
find out the buffer size.

thanks.

wan-hi

Robert Marquardt

unread,
May 27, 2005, 7:10:01 AM5/27/05
to
Wan-Hi wrote:
> hello.
>
> i'm working on a hobby project for my own mp3 (usb mass storage) player and
> try to enumerate all usb mass storage devices currently connected to my
> computer. i've been working on this quite a while because i can't get through
> the msdn efficiently enough. i planned to identify my player like this:
>
> 1) enumerate all disks (by SetupDiEnumDeviceInterfaces in conjunction with
> guid GUID_DEVINTERFACE_DISK)
> 2) find out those who are mass storage devices
> (IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
> 3) get each mass storage device's partition info
> 4) get a handle to the volume

Enumerate the volumes (GUID_DEVINTERFACE_VOLUME),
SetupDiGetDeviceInterfaceDetail gives you the DevInst. Call
CM_Get_Parent twice to get the grandparent DevInst, call
CM_Get_Device_ID and analyze the string returned. If it starts with
"USB\" then it is a USB stick.
This is also the DevInst to call CM_Request_Device_Eject on for safe
removal of the stick.

For additional tricks get the "SymbolicName" via CM_Open_DevNode_Key and
RegQueryValueEx. The returned string contains VID, PID and SerialNumber
to identify a stick individually.

The USBVIEW way of getting the info directly from the device is a bit
disruptive and may cause spurious surprise removal dialogs.

Wan-Hi

unread,
May 29, 2005, 5:59:48 AM5/29/05
to
Thank you very much. That helped a lot.

I noticed that the ConfigManager functions you mention are obsolete and no
longer documented. I looked up the declarations in the header file, but they
are hardly described. Therefore I used SetupDiGetDeviceRegistryProperty in
conjunction with the parent's and grandparent's SP_DEVINFO_DATA.
Unfortunately this function doesn't accept self-constructed SP_DEVINFO_DATA
structs, although I set the right DEVINST and class GUID, so I had to
enumerate them separately.

I wonder how to close the bridge between the Device Installation functions
and the Volume Management functions. When enumerating all devices that expose
GUID_DEVINTERFACE_VOLUME the path value in each
SP_DEVICE_INTERFACE_DETAIL_DATA begins with STORAGE instead of VOLUME. So I
can't use the path value to retrieve the mount points of a specific volume.
Why is that so? I can create a file with that value, but can't use it for
querying mount points? I tried to go over the Removable Storage Manager by
using GetVolumesFromDrive, but that didn't work either.

Robert Marquardt

unread,
May 29, 2005, 6:23:16 AM5/29/05
to
Wan-Hi wrote:

> I wonder how to close the bridge between the Device Installation functions
> and the Volume Management functions. When enumerating all devices that expose
> GUID_DEVINTERFACE_VOLUME the path value in each
> SP_DEVICE_INTERFACE_DETAIL_DATA begins with STORAGE instead of VOLUME. So I
> can't use the path value to retrieve the mount points of a specific volume.
> Why is that so? I can create a file with that value, but can't use it for
> querying mount points? I tried to go over the Removable Storage Manager by
> using GetVolumesFromDrive, but that didn't work either.

Feed the original DevicePath you got from
SetupDiGetDeviceInterfaceDetail to GetVolumeNameForVolumeMountPoint.
The only thing to do it to add a trailing backslath to the DevicePath first.
If you want to match to drive letters then feed "A:\\" through "Z:\\" to
GetVolumeNameForVolumeMountPoint and see if the result matches the above
result.

The main drawback is that the Volume Mount Point API is XP only.

Pavel A.

unread,
May 29, 2005, 8:53:12 AM5/29/05
to
"Robert Marquardt" wrote:
> Feed the original DevicePath you got from
> SetupDiGetDeviceInterfaceDetail to GetVolumeNameForVolumeMountPoint.
> The only thing to do it to add a trailing backslath to the DevicePath first.
> If you want to match to drive letters then feed "A:\\" through "Z:\\" to
> GetVolumeNameForVolumeMountPoint and see if the result matches the above
> result.
>
> The main drawback is that the Volume Mount Point API is XP only.

From the MSDN - GetVolumeNameForVolumeMountPoint, GetVolumePathName exist
also in Win2k. GetVolumePathNamesForVolumeName exists from XP up.

Regards,
--PA

Wan-Hi

unread,
May 29, 2005, 8:15:12 PM5/29/05
to
unfortunately it does not. this is the output N:\ is the same device as the
one i enumerated in the volume device info set. the values are different.

could the mount manager IOCTL codes help me?

N:\ is mount point for: \\?\Volume{ad0dea5a-a3a8-11d9-9fbc-00110928c06d}\
WE LOOKED FOR
\\?\storage#removablemedia#7&1cbd9276&0&rm#{53f5630d-b6bf-11d0-94f
2-00a0c91efb8b}

0 new messages