本文是通过禁用启用网卡让IP设置生效,因为使用DhcpNotifyConfigChange方法效果不好,且容易发生溢出问题
typedef int (CALLBACK* DHCPNOTIFYPROC)(LPWSTR, LPWSTR, BOOL, DWORD, DWORD, DWORD, int);
typedef struct tagAdapterInfo
{
string strName;// 适配器名称
string strDriverDesc;// 适配器描述
string strIP; // IP地址
string strNetMask;// 子网掩码
string strNetGate;// 网关
}ADAPTER_INFO;
BOOL GetAdapterInfo();
BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex = 0);
vector<ADAPTER_INFO*> AdapterInfoVector;
//-----------------------------------------------------------------
// 取得所有网卡信息
//-----------------------------------------------------------------
BOOL GetAdapterInfo()
{
// 这里的代码适合WINDOWS2000,对于NT需要读取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
HKEY hKey, hSubKey, hNdiIntKey;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
0,
KEY_READ,
&hKey) != ERROR_SUCCESS)
return FALSE;
DWORD dwIndex = 0;
DWORD dwBufSize = 256;
DWORD dwDataType;
char szSubKey[256];
unsigned char szData[256];
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
{
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
{
dwBufSize = 256;
if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
{
if(strcmp((char*)szData, "ethernet") == 0)//判断是不是以太网卡
{
dwBufSize = 256;
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
{
ADAPTER_INFO *pAI = new ADAPTER_INFO;
pAI->strDriverDesc = (LPCTSTR)szData;
dwBufSize = 256;
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
{
pAI->strName = (LPCTSTR)szData;
RegGetIP(pAI, (LPCTSTR)szData);
}
AdapterInfoVector.push_back(pAI);// 加入到容器中
}
}
}
RegCloseKey(hNdiIntKey);
}
RegCloseKey(hSubKey);
}
dwBufSize = 256;
} /* end of while */
RegCloseKey(hKey);
return TRUE;
}
//-----------------------------------------------------------------
// 得到注册表中的IP信息
// nIndex暂时未处理
//-----------------------------------------------------------------
BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex/* =0 */)
{
ASSERT(pAI);
HKEY hKey;
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
strKeyName += lpszAdapterName;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
strKeyName.c_str(),
0,
KEY_READ,
&hKey) != ERROR_SUCCESS)
return FALSE;
unsigned char szData[256];
DWORD dwDataType, dwBufSize;
dwBufSize = 256;
if(RegQueryValueEx(hKey, "IPAddress", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
pAI->strIP = (LPCTSTR)szData;
dwBufSize = 256;
if(RegQueryValueEx(hKey, "SubnetMask", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
pAI->strNetMask = (LPCTSTR)szData;
dwBufSize = 256;
if(RegQueryValueEx(hKey, "DefaultGateway", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
pAI->strNetGate = (LPCTSTR)szData;
RegCloseKey(hKey);
return TRUE;
}
//-----------------------------------------------------------------
// 设置注册表中的IP信息
//-----------------------------------------------------------------
BOOL RegSetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)
{
HKEY hKey;
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
strKeyName += lpszAdapterName;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
strKeyName.c_str(),
0,
KEY_WRITE,
&hKey) != ERROR_SUCCESS)
return FALSE;
char mszIPAddress[100];
char mszNetMask[100];
char mszNetGate[100];
char szDnsAddr[100];
strncpy(mszIPAddress, pIPAddress, 98);
strncpy(mszNetMask, pNetMask, 98);
strncpy(mszNetGate, pNetGate, 98);
strncpy(szDnsAddr, pDnsAddress, 98);
int nIP, nMask, nGate,nDnsAddr;
int enableDHCP=0;
nIP = strlen(mszIPAddress);
nMask = strlen(mszNetMask);
nGate = strlen(mszNetGate);
nDnsAddr = strlen(szDnsAddr);
*(mszIPAddress + nIP + 1) = 0x00;
nIP += 2;
*(mszNetMask + nMask + 1) = 0x00;
nMask += 2;
*(mszNetGate + nGate + 1) = 0x00;
nGate += 2;
*(szDnsAddr + nDnsAddr + 1) = 0x00;
nDnsAddr += 2;
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);
RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );
RegCloseKey(hKey);
return TRUE;
}
//-----------------------------------------------------------------
// 设置注册表中DHCP
//-----------------------------------------------------------------
BOOL RegSetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)
{
HKEY hKey;
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
strKeyName += lpszAdapterName;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
strKeyName.c_str(),
0,
KEY_WRITE,
&hKey) != ERROR_SUCCESS)
return FALSE;
int enableDHCP=1;
char mszIPAddress[100];
char mszNetMask[100];
char mszNetGate[100];
char szDnsAddr[100];
strncpy(mszIPAddress, "0.0.0.0", 98);
strncpy(mszNetMask, "0.0.0.0", 98);
strncpy(mszNetGate, "", 98);
strncpy(szDnsAddr, "", 98);
int nIP, nMask, nGate,nDnsAddr;
nIP = strlen(mszIPAddress);
nMask = strlen(mszNetMask);
nGate = strlen(mszNetGate);
nDnsAddr=strlen(szDnsAddr);
*(mszIPAddress + nIP + 1) = 0x00;
nIP += 2;
*(mszNetMask + nMask + 1) = 0x00;
nMask += 2;
*(mszNetGate + nGate + 1) = 0x00;
nGate += 2;
*(szDnsAddr + nDnsAddr + 1) = 0x00;
nDnsAddr += 2;
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);
int errCode = RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );
RegCloseKey(hKey);
return TRUE;
}
//-----------------------------------------------------------------
// 通知IP地址的改变
//-----------------------------------------------------------------
BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
{
BOOL bResult = FALSE;
HINSTANCE hDhcpDll;
DHCPNOTIFYPROCpDhcpNotifyProc;
WCHAR wcAdapterName[256];
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
return FALSE;
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, NULL,NULL, 0) == ERROR_SUCCESS)
bResult = TRUE;
FreeLibrary(hDhcpDll);
return bResult;
}
//-----------------------------------------------------------------
// 设置IP地址
// 如果只绑定一个IP,nIndex = 0,暂时未处理一个网卡绑定多个地址
//-----------------------------------------------------------------
BOOL SetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)
{
if(!RegSetIP(lpszAdapterName, nIndex, pIPAddress, pNetMask, pNetGate,pDnsAddress))
return FALSE;
//通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)
//if(!NotifyIPChange(lpszAdapterName, nIndex, pIPAddress, pNetMask))
// return FALSE;
//通过禁用启用网卡实现IP立即生效
list<TNetCardStruct> cardList;
EnumNetCards(&cardList);
if(!cardList.empty())
{
NetCardStateChange(&cardList.front(),FALSE);
Sleep(10);
NetCardStateChange(&cardList.front(),TRUE);
}
return TRUE;
}
//-----------------------------------------------------------------
// 设置DHCP IP地址
//-----------------------------------------------------------------
BOOL SetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)
{
if(!RegSetDHCPIP(lpszAdapterName, nIndex))
return FALSE;
//通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)
//if(!NotifyDHCPIPChange(lpszAdapterName, nIndex))
// return FALSE;
//通过禁用启用网卡实现IP立即生效
list<TNetCardStruct> cardList;
EnumNetCards(&cardList);
if(!cardList.empty())
{
NetCardStateChange(&cardList.front(),FALSE);
Sleep(10);
NetCardStateChange(&cardList.front(),TRUE);
}
return TRUE;
}
/*******************************************************网卡禁用启用操作*************************************************/
NetCard.h
#ifndef NETCARD_H_H
#define NETCARD_H_H
#include <Windows.h>
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <list>
using namespace std;
// cfgmgr32.h 在Microsoft Windows 2000 DDK 中.
// 要用 CM_Get_DevNode_Status() 来查询状态.
//---------------------------------------------------------------------------
typedef struct NetCardStruct
{
DWORD Id; // 网卡设备号
string Name; // 网卡名
bool Disabled; // 当前是否禁用
bool Changed; // 是否更改过
}TNetCardStruct;
typedef TNetCardStruct* PNetCardStruct;
/*******************函数声明***********************************/
static bool GetRegistryProperty(HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
ULONG Property,
PVOID Buffer,
PULONG Length) ;
void EnumNetCards(list<TNetCardStruct> *NetDeviceList);
bool NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled) ;
/**************************************************************/
#endif
NetCard.cpp
#include "stdafx.h"
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <list>
#include <Windows.h>
#include <SetupAPI.h>
#include "NetCard.h"
//---------------------------------------------------------------------------
// EnumNetCards 枚举出网卡
//---------------------------------------------------------------------------
void EnumNetCards(list<TNetCardStruct> *NetDeviceList)
{
string DevValue;
PNetCardStruct NetCard;
DWORD Status, Problem;
LPTSTR Buffer = NULL;
DWORD BufSize = 0;
HDEVINFO hDevInfo = 0;
hDevInfo=SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES);
if(INVALID_HANDLE_VALUE==hDevInfo)
return;
SP_DEVINFO_DATA DeviceInfoData ={sizeof(SP_DEVINFO_DATA)};
HKEY hKeyClass;
char DeviceName[200];
for(DWORD DeviceId=0;SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData);DeviceId++)
{
if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS)
continue;
if(GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS , &Buffer, (PULONG)&BufSize))
DevValue = string(Buffer);
if (strcmp(DevValue.c_str(),"Net") == 0)
{
DevValue = "";
if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME , &Buffer, (PULONG)&BufSize))
DevValue = Buffer;
if (strcmp(DevValue.c_str(),"ROOT") != 0)
{
NetCard = new TNetCardStruct;
NetCard->Id = DeviceId;
NetCard->Name = "<Unknown Device>";
if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER , &Buffer, (PULONG)&BufSize))
if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC , &Buffer, (PULONG)&BufSize))
NetCard->Name = Buffer;
NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);
NetCard->Changed = false;
NetDeviceList->push_back(*NetCard);
}
}
}
}
//---------------------------------------------------------------------------
bool GetRegistryProperty(HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
ULONG Property,
PVOID Buffer,
PULONG Length)
{
while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData, Property, NULL, (BYTE *)*(TCHAR **)Buffer, *Length, Length))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (*(LPTSTR *)Buffer) LocalFree(*(LPTSTR *)Buffer);
*(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR,*Length);
}
else return false;
}
return (*(LPTSTR *)Buffer)[0];
}
//---------------------------------------------------------------------------
// NetCardStateChange 网卡的启用与禁用
// NetCardPoint 是 PNetCardStruct 的指针.
// Enabled true = 启用 false = 禁用
//---------------------------------------------------------------------------
bool NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled)
{
PNetCardStruct NetCard = (PNetCardStruct)NetCardPoint;
DWORD DeviceId = NetCard->Id;
HDEVINFO hDevInfo = 0;
if (INVALID_HANDLE_VALUE == (hDevInfo =
SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT |DIGCF_ALLCLASSES)))
return false;
SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
DWORD Status, Problem;
if (!SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData))
return false;
if (CM_Get_DevNode_Status(&Status, &Problem,
DeviceInfoData.DevInst,0) != CR_SUCCESS)
return false;
SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.Scope = DICS_FLAG_GLOBAL;
if (Enabled)
{
if (!((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem)))
{
NetCard->Disabled = false;
return false;
}
PropChangeParams.StateChange = DICS_ENABLE;
}
else
{
if ((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem))
{
NetCard->Disabled = true;
return false;
}
if (!((Status & DN_DISABLEABLE) && (CM_PROB_HARDWARE_DISABLED != Problem)))
return false;
PropChangeParams.StateChange = DICS_DISABLE;
}
if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData,
(SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams)))
return false;
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DeviceInfoData))
return false;
if (CM_Get_DevNode_Status(&Status, &Problem,
DeviceInfoData.DevInst,0) == CR_SUCCESS)
NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);
return true;
}
设置静态IP
GetAdapterInfo();
char szIP[16]="111.111.111.11";
char szMask[16]="255.255.255.10";
char szGate[16]="111.111.111.1";
char dnsAddress[16]="222.222.222.1";
unsigned char *pIP, *pMask, *pGate;
DWORD dwIP, dwMask, dwGate;
if(SetIP(AdapterInfoVector[0]->strName.c_str(), 0, szIP, szMask, szGate,dnsAddress) == TRUE)
::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION);
else
::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);
设置动态IP
GetAdapterInfo();
if(SetDHCPIP(AdapterInfoVector[0]->strName.c_str(), 0 ) == TRUE)
::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION);
else
::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);