ネットワークアダプタの情報を取得する方法は幾つかあるようです。 それぞれの方法で、取得できる内容や、場合によって取得できる/できない、等がある かもしれませんので、挙動を確認しやすいように、各APIを呼び出して、そのまま printf 出力するプログラムを作ってみました。
ビルドする際は、 ole32.lib、oleaut32.lib、wbemuuid.lib をリンカに渡してください。
// Copyright Mocchi 2012, 2019
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#define _WIN32_DCOM
#include <windows.h>
#include <iphlpapi.h>
#include <nb30.h>
#include <wbemidl.h>
#include <objbase.h>
struct BStrContainer{
std::vector<BSTR> ss;
BSTR Add(const WCHAR *str){
ss.push_back(::SysAllocString(str));
return ss.back();
}
~BStrContainer(){
for (size_t i = 0; i < ss.size(); ++i){
::SysFreeString(ss[i]);
}
ss.clear();
}
};
struct ComPtrContainer{
std::vector<IUnknown *> unks;
template <typename T> void Add(T *p){
unks.push_back(0);
unks.back() = p;
}
~ComPtrContainer(){
for (size_t i = 0; i < unks.size(); ++i){
unks[i]->Release();
}
unks.clear();
}
};
int main(void){
std::printf("****** GetIfTable method *****\n");
HMODULE hMod_iphlpapi = ::LoadLibraryA("iphlpapi.dll");
HMODULE hMod_netapi = ::LoadLibraryA("netapi32.dll");
do{
FARPROC proc = 0;
if (hMod_iphlpapi) proc = ::GetProcAddress(hMod_iphlpapi, "GetIfTable");
std::printf("iphlpapi:%p GetIfTable:%p\n", hMod_iphlpapi, proc);
if (!proc) break;
typedef DWORD (WINAPI *GetIfTableType)(MIB_IFTABLE *pIfTable, ULONG *pdwSize, BOOL bOrder);
GetIfTableType GetIfTable_ = reinterpret_cast<GetIfTableType>(proc);
DWORD dwSize = sizeof(MIB_IFTABLE);
GetIfTable_(0, &dwSize, FALSE);
std::printf("size:%u\n", dwSize);
std::vector<BYTE> iftablebuf(dwSize);
MIB_IFTABLE *iftable = reinterpret_cast<MIB_IFTABLE *>(&iftablebuf[0]);
if (GetIfTable_(iftable, &dwSize, FALSE) != NO_ERROR){
std::printf("GetIfTable => Error\n");
break;
}
std::printf("entries:%d\n", iftable->dwNumEntries);
for (int i = 0; i < iftable->dwNumEntries; ++i){
std::printf(" No %d\n", i+1);
MIB_IFROW *ifrow = &iftable->table[i];
std::wprintf(L" NIC Name:%s\n", ifrow->wszName);
std::string desc(ifrow->bDescr, ifrow->bDescr+ifrow->dwDescrLen);
std::printf(" Description:%s\n", desc.c_str());
std::printf(" Type:%u\n", ifrow->dwType);
std::printf(" PhysAddr:");
for (int h = 0; h < 6; ++h) std::printf("%02x", ifrow->bPhysAddr[h]);
std::printf("\n");
}
}while(0);
std::printf("****** GetAdaptorsInfo method *****\n");
do{
FARPROC proc = 0;
if (hMod_iphlpapi) proc = ::GetProcAddress(hMod_iphlpapi, "GetAdaptersInfo");
std::printf("iphlpapi:%p GetAdaptersInfo:%p\n", hMod_iphlpapi, proc);
if (!proc) break;
typedef DWORD (WINAPI *GetAdaptersInfoType)(IP_ADAPTER_INFO *pAdapterInfo, ULONG *pOutBufLen);
GetAdaptersInfoType GetAdaptersInfo_ = reinterpret_cast<GetAdaptersInfoType>(proc);
DWORD dwSize = sizeof(IP_ADAPTER_INFO);
GetAdaptersInfo_(0, &dwSize);
std::printf("size:%u\n", dwSize);
std::vector<BYTE> iaibuf(dwSize);
IP_ADAPTER_INFO *iai = reinterpret_cast<IP_ADAPTER_INFO *>(&iaibuf[0]);
if (GetAdaptersInfo_(iai, &dwSize) != NO_ERROR){
std::printf("Error GetAdaptersInfo\n");
break;
}
for (IP_ADAPTER_INFO *iter = iai; iter; iter = iter->Next){
std::printf(" ComboIndex:%d\n", iter->ComboIndex);
std::printf(" AdapterName:%s\n", iter->AdapterName);
std::printf(" Description:%s\n", iter->Description);
std::printf(" Type:%u\n", iter->Type);
std::printf(" Address:");
for (int h = 0; h < 6; ++h) std::printf("%02x", iter->Address[h]);
std::printf("\n");
}
}while(0);
std::printf("****** GetNetworkParams method *****\n");
do{
FARPROC proc = 0;
if (hMod_iphlpapi) proc = ::GetProcAddress(hMod_iphlpapi, "GetNetworkParams");
std::printf("iphlpapi:%p GetNetworkParams:%p\n", hMod_iphlpapi, proc);
if (!proc) break;
typedef DWORD (WINAPI *GetNetworkParamsType)(FIXED_INFO *pFixedInfo, ULONG *pOutBufLen);
GetNetworkParamsType GetNetworkParams_ = reinterpret_cast<GetNetworkParamsType>(proc);
DWORD dwSize = 0;
if (GetNetworkParams_(0, &dwSize) != ERROR_BUFFER_OVERFLOW){
std::printf("error GetNetworkParams for getting size\n");
break;
}
std::vector<BYTE> buf(dwSize);
FIXED_INFO *fi = reinterpret_cast<FIXED_INFO *>(&buf[0]);
DWORD rc;
if (rc = GetNetworkParams_(fi, &dwSize)){
std::printf("error GetNetworkParams for getting data\n");
break;
}
std::printf("Host Name:%s\n", fi->HostName);
std::printf("Domain Name:%s\n", fi->DomainName);
for (IP_ADDR_STRING *iter = &fi->DnsServerList; iter; iter = iter->Next){
std::printf(" DNS Servers: %s\n", iter->IpAddress.String);
}
}while(0);
std::printf("****** Netbios NCBASTAT method *****\n");
do{
FARPROC proc = 0;
if (hMod_netapi) proc = ::GetProcAddress(hMod_netapi, "Netbios");
std::printf("netapi:%p Netbios:%p\n", hMod_netapi, proc);
if (!proc) break;
typedef DWORD (WINAPI *NetbiosType)(NCB *ncb);
NetbiosType Netbios_ = reinterpret_cast<NetbiosType>(proc);
UCHAR rc;
NCB ncb;
ncb.ncb_command = NCBENUM;
LANA_ENUM le;
ncb.ncb_buffer = reinterpret_cast<UCHAR *>(&le);
ncb.ncb_length = sizeof(le);
rc = Netbios_(&ncb);
if (rc){
std::printf("error NCBENUM : %d\n", rc);
break;
}
std::printf("ncb entries:%d\n", le.length);
for (int i = 0; i < le.length; ++i){
std::printf(" No:%d\n", i);
ncb.ncb_command = NCBRESET;
ncb.ncb_lana_num = le.lana[i];
rc = Netbios_(&ncb);
if (rc){
std::printf(" No:%d NCBRESET failed (%d)\n", i, rc);
continue;
}
ncb.ncb_command = NCBASTAT;
ncb.ncb_lana_num = le.lana[i];
::strcpy(reinterpret_cast<char *>(ncb.ncb_callname), "* ");
struct {
ADAPTER_STATUS as;
NAME_BUFFER nb;
}AStatItem;
ncb.ncb_buffer = reinterpret_cast<UCHAR *>(&AStatItem);
ncb.ncb_length = sizeof(AStatItem);
rc = Netbios_(&ncb);
if (rc){
std::printf(" No:%d NCBASTAT failed (%d)\n", i, rc);
continue;
}
std::wstring name(reinterpret_cast<WCHAR *>(AStatItem.nb.name), reinterpret_cast<WCHAR *>(AStatItem.nb.name)+AStatItem.nb.name_num);
std::wprintf(L" Name:%s\n", name.c_str());
std::printf(" Address:");
for (int h = 0; h < 6; ++h) std::printf("%02x", AStatItem.as.adapter_address[h]);
std::printf("\n");
}
}while(0);
std::printf("****** Win32_NetworkAdapterConfiguration method *****\n");
// ... COM の API なので、素の C++ だけで扱うにはちょっと面倒 ...
do{
HRESULT rc;
ComPtrContainer cpc;
BStrContainer bc;
::CoInitializeEx( 0, COINIT_MULTITHREADED );
if (FAILED(rc = ::CoInitializeSecurity(0, -1, 0, 0,
RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0))){
std::printf("CoInitializeSecurity failed (%d)\n", rc);
break;
}
IWbemLocator *wl = 0;
if (FAILED(rc = ::CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<VOID **>(&wl)))){
std::printf("CoCreateInstance CLSID_WbemLocator failed (%d)\n", rc);
break;
}
cpc.Add(wl);
IWbemServices *ws = 0;
if (FAILED(rc = wl->ConnectServer(bc.Add(L"root\\cimv2"), 0, 0, 0, WBEM_FLAG_CONNECT_USE_MAX_WAIT, 0, 0, &ws ))){
std::printf("ConnectServer failed (%d)\n", rc);
break;
}
cpc.unks.push_back(ws);
if (FAILED(rc = ::CoSetProxyBlanket(ws, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 0,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE))){
std::printf("CoSetProxyBlanket failed (%d)\n", rc);
break;
}
IEnumWbemClassObject *ewco;
if (FAILED(rc = ws->ExecQuery(L"WQL", L"Select * FROM Win32_NetworkAdapterConfiguration",
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 0, &ewco)) || !ewco){
std::printf("Enum failed (%d)\n", rc);
break;
}
#if 0
if (FAILED(rc = ws->CreateInstanceEnum(L"Win32_NetworkAdapter",
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 0, &ewco)) || !ewco){
std::printf("CreateInstanceEnum failed (%d)\n", rc);
break;
}
#endif
IWbemClassObject *obj = 0;
ULONG returned = 0;
ewco->Reset();
for(int i = 0;; ++i){
ewco->Next(WBEM_INFINITE, 1, &obj, &returned);
if (returned == 0) break;
std::printf(" No:%d\n", i);
VARIANT propval;
obj->Get(L"IPAddress", 0, &propval, 0, 0);
::VariantChangeType(&propval, &propval, 0, VT_BSTR);
if (propval.vt == VT_BSTR){
std::wprintf(L" IPAddress:%s\n", propval.bstrVal);
} else if (propval.vt & (VT_ARRAY | VT_BSTR)){
SAFEARRAY *sa = V_ARRAY(&propval);
unsigned int dims = ::SafeArrayGetDim(sa); // dims は常に1 ?
std::vector<long> idx(dims);
long lb, ub;
::SafeArrayGetLBound(sa, dims, &lb);
::SafeArrayGetUBound(sa, dims, &ub);
BSTR *bstr = 0;
for (long i = lb; i <= ub; ++i){
idx[dims-1] = i;
::SafeArrayGetElement(sa, &idx[0], &bstr);
std::wprintf(L" IPAddress[%d]:%s\n", i, bstr);
}
} else std::printf(" IPAddress: failed\n");
::VariantClear(&propval);
obj->Get(L"Description", 0, &propval, 0, 0);
::VariantChangeType(&propval, &propval, 0, VT_BSTR);
if (propval.vt == VT_BSTR) std::wprintf(L" Description:%s\n", propval.bstrVal);
else std::printf(" Description: failed\n");
::VariantClear(&propval);
obj->Get(L"MACAddress", 0, &propval, 0, 0);
::VariantChangeType(&propval, &propval, 0, VT_BSTR);
int ma[6] = {0};
if (propval.vt == VT_BSTR){
std::wprintf(L" MACAddress:%s\n", propval.bstrVal);
if (std::swscanf(propval.bstrVal, L"%02x:%02x:%02x:%02x:%02x:%02x", &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5], &ma[6]) != 6){
std::printf(" convert failed\n");
}
}
else std::printf(" MACAddress: failed\n");
::VariantClear(&propval);
obj->Release();
}
}while(0);
}
[PageInfo]
LastUpdate: 2019-03-29 13:34:09, ModifiedBy: mocchi_2012
[Permissions]
view:all, edit:admins, delete/config:admins