结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址
虽然Win32_NetworkAdapter包含了属性PermanentAddress,但是在当前的WMI里只是个空值,微软目前还没有实现这个属性值。但是我们仍可以通过结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址。其实现思路如下:
- 通过WMI获取物理网卡的 PNPDeviceID 。
- 将 PNPDeviceID 转化为网卡的设备路径名。
- 通过设备路径名,用CreateFile获取设备句柄。
- 通过设备句柄,用DeviceIoControl与驱动程序进行通信,获取网卡的原生MAC地址和当前MAC地址。
开发语言:Visual C++
支持平台:Windows
实现功能:
- 结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址
下载地址:
WMI_MACAddress.zip
版本历史:
V1.1 2010年05月23日
- 代码优化。
V1.0 2010年05月12日
- 完成正式版本。
接口函数:
WMI_MacAddress
源代码:
WMI_MACAddress.h
/* ---------------------------------------------------------- 文件名称: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
WMI_MACAddress.cpp
#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; }
结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址相关推荐
- 通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号
开发语言:C/C++ 支持平台:Windows 实现功能: 通过WMI获取网卡MAC地址.硬盘序列号.主板序列号.CPU ID.BIOS序列号 下载地址: WMI_DeviceQuery.zip 版本 ...
- android 获取网卡mac_防亚马逊账号关联黑科技--如何修改我们的网卡MAC到底重要不?...
大家好,我是跨境卫士的刘同学,各位搞跨境电商的大佬们估计都经常为亚马逊账号关联这种问题而苦恼吧,今天给大家带来一片技术分享. 如何修改我们的网卡MAC还有这个东东到底重要不? 啥是网卡mac呢? 网卡 ...
- Delphi自定义获取网卡MAC地址过程
//获取网卡MAC地址=============================================================== procedure CvtInt; asm ...
- android 获取网卡mac_Java获取Linux安卓设备的mac地址方法
Java如何获取Linux或安卓Android设备的mac地址呢?方法非常简单,只需要使用下方代码即可轻松通过java获取mac地址了,代码如下:public String getMacAddress ...
- php 获取mac地址栏,php 获取网卡物理(MAC)地址的实现方法
搜索热词 感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编来看看吧. 经测试代码如下: /** * 获取网卡物理(MAC)地址 * * @param * @author 编程之家 jb51. ...
- php 获取路由器mac地址,php如何获取网卡MAC地址(支持WIN与LINUX系统)
/** 获取网卡的MAC地址:目前支持WIN/LINUX系统 获取机器网卡的物理(MAC)地址 **/ class GetMacAddr{ var $return_array = array(); / ...
- Python 获取 网卡 MAC 地址
/************************************************************************ Python 获取 网卡 MAC 地址* 说明:* ...
- java获取网卡正真的mac_java获取网卡的mac地址
为了项目的安全,有时候需要得到电脑的唯一码,比如:网卡的mac地址.和大家分享一下,下面是项目中用到的工具类:/** * 获取Mac地址 * @return */ public String getM ...
- linux临时配置mac地址,Linux获取网卡型号、mac地址、修改IP地址的几种方法
1.获取所有有(无)网卡型号 方法一.ifconfig 用法:ifconfig | grep | cut -d ':' -f 1 ubuntu root@ubuntu:~# ifconfig | gr ...
最新文章
- 推荐2020年度最佳的23个的机器学习项目(附源代码)
- Gerrit 代码审核服务器的工作流和原理
- 用python 爬取百度百科内容-使用python爬取小说全部内容
- HDU3496-Watch The Movie
- 简单解决“ORA-27100: shared memory realm already exists”的问题
- 对后台返回的数据进行评分排序、时间排序!
- 封装一个信号量集操作函数的工具
- 【GCN+KG】基于知识图谱和图卷积神经网络的应用和开发
- Oracle备份还原实践
- Mac 上使用vim 快捷键
- vue 中使用海康威视视频插件
- 惠普打印机如何取消任务
- 2021Bootstrap框架入门(最新)
- ECCV2022 | 多任务SOTA模型!分割/深度/边界/显著图四项任务
- 数据库—Mysql相关
- 从头开始训练一个 NER 标注器
- Do带你解析:原生APP与web APP的区别
- SQL语句-各种查询
- 12,MongoDB的视图
- mysql在linux版本信息查询,Linux 查看 MySQL的版本信息