c++ - 为什么某些设备不使用 SetupDiGetDeviceInterfaceDetail() 进行枚举?

标签 c++ winapi driver

我正在维护一个应用程序,该应用程序使用 SetupDiGetDeviceInterfaceDetail() 来查找有关计算机上已安装串行端口的信息。我在测试时注意到有些设备(例如我的 Lucent WinModem)没有出现在该枚举中。事实证明,我公司生产的一组实现串行端口接口(interface)的设备也遇到了类似的问题。我的假设是设备的 INF 文件中缺少某些内容。有谁知道什么样的情况会导致这种遗漏?

编辑:这是我用来枚举串行端口的代码示例。我尝试了各种标志组合,但没有发现任何明显的行为差异。

DEFINE_GUID(GUID_CLASS_COMPORT, 0x4d36e978, 0xe325, 0x11ce, 0xbf, 0xc1, \
            0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);


GUID *serial_port_guid = const_cast<GUID *>(&GUID_CLASS_COMPORT);
HDEVINFO device_info = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA *detail_data = 0;

device_info = SetupDiGetClassDevs(
   serial_port_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(device_info != INVALID_HANDLE_VALUE)
{
   uint4 const detail_data_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
   detail_data = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA *>(new char[detail_data_size]);
   SP_DEVICE_INTERFACE_DATA ifc_data;
   bool more_interfaces = true;
   int rcd;
   memset(&ifc_data, 0, sizeof(ifc_data)); 
   memset(detail_data, 0, detail_data_size);
   ifc_data.cbSize = sizeof(ifc_data);
   detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
   for(uint4 index = 0; more_interfaces; ++index)
   {
      rcd = SetupDiEnumDeviceInterfaces(device_info, 0, serial_port_guid, index, &ifc_data);
      if(rcd)
      {
         // we need to get the details of this device
         SP_DEVINFO_DATA device_data = { sizeof(SP_DEVINFO_DATA) };
         rcd = SetupDiGetDeviceInterfaceDetail(
            device_info, &ifc_data, detail_data, detail_data_size, 0, &device_data);
         if(rcd)
         {
            StrAsc device_path(detail_data->DevicePath);
            byte friendly_name[256];

            rcd = SetupDiGetDeviceRegistryProperty(
               device_info, &device_data, SPDRP_FRIENDLYNAME, 0, friendly_name, sizeof(friendly_name), 0);
            if(rcd)
            {
               std::for_each(
                  port_names.begin(),
                  port_names.end(),
                  update_friendly_name(
                     reinterpret_cast<char const *>(friendly_name)));
            }
         }
         else
            more_interfaces = false;
      }
   }
}

最佳答案

这更多是关于问题的问题。当您调用该函数时,您传入的第一个参数应该是您可能从 SetupDiGetClassDevs 中获得的 DeviceInfoSet。功能。当您调用 SetupDiGetClassDevs 函数时,您为标志指定了什么(最后一个参数)在该函数上引用 Microsoft 的页面:

DIGCF_ALLCLASSES Return a list of installed devices for all device setup classes or all device interface classes.

DIGCF_DEVICEINTERFACE Return devices that support device interfaces for the specified device interface classes. This flag must be set in the Flags parameter if the Enumerator parameter specifies a device instance ID.

DIGCF_DEFAULT Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes.

DIGCF_PRESENT Return only devices that are currently present in a system.

DIGCF_PROFILE Return only devices that are a part of the current hardware profile.

根据您的选择,设备列表会发生变化。例如,Present 标志只会显示主动插入的设备。


更新:感谢您提供示例代码。

我现在的问题是,如果您想知道调制解调器的友好名称,为什么不使用相同的调用而是指定调制解调器 Guid 而不是 COM 端口?我的调制解调器 GUID 是 4D36E96D-E325-11CE-BFC1-08002BE10318

在注册表中,我可以看到一个名为“AttachedTo”的值,它指定了一个 COM 端口。我将不得不研究在 API 中绑定(bind)到哪个属性。注册表项位于

HKLM\SYSTEM\CurrentControlSet\Control\Class{4D36E96D-E325-11CE-BFC1-08002BE10318}\


另一个更新:

仔细查看示例代码。基于此,如果您尝试获取应返回 SP_DEVICE_INTERFACE_DETAIL_DATA 的设备接口(interface)类结构。这不会提供获取设备友好名称的方法。我相信您会想要设备实例。

据我所知,设备接口(interface)用于获取可用于写入的设备路径。

我为测试您的代码所做的一件事是再次尝试磁盘设备接口(interface)。我做了一些更改以使其在我的系统上运行,但仍未完全完成。我认为一个问题(可能更多)是我需要在 SetupDiGetDeviceInterfaceDetail 调用之间调整 DevicePath 变量的大小。

void Test()
{

GUID *serial_port_guid = const_cast<GUID *>(&GUID_DEVINTERFACE_DISK);
HDEVINFO device_info = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA detail_data;

device_info = SetupDiGetClassDevs(
   serial_port_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(device_info != INVALID_HANDLE_VALUE)
{
   //uint4 const detail_data_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);// + 256;
   //detail_data = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA *>(new char[detail_data_size]);
   SP_DEVICE_INTERFACE_DATA ifc_data;
   bool more_interfaces = true;
   int rcd;
   memset(&ifc_data, 0, sizeof(ifc_data)); 
   //memset(detail_data, 0, detail_data_size);
   ifc_data.cbSize = sizeof(ifc_data);
   detail_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
   for(uint4 index = 0; more_interfaces; ++index)
   {
      rcd = SetupDiEnumDeviceInterfaces(device_info, 0, serial_port_guid, index, &ifc_data);
      if(rcd)
      {
         // we need to get the details of this device
         SP_DEVINFO_DATA device_data;
         device_data.cbSize = sizeof(SP_DEVINFO_DATA);
         DWORD intReqSize;
         rcd = SetupDiGetDeviceInterfaceDetail(device_info, &ifc_data, 0, 0, &intReqSize, &device_data);

         rcd = SetupDiGetDeviceInterfaceDetail(device_info, &ifc_data, &detail_data,intReqSize,&intReqSize,&device_data);
         if(rcd)
         {
            //StrAsc device_path(detail_data->DevicePath);
            byte friendly_name[256];

            rcd = SetupDiGetDeviceRegistryProperty(
               device_info, &device_data, SPDRP_FRIENDLYNAME, 0, friendly_name, sizeof(friendly_name), reinterpret_cast<DWORD *>(sizeof(friendly_name)));
            if(rcd)
            {
              cout<<reinterpret_cast<char const *>(friendly_name);
            }
            else
            {   int num = GetLastError();
            }
         }
         else
         {
                int num = GetLastError();
            }
      }
      else
            more_interfaces = false;
   }    
}
SetupDiDestroyDeviceInfoList(device_info);
}

此外,在 INF 中,您可能必须添加 AddInterface指令将您的驱动程序与正确的接口(interface)相关联。

关于c++ - 为什么某些设备不使用 SetupDiGetDeviceInterfaceDetail() 进行枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/571229/

相关文章:

具有 1 个参数的 C++ 默认模板化构造函数

c++ - 在 C++ Windows 应用程序中捕获按下的键

c++ - Outlook Express类似地址栏控件的实现方法

Linux cdev 与 register_chrdev

c++ - 将 QML 场景渲染成纹理并保存

c++ - 在C++中的多个类中使用模板类

c++ - `using` 只有基类的一些重载

c# - 如何读取扩展文件属性/文件元数据

java - IntelliJ 找不到驱动类

javascript - Python替换javascript代码中的javascript双引号