我们进行Windows编程的时候,有些时候需要枚举设备,例如光盘,光驱,硬盘等等,
我们如何实现功能呢,请见代码分析
#include <windows.h> #include <setupapi.h> #include <stdio.h> #include <devguid.h> #include <regstr.h> /* 函数声明 */ BOOL EnumPresentDevice( const GUID * InterfaceClassGuid ); BOOL EnumAllDevice(); /************************************* * BOOL EnumClassDevice( const GUID * InterfaceClassGuid ) * 功能 根据类型列举当前存在的设备 * 参数 InterfaceClassGuid,所需列举设备接口类的GUID **************************************/ BOOL EnumClassDevice( const GUID * InterfaceClassGuid ) { HDEVINFO DeviceInfoSet; HDEVINFO NewDeviceInfoSet; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA lpDeviceInterfaceDetailData; DWORD dwBufferSize = 0; DWORD i; // 创建空设备信息列表 DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL); if(DeviceInfoSet == INVALID_HANDLE_VALUE) { printf("CreateDeviceInfoList failed: %d\n", GetLastError()); return 0; } // 根据接口类型获得新的设备信息列表 NewDeviceInfoSet = SetupDiGetClassDevsEx( InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE, DeviceInfoSet,// 之前创建的设备信息列表 NULL, NULL ); if(NewDeviceInfoSet == INVALID_HANDLE_VALUE) { printf( "SetupDiGetClassDevsEx failed: %d\n", GetLastError() ); return 0; } // 设置 SP_DEVICE_INTERFACE_DATA 大小 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (i=0; ;i++) { // 列举接口信息 BOOL bResult = SetupDiEnumDeviceInterfaces( NewDeviceInfoSet, NULL, InterfaceClassGuid, i, &DeviceInterfaceData ); if(!bResult) { if ( GetLastError()!=NO_ERROR && GetLastError()!=ERROR_NO_MORE_ITEMS ) { printf("ERROR: (%d)",GetLastError()); return FALSE; } break; } else { // 为PSP_DEVICE_INTERFACE_DETAIL_DATA结构分配内存,填充 lpDeviceInterfaceDetailData = HeapAlloc( GetProcessHeap(), 0, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)); lpDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); dwBufferSize = lpDeviceInterfaceDetailData->cbSize; // 获得接口详细信息 while(!SetupDiGetDeviceInterfaceDetail( NewDeviceInfoSet, &DeviceInterfaceData, lpDeviceInterfaceDetailData, dwBufferSize, &dwBufferSize, NULL)) { // 如果内存空间不足,再次分配,直到可以成功调用 if(ERROR_INSUFFICIENT_BUFFER==GetLastError()) { lpDeviceInterfaceDetailData = HeapReAlloc( GetProcessHeap(), 0, lpDeviceInterfaceDetailData, dwBufferSize); lpDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); } } // 显示信息 printf("DevicePath: %s\n",lpDeviceInterfaceDetailData->DevicePath); // lpDeviceInterfaceDetailData->DevicePath可作为CreateFile的参数,进行IO控制 // 释放内存 HeapFree(GetProcessHeap(),0,lpDeviceInterfaceDetailData); } } SetupDiDestroyDeviceInfoList(DeviceInfoSet); return TRUE; } /************************************* * BOOL EnumAllDevice( ) * 功能 列举当前存在的设备 * 返回值 是否成功 **************************************/ BOOL EnumAllDevice() { HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData; DWORD i; printf("Displaying the Installed Devices\n\n"); // 得到所有设备 HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, 0, // 无类型 0, // 无回调函数 DIGCF_PRESENT | DIGCF_ALLCLASSES ); if (hDevInfo == INVALID_HANDLE_VALUE) { return FALSE; } // 循环列举 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i, &DeviceInfoData);i++) { DWORD DataT; LPTSTR buffer = NULL; DWORD buffersize = 0; // 获取详细信息 while (!SetupDiGetDeviceRegistryProperty( hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buffer, buffersize, &buffersize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // 内存不足 if (buffer) HeapFree(GetProcessHeap(), 0, buffer); buffer = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, buffersize); } else break; } // 输出 printf("GUID:{%.8X-%.4X-%.4X--%.2X%.2X-%.2X%.2X%.2X%.2X%.2X%.2X} " "Device: %s\n", DeviceInfoData.ClassGuid.Data1, DeviceInfoData.ClassGuid.Data2, DeviceInfoData.ClassGuid.Data3, DeviceInfoData.ClassGuid.Data4[0], DeviceInfoData.ClassGuid.Data4[1], DeviceInfoData.ClassGuid.Data4[2], DeviceInfoData.ClassGuid.Data4[3], DeviceInfoData.ClassGuid.Data4[4], DeviceInfoData.ClassGuid.Data4[5], DeviceInfoData.ClassGuid.Data4[6], DeviceInfoData.ClassGuid.Data4[7],buffer); if (buffer) HeapFree(GetProcessHeap(), 0, buffer); } if ( GetLastError()!=NO_ERROR && GetLastError()!=ERROR_NO_MORE_ITEMS ) { return FALSE; } // 释放 SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE; } int main( int argc, char *argv[ ], char *envp[ ] ) { // 列举所有设备 printf("Enumerating All Device\n\n"); EnumAllDevice(); // 列举磁盘分卷驱动器设备 printf("\n\nEnumerating Present Volume \n\n"); EnumClassDevice(&GUID_DEVINTERFACE_VOLUME); return 0; }