找回密码
 注册
搜索
查看: 5192|回复: 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地址的详细方法介绍如下:
% S% R! v. K$ D$ V4 I% V5 z' p% E, ]
一、获取适配器名称
. G( x! N  j; Q2 C5 h4 V  M
7 M! f9 w7 x* y& J& O( A  N这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
4 }- K, u; l! c  N
' |8 Z# `9 H/ g  B5 I7 {4 l1.1 调用IP helper API取得适配器名称 " w( J2 o5 ~& k1 z/ C" I: k/ u

! r( e2 \! x! [" J6 z3 xULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
' B5 a( T1 N; O) BIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];, j0 l; |6 x; c5 o& U% S
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大' u8 o) b, |9 k3 N* d6 C
{: y% u" x, c( D6 {8 I
   delete pAdapterInfo;! W. A' ]$ v! ~; O2 H' [' L. z- V
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
! b; w' J3 @6 c6 P, H/ @3 u  B4 n    pAdapterInfoBkp = pAdapterInfo;# _) O5 G* \# X1 k
}
* W! L8 w" ]5 \( n. bif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )& ^& u" u  p: a6 [9 A
{
  d3 m+ }" S+ {    do{ // 遍历所有适配器
0 o* A! m7 l. S; _        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
2 `  ?# e6 E! j* y+ o  p' a        {
# y' i6 a+ X  z8 ~+ {6 h9 B            // pAdapterInfo->Description 是适配器描述+ \* O0 W* R8 N# `. [
           // pAdapterInfo->AdapterName 是适配器名称
+ t% M* P5 \6 p        }$ i5 y! |3 z% }1 U- F8 N
       pAdapterInfo = pAdapterInfo->Next;
$ f/ L$ M& r* f8 ~  g0 o    }while(pAdapterInfo);
' K& A: j. o  \}
$ B6 `* V; x8 N4 b' jdelete pAdapterInfoBkp;2 W6 j1 W) l" f! ]- y% O9 w7 ]4 O
0 b! m) r# }5 A/ p2 v! K
1.2 读取注册表取得适配器名称% w7 a7 B2 a/ d& y( u/ T
# D! G2 G* H. E. a) A" @
在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;, {8 W% c* a% E1 b# W& g; o2 k+ s2 s

8 N5 _1 O1 }8 t3 |5 L* q. D# y5 q% ?+ vif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,7 a, ^  p0 S+ O( n% v- W! D
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",2 t9 _6 a, C% _* }- ~
           0,) K, {. O1 X/ @+ ]7 ?5 A( L
           KEY_READ,
7 f. e9 z  T5 r            &hKey) != ERROR_SUCCESS)9 d3 f# x. e8 E
   return FALSE;5 ], G0 B" b( z+ c9 i, t4 I

% o* C9 F" _: s9 U- a' rDWORD dwIndex = 0;& k2 \9 y9 i4 N8 B3 J
DWORD dwBufSize = 256;
# F$ V: h  w3 {$ ]DWORD dwDataType;
! g# c5 L3 z* N3 ichar szSubKey[256];1 F& h3 x; a6 P
unsigned char szData[256];
5 C1 g# N& `! J* {
$ T3 g6 K/ t2 \: R* Uwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)* I; N8 L$ [  D7 z5 C, J( W
{7 Y0 \5 w- ?3 b, y4 i2 p
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
; v/ `  h4 L! D, Z    {        - R" C# z, X. u3 n# Z" U
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
: z, f! x* J& [% \3 S3 p1 T9 u        {
. h% z$ q% P3 E% N( W            dwBufSize = 256;
4 [, H! K" y/ w) g$ s            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  _- m0 ^& ~- _% b1 o
           {7 {) h4 H4 W3 V( t( t$ ~
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡+ O7 C, k8 ^* g  T5 s
               {. ?3 O  I" V9 \$ \1 S
                   dwBufSize = 256;! V( l) A4 ~' @; M) M* D) S
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)% ~, |- k7 V) B0 _4 G! J" I
                   {5 i3 t0 W, _  A. C4 p8 W+ K5 Z
                       // szData 中便是适配器详细描述# P3 v. j! {- [
                       dwBufSize = 256;
) U) V+ c. R7 Z7 Y: l2 R, O1 g* j                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
3 B$ X! Y9 F( u$ ]  p" B  I                        {4 g4 K$ _1 F% h% Z, j+ _6 D6 ^
                           // szData 中便是适配器名称# N  U1 N9 f9 ^' M& R1 _
                       }
9 P9 G8 v$ A1 [  K                    }
* X9 Y/ }8 U* |$ C8 x' k, ]                }" H$ b& }! O/ r! V7 f3 |7 ^
           }4 ^0 U0 |5 R9 W# a8 J
           RegCloseKey(hNdiIntKey);
, u7 d0 Q! `  E: H& f        }
* ^( M6 p0 c/ r        RegCloseKey(hSubKey);+ H  n0 x4 n) L5 \) m" A9 m6 Z. u; K8 z
   }4 }5 F7 H, D! |/ r

5 K+ f4 c- l! [$ K    dwBufSize = 256;0 `1 G0 R! Q3 G! h4 D% I
}    /* end of while */
* g' c' D0 \/ W% |; m5 M! S        
3 w1 e- S4 o& N* S1 X: FRegCloseKey(hKey);
, @9 D. T2 i4 ]9 _5 G4 f二、将IP信息写入注册表2 h# B' j+ m5 F8 X

  x0 D& w: k& ^+ w! s( n代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)* [' t  r: O% a- a6 T1 u0 {4 Q8 Y
{9 `3 Q& H6 N+ ^2 a& P, _& t! s
   HKEY hKey;
; E+ V: x! s' ^" Z) D    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1 r' e8 r3 n; E* _# z3 Z" L    strKeyName += lpszAdapterName;
. v9 s! y: Z# v8 t, n    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,. V2 a8 _& g5 ~$ ~# P2 u% z
               strKeyName.c_str(),
- G# r+ }0 f. t6 S) _                0,
# s: `; X' J" \4 l3 I                KEY_WRITE,
/ A# f' ]9 L* i2 J                &hKey) != ERROR_SUCCESS)
8 Z' V, ?. ]3 b# e% J" x        return FALSE;2 ^0 W  w- A: h
   : @1 }, j/ p; o, s
   char mszIPAddress[100];! A; E) X* X) G4 e+ c% c9 ]
   char mszNetMask[100];
3 S( ]! e. b: x: p3 K    char mszNetGate[100];
7 x: l: a5 j. K, C" {* b/ g0 j* B; b. R# E4 f& s; ^1 ?5 V! k% [3 p% R" I
   strncpy(mszIPAddress, pIPAddress, 98);1 {' _, @! x/ o* D1 n2 k
   strncpy(mszNetMask, pNetMask, 98);4 b: {4 Z. E" R
   strncpy(mszNetGate, pNetGate, 98);
' x- G7 g! k* Z5 i8 p% Q
: H: m5 m: S$ @' Q' g- J4 b    int nIP, nMask, nGate;
* O* S. i  R' j/ d
/ h* I# _# j4 {& W    nIP = strlen(mszIPAddress);
* ]  Z3 I8 a$ l  U# n    nMask = strlen(mszNetMask);$ _  e  j4 u/ ?+ F  d$ {4 S: x
   nGate = strlen(mszNetGate);& K' q  L& b7 P8 N4 F

9 P: F: r7 d7 G' [. q    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个02 e. p! ]# g" c3 |. r9 g
   nIP += 2;" F# ~! r3 {5 ^9 m4 x1 }0 a

6 q4 ]5 m3 K* p    *(mszNetMask + nMask + 1) = 0x00;9 j8 O1 x& f. Q1 j6 Z
   nMask += 2;
0 G  h; v$ k/ A8 W; C: r
: U( R- \2 n4 _5 u) y( z8 p% @    *(mszNetGate + nGate + 1) = 0x00;& A0 h5 g9 k$ p! Y: ?3 v4 V
   nGate += 2;
, {/ m, u8 |5 O5 [    " |  H- ]4 F% a( E
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);! g0 b7 L# z; o- `/ V  Y% e
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);  \( D, r3 Z+ E2 A% G" N' ^
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);- V% d& r! N4 ^$ i" p; s
0 d7 \7 h& G: y* w& y1 v8 i
   RegCloseKey(hKey);
: G. g/ u6 L- }
; m' B& v5 d4 s- k; o* ]" n    return TRUE;' B. Q9 t# g2 i0 L& S
}
# Q; I$ M0 z; D( q2 B8 ~0 ?
& o5 q4 n9 e3 A' d: R. e' P. J. v三、调用DhcpNotifyConfigChange通知配置的改变) O0 f: j4 k; M; `7 ^; {) [: d

$ w( o2 l3 C( W; q9 q+ M6 }未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
1 b0 N$ o' Z9 h3 H) V/ d% P- h: n9 m( D    LPWSTR lpwszServerName, // 本地机器为NULL
  a' C- R) S- N: }$ g: h" \    LPWSTR lpwszAdapterName, // 适配器名称
. E1 z/ M* P( u2 z2 ^    BOOL bNewIpAddress, // TRUE表示更改IP
5 s7 `+ w8 t; Q3 S& T( o    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
6 r8 y2 D& I2 }, ?: M# b    DWORD dwIpAddress, // IP地址' @/ @9 o' o/ q
   DWORD dwSubNetMask, // 子网掩码! ~* T4 U2 U" ?3 ^( X! Z6 y- E
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP) Q( }  V* K( X2 J2 D. P9 b
- Y* ~: D; k( Z1 {* \
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)3 o/ x+ b0 L/ K# ?) o
{5 q& H8 \/ Z6 @  J+ Y
   BOOL            bResult = FALSE;( c, b4 ^  s( N
   HINSTANCE        hDhcpDll;
( G6 C% _# g0 E9 G8 ]    DHCPNOTIFYPROC    pDhcpNotifyProc;
" \  H0 p1 f( `  M" G, _) @    WCHAR wcAdapterName[256];/ L/ U" E2 [, O8 c8 z# @- s0 E
   
( ~: B- B) _: l- ~. o$ I    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);) }( Z7 V* {# c# y1 Z3 g& A7 a
. d( r2 G" d# _# i
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)6 c" Q& a; D+ S+ ]
       return FALSE;; N; r3 H: j8 F$ G
) k$ a- S8 _: Z& V* p
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
$ Y4 d  R9 ^2 H7 j        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
% {4 k* ^2 c. L' d0 x            bResult = TRUE;
9 w) i2 C% \* W( F8 n8 n+ Z" E) T$ m/ y. i
   FreeLibrary(hDhcpDll);( c+ g4 K6 L: L1 d; q" H9 Q
   return bResult;$ E& w% K: d4 T* d2 G7 T
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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