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

Get USB Mass storage drive letter from Windows Service

940 views
Skip to first unread message

StuartNorris

unread,
Oct 19, 2008, 12:44:01 AM10/19/08
to
Hi List

I have written a service that detects the insertion of USB mass storage
devices.

In the callback for the DBT_DEVICEARRIVAL I have the device interface name
(for example)

pDevInf->dbcc_name:

\\?\USB#Vid_04e8&Pid_503b#00024444444E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

From the dbcc_name how do I determine the drive letter on the system that
this interface corresponds to?

I have had a look at the Setupapi.lib, however I am just going around in
circles and I cannot determine which call based on the information that I
have corresponds to my drive(s).

The drive I am testing with presents as two devices a CDROM and USB Storage
device in Windows.

Thanks

Stuart

Kerem Gümrükcü

unread,
Oct 19, 2008, 3:28:35 AM10/19/08
to
Hi Stuard,

you should have a look at this:

[HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices]

The Binar Data holds the DeviceID String, so you could
compare it against the IDs you get,...

This is found on my Windows XP System, I dont
know if this is available on Vista, or even 2000,...
Someone confirm please,...

Regards

Kerem

--
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
Latest Project: http://www.codeplex.com/restarts
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------
"This reply is provided as is, without warranty express or implied."
"StuartNorris" <Stuart...@discussions.microsoft.com> schrieb im
Newsbeitrag news:7C2E25E0-3375-4A05...@microsoft.com...

Maxim S. Shatskih

unread,
Oct 19, 2008, 12:22:42 PM10/19/08
to
> [HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices]
>
> The Binar Data holds the DeviceID String, so you could
> compare it against the IDs you get,...
>
> This is found on my Windows XP System, I dont
> know if this is available on Vista, or even 2000,...

Yes, MountedDevices is since w2k.

--
Maxim S. Shatskih
Windows DDK MVP
ma...@storagecraft.com
http://www.storagecraft.com


Kerem Gümrükcü

unread,
Oct 19, 2008, 4:28:28 PM10/19/08
to
Hi Maxim,

> Yes, MountedDevices is since w2k.

still the same Registry Hive in Vista based OS?


Regards

Kerem

--
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
Latest Project: http://www.codeplex.com/restarts
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------
"This reply is provided as is, without warranty express or implied."

"Maxim S. Shatskih" <ma...@storagecraft.com.no.spam> schrieb im Newsbeitrag
news:e74mtbgM...@TK2MSFTNGP05.phx.gbl...

Ben Voigt [C++ MVP]

unread,
Oct 20, 2008, 9:36:47 AM10/20/08
to
StuartNorris wrote:
> Hi List
>
> I have written a service that detects the insertion of USB mass
> storage devices.
>
> In the callback for the DBT_DEVICEARRIVAL I have the device interface
> name (for example)
>
> pDevInf->dbcc_name:
>
> \\?\USB#Vid_04e8&Pid_503b#00024444444E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
>
> From the dbcc_name how do I determine the drive letter on the system
> that this interface corresponds to?

Don't you also get the DBT_DEVTYP_VOLUME notification? That has the drive
letter in the event data.

Maxim S. Shatskih

unread,
Oct 21, 2008, 5:09:08 AM10/21/08
to
>> Yes, MountedDevices is since w2k.
>
> still the same Registry Hive in Vista based OS?

Yes

Kerem Gümrükcü

unread,
Oct 21, 2008, 5:44:24 AM10/21/08
to
> Yes

Good!

--
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
Latest Project: http://www.codeplex.com/restarts
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------
"This reply is provided as is, without warranty express or implied."
"Maxim S. Shatskih" <ma...@storagecraft.com.no.spam> schrieb im Newsbeitrag

news:%231uPuy1...@TK2MSFTNGP06.phx.gbl...

Uwe Sieber

unread,
Oct 22, 2008, 4:47:04 AM10/22/08
to

StuartNorris wrote:
> Hi List
>
> I have written a service that detects the insertion of USB mass storage
> devices.
>
> In the callback for the DBT_DEVICEARRIVAL I have the device interface name
> (for example)
>
> pDevInf->dbcc_name:
>
> \\?\USB#Vid_04e8&Pid_503b#00024444444E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
>
> From the dbcc_name how do I determine the drive letter on the system that
> this interface corresponds to?


When you get the notification for the USB device, the drive and
volume are not yet present.
If registered, you get notifications for DISK/CDROM/FLOPPY and
VOLUME too. When you get the volume notification, you have the
volume's DevicePath in db_di->dbcc_name.
Still undocumented but essential:
You can call GetVolumeNameForVolumeMountPoint with the DevicePath
(add a trailing backslash) instead of a mountpoint to get the
volume's VolumeName.
Under XP+ you can use GetVolumePathNamesForVolumeName to get
the mountpoints for a volumename. But it is not 100% reliable
for NTFS moutpoints when called while processing the volume
notification.
Under W2K you have to scan manually...

Each volume is related to a disk, cdrom or floppy device and
their parent device is the USB device.
The link between them and their volume(s) is their DeviceNumber.
I've explained this link here:
http://www.codeproject.com/system/RemoveDriveByLetter.asp

Under XP+ have a look at the drive's and volume's install state.
On first time arrivals it will be 3 (CM_INSTALL_STATE_FINISH_INSTALL)
and you will see the horrible come, go and come again game.
If you open a handle when the install state is 3 then the
go and come will fail an Windows ask for a restart...
And again, under W2K you have to write an install state emulation
to avoid this of wait a moment to see if the device goes and comes
back.
For testing first time arrivals you can use my DriveCleanup
tool which removes non present USB drives from the registry.
http://www.uwe-sieber.de/files/drivecleanup.zip


Greetings from Germany

Uwe

Uwe Sieber

unread,
Oct 22, 2008, 4:51:55 AM10/22/08
to
Ben Voigt [C++ MVP] wrote:
> StuartNorris wrote:
>> Hi List
>>
>> I have written a service that detects the insertion of USB mass
>> storage devices.
>>
>> In the callback for the DBT_DEVICEARRIVAL I have the device interface
>> name (for example)
>>
>> pDevInf->dbcc_name:
>>
>> \\?\USB#Vid_04e8&Pid_503b#00024444444E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
>>
>> From the dbcc_name how do I determine the drive letter on the system
>> that this interface corresponds to?
>
> Don't you also get the DBT_DEVTYP_VOLUME notification? That has the drive
> letter in the event data.

Using DBT_DEVTYP_VOLUME in a service is trick since it is a basic
broadcast notification which are sent to top level windows only.
If a service creates a Windows to receive this, it works only if
the service is running in the same session as the logged on user.
So, it will never work under Vista and under XP only for the first
logged on user.


Greetings from Germany

Uwe

Uwe Sieber

unread,
Oct 22, 2008, 4:59:49 AM10/22/08
to
Kerem Gümrükcü wrote:
> Hi Stuard,
>
> you should have a look at this:
>
> [HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices]
>
> The Binar Data holds the DeviceID String, so you could
> compare it against the IDs you get,...


From the DevicePath of the volume found there and the
DevicePath of the USB device which Stuart has, there
is a quite long way. And there is no need to deal
with the registry directly.


Uwe

Maxim S. Shatskih

unread,
Oct 22, 2008, 5:29:32 AM10/22/08
to
> Using DBT_DEVTYP_VOLUME in a service is trick since it is a basic
> broadcast notification which are sent to top level windows only.

PnP notifications can be SC-handle-targeted, not only HWND-targeted.

Maxim S. Shatskih

unread,
Oct 22, 2008, 5:28:49 AM10/22/08
to
>> [HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices]
>>
>> The Binar Data holds the DeviceID String

No.

The binary data holds the "mountdev ID", which is the driver's response to
IOCTL_MOUNTDEV_QUERY_ID sent from MountMgr. This is the value with which the
drive letter is associated - MountMgr is just the maintainer of this
association and of its persistence (MountedDevices registry).

For removable disk drives (where "removable" bit is on in INQUIRY data),
including CD/DVD/BD drives - Disk/ClassPnP really returns the PnP ID as a
mountdev ID.

In this _only_ case, Kerem is correct. Generally, he is not correct.

For instance, for a plain (non-DynDisk) partition on non-removable disk, the
mountdev ID is 12 bytes - 4 bytes MBR signature, 8 bytes partition offset.
No PnP IDs in it at all.

Uwe Sieber

unread,
Oct 22, 2008, 6:24:15 AM10/22/08
to
Maxim S. Shatskih wrote:
>> Using DBT_DEVTYP_VOLUME in a service is trick since it is a basic
>> broadcast notification which are sent to top level windows only.
>
> PnP notifications can be SC-handle-targeted, not only HWND-targeted.

Yes, but DBT_DEVTYP_VOLUME isn't a PnP notification. It's what
MSDN calls "basic notification". There is no way to receive
this in a HandlerEx of a service.


Uwe

Matthew Fanto

unread,
Oct 22, 2008, 12:08:06 PM10/22/08
to


Thank you again for your off-list advice. Perhaps I have a fundamental
misunderstanding (it wouldn't be the first time :)), but let me see if
I can succinctly sum up everything. It's possible that I am misreading
your post below.

In the email you sent, you said to register for
GUID_DEVINTERFACE_VOLUME. I registered for both
GUID_DEVINTERFACE_VOLUME, and GUID_DEVINTERFACE_USB_DEVICE.

NotificationFilter.dbcc_classguid = GuidDevInterfaceList[i];
HDEVNOTIFY hDeviceNotify = RegisterDeviceNotification(hStatus,
&NotificationFilter,
DEVICE_NOTIFY_SERVICE_HANDLE);


(this is in a for loop to register for the multiple class guids).

In my HandlerEx routine, I see the following event twice, once for
each of the guid's I have registered.

pData->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE


I never see the following:
pData->dbcc_devicetype == DBT_DEVTYP_VOLUME.


This is because DBT_DEVTYP_VOLUME is a basic notification, not a PnP
event, and thus only top level windows will receive it?

I use dbcc_devicename and get the following 2 names:
Name: \\?
\USB#VID_0781&PID_5204#20052444601B13B07C59#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Name: \\?
\USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Crossfire&Rev_2.0#20052444601B13B07C59&0#{53f56307-
b6bf-11d0-94f2-00a0c91efb8b}


Using GetVolumeNameForVolumeMountPoint() on either one of these (with
trailing \ appended) results in failure with error 123 (volume name
invalid). Do I have this backwards and instead should enumerate
through all the available volumes, follow the path up to the device,
and then compare to it's dbcc_devicename?

I just want to make sure that your comment "There is no way to receive
this in a HandlerEx of a service. " does not also mean that there is
no way to get volume information in a service.

Thank you and sorry for the continuing questions. There is a lot of
conflicting advice I've read, so I am trying to make sense of it.

Best,
Matt

Ben Voigt [C++ MVP]

unread,
Oct 22, 2008, 12:16:21 PM10/22/08
to

I know that RegisterDeviceNotification docs say:

NotificationFilter ... value of the dbch_devicetype member, which can be
DBT_DEVTYP_DEVICEINTERFACE or DBT_DEVTYP_HANDLE

Has anyone tried passing DBT_DEVTYP_VOLUME? The docs don't promise it will
work, but don't say it can't.

>
>
> Uwe


Uwe Sieber

unread,
Oct 22, 2008, 3:45:48 PM10/22/08
to


Yes, this variant does not exist.

> This is because DBT_DEVTYP_VOLUME is a basic notification, not a PnP
> event, and thus only top level windows will receive it?

Yes.

> I use dbcc_devicename and get the following 2 names:
> Name: \\?
> \USB#VID_0781&PID_5204#20052444601B13B07C59#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
> Name: \\?

An USB device because you have registered for
GUID_DEVINTERFACE_USB_DEVICE.


> \USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Crossfire&Rev_2.0#20052444601B13B07C59&0#{53f56307-
> b6bf-11d0-94f2-00a0c91efb8b}

A disk device. You must been registered for
GUID_DEVINTERFACE_DISK.

> Using GetVolumeNameForVolumeMountPoint() on either one of these (with
> trailing \ appended) results in failure with error 123 (volume name
> invalid).

This works for a device path of a volume, which you get when
registered for GUID_DEVINTERFACE_VOLUME.
When you receive WM_DEVICECHANGE with wParam==DBT_DEVICEARRIVAL,
check db_di->dbcc_classguid for the right GUID like this:
if ( IsEqual_GUID(GUID_DEVINTERFACE_VOLUME, db_di->dbcc_classguid) ) {

> Do I have this backwards and instead should enumerate
> through all the available volumes, follow the path up to the device,
> and then compare to it's dbcc_devicename?

Enumerating all volumes is the right choice when your service is started
while Windows is running and the device you are intersted in is already
attached. When the service is running, dealing with the BT_DEVICEARRIVAL
notification is the right choice.

> I just want to make sure that your comment "There is no way to receive
> this in a HandlerEx of a service. " does not also mean that there is
> no way to get volume information in a service.

You can get WM_DEVICECHANGE with wParam==DBT_DEVICEARRIVAL and
di->dbcc_classguid==GUID_DEVINTERFACE_VOLUME and collect all
needed information. But DBT_DEVTYP_VOLUME with the drive letter
is indeed for toplevel windows in the session of the currently
logged on user only.


Greetings from Germany

Uwe

Uwe Sieber

unread,
Oct 22, 2008, 3:51:17 PM10/22/08
to
Ben Voigt [C++ MVP] wrote:


Yes, it hardly tried to get DBT_DEVTYP_VOLUME in my service
and there seems to be no way. Finally I asked in
micosoft.public.win32.programmer.kernel:
http://groups.google.de/group/microsoft.public.win32.programmer.kernel/browse_frm/thread/98eec239d67d4500

Uwe

StuartNorris

unread,
Oct 29, 2008, 6:36:01 AM10/29/08
to
Hi Uwe,

> You can get WM_DEVICECHANGE with wParam==DBT_DEVICEARRIVAL and
> di->dbcc_classguid==GUID_DEVINTERFACE_VOLUME and collect all
> needed information.

What do you mean by collect all needed information.

Is the information I need to get the driver letter already there?

I am still trying to get this to work so an pointers would be much
appreciated. I prefer not to try to use the registry to match the
information.

Thanks

Stuart

Uwe Sieber

unread,
Oct 29, 2008, 7:59:06 AM10/29/08
to

I've answered this quite detailed in this thread:
Date: Wed, 22 Oct 2008 10:47:04 +0200

0 new messages