通过SetupAPI扫描/禁用/恢复设备(转)

来源:互联网 发布:app软件需求说明书 编辑:程序博客网 时间:2024/05/17 06:47

//不记得从哪儿看到的,觉得不错,就贴下来了

#include <stdafx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <TCHAR.H>
#include <SetupAPI.h>
#include <cfgmgr32.h>   // cfgmgr32.h 在Microsoft Windows 2000 DDK 中.
#include <regstr.h>
#pragma comment(lib,"setupapi.lib")

#define UNKNOWNDEVICE _T("<Unknown Device>")
typedef struct _DEVICE_INFO
{
    SP_DEVINFO_DATA        DevInfoData;        //设备信息包括实例句柄和设备类的GUID
    DWORD                DevID;                //在此次全局的枚举中设备ID
    TCHAR                *lpszDevName;        //设备的名称
    ULONG                ulDevNameLen;        //设备名称的长度
    BOOL                bDisableable;        //是否可以被禁用
    BOOL                bDisabled;            //是否已经被禁用
    struct _DEVICE_INFO    *pNextDevInfo;    //下一个结构块
}
DEVICE_INFO,*LPDEVICE_INFO;

DEVICE_INFO    DevInfo; //设备链表头

BOOL IsDisableable(DWORD dwDevID, HDEVINFO hDevInfo) ;
BOOL IsDisabled(DWORD dwDevID, HDEVINFO hDevInfo) ;
BOOL StateChange( DWORD dwNewState, DWORD dwDevID, HDEVINFO hDevInfo) ;

//////////////////////////////////////////////////////////////////////////
// 获得设备注册表中的内容
//////////////////////////////////////////////////////////////////////////
BOOL GetRegistryProperty( HDEVINFO DeviceInfoSet,
                        PSP_DEVINFO_DATA DeviceInfoData,
                        ULONG Property,
                        PVOID Buffer,
                        PULONG Length )
{
    while ( !SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
                                               DeviceInfoData,
                                               Property,
                                               NULL,
                                               (BYTE *)*(TCHAR **)Buffer,
                                               *Length,
                                               Length))
    {
        // 长度不够则重新分配缓冲区
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            if (*(LPTSTR *)Buffer)
                LocalFree(*(LPTSTR *)Buffer);

            *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR,*Length);
        }
        else
        {
            return false;
        }
    }

    return (BOOL)(*(LPTSTR *)Buffer)[0];
}

BOOL EnableDevice(DWORD dwDevID, HDEVINFO hDevInfo)
{
    return StateChange(DICS_ENABLE,dwDevID,hDevInfo);
}

BOOL DisableDevice(DWORD dwDevID, HDEVINFO hDevInfo)
{
    return StateChange(DICS_DISABLE,dwDevID,hDevInfo);
}

BOOL ControlDevice(DWORD dwDevID, HDEVINFO hDevInfo)
{
    BOOL bCanDisable;
    bCanDisable = (IsDisableable(dwDevID,hDevInfo) && (!IsDisabled(dwDevID,hDevInfo)));
    if(bCanDisable)
        return DisableDevice(dwDevID,hDevInfo);
    else
        return EnableDevice(dwDevID,hDevInfo);
}

void EnumNetCards()
{        
   
    DWORD Status, Problem;
    LPTSTR Buffer = NULL;
    DWORD BufSize = 0;

    // 返回所有设备信息
    HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES) ;

    if (INVALID_HANDLE_VALUE == hDevInfo )       
        return; 
    SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)}; 
    //////////////////////////////////////////////////////////////////////////
    // 枚举设备
    //////////////////////////////////////////////////////////////////////////
    for ( DWORD DeviceId=0;
        SetupDiEnumDeviceInfo( hDevInfo,DeviceId,&DeviceInfoData);
        DeviceId++)
    { 
        // 获得设备的状态
        if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst ,0) != CR_SUCCESS)
            continue; 
        // 获取设备类名
        TCHAR szDevName [MAX_PATH] = _T("") ;
        if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS , &Buffer, (PULONG)&BufSize))
        {
            lstrcpyn( szDevName, Buffer, MAX_PATH ) ;           
        }
        if ( lstrcmp( szDevName, _T("Net") ) == 0 )           
        {            
            TCHAR szName [MAX_PATH] = _T("") ;
            if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME , &Buffer, (PULONG)&BufSize))
            {
                lstrcpyn( szName, Buffer, MAX_PATH ) ;
            }
            if ( lstrcmp( szName, _T("ROOT") ) != 0 )               
            {

                if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER , &Buffer, (PULONG)&BufSize))
                {
                    lstrcpyn( szName, Buffer, MAX_PATH ) ;
                    // 获取设备描述
                    if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC , &Buffer, (PULONG)&BufSize))
                    {
                        lstrcpyn( szName, Buffer, MAX_PATH ) ;
                        if(ControlDevice(DeviceId,hDevInfo))
                        {
                            printf("Successful/n");
                        }
                        else
                        {
                            printf("FAILED/n");       
                        }
                    }                   
                }
            }
        }
    } 
    SetupDiDestroyDeviceInfoList(hDevInfo);
}



BOOL StateChange( DWORD dwNewState, DWORD dwDevID, HDEVINFO hDevInfo)
{
    SP_PROPCHANGE_PARAMS PropChangeParams;
    SP_DEVINFO_DATA        DevInfoData = {sizeof(SP_DEVINFO_DATA)};
    SP_DEVINSTALL_PARAMS devParams;


    //查询设备信息
    if (!SetupDiEnumDeviceInfo( hDevInfo, dwDevID, &DevInfoData))
    {
        OutputDebugString("SetupDiEnumDeviceInfo FAILED");
        return FALSE;
    }


    //设置设备属性变化参数
    PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
    PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
    PropChangeParams.Scope = DICS_FLAG_GLOBAL; //使修改的属性保存在所有的硬件属性文件
    PropChangeParams.StateChange = dwNewState;
    PropChangeParams.HwProfile = 0;

    //改变设备属性
    if (!SetupDiSetClassInstallParams( hDevInfo,
                                        &DevInfoData,
                                        (SP_CLASSINSTALL_HEADER *)&PropChangeParams,
                                        sizeof(PropChangeParams)))
    {
        OutputDebugString("SetupDiSetClassInstallParams FAILED");
        return FALSE;
    }
    
    PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
    PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
    PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;//使修改的属性保存在指定的属性文件
    PropChangeParams.StateChange = dwNewState;
    PropChangeParams.HwProfile = 0;

    //改变设备属性并调用安装服务
    if (!SetupDiSetClassInstallParams( hDevInfo,
                                       &DevInfoData,
                                       (SP_CLASSINSTALL_HEADER *)&PropChangeParams,
                                       sizeof(PropChangeParams)) ||
        !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DevInfoData))
    {
        OutputDebugString("SetupDiSetClassInstallParams or SetupDiCallClassInstaller FAILED");
        return TRUE;
    }
    else
    {
        //判断是否需要重新启动
        devParams.cbSize = sizeof(devParams);
        if (!SetupDiGetDeviceInstallParams( hDevInfo, &DevInfoData, &devParams))
        {
            OutputDebugString("SetupDiGetDeviceInstallParams FAILED");
            return FALSE;
        }

        if (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))
        {
            OutputDebugString("Need Restart Computer");
            return TRUE;
        }
        return TRUE;
    }
}

BOOL IsDisableable(DWORD dwDevID, HDEVINFO hDevInfo)
{
    SP_DEVINFO_DATA DevInfoData = {sizeof(SP_DEVINFO_DATA)};
    DWORD    dwDevStatus,dwProblem;
    if(!SetupDiEnumDeviceInfo(hDevInfo,dwDevID,&DevInfoData))
    {
        OutputDebugString("SetupDiEnumDeviceInfo FAILED");
        return FALSE;
    }
    //查询设备状态
    if(CM_Get_DevNode_Status(&dwDevStatus,&dwProblem,DevInfoData.DevInst,0)!=CR_SUCCESS)
    {
        OutputDebugString("CM_GET_DevNode_Status FAILED");
        return FALSE;
    }
    return ((dwDevStatus & DN_DISABLEABLE) && (dwProblem != CM_PROB_HARDWARE_DISABLED));
}

BOOL IsDisabled(DWORD dwDevID, HDEVINFO hDevInfo)
{
    SP_DEVINFO_DATA DevInfoData = {sizeof(SP_DEVINFO_DATA)};
    DWORD    dwDevStatus,dwProblem;
    if(!SetupDiEnumDeviceInfo(hDevInfo,dwDevID,&DevInfoData))
    {
        OutputDebugString("SetupDiEnumDeviceInfo FAILED");
        return FALSE;
    }

    //查询设备状态
    if(CM_Get_DevNode_Status(&dwDevStatus,&dwProblem,DevInfoData.DevInst,0)!=CR_SUCCESS)
    {
        OutputDebugString("CM_GET_DevNode_Status FAILED");
        return FALSE;
    }
    return ((dwDevStatus & DN_HAS_PROBLEM) && (dwProblem == CM_PROB_DISABLED));
}

void GuidCopy(GUID guidSrc, GUID *guidDest)
{
    guidDest->Data1 = guidSrc.Data1;
    guidDest->Data2 = guidSrc.Data2;
    guidDest->Data3 = guidSrc.Data3;
    memcpy(guidDest->Data4,guidSrc.Data4,8);
}

BOOL ConstructDeviceName(HDEVINFO DevInfoSet, PSP_DEVINFO_DATA DevInfoData, PVOID pBuffer, PULONG Length)
{
    //尝试通过各种类型的设备描述获得其设备名称
    if (!GetRegistryProperty( DevInfoSet,
                            DevInfoData,
                            SPDRP_FRIENDLYNAME ,            //设备的现实名称
                            pBuffer,
                            Length))
    {
        if (!GetRegistryProperty( DevInfoSet,
                                DevInfoData,
                                SPDRP_DEVICEDESC ,        //设备的描述
                                pBuffer,
                                Length))
        {
            if (!GetRegistryProperty( DevInfoSet,
                                    DevInfoData,
                                    SPDRP_CLASS ,            //设备类名
                                    pBuffer,
                                    Length))
            {
                if (!GetRegistryProperty( DevInfoSet,
                                        DevInfoData,
                                        SPDRP_CLASSGUID ,    //设备的GUID
                                        pBuffer,
                                        Length))
                {
                    //什么都没找到就返回UnknownDevice
                    *Length = (lstrlen(UNKNOWNDEVICE)+1)*sizeof(TCHAR);
                    *(LPTSTR *)pBuffer = (PCHAR)LocalAlloc(LPTR,*Length);
                    _tcscpy(*(LPTSTR *)pBuffer,UNKNOWNDEVICE);
                }
            }
        }
    }
    return TRUE;
}

BOOL EnumDevices(HDEVINFO hDevInfo)
{
    DWORD dwDevID ; //, dwStatus, dwProblem;
    SP_DEVINFO_DATA DevInfoData = {sizeof(SP_DEVINFO_DATA)};
    LPDEVICE_INFO    pDevInfo, pPreDevInfo;
    TCHAR            *DeviceName = NULL ;
    ULONG            ulNameLen = 256;
   
    pPreDevInfo = &DevInfo;

    //穷举每个设备
    for(dwDevID = 0;SetupDiEnumDeviceInfo(hDevInfo,dwDevID,&DevInfoData);dwDevID++)
    {
        //构造设备信息块
        pDevInfo = (LPDEVICE_INFO)malloc(sizeof(DEVICE_INFO));

        pDevInfo->pNextDevInfo = NULL;
        pDevInfo->DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        pDevInfo->ulDevNameLen;
        pDevInfo->DevID = dwDevID;
        GuidCopy(DevInfoData.ClassGuid,&pDevInfo->DevInfoData.ClassGuid);
        pDevInfo->DevInfoData.DevInst = DevInfoData.DevInst;
        pDevInfo->DevInfoData.Reserved = DevInfoData.Reserved;


        //这里有个问题,如果用设备信息块结构中的字符串指针
        //SetupDiGetDeviceRegistyProperty函数就会返回数据无效,不知道为什么。
        //所以下面只能在重新复制一遍了。
        ConstructDeviceName(hDevInfo,&DevInfoData,&DeviceName,&ulNameLen);
        pDevInfo->ulDevNameLen = ulNameLen;
        pDevInfo->lpszDevName = (TCHAR *)malloc(ulNameLen*sizeof(TCHAR));
        memcpy(pDevInfo->lpszDevName,DeviceName,ulNameLen);
        pDevInfo->bDisableable = IsDisableable(dwDevID, hDevInfo);
        pDevInfo->bDisabled = IsDisabled(dwDevID, hDevInfo);
        pPreDevInfo->pNextDevInfo = pDevInfo;
        pPreDevInfo = pDevInfo;
    }
    return FALSE;
}

int main(int argc, char* argv[])
{   
    HDEVINFO    hDevInfo = NULL ;
    LPDEVICE_INFO pDevInfo = NULL ;

    EnumNetCards() ;
    return 0 ;
    //返回设备信息
    hDevInfo = SetupDiGetClassDevs(NULL,NULL,NULL,DIGCF_PRESENT|DIGCF_ALLCLASSES);
    
    DevInfo.DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    DevInfo.ulDevNameLen = 256;
    DevInfo.pNextDevInfo = NULL;
   
    //枚举系统设备
    EnumDevices(hDevInfo);
    pDevInfo = DevInfo.pNextDevInfo;
    while(pDevInfo)
    {
        //从系统设备中查找usb mass storage设备
        TCHAR szDebugStr [512] = _T("") ;
        _stprintf(szDebugStr,"DevID : %d GUID:%x-%x-%x-%x%x%x%x%x%x%x%x DevInst : %x,DevName:%s IsDisableable:%d, IsDisabled:%d"
            ,pDevInfo->DevID
            ,pDevInfo->DevInfoData.ClassGuid.Data1
            ,pDevInfo->DevInfoData.ClassGuid.Data2
            ,pDevInfo->DevInfoData.ClassGuid.Data3
            ,pDevInfo->DevInfoData.ClassGuid.Data4[0]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[1]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[2]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[3]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[4]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[5]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[6]
            ,pDevInfo->DevInfoData.ClassGuid.Data4[7]
            ,pDevInfo->DevInfoData.DevInst
            ,pDevInfo->lpszDevName
            ,pDevInfo->bDisableable
            ,pDevInfo->bDisabled);
        OutputDebugString(szDebugStr);

        printf( "Device name=%s/n", pDevInfo->lpszDevName ) ;
       
        pDevInfo = pDevInfo->pNextDevInfo;
    }
    SetupDiDestroyDeviceInfoList(hDevInfo);

    return 0 ;
}

原创粉丝点击