导航:[首页]->[windows]->[Windows获取物理网卡外设]

原理

使用CM_Get_DevNode_Registry_Property_Ex系列api获取所有的网络硬件设备,使用SetupDiGetClassDevs系列api获取已经启用的网络设备。从【HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network{4D36E972-E325-11CE-BFC1-08002BE10318}{9082CA70-B700-4161-918F-33DCF436B119}\Connection】读取所有的网卡。

源码

#include <Windows.h>
#include <tchar.h>
#include <string>
#include <cassert>

#if defined _UNICODE || defined UNICODE
typedef std::wstring String;
#else
typedef std::string String;
#endif

#include <Cfgmgr32.h>
#pragma comment(lib,"Cfgmgr32.lib")

#include <setupapi.h>
#pragma comment (lib,"Setupapi.lib")
#define MACADDRESS_BYTELEN      6    
#define OID_802_3_PERMANENT_ADDRESS 0x01010101
#define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002
GUID GUID_DEVCLASS_QUERY = { 0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C };



HMACHINE m_hMachine;

String GetHARDWAREID(DEVNODE DevNode, ULONG flag)
{
    String  strType;
    String  strValue;
    String DisplayName;
    LPTSTR  Buffer = NULL;

    int  BufferSize = MAX_PATH + MAX_DEVICE_ID_LEN;
    ULONG  BufferLen = BufferSize * sizeof(TCHAR);

    Buffer = new TCHAR[BufferSize];
    if (CR_SUCCESS == CM_Get_DevNode_Registry_Property_Ex(DevNode,
        flag, NULL,
        Buffer, &BufferLen, 0, m_hMachine))
    {
        DisplayName = Buffer;
    }
    else
    {
        DisplayName = _T("error");
    }

    delete[] Buffer;
    return DisplayName;
}

String GetDeviceName(DEVNODE DevNode)
{
    String  strType;
    String  strValue;
    String DisplayName;
    LPTSTR  Buffer = NULL;

    int  BufferSize = MAX_PATH + MAX_DEVICE_ID_LEN;
    ULONG  BufferLen = BufferSize * sizeof(TCHAR);

    Buffer = new TCHAR[BufferSize];
    if (CR_SUCCESS == CM_Get_DevNode_Registry_Property_Ex(DevNode,
        CM_DRP_FRIENDLYNAME, NULL,
        Buffer, &BufferLen, 0, m_hMachine))
    {
        DisplayName = Buffer;
    }
    else
    {
        BufferLen = BufferSize * sizeof(TCHAR);

        if (CR_SUCCESS == CM_Get_DevNode_Registry_Property_Ex(DevNode,
            CM_DRP_DEVICEDESC, NULL,
            Buffer, &BufferLen, 0, m_hMachine))
        {
            DisplayName = Buffer;
        }
        else
        {
            DisplayName = _T("Unknown Device");
        }
    }

    delete[] Buffer;
    return DisplayName;
}

void RetrieveSubNodes(DEVINST parent, DEVINST sibling, DEVNODE dn)
{
    DEVNODE dnSibling, dnChild;

    do
    {
        CONFIGRET cr = CM_Get_Sibling_Ex(&dnSibling, dn, 0, m_hMachine);

        if (cr != CR_SUCCESS)
            dnSibling = NULL;

        TCHAR GuidString[MAX_GUID_STRING_LEN];
        ULONG Size = sizeof(GuidString);

        cr = CM_Get_DevNode_Registry_Property_Ex(dn, CM_DRP_CLASSGUID, NULL,
            GuidString, &Size, 0, m_hMachine);

        if (cr == CR_SUCCESS)
        {

            String DeviceName = GetHARDWAREID(dn, CM_DRP_CLASS);
            if (DeviceName == _T("Net"))
            {
                _tprintf(_T("CM_DRP_CLASS [%s]\n"), DeviceName.c_str());

                DeviceName = GetDeviceName(dn);
                _tprintf(_T("DeviceName [%s]\n"), DeviceName.c_str());

                DeviceName = GetHARDWAREID(dn, CM_DRP_HARDWAREID);
                _tprintf(_T("CM_DRP_HARDWAREID [%s]\n"), DeviceName.c_str());

                DeviceName = GetHARDWAREID(dn, CM_DRP_SERVICE);
                _tprintf(_T("CM_DRP_SERVICE [%s]\n"), DeviceName.c_str());


                DeviceName = GetHARDWAREID(dn, CM_DRP_CLASSGUID);
                _tprintf(_T("CM_DRP_CLASSGUID [%s]\n"), DeviceName.c_str());
            }

#if 0
            GUID Guid;
            GuidString[MAX_GUID_STRING_LEN - 2] = _T('\0');
            UuidFromString(&GuidString[1], &Guid);
            int Index;
            if (SetupDiGetClassImageIndex(&m_ImageListData, &Guid, &Index))
            {
                String DeviceName = GetDeviceName(dn);
                m_Devices.InsertItem(m_Devices.GetItemCount(), DeviceName, Index);
            }
#endif
        }

        cr = CM_Get_Child_Ex(&dnChild, dn, 0, m_hMachine);
        if (cr == CR_SUCCESS)
        {
            RetrieveSubNodes(dn, NULL, dnChild);
        }

        dn = dnSibling;

    } while (dn != NULL);

}

static BOOL GetMacAddress()
{
    HDEVINFO hDevInfo;
    DWORD MemberIndex, RequiredSize;
    SP_DEVICE_INTERFACE_DATA            DeviceInterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA    DeviceInterfaceDetailData;
    BOOL isOK = FALSE;

    // 获取设备信息集
    hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_QUERY, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
    if (INVALID_HANDLE_VALUE == hDevInfo)
    {
        return FALSE;
    }

    //  枚举设备信息集中所有设备
    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    MemberIndex = 0;
    while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVCLASS_QUERY, MemberIndex, &DeviceInterfaceData))
    {
        MemberIndex++;
        // 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER  
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL);

        // 申请接收缓冲区  
        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
        DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        // 获取设备细节信息  
        if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData,
            DeviceInterfaceDetailData, RequiredSize, NULL, NULL))
        {
            HANDLE hDeviceFile;

            _tprintf(_T("PATH [%s]\n"), 
                DeviceInterfaceDetailData->DevicePath);

            // 获取设备句柄  
            hDeviceFile = CreateFile(
                DeviceInterfaceDetailData->DevicePath,
                0,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);

            if (hDeviceFile != INVALID_HANDLE_VALUE)
            {
                ULONG   dwID;
                BYTE    ucData[MACADDRESS_BYTELEN];
                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)
                {
                    printf("%02X-%02X-%02X-%02X-%02X-%02X\n",
                        ucData[0], ucData[1], ucData[2],
                        ucData[3], ucData[4], ucData[5]);
                } // if( isOK )
            } // if( hDeviceFile != INVALID_HANDLE_VALUE )
        } // if( SetupDiGetDeviceInterfaceDetail() )

        free(DeviceInterfaceDetailData);

    } // for( )

    SetupDiDestroyDeviceInfoList(hDevInfo);

    return TRUE;
}



int _tmain(int argc, _TCHAR* argv[])
{
    TCHAR LocalComputer[MAX_PATH];
    DWORD Size = MAX_PATH - 2;

    GetComputerName(LocalComputer + 2, &Size);
    LocalComputer[0] = _T('\\');
    LocalComputer[1] = _T('\\');

    CONFIGRET cr;
    cr = CM_Connect_Machine(LocalComputer, &m_hMachine);
    DEVNODE dnRoot;
    CM_Locate_DevNode_Ex(&dnRoot, NULL, 0, m_hMachine);

    DEVNODE dnFirst;
    CM_Get_Child_Ex(&dnFirst, dnRoot, 0, m_hMachine);

    RetrieveSubNodes(dnRoot, NULL, dnFirst);

    CM_Disconnect_Machine(m_hMachine);

    GetMacAddress();
    return 0;
}

参考

  1. http://blog.csdn.net/uncledou/article/details/8693462
  2. http://www.codeproject.com/Articles/6445/Enumerate-Installed-Devices-Using-Setup-API