|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:2 m2 \6 W8 ~0 @4 l/ n$ l6 d: ^: `0 v
! G+ n2 G+ A, @) j8 U, Q3 d& y+ H一、获取适配器名称# [1 x# A7 L4 I8 o# h- w
/ z5 _: A, a" z) w. {
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
$ ^+ ?1 X y" H& Q* [8 K
# n* T3 y# [5 P9 e( ^& z) [1.1 调用IP helper API取得适配器名称 & Z. e1 v) d9 k0 ^6 B9 U
; U: u- s# S* ~; e9 Q4 X
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
+ ~+ m2 t& m8 G9 F/ ZIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
- C: M9 `! n( B: }if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大% i5 D0 k8 [: o( ?
{( |- u0 W1 A3 ^7 c5 {/ g8 @" x& }
delete pAdapterInfo;$ P' h! U& B, Q' y. ~
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];4 x% N2 S! T! }2 q: x3 F
pAdapterInfoBkp = pAdapterInfo;
6 D! j+ u2 ]+ y$ ?" R! @) P}
1 q3 G0 u0 U9 ?& x+ rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
& n. e$ [+ W) f& B# r) `' ]. q{
! ~1 k/ p$ X* q" j/ J! n0 J) I# B do{ // 遍历所有适配器# F. s! Y$ l! B) k C7 j0 u$ u1 J
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口3 j8 A- R( J7 y0 o% N
{ ~6 y4 E' Z( Y6 D
// pAdapterInfo->Description 是适配器描述
' S- o1 B! D8 t3 L2 m' J1 N // pAdapterInfo->AdapterName 是适配器名称$ i+ X& l0 K: {/ D* y$ ~! B; A
}
2 D. }! ?& A; l1 p8 _# o( i pAdapterInfo = pAdapterInfo->Next;
3 ^6 ~: y% t( x0 P) \0 _; ?6 u. S }while(pAdapterInfo);; X" r9 P" m: l
}
! [6 A# W( P/ k) B5 y( ddelete pAdapterInfoBkp;# A- X( j% h$ G/ C0 v* p
; z/ Y/ q# |6 Y7 W! E1.2 读取注册表取得适配器名称& ?9 G; C( L4 A1 h( H7 D; Y
: V7 ~8 X% M- \) u& F在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;
8 L0 k5 R- _/ U: r( x
% O' U6 `7 q; w) N0 Q+ ]8 c- S9 ~; Xif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,8 L* c/ H {' g; o2 S9 | s
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",: }' u9 @$ h" n: T$ c
0,& u M! ?! ?; S0 m" i0 ?
KEY_READ,* K- i- z! G2 q
&hKey) != ERROR_SUCCESS)8 g; D, u* m" }) ~ }$ M
return FALSE;
' @+ k/ m* n7 V2 w! z& m+ H! q$ x! q- q
DWORD dwIndex = 0;
- @. C3 P: S0 i4 X, i, x: g( }# yDWORD dwBufSize = 256; c d1 E7 F, A& w2 g( s
DWORD dwDataType;
8 J% B7 `. M6 V' R0 Dchar szSubKey[256];: B; q. G: E- G# i3 @
unsigned char szData[256];
# J. G3 X+ {. `+ D, Q+ {4 ]1 C$ P* s. s* b" _* d# Q
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)' G: O# u2 l: x" R# K
{4 ?4 h! y$ f1 C
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
% Q/ V" U+ D5 a& t, ~9 \ { * k6 S% V0 }" t A0 h
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)5 C/ p4 [# M, j# a% f
{
) M) f3 B7 h1 ?/ @ dwBufSize = 256;* ]/ F: `- h7 v$ S" N, @5 d
if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)6 E+ O) b3 r$ G; T, a* ?6 v
{" ]' A/ c6 {! s/ s
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
6 f6 U9 c' d/ U* L, [0 G {, O8 b/ _1 R; Z
dwBufSize = 256;' r" t8 n e7 P" k
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
, X3 I \! Y: o {
h4 D+ {" X; [) r // szData 中便是适配器详细描述
* V3 R, L, U; e+ N5 g# s. v dwBufSize = 256;
( P# E& f2 a( T S) i if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
7 f/ y. x% a* d& Q {" B2 U- ?% S% f2 G
// szData 中便是适配器名称
. P- a9 R, H4 D" J }4 z6 l7 k3 a X: @7 a) e4 o
} h3 x1 j r- q! J+ K
}
, `6 i& @& r: B3 o1 r }$ w) ]7 m9 _: E8 N/ ^) v
RegCloseKey(hNdiIntKey);
% {& J. n6 ~; @% k% b; V( { }
# `5 q2 @( s- n7 w& J RegCloseKey(hSubKey);
; b5 b+ f* m2 Q9 Z }9 A ?0 \5 B; H
/ W8 g# Y; \6 e' D2 ?7 z
dwBufSize = 256;
* Y/ ^' f1 b8 x8 [. h4 c3 x$ c} /* end of while */
& V( g2 f* l0 p: l1 h
+ ^) f8 M: F) J8 Q( w6 QRegCloseKey(hKey);
" F0 ] z0 C5 a8 \9 F二、将IP信息写入注册表
% g0 q' L3 K# K
6 `2 Y9 z" `& o- l' k代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)* W6 X+ q% K0 m( V; o
{
/ ^! N2 o8 Y$ q HKEY hKey;$ \) ^: O4 ^9 w1 c b5 V
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";1 B) L( C" W; t) R0 ?/ {- i
strKeyName += lpszAdapterName;
6 |/ B7 t' p; _6 N% l( F# u/ t if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,2 S/ |: Z9 G! M8 n% d1 P8 w$ Z5 _
strKeyName.c_str(),
' y) [) C; @5 m* ?3 R 0,
) H- M A2 h3 G8 @/ d V( P KEY_WRITE,- F0 J* ^. P. _+ X
&hKey) != ERROR_SUCCESS)5 [% K2 k0 B' A0 E6 M4 H
return FALSE;3 I |8 }( H7 x/ U
- C/ A6 v/ d* z& M' }+ S- |" c char mszIPAddress[100];8 T+ h( B7 y9 `) D
char mszNetMask[100];
, Y- ] a0 o) n1 p+ Z9 d char mszNetGate[100];1 ^# n/ O: h2 k1 p! F
" T& T) h% A1 W, ?
strncpy(mszIPAddress, pIPAddress, 98);
' b0 G2 i& C; G" f9 u7 I/ J strncpy(mszNetMask, pNetMask, 98);( J+ f: t- F7 Y
strncpy(mszNetGate, pNetGate, 98);6 |( r! @% d- ^+ o0 C' z: a
' F( C9 `9 l! K" a$ h int nIP, nMask, nGate;
$ h7 B4 k- e8 j+ L5 T. M
5 J+ g. E- y9 D/ g* X F9 { nIP = strlen(mszIPAddress);& \3 |1 a) y' Z1 p5 Q' E- n
nMask = strlen(mszNetMask);5 f& h7 h) V3 M2 @
nGate = strlen(mszNetGate);% q1 y' j0 b& R1 ~. m
/ j+ }1 [) G a+ P( F *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0, p4 | J" K, I f
nIP += 2;
! u9 t; Z- x9 Z1 W( u) w" z J0 H- ]2 a1 |
*(mszNetMask + nMask + 1) = 0x00;- U$ K4 T+ k% d7 s; i
nMask += 2;1 f8 J2 [6 k+ t* u# ]* f; Q
4 U) T: {8 x% k( s4 Y5 }+ r
*(mszNetGate + nGate + 1) = 0x00;
+ o: B1 G, p. g& S1 J nGate += 2;
; l4 J7 u. b5 ] H! L
' T, p, ^. V( p( [* q RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
( }* c( [9 ^% W0 c i) o+ L% z RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
& x& h' z- ?( V2 L- U RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);' i3 B$ V: c% F8 e+ Q
% m4 W; J s+ Q RegCloseKey(hKey);
6 ]4 u! e1 k' f+ p5 ^4 O
! T h" C' o. y" o3 u* E. }/ m return TRUE;
6 d6 ^) R% F* g' f9 Y9 Z) H. N& ]}
5 @0 \* l6 ^4 t1 c ?# k. b
5 z4 F: u% ]3 v三、调用DhcpNotifyConfigChange通知配置的改变2 S* r/ n! _5 q- P6 f
6 `4 D) b' `3 R2 O$ q未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(7 U P7 b+ @3 m: ]
LPWSTR lpwszServerName, // 本地机器为NULL
& I+ L) k& F% U1 j' S( v4 Z LPWSTR lpwszAdapterName, // 适配器名称
6 J3 |# {( k* t( n) m BOOL bNewIpAddress, // TRUE表示更改IP
1 S- l% T# V5 [- |$ M$ h8 D DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
; }- O7 Z0 l. G5 W) R u DWORD dwIpAddress, // IP地址. h8 A" d5 m: [7 \
DWORD dwSubNetMask, // 子网掩码$ t* V: C# N7 q
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
. S/ S9 I9 T& i8 U/ ]: a8 b
3 E% J# Q( _- ~# j; ~0 p5 w w3 }具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask). Y6 _# I9 ]1 N; A6 K @5 o
{
2 D% O, {4 c. A D BOOL bResult = FALSE;
) D* r8 a/ [& S# f% ?5 R6 b HINSTANCE hDhcpDll;
4 T& l$ D& T. p7 V! f3 }3 A# a; V DHCPNOTIFYPROC pDhcpNotifyProc;
4 X& X' f+ `) o& C4 [ WCHAR wcAdapterName[256];3 S+ T- C& S2 B: m8 I! m
% B, O* u: v" V+ C6 ?
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
" _+ u: {0 x) D+ B5 |4 h ]" G7 _/ N) r( k+ ^$ X
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)' { j. r. a8 c8 F- j' ^0 V
return FALSE;4 q; H9 r. B' w. y+ ]' ]
1 F( Y' H. w" h# y4 f0 G5 d% h
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
4 O% z8 _+ I6 D* @ if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
! V4 i- c' v1 P bResult = TRUE;, d) L3 k$ n2 w$ L$ ]" r% ~
& B0 w4 C3 l8 ^# L- d% U FreeLibrary(hDhcpDll);' D |5 A8 g; q6 X9 E
return bResult;
4 p9 g, t# m8 G- H" S. m} |
|