|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
- J, t0 j; {0 l. t f! `% {
+ N3 @! r; W* @7 o/ t: j一、获取适配器名称
: V* \/ F/ s. B4 {1 a; t% A% |' I8 ]) U3 V0 ^
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:$ o4 h z' a/ r1 h) u5 x
+ T7 |3 J7 Z' c5 \& }% N1.1 调用IP helper API取得适配器名称 4 _, Q2 v- j( ^+ A
: E/ I: R1 m( m8 |
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
, ` {: p9 s- pIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
* E+ p% `/ `" e0 I% Q! kif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大 C: I) X, b; ^( ~ k7 c
{) d Y. K) X. M( d4 q
delete pAdapterInfo;3 _4 _9 @5 b2 V
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
) r) w9 U9 g- M+ J6 d, P5 r pAdapterInfoBkp = pAdapterInfo;3 M$ O: c) j6 J; K
}; Y* F$ I2 o; h- P
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
y( g* y3 [3 E5 U( [* b{+ z1 R& g, J7 x5 s3 }0 k3 L
do{ // 遍历所有适配器. I# f4 O7 O/ z
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
9 b0 _0 s+ L6 r" V! \9 l& m {
3 V( J4 r5 T4 m. ] D // pAdapterInfo->Description 是适配器描述
2 T! ~' l, o+ K0 x: g. _) Z // pAdapterInfo->AdapterName 是适配器名称
) G& l5 @5 p( u: @# \ }
3 j$ R6 a1 ]8 m' A pAdapterInfo = pAdapterInfo->Next;
8 o3 o. N5 ]& e8 C# i }while(pAdapterInfo);+ N' K" p& a) r2 E* x) ^5 k3 z- A
}
: ^0 y: f- M+ i# T. a* [delete pAdapterInfoBkp;. |/ T" Y5 M' r7 x* U
" Z- O$ ~$ }$ ]3 o5 b
1.2 读取注册表取得适配器名称2 q& x9 J& P4 X0 E5 w4 B& r7 P& s6 o
! D9 h" }4 L5 S
在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;( `- x1 f3 @, N$ R
5 z$ k( x" R* L! Y
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,( I q7 G5 n# Q1 `. n+ q
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
+ n$ {+ y, c! ]4 e j) F c 0,: M1 T" y, e/ s- T
KEY_READ,9 M9 G4 m+ v) s8 d v) }, D5 p
&hKey) != ERROR_SUCCESS)7 Q& X! u: {0 h3 a& m' f
return FALSE;5 I& S+ S w5 V7 a) i: w
7 d0 L4 n- h1 \- @# M/ Q
DWORD dwIndex = 0;7 c/ S- ` N4 m5 |
DWORD dwBufSize = 256;
, q! C/ J' Q: I# D$ A( G5 g- Y7 nDWORD dwDataType;
" `5 ?4 r6 R" F X$ c/ `char szSubKey[256];* p. c4 p( S. |8 F: D7 x
unsigned char szData[256];1 c$ z3 l; M0 m) }# R/ p
; _! x! e9 y. q0 d
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+ r6 J8 A1 M+ w5 n{2 ]( [. J$ M0 X! X y$ `
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS) E8 j* [- `1 ^! W/ B* Y2 b
{
7 Y4 i* b+ V6 s if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)4 ?2 m: n R/ F( X/ d7 x/ S
{
( t. _- g7 w" u+ v V! O9 ?; { dwBufSize = 256;
& W7 k" i% ^0 X, f if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
( A1 c& {% O0 a, c3 y {
, H! Y+ Q" R. S- b0 s) F if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡( A: m K5 t g' u
{
5 n6 H- S2 l M# s" p3 S dwBufSize = 256;
6 x4 m5 b! D2 ^, \ if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! `/ ]( M, H h0 X
{3 M' F( T8 p9 a! }9 X* l
// szData 中便是适配器详细描述6 k- C* B4 |# k$ k4 R( R; U
dwBufSize = 256;
4 x( b( V' c1 ?! s- V if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
/ Q5 Y- s+ Q3 r/ o. l, p {& C a( t" j! x, h
// szData 中便是适配器名称 y" }5 q8 ~8 S; X, `
}- a" J: y4 `1 f" r9 X4 B
}' Q4 w M9 s& S' q
}
+ u3 s) w' W4 ~5 N! l7 r8 a+ M }2 h2 }7 [) j. T/ z& t
RegCloseKey(hNdiIntKey);
; L2 A0 W Z: P }' l( O P9 o0 n
RegCloseKey(hSubKey);1 e+ x- Y% Z, G/ E: v$ S
}4 g( n. Y, t8 K% ?% r+ U: z- n' J
- w% {9 u, s# U! i# K* d dwBufSize = 256;0 d' x3 d1 J' w
} /* end of while */
0 }/ |* M8 f& D# s% A% p/ s" _
4 I5 p7 p7 m, H! a9 F9 CRegCloseKey(hKey);
! k( D5 |. [3 B$ ~二、将IP信息写入注册表8 L/ V2 f2 O I7 a1 X o
v! r: E j' ?# I代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
, y* M; S6 a8 h/ F& B; A{8 H& O1 L! ?0 A, w3 j# m! O; X+ S
HKEY hKey;
; ~+ t1 k! F7 R7 F5 Z string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
+ ?9 e& i2 D) _" L- M% ~( h3 S strKeyName += lpszAdapterName;
2 y6 M3 _7 N' ^5 a: e if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
" P* z; z# T: b% A7 P" X strKeyName.c_str(),
3 e2 F0 X! m, f; J4 ^3 w7 M3 p/ ?- b 0,7 R; b4 |. j; J5 I# }
KEY_WRITE, E: @. K0 Z+ f# m9 a
&hKey) != ERROR_SUCCESS)
& [- w3 X) W; O- h. H return FALSE;
7 y3 i$ \& T( H4 l4 m 8 x7 x9 X$ N2 v
char mszIPAddress[100];+ Q0 ]/ k9 {; j$ g
char mszNetMask[100];
* y; b, a- Q" I3 x. l5 w7 g% M char mszNetGate[100];
7 t; q" ~) ~* p; ?: @" }3 [* `
' H0 t4 W2 l5 D# q# j1 l strncpy(mszIPAddress, pIPAddress, 98); U" t/ ] _8 b* ?9 V9 u( m
strncpy(mszNetMask, pNetMask, 98);
, w6 Z! `. v$ y5 w strncpy(mszNetGate, pNetGate, 98);
7 ?. r w5 H, j& M7 C* o
( e5 e, o8 n/ I# e int nIP, nMask, nGate;
+ a( r$ f- G( c& G! P
9 k8 E2 \) e6 N. |: S( R; o7 g nIP = strlen(mszIPAddress);- _: e6 {0 p% S5 J
nMask = strlen(mszNetMask);$ |2 b3 l( j, P7 w. {
nGate = strlen(mszNetGate);
- `- q) L. R p! {
0 q; F6 _( _: n, ~8 O5 B; k4 X *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个08 ^ T6 z4 l: M/ E, }6 M' w
nIP += 2;- u5 d |2 n% u: b$ f0 n
. e( P( p8 D, P6 f. h, q
*(mszNetMask + nMask + 1) = 0x00;, @- M7 V) c& j9 ~. B1 Y- n, H
nMask += 2;( t+ r5 V9 y0 u1 G9 ]# P/ f
& G! v* i5 k5 \7 \! J/ c *(mszNetGate + nGate + 1) = 0x00;4 c \ ]1 p: h# x5 g
nGate += 2;
0 `- Q2 z# n6 `; P. c& o+ G
; w' Q1 Z( N* h7 R% w; K' {& a RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);# J) j+ O& R" F1 w1 q x7 U" A: S
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
4 E! ^' C, m. ^- f: K' j' L( X RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
& ]! }, Q) p9 M' i; g$ D' U
2 h2 S( O3 ?% O) D) A4 Q. W/ X, h" f RegCloseKey(hKey);( e; j# ]- G- V! u
. l9 V$ u' O- w* ?0 I return TRUE;; N5 X) F5 E. B, ]+ d
}$ L7 d0 I1 a* k, Q: p
# p. u+ t1 Q% _: R! P9 M1 j三、调用DhcpNotifyConfigChange通知配置的改变
! Y, l; \) C# b N) v! G! L9 i5 J" ~+ p" M. }# P/ n# E8 u2 Z
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
, [( ^2 h/ d5 D x& b LPWSTR lpwszServerName, // 本地机器为NULL
2 `- _" G7 a9 w$ _% P LPWSTR lpwszAdapterName, // 适配器名称0 Z3 B$ Y/ @7 C9 u
BOOL bNewIpAddress, // TRUE表示更改IP
- m2 H$ K1 i+ C& `$ l1 ~ DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0+ p& Y9 {/ W! X C* x' Q4 i7 ]- d5 |4 Y
DWORD dwIpAddress, // IP地址
( O+ t# H1 {6 _* g3 {! b: ]+ T( k DWORD dwSubNetMask, // 子网掩码0 W3 |7 T; F" z7 ~& C. C
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
0 s- b5 q; Q* H7 }- J- R: }- H/ ~! j
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
; q- U9 ?6 }% M- `( ~/ S* F4 z7 h{6 W' S; T5 E7 Y$ M
BOOL bResult = FALSE;" t" [' s6 ~# X9 d4 v
HINSTANCE hDhcpDll;
1 ? Z7 H# N2 s; ]4 j% I+ R- _5 x DHCPNOTIFYPROC pDhcpNotifyProc;
" ]" O E' |( l u0 S" P WCHAR wcAdapterName[256];, E* j( i* P9 ^! W
2 }1 a, C- y$ T* j5 r6 c
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);" s: d* I* ^8 L4 F1 J2 w9 f5 y
) O$ C( D a! [( z+ M if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)1 n4 O9 z4 A; Y" \0 h
return FALSE;' a! X4 m6 J. I1 v8 ]; ]
9 `) l* L# c6 [ K
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)& l, O/ Z- k' s' @0 @7 x
if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
( z9 v' l" a2 z8 U& h bResult = TRUE;& g9 ^/ h; ] b! @1 t
% k3 ]9 J) b1 f# ?$ N FreeLibrary(hDhcpDll);
3 K7 ~' S0 j3 j6 X1 T" H return bResult;
. z/ V8 o p3 R/ B7 y} |
|