Skip to content

Instantly share code, notes, and snippets.

@gabonator
Created April 26, 2012 13:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gabonator/2499496 to your computer and use it in GitHub Desktop.
Save gabonator/2499496 to your computer and use it in GitHub Desktop.
USB enumerating tools
#include "usb.h"
#ifndef DISABLE_USB
#pragma comment(lib, "setupapi.lib")
#include "SetupAPI.h"
#include "cfgmgr32.h"
#pragma pack(4)
DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
00110 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
bool RemovableScanDisks(CArray <stDriveVolume, stDriveVolume> &arrDrives)
{
WCHAR caDrive[4] = _T("A:\\");
WCHAR volume[1024];
DWORD dwDriveMask;
// Get all drives in the system.
dwDriveMask = GetLogicalDrives();
if(dwDriveMask == 0)
return false;
// Loop for all drives (MAX_DRIVES = 26)
for(; dwDriveMask; dwDriveMask >>= 1, caDrive[0]++)
{
// if a drive is present,
if(dwDriveMask & 1)
{
// If a drive is removable
if(GetDriveType(caDrive) == DRIVE_REMOVABLE)
//Get its volume info and store it in the global variable.
if(GetVolumeNameForVolumeMountPoint(caDrive, volume, 1024))
arrDrives.Add( stDriveVolume( caDrive[0], volume ));
}
}
return true;
}
bool RemovableFillInfo( CArray <stDriveVolume, stDriveVolume> &arrDrives )
{
HDEVINFO hDevInfo;
GUID guid;
BYTE buffer[1024];
DWORD dwRequiredSize ;
WCHAR buf[1024];
DEVINST devInstParent;
DWORD dwIndex;
WCHAR volume[1024];
int nLength;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
// GUID_DEVINTERFACE_VOLUME is interface Guid for Volume class devices.
guid = GUID_DEVINTERFACE_VOLUME;
// Get device Information handle for Volume interface
hDevInfo = SetupDiGetClassDevs(&guid, NULL, NULL,
/*DIGCF_ALLCLASSES | */
DIGCF_DEVICEINTERFACE |
DIGCF_PRESENT);
if(hDevInfo == INVALID_HANDLE_VALUE)
return false;
SP_DEVINFO_DATA* pspDevInfoData =
(SP_DEVINFO_DATA*)HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
/*
for(int i=0; SetupDiEnumDeviceInfo(hDevInfo,i,pspDevInfoData); i++)
{
char buf[1024];
DWORD nSize;
if ( SetupDiGetDeviceInstanceIdA(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
{
DWORD DataT;
if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, pspDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize) )
{
int f = 9;
OutputDebugStringA( "friendlyname: " );
OutputDebugStringA( buf );
OutputDebugStringA( "\n" );
}
if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, pspDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize) )
{
OutputDebugStringA( "devicedesc: " );
OutputDebugStringA( buf );
OutputDebugStringA( "\n" );
}
}
}
*/
// Loop until device interfaces are found.
for(dwIndex = 0; ; dwIndex ++)
{
ZeroMemory(&devInterfaceData, sizeof(devInterfaceData));
devInterfaceData.cbSize = sizeof(devInterfaceData);
// Get device Interface data.
if(!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guid, dwIndex, &devInterfaceData))
break;
ZeroMemory(&devInfoData, sizeof(devInfoData));
devInfoData.cbSize = sizeof(devInfoData);
pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer;
pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// Get device interface detail data to get
// Device Instance from SP_DEVINFO_DATA and
// Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&devInterfaceData,
pDevDetail, // SP_DEVICE_INTERFACE_DETAIL_DATA
1024,
&dwRequiredSize,
&devInfoData); // SP_DEVINFO_DATA
/*
char buf[1024];
DWORD nSize;
if ( SetupDiGetDeviceInstanceIdA(hDevInfo, &devInfoData, buf, sizeof(buf), &nSize) )
{
OutputDebugStringA( buf );
OutputDebugStringA( " " );
DWORD DataT;
if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, &devInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize) )
{
OutputDebugStringA( buf );
OutputDebugStringA( " " );
} else if ( SetupDiGetDeviceRegistryPropertyA(hDevInfo, &devInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize) )
{
OutputDebugStringA( buf );
OutputDebugStringA( " " );
}
OutputDebugStringA( "\n" );
}
*/
// Get the device instance of parent. This points to USBSTOR.
CM_Get_Parent(&devInstParent,devInfoData.DevInst, 0);
// Get the device instance of grand parent. This points to USB root.
CM_Get_Parent(&devInstParent,devInstParent, 0);
// Get the device ID of the USB root.
CM_Get_Device_ID(devInstParent, buf, 1024, 0);
// If USB root device matches with the input device ID, it is the target
// device.
if( buf != NULL /*&& wcscmp(lpDevID,buf) == 0*/ )
{
// Append \ to the DevicePath of SP_DEVICE_INTERFACE_DETAIL_DATA
nLength = (int)wcslen(pDevDetail->DevicePath);
pDevDetail->DevicePath[nLength] = '\\';
pDevDetail->DevicePath[nLength+1] = 0;
// Get Volume mount point for the device path.
if(GetVolumeNameForVolumeMountPoint(pDevDetail->DevicePath, volume, 1024))
{
// Compare volume mount point with the one stored earlier.
// If both match, return the corresponding drive letter.
for(int nLoopIndex=0; nLoopIndex < arrDrives.GetSize(); nLoopIndex++)
if ( arrDrives[nLoopIndex].strFriendlyProduct.IsEmpty() )
if(wcscmp(arrDrives[nLoopIndex].strVolume, volume)==0)
{
CString strBuffer( buf );
int nVid = strBuffer.Find(_T("VID_"));
int nPid = strBuffer.Find(_T("PID_"));
if ( nVid == -1 || nPid == -1 )
continue;
int nVidE = strBuffer.Find(_T("&"), nVid);
int nPidE = strBuffer.Find(_T("\\"), nPid);
if ( nVidE == -1 || nPidE == -1 )
{
continue;
}
arrDrives[nLoopIndex].strFriendlyProduct = strBuffer.Mid(nVid+4, nVidE-nVid-4);
arrDrives[nLoopIndex].strFriendlyVendor = strBuffer.Mid(nPid+4, nPidE-nPid-4);
arrDrives[nLoopIndex].strDevicePath = CString(pDevDetail->DevicePath);
}
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return true;
}
static const GUID guidDISK =
{
0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }
};
#include "fscommands.h"
// http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx
CString GetDevicePathByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName)
{
bool IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // is there a better way?
GUID* guid;
switch (DriveType) {
case DRIVE_REMOVABLE:
if ( IsFloppy ) {
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
} else {
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
}
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return _T("");
}
// Get device interface info set handle
// for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return _T("");
}
// Retrieve a context structure for a device interface
// of a device information set.
DWORD dwIndex = 0;
BOOL bRet = FALSE;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while ( true ) {
bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL,
guid, dwIndex, &spdid);
if (!bRet) {
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&spdid, NULL, 0, &dwSize, NULL);
if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res =
SetupDiGetDeviceInterfaceDetail(hDevInfo, &
spdid, pspdidd,
dwSize, &dwSize,
&spdd);
if ( res ) {
HANDLE hDrive = CreateFile(pspdidd->DevicePath,0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, NULL, NULL);
if ( hDrive != INVALID_HANDLE_VALUE ) {
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
res = DeviceIoControl(hDrive,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof(sdn),
&dwBytesReturned, NULL);
if ( res ) {
if ( DeviceNumber == (long)sdn.DeviceNumber ) {
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return CString(pspdidd->DevicePath);
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return _T("");
}
bool RemovableFriendlyName( stDriveVolume &volDrive )
{
// "\\\\.\\X:"
// "\\\\\?\\Volume{3dd04400-bdaa-11da-af8e-806d6172696f}"
CString strDevice;
strDevice.Format(_T("\\\\.\\%c:"), toupper(volDrive.chDrive));
//strDevice = volDrive.strVolume.Left( volDrive.strVolume.GetLength()-1 );
HANDLE hDevice = CreateFile(strDevice,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, NULL, NULL);
if ( hDevice == NULL || hDevice == INVALID_HANDLE_VALUE )
return false;
DWORD dwOutBytes = 0;
STORAGE_PROPERTY_QUERY Query;
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
char Buf[1024] = {0};
PSTORAGE_DEVICE_DESCRIPTOR pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)Buf;
pDevDesc->Size = sizeof(Buf);
BOOL res = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &Query,
sizeof(STORAGE_PROPERTY_QUERY), pDevDesc, pDevDesc->Size, &dwOutBytes, (LPOVERLAPPED)NULL);
if (!res)
{
CloseHandle(hDevice);
return false;
}
if (pDevDesc->VendorIdOffset != 0)
volDrive.strFriendlyVendor = CString( (PCHAR)((PBYTE)pDevDesc + pDevDesc->VendorIdOffset) );
if (pDevDesc->ProductIdOffset != 0)
volDrive.strFriendlyProduct = CString( (PCHAR)((PBYTE)pDevDesc + pDevDesc->ProductIdOffset) );
STORAGE_DEVICE_NUMBER deviceNumber;
res = DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &deviceNumber, sizeof(deviceNumber), &dwOutBytes, (LPOVERLAPPED)NULL);
CloseHandle(hDevice);
if (!res)
return false;
char szDosDeviceName[MAX_PATH];
char szDevicePath[] = "X:\\";
szDevicePath[0] = toupper(volDrive.chDrive);
UINT DriveType = GetDriveTypeA(szDevicePath);
szDevicePath[2] = 0;
res = QueryDosDeviceA(szDevicePath, szDosDeviceName, MAX_PATH);
volDrive.strDevicePath = CString(szDosDeviceName);
volDrive.strDevice = GetDevicePathByDeviceNumber(deviceNumber.DeviceNumber, DriveType, szDosDeviceName);
//wprintf(_T("dev number = %d, drive type = %d, dos driver = %S\nDEVICE=%s\n"), deviceNumber.DeviceNumber, DriveType, szDosDeviceName, strDevPath);
return true;
}
bool RemovableEnumerate(CArray <stDriveVolume, stDriveVolume> &arrDrives)
{
// TCHAR strLabel[MAX_PATH] = {0};
// TCHAR strDrive[4] = {'?', ':', '\\'};
// DWORD dwSerial;
if ( !RemovableScanDisks( arrDrives ) )
return false;
for (int i=0; i<arrDrives.GetSize(); i++)
// {
RemovableFriendlyName( arrDrives[i] );
// strDrive[0] = tolower(arrDrives[i].chDrive);
// if ( GetVolumeInformation(strDrive, strLabel, sizeof(strLabel), &dwSerial, NULL, NULL, NULL, 0) )
// arrDrives[i].strLabel = CString( strLabel );
// }
// only XP compatible, catches problematic devices without VID/PID
RemovableFillInfo( arrDrives );
return true;
for (int i=0; i<arrDrives.GetSize(); i++)
{
CString strDebug;
strDebug.Format(_T("drive=%c:\nvolume=%s\ndevice=%s\nvendor=%s\nproduct=%s\ndevpath=%s\nlabel=%s"),
arrDrives[i].chDrive,
arrDrives[i].strVolume,
arrDrives[i].strDevice,
arrDrives[i].strFriendlyVendor,
arrDrives[i].strFriendlyProduct,
arrDrives[i].strDevicePath,
arrDrives[i].strLabel);
MessageBox( NULL, strDebug, _T("debug info"), 0 );
}
return true;
}
#else
bool RemovableEnumerate(CArray <stDriveVolume, stDriveVolume> &arrDrives)
{
return false;
}
//}
#endif
//#define DISABLE_USB
#include "_mfc.h"
struct stDriveVolume
{
stDriveVolume()
{
}
stDriveVolume( WCHAR _chDrive, CString _strVolume )
{
chDrive = _chDrive;
strVolume = _strVolume;
}
const stDriveVolume& operator=(const stDriveVolume& child)
{
chDrive = child.chDrive;
strVolume = child.strVolume;
strDevice = child.strDevice;
strDevicePath = child.strDevicePath;
strFriendlyVendor = child.strFriendlyVendor;
strFriendlyProduct = child.strFriendlyProduct;
strLabel = child.strLabel;
return *this;
}
WCHAR chDrive;
CString strVolume;
CString strDevice;
CString strFriendlyVendor;
CString strFriendlyProduct;
CString strDevicePath;
CString strLabel;
};
bool RemovableEnumerate(CArray <stDriveVolume, stDriveVolume> &arrDrives);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment