Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

最近の作業部屋活動履歴

2023-04-16
2023-03-24
2023-03-22
2023-01-25

最近のWikiの更新 (Recent Changes)

2023-04-16
2023-03-24
2023-01-25
2023-01-08
2023-01-07

Wikiガイド(Guide)

サイドバー (Side Bar)

ネットワークアダプタの情報を色んなAPIで取得するプログラム

概要

ネットワークアダプタの情報を取得する方法は幾つかあるようです。 それぞれの方法で、取得できる内容や、場合によって取得できる/できない、等がある かもしれませんので、挙動を確認しやすいように、各APIを呼び出して、そのまま printf 出力するプログラムを作ってみました。

下記ソースで試せる API 一覧

ソース

ビルドする際は、 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);
}