操作Windows网络连接相关的API,貌似没有暴漏出设置静态IP的方法,搜索了些资料最后,借助Windows的WMI(Windows Management Instruction) 来操控网络适配器了。
方法如下:
How to disable dhcp for a specific network adapter?
Recently, I am programming of android USB reverse tether. On the windows platform, a Remote NDIS network adapter was created. By default, it turns on the DHCP, however I want to disable it in codes. Is there any Win32 API to do it?
Use the WMI to fix it.
I coded one helper class to query or modify the network adapter settings
Here is the class defination
//Header file
#include <string>
struct NetWorkAdapterSetting
{
unsigned int nIfIndex;
bool bEnableDHCP;
std::wstring strIPAddress;
std::wstring strNetsubMask;
NetWorkAdapterSetting()
{
nIfIndex = 0;
bEnableDHCP = false;
}
};
struct IWbemServices;
struct IWbemLocator;
class UsbReverseTether
{
public:
UsbReverseTether(void);
~UsbReverseTether(void);
bool Init();
void Uninit();
bool getConnectedNetworkAdapterSettings( NetWorkAdapterSetting& adapterSetting );
bool enableStaticIPAddress(
unsigned int nIfIndex,
const std::wstring& strIPAddress,
const std::wstring& strNetsubMask );
private:
IWbemServices* m_pWbemSvc;
IWbemLocator* m_pWbemLoc;
};
The source file
//COM init + Prepare the WMI Service + COM unit
bool UsbReverseTether::Init()
{
HRESULT hr = CoInitializeEx( 0, COINIT_MULTITHREADED );
if ( FAILED( hr ) )
{
LOG_ERR( "Failed to initialize COM library. Error code = 0x%x", hr );
return false;
}
hr = CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if ( FAILED( hr ) )
{
LOG_ERR( "Failed to initialize security. Error code = 0x%x", hr );
CoUninitialize();
return false;
}
hr = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &m_pWbemLoc );
if (FAILED(hr))
{
LOG_ERR( "Failed to create IWbemLocator object. Err code = 0x%x", hr );
CoUninitialize();
return false;
}
// Connect to the local root\cimv2 namespace
// and obtain pointer m_pWbemSvc to make IWbemServices calls.
hr = m_pWbemLoc->ConnectServer(
L"ROOT\\CIMV2",
NULL,
NULL,
0,
NULL,
0,
0,
&m_pWbemSvc
);
if (FAILED(hr))
{
LOG_ERR( "Could not connect. Error code = 0x%x", hr );
m_pWbemLoc->Release();
m_pWbemLoc = NULL;
CoUninitialize();
return false;
}
LOG_TRACE( "Connected to ROOT\\CIMV2 WMI namespace" );
// Set the proxy so that impersonation of the client occurs.
hr = CoSetProxyBlanket(m_pWbemSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr))
{
LOG_ERR( "Could not set proxy blanket. Error code = 0x%x", hr );
m_pWbemSvc->Release();
m_pWbemLoc->Release();
CoUninitialize();
return false;
}
return true;
}
void UsbReverseTether::Uninit()
{
if ( NULL != m_pWbemSvc )
{
m_pWbemSvc->Release();
m_pWbemSvc = NULL;
}
if ( NULL != m_pWbemLoc )
{
m_pWbemLoc->Release();
m_pWbemLoc = NULL;
}
CoUninitialize();
}
Query the USB Remote RNDIS network adapter setting
bool UsbReverseTether::getConnectedNetworkAdapterSettings( NetWorkAdapterSetting& adapterSetting )
{
HRESULT hr = S_OK;
IEnumWbemClassObject* pEnumerator = NULL;
hr = m_pWbemSvc->ExecQuery( _bstr_t("WQL"),
_bstr_t("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE AND ServiceName=\'usb_rndisx\'"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator );
if ( FAILED( hr ) )
{
LOG_ERR( "ExecQuery. Error code = 0x%x", hr );
return false;
}
bool bOK = false;
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
int nCount = 0;
while ( pEnumerator )
{
hr = pEnumerator->Next( WBEM_INFINITE, 1, &pclsObj, &uReturn );
if(0 == uReturn)
{
break;
}
++nCount;
if ( nCount > 1 )
{
LOG_WARN( "There is more than 1 connected usb network adapter" );
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"Index", 0, &vtProp, 0, 0);
if ( FAILED( hr ) )
{
LOG_ERR( "IWbemClassObject::Getproperty(Index). Error code = 0x%x", hr );
break;
}
adapterSetting.nIfIndex = vtProp.uintVal;
VariantClear(&vtProp);
hr = pclsObj->Get(L"DHCPEnabled", 0, &vtProp, 0, 0);
if ( FAILED( hr ) )
{
LOG_ERR( "IWbemClassObject::Getproperty(DHCPEnabled). Error code = 0x%x", hr );
break;
}
adapterSetting.bEnableDHCP = vtProp.boolVal;
VariantClear(&vtProp);
hr = pclsObj->Get(L"IPAddress", 0, &vtProp, 0, 0);
if ( FAILED( hr ) )
{
LOG_ERR( "IWbemClassObject::Getproperty(IPAddress). Error code = 0x%x", hr );
break;
}
SAFEARRAY* psa = vtProp.parray;
if( psa )
{
void **p = (void **)psa->pvData;
wchar_t *wstr = (wchar_t *)*p;
adapterSetting.strIPAddress = wstr;
}
VariantClear(&vtProp);
hr = pclsObj->Get(L"IPSubnet", 0, &vtProp, 0, 0);
if ( FAILED( hr ) )
{
LOG_ERR( "IWbemClassObject::Getproperty(SubnetMask). Error code = 0x%x", hr );
break;
}
if( psa )
{
void **p = (void **)psa->pvData;
wchar_t *wstr = (wchar_t *)*p;
adapterSetting.strNetsubMask = wstr;
}
VariantClear(&vtProp);
bOK = true;
}
return bOK;
}
Enable static IP Address
bool UsbReverseTether::enableStaticIPAddress( unsigned int nIfIndex, const std::wstring& strIPAddress, const std::wstring& strNetsubMask )
{
HRESULT hr = S_OK;
BSTR MethodName = _bstr_t(L"EnableStatic");
BSTR ClassName = _bstr_t(L"Win32_NetworkAdapterConfiguration");
IWbemClassObject* pClass = NULL;
hr = m_pWbemSvc->GetObject( ClassName, 0, NULL, &pClass, NULL);
if ( FAILED( hr ) )
{
LOG_ERR( "GetObject. Error code = 0x%x", hr );
return false;
}
IWbemClassObject* ppInSignature = NULL;
hr = pClass->GetMethod( L"EnableStatic",0, &ppInSignature, NULL );
if ( FAILED( hr ) )
{
LOG_ERR( "GetMethod. Error code = 0x%x", hr );
return false;
}
IWbemClassObject* pInputParaInstance = NULL;
hr = ppInSignature->SpawnInstance(0, &pInputParaInstance);
if ( FAILED( hr ) )
{
LOG_ERR( "SpawnInstance. Error code = 0x%x", hr );
return false;
}
long aindex[]={0};
BSTR ipaddress = SysAllocString( strIPAddress.c_str() );
SAFEARRAY *ip_list = SafeArrayCreateVector(VT_BSTR,0,1);
SafeArrayPutElement(ip_list,aindex, ipaddress );
VARIANT varIPAddress;
varIPAddress.vt = VT_ARRAY|VT_BSTR;
varIPAddress.parray = ip_list;
hr = pInputParaInstance->Put( L"IPAddress", 0, &varIPAddress, 0 );
if ( FAILED( hr ) )
{
LOG_ERR( "Put(IPAddress). Error code = 0x%x", hr );
SysFreeString( ipaddress );
return false;
}
SAFEARRAY *mask_list = SafeArrayCreateVector(VT_BSTR,0,1);
BSTR netsubMask = SysAllocString( strNetsubMask.c_str() );
SafeArrayPutElement(mask_list,aindex, netsubMask );
VARIANT varSubnetMask;
varSubnetMask.vt = VT_ARRAY|VT_BSTR;
varSubnetMask.parray = mask_list;
hr = pInputParaInstance->Put(L"SubnetMask", 0,
&varSubnetMask, 0);
if ( FAILED( hr ) )
{
SysFreeString( netsubMask );
LOG_ERR( "Put(SubnetMask). Error code = 0x%x", hr );
return false;
}
wchar_t className[100] = {0};
swprintf( className, 100, L"Win32_NetworkAdapterConfiguration.Index=%d", nIfIndex );
BSTR indexClassName = _bstr_t(className);
IWbemClassObject* ppOutSignature = NULL;
hr = m_pWbemSvc->ExecMethod(indexClassName, _bstr_t(L"EnableStatic"), 0,
NULL, pInputParaInstance, &ppOutSignature, NULL);
if ( FAILED( hr ) )
{
SysFreeString( ipaddress );
SysFreeString( netsubMask );
LOG_ERR( "ExecMethod(EnableStatic). Error code = 0x%x", hr );
return false;
}
VARIANT ret_value;
hr = ppOutSignature->Get(L"ReturnValue", 0, &ret_value, 0, 0);
int bResult = V_I4(&ret_value);
SysFreeString( ipaddress );
SysFreeString( netsubMask );
return true;
}