I did this test on my PC (in C++ as you tagged C++...) by enumerating disk drives; I get :
DeviceID : SCSI\DISK&VEN_ATA&PROD_ST1000DM003-1SB1\4&38FBD192&0&000000
Parent DeviceID : PCI\VEN_8086&DEV_8C02&SUBSYS_B0051458&REV_05\3&11583659&0&FA
Drive Letters : D:, E:, C:
DeviceID : USBSTOR\DISK&VEN__USB&PROD__SANDISK_3.2GEN1&REV_1.00\010130EBADCCCEFA5A8FF9F68DAD45551D020722931C25CB45700559C9CEEC9
Parent DeviceID : USB\VID_0781&PID_5591\010130EBADCCCEFA5A8FF9F68DAD45551D020722931C25CB45700559C9CEEC9080A500000000000000000000CE43F2EEFF0A250091558107B8A8A55D
Drive Letters : H:
Test code :
HANDLE hDevice = NULL;
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD dwDeviceIndex = 0; SetupDiEnumDeviceInfo(DeviceInfoSet, dwDeviceIndex, &DeviceInfoData); dwDeviceIndex++)
{
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (DWORD dwMemberIndex = 0; SetupDiEnumDeviceInterfaces(DeviceInfoSet, &DeviceInfoData, &GUID_DEVINTERFACE_DISK, dwMemberIndex, &DeviceInterfaceData); dwMemberIndex++)
{
DWORD dwDeviceInterfaceDetailDataSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA, DevicePath) + MAX_PATH * sizeof(TCHAR);
PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[dwDeviceInterfaceDetailDataSize];
pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &DeviceInterfaceData, pDeviceInterfaceDetailData, dwDeviceInterfaceDetailDataSize, NULL, NULL))
{
CONFIGRET cRet;
DEVINST hDevInst = DeviceInfoData.DevInst;
DEVINST hParentDevInst;
cRet = CM_Get_Parent(&hParentDevInst, hDevInst, 0);
TCHAR wsParentDeviceID[MAX_DEVICE_ID_LEN];
cRet = CM_Get_Device_ID(hParentDevInst, wsParentDeviceID, sizeof(wsParentDeviceID) / sizeof(TCHAR), 0);
TCHAR wsDeviceID[MAX_DEVICE_ID_LEN];
cRet = CM_Get_Device_ID(hDevInst, wsDeviceID, sizeof(wsDeviceID) / sizeof(TCHAR), 0);
WCHAR wsText[MAX_PATH] = L"";
wsprintf(wsText, L"DeviceID : %s\r\n", wsDeviceID); // 1 PowerDeviceD0
OutputDebugString(wsText);
wsprintf(wsText, L"\tParent DeviceID : %s\r\n", wsParentDeviceID); // 1 PowerDeviceD0
OutputDebugString(wsText);
/* hDevice = CreateFile(pDeviceInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
}*/
WCHAR wsDriveLetters[MAX_PATH] = L"";
GetDriveLettersFromDevInstID(wsDeviceID, wsDriveLetters);
wsprintf(wsText, L"\tDrive Letters : %s\r\n", wsDriveLetters); // 1 PowerDeviceD0
OutputDebugString(wsText);
}
}
}
Utility functions :
void GetDriveLettersFromDevInstID(LPCTSTR pwsDeviceInstanceID, __out LPTSTR pwsDriveLetters)
{
pwsDriveLetters[0] = 0;
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
// hr = 0x80010119
hr = CoInitializeSecurity(NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_NONE, // RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (SUCCEEDED(hr))
{
IWbemLocator* pLoc = NULL;
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (SUCCEEDED(hr))
{
IWbemServices* pSvc = NULL;
hr = pLoc->ConnectServer(bstr_t(L"ROOT\\CIMV2"), NULL, NULL, NULL, 0, NULL, NULL, &pSvc);
if (SUCCEEDED(hr))
{
hr = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (SUCCEEDED(hr))
{
WCHAR wsQuery[MAX_PATH] = L"";
lstrcpy(wsQuery, L"SELECT * FROM Win32_DiskDrive where PNPDeviceID='");
lstrcat(wsQuery, pwsDeviceInstanceID);
lstrcat(wsQuery, L"'");
StrReplace(wsQuery, L"\\", L"\\\\", ARRAYSIZE(wsQuery));
IEnumWbemClassObject* pWbemEnum = NULL;
hr = pSvc->ExecQuery(bstr_t("WQL"),
bstr_t(wsQuery),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pWbemEnum);
if (SUCCEEDED(hr))
{
IWbemClassObject* pclsObj;
ULONG uReturn = 0;
int nCount = 0;
while (pWbemEnum)
{
hr = pWbemEnum->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
// 0x80041010 Invalid class WBEM_E_INVALID_CLASS
// 2147749911 (0x80041017) WBEM_E_INVALID_QUERY
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
VariantInit(&vtProp);
hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);
WCHAR wsDeviceID[255] = L"";
wsprintf(wsDeviceID, L"%s", vtProp.bstrVal);
VariantClear(&vtProp);
lstrcpy(wsQuery, L"ASSOCIATORS OF {Win32_DiskDrive.DeviceID='");
lstrcat(wsQuery, wsDeviceID);
lstrcat(wsQuery, L"'");
lstrcat(wsQuery, L"} WHERE AssocClass = Win32_DiskDriveToDiskPartition");
//lstrcpy(wsQuery, L"ASSOCIATORS OF {Win32_DiskDrive.DeviceID='\\\\.\\PHYSICALDRIVE0'} WHERE AssocClass = Win32_DiskDriveToDiskPartition");
IEnumWbemClassObject* pWbemEnum2 = NULL;
hr = pSvc->ExecQuery(bstr_t("WQL"),
bstr_t(wsQuery),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pWbemEnum2);
StrReplace(wsQuery, L"\\", L"\\\\", ARRAYSIZE(wsQuery));
// ASSOCIATORS OF {Win32_DiskDrive.DeviceID= "\\\\.\\PHYSICALDRIVE1"} WHERE AssocClass = Win32_DiskDriveToDiskPartition
// hr = 0x8004103a WBEM_E_INVALID_OBJECT_PATH 2147749946 (0x8004103A)
if (SUCCEEDED(hr))
{
IWbemClassObject* pclsObj2;
ULONG uReturn2 = 0;
while (pWbemEnum2)
{
hr = pWbemEnum2->Next(WBEM_INFINITE, 1, &pclsObj2, &uReturn2);
if (0 == uReturn2)
{
break;
}
VARIANT vtProp;
VariantInit(&vtProp);
hr = pclsObj2->Get(L"DeviceID", 0, &vtProp, 0, 0);
WCHAR wsPartitionDeviceID[255] = L"";
wsprintf(wsPartitionDeviceID, L"%s", vtProp.bstrVal);
VariantClear(&vtProp);
lstrcpy(wsQuery, L"ASSOCIATORS Of {Win32_DiskPartition.DeviceID='");
lstrcat(wsQuery, wsPartitionDeviceID);
lstrcat(wsQuery, L"'");
lstrcat(wsQuery, L"} WHERE AssocClass = Win32_LogicalDiskToPartition");
IEnumWbemClassObject* pWbemEnum3 = NULL;
hr = pSvc->ExecQuery(bstr_t("WQL"),
bstr_t(wsQuery),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pWbemEnum3);
StrReplace(wsQuery, L"\\", L"\\\\", ARRAYSIZE(wsQuery));
if (SUCCEEDED(hr))
{
IWbemClassObject* pclsObj3;
ULONG uReturn3 = 0;
while (pWbemEnum3)
{
hr = pWbemEnum3->Next(WBEM_INFINITE, 1, &pclsObj3, &uReturn3);
if (0 == uReturn3)
{
break;
}
VARIANT vtProp;
VariantInit(&vtProp);
hr = pclsObj3->Get(L"DeviceID", 0, &vtProp, 0, 0);
WCHAR sLogicalDeviceID[255] = L"";
wsprintf(sLogicalDeviceID, L"%s", vtProp.bstrVal);
VariantClear(&vtProp);
if (lstrcmp(pwsDriveLetters, L"") == 0)
{
lstrcat(pwsDriveLetters, sLogicalDeviceID);
}
else
{
lstrcat(pwsDriveLetters, L", ");
lstrcat(pwsDriveLetters, sLogicalDeviceID);
}
pclsObj3->Release();
}
pWbemEnum3->Release();
}
pclsObj2->Release();
}
pWbemEnum2->Release();
}
nCount++;
pclsObj->Release();
}
pWbemEnum->Release();
}
}
pSvc->Release();
}
pLoc->Release();
}
}
CoUninitialize();
}
}
int StrReplace(LPCTSTR sStringReplace, LPCTSTR sOldStr, LPCTSTR sNewStr, int nStringLengthMax)
{
int nNewLength = lstrlen(sNewStr);
int nOldLength = lstrlen(sOldStr);
int nStringLength = lstrlen(sStringReplace);
LPCTSTR pCharRep;
if ((pCharRep = wcsstr(sStringReplace, sOldStr)) == NULL)
return -1;
int nAdd = 0;
while (pCharRep != NULL)
{