找回密码
 注册
搜索
查看: 5193|回复: 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地址的详细方法介绍如下:
  K  _# T4 U0 O1 E/ R" u0 J4 E% \0 H# O' ^$ w7 W# [0 \6 ?# A
一、获取适配器名称
3 ^! o& G  S6 m2 a6 {$ S" e9 Q5 {' u- k, Y% H7 h! o
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
5 {/ F0 X+ G3 r3 P) s3 F. j
+ a" w( ]. z" Y0 ^8 L/ R, J1.1 调用IP helper API取得适配器名称
4 [+ L% y: X' Z1 _# b  J5 ~& [/ Z: y
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
- L4 s% V) [* T7 H/ n, SIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
( l0 s9 e1 k: vif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
+ R/ ^) G( V. q7 O' d{; i5 S5 T0 I; F1 y) k
   delete pAdapterInfo;
0 I# D$ U+ ~7 l+ A! v9 h- W/ {    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
4 j4 f+ l' u  C0 z9 Y    pAdapterInfoBkp = pAdapterInfo;
9 L# N. J4 N& H9 I! e}
- ]0 F1 o/ L: Wif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
* D3 D/ c4 b/ N/ V) J& c4 `{! y$ S! Z. j, x' q6 Q2 @; {) u: T- d
   do{ // 遍历所有适配器
8 w. ]1 o9 d7 `9 V+ n- T0 \  m        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口( ?9 b% F  ~. z; D: T6 U
       {
# ~+ \  q- q( ^9 Y" e, ~* c            // pAdapterInfo->Description 是适配器描述# t- k  h- L5 `
           // pAdapterInfo->AdapterName 是适配器名称
2 }' B- L% _" C" P% @1 ~& X        }
8 o' n% |7 X6 a( e+ g        pAdapterInfo = pAdapterInfo->Next;
( @6 r  g, `0 F" I5 H    }while(pAdapterInfo);
! O: u  Y6 x( j; o2 j3 Z/ _}
9 `/ J& p8 l2 C. Z7 @delete pAdapterInfoBkp;
  J' m" _" Y! i. V5 {
. `7 o6 L$ z2 F3 s7 N1 |* v1.2 读取注册表取得适配器名称
' _: U* I' @% B5 r: ^2 d
! G) F/ E7 c6 |7 `; R" C在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;2 t8 C: b4 L" n% ~3 e
9 C, Q, y2 F2 v
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 ~- ?& v2 m, q# @  `
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",# }8 G2 u. e( m9 s) Q. Y+ a6 _" x7 h
           0,% A  u* F4 |. K7 |" T0 m, K
           KEY_READ,0 K. a3 c9 {* @& i0 [" o  W# y
           &hKey) != ERROR_SUCCESS)
6 O- k- @% F" \5 l- x; C    return FALSE;+ l. Z( B5 Z' \5 r
' x/ `0 X0 I! E% h7 s2 e
DWORD dwIndex = 0;
1 T: c& |3 L. rDWORD dwBufSize = 256;4 J/ C2 o/ h* ^" B
DWORD dwDataType;0 V4 `( ]) y! G6 t
char szSubKey[256];* \3 \9 H. X6 P. d2 E5 x- a, x9 }
unsigned char szData[256];
: C7 ~9 H! U6 b, N/ W4 e
( y* h9 H' \- |0 Jwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)3 v0 o& H+ @! a& G( W) w
{
6 k/ y+ @2 Z( a; Q" r# u0 V3 }    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS); ]5 J$ z" ]6 S; O& c( |
   {        # y6 i* ~( b4 T3 |* l
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
& B6 e0 E; I9 ^" n( P; x2 b' \        {) s! R6 b+ b5 T9 L% f  Q
           dwBufSize = 256;
; e+ g+ A4 F# k( ?8 O# _            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)5 ?2 n6 x" S( I0 K7 v  X# C
           {, j# d' f5 m, T' e3 E% i
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
% _6 Z- {" C# E/ ]6 [. E7 h                {* l, A! g2 r( Y- B
                   dwBufSize = 256;
+ R7 z# X/ g- a$ U+ p, c* C# a$ r! C                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)' ]2 N; W0 Q/ R6 C7 x3 M2 R& _2 z% g
                   {6 v1 N; t2 g5 k5 W( `
                       // szData 中便是适配器详细描述, V" x' m' D* U
                       dwBufSize = 256;  G# o  b$ M$ z& @
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
2 c. h0 Z0 v5 G* J4 j+ m9 X+ q- y$ D                        {+ s: E4 f0 F4 t; y
                           // szData 中便是适配器名称$ u- R2 W- B2 z; Z8 }7 q
                       }
: a. f/ H/ ?  E9 o/ Y                    }7 \+ t) e$ L+ P: O
               }
$ w8 c" x5 C9 p! a: X/ r( M  L            }5 p* e2 x2 ~& ]$ A) u
           RegCloseKey(hNdiIntKey);
; f' M. T7 h5 U1 H# N        }
$ C8 N* }: e% a) l        RegCloseKey(hSubKey);
5 N: K) w- x5 Z; d! @+ @& j    }- k  Y* V$ E# X; s) n
4 b" i. c% W, Z$ u* V; i1 ^
   dwBufSize = 256;( p& J8 N' J+ T. {9 p1 F
}    /* end of while */3 h1 J& W. b$ W! w, M
       
) c) f) m7 F/ y: @RegCloseKey(hKey);" Z  L( v6 w- s
二、将IP信息写入注册表$ e1 R7 a7 {9 M( R5 E- j5 B

5 E7 ~! g8 F& a7 A/ |1 O) |7 B6 ]6 C代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)8 \* \2 \# N/ y- [7 z& F
{
  L; o4 c) s. d" Y+ G    HKEY hKey;
4 J8 \2 C, E  w" p    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";& _7 w5 g% V% j' r. N! L
   strKeyName += lpszAdapterName;! u, U0 u) e$ R' H2 U# I5 n
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,/ U* v6 j, Q' _. _( n: K1 x1 T$ E5 U" v
               strKeyName.c_str(),: P7 i( m) d0 [; l$ l
               0,
, R- J1 X% F  V* c  _: X/ a* J- r                KEY_WRITE,) s5 ~( P+ P7 p6 A% S
               &hKey) != ERROR_SUCCESS)
" `6 N; \( X% p1 a5 @        return FALSE;* m7 b, o1 n% \( U6 d) @% \  O# w
   
2 t' g( @) K7 P9 U: q    char mszIPAddress[100];
$ U! t0 X% U( ?# h2 T7 o    char mszNetMask[100];
9 M- K- T4 O# w    char mszNetGate[100];
) Z9 X, h5 R5 S5 r9 m
- K$ W7 u5 M. {9 _/ K9 X4 r4 ]    strncpy(mszIPAddress, pIPAddress, 98);$ e3 F) x5 x4 G) C% c6 a* F
   strncpy(mszNetMask, pNetMask, 98);
$ O5 L- E- w! f    strncpy(mszNetGate, pNetGate, 98);
) F7 ?# S! y/ {9 z( z
+ g0 u# t! }( V; Y/ \: k    int nIP, nMask, nGate;
0 a/ x9 g. s( r; r9 {3 N  h; R
   nIP = strlen(mszIPAddress);
9 D9 F5 A: u+ E4 [    nMask = strlen(mszNetMask);* V* L8 X' ~. e! D5 A. X3 h
   nGate = strlen(mszNetGate);1 A2 B+ @6 U1 v+ ?8 C1 z8 o

  p6 K6 l' j# }  E6 l    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个05 O6 x) J( x1 o& M
   nIP += 2;
% {; e" C! G8 E' D4 R, U
" g1 J. ~9 y; y/ }8 V    *(mszNetMask + nMask + 1) = 0x00;: M$ K; _! w" o: E; L
   nMask += 2;) K# d+ n$ A9 ], i2 P" k: x
8 c% Y& U$ f) e1 M% k( N
   *(mszNetGate + nGate + 1) = 0x00;( S' s2 s: O) r; q, Y" b6 d+ S  B$ v
   nGate += 2;! {, H6 Z0 n: ]! x
   
  S- d6 s; n7 Q. K' @    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);, P0 f, L4 C6 F1 ~' ^; I. p
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);' _" L3 ]; }% y. z
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);: n6 o; ]# i& j- ?

( n$ w/ ^: Q) g    RegCloseKey(hKey);
  a1 P4 \! c: \6 R
+ v$ B/ Q$ d* U: E( L) \$ j5 f    return TRUE;
1 M1 S* M' f* ?# X}0 M0 H  C: b  A% ~5 w" Y; D& Y4 w

2 }1 h+ p8 ?$ F. I6 {/ j三、调用DhcpNotifyConfigChange通知配置的改变
  i' e5 D, K: o( |* f$ ]7 ^& ~) \4 G( x7 z8 {2 ~! `
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
4 n9 u2 ?# f( u4 {4 n: T" k3 K    LPWSTR lpwszServerName, // 本地机器为NULL1 c7 X+ ?' w2 E4 I$ Q
   LPWSTR lpwszAdapterName, // 适配器名称
% Q  h1 n/ B# d: d  S    BOOL bNewIpAddress, // TRUE表示更改IP0 `. v: v+ Y8 E
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
% V" ?% E9 V4 N    DWORD dwIpAddress, // IP地址, p# X' t# A* ~. B/ K8 X
   DWORD dwSubNetMask, // 子网掩码
$ Y! ~; }  L7 x& \) R    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP5 K+ E- _7 ?, T6 b9 G+ {

% X, T( T4 M* E: A5 K6 U5 M具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
8 i" m5 ~8 |5 d8 y. C# ]{
0 d  p8 l  j- c% m: a1 s" @    BOOL            bResult = FALSE;+ z! E3 K& |2 |4 i
   HINSTANCE        hDhcpDll;
# d/ F3 G7 R/ ^% H- I" q  O    DHCPNOTIFYPROC    pDhcpNotifyProc;
* e* e' E; ?1 |" o. G0 F8 U+ ]) n7 u! p, \    WCHAR wcAdapterName[256];
& V1 ~' T# V# c1 Z    
8 V. M2 D/ j7 @5 ~    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);0 B6 h2 Y  [# B

% T- @/ E9 C9 R9 @& ?    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
$ K1 S: |$ q' b% ?8 d& x        return FALSE;, g5 N1 R# U( G- z

1 T9 X- s( ]9 b; X: \  p    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
2 B; B# q& R, y) k* O        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)0 v9 @! I' G: G! x* n
           bResult = TRUE;
: Z4 k5 U9 L: v, _/ a% p8 p% m4 ]+ E/ j' Q$ I# J  m6 o
   FreeLibrary(hDhcpDll);
7 i) a/ J) @$ c2 h    return bResult;; f, t3 O7 ~  E6 U' V( i
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-14 00:56 , Processed in 0.017152 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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