找回密码
 注册
搜索
查看: 4686|回复: 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地址的详细方法介绍如下:; u" t0 G! B( F

/ ~  t( I3 @  P' ?  f一、获取适配器名称
' W% b, I- L. x$ C+ C. Q3 }: C, v, x+ E6 Z5 n
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:, I( }  \7 E- H  J

8 l& N0 `6 A) Z: \/ j! b' g1.1 调用IP helper API取得适配器名称 4 H7 x# ~" p% m& i# I% y9 `
+ f6 @" ]/ M* V& w
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
' \0 W  p3 v5 W+ H9 HIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
3 W2 L$ i6 d- O3 eif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
( ^- F# N& `; h. a( c1 Y{* F* J- c9 z8 J
   delete pAdapterInfo;
# R/ u6 i4 c8 r    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];( s* m1 R# j. P/ Q/ j) W# A9 }1 Q
   pAdapterInfoBkp = pAdapterInfo;
) H7 f8 q: {) k  K# A/ ?$ h, h% ]}
9 Y3 ]/ W" k9 g1 Eif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
4 K5 P, o' }$ b, t3 x{
) t" N3 m6 V7 v0 B  N8 _    do{ // 遍历所有适配器
2 T7 i7 i1 M/ R; c  n2 N% o: B        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口: A# q% v# [/ j
       {
% S0 }2 g# z, n! A. a+ B            // pAdapterInfo->Description 是适配器描述
9 O' S1 y( j, x$ N* x            // pAdapterInfo->AdapterName 是适配器名称5 X' e  [& w" T' J  x  I
       }
: d$ q6 v/ y5 ^7 Z7 p- H        pAdapterInfo = pAdapterInfo->Next;
. `$ m& E# l+ f    }while(pAdapterInfo);& l9 s! |% G* n) S+ K) P
}% J: n- C) D  o9 F
delete pAdapterInfoBkp;
% V8 g9 ]; Y$ R! Z. b. n) s, S0 ^" r; }8 z3 q
1.2 读取注册表取得适配器名称
* v' L% n% @2 h$ ]
$ z4 K/ A% t, a% k, M& s& I在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;, \& U9 M& _9 E/ `8 I. Z/ ~
3 H0 {" X/ O: Y+ K. V5 g9 S* x! v
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
6 U2 r- }& j; G# a            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",: d; ~+ S; g0 c6 i  l, J3 R* y
           0,
& ~' e" \/ L- s            KEY_READ,, x; j* ]7 H- U
           &hKey) != ERROR_SUCCESS)) \7 x7 ]( e4 _% V
   return FALSE;- g4 j7 {  y) ~, \& V& A4 i
) V% W/ B* ]- S6 o6 B6 ]( @
DWORD dwIndex = 0;" f" |. H1 z& h
DWORD dwBufSize = 256;3 g% S$ O  s! E  {$ w# d' i
DWORD dwDataType;
- a# t  C; ~& ?* k7 j% jchar szSubKey[256];
' I+ I( m# U* G5 c  z, aunsigned char szData[256];
8 j1 n& n5 n. A7 p
3 M, l, q( P9 u( N1 O& Uwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
4 u  @6 B4 K0 ?- h{0 z3 s& r3 l( |$ D# s5 p3 T
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
- g( v2 W- A% j/ ^% _+ I    {        
, q9 e+ T* Q/ u4 h. k        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
  `5 ~$ Y+ B& [8 q+ x" }/ A        {
/ M2 Z" l# F: p3 {            dwBufSize = 256;
5 s) L$ A% L9 L' @" c) }1 _            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)4 B* j& s/ i0 ^% J, }
           {* g' u0 s2 ^$ t
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
4 n7 Z" ]6 E; ], E                {
. T8 ]5 L( @$ o                    dwBufSize = 256;: ^9 Z% \. T! W8 I3 g. s
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)" ^& K2 H" e: h8 X) W# a- `
                   {6 m& M3 o% i; V
                       // szData 中便是适配器详细描述+ p3 _4 ?$ m. g) j& g. h
                       dwBufSize = 256;/ T* k' a7 @$ Q3 |. Z9 {% P/ z
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)/ J# T$ W2 N, t% V6 ]
                       {
! P& _0 @9 c0 L8 b$ X                            // szData 中便是适配器名称" N+ [  E# t  y. `' [8 k
                       }7 ?7 a9 k/ T+ V
                   }
: D, w# R) ^( W, C                }( Y0 v/ x, r! l
           }
+ L1 [1 c* H# R/ G            RegCloseKey(hNdiIntKey);
8 _$ X# }% ?8 |        }
) `( z/ [0 S3 i* X/ |) d        RegCloseKey(hSubKey);  F* ?0 [2 w# Q! b# G5 Y
   }
" a. d- F# B) o- S
$ P! s$ I' U$ R7 R  t    dwBufSize = 256;: t: R, V/ I) v& x8 O% m& W
}    /* end of while */# x5 i2 D1 h2 D; [/ r6 y
       # D8 t" u- o7 Y9 t* Y7 h7 q/ g
RegCloseKey(hKey);7 {' d/ W% z: Z( L5 h
二、将IP信息写入注册表; p; h0 h: q( h. f5 K- v
' o3 _# h9 f. o& B& r& S
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)2 L  t$ S' Z4 h# ]5 c& Q" v
{% g% i/ |* x0 e6 a$ C* f3 R
   HKEY hKey;2 J" G. @4 S# N
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
/ @% i1 e8 O& Z1 ]; |    strKeyName += lpszAdapterName;5 g! k8 Z* V& U! Q' h
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 g7 N9 d# b: A                strKeyName.c_str(),
# G7 Q7 m3 x$ M* r( l                0,5 [5 d% `, D& s
               KEY_WRITE,
3 e; A' n1 @4 n* h% B/ y5 c* F                &hKey) != ERROR_SUCCESS)
) W) G: ~  X  P: _. o+ }        return FALSE;
# ]9 x* E% o7 o# V    ( h0 g* q6 T4 w8 a
   char mszIPAddress[100];( \7 k+ [* H4 Z" c" |
   char mszNetMask[100];1 W7 C2 W: I4 |8 Z, T
   char mszNetGate[100];
. J# w: K: s: C, L. Z
% L8 D  B% V/ s- [0 B    strncpy(mszIPAddress, pIPAddress, 98);
% ?/ {& i8 _" U, M    strncpy(mszNetMask, pNetMask, 98);
4 V, ?3 Q, R/ [. j6 \' V    strncpy(mszNetGate, pNetGate, 98);
) z& E3 d, c: b; Y6 o0 Z. O9 I, h8 o, {  Z- m% \
   int nIP, nMask, nGate;
$ E+ j( I. r" Q' L: ?. m  Z0 `: M
9 d/ }9 n0 X1 |7 `0 G    nIP = strlen(mszIPAddress);
- ?6 M( q; `! S& J2 e+ s    nMask = strlen(mszNetMask);
3 N; c6 S$ I) o2 N    nGate = strlen(mszNetGate);0 F+ H9 |& J/ f" n
2 q/ ^( h( M/ Z# y$ ^
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0$ B( g7 ~/ R: z( X4 O- q! \2 }
   nIP += 2;5 _1 z% v4 d6 U4 m0 I( C" V

1 F- G8 j) x, z( V2 w' X    *(mszNetMask + nMask + 1) = 0x00;% F) n- P( M6 }; i8 ?
   nMask += 2;
1 Z, C* B. W  |" g1 b3 N# g  H& R' \& a; R# p
   *(mszNetGate + nGate + 1) = 0x00;5 p# t6 L' {, @" {9 Q' \/ W
   nGate += 2;! q% M4 w7 M: M/ \: Q8 q& D0 ~
   1 h5 @' _8 X2 r" O# m, {
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
8 D5 m+ O; T' V8 K) \6 W    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);! B  Z; B: `' l$ C- o
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
# N% z, A& w, R2 D
; f! e2 z3 S. v) z' S" E    RegCloseKey(hKey);' P5 [& V4 ?4 \- a) r6 B+ \
4 p; i( \3 Z: e: M& x3 B
   return TRUE;
0 E$ B$ K1 d* H1 p, o}; l* t# {' s& `" o

7 g2 p: _1 t- T1 Y2 i9 s三、调用DhcpNotifyConfigChange通知配置的改变
, z! Q# W" Z7 q* u# i! R% j0 w9 Y7 e1 J* S/ _& Q5 |6 |
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(' F+ \# b# E7 `
   LPWSTR lpwszServerName, // 本地机器为NULL4 l' [0 R0 I+ K  l* F' R# }
   LPWSTR lpwszAdapterName, // 适配器名称2 J5 {2 l+ P- c5 K( _" F
   BOOL bNewIpAddress, // TRUE表示更改IP
* b" r4 Y+ h4 k" J& S    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
& w- C! w0 n! J% d9 X/ p    DWORD dwIpAddress, // IP地址
& Q2 l  h9 N( v& Q    DWORD dwSubNetMask, // 子网掩码
8 U( t- G2 q2 J/ c  N3 J! T    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
$ i! ^4 d7 t! f) O+ u* h9 C  w5 }6 F5 I. b# P+ Q
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
# t) Y3 _% {: b( e8 x9 M{: S/ ]$ B/ D9 d' j
   BOOL            bResult = FALSE;$ ~' J# M4 T8 p( a. M$ |2 P( ]+ A
   HINSTANCE        hDhcpDll;
9 X; ~  D3 ?7 N! `5 S    DHCPNOTIFYPROC    pDhcpNotifyProc;2 [8 t$ B/ D, Y3 @1 J3 E8 g" a7 I/ h. ~
   WCHAR wcAdapterName[256];
" }1 o8 x, S4 ]% o, R    
/ C$ U/ d) K  M  G9 f- c0 s+ q/ B    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
$ p- \* {5 H3 `2 V" h& H% L0 q2 c* ]) s' T; V6 L% }4 _  ~6 q
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)  a' `7 l* m, W) Z* i1 p
       return FALSE;
# E9 X( E% {; F9 X! |
  ~3 z. `/ E4 S2 ]# @0 x. P    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)7 U  q  P4 s! k% S- R
       if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
" `: k+ d# X# U# S            bResult = TRUE;4 A& a% E" l4 O1 x1 x

2 t+ O, s& a1 v$ c! I; `. R    FreeLibrary(hDhcpDll);0 p4 l$ g  Z% h; |( x. F. c
   return bResult;
9 z+ U" r2 W: t, @0 o$ P}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-30 13:07 , Processed in 0.035110 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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