Goal: Get USB drive letter upon insertion.

Done so far:
Detection of drive.

-------------------------------------------------------------

Im using the method of RegisterDeviceNotification()

WM_DEVICECHANGE // Received message
                |
DBT_DEVICEARRIVAL // Received Message
                |
DEV_BROADCAST_HDR // Pointer from lParam
                |
PDEV_BROADCAST_VOLUME //Pointer from  DEV_BROADCAST_HDR Pointer

When getting the index drive letter from dbcv_unitmask.
It works for DVD ( obviously ) but returns a -1 for USBs.

So I was going to try going though all possible drives, then check for the latest plugged in.

WIN32_FILE_ATTRIBUTE_DATA ad;
SYSTEMTIME Time;


GetFileAttributesEx(  "L:\\", GetFileExInfoStandard, &ad );


FileTimeToSystemTime( &ad.ftCreationTime, &Time );

But it only has time for creation time, access time, write time.
Not being inserted.

Is there a better method to get a USB's drive letter the moment it is plugged in, I don't need a example code. Just some API names if possible.

Dani AI

Generated

A common reason DBT_DEVICEARRIVAL gives a usable drive-letter mask for DVDs but not for USB sticks is that the arrival you receive isn’t always a volume notification. Optical media often triggers a DBT_DEVTYP_VOLUME message (so dbcv_unitmask is valid), while many USB mass‑storage devices arrive as a device‑interface notification. If you cast every arrival to a volume structure you’ll get nonsense (often -1). Check the header’s dbch_devicetype before casting.

Prefer registering for the volume interface class and map the volume GUID to mount points. The workflow that tends to be reliable is: handle the WM_DEVICECHANGE arrival, test dbch_devicetype, and when you get a device‑interface/volume GUID (the dbcc_name string) call the volume‑to‑mount API to obtain drive letters. Minimal pseudocode:

hdr = (PDEV_BROADCAST_HDR)lParam
if (hdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
  // valid dbcv_unitmask -> compute letter(s)
}
else if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
  // dbcc_name contains a volume GUID path like \\?\Volume{...}\
  // call GetVolumePathNamesForVolumeName(volumeGuid, ...) to get drive letters
}

If you prefer the simplest fallback, the before/after enumeration (GetLogicalDriveStrings / GetDriveType) that used is pragmatic and often sufficient. Other options: use SetupAPI (SetupDi* / SetupDiGetDeviceInterfaceDetail) for richer device metadata, or subscribe to WMI volume events if you need timestamps. Note that filesystem timestamps (creation/access/write) do not record "insertion time"—record the time when you detect the event instead.

Troubleshooting checklist: verify dbch_devicetype before casting; ensure you registered for the volume interface (not only the USB device class); allow a small retry/delay because mounting can finish after the initial notification; handle multi‑partition drives and mount points; and remember some devices present as "fixed" vs "removable" which affects behavior. ’s MSDN pointer and ’s CodeProject roundup have useful examples if you need sample code.

Recommended Answers

All 4 Replies

I made a before and after enumeration using GetDriveType().

Thanks anyways tho.

Regards,

Gen

If your program is a regular GUI application, then you might consider using the code from Detecting Media Insertion or Removal. I.e. not involving RegisterDeviceNotification() at all.

If your program is a regular GUI application, then you might consider using the code from Detecting Media Insertion or Removal. I.e. not involving RegisterDeviceNotification() at all.

I am already using those messages.

It does not properly give the index for any USB removable devices.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.