I wrote a program in C which demonstrate how to receive the information which you need
#include <windows.h>
#include <devguid.h> // for GUID_DEVCLASS_CDROM etc
#include <setupapi.h>
#include <cfgmgr32.h> // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
#include <tchar.h>
#include <stdio.h>
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
#pragma comment (lib, "setupapi.lib")
//
// Define the various device characteristics flags (defined in wdm.h)
//
#define FILE_REMOVABLE_MEDIA 0x00000001
#define FILE_READ_ONLY_DEVICE 0x00000002
#define FILE_FLOPPY_DISKETTE 0x00000004
#define FILE_WRITE_ONCE_MEDIA 0x00000008
#define FILE_REMOTE_DEVICE 0x00000010
#define FILE_DEVICE_IS_MOUNTED 0x00000020
#define FILE_VIRTUAL_VOLUME 0x00000040
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
#define FILE_DEVICE_SECURE_OPEN 0x00000100
#define FILE_CHARACTERISTIC_PNP_DEVICE 0x00000800
#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000
#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000
#pragma warning (disable: 4201)
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#pragma warning (default: 4201)
typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1,
FileFsLabelInformation, // 2
FileFsSizeInformation, // 3
FileFsDeviceInformation, // 4
FileFsAttributeInformation, // 5
FileFsControlInformation, // 6
FileFsFullSizeInformation, // 7
FileFsObjectIdInformation, // 8
FileFsDriverPathInformation, // 9
FileFsVolumeFlagsInformation,// 10
FileFsMaximumInformation
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
typedef struct _FILE_FS_DEVICE_INFORMATION {
DEVICE_TYPE DeviceType;
ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
typedef NTSTATUS (NTAPI *LPFN_NT_QUERY_VOLUME_INFORMATION_FILE) (HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FsInformation, ULONG Length,
FS_INFORMATION_CLASS FsInformationClass);
BOOL GetDriveTypeAndCharacteristics (HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics)
{
HMODULE hNtDll;
LPFN_NT_QUERY_VOLUME_INFORMATION_FILE lpfnNtQueryVolumeInformationFile;
NTSTATUS ntStatus;
IO_STATUS_BLOCK IoStatusBlock;
FILE_FS_DEVICE_INFORMATION FileFsDeviceInfo;
BOOL bSuccess = FALSE;
hNtDll = GetModuleHandle (TEXT("ntdll.dll"));
if (hNtDll == NULL)
return FALSE;
lpfnNtQueryVolumeInformationFile = (LPFN_NT_QUERY_VOLUME_INFORMATION_FILE)GetProcAddress (hNtDll, "NtQueryVolumeInformationFile");
if (lpfnNtQueryVolumeInformationFile == NULL)
return FALSE;
ntStatus = lpfnNtQueryVolumeInformationFile (hDevice, &IoStatusBlock,
&FileFsDeviceInfo, sizeof(FileFsDeviceInfo),
FileFsDeviceInformation);
if (ntStatus == NO_ERROR) {
bSuccess = TRUE;
*pDeviceType = FileFsDeviceInfo.DeviceType;
*pCharacteristics = FileFsDeviceInfo.Characteristics;
}
return bSuccess;
}
void FildVolumeName (LPCTSTR pszDeviceName)
{
TCHAR szVolumeName[MAX_PATH] = TEXT("");
TCHAR szDeviceName[MAX_PATH] = TEXT("");
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwCharCount;
BOOL bSuccess;
hFind = FindFirstVolume (szVolumeName, ARRAYSIZE(szVolumeName));
if (hFind == INVALID_HANDLE_VALUE) return;
while(TRUE) {
// Skip the \? prefix and remove the trailing backslash.
size_t Index = lstrlen(szVolumeName) - 1;
if (szVolumeName[0] != TEXT('\') ||
szVolumeName[1] != TEXT('\') ||
szVolumeName[2] != TEXT('?') ||
szVolumeName[3] != TEXT('\') ||
szVolumeName[Index] != TEXT('\')) return; // error
// QueryDosDeviceW doesn't allow a trailing backslash,
// so temporarily remove it.
szVolumeName[Index] = TEXT('');
dwCharCount = QueryDosDevice (&szVolumeName[4], szDeviceName, ARRAYSIZE(szDeviceName));
szVolumeName[Index] = TEXT('\');
if (dwCharCount == 0) return; // error
if (lstrcmp (pszDeviceName, szDeviceName) == 0) {
_tprintf (TEXT(" Volume Device Name: %s
"), szVolumeName);
return;
}
bSuccess = FindNextVolume (hFind, szVolumeName, ARRAYSIZE(szVolumeName));
if (!bSuccess) {
DWORD dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NO_MORE_ITEMS)
break;
else
break; // ERROR!!!
}
}
}
void DumpVidPidMi (LPCTSTR pszDeviceInstanceId)
{
TCHAR szDeviceInstanceId[MAX_DEVICE_ID_LEN];
const static LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};
LPTSTR pszToken, pszNextToken;
int j;
lstrcpy (szDeviceInstanceId, pszDeviceInstanceId);
pszToken = _tcstok_s (szDeviceInstanceId , TEXT("\#&"), &pszNextToken);
while(pszToken != NULL) {
for (j = 0; j < 3; j++) {
if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0) {
switch(j) {
case 0:
_tprintf (TEXT(" vid: "%s"
"), pszToken + lstrlen(arPrefix[j]));
break;
case 1:
_tprintf (TEXT(" pid: "%s"
"), pszToken + lstrlen(arPrefix[j]));
break;
case 2:
_tprintf (TEXT(" mi: "%s"
"), pszToken + lstrlen(arPrefix[j]));
break;
default:
break;
}
}
}
pszToken = _tcstok_s (NULL, TEXT("\#&"), &pszNextToken);
}
}
BOOL FindDiInfos (LPCGUID pGuidInferface, LPCGUID pGuidClass, LPCTSTR pszEnumerator,
DEVICE_TYPE DeviceType, DWORD DeviceNumber,
DWORD dwDeviceInstanceIdSize, // MAX_DEVICE_ID_LEN
OUT LPTSTR pszDeviceInstanceId,
OUT PDWORD pdwRemovalPolicy)
//#define CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL 1
//#define CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL 2
//#define CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL 3
{
HDEVINFO hIntDevInfo = NULL;
DWORD dwIndex;
BOOL bFound = FALSE;
HANDLE hDev = INVALID_HANDLE_VALUE;
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
// set defaults
*pdwRemovalPolicy = 0;
pszDeviceInstanceId[0] = TEXT('');
__try {
hIntDevInfo = SetupDiGetClassDevs (pGuidInferface, pszEnumerator, NULL,
pGuidInferface != NULL? DIGCF_PRESENT | DIGCF_DEVICEINTERFACE:
DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hIntDevInfo == INVALID_HANDLE_VALUE)
__leave;
for (dwIndex = 0; ;dwIndex ++) {
SP_DEVICE_INTERFACE_DATA interfaceData;
SP_DEVINFO_DATA deviceInfoData;
DWORD dwDataType, dwRequiredSize;
BOOL bSuccess;
ZeroMemory (&interfaceData, sizeof(interfaceData));
interfaceData.cbSize = sizeof(interfaceData);
bSuccess = SetupDiEnumDeviceInterfaces (hIntDevInfo, NULL, pGuidInferface, dwIndex, &interfaceData);
if (!bSuccess) {
DWORD dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NO_MORE_ITEMS)
break;
else
break; // ERROR!!!
}
dwRequiredSize = 0;
bSuccess = SetupDiGetDeviceInterfaceDetail (hIntDevInfo, &interfaceData, NULL, 0, &dwRequiredSize, NULL);
if ((!bSuccess && GetLastError() != ERROR_INSUFFICIENT_BUFFER) || dwRequiredSize == 0)
continue; // ERROR!!!
if (pInterfaceDetailData)
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalFree (pInterfaceDetailData);
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc (LPTR, dwRequiredSize);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
ZeroMemory (&deviceInfoData, sizeof(deviceInfoData));
deviceInfoData.cbSize = sizeof(deviceInfoData);
bSuccess = SetupDiGetDeviceInterfaceDetail (hIntDevInfo, &interfaceData,
pInterfaceDetailData, dwRequiredSize, &dwRequiredSize, &deviceInfoData);
if (!bSuccess)
continue;
hDev = CreateFile (pInterfaceDetailData->DevicePath,
0, // no access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDev != INVALID_HANDLE_VALUE) {
STORAGE_DEVICE_NUMBER sdn;
DWORD cbBytesReturned;
bSuccess = DeviceIoControl (hDev, // device to be queried
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, // no input buffer
(LPVOID)&sdn, sizeof(sdn), // output buffer
&cbBytesReturned, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if (bSuccess) {
if (sdn.DeviceType == DeviceType &&
sdn.DeviceNumber == DeviceNumber) {
DEVINST dnDevInstParent, dnDevInstParentParent;
CONFIGRET ret;
// device found !!!
TCHAR szBuffer[4096];
_tprintf (TEXT(" DevicePath: %s
"), pInterfaceDetailData->DevicePath);
bSuccess = SetupDiGetDeviceInstanceId (hIntDevInfo, &deviceInfoData, pszDeviceInstanceId,
dwDeviceInstanceIdSize, &dwRequiredSize);
if (dwRequiredSize > MAX_DEVICE_ID_LEN)
continue;
bSuccess = SetupDiGetDeviceRegistryProperty (hIntDevInfo, &deviceInfoData, SPDRP_REMOVAL_POLICY, &dwDataType,
(PBYTE)pdwRemovalPolicy, sizeof(DWORD), &dwRequiredSize);
// SPDRP_CHARACTERISTICS - Device characteristics
//