Need help retrieving the drive letter uppon mass storage arrival
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9

Thread: Need help retrieving the drive letter uppon mass storage arrival

  1. #1
    Join Date
    Apr 2008
    Posts
    6

    Post 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.

  2. #2
    Join Date
    Jun 2006
    Location
    M31
    Posts
    885

    Re: Need help retrieving the drive letter upon mass storage arrival

    MSDN sample. =\

  3. #3
    Join Date
    Apr 2008
    Posts
    6

    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.

  4. #4
    Join Date
    Jun 2006
    Location
    M31
    Posts
    885

    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...

  5. #5
    Join Date
    Apr 2008
    Posts
    6

    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 "HA".

    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.

  6. #6
    Join Date
    Mar 2013
    Posts
    2

    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;

    }

  7. #7
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,266

    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. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  8. #8
    Join Date
    Mar 2013
    Posts
    2

    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.

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,300

    Re: Need help retrieving the drive letter uppon mass storage arrival

    Quote Originally Posted by anatolymik View Post
    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 View Post
    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
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center