找回密码
 注册
搜索
查看: 4728|回复: 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地址的详细方法介绍如下:" L: K1 I) C3 N: u/ s1 y" @

+ O( _8 g1 c3 O1 N2 t. f一、获取适配器名称& E2 K! l5 H; E1 k! A" L
( B2 q; Z/ e+ O1 a
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:5 [8 \. J" w$ l: r9 x

! x/ s' D4 J% _& e8 u1.1 调用IP helper API取得适配器名称 9 x# L3 K; o6 g  J( |0 ^9 p' {2 B

# R& r) a, [9 ?+ A1 `9 C% MULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);4 o$ c8 I4 X) |' \, x: _
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];5 |$ U$ @( G; c6 X$ Q' C
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大7 E8 i4 v+ i, Z! H0 p0 [
{( Y; o5 c) A' X: d+ V/ F" S% R
   delete pAdapterInfo;: F# A/ x# g0 p) N9 h7 I
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
+ G- ?/ ]8 {  V+ L- d+ S7 m7 a    pAdapterInfoBkp = pAdapterInfo;! z, s/ w8 e5 G# I5 Z
}
& o+ D3 P* w4 `7 n: Z" lif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )$ R' E, U- H$ ?
{
$ g( v! p1 K. Z6 b' R! x    do{ // 遍历所有适配器
8 B$ d; N$ L: g- a        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口* o% J' c  \# E
       {; J! ]+ K1 d0 r$ v, [# ^& l
           // pAdapterInfo->Description 是适配器描述) U, i) M  N1 w! z& ~! t
           // pAdapterInfo->AdapterName 是适配器名称$ l& }0 p8 g1 C) T% ~" v. a
       }2 y5 r4 W( ^, n/ L7 v/ M% ?
       pAdapterInfo = pAdapterInfo->Next;
3 |. d: R4 j) B9 `2 i    }while(pAdapterInfo);# V- C3 H# j! u& s$ M1 x6 C3 u
}
8 f, |. Z3 U6 d' V' x4 G/ g( D0 ?delete pAdapterInfoBkp;- r, A* l6 r; E9 T
. f8 A" k& i5 l4 [
1.2 读取注册表取得适配器名称
% X! Y- o: o# v7 X3 q! d. r% `' v$ r9 g/ X3 g
在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;# W* G2 V0 s7 E% F6 Q
+ j2 t8 O3 J4 [, o& m- q* g
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
0 W0 i- r$ P5 _/ q( O! d            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",/ x: L5 \2 \2 F+ u9 S8 G
           0,
- A, _0 A; L8 Z            KEY_READ,
( ]- C! ~. e" x            &hKey) != ERROR_SUCCESS)) ~: F5 S% \% T* |- S3 H+ O4 B
   return FALSE;
% X# o$ O8 |1 ]& K
2 H, |( J8 E, D/ V  @$ `DWORD dwIndex = 0;, g2 q* F% S1 z0 T5 l# `
DWORD dwBufSize = 256;4 U9 [6 Z/ Q4 a9 R& W! G- G
DWORD dwDataType;4 G4 ^% O: ~: ]* Y+ b  p+ B4 _- O
char szSubKey[256];1 G4 x0 u9 e: n. C/ d( B1 n$ @: X
unsigned char szData[256];
* }; g) r% ]. u+ W1 L
) i1 R7 j2 R+ x* q( Iwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)  Y$ q3 p  G, t2 E  `5 _" _
{0 _) X: s5 b# p: M
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
/ s- v* N7 E- N    {        
$ L9 A" K) E% R& `. Z        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS); O4 F' {" `3 ~9 D, x: P' _8 L+ B
       {8 H$ s# @! r7 P2 h: F
           dwBufSize = 256;
0 Y+ D2 z8 @, ?            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
9 F* D1 g- F( _0 d% f            {" M2 p5 c3 Y& C  G# D
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
; m: K$ ]4 A0 Z, L                {4 n# G" c  f7 V& F( E
                   dwBufSize = 256;
) Q; A% d8 q+ s, q) {5 f2 O                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
6 x$ x. b( |7 ]; A& ^1 M                    {
8 b$ |" r' S% T) P                        // szData 中便是适配器详细描述
1 f" E/ b& W6 c; V% G8 E                        dwBufSize = 256;
6 W/ s) r  W3 a                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)- i  @' g6 o1 _% \" w& y
                       {" k; z2 r7 a( K; |
                           // szData 中便是适配器名称
; y$ g9 q" k) n+ _8 i                        }, K4 C6 x8 R# h1 K
                   }
4 _* n; B, r* |; l; ~8 f                }- q. W$ O& ~6 r1 @1 N$ n
           }
+ ~3 s. `: `( j9 {+ o            RegCloseKey(hNdiIntKey);; x: S/ W' X% x
       }+ }& ]7 p0 f$ k" C; u/ x8 L
       RegCloseKey(hSubKey);
1 ~3 `, P, _- x: o! \; u    }
5 z2 V9 h2 C7 m3 X- u1 Z7 m( W/ p: N- |2 @0 E; j
   dwBufSize = 256;
3 J$ n5 Y2 B0 B0 Q( \}    /* end of while */$ f2 m6 A7 S0 [  K5 h! }* |
       3 e2 |; U3 B. ]. B& D
RegCloseKey(hKey);5 ~% f9 F4 r- \8 c; ]
二、将IP信息写入注册表0 z1 G: U# B) Y8 `) K  K

" P* C# m( V& v2 M代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
- d) M! S. N, _7 r{
& k& W& }' b  Q. V3 H    HKEY hKey;
  z( Z+ l/ A1 L$ w3 d0 A7 i2 B    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
/ q& v7 ^! [$ ^0 n    strKeyName += lpszAdapterName;
# o1 J* P4 f0 ~' t8 a) \    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- n, J% N3 a3 w' I+ c5 F& g                strKeyName.c_str(),
: V; s5 O/ h, f% g                0,
& s, a2 N8 L/ j. h7 ~6 f7 e                KEY_WRITE,) d& f  H* d3 s8 p! w1 P1 P, B# n
               &hKey) != ERROR_SUCCESS)7 m( @' o* Q" v
       return FALSE;
# s7 x- i: ~" Q9 I$ M; H    , D' D% Z" w! X0 b0 }$ j. J  ?
   char mszIPAddress[100];
( j" b6 [6 x8 K& w    char mszNetMask[100];6 H$ E+ K- d% K; b2 @' m" V  ^
   char mszNetGate[100];+ h( `$ }6 z5 l4 Q4 D

9 d+ V3 ^: ~( E9 R+ k: o    strncpy(mszIPAddress, pIPAddress, 98);
4 Q* D: ~: a* v% B0 D    strncpy(mszNetMask, pNetMask, 98);
, C$ x: `% f) w8 ]8 u% q    strncpy(mszNetGate, pNetGate, 98);0 E# Y+ C! J7 n/ d0 i
! _2 p3 Z# X% U6 C* d
   int nIP, nMask, nGate;% y' n: ^2 @* z2 `9 Q
2 a! h$ F5 M7 P, w/ T! n# c
   nIP = strlen(mszIPAddress);$ i0 _9 Z* \6 o" w7 Y1 m$ S
   nMask = strlen(mszNetMask);) f: A+ c' ^6 ^$ P8 d7 a
   nGate = strlen(mszNetGate);8 k# |/ Z% T' j: R+ q
, Y9 t0 t) I( I4 J0 f6 Y# q1 Y
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个08 ~) R: A" s" }4 i2 T- o8 ^0 E
   nIP += 2;9 w5 M( v1 r7 G) f3 z
6 d. Z" A' d  Z4 j
   *(mszNetMask + nMask + 1) = 0x00;7 B; M& B. k0 ^- Q8 I) M3 L
   nMask += 2;. V4 X- G8 d2 ^" i+ Y: j! Y% |2 U( r5 d

6 c& G. c" v2 _$ b8 Y- P+ Y" G9 c    *(mszNetGate + nGate + 1) = 0x00;& |0 t! A% X7 i/ C8 V. y
   nGate += 2;4 R! a2 z; L0 n
   % P3 }2 I! y7 _
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);8 ?* A% l  R2 e8 n7 N9 q0 w
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
( o' L  T6 R! w6 ?    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);6 n- [# a* x/ N! x. M) E2 _

+ _( n3 J: w# z  V. P    RegCloseKey(hKey);2 h4 k; l9 |# n/ N/ q
8 F: Q1 Q2 R( O
   return TRUE;3 X" K) W+ r5 H% B5 m
}
& n# v1 v9 |4 j
; A0 @1 w( V! q6 N三、调用DhcpNotifyConfigChange通知配置的改变
/ c5 G: Q% }% u
  t; t( D0 Q0 |; d8 g未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(' y' m1 z3 r  y
   LPWSTR lpwszServerName, // 本地机器为NULL
: a1 y' k6 a* x$ y8 `    LPWSTR lpwszAdapterName, // 适配器名称1 w& @5 ?% g  B+ o! v; b6 D
   BOOL bNewIpAddress, // TRUE表示更改IP
3 E+ z/ n* n7 I* P    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0  ?$ i% X0 g/ @" V1 v. @+ J
   DWORD dwIpAddress, // IP地址, Q* M2 F3 Y1 W: q
   DWORD dwSubNetMask, // 子网掩码
" P2 h/ o$ ?& [& d& V  y    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP0 R, p; C% Z* y( V
% y5 C' m$ ~& \; S6 l
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
, f& D5 u; O+ t{
4 P' |6 f2 P' d8 ]% A3 w2 [    BOOL            bResult = FALSE;; w0 _: S& x1 B6 X5 y7 R% @/ M
   HINSTANCE        hDhcpDll;, q' u+ z( ?9 R1 f* D; x
   DHCPNOTIFYPROC    pDhcpNotifyProc;6 T/ n- w( x! [7 S
   WCHAR wcAdapterName[256];
; g( d; x4 M9 @, d( `- d6 N! J    
( x" V% r$ g( E* }7 G$ c  f    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);/ }8 _. {$ g7 F) l' ]& J1 R* S
/ r+ H# y3 |6 z8 l% D" X
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)! m0 V7 O5 v/ {
       return FALSE;/ i6 P- A/ H$ X$ Z& U! n
) Z4 {7 o  K; M" N) C' R
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
0 d) }# O: A" X' D7 E8 d6 t        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
8 [1 s+ a1 r9 X            bResult = TRUE;
$ P4 v' R/ Y9 g" a" l: x9 \: z0 f4 R8 O5 A2 @& J
   FreeLibrary(hDhcpDll);) n. r8 {% f2 U: y- G# `
   return bResult;
, N2 g- |9 k, X}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-15 02:59 , Processed in 0.019125 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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