Introduction
This is one way of changing DNS in C++ using Iphlpapi.h, register, and two undocumented Windows APIs. It's a simple program, no UI for you, sorry...
- Use
GetAdaptersInfo
to get adapters information. - Then use
GetPerAdapterInfo
to get information for every ethernet network card. The information contains DNS list. - Use register to set the DNS by open HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\
Interfaces\\lpszAdapterName, the name is got from GetAdaptersInfo
. - Use
DhcpNotifyConfigChange
to notify the IP change. - Use
DnsFlushResolverCache
to flush the DNS.
Using the Code
- Use
GetAdaptersInfo
:
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) ==
ERROR_BUFFER_OVERFLOW ) {
delete pAdapterInfo;
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
pAdapterInfoBkp = pAdapterInfo;
}
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
{
do{
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) {
}
pAdapterInfo = pAdapterInfo->Next;
}while(pAdapterInfo);
FlushDNS();
}
- Use
GetPerAdapterInfo
:
if( GetPerAdapterInfo(
pAdapterInfo->Index,
pPerAdapterInfo,
&ulPerAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) {
delete pPerAdapterInfo;
pPerAdapterInfo = (IP_PER_ADAPTER_INFO*)new char[ulPerAdapterInfoSize];
pPerAdapterInfoBkp = pPerAdapterInfo;
}
DWORD dwRet;
if((dwRet = GetPerAdapterInfo(
pAdapterInfo->Index,
pPerAdapterInfo,
&ulPerAdapterInfoSize)) == ERROR_SUCCESS)
{
AdaptInfo tmpadpif;
pAddrStr = pPerAdapterInfo->DnsServerList.Next;
strncpy(tmpadpif.AdapterName, pAdapterInfo->AdapterName,
sizeof(pAdapterInfo->AdapterName));
tmpadpif.NameSever = pPerAdapterInfo->DnsServerList.IpAddress.String;
cout<<pPerAdapterInfo->DnsServerList.IpAddress.String<<endl;
char tmp[16];
strcpy( tmp, "172.16.227.4");
if ( strcmp(pPerAdapterInfo->DnsServerList.IpAddress.String, tmp) == 0 )
{
return 0;
}
while(pAddrStr)
{
tmpadpif.NameSever += ",";
tmpadpif.NameSever += pAddrStr->IpAddress.String;
cout<<pAddrStr->IpAddress.String<<endl;
pAddrStr = pAddrStr->Next;
}
vecAdpif.push_back( tmpadpif );
RegSetDNS( tmpadpif.AdapterName, tmp);
NotifyIPChange(pAdapterInfo->AdapterName);
}
- Open registry to set DNS or IP addr. For this part, please refer to the download code.
- We have something fresh here:
typedef int (CALLBACK* DNSFLUSHPROC)();
typedef int (CALLBACK* DHCPNOTIFYPROC)
(LPWSTR, LPWSTR, BOOL, DWORD, DWORD, DWORD, int);
- After setting DNS in registy, we need to inform the system about the change. Now we use Windows undocumented API:
DhcpNotifyConfigChange
. It is located in dhcpcsvc.dll.
BOOL DhcpNotifyConfigChange(
LPWSTR lpwszServerName, LPWSTR lpwszAdapterName, BOOL bNewIpAddress, DWORD dwIpIndex, DWORD dwIpAddress, DWORD dwSubNetMask, int nDhcpAction );
Please refer to the code.
- Flush DNS, use another Windows undocumented API:
DnsFlushResolverCache
, located in dnsapi.dll.
DnsFlushResolverCache();
- It's ok now.
Points of Interest
I have not learned how to use WMI in VC++. Sigh, it's not a good way to change Ipaddr
and DNS in registy. netsh is not good too. If anyone has a better idea, please share with us.