I am writing an app using windows API that needs to check on startup that it is running from a USB device. What I have achieved so far
- List devices using SetupDiEnumDeviceInfo
- Detecting which device is removable
Here is my code to do the above 2 tasks
HDEVINFO hdevinfo = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE,NULL, NULL, DIGCF_PRESENT);
if (hdevinfo == INVALID_HANDLE_VALUE) {
WriteLog(L"hdevinfo is INVALID_HANDLE_VALUE");
return USB_PROT_ERROR;
}
DWORD MemberIndex = 0;
SP_DEVINFO_DATA sp_devinfo_data;
ZeroMemory(&sp_devinfo_data, sizeof(sp_devinfo_data));
sp_devinfo_data.cbSize = sizeof(sp_devinfo_data);
while (SetupDiEnumDeviceInfo(hdevinfo, MemberIndex, &sp_devinfo_data)) {
DWORD PropertyRegDataType;
DWORD RequiredSize;
TCHAR PropertyBuffer[500];
//get the name of this device
if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sp_devinfo_data, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &PropertyRegDataType, (PBYTE)&PropertyBuffer, sizeof(PropertyBuffer), &RequiredSize)) {
WriteLog(L"Device name: %s", PropertyBuffer);
DWORD PropertyValue;
//get removal policy for this device
if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sp_devinfo_data, SPDRP_REMOVAL_POLICY, &PropertyRegDataType, (PBYTE)&PropertyValue, sizeof(PropertyValue), &RequiredSize)) {
if (PropertyValue == CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL) {
//not removable
WriteLog(L"Not Removable");
}
else {
//removable
WriteLog("Removable");
}
}
}
}
On my PC with 1 HARD DRIVE and 1 USB DRIVE attached, I get this output:
Device name: \Device\00000031
Not Removable
Device name: \Device\00000070
Removable
From the output it is clear that \Device\00000070 is my USB device. And from My Computer I can see that my USB device is mounted on H drive
What I want to achieve now is
- Find out that on which drive letter (in my case it is H:) that removable device (in my case it is \Device\00000070) is mounted.
OR
Find out all the volumes(sub devices I can say) that are under this device. For example if I pass GUID_DEVCLASS_VOLUME GUID to SetupDiGetClassDevs function then my output looks like this:
Device name: \Device\HarddiskVolume2 Not Removable
Device name: \Device\HarddiskVolume4 Not Removable
Device name: \Device\HarddiskVolume9 Not Removable
Device name: \Device\HarddiskVolume5 Not Removable
After some debugging I found that \Device\HarddiskVolume9 is my USB but you can see in the output that it always show "Not Removable". So if I can find out that \Device\HarddiskVolume9 belongs to \Device\00000070 then that will also work for me as I can then easily use Volume management functions to find the drive letter for \Device\HarddiskVolume9 and match with the drive letter of the executable.
I want to do this using C/C++ Windows API without using any 3rd party library and no .NET code.