出处:http://www.cppblog.com/lizao2/archive/2012/10/11/193147.aspx
源代码运行效果图如下:

设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API:DhcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
一、获取适配器名称
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
1.1 调用IP helper API取得适配器名称

1.2 读取注册表取得适配器名称
在Windows2000中可以通过遍历 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\000n\ (n是从0开始编号的数字)所有接口, 在Windows NT中可以读取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards中的信息,下面以Windows2000为例:


二、将IP信息写入注册表
代码如下:

三、调用DhcpNotifyConfigChange通知配置的改变
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下:

具体调用代码如下:

四.临时修改ip为自动获取,重启后恢复手动配置。把传入参数改成下面的即可。
if((pDhcpNotifyProc)(NULL, wcAdapterName, FALSE,0,0,0,1) == ERROR_SUCCESS)
说明,本方法在win7下无效,DhcpNotifyConfigChange返回50,ERROR_NOT_SUPPORTED,The request is not supported.
因此尝试网卡重启的方法:
出处:http://blog.****.net/bbdxf/article/details/7548443
Windows下程序修改IP的三种方法
以下讨论的平台依据是Window XP + SP1, 不考虑Windows其它版本的兼容性问题, 但对NT系列的系统, 理论上是通用的.
方法一: 网卡重启
更改Windows网卡属性选项中IP地址, 通过对比前后注册表, 可以发现以下几处发生变化
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
其中{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}是网卡名称(AdapterName), 不同的网卡, 不同的接入位置, 不同的接入的时间, 对应的值都不一样, 它的值是第一次接入系统时, 由系统生成的GUID值.
此处CurrentControlSet实际是ControlSet001的别名.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
是主要的设置处.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
对一些服务有影响, 如不设置, 用netstat可以看到原来的IP地址仍处于监听状态(?).
但为了使设置生效, 还有很重要的一步, 即重启网卡.
更改网卡的配置, 一般而言需要重启网卡, 如
Linux系统, 只需运行
#ifconfig eth0 down
#ifconfig eht0 up
就可以实现网卡的重启.
Windows环境下的步骤与之类似: 先禁用本地连接(网卡), 再启用本地连接(网卡). 但没有相应的命令或者直接的API. 所幸的是DDK提供一套设备安装函数, 用于控制系统设备, 包括控制设备的状态改变.
/****************************************************************************************
Purpose: change state of the selected device
Input : hDevInfo device info set
pDeviceInfoData selected device info
NewState one of enable/disable
Output : TRUE for success, FALSE for failed
****************************************************************************************/
BOOL ChangeDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDeviceInfoData, DWORD NewState)
{
SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};
SP_DEVINSTALL_PARAMS devParams;
if (!pDeviceInfoData) {
return FALSE;
}
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
PropChangeParams.StateChange = NewState;
PropChangeParams.HwProfile = 0;
if (!SetupDiSetClassInstallParams(hDevInfo,pDeviceInfoData,
(SP_CLASSINSTALL_HEADER *)&PropChangeParams,sizeof(PropChangeParams))
|| !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,pDeviceInfoData)) {
return FALSE;
}
reutrn TRUE;
}
/* hDevInfo如何得到***********************************************************/
m_hDevInfo = SetupDiGetClassDevs(
(LPGUID) &GUID_DEVCLASS_NET, /* GUID_DEVCLASS_NET表示仅列出网络设备 */
NULL,
this->m_hWnd,
DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == m_hDevInfo) {
return FALSE;
}
/* pDeviceInfoData如何得到**************************************************/
k = 0;
while (SetupDiEnumDeviceInfo(m_hDevInfo, k ,&DeviceInfoData)) {
k++;
if (CR_SUCCESS != CM_Get_DevNode_Status(&Status, &Problem,
DeviceInfoData.DevInst,0)) {
continue;
}
if ((Status & DN_NO_SHOW_IN_DM)) {
continue;
}
if (GetRegistryProperty(m_hDevInfo,
&DeviceInfoData,
SPDRP_FRIENDLYNAME,
&pBuffer,
&Length)) {
m_Adapter[adapter_num].index = k - 1; /* 当前网卡在设备信息集中的索引 */
_tcscpy(m_Adapter[adapter_num].desc, pBuffer); /* 当前网卡 */
GetRegistryProperty(m_hDevInfo,
&DeviceInfoData,
SPDRP_DRIVER,
&pBuffer,
&Length);
_tcscpy(m_Adapter[adapter_num].driver, pBuffer);
adapter_num++;
}
}
/* GetRegistryProperty是对SetupDiGetDeviceRegistryProperty封装***************/
BOOL GetRegistryProperty(HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
ULONG Property,
LPTSTR* Buffer,
PULONG Length)
{
while (!SetupDiGetDeviceRegistryProperty(
DeviceInfoSet,
DeviceInfoData,
Property,
NULL,
(PBYTE)(*Buffer),
*Length,
Length
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (*(LPTSTR *)Buffer)
LocalFree(*(LPTSTR *)Buffer);
*Buffer = (LPTSTR)LocalAlloc(LPTR, *Length);
}else {
return FALSE;
}
}
return TRUE;
}
/* m_Adapter的数据结构 */
typedef struct adapter_info_s {
char name[NAME_LEN]; /* 内部设备名, UUID的字符串形式 */
char desc[NAME_LEN]; /* 网卡描述 */
char driver[NAME_LEN]; /* 网卡在注册表中的位置, 如{4D36E972-E325-11CE-BFC1-08002BE10318}\0011
实际完整的键名为System\\CurrentControlSet\\Control\\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0011
该键包含的内容与SetupDiGetDeviceRegistryProperty得到的设备属性基本相同
如NetCfgInstanceId即为内部设备名 DriverDesc为设备描述 */
int index;
}adapter_info_t;
/*****************************************************************************
用何名称区分不同的网卡
有如下名称可供选择
本地连接名, 这是系统使用的方法, 调用的是netman.dll中的未公开函数HrLanConnectionNameFromGuidOrPath(其原型笔者正在调试之中, 成功之后会另行撰文); 其实也可从注册表中获得HKLM\System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Connection\Name
网卡类型描述
设备友好名 它与网卡类型描述基本相同, 当存在同种类型的网卡, 它会加#n(n = 2, 3, 4...)以示区分
如本程序中笔者即以设备友好名区分网卡
*****************************************************************************/
/* 重启网卡的过程************************************************************/
k = pAdapter->GetCurSel(); /* m_Adapter[k]即当前网卡 */
if (SetupDiEnumDeviceInfo(m_hDevInfo, m_Adapter[k].index ,&DeviceInfoData))
{
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_DISABLE); /* 禁用网卡 */
ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_ENABLE); /* 启用网卡 */
/* 重启网卡, 一般情况下, 以下命令相当于前两命令的组合. 但我仍建议使用前者 */
// ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_PROPCHANGE);
SetCursor(hCursor);
}
/* 扫尾工作 */
SetupDiDestroyDeviceInfoList(m_hDevInfo);
总结: 通过网卡重启更改IP的方法有两个步骤: 修改注册表, 重启网卡. 重启网卡的全过程上面已作描述. 注册表修改的内容为文中列出四个主要项, 如{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}的网卡名称即是内部设备名, 在adapter结构中已给出. 整个注册表修改的过程比较简单, 本文不加叙述.
方法二:未公开函数
Windows系统中, 更改Windows网卡属性选项中IP地址, 可以即时使更改生效, 并且没有重启网卡的过程. 系统自带的netsh也能通过命令行或脚本文件的形式, 完成更改IP的功能时, 也不需要重启网卡
同时也有很多共享软件, 可以实现同样的功能, 常见IP地址更改软件有IPFreeSet, IPChanger, IPProfile, IPHelp, IPSet, SNet等.
笔者通过分析netsh发现一个未公开函数, 即用netcfgx.dll封装的dhcpcsvc.dll中DhcpNotifyConfigChange函数
具体的方法参见VCKB 25期 王骏先生的 "不重起Windows直接更改IP地址", 他得到的函数原型比我准确, 思路也很清晰.
分析上述共享软件时, 发现其技术要点不外乎三种: 使用未公开函数, 调用netsh命令, 重启网卡硬件. 调用netsh命令的实质还是使用未公开函数
使用未公开函数的有: IPFreeSet, IPChanger
调用netsh命令的有 : IPHelp, IPSet. 两者都是用Delphi开发的.
重启网卡硬件: IPSwitcher
速度比较: 因为netsh本身的实现是调用netcfgx.dll, netcfgx.dll封装了对未公开函数的使用, 故效率相对较低. 在一台CPU:PIII500/RAM:256/XP的系统中, IPHelp需要6~7秒才能完成, 而IPFreeSet只需要1~2秒.
方法三:一卡多IP
除以上两个方法外, 笔者再介绍一种方法. 无论是在Windows下还是在Linux下, 一块网卡都可同时具有多个IP地址. 根据TCP/IP原理, 在网络层标识通信节点是IP地址, 在链路层上的则是MAC地址. 只要通过ARP, 将多个IP与一个MAC对应起来, 就可实现一网卡多IP(其实是一MAC多IP). 系统本身也有相应的设置选项, 如windows是通过TCP/IP属性的高级选项添加的, Linux下可由ifconfig命令添加.
iphlpapi提供AddIPAddress和DelIPAddress. 如果能先加入新的IP, 再去除原来的IP, 即可实现IP地址的更改.
具体内容参见我下篇文章"iphlpapi"的使用
出处:http://blog.****.net/delbboy/article/details/7446409
本文是通过禁用启用网卡让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);
-