利用SetupAPI实现遍历设备管理器

因为项目需要,需要遍历设备管理器,找了很多资料,结果发现还是使用SetupAPI来实现比较靠谱,其本质是读取注册表的内容,当然也可以通过遍历注册表来实现,当然这样会比较麻烦。

/*********************************
* 枚举所有设备信息
* @int index[in] 枚举设备时的序号
* @LPTSTR lpDeviceClassName[out] 设备的Class,对应注册表中的Class的值
* @LPTSTR lpDeviceClassDesc[out] 设备描述,对应注册表的默认值
* @BOOL*  bDevicePresent         设备是否存在 
*********************************/
BOOL CGetComputerInfo::EnumDeviceClasses(int index,LPTSTR lpDeviceClassName,
                       LPTSTR lpDeviceClassDesc,BOOL* bDevicePresent)
{
    BOOL bRet = FALSE;
    GUID ClassGuid;
    HDEVINFO hNewDeviceInfoSet = INVALID_HANDLE_VALUE;//设备信息集
    int result;
    BOOL bResNam = FALSE;
    LPTSTR lpClassName = NULL;
    HKEY hKeyClass = NULL;
    ULONG RequiredSize = MAX_PATH;
    WCHAR* name = NULL;

    __try
    {
        ZeroMemory(&ClassGuid, sizeof(GUID));

        //按index顺序枚举设备列表,获取设备UID
        //对应注册表路径:"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\"
        result = CM_Enumerate_Classes(index, &ClassGuid, 0);
        if(result != CR_SUCCESS)
        {
            return FALSE;
        }
        
        //根据GUID获得设备名
        name = new WCHAR[MAX_PATH];
        bResNam = SetupDiClassNameFromGuid(&ClassGuid, name, RequiredSize, &RequiredSize);
        if(RequiredSize > 0)
        {
            delete [] name;
            name = NULL;
            name = new WCHAR[RequiredSize];
            bResNam = SetupDiClassNameFromGuid(&ClassGuid, name, RequiredSize, &RequiredSize);
        }
        
        //根据GUID返回device information Handle(HDEVINFO)
        hNewDeviceInfoSet = SetupDiGetClassDevs(&ClassGuid, 0, NULL, DIGCF_PRESENT);
        if (hNewDeviceInfoSet == INVALID_HANDLE_VALUE)
        {  
            *bDevicePresent = FALSE;
            StringCchCopy(lpDeviceClassName,MAX_PATH,name);
            return FALSE;
        }
        
        //打开device setup class registry key
        hKeyClass = SetupDiOpenClassRegKeyEx(&ClassGuid, MAXIMUM_ALLOWED,DIOCR_INSTALLER,NULL, 0);
        if (hKeyClass == INVALID_HANDLE_VALUE)
        {  
            *bDevicePresent = FALSE;
            StringCchCopy(lpDeviceClassName,MAX_PATH,name);
            return FALSE;

        }
        else
        {
            LONG dwSize = MAX_PATH;
            //读取注册表默认值
            LONG res = RegQueryValue(hKeyClass, NULL, lpDeviceClassDesc, &dwSize);
            if (res != ERROR_SUCCESS)
            {
                StringCchCopy(lpDeviceClassDesc,MAX_PATH,_T(""));
                return FALSE;
            }
        }

        StringCchCopy(lpDeviceClassName,MAX_PATH,name);
        *bDevicePresent =TRUE;
        bRet = TRUE;
    }
    __finally
    {
        if(name)
        {
            delete [] name;
            name = NULL;
        }
        if(hKeyClass)
        {
            RegCloseKey(hKeyClass);
            hKeyClass = NULL;
        }
        if(hNewDeviceInfoSet)
        {
            SetupDiDestroyDeviceInfoList(hNewDeviceInfoSet);
            hNewDeviceInfoSet = NULL;
        }  
    }
    return bRet;
}

/*********************************
* 获取设备具体名,若具有多个名,通过index进行枚举
* @int index[in] 枚举设备名时的序号
* @LPTSTR DeviceClassName[out]   设备的Class,对应注册表中的Class的值
* @LPTSTR DeviceName[out] 设备具体名字,详见设备管理器 
*********************************/
DWORD CGetComputerInfo::EnumDevices(int index, LPTSTR DeviceClassName, LPTSTR DeviceName)
{
    ULONG RequiredSize = 0;
    //GUID guid;
    //ZeroMemory(&guid, sizeof(GUID));
    GUID* guids = new GUID[1];

    HDEVINFO hNewDeviceInfoSet = INVALID_HANDLE_VALUE;
    SP_DEVINFO_DATA DeviceInfoData;

    //获取GUIDS大小
    BOOL res=SetupDiClassGuidsFromName(DeviceClassName, &guids[0], RequiredSize, &RequiredSize);
    if (RequiredSize==0)
    {
        StringCchCopy(DeviceName,MAX_PATH, _T(""));
        delete [] guids;
        guids = NULL;
        return CSIERROR_GUIDSFAILED;
    }
    if (!res)
    {
        delete [] guids;
        guids=new GUID[RequiredSize];
        
        //获取GUID的名字
        res=SetupDiClassGuidsFromName(DeviceClassName, &guids[0], RequiredSize, &RequiredSize);
        if (!res || RequiredSize==0)
        {
            StringCchCopy(DeviceName,MAX_PATH, _T(""));
            delete [] guids;
            guids = NULL;
            return CSIERROR_GUIDSFAILED;
        }
    }

    //返回设备信息句柄
    hNewDeviceInfoSet=SetupDiGetClassDevs(&guids[0], 0, NULL, DIGCF_PRESENT );
    if(hNewDeviceInfoSet == INVALID_HANDLE_VALUE)
    {
        delete [] guids;
        guids = NULL;
        return CSIERROR_INVALID_HANDLE;
    }

    //初始化SP_DEVINFO_DATA结构
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    DeviceInfoData.DevInst=0;
    ZeroMemory(&DeviceInfoData.ClassGuid, sizeof(GUID));
    DeviceInfoData.Reserved=0;

    //根据HDEVINFO返回要枚举设备的信息
    res=SetupDiEnumDeviceInfo(hNewDeviceInfoSet, index, &DeviceInfoData);
    if (!res) 
    {
        //设备不存在,销毁枚举设备信息的句柄
        SetupDiDestroyDeviceInfoList(hNewDeviceInfoSet);
        hNewDeviceInfoSet = INVALID_HANDLE_VALUE;
        StringCchCopy(DeviceName,MAX_PATH, _T(""));
        delete [] guids;
        guids = NULL;
        return CSIERROR_NO_DEVICE;
    }
    
    // 返回设备具体名
    if (!SetupDiGetDeviceRegistryProperty(hNewDeviceInfoSet, &DeviceInfoData,
        SPDRP_FRIENDLYNAME, 0, (BYTE*) DeviceName, 
        MAX_PATH, NULL))
    {
        res = SetupDiGetDeviceRegistryProperty(hNewDeviceInfoSet, &DeviceInfoData,
            SPDRP_DEVICEDESC, 0, (BYTE*) DeviceName,
            MAX_PATH, NULL);
        if (!res)
        {
            //设备名获取失败
            SetupDiDestroyDeviceInfoList(hNewDeviceInfoSet);
            hNewDeviceInfoSet = INVALID_HANDLE_VALUE;
            StringCchCopy(DeviceName,MAX_PATH, _T(""));
            delete [] guids;
            guids = NULL;
            return CSIERROR_GETDEVICENAME;
        }
    }
    delete [] guids;
    guids = NULL;
    SetupDiDestroyDeviceInfoList(hNewDeviceInfoSet);
    hNewDeviceInfoSet = INVALID_HANDLE_VALUE;
    return CSIERROR_OK;
}



你可能感兴趣的:(VC++)