2

I am not able to know how to use the IOCTL_MOUNTMGR_QUERY_POINTS .

I have searched the internet and found some sample code to try with.

but i am not sure whether its correct or not....

can you please let me know how to use the IOCTL_MOUNTMGR_QUERY_POINTS to get the drive letter

Thank you for your time

below is my source coode

HANDLE hUsbDevice = CreateFile( pDetData->DevicePath,  
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);

UCHAR Bytes[10000];
PMOUNTMGR_MOUNT_POINTS pMntPoints = (PMOUNTMGR_MOUNT_POINTS) Bytes;
MOUNTMGR_MOUNT_POINT mntPoint, *pmnt;
DWORD bytesReturned;
if (hUsbDevice == INVALID_HANDLE_VALUE) {
    qDebug()<<"CreateFile failed with error: %d\n"<<GetLastError();
}
else {
   qDebug ()<<"VALID DEVICE";
   BOOL status = DeviceIoControl( hUsbDevice, 
      IOCTL_MOUNTMGR_QUERY_POINTS,
      &mntPoint,
      sizeof(MOUNTMGR_MOUNT_POINT),
      pMntPoints,
      10000,
      &bytesReturned,
      NULL);

    wprintf(L"\tBOOL VALUE : %d\n", status);
    qDebug ()<<pMntPoints->MountPoints;
}
user198725878
  • 6,266
  • 18
  • 77
  • 135
  • 3
    I personally do not know how to use `IOCTL_MOUNTMGR_QUERY_POINTS`, but I'm sure that adding a lot of empty lines is not the way to go. – avakar Jun 10 '10 at 08:37
  • 1
    When posting here, do not use ALL CAPS in the question title, and do minimise vertical whitespace. I have edited your code with this in mind, this time only! –  Jun 10 '10 at 08:41

1 Answers1

5

OK! Here is a code example, but written without any error control to make it shorter:

#include <windows.h>
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
#include <tchar.h>
#include <stdio.h>

#pragma comment(lib, "Crypt32.lib")

int main()
{
    TCHAR chDrive = 'N', szUniqueId[128];
    TCHAR szDeviceName[7] = _T("\\\\.\\");
    HANDLE hDevice, hMountMgr; 
    BYTE byBuffer[1024];
    PMOUNTDEV_NAME pMountDevName;
    DWORD cbBytesReturned, dwInBuffer, dwOutBuffer, ccb;
    PMOUNTMGR_MOUNT_POINT pMountPoint;
    BOOL bSuccess;
    PBYTE pbyInBuffer, pbyOutBuffer;
    LPTSTR pszLogicalDrives, pszDriveRoot;

    // MOUNTMGR_DOS_DEVICE_NAME is defined as L"\\\\.\\MountPointManager"
    hMountMgr = CreateFile (MOUNTMGR_DOS_DEVICE_NAME,
                            0, FILE_SHARE_READ | FILE_SHARE_WRITE,
                            NULL, OPEN_EXISTING, 0, NULL);
    if (hMountMgr == INVALID_HANDLE_VALUE)
        return 1;

    cbBytesReturned = GetLogicalDriveStrings (0, NULL);
    pszLogicalDrives = (LPTSTR) LocalAlloc (LMEM_ZEROINIT,
                                            cbBytesReturned*sizeof(TCHAR));
    cbBytesReturned = GetLogicalDriveStrings (cbBytesReturned,
                                                pszLogicalDrives);
    for (pszDriveRoot = pszLogicalDrives; *pszDriveRoot != TEXT('\0');
            pszDriveRoot += lstrlen(pszDriveRoot) + 1) {

        szDeviceName[4] = pszDriveRoot[0];
        szDeviceName[5] = _T(':');
        szDeviceName[6] = _T('\0');
        //lstrcpy (&szDeviceName[4], TEXT("\\??\\USBSTOR\\DISK&VEN_SANDISK&PROD_CRUZER&REV_8.01\\1740030578903736&0"));

        hDevice = CreateFile (szDeviceName, 0,
                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                NULL, OPEN_EXISTING, 0, NULL);
        if (hDevice == INVALID_HANDLE_VALUE)
            return 1;

        bSuccess = DeviceIoControl (hDevice,
                                    IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 
                                    NULL, 0,
                                    (LPVOID)byBuffer, sizeof(byBuffer),
                                    &cbBytesReturned,
                                    (LPOVERLAPPED) NULL);
        pMountDevName = (PMOUNTDEV_NAME) byBuffer;
        _tprintf (TEXT("\n%.*ls\n"), pMountDevName->NameLength/sizeof(WCHAR),
                                        pMountDevName->Name);
        bSuccess = CloseHandle (hDevice);

        dwInBuffer = pMountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
        pbyInBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwInBuffer);
        pMountPoint = (PMOUNTMGR_MOUNT_POINT) pbyInBuffer;
        pMountPoint->DeviceNameLength = pMountDevName->NameLength;
        pMountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
        CopyMemory (pbyInBuffer + sizeof(MOUNTMGR_MOUNT_POINT),
                    pMountDevName->Name, pMountDevName->NameLength);

        dwOutBuffer = 1024 + sizeof(MOUNTMGR_MOUNT_POINTS);
        pbyOutBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwOutBuffer);
        bSuccess = DeviceIoControl (hMountMgr,
                                    IOCTL_MOUNTMGR_QUERY_POINTS, 
                                    pbyInBuffer, dwInBuffer,
                                    (LPVOID)pbyOutBuffer, dwOutBuffer,
                                    &cbBytesReturned,
                                    (LPOVERLAPPED) NULL);
        if (bSuccess) {
            ULONG i;
            PMOUNTMGR_MOUNT_POINTS pMountPoints = (PMOUNTMGR_MOUNT_POINTS) pbyOutBuffer;
            for (i=0; i<pMountPoints->NumberOfMountPoints; i++) {
                _tprintf (TEXT("#%i:\n"), i);
                _tprintf (TEXT("    Device=%.*ls\n"),
                        pMountPoints->MountPoints[i].DeviceNameLength/sizeof(WCHAR),
                        pbyOutBuffer + pMountPoints->MountPoints[i].DeviceNameOffset);
                _tprintf (TEXT("    SymbolicLink=%.*ls\n"),
                        pMountPoints->MountPoints[i].SymbolicLinkNameLength/sizeof(WCHAR),
                        pbyOutBuffer + pMountPoints->MountPoints[i].SymbolicLinkNameOffset);
                ccb = sizeof(szUniqueId)/sizeof(szUniqueId[0]);

                if (CryptBinaryToString (pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset,
                                        pMountPoints->MountPoints[i].UniqueIdLength,
                                        CRYPT_STRING_BASE64, 
                                        szUniqueId, &ccb))
                    _tprintf (TEXT("    UniqueId=%s\n"), szUniqueId);
                else
                    _tprintf (TEXT("    UniqueId=%.*ls\n"),
                            pMountPoints->MountPoints[i].UniqueIdLength/sizeof(WCHAR),
                            pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset);
            }
        }
        pbyInBuffer = (PBYTE) LocalFree (pbyInBuffer);
        pbyOutBuffer = (PBYTE) LocalFree (pbyOutBuffer);
    }
    pszLogicalDrives = (LPTSTR) LocalFree (pszLogicalDrives);
    bSuccess = CloseHandle (hMountMgr);

    return 0;
}

if produce on my computer the output like

\Device\HarddiskVolume3
#0:
    Device=\Device\HarddiskVolume3
    SymbolicLink=\DosDevices\C:
    UniqueId=O5TWlQAAwBRIAAAA
#1:
    Device=\Device\HarddiskVolume3
    SymbolicLink=\??\Volume{12703dc4-bf56-11db-8c6c-806e6f6e6963}
    UniqueId=O5TWlQAAwBRIAAAA

...

\Device\CdRom2
#0:
    Device=\Device\CdRom2
    SymbolicLink=\DosDevices\L:
    UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
#1:
    Device=\Device\CdRom2
    SymbolicLink=\??\Volume{2c5f6a93-2b50-11df-aa6a-005056c00008}
    UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}

\Device\HarddiskVolume8
#0:
    Device=\Device\HarddiskVolume8
    SymbolicLink=\DosDevices\N:
    UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
#1:
    Device=\Device\HarddiskVolume8
    SymbolicLink=\??\Volume{ae08a3c8-71cf-11de-bc1d-005056c00008}
    UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Sorry, but your question was how to use `IOCTL_MOUNTMGR_QUERY_POINTS`. Your original code was wrong. First of all you should use L"\\\\.\\MountPointManager" as a device name and not hUsbDevice. Second you should fill input buffer `MOUNTMGR_MOUNT_POINT` with a special way which I showed you in the example. But now you asked me the same question which is already answered in http://stackoverflow.com/questions/2995957/how-to-map-drive-letter-to-devicepath! If you do not understand how to get the drive letter for DevicePath of a USB stick I can explain it you, but it is quite another question. – Oleg Jun 11 '10 at 08:33
  • reallydo not understand how to get the drive letter for DevicePath of a USB stick .can you pls explain it to me – user198725878 Jun 12 '10 at 02:58
  • OK! I will write a small test program. What is you original requirement? Do you want enumerate all USB devices (or other bus like firewire) or Removable devices or Storage devices or devices which has a Volume mounted and show drive letter and storage device name or it's parent USB device name (which can be removed)? Or you have another starting point and want display another information? – Oleg Jun 12 '10 at 08:56
  • Thanks for your reply..i want to get the vid,pid and drive letter for all the usb mass storage devices plugged in the system. also if new usb mass storage device is plugged or removed from the system i need to get the vid,pid and drive letter – user198725878 Jun 16 '10 at 04:18
  • 1
    I wrote a program which do what you want, but I am not sure where I should post it. All questions has the name which is not corresponds my answer and it will makes difficult for other reader to read it. So probably the best way if you open one more question and ask how to get to all drive letters on a computer information about VendorId, ProductId, Hardware ID and whether the drive is removable. My program will display a little more additional information, but it is not important. I will post a full source code which do this. To compile this code you will need Windows DDK headers and libs. – Oleg Jun 18 '10 at 23:40
  • I tried your code snippet, but it didn't work in Windows 7. I always get "Invalid Parameter" Error in IOCTL_MOUNTMGR_QUERY_POINTS DeviceIoControl. – bkausbk Apr 26 '12 at 13:57
  • @bkausbk: Sorry, but the code works on my Windows 7 64bit computer without any problem. The only thing which is not so good in the code if how the values of `UniqueId` will be displayed. The `pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset` is not UNICODE string for some devices. – Oleg Apr 26 '12 at 14:29
  • @bkausbk: I updated the code by improving of decoding of the UniqueId. – Oleg Apr 26 '12 at 14:52
  • @Oleg: Thank you for your help. I found the problem. Because I didn't had the DDK installed, I copied the struct definitions from MSDN and included #pragma pach(1). But this is not allowed! – bkausbk Apr 27 '12 at 08:21
  • @bkausbk: OK, I understand. I recommend you to install DDK. It's free. At least you need to have full headers to be able to compile the programs correctly. I personally prefer to include the original headers to reduce problems like you did and to be able to update the program to the new version of DDK just updating of the path to the DDK header file. – Oleg Apr 27 '12 at 08:42
  • @Oleg: Do you have any idea why `GetVolumePathNamesForVolumeName` don't accepts here returned SymbolLinks as Volume name? Either something like **\DosDevices\X:** or paths like **\??\Volume{guid}** should work here. All here returned SymbolLinks are part of this registry key **HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices**. What is the best way to get real Paths/Driveletter from returned SymbolLink? – bkausbk Apr 27 '12 at 12:17
  • @bkausbk: Look at the code from my [another answer](http://stackoverflow.com/a/3100268/315935). The code demnstrate how to use `DeviceType`, `DeviceNumber` to find full information about all drive letters of the computer. – Oleg Apr 27 '12 at 12:58
  • @Oleg: Ok thank you, but I think my solution should also work. Iterating over MountPoints array until a symbolic link like **\\??\Volume** is found. Replacing \\??\ by \\?\ and then calling `GetVolumePathNamesForVolumeName` will give me the drive or a path where the volume is mounted. – bkausbk May 02 '12 at 07:14
  • @bkausbk: You are welcome! I am not sure what you want to say. I posted you the link to some code which work. I never wrote that it's *the only* way to get the information. I am glad to know that you have another way to get the same information, but you post comment to my answer which is almost two years old. The code which I post I get from my old program which was interesting for me about 10 years ago. Now it's not subject of my interest. I just shared my old code with other. – Oleg May 02 '12 at 07:25