找回密码
 注册
搜索
查看: 4548|回复: 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 V& K# |8 y  p* R8 A' e% Y
7 V2 k# i, R& T+ n( T一、获取适配器名称2 k. |4 h! V8 h# k

, `; o7 Z! B$ T' L  E: A5 w这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:6 E- c" _/ e( K/ x3 n/ f! R3 n

! X, K4 R% f  T3 ^! O1.1 调用IP helper API取得适配器名称 2 ]9 `/ q4 }0 N, H9 [0 _7 \9 @
0 _9 w8 M8 c9 A) T; {6 U* b* _
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
9 d+ j- F$ i% `( uIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];$ v  f( o- q, F0 U4 V' H3 |4 e2 l
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
- q, Z  l0 `: e7 f& g; y{
3 |1 q* Y- q9 x' [    delete pAdapterInfo;# f, L" i/ D' {( ]8 v& M
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
! M) h- s6 A0 Q3 r& k+ T) ~    pAdapterInfoBkp = pAdapterInfo;1 ?% ]" @# o! ~
}
+ ?- }: k+ ?  M+ Y+ z, bif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )  n; M7 @( \; w2 q4 W
{8 ~# G! b; G1 ?; ]6 _, R
   do{ // 遍历所有适配器+ x# Z3 c' T" e7 z
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口9 t$ [" F" y8 p* M
       {. |- o# ]/ R% |7 D( X! F) C
           // pAdapterInfo->Description 是适配器描述7 W& a2 R& c; N
           // pAdapterInfo->AdapterName 是适配器名称* L" `5 v+ Q' x$ Q& X% w
       }2 I& g+ S, o' ]; ^
       pAdapterInfo = pAdapterInfo->Next;9 |: q- i# u* b/ T8 o& o) t
   }while(pAdapterInfo);
/ J+ Z1 ]4 R$ Y# k, D3 t, F}. D3 i; s; C! H4 h, l. r7 |; ^
delete pAdapterInfoBkp;
% O' ]8 ~* _9 o# U. s& q! R0 v0 s! E! N# c+ b' V
1.2 读取注册表取得适配器名称
* K7 |* q! \6 N: E' r; ], Z( v. n2 K
在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;: T: \$ i7 j; l! I' M" l

! e1 j. P0 q# W& a1 Qif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  I- p6 v9 X, M7 W            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
6 G) E, H. t. O9 ]            0,, C- A2 t* N$ [2 h- P
           KEY_READ,3 V. A  Y  y  e* h4 _& v" T  z" h, d( l
           &hKey) != ERROR_SUCCESS)
$ Q9 j: L+ ?1 F1 m$ W    return FALSE;0 `( D# Q! O) V  \) w
: ?7 {3 A# @" O' U# D9 j- p
DWORD dwIndex = 0;" L2 k, F$ r( t' ?
DWORD dwBufSize = 256;
/ ^7 o+ |( |0 M# b* gDWORD dwDataType;
% b- g4 q6 E3 x* f3 X+ Y$ l( S% v) wchar szSubKey[256];; r; d, @7 p2 j8 o1 u' K  J. J& Z
unsigned char szData[256];
9 r) {# I5 r2 k) C0 r; @
, q2 h8 a+ e0 ]% _: E. c7 z& Ewhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
2 Q& U4 ?3 \: X  h- B+ z1 G7 O{
* v- H- a, {8 K# R' @2 H    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
, K; W: L' n7 n. O; o( C    {        + S" A3 E; O. a# P1 j0 K
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)! A/ l" R0 C6 v% }2 T9 i+ h) j
       {$ U. S. {" b: A. k& O
           dwBufSize = 256;
5 N6 ^, x) P' y0 E3 p            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)* b+ _8 t4 Q1 s' s$ d! [( J
           {# w5 R) r, T) `' ]7 `* ~
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
- J5 x  i" J( X1 n( f, p                {, E2 j' o+ ?2 _* u
                   dwBufSize = 256;5 T# t" I2 L) e, t  O- [
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
4 h; J0 r% q' B$ s$ v4 J! |                    {/ ~1 l6 g- n7 s$ Q8 c; k
                       // szData 中便是适配器详细描述: Y# T6 l* I! g- j9 W, ~% M
                       dwBufSize = 256;* f" D/ c7 `: F, g$ T& x0 q
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)# Z: o1 R$ H7 V5 Z  Q  U
                       {2 V5 L+ Y( s, a' W& Y) e5 y
                           // szData 中便是适配器名称
8 @8 Z9 `* _9 C, i                        }
4 {- p$ e. A3 s' N                    }
$ D; e" O9 q6 N) g  K& J) M                }
3 ]* R. A1 t! z            }; r" T" |& X2 P" F& P$ z, f2 @
           RegCloseKey(hNdiIntKey);
4 C2 T5 h9 X& ~# f) k2 p        }* r6 Q8 q/ R( J) W
       RegCloseKey(hSubKey);
  _1 k* f: U; _& e5 ?    }
4 V- |% J5 ]  M
! n  v% b; w# y: O, X9 g    dwBufSize = 256;: C* q( B( N/ F5 p8 \2 U
}    /* end of while */
9 B1 d; n. }. R$ H# A2 w* n        
, A# b7 j2 m  ~/ }/ Q; vRegCloseKey(hKey);' F  {, ^' T$ \/ @& D  L
二、将IP信息写入注册表
3 m  D( q, G# l
( k( J  k' r0 O6 S: h7 a代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
# h0 F/ ?& q% }2 {1 c{
* L7 Y# W, O! y1 y9 n3 w! P    HKEY hKey;
1 d, b7 O8 C. k' p5 q    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
, E+ E' I( d( L7 J: M    strKeyName += lpszAdapterName;$ U. c$ p# w; Q9 v' V
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,6 g4 T9 L! y& G) m+ n
               strKeyName.c_str(),% B. {# s, H+ `( o2 w' s
               0,
5 X, V4 }0 t% M; Z. q: y: H4 \# d" V                KEY_WRITE,+ [& I  Y" H- W; f
               &hKey) != ERROR_SUCCESS)
0 Y2 t% S; i& r# }4 a/ X2 K3 s  Y        return FALSE;) T) b; G& U) Y1 {6 n3 O( ^7 Q' {
   2 e! g6 m- J+ G) J0 w, C4 ^
   char mszIPAddress[100];, o2 {- p- T) f( l' H
   char mszNetMask[100];2 ~# |8 v% t3 A$ Q; ^
   char mszNetGate[100];% j$ u: j/ ~" [# W
" w+ K% O5 E& h$ a
   strncpy(mszIPAddress, pIPAddress, 98);$ n" ~: s: a! Q1 R
   strncpy(mszNetMask, pNetMask, 98);
& w2 |8 H- N5 P/ ^9 n8 G5 y/ ~! a    strncpy(mszNetGate, pNetGate, 98);- S* h" J) n  Z$ j' m
* m- V9 Y* [9 u# p9 r) D; l- i
   int nIP, nMask, nGate;7 M, o3 a2 n" S& L7 V( j  e; n0 @+ E

( U* y+ g* W1 L! r% D    nIP = strlen(mszIPAddress);
1 `+ d. k4 ?  g+ T" T3 E& E5 L    nMask = strlen(mszNetMask);
3 i; b" Z& Y& V2 L: }" H    nGate = strlen(mszNetGate);
: r8 {* ?0 ^$ D7 m: i! u) {6 c8 Q. K% d. ?# x" H$ |3 L& _5 R
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
! E: D4 R* i6 ?3 V1 Z) k    nIP += 2;9 ]+ b/ P. n; k, y! ]
6 ^6 J) S4 R% `& B+ L9 U
   *(mszNetMask + nMask + 1) = 0x00;- o3 N" U6 [# \; i
   nMask += 2;. h: H0 K* A+ _1 g4 }

3 F' }- {. E/ L6 E    *(mszNetGate + nGate + 1) = 0x00;8 H5 G' w5 b6 G8 H( b4 r
   nGate += 2;3 b3 ?4 b  e8 ^/ Q
   / T* U) Y6 R# |3 b: H  m5 T
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
7 W, v# t; {# k* d7 |/ |    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
4 w! @. M6 j* M1 I5 n" m. D9 R    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);" g; ]/ ?7 e- J4 [+ K, P

3 x. S- K8 d- \! z) f& w7 U0 t4 M    RegCloseKey(hKey);9 b7 `1 g# l) p: Z  i$ \: h, }

% h0 N1 ^7 i  U5 e# V# v& ^, E    return TRUE;
( b& O: |( P1 A}1 A* G. j) s" J! F* j
8 `) J( L& d' q: j  P' K# h7 [# q" V
三、调用DhcpNotifyConfigChange通知配置的改变
! @9 N& Q7 S% Q7 o  @& u( B0 Z- H! y3 C6 N# v
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
1 w9 @& ?" D0 n  y0 n# }1 V    LPWSTR lpwszServerName, // 本地机器为NULL
$ z, V- ?( Q' |& v; `    LPWSTR lpwszAdapterName, // 适配器名称
' Y* }* m5 o+ r2 w) ~    BOOL bNewIpAddress, // TRUE表示更改IP
1 c$ Q7 w2 ^9 L, d( ]    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0! L7 W: J- ^2 A! _
   DWORD dwIpAddress, // IP地址$ g8 H  _5 t/ Z; O) Q
   DWORD dwSubNetMask, // 子网掩码) C, O* Y# f8 X
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP% w, m0 h' B9 @5 P8 B& ^

0 ?* m/ H! e: @6 [3 e0 b具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
$ B) i( @. L$ t/ ]: ]{' S8 K5 q' j! H& r" d% J
   BOOL            bResult = FALSE;6 T0 a/ }  C( R4 |: u8 O
   HINSTANCE        hDhcpDll;( ?, |8 \$ ~7 j! I+ Y* o* r- l# U+ H
   DHCPNOTIFYPROC    pDhcpNotifyProc;6 x5 }$ g9 Z4 V- U  w0 {. F, W: g/ I' q
   WCHAR wcAdapterName[256];9 ~6 Y+ z& Y0 E6 V( g. T' f% }, C% ?
   
8 ^9 |; N6 k6 w+ Q( D! r* Q5 a    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
; R" Q6 ]+ l/ L" c  M2 w1 E! c7 L" G9 _7 I
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)4 H. V: q% F/ E* I+ g! u: W4 O
       return FALSE;
4 p0 D) D9 c! c7 _! s; ?0 u
0 Z7 s) v/ J& X8 h( g$ Q& l    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
& ?1 z* s( c% Q1 I8 w) Q        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)9 R& v  e$ r1 ~% `0 \" G& u
           bResult = TRUE;+ S' {- R* n- ^7 G" K3 M

- A* M& |( y3 [9 S    FreeLibrary(hDhcpDll);5 _6 V6 ~4 o& U% N
   return bResult;
* O8 w3 u5 O+ G) C& |) r5 N}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 16:11 , Processed in 0.042271 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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