获得计算机网卡信息

来源:互联网 发布:linux默认命令行启动 编辑:程序博客网 时间:2024/04/29 12:12

着重申明: 1, 本文中所有代码均是  秦建辉 所写,其版权所有。 

                      2, 感谢其分享。

PS : 我不认识他,这是我在网上找到的。


头文件

/* ----------------------------------------------------------
文件名称:WMI_MACAddress.h


作者:秦建辉


MSN:splashcn@msn.com


版本历史:
V1.1 2010年05月23日
代码优化。


V1.0 2010年05月12日
完成正式版本。


功能描述:
结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址


接口函数:
WMI_MacAddress
 ------------------------------------------------------------ */
#pragma once


#include <windows.h>


#define MACADDRESS_BYTELEN 6// MAC地址字节长度


typedef struct _T_MACADDRESS {
BYTE PermanentAddress[MACADDRESS_BYTELEN];// 原生MAC地址
BYTE MACAddress[MACADDRESS_BYTELEN];// 当前MAC地址
} T_MACADDRESS;


//-------------------导出函数-------------
#ifdef __cplusplus
extern "C"{
#endif


/*
功能:结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址
入口参数:
iQueryType:需要获取的网卡类型
0:包括USB网卡
1:不包括USB网卡
pMacAddress:存储网卡MAC地址
uSize:可存储的最大网卡数目
返回值:
-1:不支持的设备属性值
-2:WMI连接失败
-3:不正确的WQL查询语句
>=0:获取的网卡数目
*/
INT WMI_MacAddress( INT iQueryType, T_MACADDRESS *pMacAddress, INT iSize );


#ifdef __cplusplus
}
#endif


源文件


#include "stdafx.h"


#include "WMI_MACAddress.h"
#include <comutil.h>
#include <Wbemidl.h>
#include <tchar.h>
#include <strsafe.h>
#include <algorithm>
#include <ntddndis.h>
#include <atlconv.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[] = {
// 包含USB网卡
"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
L"PNPDeviceID",


// 不包含USB网卡
"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%')) AND (NOT (PNPDeviceID LIKE 'USB%'))",
L"PNPDeviceID"
};


static BOOL WMI_DoWithPNPDeviceID( const TCHAR *PNPDeviceID, T_MACADDRESS *pMacAddress, INT iIndex )
{
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_CURRENT_ADDRESS;
isOK = DeviceIoControl( hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL );
if( isOK )
{
memcpy( pMacAddress[iIndex].MACAddress, ucData, 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 )
{
memcpy( pMacAddress[iIndex].PermanentAddress, ucData, dwByteRet );
}
}


CloseHandle( hDeviceFile );
}


return isOK;
}


INT WMI_MacAddress( INT iQueryType, T_MACADDRESS *pMacAddress, 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( (pMacAddress != NULL) && (iTotal >= iSize) )
{
break;
}


        pEnumerator->Next(
WBEM_INFINITE,
1, 
            &pclsObj,
&uReturn
);


        if( uReturn == 0 )
        {
            break;
        }


VARIANT vtProperty;
TCHAR szProperty[128];

// 获取网卡设备标识符
VariantInit( &vtProperty );
pclsObj->Get( szWQLQuery[iQueryType].szProperty, 0, &vtProperty, NULL, NULL );
StringCchCopy( szProperty, sizeof(szProperty)/sizeof(TCHAR), W2T(vtProperty.bstrVal) );
VariantClear( &vtProperty );


if( pMacAddress != NULL )
{ // 通过设备标识符获取原生MAC地址和当前MAC地址
if( WMI_DoWithPNPDeviceID( szProperty, pMacAddress, iTotal ) )
{
iTotal++;
}
}
else
{
iTotal++;
}


pclsObj->Release();
    } // End While


    // 释放资源
pEnumerator->Release();
    pSvc->Release();
    pLoc->Release();    
    CoUninitialize();


    return iTotal;
}

原创粉丝点击