找回密码
 注册
搜索
查看: 5191|回复: 1

[收藏]Windows NT/2000更改IP地址不需要重新启动就可以生效的方法探索

[复制链接]
发表于 2005-5-24 11:03:31 | 显示全部楼层 |阅读模式
  设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的APIhcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:3 q6 j1 ?$ o$ d
3 O/ e( |: Z4 _" I3 k' u: F
一、获取适配器名称
( D8 P) f/ Q4 h, y
  q, m0 T0 J. ]& P4 p这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
$ q* x8 G$ K& b- j5 L& y6 u+ A0 Y! u- }6 q- G
1.1 调用IP helper API取得适配器名称 1 U+ n; P3 I6 i% p, H
3 s8 i/ f0 D9 ~' w
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
! ]  w& P% p( _: E; H( [4 MIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];& Y2 Y, m5 Y' h6 |7 R
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
" _9 x; j% {0 x; B  g) N; c{4 x7 d8 \% ]( L" p2 p  L+ v
   delete pAdapterInfo;6 }# g4 c/ o% B5 ~& N) Y) x
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
  u. A# o2 J3 ~" v) @    pAdapterInfoBkp = pAdapterInfo;
! _0 R. S/ `! ~1 L" q}
1 }' g  L5 b5 T& y  n6 B1 \if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
9 W. G' t' ?# L# D4 K{1 I) M" {$ F+ K
   do{ // 遍历所有适配器- S) U2 b4 O" T! h0 m' R/ D% X: O
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
5 k! d- ]- w" g6 F6 V1 ?        {
/ N1 e8 Z, F5 M& O            // pAdapterInfo->Description 是适配器描述
0 G6 v$ g4 \8 W/ I            // pAdapterInfo->AdapterName 是适配器名称9 s8 D! ~; c/ k
       }
" F- d% L( G3 G8 e6 h        pAdapterInfo = pAdapterInfo->Next;
; Z- a9 O) d  I) [  d2 Q8 k    }while(pAdapterInfo);
1 p9 q4 n  O5 n# A}
' v4 x- B) K3 y: E4 `" o- adelete pAdapterInfoBkp;: |; F  V$ Z$ c) n1 ]$ y2 y

. d( T" V3 N: ]3 C1.2 读取注册表取得适配器名称6 F  R) y9 x: m- v* i7 J6 j& U
2 `$ j( X/ a8 z, d* b
在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为例: HKEY hKey, hSubKey, hNdiIntKey;+ k+ v. N" @- j' D$ r2 K
/ X% y0 E- {# u( b  ]. Y& v% T' U
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,& D& ?# Z7 j  H0 g, J# J5 n( s
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",- e; |1 s" u% M+ P, f2 Q
           0,# v2 S- v- S7 [, j* `: ?2 C
           KEY_READ,
# a& Z" g+ g/ g" m: M            &hKey) != ERROR_SUCCESS)% _9 W) L1 J5 k- q  f, j5 T% j9 U
   return FALSE;) v3 x/ ~( I# F
# S) D) N$ o8 I- R* y7 C
DWORD dwIndex = 0;
: |# A% L8 d' I, h0 o4 RDWORD dwBufSize = 256;
3 y% E1 b& \4 b7 f0 wDWORD dwDataType;
% S  \" L0 F6 x. ], y: [char szSubKey[256];
" R1 o  C2 e8 ~3 B. p4 Z! Iunsigned char szData[256];* T2 i$ W4 B/ C- x& e
% x3 s2 X2 a/ ?: l" R9 D* J
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
) \) R) p! v& {  @- B9 p" V7 I! F# _7 F{
, t4 D8 g( f/ I! H; |( S5 `6 `    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
' {. m% i  b1 p" Q" k  K9 X    {        
& @; {( g, Q- @9 n0 A2 D        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)9 `- \; u  d1 W  V& s
       {. o* ^! J; }3 n
           dwBufSize = 256;9 y$ }* I" K# t4 G9 ]
           if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS); ?$ o/ f/ s; ^3 |( u  c' `
           {
  ]( r; m2 y' L0 H% r3 B                if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
- y9 C. [$ V; Y0 U  R. T6 Z# ]                {
# f: B0 H& `6 k' d                    dwBufSize = 256;
' @4 j, C* l* L: A0 I                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
+ c2 G; _$ Y5 B; K                    {
$ R, a0 a5 R" D; r1 T% }, V8 E7 b                        // szData 中便是适配器详细描述9 K" a) W4 D3 o0 D
                       dwBufSize = 256;
7 Y0 }2 @* y1 f" v8 C; j+ T1 W: P                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)8 C0 m9 @% p9 d1 }, z2 U0 f
                       {
8 w$ X1 _2 j+ ?9 K! `, ]                            // szData 中便是适配器名称* F# N- s6 a# {( e+ M; ^
                       }
1 t$ k) @+ z. p0 ~  \! Y6 a3 `                    }4 i, g3 j% v. U) t
               }2 O& g! e. }# ^3 @9 u
           }! s. D" D0 u# _$ Q8 b
           RegCloseKey(hNdiIntKey);
. i0 i  F% t' x: _1 X2 g        }( X5 J9 x# k! v! U" I
       RegCloseKey(hSubKey);
- y1 n5 _3 ], G( P/ p    }8 U7 E/ D! ?2 A1 j' I' a* I
& p8 p3 g5 z9 e- ^" E9 X
   dwBufSize = 256;7 |9 D2 d# q% z( J, n4 }% F
}    /* end of while */
3 I1 Q5 M$ @) i' E/ z        4 [' V; U% N, {- M1 P
RegCloseKey(hKey);
' E* M7 r. i* T* g4 K二、将IP信息写入注册表
  x3 T5 E1 g, Q( K( P8 s* \9 [
9 o. t/ a6 h" t! ~' [: S6 P. B代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
1 ]5 Z* c$ D8 g9 r{! b9 r7 Q$ G5 I& B
   HKEY hKey;  ]! Q7 u( O4 o/ z) o: z6 T! X' J
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1 F* n4 B; b* [- f% z    strKeyName += lpszAdapterName;' w& `5 P4 X( K( [
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 E) W+ w7 p0 a. w8 n0 T                strKeyName.c_str(),) k0 I# ^  S# T6 I$ ?! }
               0,
3 c9 l  @! P* F$ z4 w, p, |' v                KEY_WRITE,, w' W* L, u  S- G9 z7 w, J
               &hKey) != ERROR_SUCCESS)1 [6 A8 [5 h8 x, v2 E- F
       return FALSE;
% }( t# g' R# ?$ N$ |    
9 G0 |- {& I4 ~) w4 a0 A4 i+ V    char mszIPAddress[100];0 T' S7 l: g' l" P
   char mszNetMask[100];( O4 n, @: Q. L* b( [
   char mszNetGate[100];! p# F6 b: [+ R, \0 w
: }/ T* J' f+ C  y/ @
   strncpy(mszIPAddress, pIPAddress, 98);8 }9 i2 F/ M; n: S5 T  J
   strncpy(mszNetMask, pNetMask, 98);( G7 L6 I" Y5 X$ [( R- M" b
   strncpy(mszNetGate, pNetGate, 98);
2 D8 F+ F- e, O# j! S9 R& L+ Q! m; O: z/ ?% D% |
   int nIP, nMask, nGate;7 N" }& i' _0 U3 O

  P0 B% a8 {9 k4 X7 O; ]    nIP = strlen(mszIPAddress);
! A9 f7 d7 I' {! r' j' H    nMask = strlen(mszNetMask);
1 }( V/ J! N" M, }0 m    nGate = strlen(mszNetGate);" G1 D4 J5 s7 x) r% h' I

- _3 Z# Q& H, B! E0 z    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
% T, f  U% x! d+ B6 _( O0 t% P    nIP += 2;
8 X4 ]) _! l1 \. O' b& w  I; x& b3 u4 m; s
   *(mszNetMask + nMask + 1) = 0x00;
: X# e* [0 ?4 Y$ D2 \& K  A    nMask += 2;
- o3 [7 i+ R! c3 \( w
& |% Z6 O- j) d    *(mszNetGate + nGate + 1) = 0x00;$ }8 y  `& ^0 j0 n
   nGate += 2;# [2 k, h! Y4 {$ x) d' v) X( P9 b
   
3 k9 U! Q! d5 C! l+ D+ d) W# g    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
# _0 N# f. i' u, ~    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);4 @: Y6 o% z# r1 |
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
" h1 t4 R, R7 D: Y. v" ~, d9 Y; b; F3 j# |8 a
   RegCloseKey(hKey);
$ |$ N  {& _: [' ]' G# J
$ Y, J1 M: k: ~/ H, G    return TRUE;
* s7 q/ V" b; V, ~* b( D: k2 m}
$ ]  g, w/ v* d1 F
6 D* U1 {, R. [" f- J' S三、调用DhcpNotifyConfigChange通知配置的改变
2 n, O: M5 o# ]5 ]1 Q- q: p) H& W6 L- y4 S' z% l: Y5 C4 s3 y8 Q0 |( {
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
7 B, P, J, X8 f    LPWSTR lpwszServerName, // 本地机器为NULL
. I" }" Y! V9 p! ^    LPWSTR lpwszAdapterName, // 适配器名称
- Y/ X8 d* O: e1 {* S    BOOL bNewIpAddress, // TRUE表示更改IP# F. n9 J& f0 Y/ Y9 ~: a2 a. A
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0$ }$ }& c. E. h" u/ h2 \1 k
   DWORD dwIpAddress, // IP地址  B* A5 ?; l! H/ x- }9 @9 i
   DWORD dwSubNetMask, // 子网掩码" s, M( z" M% a) P# t9 q' |0 F
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP6 [0 A: l0 |! H; X& s( w

" k3 s- M; F9 c( I; E! O0 K具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
# N2 B0 n9 s0 g5 _0 F4 [& k" F{) d/ W% N/ c; n  c
   BOOL            bResult = FALSE;
$ N( J3 t5 J; K. l# f. }    HINSTANCE        hDhcpDll;( g$ X/ q! S, z/ X$ [" _
   DHCPNOTIFYPROC    pDhcpNotifyProc;
! k2 r6 h$ d, ]4 n- s    WCHAR wcAdapterName[256];
5 f5 |% {9 [/ y) H6 }, S    
$ U8 f4 E  o6 ]0 m1 }4 ?2 l( t* G    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);; o7 e+ B& y9 {
7 y  E: z. x. D1 o$ H1 ?( k
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)( c! z* E: I( [
       return FALSE;
1 p( ]! @5 c  b$ ]
- ^' P& M; D* V+ o    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)- T- D2 w) ]4 _( b
       if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
' l- I2 h3 f7 C! t            bResult = TRUE;, K2 s- N. g- P2 ]

; ?" k! p' _7 w    FreeLibrary(hDhcpDll);; q) \1 Q, Z& i  h: |5 n, Y9 ]
   return bResult;( r! D4 K% ~' w; h8 {. p5 y
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-8-13 22:50 , Processed in 0.019104 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表