找回密码
 注册
搜索
查看: 4628|回复: 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地址的详细方法介绍如下:1 I2 [0 E6 [) c" A& H0 x
  s- V* Q8 ^: @' a' X5 f
一、获取适配器名称
# t& x2 o- i4 \/ H/ y/ `7 t: k; e( `  u
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:7 S: G0 z/ ]' A

& Z% P1 ?# f1 S$ I1.1 调用IP helper API取得适配器名称
* K0 m8 c* c+ }2 j, L/ p1 m/ n+ J# z4 l) J- X- Z& O4 J: h
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
% Y. }) R0 s" ]7 F5 C* |4 zIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
' }/ F  k9 g" k" e. rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大6 U& A8 J3 O( S4 d
{
4 f2 w/ L( J4 }, ?/ y    delete pAdapterInfo;( X. B+ M* ]& W/ H* [
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
4 [' K. a9 g- p) |5 j" M9 L: o    pAdapterInfoBkp = pAdapterInfo;' i  U8 }3 a* a- w' m
}
2 B+ R8 r( @$ r' _" Qif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )6 _, Q( v% g) u" {
{! {) X  C; L* d9 p% E' i
   do{ // 遍历所有适配器! j8 `- k0 m  M
       if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口$ w: y+ }8 A$ b. h
       {; U8 }: z/ |  a
           // pAdapterInfo->Description 是适配器描述2 s. F+ Y% L! T4 c2 r
           // pAdapterInfo->AdapterName 是适配器名称
' T+ V3 b, D8 j* u4 c$ y; m2 I        }
  u9 J" c: @( e$ Q3 X        pAdapterInfo = pAdapterInfo->Next;0 B5 D, |9 y  m; ^9 j5 w/ |3 E  u
   }while(pAdapterInfo);
! Y+ C7 G7 w4 ^# R0 W; `}
* H; T+ t! C* {$ W6 z! q  Cdelete pAdapterInfoBkp;+ |' [! s/ c# {; R$ l* O. ]8 l
0 x5 B  G' P9 L( V" W7 l* G! O
1.2 读取注册表取得适配器名称& a8 t# i8 x  b

: h) t; P5 X* ~# {) r' E在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;9 |: H+ V5 y, c" z9 s$ G! [0 Y* w

/ I8 d: w" i) Aif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 p, P% V9 Z$ U2 }2 S7 B  ~. M            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",' h6 W- W7 ?# C: q) q. c; @( ?
           0,
  s, i3 X' `4 u$ W' o% I, q1 U            KEY_READ,
- q  H+ s# }" L; N, v# [            &hKey) != ERROR_SUCCESS)
; N8 L* c1 e5 |  j9 W    return FALSE;
* n1 m) v. G" {4 \! P$ z2 @1 |0 l8 A2 q( s! ^# w
DWORD dwIndex = 0;* s* @) |- d# e, o: u7 |
DWORD dwBufSize = 256;
" v8 d% V' p: F6 B) }+ F4 Z3 a' FDWORD dwDataType;
% ~6 X" {, |2 V7 _0 Zchar szSubKey[256];
8 s) t" ?* m% Bunsigned char szData[256];9 D$ x6 p& n! t3 G
( ^+ W+ X) C) m, V
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
; ^1 r, ~* z3 U- X4 ^# v{
9 s# o, C' {6 X0 u, o    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
6 S& b% c- d- |7 H    {        
$ t% m% ]! n; ^4 F4 U$ M0 c. C        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS); S2 B8 T$ K7 {; g
       {; O- i! [* ]! N
           dwBufSize = 256;
+ ~0 a+ a1 @8 S1 P. Q            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS). y! t, _+ p2 P6 b
           {) b) l( Y/ q$ _* J) ^$ D' S
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
4 @7 G% w, H3 e+ m& p( J6 q! x                {7 G$ R3 @8 c0 ?% F$ y3 W3 |. v
                   dwBufSize = 256;, [! f+ b0 ]" x0 M
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)$ H" O7 U9 H. O8 q4 ^) g0 u& ^
                   {$ K. q. {. m; o3 E9 f3 ?) a
                       // szData 中便是适配器详细描述
$ K  C/ I( R; I* ^6 e                        dwBufSize = 256;
' G- Q5 I% L/ {0 |. f                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
' \7 l* }5 a) N; y$ x                        {4 D9 C' j" r' W* v) |/ h* J
                           // szData 中便是适配器名称
7 B1 K  S& @# _  D) P, L0 t8 s/ }7 G                        }2 a; S% g( R/ k# j6 h
                   }7 M" g' ^( c3 t; P$ B# g- w9 ^
               }
8 f8 G/ H/ L* C( N2 r3 d, ]' p            }
# k7 G6 M6 g0 X8 c/ H4 P3 T+ b8 E            RegCloseKey(hNdiIntKey);- h( W4 {6 T* J: V; \
       }% H7 j5 {6 B% G5 R# g$ {# }
       RegCloseKey(hSubKey);
: G+ q- e; i$ J* k/ k8 G+ @1 Q& z    }
5 n, |0 }: u$ F; M" F) I1 j: Z+ @0 |5 |3 h
   dwBufSize = 256;
; v# E0 ]! y. k1 r9 _}    /* end of while */
: g3 D( B; x! E3 Q* [- ^  T3 @* Z        
" i9 H) T6 {/ U0 w* BRegCloseKey(hKey);. N& r, ~% C; k) P- _. J6 w
二、将IP信息写入注册表# l0 V. \, P( K/ o8 p2 E

' y2 y9 N" b9 f! W, f) i/ C代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
, w5 ?& ?' X5 L8 v{5 f/ N6 y& w& I) A* M  _
   HKEY hKey;
3 Q, }0 f! V. H  J3 m# I- s    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  P9 n# P' h/ J# I( l- I- z    strKeyName += lpszAdapterName;' w1 B4 R2 Z8 F3 z; x  n3 ?' [
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,! Z- W1 G3 d5 Z1 a
               strKeyName.c_str(),
& c0 l1 o4 d8 z                0,
- C3 d5 e- m, P; x                KEY_WRITE,3 l6 C# [! q+ U
               &hKey) != ERROR_SUCCESS)- N) n  k; y- u7 H% S& e) W% E
       return FALSE;
5 [* b4 ?! y4 s+ l4 }, \  R    9 E9 }% C" O+ p3 i
   char mszIPAddress[100];
6 N: \! a8 n0 e  }- k    char mszNetMask[100];
; S# n' z' ^7 q' M0 X; c    char mszNetGate[100];* l- h+ N- o# r% v

" c" q6 U" B! ~( P8 z. Y    strncpy(mszIPAddress, pIPAddress, 98);, _5 v7 j3 ?+ T3 W2 H
   strncpy(mszNetMask, pNetMask, 98);& p) K3 _/ U) x, u
   strncpy(mszNetGate, pNetGate, 98);
, y5 B) @* E4 m  @" o/ U3 p0 X# i
5 B! ^4 E0 x9 }9 O" u    int nIP, nMask, nGate;
, f$ N; c6 J% s* G5 o5 H; Z, j8 k- s' |0 o3 g: w; y# L
   nIP = strlen(mszIPAddress);& Q  x# S  {6 b. @+ K0 s- Z
   nMask = strlen(mszNetMask);
1 O7 l6 V9 y, t6 C  z+ B    nGate = strlen(mszNetGate);. }/ U+ r$ h# s! v3 M
/ d  F' ^/ G  d2 N
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个07 B5 y. Q$ k. d, ^
   nIP += 2;
+ R  U1 B8 I/ c+ M
- k7 [0 S: B' X1 ^+ @  t    *(mszNetMask + nMask + 1) = 0x00;
3 N" u# \2 G6 r    nMask += 2;3 N1 y2 x3 h/ q6 v: N  B2 D0 x
' a& g" C  q1 {( T1 `$ X0 D1 ], m
   *(mszNetGate + nGate + 1) = 0x00;6 o% ^% F: U7 a* \% q1 U
   nGate += 2;
+ h3 s: D3 [! C8 C& |5 o* ?    
  \9 ?/ Q* r% f/ O: K) d1 p8 L' k    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
( s$ q! d! d9 f1 K4 m    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);* \$ r- z8 f7 }$ M# ^
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);. Z* Z2 @5 D) n, h( q

2 a+ @/ c' i- n0 P0 Y' \    RegCloseKey(hKey);
% _0 x0 C: {% V! k; [- K4 X' V1 Q8 \" z
   return TRUE;
& ?$ f# x/ }) j}
( e* R4 c7 e" w0 R2 Y, X; S# L! ~
  q% d5 s, H& E, N  L' `& C三、调用DhcpNotifyConfigChange通知配置的改变' `. R( z+ t2 R2 U1 D0 H

0 Q8 L& w) l9 O" y  U2 I( S未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
- @5 [. @8 f0 \9 x# V) a    LPWSTR lpwszServerName, // 本地机器为NULL
) k, V8 N2 n0 j) C& j: H    LPWSTR lpwszAdapterName, // 适配器名称
" v) X8 @  a: H% ]6 K5 m& k' b; Z    BOOL bNewIpAddress, // TRUE表示更改IP$ N- |( M* q+ h  f( o2 ^
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为09 ~$ L, q, a8 ]4 Z: \# E8 S
   DWORD dwIpAddress, // IP地址, s& A4 w+ r, v+ T4 _% d
   DWORD dwSubNetMask, // 子网掩码' P4 M4 z5 \7 x& w  A' f
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
$ [) B  \5 M/ D6 m  G+ X) b3 o9 j1 N. _  ~
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
2 u3 }, _/ |/ s1 p& G* M) G, X% Q% h{
  e' m& x  C5 n    BOOL            bResult = FALSE;- j; ^& U8 y0 |8 }) y, D! }8 _
   HINSTANCE        hDhcpDll;. Y7 [5 U/ {+ p" y2 h
   DHCPNOTIFYPROC    pDhcpNotifyProc;% {5 A( Y+ F( Z) s! G2 ~4 v
   WCHAR wcAdapterName[256];$ K& K. Q' z; e) v! ?% ?  L1 P( D
   7 \! i& c7 R1 x9 n: ]
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
# R: {6 L% J2 c8 k* T3 h+ y; P
! a+ `! S. ?4 J& K$ M5 \    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)( ]9 w7 P) `+ ]6 ?& ~" w) `
       return FALSE;4 q6 d& ^6 [& q! O) p
; p" ^+ D2 @" l+ k! _
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
; G7 M4 w' T7 v7 H& H. e5 q        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)7 P6 l! O% I( f" e) U0 E
           bResult = TRUE;! o- [6 c  @" t

$ R& c: N- G  M, T, G0 C    FreeLibrary(hDhcpDll);0 q$ t* z* V2 m1 s4 ?- D# k
   return bResult;
; f+ `7 H+ R7 j8 H}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-9 07:10 , Processed in 0.034266 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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