找回密码
 注册
搜索
查看: 4932|回复: 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地址的详细方法介绍如下:
- J, t0 j; {0 l. t  f! `% {
+ N3 @! r; W* @7 o/ t: j一、获取适配器名称
: V* \/ F/ s. B4 {1 a; t% A% |' I8 ]) U3 V0 ^
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:$ o4 h  z' a/ r1 h) u5 x

+ T7 |3 J7 Z' c5 \& }% N1.1 调用IP helper API取得适配器名称 4 _, Q2 v- j( ^+ A
: E/ I: R1 m( m8 |
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
, `  {: p9 s- pIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
* E+ p% `/ `" e0 I% Q! kif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大  C: I) X, b; ^( ~  k7 c
{) d  Y. K) X. M( d4 q
   delete pAdapterInfo;3 _4 _9 @5 b2 V
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
) r) w9 U9 g- M+ J6 d, P5 r    pAdapterInfoBkp = pAdapterInfo;3 M$ O: c) j6 J; K
}; Y* F$ I2 o; h- P
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
  y( g* y3 [3 E5 U( [* b{+ z1 R& g, J7 x5 s3 }0 k3 L
   do{ // 遍历所有适配器. I# f4 O7 O/ z
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
9 b0 _0 s+ L6 r" V! \9 l& m        {
3 V( J4 r5 T4 m. ]  D            // pAdapterInfo->Description 是适配器描述
2 T! ~' l, o+ K0 x: g. _) Z            // pAdapterInfo->AdapterName 是适配器名称
) G& l5 @5 p( u: @# \        }
3 j$ R6 a1 ]8 m' A        pAdapterInfo = pAdapterInfo->Next;
8 o3 o. N5 ]& e8 C# i    }while(pAdapterInfo);+ N' K" p& a) r2 E* x) ^5 k3 z- A
}
: ^0 y: f- M+ i# T. a* [delete pAdapterInfoBkp;. |/ T" Y5 M' r7 x* U
" Z- O$ ~$ }$ ]3 o5 b
1.2 读取注册表取得适配器名称2 q& x9 J& P4 X0 E5 w4 B& r7 P& s6 o
! D9 h" }4 L5 S
在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;( `- x1 f3 @, N$ R
5 z$ k( x" R* L! Y
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,( I  q7 G5 n# Q1 `. n+ q
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
+ n$ {+ y, c! ]4 e  j) F  c            0,: M1 T" y, e/ s- T
           KEY_READ,9 M9 G4 m+ v) s8 d  v) }, D5 p
           &hKey) != ERROR_SUCCESS)7 Q& X! u: {0 h3 a& m' f
   return FALSE;5 I& S+ S  w5 V7 a) i: w
7 d0 L4 n- h1 \- @# M/ Q
DWORD dwIndex = 0;7 c/ S- `  N4 m5 |
DWORD dwBufSize = 256;
, q! C/ J' Q: I# D$ A( G5 g- Y7 nDWORD dwDataType;
" `5 ?4 r6 R" F  X$ c/ `char szSubKey[256];* p. c4 p( S. |8 F: D7 x
unsigned char szData[256];1 c$ z3 l; M0 m) }# R/ p
; _! x! e9 y. q0 d
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+ r6 J8 A1 M+ w5 n{2 ]( [. J$ M0 X! X  y$ `
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)  E8 j* [- `1 ^! W/ B* Y2 b
   {        
7 Y4 i* b+ V6 s        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)4 ?2 m: n  R/ F( X/ d7 x/ S
       {
( t. _- g7 w" u+ v  V! O9 ?; {            dwBufSize = 256;
& W7 k" i% ^0 X, f            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
( A1 c& {% O0 a, c3 y            {
, H! Y+ Q" R. S- b0 s) F                if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡( A: m  K5 t  g' u
               {
5 n6 H- S2 l  M# s" p3 S                    dwBufSize = 256;
6 x4 m5 b! D2 ^, \                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! `/ ]( M, H  h0 X
                   {3 M' F( T8 p9 a! }9 X* l
                       // szData 中便是适配器详细描述6 k- C* B4 |# k$ k4 R( R; U
                       dwBufSize = 256;
4 x( b( V' c1 ?! s- V                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
/ Q5 Y- s+ Q3 r/ o. l, p                        {& C  a( t" j! x, h
                           // szData 中便是适配器名称  y" }5 q8 ~8 S; X, `
                       }- a" J: y4 `1 f" r9 X4 B
                   }' Q4 w  M9 s& S' q
               }
+ u3 s) w' W4 ~5 N! l7 r8 a+ M            }2 h2 }7 [) j. T/ z& t
           RegCloseKey(hNdiIntKey);
; L2 A0 W  Z: P        }' l( O  P9 o0 n
       RegCloseKey(hSubKey);1 e+ x- Y% Z, G/ E: v$ S
   }4 g( n. Y, t8 K% ?% r+ U: z- n' J

- w% {9 u, s# U! i# K* d    dwBufSize = 256;0 d' x3 d1 J' w
}    /* end of while */
0 }/ |* M8 f& D# s% A% p/ s" _        
4 I5 p7 p7 m, H! a9 F9 CRegCloseKey(hKey);
! k( D5 |. [3 B$ ~二、将IP信息写入注册表8 L/ V2 f2 O  I7 a1 X  o

  v! r: E  j' ?# I代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
, y* M; S6 a8 h/ F& B; A{8 H& O1 L! ?0 A, w3 j# m! O; X+ S
   HKEY hKey;
; ~+ t1 k! F7 R7 F5 Z    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+ ?9 e& i2 D) _" L- M% ~( h3 S    strKeyName += lpszAdapterName;
2 y6 M3 _7 N' ^5 a: e    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
" P* z; z# T: b% A7 P" X                strKeyName.c_str(),
3 e2 F0 X! m, f; J4 ^3 w7 M3 p/ ?- b                0,7 R; b4 |. j; J5 I# }
               KEY_WRITE,  E: @. K0 Z+ f# m9 a
               &hKey) != ERROR_SUCCESS)
& [- w3 X) W; O- h. H        return FALSE;
7 y3 i$ \& T( H4 l4 m    8 x7 x9 X$ N2 v
   char mszIPAddress[100];+ Q0 ]/ k9 {; j$ g
   char mszNetMask[100];
* y; b, a- Q" I3 x. l5 w7 g% M    char mszNetGate[100];
7 t; q" ~) ~* p; ?: @" }3 [* `
' H0 t4 W2 l5 D# q# j1 l    strncpy(mszIPAddress, pIPAddress, 98);  U" t/ ]  _8 b* ?9 V9 u( m
   strncpy(mszNetMask, pNetMask, 98);
, w6 Z! `. v$ y5 w    strncpy(mszNetGate, pNetGate, 98);
7 ?. r  w5 H, j& M7 C* o
( e5 e, o8 n/ I# e    int nIP, nMask, nGate;
+ a( r$ f- G( c& G! P
9 k8 E2 \) e6 N. |: S( R; o7 g    nIP = strlen(mszIPAddress);- _: e6 {0 p% S5 J
   nMask = strlen(mszNetMask);$ |2 b3 l( j, P7 w. {
   nGate = strlen(mszNetGate);
- `- q) L. R  p! {
0 q; F6 _( _: n, ~8 O5 B; k4 X    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个08 ^  T6 z4 l: M/ E, }6 M' w
   nIP += 2;- u5 d  |2 n% u: b$ f0 n
. e( P( p8 D, P6 f. h, q
   *(mszNetMask + nMask + 1) = 0x00;, @- M7 V) c& j9 ~. B1 Y- n, H
   nMask += 2;( t+ r5 V9 y0 u1 G9 ]# P/ f

& G! v* i5 k5 \7 \! J/ c    *(mszNetGate + nGate + 1) = 0x00;4 c  \  ]1 p: h# x5 g
   nGate += 2;
0 `- Q2 z# n6 `; P. c& o+ G    
; w' Q1 Z( N* h7 R% w; K' {& a    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);# J) j+ O& R" F1 w1 q  x7 U" A: S
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
4 E! ^' C, m. ^- f: K' j' L( X    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
& ]! }, Q) p9 M' i; g$ D' U
2 h2 S( O3 ?% O) D) A4 Q. W/ X, h" f    RegCloseKey(hKey);( e; j# ]- G- V! u

. l9 V$ u' O- w* ?0 I    return TRUE;; N5 X) F5 E. B, ]+ d
}$ L7 d0 I1 a* k, Q: p

# p. u+ t1 Q% _: R! P9 M1 j三、调用DhcpNotifyConfigChange通知配置的改变
! Y, l; \) C# b  N) v! G! L9 i5 J" ~+ p" M. }# P/ n# E8 u2 Z
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
, [( ^2 h/ d5 D  x& b    LPWSTR lpwszServerName, // 本地机器为NULL
2 `- _" G7 a9 w$ _% P    LPWSTR lpwszAdapterName, // 适配器名称0 Z3 B$ Y/ @7 C9 u
   BOOL bNewIpAddress, // TRUE表示更改IP
- m2 H$ K1 i+ C& `$ l1 ~    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0+ p& Y9 {/ W! X  C* x' Q4 i7 ]- d5 |4 Y
   DWORD dwIpAddress, // IP地址
( O+ t# H1 {6 _* g3 {! b: ]+ T( k    DWORD dwSubNetMask, // 子网掩码0 W3 |7 T; F" z7 ~& C. C
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
0 s- b5 q; Q* H7 }- J- R: }- H/ ~! j
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
; q- U9 ?6 }% M- `( ~/ S* F4 z7 h{6 W' S; T5 E7 Y$ M
   BOOL            bResult = FALSE;" t" [' s6 ~# X9 d4 v
   HINSTANCE        hDhcpDll;
1 ?  Z7 H# N2 s; ]4 j% I+ R- _5 x    DHCPNOTIFYPROC    pDhcpNotifyProc;
" ]" O  E' |( l  u0 S" P    WCHAR wcAdapterName[256];, E* j( i* P9 ^! W
   2 }1 a, C- y$ T* j5 r6 c
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);" s: d* I* ^8 L4 F1 J2 w9 f5 y

) O$ C( D  a! [( z+ M    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)1 n4 O9 z4 A; Y" \0 h
       return FALSE;' a! X4 m6 J. I1 v8 ]; ]
9 `) l* L# c6 [  K
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)& l, O/ Z- k' s' @0 @7 x
       if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
( z9 v' l" a2 z8 U& h            bResult = TRUE;& g9 ^/ h; ]  b! @1 t

% k3 ]9 J) b1 f# ?$ N    FreeLibrary(hDhcpDll);
3 K7 ~' S0 j3 j6 X1 T" H    return bResult;
. z/ V8 o  p3 R/ B7 y}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 09:00 , Processed in 0.018335 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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