找回密码
 注册
搜索
查看: 4727|回复: 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地址的详细方法介绍如下:# f& Y/ i+ B' N. D; }4 S
4 U! P' R7 ?+ t5 t9 q
一、获取适配器名称
7 ~8 o9 S7 m. _1 \. }: q& Y& c. D1 l8 ^; F: L" ~
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
7 i- V  {, k/ s( N9 c) X$ K, z4 I- h9 O1 I: x: \" u
1.1 调用IP helper API取得适配器名称 0 ^8 R9 o! X. @/ K! f3 e8 F/ P
5 J0 e) V2 q( b3 B
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
0 f8 H+ N( e9 X. m% Y$ u; FIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
5 I2 i; f/ L. V# \- J. Xif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大4 I. M8 W/ ?# @9 d5 X& S: {
{
* S- r1 G, s5 f" d; ~% ]4 a/ Z2 D    delete pAdapterInfo;
# U* W4 x! c6 v) A& c    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];4 ~8 t4 k& S- L) w
   pAdapterInfoBkp = pAdapterInfo;
$ w4 j6 ?" j* d- x5 m}
; j2 [2 @# o$ Y/ h7 ]if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )# O+ T% X  R$ `3 A' }+ v4 n9 ]- B+ u# H
{
2 g; ?! O) U, Z    do{ // 遍历所有适配器( X( A: J( l. }$ h. E
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
3 X% J) M3 ?0 o9 P" D; F        {
0 M; C, t* D- p' ]* i6 n            // pAdapterInfo->Description 是适配器描述
; q( t2 j* m( q* x) n1 W            // pAdapterInfo->AdapterName 是适配器名称
4 l% W1 [/ J; f  ?' m' X: J2 j- |        }+ B- m. w- A2 X6 C% V
       pAdapterInfo = pAdapterInfo->Next;4 S& k" l" P" C" E# E8 f, {# z
   }while(pAdapterInfo);6 c5 l: h! z2 L" k
}) r1 e1 d6 N! K# P" P
delete pAdapterInfoBkp;
) f6 l  \' B' m0 q) G, b* J& Y6 u. @6 k5 B6 N2 h
1.2 读取注册表取得适配器名称7 H3 _* _4 w7 `  _

$ H3 O9 z3 P  C7 {  t5 F在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;
4 B; L( K8 T3 D1 }) u+ P- |+ b9 ?) ?0 r
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- |) R; [: ?! t# j            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
6 l1 e" c6 _% _2 `            0,
( q( y" a1 p1 z' W: ~; p- H& G) B            KEY_READ,( B3 N- P* F+ e0 C- i9 W# x+ }. Y% v
           &hKey) != ERROR_SUCCESS)
6 |8 V2 y! K, D$ i) l    return FALSE;- d5 c3 g4 G6 o. X  \0 v5 z

) g8 G; w7 j# K1 C0 RDWORD dwIndex = 0;) [3 A; E8 ?. W* Q
DWORD dwBufSize = 256;& X0 V% d0 Z) S" e5 [
DWORD dwDataType;
4 K- R$ i' C/ m: j/ E. y3 B" x* ~( ]char szSubKey[256];
$ d6 F; ~( C. Q+ _0 Y# d9 runsigned char szData[256];
# y  N/ n4 ]) f0 Y7 @" o
2 l" j$ Y/ z3 C6 F, dwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)- e! f  _' N. D  i7 V
{
" d: S+ F. i9 }+ O6 G  g; ?1 @7 _- K, D    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS); I- M6 Z2 m4 K7 w8 A5 B
   {        7 J; J' s3 P  o6 d7 |3 e$ M
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)) [. U- K5 m" Z, w8 p+ s0 {
       {7 ]$ ^0 B9 j0 X2 {
           dwBufSize = 256;
; i! [$ b4 a# }* ]: f" X            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)1 ]- o! H6 t* U" x. x6 d
           {9 T' |  n/ D1 s1 @9 h
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡0 X( g6 P# n( x* R- E
               {) N; y* ]+ D7 W5 I+ ?
                   dwBufSize = 256;8 X5 d* P1 B+ r& B" s6 n
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
% H5 j  m4 d, q                    {
' W, _! D) w& O" n; n2 @                        // szData 中便是适配器详细描述- h& U/ ]3 ~  }* F
                       dwBufSize = 256;
+ n$ y4 M# ~' h# h7 h% p5 ]8 }$ r" S                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
$ y/ `5 v9 H6 c8 u3 b                        {; j; m+ D9 k# J5 F' l- u
                           // szData 中便是适配器名称/ P7 y$ o& }# Q% L+ G
                       }
# G! c2 `4 x9 P( P                    }2 L$ m, L  p0 b7 \: v
               }
0 v) S5 z% P. B# y0 ~# k0 `            }
$ W* r, R$ y8 v9 f; K0 E& l' q5 `            RegCloseKey(hNdiIntKey);
2 X! I4 u! |. J9 @1 g( X        }8 B- h3 P) t6 j7 Q! P8 E
       RegCloseKey(hSubKey);
# r& P( j- C+ {6 l    }  V6 n; p0 O. T  P8 e6 R

' H0 N7 ]# j5 A$ l- s) Q    dwBufSize = 256;
; c. {3 C0 N4 B) X* n- f9 z& Z}    /* end of while */
2 u# n! \* F7 z! E' S5 J+ a        2 {/ G+ \+ {2 R; e- u# E% z
RegCloseKey(hKey);
* K5 D0 n( {' j" V二、将IP信息写入注册表
" U+ ^0 ~& l  \1 q+ P1 V5 D; P* E9 ]6 V6 l8 J' J
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
& m. D% ^* h* ?7 Q{
8 k6 G7 l. b5 L" L    HKEY hKey;7 @- Z* f. y8 i. B
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";% X! u+ t; T; E
   strKeyName += lpszAdapterName;
9 x# T& D$ u6 K8 ?, q    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
, F; D' \2 x5 k$ E                strKeyName.c_str(),
3 o. s3 f/ @. i, w                0,8 Q# ~0 r) S, Y8 m
               KEY_WRITE,
# A9 o& v, j3 F$ x# F) ?                &hKey) != ERROR_SUCCESS)
; @: Q- L8 U4 k0 s  z; t        return FALSE;
, a3 z0 a) X1 \- {. d    
: v2 w/ \. H$ y4 N( N  f    char mszIPAddress[100];
5 j1 b; P$ @# z: g1 j    char mszNetMask[100];
% @. T: V) W1 Q0 T7 `! Y2 t7 U) L    char mszNetGate[100];
+ q9 u0 Y8 h. }/ h9 f$ m, R' v
+ N  O  w# b! b    strncpy(mszIPAddress, pIPAddress, 98);( ~  E- c- _) a% Y
   strncpy(mszNetMask, pNetMask, 98);
- G3 M" f3 ?0 T. k: D    strncpy(mszNetGate, pNetGate, 98);8 j9 F/ C1 D6 Z2 u6 X; N( v

# A* V" Z9 W" W, Z1 z" A    int nIP, nMask, nGate;
& A+ U# g0 \* O2 |* w3 J+ q8 Q' `( |5 g; h: N6 L+ R
   nIP = strlen(mszIPAddress);4 J) T# \" N; }  x
   nMask = strlen(mszNetMask);
7 ]5 V# E4 o- r5 O- G9 k* N6 s    nGate = strlen(mszNetGate);
4 t: X0 o' l$ W: E# W, Y
( ^1 E: e1 B+ b8 r1 G1 ]    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
1 Z& ~8 a. J0 c3 h    nIP += 2;
9 t4 }3 z6 D) S1 J
! |/ A2 a& C) x1 i) e! |    *(mszNetMask + nMask + 1) = 0x00;
% ]  E9 S' O* B4 m    nMask += 2;) u/ q; a" v! ^
' g; L0 _% F/ d2 k/ I! L5 u
   *(mszNetGate + nGate + 1) = 0x00;& j. a; W. h  @( `0 {/ m
   nGate += 2;5 r* }, f! ?+ ^8 ], K( i, Y2 M2 X
   
7 h  o9 h) N% o2 ]' r0 P    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);9 S: Z0 r* ?! ~, O' @& o
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
2 X  d8 Q, t0 V3 L5 v    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
- e$ v7 M+ ~1 T5 G- ~' m7 y
- P! {% \. X( {# A" a    RegCloseKey(hKey);
" V$ @) W8 \3 `! t/ e: v" ]8 a% X- N5 c$ b; k8 N
   return TRUE;
0 {# l& r0 F0 _/ u}
# H: z4 }6 y. c- Y
7 e# t$ P9 H( q& X/ f; d三、调用DhcpNotifyConfigChange通知配置的改变
3 A* |* u" q% @8 _
. O5 t  P& H; _# i0 y! ]未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(6 U  a: ]* p, Q8 \+ N; N4 Z& c
   LPWSTR lpwszServerName, // 本地机器为NULL3 w# I% F4 m3 a
   LPWSTR lpwszAdapterName, // 适配器名称
+ g. b6 K) _" X! W    BOOL bNewIpAddress, // TRUE表示更改IP
4 U' l: |+ ~" C- e    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
! L& p/ M( X/ _) J( D  j4 ]: _9 C    DWORD dwIpAddress, // IP地址$ T* B( g. h: T7 D( Q
   DWORD dwSubNetMask, // 子网掩码  z# M: t" l  q) W1 G
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP6 W& u# j  d# q3 x; k( t# O! ]

' ~4 _" ~& X- \! a* ~( ^具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
" _( Q' N6 s$ l2 Y) \' h0 E. ~{
3 h6 m" P& ?" Q1 C    BOOL            bResult = FALSE;
5 v6 a( m2 ?) H0 }1 j4 r    HINSTANCE        hDhcpDll;% H3 ]4 ^: f2 i7 d
   DHCPNOTIFYPROC    pDhcpNotifyProc;& T' q- E7 b( _  ?5 W
   WCHAR wcAdapterName[256];) N' O+ I6 d  ?4 n$ N
   
4 T  g/ C1 D7 R4 f( f/ T    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);- q( v" V7 ?* N2 g3 b- K% v
3 S3 l; ~* G0 e0 @0 Y8 K4 V
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL). M, o5 i/ }  v  C' ^1 V
       return FALSE;
) T. ~0 n+ x8 s2 |4 D! h. _: |
3 P4 O% X$ F- W6 u    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)& x  J( n0 J8 S. j# K$ ?' u( x
       if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
: t( L) c* Z* X$ W' x) ?! M' R            bResult = TRUE;$ ]$ S& x3 U! U/ c, f& O& G
" |7 Q! Z1 F) n# {- L
   FreeLibrary(hDhcpDll);
9 U- W& H$ J/ K, K* M6 ~5 E    return bResult;
0 [. Z! s) ?8 }5 N7 W) h( L}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-15 02:58 , Processed in 0.018752 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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