找回密码
 注册
搜索
查看: 4993|回复: 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地址的详细方法介绍如下:" c( {' i* f7 o
* [4 ]$ l6 C0 u1 ?6 e) k% B
一、获取适配器名称
( N, g) ^! f/ {( \- k2 ]* z) U' ]( |: T& x9 Y) V  V7 i8 l
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
3 y; b/ }' }! c4 r! L* U* c5 y7 Y1 P% I4 P
1.1 调用IP helper API取得适配器名称 4 B9 t8 |2 ~, g6 T$ ?5 I' `

  c- q% `: f8 SULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);1 T. a5 d: p3 g! \
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
  Y5 i9 b  B7 b# l% Rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
9 O# l5 e  j/ d! {3 b{5 z/ u7 U( Q/ N  Y( J! ?
   delete pAdapterInfo;" \6 J) z% f( x! q# D
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
* B: y, O& d' E, |    pAdapterInfoBkp = pAdapterInfo;
* E) C- z# R/ l}
5 Y" m1 j# M3 m; e0 rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )  X9 p8 d2 X- |; L8 K9 w
{
/ o5 k4 C6 i( g" h* b0 g1 D    do{ // 遍历所有适配器
# a) ~6 P+ w, d/ q        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口& x* h- a7 ~  Q! h( X
       {
+ Z& T" ~" w' _3 O2 l            // pAdapterInfo->Description 是适配器描述2 @% T8 ?+ P! {" a
           // pAdapterInfo->AdapterName 是适配器名称
" g3 {; y0 ?6 j! O$ b- R  ?        }* g7 B1 ^6 ]$ e' ?& @' }
       pAdapterInfo = pAdapterInfo->Next;
& C/ G2 Z( [7 c! S    }while(pAdapterInfo);( z2 U% N6 x! l  s
}$ x5 _! W3 m/ `2 G5 R" T
delete pAdapterInfoBkp;. Z4 s# s" Q4 B0 J
9 ~0 @) k" W) T
1.2 读取注册表取得适配器名称
2 W/ l/ `. b5 Q1 p6 P
2 T) }+ Y4 r& A& s# R2 N# o在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;; o( d# ]# I. ~% }) S* r
; p* z% P9 P- x" d) M. m3 [
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  D2 ~( ~" ~' [) r9 R
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",- G+ T2 o! g3 ]8 I; q
           0,
% y( S( q( O1 z* t% V- Q            KEY_READ,
% D! D; H' ~7 v& _( U* k* S! T            &hKey) != ERROR_SUCCESS)& Z8 i  m( O4 h4 M% s" H  k
   return FALSE;
% _: M# U, A7 J0 I2 A& E& z6 t3 @* q. T
DWORD dwIndex = 0;
/ H, H; D0 G+ VDWORD dwBufSize = 256;' q( D  p& e# O& |5 L) D2 O
DWORD dwDataType;  y. V8 p# u) m' [, c
char szSubKey[256];
( J0 `( A+ d/ c& c4 k" J2 q" b8 G/ |unsigned char szData[256];  l5 {4 m  [5 B( B9 b$ h! o

, I5 N( z( p6 N& Mwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)! r3 P# Z& v* J- e) X- y
{
1 G2 g9 e8 Q! B    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)1 _" I+ D& I( r
   {        9 ]% ?  v; h  U, @2 J* u1 N9 P3 j
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
5 Q0 z; b% G" c- y6 Q! i4 d- ]        {& @2 c' b; L& ~) ?: H, o
           dwBufSize = 256;
1 t4 M8 b3 ~) D  J5 {            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)1 h5 O9 r8 I* i0 B* Y
           {: @1 T, J7 A0 w
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
- Y" _: p, C0 J( k/ t% s                {. X; y5 s& F% I) ]2 F
                   dwBufSize = 256;- ?) c' L: |4 P. ^4 F
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)3 M- M: X/ L% h' v. K+ @2 v
                   {
$ x9 N1 }% s4 [% R; ~                        // szData 中便是适配器详细描述
9 M  ^" q, q# x6 K! r; D                        dwBufSize = 256;
4 [* ^/ I0 }1 E                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)" Q3 C, Q) u7 r5 w
                       {
# }+ s) a1 H1 L* i! {                            // szData 中便是适配器名称
  o7 R$ ]5 G1 F+ C, \5 P                        }
  F% W* C, O1 B( J. L' c                    }5 [: j; a; T# Q# V7 E" x# l. b
               }
4 N0 ]0 `& t$ s  C9 v8 _* t1 s            }- G% c5 h5 o) }
           RegCloseKey(hNdiIntKey);7 m3 ]* [7 e& E! y8 |' D5 w
       }
# W: N7 h# k. A8 u5 {9 d( N        RegCloseKey(hSubKey);/ x- Y5 k0 |2 I4 X+ h' v: L6 M
   }* ?* n% [: b" L, Z7 F+ R9 [. V2 W
5 V4 o# {4 H# j. r
   dwBufSize = 256;( [* H/ t: X9 A
}    /* end of while */
/ N. c; G. R- |" e/ m! k) l; o6 f5 }        
4 ]) M( g$ i5 |: N/ G, s1 V; O" @RegCloseKey(hKey);/ v" L( q& l) Y2 V7 b
二、将IP信息写入注册表* \4 D3 m/ X$ {( m

& L1 t8 ~6 \- h' |7 Y3 [( J代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
6 ]  m. f; w3 v$ R4 v6 Q{
; x7 D8 I6 C1 Q' e    HKEY hKey;
! S" Z" W4 L( b5 _9 c5 [    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";% h- Y0 Q& H9 `7 O# \2 Q" z
   strKeyName += lpszAdapterName;8 u2 }. g* B& m4 @
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
# A/ a2 @* U1 w$ g- f                strKeyName.c_str(),9 a5 C3 x# E: M  X" M$ ^/ p
               0,
. y4 |# b' R; T3 _# i% d# @                KEY_WRITE,
- G( e+ X0 H; Y% Q                &hKey) != ERROR_SUCCESS)4 [7 \, j) l0 @3 l
       return FALSE;' o. ~$ r6 u$ s  H% w; A8 M
   
: N6 \' c& u) }    char mszIPAddress[100];
) \7 O  }+ F# _9 {2 X" c6 i( d: `3 B    char mszNetMask[100];1 c1 f/ Z! F) Y9 @. T/ H
   char mszNetGate[100];
3 B6 K8 e. U% s8 b$ x2 o" E. I/ D0 Y. G4 m# l8 N" Z, q) [  k0 t
   strncpy(mszIPAddress, pIPAddress, 98);( L1 U) k6 j7 Y! x: o9 {
   strncpy(mszNetMask, pNetMask, 98);4 @: `& Z. D" h, _- C3 ]" i
   strncpy(mszNetGate, pNetGate, 98);1 K( f/ M8 c) [

( u1 C, p7 ]3 \! A4 u2 M9 n, M    int nIP, nMask, nGate;- y: e1 R) P6 I  k

& Y6 H; L& ~+ o8 d& ^- O# F* R5 y    nIP = strlen(mszIPAddress);
& F! I7 u4 T6 W' j7 }    nMask = strlen(mszNetMask);
2 M4 Q7 s1 S6 U& r( D% M    nGate = strlen(mszNetGate);
6 Y  E. Q! N9 a0 W2 {- `; N
8 H( @2 d- t! Y/ G    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
" w) l( c# `% O$ ?8 b% L    nIP += 2;8 b  i1 u1 J- ]) v1 \8 g; i1 O. @$ H; a
& [2 V$ x. V; b+ N# K) r4 z* l
   *(mszNetMask + nMask + 1) = 0x00;
1 E6 n! v/ u" x) M/ z& p7 B    nMask += 2;
0 R0 [# }& ?# S  `. R9 w
$ K: O8 i6 M& J( V; z$ B    *(mszNetGate + nGate + 1) = 0x00;
' c2 Z$ ?/ T. w4 }1 _6 P    nGate += 2;
" j" \. A: u9 E3 ^9 i, ^$ o0 F    3 P. B/ u1 {/ e- N* D
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
" `5 o0 [& ~3 p7 r4 L$ }    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);) l- D1 h$ f9 f; \5 w5 ^! x
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);, P4 ]. x0 V% j; k
  B* [$ m, |  J6 U
   RegCloseKey(hKey);
, {% B  b3 ^' I1 f
) n7 E0 A* V# a# q# n  W* [    return TRUE;
- a# h8 t6 g! g% V+ Z+ j}9 Y$ \; d7 E# o. H$ T
7 l6 n: T6 K  O
三、调用DhcpNotifyConfigChange通知配置的改变
# ^5 n6 l- ^& j% f& Z0 s' i: b5 j+ k3 G: M
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange($ v+ G# e2 L$ `- x  R2 k# U
   LPWSTR lpwszServerName, // 本地机器为NULL2 c/ V! s) e6 \1 ]+ @; d* f
   LPWSTR lpwszAdapterName, // 适配器名称9 O) K" @% z: T. z7 w% g4 e
   BOOL bNewIpAddress, // TRUE表示更改IP
; w- j3 J; b: m    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0" B3 A/ A) w  `0 H5 \. p  Q
   DWORD dwIpAddress, // IP地址0 X, m; V0 ?+ @: s) o. Z
   DWORD dwSubNetMask, // 子网掩码
/ A' k# `8 G3 O- i" d    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP6 o7 B" x) ?8 x

8 a, I9 }7 ~7 Y8 b0 X+ b( m具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
. x3 _& t1 Q9 S5 `) s4 C) Q{
- W5 y2 j8 g2 a, Q    BOOL            bResult = FALSE;
  F' u8 H% c8 s    HINSTANCE        hDhcpDll;' _( l9 h. W1 M3 M# c
   DHCPNOTIFYPROC    pDhcpNotifyProc;
" y, v! M/ k# H5 d  d* {% K- g    WCHAR wcAdapterName[256];
" W$ K* b& y* \    % _! x+ m( i" _) j8 F, j/ S0 [8 D! M3 `
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
% [, @$ X& L) M4 V8 G) a
$ I+ R4 n' |( ~' y+ f* u    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
) t1 Y7 g5 ]7 F8 f3 A1 ?        return FALSE;
6 Q2 l( {8 I$ A! t/ ]' R& C4 C$ e. ^3 t$ I4 |: g0 s' M
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
* l+ F2 Z( l$ ]0 c( N7 p# ]6 s! e        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)3 K) W3 L) j" p' z1 F! G- t7 d
           bResult = TRUE;6 K2 x* x- R% w

' U8 n3 _9 U* j2 _$ q    FreeLibrary(hDhcpDll);
/ V( n  n$ @) c1 G& e' a6 ^1 O    return bResult;
3 O2 ?# T7 Y- x}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-18 11:01 , Processed in 0.017508 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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