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

来源:互联网 发布:算法第四版高清pdf 编辑:程序博客网 时间:2024/04/30 20:05

转载自:http://blog.csdn.net/jhqin/article/details/5548656


开发语言:C/C++

支持平台:Windows

实现功能:

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

版本历史:

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


/* ----------------------------------------------------------文件名称:WMI_DeviceQuery.h作者:秦建辉MSN:splashcn@msn.com版本历史:V1.42010年05月17日修正了硬盘序列号处理中的错误。现在和EVEREST Ultimate Edition 5.5一致。V1.32010年05月11日增加了对网卡原生MAC地址的查询。V1.22010年05月05日增加对硬盘序列号的进一步处理。V1.12010年04月30日修正微软MSDN例子错误,并增加对虚拟机网卡的判断。V1.02010年04月27日完成正式版本。功能描述:基于WMI获取设备属性:0:网卡原生MAC地址1:硬盘序列号2:主板序列号3:CPU ID4:BIOS序列号5:主板型号6:网卡当前MAC地址接口函数:WMI_DeviceQuery------------------------------------------------------------ */#pragma once#include <windows.h>#ifndef MACRO_T_DEVICE_PROPERTY#define MACRO_T_DEVICE_PROPERTY#define PROPERTY_MAX_LEN128// 属性字段最大长度typedef struct _T_DEVICE_PROPERTY{TCHAR szProperty[PROPERTY_MAX_LEN];} T_DEVICE_PROPERTY;#endif#define WMI_QUERY_TYPENUM7// WMI查询支持的类型数#ifdef __cplusplusextern "C"{#endif/*功能:通过WMI获取设备属性参数说明:iQueryType:需要查询的设备属性0:网卡原生MAC地址1:硬盘序列号2:主板序列号3:CPU ID4: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

#include "stdafx.h"#include "WMI_DeviceQuery.h"#include <comutil.h>#include <Wbemidl.h>#include <tchar.h>#include <strsafe.h>#include <algorithm>#include <atlconv.h>#include <ntddndis.h>#include <winioctl.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 ){TCHARDevicePath[MAX_PATH];HANDLEhDeviceFile;BOOLisOK = 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 ){ULONGdwID;BYTEucData[8];DWORDdwByteRet;// 获取网卡原生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] );}}CloseHandle( hDeviceFile );}return isOK;}static BOOL WMI_DoWithHarddiskSerialNumber( TCHAR *SerialNumber, UINT uSize ){UINTiLen;UINTi;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;INTiTotal = 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 );USES_CONVERSION; 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;}


实现代码:

T_DEVICE_PROPERTY mac;for (int i=0; i<7; i++){WMI_DeviceQuery(i, &mac, 2);cout<<mac.szProperty<<endl;}





编译时可能遇到各种问题,具体请到原博客查看评论及具体解决办法:

原创:http://blog.csdn.net/jhqin/article/details/5548656


0 0
原创粉丝点击