zoukankan      html  css  js  c++  java
  • windows平台下获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

    转自http://blog.csdn.net/jhqin/article/details/5548656,如有侵权,请联系本人删除,谢谢!!

    头文件:WMI_DeviceQuery.h

    /* ---------------------------------------------------------- 
    文件名称: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

    #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;  
    }  
    
  • 相关阅读:
    第十一章 表单与验证
    第十章 日期与时间
    第九章 正则表达式
    第八章 字符串处理
    纯C实现面向对象之接口编程
    csharp 面向对象编程
    cpp面向对象编程
    javascriptMVC框架面向对象编程
    堆栈的区别
    Java堆栈简介
  • 原文地址:https://www.cnblogs.com/lzm-cn/p/9186286.html
Copyright © 2011-2022 走看看