找回密码
 注册
搜索
查看: 4990|回复: 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地址的详细方法介绍如下:4 ?# K+ x, v+ [, S$ @7 L; f7 z: Z

! O, O4 e) S7 M8 U7 j一、获取适配器名称. ?8 ^5 m( d0 e. w+ \
0 m  b. t% R( R* C3 A2 z
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:0 c( T6 n# u3 V+ y; k

7 |! a1 a8 e% R0 G. K: s1.1 调用IP helper API取得适配器名称
. X6 _) U9 R/ g
$ }2 a. Y  V; q; F8 zULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
4 `8 `2 r# N, i6 o; ]IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];& v( j( W" u0 j0 f$ K2 [' i* U
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大( h/ _& b" I- C- \, a! M
{$ A. G; [* R" T/ [
   delete pAdapterInfo;
" g1 b9 s; z0 l3 Z% n9 M8 Q" C    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];5 x* {5 q% M! g5 m  k3 h: t9 t& T
   pAdapterInfoBkp = pAdapterInfo;
8 O" [# L: o  ]; o* s}3 S$ D6 p& \8 L$ J
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
" B2 p5 V) |5 u7 e. P9 R{% E. P; n2 k) s7 \; m2 _( z$ M
   do{ // 遍历所有适配器
) D, V2 i# B, a" [. x3 b        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
' p/ l3 H9 K3 \' f; {        {
  O5 M# n' z$ f0 S6 T/ @- I, w            // pAdapterInfo->Description 是适配器描述/ t$ x" e2 B4 D
           // pAdapterInfo->AdapterName 是适配器名称$ R/ P3 E: T. l" v* i9 B
       }
& h; c; T* F+ Y/ S6 I        pAdapterInfo = pAdapterInfo->Next;
  j) Q5 v6 f2 t$ B% n8 V2 H  W9 R( X    }while(pAdapterInfo);
, k3 e( o& y- }& f+ t# o8 T}
) _! Y5 \* o. kdelete pAdapterInfoBkp;
) W: s% c+ F8 N% [
, E) e- s5 ]$ d9 r+ b8 D8 G1.2 读取注册表取得适配器名称
" x3 I" k8 C) ^) f6 N" r4 \
; ^- v* k* Z8 @: Z( D8 Z2 Q在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;
; ^% F, F* T) D- e1 u" i' v& @3 u* r0 o& @2 q' d
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 e$ B) }3 C3 Y: m            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",. T" I6 y: M2 ?! x: @% J; v/ J
           0,
2 i5 E  E$ n% k, g5 \; E8 l            KEY_READ,# N7 [; A+ ], m, Q
           &hKey) != ERROR_SUCCESS)2 C7 |* j* V6 S- g; O0 r
   return FALSE;9 A& ?+ _4 s. S# p' n6 L7 w
; o: F4 ]+ @) ^
DWORD dwIndex = 0;0 v1 j! H1 ~; B4 Q; o3 T
DWORD dwBufSize = 256;
( K4 l" ]3 n, N4 p6 ^% H$ qDWORD dwDataType;
' u& S  g: R5 R( K6 D! N: jchar szSubKey[256];
7 T! n% W# O2 ^( a5 Bunsigned char szData[256];
5 Q4 y+ k/ d/ d8 j! ?. h  M
- M% ]% p+ F( _3 R" nwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
9 M. Q; y- k1 F- S) X7 o, `7 \& e{
/ K4 ]' l2 p- @* H8 S" @% Q    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)8 [& J" N# E* C+ X# N* F+ M
   {        
9 }9 ^* l! ^& U        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
8 A9 R& H" ^/ |# v( x( O        {+ g/ Z5 y+ C1 Z* K
           dwBufSize = 256;
5 J' x( {# p0 s" [            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
3 c4 L' d# D: K5 A5 G; i            {* u, U$ R3 P* g' }2 R- N; d
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡. _5 u9 o6 T* g/ [3 z; k
               {, S% [* E0 A0 m/ P+ Q( T
                   dwBufSize = 256;6 o- L, C4 {" o7 @* n
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
/ R- X7 T" ]' [7 X1 g0 X% F                    {
$ \2 _- X' K# N& \                        // szData 中便是适配器详细描述
- W5 g; w  Q; h                        dwBufSize = 256;3 W; t9 A+ J$ }& ^" C2 P6 V6 I
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)  [" y+ K) Z1 e) b
                       {
! g. J; f; p' v7 [4 C                            // szData 中便是适配器名称
; E6 A) ]9 k: E! P5 j; Z2 E( R& s9 I                        }2 f0 Y. l1 R4 o. I  h
                   }& G  L# ^5 e4 u* `) s
               }
! l! h" c8 M1 e5 x$ }            }
' r! _) m. a0 }8 j, [3 J            RegCloseKey(hNdiIntKey);( y2 W$ g, M$ z% {
       }) p& c) k1 n5 e. C) |+ t
       RegCloseKey(hSubKey);
/ c# L, c6 \. @2 R0 w$ B    }
3 p3 f/ ?( l4 H. P3 b# ^& J+ z' h* v
   dwBufSize = 256;
- a3 k, ^: N; F7 x1 E}    /* end of while */
# r! a( A/ q$ t5 W( F2 ]  ^% D/ ^        ! r( T, x5 y7 V, ?, Q) r
RegCloseKey(hKey);$ |( X& v# `% L% `
二、将IP信息写入注册表5 C7 W& U! w% ~' i
; X$ t  F0 g, K( }
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)9 b1 S1 m, w. w, j# Y( o1 Y
{5 ^7 g" c) c: D' J5 y# f5 O/ x
   HKEY hKey;
  u9 i/ g# l3 a! v4 P  y& H3 n6 R    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
4 O  m% M5 j) e' D# l, ^    strKeyName += lpszAdapterName;
+ t* \+ O; G, [' n    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
! ~7 j* h$ O1 r/ E/ p0 L" n                strKeyName.c_str(),! V: l% t/ e0 [1 n
               0,
/ R8 g6 r6 S( T% [! f. D                KEY_WRITE,9 a. N; X7 M0 v: B  d( n! p6 I
               &hKey) != ERROR_SUCCESS)
4 `+ a2 K3 B6 H$ k& T        return FALSE;6 ]% a0 K/ F- W$ Q7 H
   8 x  v# G* z& K: O/ f: @4 _! r% w
   char mszIPAddress[100];
7 ~$ z8 J! i& H. `9 P( D- i% _    char mszNetMask[100];
  n1 ?$ ^4 @5 D4 Q6 e3 n1 H    char mszNetGate[100];
# ]  v, S' K, X" y/ i6 w2 l; p2 ^% D8 v6 Q/ X$ }
   strncpy(mszIPAddress, pIPAddress, 98);
9 u4 {0 N0 m. z$ j) _    strncpy(mszNetMask, pNetMask, 98);* F# \) z* {( _! S: S
   strncpy(mszNetGate, pNetGate, 98);4 `& x) V; u  y0 _; E% j1 v* s3 w
1 l. _( X5 p; p
   int nIP, nMask, nGate;3 [) ]7 n9 h9 ?
7 S  O# _1 b$ Z  l
   nIP = strlen(mszIPAddress);0 C2 Y! Y5 Q4 v+ r: k
   nMask = strlen(mszNetMask);8 S: k0 L9 ]1 h1 C3 ?" ^' Q. B
   nGate = strlen(mszNetGate);
' y* N3 \# p8 j. s( B- Y) i: B6 P( R5 Q3 e" u9 T
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
- B5 P$ b5 S/ B6 F9 t: E7 X- Z3 v    nIP += 2;) v( g' S0 c% Q  v1 j- j. m
+ T# f( L1 p" k/ h
   *(mszNetMask + nMask + 1) = 0x00;: l7 z" }4 [) l+ u, P
   nMask += 2;) s, I% V! j* L/ V% F& \
. l% V5 \* N# G9 Q7 E" t
   *(mszNetGate + nGate + 1) = 0x00;
5 m2 Z( J6 Q* O% ]5 s    nGate += 2;
, f1 o. u. r* h1 X8 e    " T. E7 G; }) p" |% g& j
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
* |5 ^# I  r) \" V* \    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);/ S  Z6 \3 r0 [8 D4 C
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);9 h9 B2 h7 m$ S' g  E- F/ l4 ^

( j  n3 d% T9 u9 @' C    RegCloseKey(hKey);4 ?- q; @! R& c' Q

7 j- s& T, R* L6 [% j    return TRUE;
& I6 Z% |0 H; F% I}
4 ], X* V# b' V/ r  X. o5 Z2 ?% z8 q6 N& w$ K* i0 {
三、调用DhcpNotifyConfigChange通知配置的改变' I7 m2 b7 X' v2 H

0 H* N( o0 ^6 E$ ^: `" o8 N未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(5 G+ E; Q- K6 f0 M
   LPWSTR lpwszServerName, // 本地机器为NULL; |6 A% c3 a# ?4 x+ K+ P
   LPWSTR lpwszAdapterName, // 适配器名称. Y7 V2 Y# C" I' ~( z$ B. F6 e) e; c
   BOOL bNewIpAddress, // TRUE表示更改IP
8 t0 N3 J. M+ r; \    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0- ]9 b) c/ I" z8 I( F: v: \
   DWORD dwIpAddress, // IP地址* u0 ]2 M# w# R7 d+ ^) z% {
   DWORD dwSubNetMask, // 子网掩码0 o- d% W/ a6 y, U
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP" O( {4 l: ^  |2 a

9 p1 ]. r, C- c' ^  c具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)# }' D2 S! L2 n' ~; R
{
) [% s. S* J: b6 ^    BOOL            bResult = FALSE;
1 n) W) N/ o' J+ \9 @" L5 }) e    HINSTANCE        hDhcpDll;2 T$ l) q6 S5 P
   DHCPNOTIFYPROC    pDhcpNotifyProc;! w2 ], w4 R0 x2 a* Q. V& C- o
   WCHAR wcAdapterName[256];: {' r5 e- a! U1 b" o
   
/ }8 k5 y& N7 X2 ^    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);$ W$ T/ A* [7 ~3 W. P

+ p0 M  c" ~- O1 W- s    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)2 N4 q9 B! g5 @3 c: b
       return FALSE;
+ c5 W+ M: l8 g8 X
" T( Z7 w, o) @8 _    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
+ C, U6 u' V6 d- m        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
; [$ z% V" {# O; |/ X6 m0 q            bResult = TRUE;
# g2 w" D3 f, h- V  V, l$ |! I1 T  O" c% l8 y- f% W8 _
   FreeLibrary(hDhcpDll);
* I$ {# x: b" Y& z    return bResult;
: T' S- t8 B  R0 s' l}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 08:47 , Processed in 0.017822 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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