您的位置:首页 > 理论基础

获得计算机网卡信息

2013-11-29 16:02 260 查看
着重申明: 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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息