Need help retrieving the drive letter upon mass storage arrival
Hi,
I'm writing a simple software that has to detect a new USB device insertion and basically retrieve a couple of informations from it before it really start working.
By using some MSDN references I could get the message for device arrival without major problems, however, I'm not being able to get the drive letter.
basically this is what I did:
1- Registered my software to receive device arrival/removal message for the desired type:
static const GUID GUID_DEVINTERFACE_USBSTOR =
{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
....
hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
....
then I created a ::OnMyDeviceChange(WPARAM wParam, LPARAM lParam) function to handle these notifications.
until here, everything is working fine.
I can get the enumeration information from a DEV_BROADCAST_DEVICEINTERFACE structure. However, according to the documentation, I would also need a DEV_BROADCAST_VOLUME structure to get the drive letter from, but seems that it's not available at the moment I get notified of a device arrival.
So I was wondering, what can I do to get the drive letter associated to that device arrival event?
Namaste
Re: Need help retrieving the drive letter upon mass storage arrival
Re: Need help retrieving the drive letter uppon mass storage arrival
This is the MSDN sample that I used and mentioned before.
however, I need two informations for a given enumeration and I'm not being able to get.
I need to get the dbcc_name from the DEV_BROADCAST_DEVICEINTERFACE and the dbcv_unitmask from the DEV_BROADCAST_VOLUME.
seens that I don't have both informations at the same time. first I get the DEVICEINTERFACE AND LATER THE BROADCAST_VOLUME.
I wanted to get both at the same time to make sure they both belongs to the same enumeration.
this is what I tried to do:
LRESULT CTFCPROGRAMMERDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
switch( pHdr->dbch_devicetype )
{
case DBT_DEVTYP_DEVICEINTERFACE:
{
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
break;
}
....
But it won't work, so I'm looking in a better way of doing this without having to receive two messages.
Since I will be connecting several devices to a computer, I want to make sure that I've all the information from the enumeration in one shot
Re: Need help retrieving the drive letter uppon mass storage arrival
Code:
if(msg == WM_DEVICECHANGE && wParam == DBT_DEVICEARRIVAL)
{
PDEV_BROADCAST_DEVICEINTERFACE pData = reinterpret_cast<PDEV_BROADCAST_DEVICEINTERFACE>(lParam);
if(pData->dbcc_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME pVolume = reinterpret_cast<PDEV_BROADCAST_VOLUME>(lParam);
//Extract letter from pVolume->dbcv_unitmask...
}
}
Just wrote a small test; seemed to work with my USB key...
Re: Need help retrieving the drive letter uppon mass storage arrival
I've just tried your code here and the same thing happened.
It can successfully retrieve the drive letter, but the dbcc_name is not holding the correct value.
did you check your pData.dbcc_name?
Mine have "HÈA".
It was supposed to have:
"\\?\USB#Vid_05e3&Pid_0712#000000009225#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"
these are the info that I'm looking for
this string + the drive letter.
Re: Need help retrieving the drive letter uppon mass storage arrival
#include "stdafx.h"
#include "windows.h"
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
bool GetDriveLetterForDeviceInterface( TCHAR *InterfaceName, UCHAR *Letter ) {
HANDLE MountMgr = INVALID_HANDLE_VALUE;
HANDLE Interface = INVALID_HANDLE_VALUE;
MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetter;
ULONG DeviceNameLength = sizeof( MOUNTMGR_DRIVE_LETTER_TARGET ) + 128;
void* DeviceName = NULL;
DWORD BytesReturned;
bool Result = false;
MountMgr = CreateFile(
MOUNTMGR_DOS_DEVICE_NAME,
FILE_READ_ACCESS | FILE_WRITE_ACCESS,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( MountMgr == INVALID_HANDLE_VALUE )
goto Exit;
Interface = CreateFile(
InterfaceName,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( Interface == INVALID_HANDLE_VALUE )
goto Exit;
while ( true ) {
if ( DeviceName )
free( DeviceName );
DeviceName = malloc( DeviceNameLength );
if ( !DeviceName )
goto Exit;
Result = DeviceIoControl(
Interface,
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
NULL,
0,
DeviceName,
DeviceNameLength,
&BytesReturned,
NULL
) ? true : false;
if ( Result )
break;
if ( GetLastError() == ERROR_MORE_DATA ||
GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
GetLastError() == ERROR_BUFFER_OVERFLOW ) {
DeviceNameLength *= 2;
continue;
}
goto Exit;
}
Result = DeviceIoControl(
MountMgr,
IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
DeviceName,
DeviceNameLength,
&DriveLetter,
sizeof(DriveLetter),
&BytesReturned,
NULL
) ? true : false;
if ( !Result )
goto Exit;
*Letter = DriveLetter.CurrentDriveLetter;
*Letter &= ~0x20;
Result = true;
Exit:
if ( DeviceName )
free( DeviceName );
if ( Interface != INVALID_HANDLE_VALUE )
CloseHandle( Interface );
if ( MountMgr != INVALID_HANDLE_VALUE )
CloseHandle( MountMgr );
return Result;
}
int _tmain(int argc, _TCHAR* argv[]) {
UCHAR Letter;
bool Result = false;
Result = GetDriveLetterForDeviceInterface(
TEXT("\\\\.\\STORAGE#Volume#{8871b640-813c-11e1-a7c5-806e6f6e6963}#0000000006500000#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}"),
&Letter
);
return 0;
}
Re: Need help retrieving the drive letter uppon mass storage arrival
If you are going to post code to a 5 year old thread, at least follow the etiquette of this forum and correctly format the code and enclose within [code] tags.
Your code does what exactly? And why have you posted it without any comment or explanation?
Re: Need help retrieving the drive letter uppon mass storage arrival
I beg your pardon.
Code:
#include "stdafx.h"
#include "windows.h"
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
bool GetDriveLetterForDeviceInterface( TCHAR *InterfaceName, UCHAR *Letter ) {
HANDLE MountMgr = INVALID_HANDLE_VALUE;
HANDLE Interface = INVALID_HANDLE_VALUE;
MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetter;
ULONG DeviceNameLength = sizeof( MOUNTMGR_DRIVE_LETTER_TARGET ) + 128;
void* DeviceName = NULL;
DWORD BytesReturned;
bool Result = false;
MountMgr = CreateFile(
MOUNTMGR_DOS_DEVICE_NAME,
FILE_READ_ACCESS | FILE_WRITE_ACCESS,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( MountMgr == INVALID_HANDLE_VALUE )
goto Exit;
Interface = CreateFile(
InterfaceName,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if ( Interface == INVALID_HANDLE_VALUE )
goto Exit;
while ( true ) {
if ( DeviceName )
free( DeviceName );
DeviceName = malloc( DeviceNameLength );
if ( !DeviceName )
goto Exit;
Result = DeviceIoControl(
Interface,
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
NULL,
0,
DeviceName,
DeviceNameLength,
&BytesReturned,
NULL
) ? true : false;
if ( Result )
break;
if ( GetLastError() == ERROR_MORE_DATA ||
GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
GetLastError() == ERROR_BUFFER_OVERFLOW ) {
DeviceNameLength *= 2;
continue;
}
goto Exit;
}
Result = DeviceIoControl(
MountMgr,
IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
DeviceName,
DeviceNameLength,
&DriveLetter,
sizeof(DriveLetter),
&BytesReturned,
NULL
) ? true : false;
if ( !Result )
goto Exit;
*Letter = DriveLetter.CurrentDriveLetter;
*Letter &= ~0x20;
Result = true;
Exit:
if ( DeviceName )
free( DeviceName );
if ( Interface != INVALID_HANDLE_VALUE )
CloseHandle( Interface );
if ( MountMgr != INVALID_HANDLE_VALUE )
CloseHandle( MountMgr );
return Result;
}
int _tmain(int argc, _TCHAR* argv[]) {
UCHAR Letter;
bool Result = false;
Result = GetDriveLetterForDeviceInterface(
TEXT("\\\\.\\STORAGE#Volume#{8871b640-813c-11e1-a7c5-806e6f6e6963}#0000000006500000#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}"),
&Letter
);
return 0;
}
This is an example how to obtain drive letter by interface name cantained in structures like DEV_BROADCAST_DEVICEINTERFACE. It's especially useful in services due to services don't retreive DEV_BROADCAST_VOLUME notification. The GetDriveLetterForDeviceInterface function takes two parameters, interface name and a pointer to UCHAR variable which contains the result. The function returns true if it could determine the letter successfully or false otherwise. UCHAR variable contains 0(if the drive has no a letter) or corresponding drive letter.
About 5 years, i think it doesn't matter because you can still meet enough posts like this.
Re: Need help retrieving the drive letter uppon mass storage arrival
Quote:
Originally Posted by
anatolymik
I beg your pardon.
Code:
#include "stdafx.h"
#include "windows.h"
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
bool GetDriveLetterForDeviceInterface( TCHAR *InterfaceName, UCHAR *Letter ) {
...
}
Your code is still unformatted! Note that any code enclosed within Code tages must be initially formatted with the proper indentations!
Quote:
Originally Posted by
anatolymik
This is an example how to obtain drive letter by interface name cantained in structures like DEV_BROADCAST_DEVICEINTERFACE. It's especially useful in services due to services don't retreive DEV_BROADCAST_VOLUME notification. The GetDriveLetterForDeviceInterface function takes two parameters, interface name and a pointer to UCHAR variable which contains the result. The function returns true if it could determine the letter successfully or false otherwise. UCHAR variable contains 0(if the drive has no a letter) or corresponding drive letter.
About 5 years, i think it doesn't matter because you can still meet enough posts like this.
Then you should have better submit it as an article or a tip (with some comments and explanations, of course!)