找回密码
 注册
搜索
查看: 4934|回复: 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地址的详细方法介绍如下:* o' ^" u+ f, R) R$ A8 t
/ t/ E) R3 c/ Q" r' [4 Z, u3 d
一、获取适配器名称1 z( b2 y* A' @2 x. q! L9 f  i2 E

+ H, I8 k6 R! v2 K% p# ?这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:* c  S7 E1 y5 Z7 P6 [

- I* k+ C2 I; Y: X% Z1.1 调用IP helper API取得适配器名称
" f2 |& J9 E7 q) X9 D3 v: F) E5 x2 O$ y2 {6 ~) i
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
4 Q2 |/ L9 L; G; C2 a, YIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];- z2 \( @# a7 |/ z  |7 u" ~
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
$ ?  l1 W6 |2 h7 u$ |7 p8 e{
4 I. \5 b& ?- O" z! R    delete pAdapterInfo;
! A# f: B& j" I3 q* E    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];6 @+ v- a8 f* |0 H5 L9 C4 g8 s
   pAdapterInfoBkp = pAdapterInfo;' c( w2 g0 Z1 D3 {( D5 r7 Q8 `$ p
}
7 B/ C" w; F7 W( M: I! Nif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )$ H4 I) d9 s$ N
{
' Y+ E- O0 ~2 E& b5 h# I8 H, u    do{ // 遍历所有适配器
: X# a' \+ F3 \' K8 v4 J        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
* f4 c- v, J& T/ p# b4 J' m; [! i        {
  w) {8 w) C: e" M            // pAdapterInfo->Description 是适配器描述. R& i; H2 `9 G# t
           // pAdapterInfo->AdapterName 是适配器名称8 z, l' X1 W* |
       }' k1 ?- V7 c0 h$ b; A! m
       pAdapterInfo = pAdapterInfo->Next;6 V$ v* a, B# U/ Z) p
   }while(pAdapterInfo);
4 l; s" J# }6 ~0 Q* o}
6 Q, c/ M; C) K& K. rdelete pAdapterInfoBkp;6 v& B: y( z4 l  h

0 {9 w: F$ d) ~; d& e( u+ |5 J1.2 读取注册表取得适配器名称$ t; r7 b; [" Z! L

% `1 Z! h# c, l) `3 ?5 j在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! M4 S: f- y& K
# Q3 G$ x, w" m4 h( C
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,, b# i' o7 u6 {# k
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",7 v+ T. I: z0 _5 F
           0,
3 r- R9 c- }5 H5 _% v4 v* [            KEY_READ,
1 L7 I+ U! j! y1 O" H; T            &hKey) != ERROR_SUCCESS)& r; D  D9 v+ f" f
   return FALSE;
0 ?, z' l1 J, i8 c
$ _5 Z9 ~6 I8 L1 @DWORD dwIndex = 0;0 `! l: M1 v- z$ P9 `
DWORD dwBufSize = 256;
6 J3 _+ O7 B! A$ wDWORD dwDataType;
8 @3 Z) y9 x) @1 i$ m) j2 \. schar szSubKey[256];
9 b5 [0 L0 c' gunsigned char szData[256];
$ j9 ?0 A- i( W. H+ S4 @+ W) A! A1 U% p% S( w  I2 X
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
9 i$ X4 |6 D2 P9 H$ F{
) m* P  @9 d# a2 I    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
* q* d: X$ q! f    {        4 S7 X) M. @* L3 G0 [
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
$ M2 w. g* @$ A/ c# s- l$ T        {
6 v: Z1 r" ^- Z8 P$ w) v            dwBufSize = 256;  s: T$ g( y' M/ [; U+ i  x
           if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
! l1 S9 D0 E5 V% M9 _9 u6 n            {) s( U( Z' }# q
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
2 }7 Q( z( T$ S4 ^0 q                {. N. Y! V; h( G
                   dwBufSize = 256;+ N( E+ z; \; M' v5 T$ h& ^
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! V3 ?& P+ H  L+ S& w& }# w
                   {
. f7 Q8 @; n( h                        // szData 中便是适配器详细描述5 h; M8 `6 c, `- ]5 J+ c9 f% f
                       dwBufSize = 256;
: g9 X. ^& j0 b, _                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)3 H. V1 [/ U/ @/ D- M
                       {
, c" y& d% p1 k" |) w* D                            // szData 中便是适配器名称& N! U! u* S' V6 W! j* z/ q7 u* `
                       }1 x5 e  [4 l  B
                   }5 x  ]! Z$ i- M3 {  s  D1 k
               }) [6 A1 w; {7 C9 L+ e: @5 C9 J
           }# d$ y5 e3 b" R
           RegCloseKey(hNdiIntKey);
1 Y  U5 ~" D) @6 ?        }
' z8 s. d" R, a& S" e        RegCloseKey(hSubKey);$ l! m2 r- J# o- ~( I1 P3 Y: K
   }
  v: p% y- n) S1 O3 D8 G+ A0 k) a6 J8 t
   dwBufSize = 256;4 P6 T' u7 ~. M$ h6 {+ {3 G
}    /* end of while */
5 d9 f: @2 E, f$ h        
+ p1 \# {6 G5 X$ G) b* J7 ~0 [4 t& gRegCloseKey(hKey);
3 O! J  x- N& R9 \, ]二、将IP信息写入注册表
. m1 N$ }  w9 k5 A7 g; f1 W, U. s% M$ {0 v# f* P7 o9 P1 b- N0 k
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)% V) d2 [5 Q+ m
{
; m: C4 b. i( S6 j    HKEY hKey;
3 ]# B9 M4 d& w" z) ^( j    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";) f  `* @4 `9 j; [- u
   strKeyName += lpszAdapterName;
6 N$ q; t6 ~/ R& `( ]/ ^( y    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 ^, i& t) O- C* E
               strKeyName.c_str(),
: z9 D( v- Y0 _( g% `# e4 p& P; Y                0,+ V$ S5 R" h* v- i1 A1 |% {( \! C
               KEY_WRITE,
- Y  b! k4 J3 \) W: Z5 t                &hKey) != ERROR_SUCCESS)
; N& q  \% \  z( B1 t5 d        return FALSE;
) G7 ]* F0 o% ]8 k3 a& [+ ]    
4 f/ K- O- P1 T, D; a    char mszIPAddress[100];
& L/ C' A1 m* c: _    char mszNetMask[100];
* e7 S- ]* G7 g, p" L6 l' J5 @    char mszNetGate[100];% q8 j4 c4 `; k' d# O
3 {' F  u. f0 [) Y1 f
   strncpy(mszIPAddress, pIPAddress, 98);. K: g$ U: {' r6 v0 X: P& d; F* i4 A
   strncpy(mszNetMask, pNetMask, 98);
; w! P, }9 Y: d" `' C; `- c& t7 [    strncpy(mszNetGate, pNetGate, 98);
/ z' ~+ p' Y8 w& e1 j$ F
1 S9 ~7 J% \# Z, [* B; M    int nIP, nMask, nGate;
8 Y$ k0 f6 B! L+ y: `' b+ L& ?' O, `; q, ^9 N& x) N
   nIP = strlen(mszIPAddress);
* N7 k8 C4 w: c2 t+ P0 m    nMask = strlen(mszNetMask);
5 O3 E9 {% o' C4 b7 n8 q3 {    nGate = strlen(mszNetGate);
$ ]" _4 f; R5 |  V2 G. Q) P7 K4 A$ X) M" F8 @
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
7 `& q7 ?. n. A    nIP += 2;
- C8 l% Q" r6 u, Q9 t* G: q6 e
" u; Q4 z& P0 G- U    *(mszNetMask + nMask + 1) = 0x00;, `4 u) X2 G# Z# w! u
   nMask += 2;
4 n: n! l2 [4 V' |3 Q* F8 h4 y5 t1 n* W* v; y- _( g% B4 b
   *(mszNetGate + nGate + 1) = 0x00;* d) m3 u  j' H2 M
   nGate += 2;# c1 y9 P8 u" j, \! R1 I  E8 U
   
" a6 p  l3 u* }6 a4 n    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
6 M8 U1 v# C7 k" s    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
; A8 q$ U( j! f3 {& U1 ]- L: T. ^    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);$ ]. c  K/ G) g/ `) D

3 B5 H4 {6 T4 M4 S    RegCloseKey(hKey);
9 w1 t" J! ?' W7 a$ ]* H3 N3 _8 _0 ^% L  t% K
   return TRUE;- F9 z* E+ k7 r9 A% Q+ \
}
) \$ N6 ~/ t9 w# D' M1 i
& `& C# T( w$ I: S. V三、调用DhcpNotifyConfigChange通知配置的改变
$ \1 }, s& k# X% n* H$ X  |% G3 N9 E' m! e0 p
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
0 w# u6 |8 M- k" z    LPWSTR lpwszServerName, // 本地机器为NULL5 r, ?% |! T, w7 b/ W" J; `
   LPWSTR lpwszAdapterName, // 适配器名称
6 `4 }8 k+ c/ r    BOOL bNewIpAddress, // TRUE表示更改IP6 r( S! D* d% c7 p/ C) j
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
: J: C) D6 h, n- y( E- O    DWORD dwIpAddress, // IP地址5 ^& M% g6 n; ^
   DWORD dwSubNetMask, // 子网掩码
  W1 P* r9 s: R2 _5 S    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
8 u; Q+ }5 X; O7 e% d% N
' h/ G! [4 r$ ^8 o. K2 s! Y" i具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)4 S( ^* x" W% L) e2 i  O$ D" S
{
5 x% s( X$ u, k/ M% M    BOOL            bResult = FALSE;
8 \9 O1 d5 `2 b6 h) |    HINSTANCE        hDhcpDll;
3 @$ U: }9 u- V6 w! n6 n( K    DHCPNOTIFYPROC    pDhcpNotifyProc;
5 E* U4 d# [; H" v) @& j    WCHAR wcAdapterName[256];1 i! H7 `- f' \
   
$ ^) ^3 l1 s4 v. g" @2 q    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);. L3 G( e8 D2 [$ V

/ ^. M$ z0 g& a  i2 V. G    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
. ]# P! S" _" m% f" X0 D" c  a        return FALSE;
8 y0 y. u( H- m0 t( b0 X' a& D+ |0 }2 M0 A( O2 ~+ C' u
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
% w, V) @7 u1 {! Q3 Y        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
, Y* l* F/ e5 B2 x+ X            bResult = TRUE;# ^8 Z  P# h# g: s) e
: V; V6 @4 Y& j  n
   FreeLibrary(hDhcpDll);, z" }0 {  p  ?* b7 \. J* M; s
   return bResult;& p6 z5 ~# Y7 u4 }. X
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 10:34 , Processed in 0.019857 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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