Windows多网卡配置ICS网络共享C++实现

xingyun86 2021-8-7 912

Windows多网卡配置ICS网络共享C++实现

#include <unordered_map>
#ifdef _MSC_VER
#include <WinSock2.h>
#include <NetCon.h>
#define MAX_PATH_LEN   MAX_PATH
#define popen   _popen
#define pclose   _pclose
#else
#include <unistd.h>
#include <limits.h>
#define MAX_PATH_LEN   PATH_MAX 
#endif
class NetConProperties
{
public:
	GUID guidId;
private:
	/* [string] */ LPCWSTR pszwName;
	/* [string] */ LPCWSTR pszwDeviceName;
public:
	NETCON_STATUS Status;
	NETCON_MEDIATYPE MediaType;
	DWORD dwCharacter;
	CLSID clsidThisObject;
	CLSID clsidUiObject;
	std::wstring wszwName;
	std::wstring wszwDeviceName;
private:
	void __init(const NETCON_PROPERTIES* pntp)
	{
		memcpy(this, pntp, sizeof(NETCON_PROPERTIES));
		this->wszwName = this->pszwName;
		this->wszwDeviceName = this->pszwDeviceName;
		this->pszwName = this->pszwDeviceName = NULL;
	}
	void __init(const NETCON_PROPERTIES& ntp)
	{
		memcpy(this, &ntp, sizeof(ntp));
		this->wszwName = this->pszwName;
		this->wszwDeviceName = this->pszwDeviceName;
		this->pszwName = this->pszwDeviceName = NULL;
	}
public:
	NetConProperties(const NETCON_PROPERTIES& ntp)
	{
		__init(ntp);
	}
	NetConProperties(const NETCON_PROPERTIES* pntp)
	{
		__init(pntp);
	}
	NetConProperties& operator =(const NETCON_PROPERTIES& ntp)
	{
		__init(ntp);
	}
};
class ComNetSharingManager
{
public:
	ComNetSharingManager()
	{
		if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
		{
			CoInitialize(NULL);
		}
		// init security to enum RAS connections
		CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
		HRESULT hr = ::CoCreateInstance(__uuidof(NetSharingManager), NULL, CLSCTX_ALL, __uuidof(INetSharingManager), (void**)&pNSM);
		if (!pNSM)
		{
			wprintf(L"failed to create NetSharingManager object\r\n");
		}
	}
	~ComNetSharingManager()
	{
		CoUninitialize();
	}
private:
	INetSharingManager* pNSM = NULL;
public:
	HRESULT EnumShareNet(std::unordered_map<std::wstring, NetConProperties>& mapNCP)
	{
		INetConnection* pNC = NULL;
		INetSharingConfiguration* pNSC = NULL;
		IEnumVARIANT* pEV = NULL;
		IUnknown* pUnk = NULL;
		INetSharingEveryConnectionCollection* pNSECC = NULL;
		INetSharingConfiguration* pNSCSrc = NULL;
		INetSharingConfiguration* pNSCDst = NULL;
		INT nMaxRetryNum = 10;
		VARIANT_BOOL bSharingEnabled = VARIANT_TRUE;
		HRESULT hr = pNSM->get_EnumEveryConnection(&pNSECC);
		VARIANT v = { 0 };
		VariantInit(&v);
		if (!pNSECC)
		{
			wprintf(L"failed to get EveryConnectionCollection!\r\n");
			return S_FALSE;
		}
		hr = pNSECC->get__NewEnum(&pUnk);
		if (pUnk)
		{
			hr = pUnk->QueryInterface(__uuidof(IEnumVARIANT), (void**)&pEV);
			pUnk->Release();
		}
		while (S_OK == pEV->Next(1, &v, NULL))
		{
			if (V_VT(&v) == VT_UNKNOWN)
			{
				V_UNKNOWN(&v)->QueryInterface(__uuidof(INetConnection), (void**)&pNC);
				if (pNC)
				{
					NETCON_PROPERTIES* pNP = NULL;
					hr = pNC->GetProperties(&pNP);
					if (SUCCEEDED(hr))
					{
						mapNCP.emplace(pNP->pszwDeviceName, NetConProperties(pNP));
						pNC->Release();
					}
				}
			}
		}
		return hr;
	}
	HRESULT AddShareNet(LPCWSTR wSrcDeviceName, LPCWSTR wDstDeviceName)
	{
		INetConnection* pNC = NULL;
		INetSharingConfiguration* pNSC = NULL;
		IEnumVARIANT* pEV = NULL;
		IUnknown* pUnk = NULL;
		INetSharingEveryConnectionCollection* pNSECC = NULL;
		INetSharingConfiguration* pNSCSrc = NULL;
		INetSharingConfiguration* pNSCDst = NULL;
		INT nMaxRetryNum = 10;
		VARIANT_BOOL bSharingEnabled = VARIANT_TRUE;
		HRESULT hr = pNSM->get_EnumEveryConnection(&pNSECC);
		VARIANT v = { 0 };
		VariantInit(&v);
		if (!pNSECC)
		{
			wprintf(L"failed to get EveryConnectionCollection!\r\n");
			return S_FALSE;
		}
		hr = pNSECC->get__NewEnum(&pUnk);
		if (pUnk)
		{
			hr = pUnk->QueryInterface(__uuidof(IEnumVARIANT), (void**)&pEV);
			pUnk->Release();
		}
		while (S_OK == pEV->Next(1, &v, NULL))
		{
			if (V_VT(&v) == VT_UNKNOWN)
			{
				V_UNKNOWN(&v)->QueryInterface(__uuidof(INetConnection), (void**)&pNC);
				if (pNC)
				{
					NETCON_PROPERTIES* pNP = NULL;
					pNC->GetProperties(&pNP);
					if (SUCCEEDED(hr))
					{
						if (pNP->Status == NCS_CONNECTED)
						{
							hr = pNSM->get_INetSharingConfigurationForINetConnection(pNC, &pNSC);
							if (!wcscmp(pNP->pszwDeviceName, wSrcDeviceName))
							{
								pNSCSrc = pNSC;
							}
							else if (!wcscmp(pNP->pszwDeviceName, wDstDeviceName))
							{
								pNSCDst = pNSC;
							}
							else
							{
								pNSC->Release();
							}
						}
						pNC->Release();
					}
				}
			}
		}
		if (pNSCSrc != NULL && pNSCDst != NULL)
		{
			hr = pNSCSrc->DisableSharing();
			hr = pNSCDst->DisableSharing();
			bSharingEnabled = VARIANT_TRUE;
			while (SUCCEEDED(hr = pNSCSrc->get_SharingEnabled(&bSharingEnabled)) && (bSharingEnabled != VARIANT_FALSE) && (nMaxRetryNum--))
			{
				Sleep(100);
			}
			hr = pNSCSrc->EnableSharing(ICSSHARINGTYPE_PUBLIC);
			hr = pNSCDst->EnableSharing(ICSSHARINGTYPE_PRIVATE);
		}
		if (pNSCSrc != NULL)
		{
			pNSCSrc->Release();
		}
		if (pNSCDst != NULL)
		{
			pNSCDst->Release();
		}
		return hr;
	}
	std::string AddIp(const std::string& name, const std::string& addr, const std::string& mask, const std::string& gateway, const std::string& gwmetric="1")
	{
		std::string cmd = "netsh interface ip set address name=\"" + name + "\" source=static addr=" + addr + " mask=" + mask + " gateway=" + gateway + " gwmetric="+ gwmetric;
		return RunCmd("cmd /c " + cmd);
	}
private:
	std::string RunCmd(const std::string& cmd)
	{
		std::string ret = ("");
		FILE* f = popen((cmd + " 2>&1").c_str(), "r");
		if (f != nullptr)
		{
			size_t s = 0;
			char d[MAX_PATH_LEN] = { 0 };
			while (!feof(f))
			{
				s = fread(d, sizeof(char), sizeof(d) / sizeof(char), f);
				if (s > 0)
				{
					ret.append(d, s);
				}
			}
			pclose(f);
		}
		else
		{
			printf("popen %s error:(%d),%s.\n", cmd.c_str(), errno, strerror(errno));
		}
		return ret;
	}
};

调用方法:

配置Intel(R) Ethernet Connection (7) I219-V为外网,VIA Velocity-Family Gigabit Ethernet Adapter为内网,外网共享给内网,并给内网配置新的ip网段。

int main(int argc, char ** argv)
{
	setlocale(LC_ALL, "chs");
	std::cout << "Hello CMake." << std::endl;
	ComNetSharingManager cnsm = {};
	std::unordered_map<std::wstring, NetConProperties> mapNCP = {};
	{
		std::string addr = "192.168.1.254";
		std::string mask = "255.255.255.0";
		std::string gateway = "192.168.1.254";
		std::wstring wSrcDeviceName = L"Intel(R) Ethernet Connection (7) I219-V";
		std::wstring wDstDeviceName = L"VIA Velocity-Family Gigabit Ethernet Adapter";
		
		if (SUCCEEDED(cnsm.EnumShareNet(mapNCP)) && SUCCEEDED(cnsm.AddShareNet(wSrcDeviceName.c_str(), wDstDeviceName.c_str())))
		{
			for (auto it : mapNCP)
			{
				wprintf(L"%s,%s,%d\n", it.second.wszwDeviceName, it.second.wszwName.c_str(), it.second.Status);
			}
			if (mapNCP.find(wDstDeviceName) != mapNCP.end())
			{
				cnsm.AddIp(WToANSI(mapNCP.at(wDstDeviceName).wszwName), addr, mask, gateway);
			}
		}
	}
	return 0;
}


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回