现在的位置: 首页 > 综合 > 正文

通过WMI获得网卡MAC地址,硬盘序号,主板序号等硬件信息

2012年02月14日 ⁄ 综合 ⁄ 共 11078字 ⁄ 字号 评论关闭

开发语言:C/C++

支持平台:Windows

实现功能:

通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号
下载地址:

WMI_DeviceQuery.zip

版本历史:

V1.4 2010年05月17日 

修正了硬盘序列号处理中的错误。现在和EVEREST Ultimate Edition 5.5一致。 

V1.3 2010年05月11日 

增加了对网卡原生MAC地址的查询。
V1.2 2010年05月05日

增加对硬盘序列号的进一步处理。

V1.1 2010年04月30日

修正微软MSDN例子错误,并增加对虚拟网卡的判断。
V1.0 2010年04月27日

完成正式版本。
接口函数:

WMI_DeviceQuery

接口文件:WMI_DeviceQuery.h

 view plaincopy to clipboardprint?
/* ---------------------------------------------------------- 
文件名称:WMI_DeviceQuery.h 
 
作者:秦建辉 
 
MSN:splashcn@msn.com 
 
版本历史: 
    V1.4    2010年05月17日 
            修正了硬盘序列号处理中的错误。现在和EVEREST Ultimate Edition 5.5一致。 
 
    V1.3    2010年05月11日 
            增加了对网卡原生MAC地址的查询。 
 
    V1.2    2010年05月05日 
            增加对硬盘序列号的进一步处理。 
 
    V1.1    2010年04月30日 
            修正微软MSDN例子错误,并增加对虚拟机网卡的判断。 
             
    V1.0    2010年04月27日 
            完成正式版本。 
 
功能描述: 
    基于WMI获取设备属性: 
        0:网卡原生MAC地址 
        1:硬盘序列号 
        2:主板序列号 
        3:CPU ID 
        4:BIOS序列号 
        5:主板型号 
        6:网卡当前MAC地址 
 
接口函数: 
    WMI_DeviceQuery 
------------------------------------------------------------ */ 
#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 WMI_QUERY_TYPENUM   7   // WMI查询支持的类型数  
 
#ifdef __cplusplus  
extern "C" 
{  
#endif  
 
/* 
功能:通过WMI获取设备属性 
参数说明: 
    iQueryType:需要查询的设备属性 
            0:网卡原生MAC地址 
            1:硬盘序列号 
            2:主板序列号 
            3:CPU ID 
            4:BIOS序列号 
            5:主板型号 
            6:网卡当前MAC地址 
    properties:存储设备属性值 
    iSize:可存储的最大设备个数 
返回值: 
     -1:不支持的设备属性值 
     -2:WMI连接失败 
     -3:不正确的WQL查询语句 
    >=0:获取的设备个数   
*/ 
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize );  

 
#ifdef __cplusplus  
}  
#endif 
/* ----------------------------------------------------------
文件名称:WMI_DeviceQuery.h

作者:秦建辉

MSN:splashcn@msn.com

版本历史:
 V1.4 2010年05月17日
   修正了硬盘序列号处理中的错误。现在和EVEREST Ultimate Edition 5.5一致。

 V1.3 2010年05月11日
   增加了对网卡原生MAC地址的查询。

 V1.2 2010年05月05日
   增加对硬盘序列号的进一步处理。

 V1.1 2010年04月30日
   修正微软MSDN例子错误,并增加对虚拟机网卡的判断。
   
 V1.0 2010年04月27日
   完成正式版本。

功能描述:
 基于WMI获取设备属性:
  0:网卡原生MAC地址
  1:硬盘序列号
  2:主板序列号
  3:CPU ID
  4:BIOS序列号
  5:主板型号
  6:网卡当前MAC地址

接口函数:
 WMI_DeviceQuery
------------------------------------------------------------ */
#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 WMI_QUERY_TYPENUM 7 // WMI查询支持的类型数

#ifdef __cplusplus
extern "C"
{
#endif

/*
功能:通过WMI获取设备属性
参数说明:
 iQueryType:需要查询的设备属性
   0:网卡原生MAC地址
   1:硬盘序列号
   2:主板序列号
   3:CPU ID
   4:BIOS序列号
   5:主板型号
   6:网卡当前MAC地址
 properties:存储设备属性值
 iSize:可存储的最大设备个数
返回值:
  -1:不支持的设备属性值
  -2:WMI连接失败
  -3:不正确的WQL查询语句
 >=0:获取的设备个数 
*/
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize );

#ifdef __cplusplus
}
#endif
  

实现文件:WMI_DeviceQuery.cpp

view plaincopy to clipboardprint?
#include "WMI_DeviceQuery.h"  
#include <comutil.h>  
#include <Wbemidl.h>  
#include <tchar.h>  
#include <strsafe.h>  
#include <algorithm>  
#include <atlconv.h>  
#include <ntddndis.h>  
 
#pragma comment (lib, "comsuppw.lib")  
#pragma comment (lib, "wbemuuid.lib")  
 
typedef struct _T_WQL_QUERY  
{  
    CHAR*   szSelect;       // SELECT语句  
    WCHAR*  szProperty;     // 属性字段  
} T_WQL_QUERY;  
 
// WQL查询语句  
const T_WQL_QUERY szWQLQuery[] = {  
    // 网卡原生MAC地址  
    "SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",  

    L"PNPDeviceID",  
 
    // 硬盘序列号  
    "SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')",  

    L"SerialNumber",  
 
    // 主板序列号  
    "SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)",  
    L"SerialNumber",      
 
    // 处理器ID  
    "SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)",  
    L"ProcessorId",  
 
    // BIOS序列号  
    "SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)",  
    L"SerialNumber",  
 
    // 主板型号  
    "SELECT * FROM Win32_BaseBoard WHERE (Product IS NOT NULL)",  
    L"Product",  
 
    // 网卡当前MAC地址  
    "SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",  

    L"MACAddress",  
};  
 
// 通过“PNPDeviceID”获取网卡原生MAC地址  
static BOOL WMI_DoWithPNPDeviceID( const TCHAR *PNPDeviceID, TCHAR *MacAddress, UINT uSize )  

{  
    TCHAR   DevicePath[MAX_PATH];  
    HANDLE  hDeviceFile;      
    BOOL    isOK = FALSE;  
 
    // 生成设备路径名  
    StringCchCopy( DevicePath, MAX_PATH, TEXT("////.//") );  
    StringCchCat( DevicePath, MAX_PATH, PNPDeviceID );  
    StringCchCat( DevicePath, MAX_PATH, TEXT("#{ad498944-762f-11d0-8dcb-00c04fc3358c}") );  

 
    // 将“PNPDeviceID”中的“/”替换成“#”,以获得真正的设备路径名  
    std::replace( DevicePath + 4, DevicePath + 4 + _tcslen(PNPDeviceID), TEXT('//'), TEXT('#') );   

 
    // 获取设备句柄  
    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 )  
        {   // 将字节数组转换成16进制字符串  
            for( DWORD i = 0; i < dwByteRet; i++ )  
            {  
                StringCchPrintf( MacAddress + (i << 1), uSize - (i << 1), TEXT("%02X"), ucData[i] );  

            }  
 
            MacAddress[dwByteRet << 1] = TEXT('/0');  // 写入字符串结束标记  
        }  
 
        CloseHandle( hDeviceFile );  
    }  
 
    return isOK;  
}  
 
static BOOL WMI_DoWithHarddiskSerialNumber( TCHAR *SerialNumber, UINT uSize )  
{  
    UINT    iLen;  
    UINT    i;  
 
    iLen = _tcslen( SerialNumber );  
    if( iLen == 40 )    // InterfaceType = "IDE"  
    {   // 需要将16进制编码串转换为字符串  
        TCHAR ch, szBuf[32];  
        BYTE b;       
 
        for( i = 0; i < 20; i++ )  
        {   // 将16进制字符转换为高4位  
            ch = SerialNumber[i * 2];  
            if( (ch >= '0') && (ch <= '9') )  
            {  
                b = ch - '0';  
            }  
            else if( (ch >= 'A') && (ch <= 'F') )  
            {  
                b = ch - 'A' + 10;  
            }  
            else if( (ch >= 'a') && (ch <= 'f') )  
            {  
                b = ch - 'a' + 10;  
            }  
            else 
            {   // 非法字符  
                break;  
            }  
 
            b <<= 4;  
 
            // 将16进制字符转换为低4位  
            ch = SerialNumber[i * 2 + 1];  
            if( (ch >= '0') && (ch <= '9') )  
            {  
                b += ch - '0';  
            }  
            else if( (ch >= 'A') && (ch <= 'F') )  
            {  
                b += ch - 'A' + 10;  
            }  
            else if( (ch >= 'a') && (ch <= 'f') )  
            {  
                b += ch - 'a' + 10;  
            }  
            else 
            {   // 非法字符  
                break;  
            }  
 
            szBuf[i] = b;  
        }  
 
        if( i == 20 )  
        {   // 转换成功  
            szBuf[i] = L'/0';  
            StringCchCopy( SerialNumber, uSize, szBuf );  
            iLen = _tcslen( SerialNumber );  
        }  
    }  
 
    // 每2个字符互换位置  
    for( i = 0; i < iLen; i += 2 )  
    {  
        std::swap( SerialNumber[i], SerialNumber[i+1] );  
    }  
 
    // 去掉空格  
    std::remove( SerialNumber, SerialNumber + _tcslen(SerialNumber) + 1, L' ' );  

 
    return TRUE;  
}  
 
static BOOL WMI_DoWithProperty( INT iQueryType, TCHAR *szProperty, UINT uSize )  

{  
    BOOL isOK = TRUE;  
 
    switch( iQueryType )  
    {  
    case 0:     // 网卡原生MAC地址          
        isOK = WMI_DoWithPNPDeviceID( szProperty, szProperty, uSize );  
        break;  
 
    case 1:     // 硬盘序列号  
        isOK = WMI_DoWithHarddiskSerialNumber( szProperty, uSize );  
        break;  
 
    case 6:     // 网卡当前MAC地址  
        // 去掉冒号  
        std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L':' );  
        break;  
 
    default:  
        // 去掉空格  
        std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L' ' );  
    }  
 
    return isOK;  
}  
 
// 基于Windows Management Instrumentation(Windows管理规范)  
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize )  

{  
    HRESULT hres;  
    INT iTotal = 0;  
      
    // 判断查询类型是否支持  
    if( (iQueryType < 0) || (iQueryType >= sizeof(szWQLQuery)/sizeof(T_WQL_QUERY)) )  

    {  
        return -1;  // 查询类型不支持  
    }  
 
    // 初始化COM  
    hres = CoInitializeEx( NULL, COINIT_MULTITHREADED );   
    if( FAILED(hres) )  
    {  
        return -2;  
    }  
 
    // 设置COM的安全认证级别  
    hres = CoInitializeSecurity(   
        NULL,   
        -1,   
        NULL,   
        NULL,   
        RPC_C_AUTHN_LEVEL_DEFAULT,   
        RPC_C_IMP_LEVEL_IMPERSONATE,  
        NULL,  
        EOAC_NONE,  
        NULL  
        );  
    if( FAILED(hres) )  
    {  
        CoUninitialize();  
        return -2;  
    }  
      
    // 获得WMI连接COM接口  
    IWbemLocator *pLoc = NULL;  
    hres = CoCreateInstance(   
        CLSID_WbemLocator,               
        NULL,   
        CLSCTX_INPROC_SERVER,   
        IID_IWbemLocator,  
        reinterpret_cast<LPVOID*>(&pLoc)  
        );   
    if( FAILED(hres) )  
    {  
        CoUninitialize();  
        return -2;  
    }  
 
    // 通过连接接口连接WMI的内核对象名"ROOT//CIMV2"  
    IWbemServices *pSvc = NULL;  
    hres = pLoc->ConnectServer(  
         _bstr_t( L"ROOT//CIMV2" ),  
         NULL,  
         NULL,  
         NULL,  
         0,  
         NULL,  
         NULL,  
         &pSvc  
         );      
    if( FAILED(hres) )  
    {  
        pLoc->Release();   
        CoUninitialize();  
        return -2;  
    }  
 
    // 设置请求代理的安全级别  
    hres = CoSetProxyBlanket(  
        pSvc,  
        RPC_C_AUTHN_WINNT,  
        RPC_C_AUTHZ_NONE,  
        NULL,  
        RPC_C_AUTHN_LEVEL_CALL,  
        RPC_C_IMP_LEVEL_IMPERSONATE,  
        NULL,  
        EOAC_NONE  
        );  
    if( FAILED(hres) )  
    {  
        pSvc->Release();  
        pLoc->Release();       
        CoUninitialize();  
        return -2;  
    }  
 
    // 通过请求代理来向WMI发送请求  
    IEnumWbemClassObject *pEnumerator = NULL;  
    hres = pSvc->ExecQuery(  
        bstr_t("WQL"),   
        bstr_t( szWQLQuery[iQueryType].szSelect ),  
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,   
        NULL,  
        &pEnumerator  
        );  
    if( FAILED(hres) )  
    {  
        pSvc->Release();  
        pLoc->Release();  
        CoUninitialize();  
        return -3;  
    }  
 
    // 循环枚举所有的结果对象    
    while( pEnumerator )  
    {  
        IWbemClassObject *pclsObj = NULL;  
        ULONG uReturn = 0;  
 
        if( (properties != NULL) && (iTotal >= iSize) )  
        {  
            break;  
        }  
 
        pEnumerator->Next(  
            WBEM_INFINITE,  
            1,   
            &pclsObj,  
            &uReturn  
            );  
 
        if( uReturn == 0 )  
        {  
            break;  
        }  
 
        if( properties != NULL )  
        {   // 获取属性值  
            VARIANT vtProperty;  
              
            VariantInit( &vtProperty );   
            pclsObj->Get( szWQLQuery[iQueryType].szProperty, 0, &vtProperty, NULL, NULL );  

            StringCchCopy( properties[iTotal].szProperty, PROPERTY_MAX_LEN, W2T(vtProperty.bstrVal) );  

            VariantClear( &vtProperty );  
 
            // 对属性值做进一步的处理  
            if( WMI_DoWithProperty( iQueryType, properties[iTotal].szProperty, PROPERTY_MAX_LEN ) )  

            {  
                iTotal++;  
            }  
        }  
        else 
        {  
            iTotal++;  
        }  
 
        pclsObj->Release();  
    } // End While  
 
    // 释放资源  
    pEnumerator->Release();  
    pSvc->Release();  
    pLoc->Release();      
    CoUninitialize();  
 
    return iTotal;  

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jhqin/archive/2010/05/01/5548656.aspx

抱歉!评论已关闭.