设备接口列举(备忘)常用手法

一般列举设备驱动都是安装程序需要完成的工作
HDEVINFO SetupDiCreateDeviceInfoList(
    IN LPGUID ClassGuid, OPTIONAL
    IN HWND hwndParent OPTIONAL
    );
作用:创建一个空的设备信息列表.
ClassGuid参数指定一个设备类型GUID,hwndParent参数表示需要显示设备信息窗口.可以设置为NUll
返回值为HDEVINFO,指向设备类型的句柄.
    
HDEVINFO SetupDiCreateDeviceInfoListEx(
    IN LPGUID ClassGuid, OPTIONAL
    IN HWND hwndParent, OPTIONAL
    IN PCTSTR MachineName, OPTIONAL
    IN PVOID Reserved
    );
等API获得HDEVINFO类型的设备信息链表
然后由
WINSETUPAPI BOOL WINAPI
SetupDiEnumDeviceInterfaces(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
    IN LPGUID InterfaceClassGuid,
    IN DWORD MemberIndex,
    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
    );
依次读出设备信息列表中的设备信息.

还可以用
WINSETUPAPI BOOL WINAPI
SetupDiGetDeviceRegistryProperty(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVINFO_DATA DeviceInfoData,
    IN DWORD Property,
    OUT PDWORD PropertyRegDataType, OPTIONAL
    OUT PBYTE PropertyBuffer,
    IN DWORD PropertyBufferSize,
    OUT PDWORD RequiredSize OPTIONAL
    );

WINSETUPAPI BOOL WINAPI
SetupDiGetDeviceInterfaceDetail(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, OPTIONAL
    IN DWORD DeviceInterfaceDetailDataSize,
    OUT PDWORD RequiredSize, OPTIONAL
    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
    );
等获得更为详细的信息

设备接口类型GUID
设备类型GUID(class GUID),比如列举磁盘可以使用GUID_DEVINTERFACE_DISK.
列举串口可以使用GUID_DEVINTERFACE_COMPORT等.
设备类型GUID列举略

关键API
HDEVINFO SetupDiCreateDeviceInfoList(
    IN LPGUID ClassGuid, OPTIONAL
    IN HWND hwndParent OPTIONAL
    );
作用:创建一个空的设备信息列表.
ClassGuid参数指定一个设备类型GUID,hwndParent参数表示需要显示设备信息窗口.可以设置为NUll
返回值为HDEVINFO,指向设备类型的句柄.

HDEVINFO
SetupDiGetClassDevsEx(
    IN LPGUID ClassGuid, OPTIONAL
    IN PCTSTR Enumerator, OPTIONAL
    IN HWND hwndParent, OPTIONAL
    IN DWORD Flags,
    IN HDEVINFO DeviceInfoSet, OPTIONAL
    IN PCTSTR MachineName, OPTIONAL
    IN PVOID Reserved
    );
ClassGuid:指明了需要获取信息的设备类型GUID,如果Flags参数设为DIGCF_ALLCLASSES,那么这
个参数是无效的.
Enumerator:一般情况下可以设置为NULL
hwndParent参数:是用于显示窗口的句柄,可以显示为NULL
Flags参数:标志位
DIGCF_ALLCLASSES 
Return a list of installed devices for the specified device setup classes or device interface classes. 
DIGCF_DEVICEINTERFACE 
Return devices that support device interfaces for the specified device interface classes. 
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. 
DIGCF_PROFILE 
Return only devices that are a part of the current hardware profile. 
DeviceInfoSet参数:是一个已经存在的设备信息
MachineName:所列举的机器名,如果为本机,则设置为NULL。

WINSETUPAPI BOOL WINAPI
SetupDiEnumDeviceInterfaces(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
    IN LPGUID InterfaceClassGuid,
    IN DWORD MemberIndex,
    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
    );
函数功能是从已经获取的设备接口列表信息中获取信息并使用结构保存,每调用一次会依次返回一个
接口信息.
DeviceInfoSet参数:由SetupDiGetClassDevsEx等函数返回结果,设备接口列表.
DeviceInfoData:
DeviceInfoData 
A pointer to an SP_DEVINFO_DATA structure that specifies a device information el
ement in DeviceInfoSet. This parameter is optional and can be NULL. If this para
meter is specified, SetupDiEnumDeviceInterfaces constrains the enumeration to th
e interfaces that are supported by the specified device. If this parameter is NU
LL, repeated calls to SetupDiEnumDeviceInterfaces return information about the i
nterfaces that are associated with all the device information elements in Device
InfoSet. This pointer is typically returned by SetupDiEnumDeviceInfo. 
InterfaceClassGuid 
A pointer to a GUID that specifies the device interface class for the requested 
interface. 
MemberIndex 
A zero-based index into the list of interfaces in the device information set. Th
e caller should call this function first with MemberIndex set to zero to obtain 
the first interface. Then, repeatedly increment MemberIndex and retrieve an inte
rface until this function fails and GetLastError returns ERROR_NO_MORE_ITEMS.
If DeviceInfoData specifies a particular device, the MemberIndex is relative to 
only the interfaces exposed by that device.

DeviceInterfaceData 
A pointer to a caller-allocated buffer that contains, on successful return, a co
mpleted SP_DEVICE_INTERFACE_DATA structure that identifies an interface that mee
ts the search parameters. The caller must set DeviceInterfaceData.cbSize to size
of(SP_DEVICE_INTERFACE_DATA) before calling this function. 
typedef struct _SP_DEVICE_INTERFACE_DATA {
DWORD cbSize;
GUID InterfaceClassGuid;
DWORD Flags;
ULONG_PTR Reserved;
} SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;

SetupDiGetDeviceRegistryProperty和SetupDiGetDeviceInterfaceDetail获取设备接口详细信息
WINSETUPAPI BOOL WINAPI
SetupDiGetDeviceRegistryProperty(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVINFO_DATA DeviceInfoData,
    IN DWORD Property,
    OUT PDWORD PropertyRegDataType, OPTIONAL
    OUT PBYTE PropertyBuffer,
    IN DWORD PropertyBufferSize,
    OUT PDWORD RequiredSize OPTIONAL
    );
    
WINSETUPAPI BOOL WINAPI
SetupDiGetDeviceInterfaceDetail(
    IN HDEVINFO DeviceInfoSet,
    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, OPTIONAL
    IN DWORD DeviceInterfaceDetailDataSize,
    OUT PDWORD RequiredSize, OPTIONAL
    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
    );
   

code:


/* 头文件 */
#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值