找回密码
 注册
搜索
查看: 4765|回复: 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地址的详细方法介绍如下:2 W. q! S2 N2 G& ^9 q

5 j: x+ P( V' u% K6 p0 ]一、获取适配器名称6 F0 Y1 T- v0 \/ A

. n# k7 z" T0 Z+ u这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
  v2 f2 H2 M# u/ @- Y1 n' c
2 T# w6 Q; \" M6 H1 K: i1.1 调用IP helper API取得适配器名称
0 x' ?4 l! z$ Q  Y( {; [& z6 w
/ J1 `4 K$ Z7 N/ HULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);5 L& H+ j5 v* }' s) ^: H8 L. t8 f
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
9 L# d9 Q2 b/ U6 Gif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大5 O  J" H7 u% q9 W
{
& d. B; q4 s( O8 ^. {1 }    delete pAdapterInfo;$ ~& {. @6 D+ _% @8 Q* X5 u( U
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];* z) n2 ~7 L" H# X( F
   pAdapterInfoBkp = pAdapterInfo;
; p% I4 W/ K. {0 y& U% g' Y}6 }! ^, O- o2 v  A# Z
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )$ i' b" l2 E- u# r& ~' D. m
{; s& J5 B: }6 E* w9 t' Q! O
   do{ // 遍历所有适配器, w2 r! `2 ^' C( M
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
* A; r3 p' R9 Y$ |6 r        {
2 q% M/ e+ P% M% m1 T  ~& N) H            // pAdapterInfo->Description 是适配器描述1 l2 G0 ~% k9 L) j
           // pAdapterInfo->AdapterName 是适配器名称% A+ q" e! G' C. e) X6 U/ T
       }) z2 t+ T# m* A' @5 t3 ?& s4 M( T
       pAdapterInfo = pAdapterInfo->Next;
9 \1 l7 I% Z0 ?6 _    }while(pAdapterInfo);
" b1 F, ?! Z& A3 f& O3 z! \}
) d& s8 e3 B( |9 F8 ]delete pAdapterInfoBkp;
, L" f4 p) a: f% e% f3 h, f" O5 f7 Z; m1 }
1.2 读取注册表取得适配器名称+ ~2 G- h; c; G6 \$ ?

6 R# }$ v. O& m0 H在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;
/ v: p: w, q. R- e; Q, T! f6 j; B6 ^3 `. V# z" G' B5 d  i0 t
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 u5 _# Q6 J  F
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
$ b) L! w% o# ?            0,* R+ I. F  V6 [
           KEY_READ,
7 W$ C4 F  n# b& o" `, `            &hKey) != ERROR_SUCCESS), r' b# Z; z7 M  U
   return FALSE;
; D8 G/ m% l6 |3 e1 `7 W! f4 M
( Z6 E9 |& i$ p4 b) L9 \DWORD dwIndex = 0;8 t# l1 p  P7 x7 J$ H
DWORD dwBufSize = 256;4 p2 y4 a5 K1 j( M, F/ L
DWORD dwDataType;
: L, s& Q6 D/ M; nchar szSubKey[256];1 B1 t* s# |8 }: ^0 I
unsigned char szData[256];
4 z" Y9 s6 R+ P* Y; v& c; ?
* N3 f6 L: Y2 t8 qwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)% m$ T8 n& X, ]5 I% h
{
7 M# q  O! S2 a6 o5 V: j% k    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)1 }6 _! \6 p7 m( z# V9 i! I9 A
   {        $ d9 L3 Q; C" L5 g
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)+ f7 V4 s' [. W% v* g
       {
  a1 x9 s0 ?; V7 C. L            dwBufSize = 256;
( \2 |  w3 v9 ~4 v/ _            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! Y5 N. L3 b2 A. p! z' A
           {
3 U( L& c& n) [. L" a; ?# U; {                if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
& w- `7 [5 o! ]2 L8 H0 B) |; y                {
& c* E5 L: H! a# I                    dwBufSize = 256;2 G( v" E2 ~$ f9 E
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
% ^1 S3 L3 x6 H: i. Z                    {7 M1 J; W! m2 }  z
                       // szData 中便是适配器详细描述- }2 @* J# O! k" a  p% S& Z4 ~
                       dwBufSize = 256;
3 V! h& d* z8 w* v                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
; J2 a! h+ L7 R. n                        {9 F: R7 F7 ~8 H1 H+ P3 J& \* F
                           // szData 中便是适配器名称9 ^, _. b- ^% f7 v  S8 X
                       }
/ \& X* Q' }/ ~; s# o* [7 L+ U                    }% F2 y6 \' U: j
               }
& r* V0 F4 C, d4 N            }3 L& Z/ x. Y3 O  ?* Y  E
           RegCloseKey(hNdiIntKey);
7 M8 M! D, ^6 i" ~) s$ p/ X5 r        }
/ s3 S' l; w( o! m4 g        RegCloseKey(hSubKey);
* q$ b! J/ p- J" h2 D) R- U' t: d    }
6 n- v9 ~5 C! Q( ?0 ?/ n2 w9 r$ I0 c
   dwBufSize = 256;
( n7 S  F9 j9 k, ?6 s, d& O# u; C}    /* end of while */
) D7 Z9 ^6 D& _; N! Q        
2 v; ~7 l, S* I& ]# d' u; ~  J7 XRegCloseKey(hKey);) t( O: O" m1 b& i$ U' t
二、将IP信息写入注册表5 z' i% A9 C/ ?' f3 G' }" ^

) g, N/ r7 Y" |' M代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)3 m) m3 g, K, ^0 m' @1 Q
{
1 m, _# x' ^5 i! l' O, h+ I/ c' n    HKEY hKey;& a7 W2 S7 ~6 o$ x6 F- O
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
/ w0 d; o/ I3 K( l6 J/ D; Z& t  |    strKeyName += lpszAdapterName;5 x9 S7 g! ]# D+ J# A+ g2 I2 @
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
2 Y; z% P: s4 Z* i: Z/ ?                strKeyName.c_str(),
/ J- P: Q1 H+ h" j0 `: {                0,
/ c& {. d: V0 _; q( J% w                KEY_WRITE,4 J- i2 K2 ]# {+ `  F  U% {; }
               &hKey) != ERROR_SUCCESS): @# P0 F  B! L( U- T; O# I
       return FALSE;1 l- z( t8 f+ d8 B
   
# w6 i. e: H6 g% `+ y& l    char mszIPAddress[100];. K- _7 D  g, A3 M+ K
   char mszNetMask[100];
. t! f% d: y$ G    char mszNetGate[100];
$ ]# e: k# V7 I! j, f2 G
. v4 ]: t+ b7 Z7 F7 Z    strncpy(mszIPAddress, pIPAddress, 98);
% H# h1 A+ Y/ U( s0 B. ~$ T    strncpy(mszNetMask, pNetMask, 98);. A' _+ j' G" e) Z' z% X, ^6 Z* b5 _
   strncpy(mszNetGate, pNetGate, 98);6 a! x. K/ f% }

5 E, d7 p$ S: ^$ S    int nIP, nMask, nGate;3 C) H+ c* h) z  U4 ?& y

# v' n) T# [: P+ |# ?    nIP = strlen(mszIPAddress);: t! B1 \; ], B# O) a; t" E
   nMask = strlen(mszNetMask);6 g" |$ F# `; C) r" m8 r
   nGate = strlen(mszNetGate);
3 `7 `! I0 h8 U* J& }" P0 ~, i. b7 b& Y2 K. O# f1 J, |. g' d
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
* y1 C& Y4 v! l" g' B    nIP += 2;7 T" n7 T' R* S- Y

4 D' x' k6 K$ C  Q5 S" [8 s    *(mszNetMask + nMask + 1) = 0x00;
" R$ d, G; C' _! W( `6 \: J2 ]    nMask += 2;/ h) j7 j$ v% ^& p
. Z1 ?4 e  k/ y+ S, b
   *(mszNetGate + nGate + 1) = 0x00;
$ U4 e! q! w+ V, C0 z; G- q    nGate += 2;
( j! v; A# `: }. m4 Q    # C) l# j# ]) P4 I$ f+ C- D: M
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);7 O! e6 F; Z+ U* h( m# T& i
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
: d2 h4 L7 [# u# a+ c    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
- \3 G4 W9 s" q  D+ r; s: ?* m
7 v" j' o5 ~% n7 k    RegCloseKey(hKey);
& r9 V3 r* d. |0 \% P; K# P* T/ \+ a; k  U7 ~1 A+ }
   return TRUE;
* \* s9 I: w, y, M. d}+ Q4 n0 p+ Y# X; b" t& e& _& `
) {# U1 m+ `: V# a* g9 ~8 v
三、调用DhcpNotifyConfigChange通知配置的改变- @- g2 Z# b3 k; r; Q
: m% G- k) y% o+ k1 x; P
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(3 v# d* {) ?: o4 \( E
   LPWSTR lpwszServerName, // 本地机器为NULL
' t% l9 F7 I! q4 C9 z! g9 p% L    LPWSTR lpwszAdapterName, // 适配器名称
, B2 ?# `: Q3 E$ L2 |3 B; R* l    BOOL bNewIpAddress, // TRUE表示更改IP
5 ^( g: ^2 D+ ~- v' n) V    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
' }# ]: x, |0 g( u/ l' d) N- d    DWORD dwIpAddress, // IP地址$ R% R1 G1 N% y' ^' d1 {# _6 L
   DWORD dwSubNetMask, // 子网掩码1 a0 ~9 y2 A. q
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
- l2 S+ F$ S' Q* y$ t
5 N6 ^, l; R/ }" {9 ]4 K具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
0 O& Y+ r7 m7 v# F{2 l& _" {& P6 w8 b! I8 h
   BOOL            bResult = FALSE;
$ t0 G4 f+ Z/ l/ _! ?; Q    HINSTANCE        hDhcpDll;) d% F9 l0 @! ?1 [& k& T
   DHCPNOTIFYPROC    pDhcpNotifyProc;6 s9 W4 A5 Y. C1 g$ c+ n2 C9 M
   WCHAR wcAdapterName[256];/ ^* t! p% y: S
   
$ i4 F6 J0 X# K    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);' L0 ?# k0 b! A  y( t; a

7 S- r, @* s2 O! {* b5 r/ X- C) o    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
9 d5 n4 r6 J9 N: O5 _, R0 }/ L        return FALSE;5 r7 J# Y! I! d

, [' L& q7 f, j: F( o    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)- f" y5 w  J1 ]9 K3 n1 y! M( P
       if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)- r0 S1 u3 n) L& A4 C
           bResult = TRUE;
/ T1 ~, N. l1 G( s) ?5 u+ H+ h/ \# h3 r5 i. ~2 a( l
   FreeLibrary(hDhcpDll);6 R7 i) _7 ^% }* ]4 k/ L/ n0 }
   return bResult;
) V0 ^- o6 q. _6 b}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-13 10:12 , Processed in 0.018853 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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