How to programmatically mount a drive in Windows?

We manufacture and sell a device that our users sometimes want to connect to their computer in large quantities with several USB hubs. This is a USB-based device that has user interface (HID) and mass storage (MSD) interfaces. Windows automatically mounts the file system of each device until it has the letter "Z:".

I can go through the device tree and get the device instance identifiers for the HID and USBSTOR interfaces using a combination of PnP Configuration Manager and Device Installation . Using the path of the USB drive, I can also get the disk number (i.e. \\.\PhysicalDrive1 ).

The next step is to install these disks as necessary by cyclic moving the letters of the disks when we communicate with devices or, even better, mount them in temporary directories on the C: drive. I'm having difficulty trying to use DefineDosDevice for this task and cannot succeed with SetVolumeMountPoint because the device does not have a GUID volume before it is installed. This presents a problem with the chicken and the egg.

If only our customers used unix !!!

+4
source share
2 answers

Windows does not mount drives; he mounts the volume. However, the size of a USBSTOR device is not specified as a child of a node in the device tree. Thus, you need to list all volumes and perform a bunch of manipulations and string comparisons to combine the STOP / VOLUME storage nodes with the USBSTOR nodes.

All volume GUIDs are enumerated using the FindFirstVolume function set. Leading characters "\. \" And trailing "\" can be removed, and the resulting string is then passed to QueryDosDevice . This gives the name of the device.

Next, you need to list all volumes using GUID_DEVINTERFACE_VOLUME with SetupDiGetClassDevs and friends. Compare the device type and number of each volume with the USBSTOR device you are looking for using IOCTL_STORAGE_GET_DEVICE_NUMBER . After reconciliation, you can get the device name from the volume and compare it with another list of device names to find the GUID of the volume.

Finally, the volume GUID can be used successfully with SetVolumeMountPoint .

Thanks to Gabe for his very helpful help in commenting on my question.


Code snippets

Get the type and number of the device from the device path:

 STORAGE_DEVICE_NUMBER sdn; HANDLE handle = CreateFile(devInterfaceDetail->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); DWORD len = 0; DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof (sdn), &len, NULL); 

Find the device name for the corresponding USBSTOR instance by iterating over all volume interfaces and comparing the disk number with the above snippet:

 std::string deviceName; HDEVINFO devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); SP_DEVICE_INTERFACE_DATA devInterface = { 0 }; devInterface.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); for (int i = 0; SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_VOLUME, i, &devInterface); ++i) { SP_DEVINFO_DATA devInfoData = { 0 }; devInfoData.cbSize = sizeof (SP_DEVINFO_DATA); DWORD len; SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, NULL, 0, &len, &devInfoData); std::vector<char> buf(len); SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA *) &buf[0]; devInterfaceDetail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); if (SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, devInterfaceDetail, len, NULL, &devInfoData)) { if (DEVICE_NUMBER == this->getDeviceNumber(devInterfaceDetail->DevicePath)) { std::vector<BYTE> buf(MAX_PATH + 1); DWORD type, len; if (SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &type, &buf[0], buf.size(), &len)) { deviceName.assign(buf.begin(), buf.begin() + len); break; } } } } 
+8
source

It seems to me that you need to use IOCTL_MOUNTMGR_CREATE_POINT . Unfortunately, the most common IOCTL_MOUNTMGR_XXX example IOCTL_MOUNTMGR_XXX written for kernel-mode drivers, but this is not required. Probably my old answer (which uses IOCTL_MOUNTMGR_QUERY_POINTS ) and another may help you with this. See also http://msdn.microsoft.com/en-us/library/ff567603.aspx and http://support.microsoft.com/kb/836662 .

Perhaps after a better understanding of how IOCTL_MOUNTMGR_CREATE_POINT , you can solve the problem regarding SetVolumeMountPoint .

0
source

All Articles