开发语言:C/C++
开发工具:
- Visual Studio 2010
- Windows Driver Kit Version 7600.16385.1
支持平台:Windows
实现功能:
- 通过WDK获取设备的VID-PID、网卡原生MAC地址、硬盘序列号
下载地址:
V1.3 2010年05月22日
- 增加获取硬盘序列号(需要系统管理员权限)。
V1.2 2010年05月20日
- 更新接口函数。
- 增加获取网卡原生MAC地址。
V1.1 2010年04月27日
- 优化代码。
V1.0 2010年04月15日
完成正式版本。获取设备的VID-PID。
接口函数:
WDK_DeviceQuery_Property
WDK_DeviceQuery_VIDPID
接口文件:WDK_DeviceQuery.h
作者:秦建辉
MSN:splashcn@msn.com
版本历史:
V1.3 2010年05月22日
增加获取硬盘序列号(需要系统管理员权限)。
V1.2 2010年05月20日
更新接口函数。
增加获取网卡原生MAC地址。
V1.1 2010年04月27日
优化代码。
V1.0 2010年04月15日
完成正式版本。获取设备的VID-PID。
功能描述:
基于WDK获取设备属性值。
接口函数:
WDK_DeviceQuery_Property
WDK_DeviceQuery_VIDPID
------------------------------------------------------------ */
#pragma once
#include <windows.h>
#ifndef MACRO_T_DEVICE_PROPERTY
#define MACRO_T_DEVICE_PROPERTY
#define PROPERTY_MAX_LEN 128 // 属性字段最大长度
typedef struct _T_DEVICE_PROPERTY
{
TCHAR szProperty[PROPERTY_MAX_LEN];
} T_DEVICE_PROPERTY;
#endif
#define WDK_QUERY_TYPENUM 4 // WDK查询支持的类型数
#ifndef MACRO_HIDD_VIDPID
#define MACRO_HIDD_VIDPID
typedef struct _HIDD_VIDPID
{
USHORT VendorID;
USHORT ProductID;
} HIDD_VIDPID;
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/*
功能:基于WDK获取设备属性值
参数说明:
iQueryType:需要查询的设备属性
0:人机交互设备的VID-PID
1:网卡原生MAC地址(包含USB网卡)
2:网卡原生MAC地址(剔除USB网卡)
3:硬盘序列号(需要系统管理员权限)
properties:存储设备属性值
iSize:可存储的最大设备数
返回值:
-1:获取设备信息表失败
-2:不支持的查询类型
>=0:实际获取的设备数
*/
INT WDK_DeviceQuery_Property( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize );
/*
功能:获取指定设备接口类相关设备的VID和PID
参数说明:
pGuid:指向设备接口类GUID
pVIDPID:存储设备的VID和PID
iSize:可存储的最大设备数
返回值:
-1:获取设备信息表失败
>=0:实际获取的设备数
*/
INT WDK_DeviceQuery_VIDPID( const GUID* pGuid, HIDD_VIDPID* pVIDPID, INT iSize );
#ifdef __cplusplus
}
#endif
实现代码:WDK_DeviceQuery.cpp
#ifdef __cplusplus
extern "C"
{
#endif
#include <hidsdi.h>
#ifdef __cplusplus
}
#endif
#pragma comment (lib, "Setupapi.lib")
#pragma comment (lib, "hid.lib")
const GUID GUID_QUERYSET[] = {
// 人机交互设备VID-PID
{0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30},
// 网卡原生MAC地址(包含USB网卡)
{0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},
// 网卡原生MAC地址(剔除USB网卡)
{0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},
// 硬盘序列号
{0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B},
};
// 获取设备的VID-PID
static BOOL WDK_GetVIDPID( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize )
{
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 获取设备句柄
hDeviceFile = CreateFile( DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hDeviceFile != INVALID_HANDLE_VALUE )
{ // 获取设备属性
HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(HIDD_ATTRIBUTES);
isOK = HidD_GetAttributes( hDeviceFile, &Attributes );
if( isOK )
{
if( szProperty != NULL )
{
StringCchPrintf( szProperty, uSize, TEXT("%04X-%04X"), Attributes.VendorID, Attributes.ProductID );
}
}
CloseHandle( hDeviceFile );
}
return isOK;
}
// 获取网卡原生MAC地址
static BOOL WDK_GetMacAddress( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize, BOOL isIncludeUSB )
{
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 剔除虚拟网卡
if( _tcsnicmp( DevicePath + 4, TEXT("root"), 4 ) == 0 )
{
return FALSE;
}
if( !isIncludeUSB )
{ // 剔除USB网卡
if( _tcsnicmp( DevicePath + 4, TEXT("usb"), 4 ) == 0 )
{
return FALSE;
}
}
// 获取设备句柄
hDeviceFile = CreateFile( DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hDeviceFile != INVALID_HANDLE_VALUE )
{
ULONG dwID;
BYTE ucData[8];
DWORD dwByteRet;
// 获取原生MAC地址
dwID = OID_802_3_PERMANENT_ADDRESS;
isOK = DeviceIoControl( hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL );
if( isOK )
{
if( szProperty != NULL )
{ // 将字节数组转换成16进制字符串
for( DWORD i = 0; i < dwByteRet; i++ )
{
StringCchPrintf( szProperty + (i << 1), uSize - (i << 1), TEXT("%02X"), ucData[i] );
}
}
}
CloseHandle( hDeviceFile );
}
return isOK;
}
// 获取硬盘序列号(需要系统管理员权限)
static BOOL WDK_GetHarddiskSerialNumberWithAdminRights( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize )
{
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 获取设备句柄
hDeviceFile = CreateFile( DevicePath,
GENERIC_READ | GENERIC_WRITE, // 注意:需要系统管理员权限才能执行读写操作
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hDeviceFile != INVALID_HANDLE_VALUE )
{
GETVERSIONINPARAMS VersionInParams;
DWORD dwByteRet;
// 获取硬盘属性
isOK = DeviceIoControl( hDeviceFile, SMART_GET_VERSION, NULL, 0, &VersionInParams, sizeof(GETVERSIONINPARAMS), &dwByteRet, NULL );
if( isOK )
{
isOK = FALSE;
if( VersionInParams.fCapabilities & CAP_ATA_ID_CMD )
{
BYTE abSCIP[sizeof(SENDCMDINPARAMS) - 1] = {0};
BYTE abSCOP[sizeof(SENDCMDOUTPARAMS) - 1 + 512] = {0};
SENDCMDINPARAMS *scip = reinterpret_cast<SENDCMDINPARAMS*>(abSCIP);
SENDCMDOUTPARAMS *scop = reinterpret_cast<SENDCMDOUTPARAMS*>(abSCOP);
// 设置输入参数
scip->irDriveRegs.bCommandReg = ID_CMD;
// 设置输出参数
scop->cBufferSize = 512;
// 获取硬盘详细信息
isOK = DeviceIoControl( hDeviceFile, SMART_RCV_DRIVE_DATA, scip, sizeof(abSCIP), scop, sizeof(abSCOP), &dwByteRet, NULL );
if( isOK )
{
if( szProperty != NULL )
{ // 提取硬盘序列号
for( UINT i = 0; i < 20; i += 2 )
{ // 颠倒高低位字节
szProperty[i] = scop->bBuffer[i+21];
szProperty[i + 1] = scop->bBuffer[i+20];
}
szProperty[20] = TEXT('/0');
// 去掉空格
std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L' ' );
}
}
}
}
CloseHandle( hDeviceFile );
}
return isOK;
}
static BOOL WDK_GetProperty( TCHAR* DevicePath, INT iQueryType, TCHAR* szProperty, UINT uSize )
{
BOOL isOK = FALSE;
switch( iQueryType )
{
case 0:
// 获取设备的VID-PID
isOK = WDK_GetVIDPID( DevicePath, szProperty, uSize );
break;
case 1: // 网卡原生MAC地址(包含USB网卡)
isOK = WDK_GetMacAddress( DevicePath, szProperty, uSize, TRUE );
break;
case 2: // 网卡原生MAC地址(剔除USB网卡)
isOK = WDK_GetMacAddress( DevicePath, szProperty, uSize, FALSE );
break;
case 3: // 硬盘序列号(需要系统管理员权限)
isOK = WDK_GetHarddiskSerialNumberWithAdminRights( DevicePath, szProperty, uSize );
break;
default:
break;
}
return isOK;
}
INT WDK_DeviceQuery_Property( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize )
{
HDEVINFO hDevInfo;
DWORD MemberIndex, RequiredSize;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
INT iTotal = 0;
// 判断查询类型是否支持
if( (iQueryType < 0) || (iQueryType >= sizeof(GUID_QUERYSET)/sizeof(GUID)) )
{
return -2; // 查询类型不支持
}
// 获取设备信息集
hDevInfo = SetupDiGetClassDevs( GUID_QUERYSET + iQueryType, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
if( hDevInfo == INVALID_HANDLE_VALUE )
{
return -1;
}
// 枚举设备信息集中所有设备
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for( MemberIndex = 0; ((properties == NULL) || (iTotal < iSize)); MemberIndex++ )
{ // 获取设备接口
if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, GUID_QUERYSET + iQueryType, MemberIndex, &DeviceInterfaceData ) )
{ // 设备枚举完毕
break;
}
// 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER
SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL );
// 申请接收缓冲区
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( RequiredSize );
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// 获取设备细节信息
if( SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL ) )
{
if( properties != NULL )
{
if( WDK_GetProperty( DeviceInterfaceDetailData->DevicePath, iQueryType, properties[iTotal].szProperty, PROPERTY_MAX_LEN ) )
{
if( iTotal > 0 )
{ // 剔除重复设备
if( _tcscmp( properties[iTotal].szProperty, properties[iTotal - 1].szProperty ) != 0 )
{
iTotal++;
}
}
else
{
iTotal++;
}
}
}
else
{
iTotal++;
}
}
free( DeviceInterfaceDetailData );
}
SetupDiDestroyDeviceInfoList( hDevInfo );
return iTotal;
}
INT WDK_DeviceQuery_VIDPID( const GUID* pGuid, HIDD_VIDPID* pVIDPID, INT iSize )
{
HDEVINFO hDevInfo;
DWORD MemberIndex, RequiredSize;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
INT iTotal = 0;
// 获取设备信息集
hDevInfo = SetupDiGetClassDevs( pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
if( hDevInfo == INVALID_HANDLE_VALUE )
{
return -1;
}
// 枚举设备信息集中所有设备
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for( MemberIndex = 0; ((pVIDPID == NULL) || (iTotal < iSize)); MemberIndex++ )
{ // 获取设备接口
if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, pGuid, MemberIndex, &DeviceInterfaceData ) )
{ // 设备枚举完毕
break;
}
// 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER
SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL );
// 申请接收缓冲区
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( RequiredSize );
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// 获取设备细节信息
if( SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL ) )
{ // 获取设备句柄
HANDLE hDeviceFile;
hDeviceFile = CreateFile( DeviceInterfaceDetailData->DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if( hDeviceFile != INVALID_HANDLE_VALUE )
{ // 获取设备属性
HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(HIDD_ATTRIBUTES);
if( HidD_GetAttributes( hDeviceFile, &Attributes ) )
{
if( pVIDPID != NULL )
{
pVIDPID[iTotal].VendorID = Attributes.VendorID;
pVIDPID[iTotal].ProductID = Attributes.ProductID;
if( iTotal > 0 )
{ // 剔除重复设备
if( (pVIDPID[iTotal].VendorID != pVIDPID[iTotal - 1].VendorID) || (pVIDPID[iTotal].ProductID != pVIDPID[iTotal - 1].ProductID) )
{
iTotal++;
}
}
else
{
iTotal++;
}
}
else
{
iTotal++;
}
}
CloseHandle( hDeviceFile );
}
}
free( DeviceInterfaceDetailData );
}
SetupDiDestroyDeviceInfoList( hDevInfo );
return iTotal;
}