找回密码
 注册
搜索
查看: 4627|回复: 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地址的详细方法介绍如下:) ~/ _  m7 k7 [3 o$ N- B
9 M3 w# X8 _' x5 P/ j# R6 {3 R
一、获取适配器名称+ [1 M( q; u& q
! u9 K- s! K' U" f# A, d& P, |) d
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:8 w$ c* h2 [0 E, p$ _

2 ~: {' R; N) d2 Q7 P4 Q& p/ i. n1.1 调用IP helper API取得适配器名称
0 d' ?& l6 Q1 ~% m% a# [& L0 w. a
! j; K- L" ?% d+ OULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);. I- E9 a8 a6 g" l
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];$ p( f6 t& L9 _
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
6 z0 R4 W0 O# Y6 n* d{& o: s( I7 {5 I4 s- D
   delete pAdapterInfo;( }" ]* \) L4 }* P! e7 G* \7 V
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
; f, P* W! @2 E6 x( j/ {/ X& a& l    pAdapterInfoBkp = pAdapterInfo;
+ M# j: x0 q- p$ T5 s; X6 c$ F}( X0 m) w- ]' h! S3 K
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )0 l% b4 E# [: T- n
{
1 }* o' Y) S- \! ~/ B    do{ // 遍历所有适配器$ z+ v+ |( y$ q! `; w' U8 H9 e8 z1 v
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
/ j3 Q) `9 E7 @6 u, F; Y$ Y        {, m! R. Y$ ~( s  Z1 [6 H
           // pAdapterInfo->Description 是适配器描述1 P* E0 c$ b2 G- e- N8 e
           // pAdapterInfo->AdapterName 是适配器名称0 X, j' E8 v1 ~: }9 i9 v
       }
( B' g; ?! h& t1 V  P7 _/ g) A& r        pAdapterInfo = pAdapterInfo->Next;7 t; g) J2 M' ^- e$ K
   }while(pAdapterInfo);+ t) S+ v. w# T9 R0 L
}- [; p' p& O# s8 f
delete pAdapterInfoBkp;
1 r3 H# }- |4 I* i% P+ l
0 T0 L& X: N( f0 ^( b2 o( p1.2 读取注册表取得适配器名称
. ?3 A( a2 ?! K/ e  O8 _# k; X
* [3 {7 x! F1 `! C4 w  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;" G' {9 @* }' M4 ?  e0 O) T

2 {- l' u$ t( o4 J3 q+ xif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,! o" W$ q% x) K  ?
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
. m" F, u' j9 C, c  E            0,; p: m- d9 m$ C7 I
           KEY_READ,
0 s9 o! c) h1 G7 @            &hKey) != ERROR_SUCCESS)
0 Y! g- \7 J9 H+ V0 Y$ o/ L" Q+ ]0 L. o    return FALSE;
4 O- }. H1 m  h" r0 t# A7 D5 S, s0 y' h3 |) [
DWORD dwIndex = 0;; B! L9 V/ l5 Y" x# |- G6 ?4 t2 H
DWORD dwBufSize = 256;
# Z# C' |1 h  T- _- C' Z9 rDWORD dwDataType;
: P' Z5 X& v" ?: U6 g- Zchar szSubKey[256];
1 w; j& ]' @! W7 C" ^$ E0 Z2 Gunsigned char szData[256];7 p: }7 A+ z% {
2 u) K" y5 k2 ]. w
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)8 p7 g6 c# Q' j4 ^8 d
{
2 c' Y8 N! _+ S( k) {; h  Z    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
5 x2 }* ~, z" [3 b    {        
3 i+ o5 v5 [: @4 E6 I        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
1 d9 g6 c1 O- b& E& ~        {$ A. E2 Y; w* ?7 k* Q' _; L9 V# S
           dwBufSize = 256;
( |8 \% Z/ o) K, y! ^            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)6 Z# _" i) y% v! a
           {! w6 r( y  K: }; _
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡% y1 C  ~* v. V# C
               {, [! M5 A! _5 q  Y
                   dwBufSize = 256;/ W; t. J7 l- m, M- i
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)* u" Q" Z" f- n; Y3 u. N0 m
                   {( f% F" w9 ~. F, A# q0 e
                       // szData 中便是适配器详细描述
" r) f6 j# r/ @( l% C                        dwBufSize = 256;! l) \$ D" y: k0 \5 E+ M& b
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  b5 m& u. j$ j# w  \3 P% Q                        {
' I, C6 ]; h, m% N5 B8 b. i5 d. l                            // szData 中便是适配器名称
2 N: T) T0 y0 _6 _7 L                        }
% Q1 f" L9 o8 N$ X1 b" R- s                    }/ H/ N3 T' ?1 ]& p( l, o0 f' s
               }
4 s3 T, s; n0 S' ^  W            }
, G- h# P% S% a& d            RegCloseKey(hNdiIntKey);
( C- }% R" _% f        }
( K& U1 q6 X4 }6 g  z0 N! U        RegCloseKey(hSubKey);  R" R/ J" i) B" |
   }
; p/ u% y6 c. m( |4 g: D+ T! _# D% B$ S2 M
   dwBufSize = 256;9 L3 Y' i" O) f5 u! X  X" g
}    /* end of while */7 B0 @2 |4 q/ c
       5 z6 q/ s6 f& r1 H' M" p
RegCloseKey(hKey);$ N% F4 R2 \& |4 r, `2 E
二、将IP信息写入注册表; X, b& m7 q5 N1 P) Q0 Y7 B

/ b8 K6 ~) t( [" c6 m1 A代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
! U2 }8 W* t' E9 a/ h{- V1 f$ w% O* ]* s" c' ^# p
   HKEY hKey;# ?) y9 O+ r( i
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";7 m' i* b% }3 c1 Y$ o
   strKeyName += lpszAdapterName;
* U/ i) p; E- {/ m" P    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,; p8 w5 o% H  w1 Q! ^5 L( t
               strKeyName.c_str(),
4 ]5 @; K  K6 R) F3 R3 c! v                0,5 v  s. r7 E8 E9 x' m, l8 j
               KEY_WRITE,. l" j! R, u5 n; E
               &hKey) != ERROR_SUCCESS)8 \& H7 h5 x, O, Q( [! u5 v6 X& ^
       return FALSE;
/ m( W) i4 [) M  P- B    , G' t0 o/ ^+ R" y) i' x" G
   char mszIPAddress[100];
9 l. n7 \6 r+ ?* ~4 d7 c' {( r    char mszNetMask[100];
8 V. e: V$ @8 |  u% s/ Z    char mszNetGate[100];  A' R- Y0 T, V
! }' u! ~% F3 i, h0 X# P; b' m0 Q
   strncpy(mszIPAddress, pIPAddress, 98);
$ U+ o. `  n0 X$ x/ C6 _9 h7 h; |    strncpy(mszNetMask, pNetMask, 98);
( I" F4 u3 M; v5 y    strncpy(mszNetGate, pNetGate, 98);
* F' q  y3 V7 z6 T
& u4 p2 C. l! }/ M, O( i    int nIP, nMask, nGate;
  ]9 j: B6 O9 K, F! k: @" y5 w* e0 x* M8 n8 Y
   nIP = strlen(mszIPAddress);6 M7 u% f& e2 a7 a6 d
   nMask = strlen(mszNetMask);
- n6 m% [- q: |4 I8 L5 K) I    nGate = strlen(mszNetGate);
/ R9 |* t5 x  Y% D
' B& k! N+ t: O7 G    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个06 z/ b. |, q/ R9 T
   nIP += 2;, x3 u. f) e/ Q- X( g1 f6 ?

% B; F: Z$ w# P4 k) M1 `    *(mszNetMask + nMask + 1) = 0x00;
9 C4 [  m6 c6 B4 L* T    nMask += 2;. m5 M4 {  i: z+ a) [! m

& s* ?' a* f8 y) ^    *(mszNetGate + nGate + 1) = 0x00;
5 u+ {# k" g( t6 _- h    nGate += 2;6 Y: O- q, Q& b9 F' j0 ]5 U
   
; o2 ]  U2 d/ c6 ~% d' [' W    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);8 E% y% J$ a/ S! c. @( Q+ [
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);3 |1 p  T& Z, G( N9 ?2 S! ?
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);) [7 E0 k" o& T' y  H2 b8 a3 T/ V1 ^

1 H% S4 _/ E5 e' K$ e    RegCloseKey(hKey);
$ Y2 q6 ?* \5 P1 @6 e7 _
6 v9 J+ k+ j$ Y( F% ?    return TRUE;
" e. v1 k8 p1 T* s5 d}( w, O$ M+ a; u- b3 O  [% K. _
. b. W; T6 z1 Y( z* k
三、调用DhcpNotifyConfigChange通知配置的改变
; M0 n; S2 y/ V( b$ ^& B* j. \. B7 r7 y. D" s3 g2 t+ ]7 ^7 G
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(& f) p! a4 P* B6 E" f- X5 ^% I7 p
   LPWSTR lpwszServerName, // 本地机器为NULL) m; _  X+ B! L# q  T
   LPWSTR lpwszAdapterName, // 适配器名称  A; a  H/ j' a; k- v7 ]
   BOOL bNewIpAddress, // TRUE表示更改IP
3 R5 B: T5 n. c2 D    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
' h& @1 |" f) v% Y' ~1 x6 q7 ~    DWORD dwIpAddress, // IP地址$ b8 J4 J0 q: x' P
   DWORD dwSubNetMask, // 子网掩码2 D+ M6 N" N$ p2 t1 d- @2 r4 [
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
0 y: x3 V- s# i5 V) K. U8 ?4 r9 _6 W. z6 N' K' |
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
  O4 C( C* C) \6 E3 Z{
3 V" ?1 _8 Z: D' z    BOOL            bResult = FALSE;& k5 R7 f7 m+ `' L! k
   HINSTANCE        hDhcpDll;+ N8 S6 {" `0 O- m
   DHCPNOTIFYPROC    pDhcpNotifyProc;8 j' e6 v' N$ d" s0 p5 W1 W* H/ u
   WCHAR wcAdapterName[256];
2 E' z9 I; Z4 G( A3 D7 m    
8 I1 ~- k/ v5 i6 O, W. r7 P3 V    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);: ]/ N, W/ T6 P/ F
  Z6 ?% d: T) w# a2 }+ x; o
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)  ~+ [3 X0 y( E9 _
       return FALSE;
  a4 c" B% K# V4 r
* t+ Y. \1 D# W, l9 i/ E* T    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
1 s' F3 U) A* l: o5 j  Q        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)4 Q2 L1 Y* j$ D$ w2 h5 f# N
           bResult = TRUE;
/ d# T2 P- ?# J' l1 @8 ?  x  I* V- F$ y2 o' `
   FreeLibrary(hDhcpDll);
% v2 y; C) T6 X" s$ U( i4 A    return bResult;- y" @3 D; P3 ^5 y3 s
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 06:27 , Processed in 0.034922 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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