• DDK


    想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些API函数,就像本文描述的,采用的API函数就是SetupDi系列的函数。不过这类函数有很多,具体的请参见MSDN,而实现设备启用、停用仅需要用到的就只有5个函数:
           SetupDiGetClassDevs                   // 获取设备信息集
           SetupDiEnumDeviceInfo                 // 从设备信息集中枚举每个设备的具体信息
           SetupDiGetDeviceRegistryProperty      // 从注册表中读取PnP设备的属性
           SetupDiSetClassInstallParams          // 设置(包括取消)设备类的安装参数
           SetupDiCallClassInstaller             // 安装指定设备
    以上函数均在setupapi.h头文件中声明,该头文件包含在setupapi.lib函数库中(使用以上函数前需要声明这个头文件)。

    接下来就是如何实现设备的启用与停用。
    从原理上讲,设备的启用与停用其实就是对该设备进行重安装。

    首先,我们需要声明两个变量用来保存指定设备类的属性信息:
        HDEVINFO        m_hDevInfo;              // 类似设备句柄,以下暂且称为设备句柄
        SP_DEVINFO_DATA m_DeviceInfoData;        // 设备详细属性信息

    然后调用SetupDiGetClassDevs函数获取设备句柄的值。(在这个函数中,需要指定设备类的GUID,如果不清楚这个GUID,可以在相应的安装文件.inf中查找。注意:设备类的GUID,不是设备的GUID!)

    接着循环使用SetupDiEnumDeviceInfo函数枚举对应设备类中的设备,并使用SetupDiGetDeviceRegistryProperty函数获取得到的设备的详细信息,进行判断是否为所需的设备(判断的方式有多种,具体参考MSDN,本文采用设备描述进行判断)。
    一旦枚举结束(即枚举不成功,而且用GetLastError()可以得到错误码259)即可退出循环。当然如果找到设备,即可break退出。

    如果找到对应的设备,就调用SetupDiSetClassInstallParams函数设置安装的属性。这里有个注意的地方需要详细说明一下:
    SetupDiSetClassInstallParams的函数原型如下:
    WINSETUPAPI BOOL WINAPI
      SetupDiSetClassInstallParams(
        IN HDEVINFO  DeviceInfoSet,
        IN PSP_DEVINFO_DATA  DeviceInfoData,  OPTIONAL
        IN PSP_CLASSINSTALL_HEADER  ClassInstallParams,  OPTIONAL
        IN DWORD  ClassInstallParamsSize
        );
    注意第三个参数PSP_CLASSINSTALL_HEADER  ClassInstallParams,
    这里我们不采用这个结构,而是采用另外一个结构:SP_PROPCHANGE_PARAMS
    并在这个结构中,
    设置ClassInstallHeader字段中(我们发现这个字段也是一个结构,就是PSP_CLASSINSTALL_HEADER结构)的InstallFunction字段值为DIF_PROPERTYCHANGE,
    设置StateChange值为DICS_ENABLE(该值为启用,若是停用则为DICS_DISABLE)
    然后采用强行转换将其转为PSP_CLASSINSTALL_HEADER结构。

    最后,调用SetupDiCallClassInstaller函数执行设备的安装(即:启用或者停用),注意该函数第一个参数值应为DIF_PROPERTYCHANGE。
    从设备管理器中,可以验证我们的做法。

    ON_WM_DEVICECHANGE() 消息可以检测到设备插拔

    BOOL CDirverDemoDlg::OnDeviceChange( UINT nEventType, DWORD dwData )
    {
     m_mobileDevice.Analysis();
     if(nEventType == DBT_DEVICEARRIVAL)         //插入事件
      //AfxMessageBox(_T("插入设置")) ;
     if(nEventType == DBT_DEVICEREMOVECOMPLETE)    //弹出事件
      //AfxMessageBox(_T("弹出设置")) ;
     return TRUE;

    }

    Windows设备的具体属性

    #define SPDRP_DEVICEDESC                  (0x00000000) 

    // DeviceDesc (R/W)

    //设备描述,如:Realtek RTL8139 Family PCI Fast Ethernet NIC,Intel(R) PRO/100 VE Network Connection
    #define SPDRP_HARDWAREID                  (0x00000001) 

    // HardwareID (R/W)

    //硬件ID(如:PCI/VEN_10EC&DEV_8139&SUBSYS_813910EC&REV_10,PCI/VEN_10EC&DEV_8139&SUBSYS_813910EC&REV_10, PCI/VEN_8086&DEV_1039&SUBSYS_026A1014&REV_81)
    #define SPDRP_COMPATIBLEIDS               (0x00000002) 

    // CompatibleIDs (R/W)

    (如:PCI/VEN_10EC&DEV_8139&REV_10,PCI、VEN_8086&DEV_1039&REV_81)
    #define SPDRP_NTDEVICEPATHS               (0x00000003) 

    // Unsupported, DO NOT USE
    #define SPDRP_SERVICE                     (0x00000004) 

    // Service (R/W)

    (如:rtl8139、E100B)
    #define SPDRP_CONFIGURATION               (0x00000005) 

    // Configuration (R)

    (如:其它)
    #define SPDRP_CONFIGURATIONVECTOR         (0x00000006) 

    // ConfigurationVector (R)

    (如:其它)
    #define SPDRP_CLASS                       (0x00000007) 

    // Class (R--tied to ClassGUID)

    (如:Net)
    #define SPDRP_CLASSGUID                   (0x00000008) 

    // ClassGUID (R/W)

    //设备的类别标识(如:网卡{4D36E972-E325-11CE-BFC1-08002BE10318})
    #define SPDRP_DRIVER                      (0x00000009) 

    // Driver (R/W)

    //(如:{4D36E972-E325-11CE-BFC1-08002BE10318}/0016)
    #define SPDRP_CONFIGFLAGS                 (0x0000000A) 

    // ConfigFlags (R/W)

    (如:其它)
    #define SPDRP_MFG                         (0x0000000B) 

    // Mfg (R/W)

    //供应商的名称
    #define SPDRP_FRIENDLYNAME                (0x0000000C) 

    // FriendlyName (R/W)

    //直观的名字
    #define SPDRP_LOCATION_INFORMATION        (0x0000000D) 

    // LocationInformation (R/W)

    //本地环境属性(如:PCI 总线 2、设备 10、功能 0)
    #define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME (0x0000000E) 

    // PhysicalDeviceObjectName (R)

    //(如:/Device/NTPNP_PCI0012)
    #define SPDRP_CAPABILITIES                (0x0000000F) 

    // Capabilities (R)

    (如:其它)
    #define SPDRP_UI_NUMBER                   (0x00000010) 

    // UiNumber (R)

    (如:其它)
    #define SPDRP_UPPERFILTERS                (0x00000011) 

    // UpperFilters (R/W)

    (如:其它)
    #define SPDRP_LOWERFILTERS                (0x00000012) 

    // LowerFilters (R/W)

    (如:其它)
    #define SPDRP_MAXIMUM_PROPERTY            (0x00000013) 

    // Upper bound on ordinals

    (如:其它)

      GUID_DEVCLASS_FDC 软盘控制器

      GUID_DEVCLASS_DISPLAY 显示卡

      GUID_DEVCLASS_CDROM 光驱

      GUID_DEVCLASS_KEYBOARD 键盘

      GUID_DEVCLASS_COMPUTER 计算机

      GUID_DEVCLASS_SYSTEM 系统

      GUID_DEVCLASS_DISKDRIVE 磁盘驱动器

      GUID_DEVCLASS_MEDIA 声音、视频和游戏控制器

      GUID_DEVCLASS_MODEMMODEM

      GUID_DEVCLASS_MOUSE 鼠标和其他指针设备

      GUID_DEVCLASS_NET 网络设备器

      GUID_DEVCLASS_USB 通用串行总线控制器

        GUID_DEVCLASS_FLOPPYDISK 软盘驱动器

      GUID_DEVCLASS_UNKNOWN 未知设备

      GUID_DEVCLASS_SCSIADAPTER  SCSI 和 RAID 控制器

      GUID_DEVCLASS_HDCIDE  ATA/ATAPI 控制器

      GUID_DEVCLASS_PORTS端口 (COM 和 LPT)

      GUID_DEVCLASS_MONITOR 监视器


  • 相关阅读:
    02HTML和CSS知识点总结(二)
    个人对stm32ADC编程关键点的理解
    stm32_ADC定时器采样(DMA均值处理数据)
    使用AD画PCB的技能总结(纯属个人笔记,请大神多多指导)
    STM32_DAC之软件触发(Trigger)
    对stm32寄存器的理解(个人理解,大神轻喷)
    3.13考研长难句分析
    3.14考研长难句分析
    用stm32f10x建立新的工程或移植工程重要步骤
    mac air 上的Linux命令训练(1)
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693636.html
Copyright © 2020-2023  润新知