C++不重起Windows直接更改IP地址

出处: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.csdn.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.csdn.net/delbboy/article/details/7446409


本文是通过禁用启用网卡让IP设置生效,因为使用DhcpNotifyConfigChange方法效果不好,且容易发生溢出问题

[cpp]  view plain  copy
  1. typedef int (CALLBACK* DHCPNOTIFYPROC)(LPWSTRLPWSTRBOOLDWORDDWORDDWORDint);  
  2.   
  3. typedef struct tagAdapterInfo  
  4. {  
  5. string strName;// 适配器名称  
  6. string strDriverDesc;// 适配器描述  
  7. string strIP; // IP地址  
  8. string strNetMask;// 子网掩码  
  9. string strNetGate;// 网关  
  10. }ADAPTER_INFO;  
  11.   
  12. BOOL GetAdapterInfo();  
  13. BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex = 0);  
  14.   
  15. vector<ADAPTER_INFO*> AdapterInfoVector;  
  16.   
  17.   
  18. //-----------------------------------------------------------------  
  19. // 取得所有网卡信息  
  20. //-----------------------------------------------------------------  
  21. BOOL GetAdapterInfo()  
  22. {  
  23. // 这里的代码适合WINDOWS2000,对于NT需要读取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards  
  24. HKEY hKey, hSubKey, hNdiIntKey;  
  25.   
  26.   
  27. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  28. "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",  
  29. 0,  
  30. KEY_READ,  
  31. &hKey) != ERROR_SUCCESS)  
  32. return FALSE;  
  33.   
  34. DWORD dwIndex = 0;  
  35. DWORD dwBufSize = 256;  
  36. DWORD dwDataType;  
  37. char szSubKey[256];  
  38. unsigned char szData[256];  
  39.   
  40. while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)  
  41. {  
  42. if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)  
  43. {   
  44. if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)  
  45. {  
  46. dwBufSize = 256;  
  47. if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  48. {  
  49. if(strcmp((char*)szData, "ethernet") == 0)//判断是不是以太网卡  
  50. {  
  51. dwBufSize = 256;  
  52. if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  53. {  
  54. ADAPTER_INFO *pAI = new ADAPTER_INFO;  
  55. pAI->strDriverDesc = (LPCTSTR)szData;  
  56. dwBufSize = 256;  
  57. if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  58. {  
  59. pAI->strName = (LPCTSTR)szData;  
  60. RegGetIP(pAI, (LPCTSTR)szData);  
  61. }  
  62. AdapterInfoVector.push_back(pAI);// 加入到容器中  
  63. }  
  64. }  
  65. }  
  66. RegCloseKey(hNdiIntKey);  
  67. }  
  68. RegCloseKey(hSubKey);  
  69. }  
  70.   
  71. dwBufSize = 256;  
  72. /* end of while */  
  73.   
  74. RegCloseKey(hKey);  
  75.   
  76. return TRUE;  
  77. }  
  78.   
  79.   
  80. //-----------------------------------------------------------------  
  81. // 得到注册表中的IP信息  
  82. // nIndex暂时未处理  
  83. //-----------------------------------------------------------------  
  84.   
  85. BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex/* =0 */)  
  86. {  
  87. ASSERT(pAI);  
  88.   
  89. HKEY hKey;  
  90. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";  
  91. strKeyName += lpszAdapterName;  
  92. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  93. strKeyName.c_str(),  
  94. 0,  
  95. KEY_READ,  
  96. &hKey) != ERROR_SUCCESS)  
  97. return FALSE;  
  98.   
  99.   
  100. unsigned char szData[256];  
  101. DWORD dwDataType, dwBufSize;  
  102.   
  103.   
  104. dwBufSize = 256;  
  105. if(RegQueryValueEx(hKey, "IPAddress", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  106. pAI->strIP = (LPCTSTR)szData;  
  107.   
  108.   
  109. dwBufSize = 256;  
  110. if(RegQueryValueEx(hKey, "SubnetMask", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  111. pAI->strNetMask = (LPCTSTR)szData;  
  112.   
  113.   
  114. dwBufSize = 256;  
  115. if(RegQueryValueEx(hKey, "DefaultGateway", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  
  116. pAI->strNetGate = (LPCTSTR)szData;  
  117.   
  118.   
  119. RegCloseKey(hKey);  
  120. return TRUE;  
  121. }  
  122.   
  123.   
  124. //-----------------------------------------------------------------  
  125. // 设置注册表中的IP信息  
  126. //-----------------------------------------------------------------  
  127. BOOL RegSetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)  
  128. {  
  129. HKEY hKey;  
  130. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";  
  131. strKeyName += lpszAdapterName;  
  132. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  133. strKeyName.c_str(),  
  134. 0,  
  135. KEY_WRITE,  
  136. &hKey) != ERROR_SUCCESS)  
  137. return FALSE;  
  138.   
  139.   
  140. char mszIPAddress[100];  
  141. char mszNetMask[100];  
  142. char mszNetGate[100];  
  143. char szDnsAddr[100];  
  144.   
  145. strncpy(mszIPAddress, pIPAddress, 98);  
  146. strncpy(mszNetMask, pNetMask, 98);  
  147. strncpy(mszNetGate, pNetGate, 98);  
  148. strncpy(szDnsAddr, pDnsAddress, 98);  
  149.   
  150.   
  151. int nIP, nMask, nGate,nDnsAddr;  
  152. int enableDHCP=0;  
  153.   
  154.   
  155. nIP = strlen(mszIPAddress);  
  156. nMask = strlen(mszNetMask);  
  157. nGate = strlen(mszNetGate);  
  158. nDnsAddr = strlen(szDnsAddr);  
  159.   
  160.   
  161. *(mszIPAddress + nIP + 1) = 0x00;  
  162. nIP += 2;  
  163.   
  164.   
  165. *(mszNetMask + nMask + 1) = 0x00;  
  166. nMask += 2;  
  167.   
  168.   
  169. *(mszNetGate + nGate + 1) = 0x00;  
  170. nGate += 2;  
  171.   
  172.   
  173. *(szDnsAddr + nDnsAddr + 1) = 0x00;  
  174. nDnsAddr += 2;  
  175.   
  176.   
  177. RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);  
  178. RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);  
  179. RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);  
  180. RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);  
  181.   
  182. RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );  
  183.   
  184.   
  185. RegCloseKey(hKey);  
  186.   
  187.   
  188. return TRUE;  
  189. }  
  190.   
  191.   
  192. //-----------------------------------------------------------------  
  193. // 设置注册表中DHCP  
  194. //-----------------------------------------------------------------  
  195. BOOL RegSetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)  
  196. {  
  197. HKEY hKey;  
  198. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";  
  199. strKeyName += lpszAdapterName;  
  200. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  201. strKeyName.c_str(),  
  202. 0,  
  203. KEY_WRITE,  
  204. &hKey) != ERROR_SUCCESS)  
  205. return FALSE;  
  206.   
  207. int enableDHCP=1;  
  208. char mszIPAddress[100];  
  209. char mszNetMask[100];  
  210. char mszNetGate[100];  
  211. char szDnsAddr[100];  
  212.   
  213.   
  214. strncpy(mszIPAddress, "0.0.0.0", 98);  
  215. strncpy(mszNetMask, "0.0.0.0", 98);  
  216. strncpy(mszNetGate, "", 98);  
  217. strncpy(szDnsAddr, "", 98);  
  218.   
  219.   
  220. int nIP, nMask, nGate,nDnsAddr;  
  221.   
  222.   
  223. nIP = strlen(mszIPAddress);  
  224. nMask = strlen(mszNetMask);  
  225. nGate = strlen(mszNetGate);  
  226. nDnsAddr=strlen(szDnsAddr);  
  227.   
  228.   
  229. *(mszIPAddress + nIP + 1) = 0x00;  
  230. nIP += 2;  
  231.   
  232.   
  233. *(mszNetMask + nMask + 1) = 0x00;  
  234. nMask += 2;  
  235.   
  236.   
  237. *(mszNetGate + nGate + 1) = 0x00;  
  238. nGate += 2;  
  239.   
  240.   
  241. *(szDnsAddr + nDnsAddr + 1) = 0x00;  
  242. nDnsAddr += 2;  
  243.   
  244.   
  245. RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);  
  246. RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);  
  247. RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);  
  248. RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);  
  249.   
  250.   
  251. int errCode = RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );  
  252.   
  253. RegCloseKey(hKey);  
  254. return TRUE;  
  255. }  
  256.   
  257.   
  258. //-----------------------------------------------------------------  
  259. // 通知IP地址的改变  
  260. //-----------------------------------------------------------------  
  261.   
  262. BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)  
  263. {  
  264. BOOL bResult = FALSE;  
  265. HINSTANCE hDhcpDll;  
  266. DHCPNOTIFYPROCpDhcpNotifyProc;  
  267. WCHAR wcAdapterName[256];  
  268.   
  269.   
  270. MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);  
  271.   
  272.   
  273. if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)  
  274. return FALSE;  
  275.   
  276.   
  277. if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)  
  278. if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, NULL,NULL, 0) == ERROR_SUCCESS)  
  279. bResult = TRUE;  
  280.   
  281.   
  282. FreeLibrary(hDhcpDll);  
  283. return bResult;  
  284. }  
  285.    
  286. //-----------------------------------------------------------------  
  287. //  设置IP地址  
  288. //  如果只绑定一个IP,nIndex = 0,暂时未处理一个网卡绑定多个地址  
  289. //-----------------------------------------------------------------  
  290. BOOL SetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)  
  291. {  
  292.     if(!RegSetIP(lpszAdapterName, nIndex, pIPAddress, pNetMask, pNetGate,pDnsAddress))  
  293.         return FALSE;  
  294.   
  295.   
  296.     //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)  
  297.     //if(!NotifyIPChange(lpszAdapterName, nIndex, pIPAddress, pNetMask))  
  298.     //  return FALSE;  
  299.   
  300.   
  301.     //通过禁用启用网卡实现IP立即生效  
  302.     list<TNetCardStruct> cardList;  
  303.     EnumNetCards(&cardList);  
  304.     if(!cardList.empty())  
  305.     {  
  306.         NetCardStateChange(&cardList.front(),FALSE);  
  307.         Sleep(10);  
  308.         NetCardStateChange(&cardList.front(),TRUE);  
  309.     }  
  310.   
  311.   
  312.     return TRUE;  
  313. }  
  314.   
  315.   
  316. //-----------------------------------------------------------------  
  317. //  设置DHCP IP地址  
  318. //-----------------------------------------------------------------  
  319. BOOL SetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)  
  320. {  
  321.     if(!RegSetDHCPIP(lpszAdapterName, nIndex))  
  322.         return FALSE;  
  323.   
  324.   
  325.     //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)  
  326.     //if(!NotifyDHCPIPChange(lpszAdapterName, nIndex))  
  327.     //  return FALSE;  
  328.   
  329.   
  330.     //通过禁用启用网卡实现IP立即生效  
  331.     list<TNetCardStruct> cardList;  
  332.     EnumNetCards(&cardList);  
  333.     if(!cardList.empty())  
  334.     {  
  335.         NetCardStateChange(&cardList.front(),FALSE);  
  336.         Sleep(10);  
  337.         NetCardStateChange(&cardList.front(),TRUE);  
  338.     }  
  339.     return TRUE;  
  340. }  
  341.    

/*******************************************************网卡禁用启用操作*************************************************/

NetCard.h

[cpp]  view plain  copy
  1. #ifndef NETCARD_H_H  
  2. #define NETCARD_H_H  
  3.   
  4. #include <Windows.h>  
  5. #include <SetupAPI.h>     
  6. #include <cfgmgr32.h>     
  7. #include <list>  
  8.   
  9. using namespace std;  
  10.   
  11.   
  12. //     cfgmgr32.h 在Microsoft Windows 2000 DDK 中.     
  13. //     要用 CM_Get_DevNode_Status() 来查询状态.     
  14. //---------------------------------------------------------------------------     
  15. typedef struct  NetCardStruct     
  16. {     
  17.     DWORD    Id;         // 网卡设备号     
  18.     string   Name;     // 网卡名     
  19.     bool     Disabled;     // 当前是否禁用     
  20.     bool     Changed;         // 是否更改过     
  21. }TNetCardStruct;     
  22. typedef TNetCardStruct*  PNetCardStruct;     
  23.   
  24. /*******************函数声明***********************************/  
  25. static bool GetRegistryProperty(HDEVINFO DeviceInfoSet,     
  26.                                     PSP_DEVINFO_DATA DeviceInfoData,   
  27.                                     ULONG Property,   
  28.                                     PVOID Buffer,  
  29.                                     PULONG Length)   ;  
  30. void    EnumNetCards(list<TNetCardStruct>  *NetDeviceList);  
  31. bool   NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled)  ;  
  32. /**************************************************************/  
  33.   
  34. #endif  

NetCard.cpp

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <SetupAPI.h>     
  3. #include <cfgmgr32.h>       
  4. #include <list>  
  5. #include <Windows.h>  
  6. #include <SetupAPI.h>  
  7.   
  8. #include "NetCard.h"  
  9.    
  10. //---------------------------------------------------------------------------     
  11. //     EnumNetCards 枚举出网卡     
  12. //---------------------------------------------------------------------------     
  13. void  EnumNetCards(list<TNetCardStruct>  *NetDeviceList)     
  14. {     
  15.     string DevValue;     
  16.     PNetCardStruct NetCard;     
  17.     DWORD  Status, Problem;     
  18.     LPTSTR Buffer   = NULL;     
  19.     DWORD  BufSize  = 0;     
  20.     HDEVINFO hDevInfo   = 0;    
  21.   
  22.     hDevInfo=SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES);   
  23.     if(INVALID_HANDLE_VALUE==hDevInfo)     
  24.         return;   
  25.   
  26.     SP_DEVINFO_DATA  DeviceInfoData ={sizeof(SP_DEVINFO_DATA)};  
  27.   
  28.     HKEY hKeyClass;     
  29.     char DeviceName[200];     
  30.     for(DWORD DeviceId=0;SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData);DeviceId++)     
  31.     {     
  32.         if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS)     
  33.             continue;     
  34.         if(GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS , &Buffer, (PULONG)&BufSize))     
  35.             DevValue = string(Buffer);     
  36.   
  37.         if (strcmp(DevValue.c_str(),"Net") == 0)     
  38.         {     
  39.             DevValue = "";   
  40.   
  41.             if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME , &Buffer, (PULONG)&BufSize))     
  42.                 DevValue = Buffer;     
  43.   
  44.             if (strcmp(DevValue.c_str(),"ROOT") != 0)     
  45.             {     
  46.                 NetCard = new TNetCardStruct;     
  47.                 NetCard->Id = DeviceId;     
  48.                 NetCard->Name = "<Unknown Device>";     
  49.                 if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER , &Buffer, (PULONG)&BufSize))     
  50.                     if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC , &Buffer, (PULONG)&BufSize))     
  51.                         NetCard->Name = Buffer;     
  52.                 NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);     
  53.                 NetCard->Changed = false;     
  54.                 NetDeviceList->push_back(*NetCard);     
  55.             }     
  56.         }     
  57.     }     
  58. }     
  59.   
  60. //---------------------------------------------------------------------------     
  61. bool   GetRegistryProperty(HDEVINFO DeviceInfoSet,     
  62.     PSP_DEVINFO_DATA DeviceInfoData,   
  63.     ULONG Property,   
  64.     PVOID Buffer,  
  65.     PULONG Length)     
  66. {     
  67.     while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,     
  68.         DeviceInfoData, Property, NULL, (BYTE *)*(TCHAR **)Buffer, *Length, Length))     
  69.     {     
  70.         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)     
  71.         {     
  72.             if (*(LPTSTR *)Buffer) LocalFree(*(LPTSTR *)Buffer);     
  73.             *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR,*Length);     
  74.         }     
  75.         else return false;     
  76.     }     
  77.     return (*(LPTSTR *)Buffer)[0];     
  78. }     
  79.   
  80.   
  81. //---------------------------------------------------------------------------     
  82. //     NetCardStateChange 网卡的启用与禁用     
  83. //             NetCardPoint 是 PNetCardStruct 的指针.     
  84. //             Enabled     true = 启用     false = 禁用     
  85. //---------------------------------------------------------------------------     
  86. bool   NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled)   
  87. {     
  88.     PNetCardStruct NetCard = (PNetCardStruct)NetCardPoint;   
  89.     DWORD DeviceId = NetCard->Id;   
  90.     HDEVINFO hDevInfo = 0;   
  91.     if (INVALID_HANDLE_VALUE == (hDevInfo =   
  92.         SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT |DIGCF_ALLCLASSES)))   
  93.         return false;   
  94.     SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};   
  95.     DWORD Status, Problem;   
  96.     if (!SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData))   
  97.         return false;  
  98.   
  99.     if (CM_Get_DevNode_Status(&Status, &Problem,   
  100.         DeviceInfoData.DevInst,0) != CR_SUCCESS)   
  101.         return false;  
  102.   
  103.     SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};   
  104.     PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;   
  105.     PropChangeParams.Scope = DICS_FLAG_GLOBAL;   
  106.     if (Enabled)   
  107.     {   
  108.         if (!((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem)))   
  109.         {   
  110.             NetCard->Disabled = false;   
  111.             return false;   
  112.         }   
  113.         PropChangeParams.StateChange = DICS_ENABLE;   
  114.     }   
  115.     else   
  116.     {   
  117.         if ((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem))   
  118.         {   
  119.             NetCard->Disabled = true;   
  120.             return false;   
  121.         }   
  122.         if (!((Status & DN_DISABLEABLE) && (CM_PROB_HARDWARE_DISABLED != Problem)))   
  123.             return false;   
  124.         PropChangeParams.StateChange = DICS_DISABLE;   
  125.     }  
  126.   
  127.     if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData,   
  128.         (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams)))   
  129.         return false;   
  130.     if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DeviceInfoData))   
  131.         return false;   
  132.     if (CM_Get_DevNode_Status(&Status, &Problem,   
  133.         DeviceInfoData.DevInst,0) == CR_SUCCESS)   
  134.         NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);   
  135.     return true;   
  136. }    

设置静态IP

[cpp]  view plain  copy
  1. GetAdapterInfo();  
  2.   
  3.   
  4. char szIP[16]="111.111.111.11";  
  5. char szMask[16]="255.255.255.10";  
  6. char szGate[16]="111.111.111.1";  
  7. char dnsAddress[16]="222.222.222.1";  
  8.    
  9. unsigned char *pIP, *pMask, *pGate;  
  10. DWORD dwIP, dwMask, dwGate;  
  11.    
  12.   
  13. if(SetIP(AdapterInfoVector[0]->strName.c_str(), 0, szIP, szMask, szGate,dnsAddress) == TRUE)  
  14. ::MessageBox(this->m_hWnd, "设置IP地址成功!""操作结果", MB_OK | MB_ICONINFORMATION);  
  15. else  
  16. ::MessageBox(this->m_hWnd, "设置IP地址失败!""操作结果", MB_OK | MB_ICONERROR);  

设置动态IP

[cpp]  view plain  copy
  1. GetAdapterInfo();  
  2.   
  3. if(SetDHCPIP(AdapterInfoVector[0]->strName.c_str(), 0 ) == TRUE)  
  4. ::MessageBox(this->m_hWnd, "设置IP地址成功!""操作结果", MB_OK | MB_ICONINFORMATION);  
  5. else  
  6. ::MessageBox(this->m_hWnd, "设置IP地址失败!""操作结果", MB_OK | MB_ICONERROR);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值