-
April 23rd, 2008, 08:26 AM
#1
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
Last edited by Namaste; April 23rd, 2008 at 08:31 AM.
-
April 23rd, 2008, 09:12 AM
#2
Re: Need help retrieving the drive letter upon mass storage arrival
-
April 23rd, 2008, 09:22 AM
#3
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
Last edited by Namaste; April 23rd, 2008 at 09:27 AM.
-
April 23rd, 2008, 10:11 AM
#4
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...
-
April 23rd, 2008, 10:50 AM
#5
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.
-
March 22nd, 2013, 04:36 PM
#6
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;
}
-
March 22nd, 2013, 04:53 PM
#7
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?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 25th, 2013, 04:33 AM
#8
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.
-
March 26th, 2013, 10:08 AM
#9
Re: Need help retrieving the drive letter uppon mass storage arrival
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!
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!)
Victor Nijegorodov
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|