|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:# g1 h- }" H' d) B/ s( \
8 d6 K" i) g' s* {' B一、获取适配器名称( k) B( z; U: F' {+ a# a; x H. d
1 H; u) _! A7 {# e: X& X; m这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:; n" H% U* [+ w! H- G: f$ {0 L* }
V" B, G7 t6 M$ z: O8 |1.1 调用IP helper API取得适配器名称
! n) S& X u* f# X- e
) R: C/ l/ q) P/ x( C3 LULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
* r* ]. H& k- bIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];' p) [7 e& ?. l5 h$ }
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
! H* e4 Q& {1 ]" R2 A{
) `7 X, Z4 x; ^ delete pAdapterInfo;
: a- X; G" j1 Q+ D pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];" d) V1 U* |" a% D+ n4 ~# ~( K
pAdapterInfoBkp = pAdapterInfo;
G9 E; I' T x) z}" _5 D. t1 F, ^; e5 W
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
" O; v8 a6 i- `' e; m{
) N: `! `2 s( c) F+ R do{ // 遍历所有适配器# J4 J* g" d, J
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
; S3 X- E8 F% ~3 s {/ v- }9 ?6 f: _7 I' i/ Y2 g" R
// pAdapterInfo->Description 是适配器描述/ v4 [; D' k! V0 ]; Q2 ^
// pAdapterInfo->AdapterName 是适配器名称 T5 `+ j# T/ R6 m
}
, p6 A, Z# c) L" _& Z pAdapterInfo = pAdapterInfo->Next;2 M1 Q3 R' `1 ^! h" c
}while(pAdapterInfo);% l6 [5 e* S4 O {
}7 `; ^+ y9 {7 E- e/ ]$ S
delete pAdapterInfoBkp;# |0 I' H; w- n( {4 c, I
: L0 x, v1 t! R! Q
1.2 读取注册表取得适配器名称
, P c% y' G5 V! T
3 f( P; t! _% Z在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;- D9 q! l7 s; | c; A7 m. |) m
- c0 y- o$ e3 p4 Y$ F' e% ~' }" yif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,+ M% `& L$ J3 m' T8 r
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
# R+ q; X$ x- W3 k 0,6 N @7 X" W2 J0 x9 ]9 |
KEY_READ,& o+ H5 N0 {+ o) n4 H1 b* a
&hKey) != ERROR_SUCCESS)
3 h6 w- q: r6 J; ] i" U+ S3 n return FALSE;
. Q* J$ `& K0 Y
: n8 t7 i9 p r, O5 i$ }DWORD dwIndex = 0;
$ n0 Q' E( y5 x' w$ Y; y( }DWORD dwBufSize = 256;
( ?# X% p$ V/ q2 j* |DWORD dwDataType;
5 s1 H' @4 M* o6 A [0 _char szSubKey[256];. Z$ W |& n l$ p# o1 A X
unsigned char szData[256];
4 T' o* v# m: @) g$ j0 a. }
6 ~$ W% m. z" S; Y2 k( ]while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
U$ {: Y* _- Q. ?3 P{3 K1 ~% j3 r+ e# N2 j# N
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
9 X. c% J# R4 Z* M) ? { 5 Q4 L& o! K+ ]" T4 J Z
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
0 u& S5 [2 W6 x: J7 W' X. a/ f. F3 R {( ]6 @ t$ L4 D7 n( A% s" T4 ]5 ?- B5 g
dwBufSize = 256;8 l) m( O% q! c; B
if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)5 {+ T; @. z1 m G p
{- u k8 w) N5 W7 ^* r
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
8 h6 a1 w9 s+ j# l- i {
: g8 w0 S8 k- A: w& [8 q! l! P dwBufSize = 256;! `. u* K9 k& K" I% w0 }
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)0 ]" E. g1 F- v1 P! t& S
{/ J @6 P$ t; K1 V
// szData 中便是适配器详细描述" W+ @1 Y) f0 y; v2 B- T/ F/ J1 z
dwBufSize = 256;2 w7 v) E& o7 R6 t# g3 B* w/ D+ K' _
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)9 r% r( c/ s8 v9 O8 k" R; p9 j
{
, K/ n0 l" H) m% L2 e( ^) L // szData 中便是适配器名称" Z3 x+ i1 h" ^1 D4 [2 A7 d
}
* u' I9 A2 U5 z* h% J7 f! _- v }7 t( x) j! p6 S/ f& J
}
* Y2 L- {7 I0 f4 C0 \ }# J2 U+ O4 i$ y4 C9 v$ d; _4 n8 K
RegCloseKey(hNdiIntKey);
9 }, S* h- ] B& P }& w3 O$ }4 {8 f5 o2 w
RegCloseKey(hSubKey);
! H H" D7 l+ ]3 Y* v4 y6 ^1 M( @/ x }
7 n1 k* G& j9 {! F( B9 U3 j8 c k e3 M% a& M
dwBufSize = 256;
, S. O# w1 c* E- n1 z} /* end of while *// s: u& u* J8 w* h) N4 q
& \7 w2 [8 n. h; }RegCloseKey(hKey);
& R0 b3 D Z) X( u8 v二、将IP信息写入注册表
3 A c7 \- u0 U% O$ @2 N
1 R5 G6 S7 b2 m9 O1 s( d代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
$ Q; P) q* F8 o& {, h, J; z{
* j; F$ I8 i4 f7 t% @$ t HKEY hKey;' b" T) E( ]: `/ W0 u* g9 k- Y5 k
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
( w" O: Q: e) O# \' G! c/ y strKeyName += lpszAdapterName;
% C: W5 s5 B s8 Y8 ] if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
; q$ d! w, h- J- r- e8 z% t strKeyName.c_str(),
- E* }% d6 e* w- j& R4 h0 b 0,
# O( T9 d* U; K$ |3 n1 f KEY_WRITE,
+ X6 g( I3 v0 o0 K. \$ w. C/ c; g &hKey) != ERROR_SUCCESS)1 G$ {$ s4 R2 ^# J1 m/ j
return FALSE;+ A* V- q0 j9 e& Y+ F
5 u) f. t0 i, n$ ~) H
char mszIPAddress[100];0 I& v$ U& R* ?* _4 s/ }
char mszNetMask[100];
4 N" s D/ d" O5 L" o char mszNetGate[100];
/ i, q5 P0 M0 b1 V1 a0 f
. E! J# e/ ~2 L, { strncpy(mszIPAddress, pIPAddress, 98);; d7 P/ [# X4 d, l0 k' G# A# _" z$ w! d
strncpy(mszNetMask, pNetMask, 98);9 q( W" J* m. v% G. t; Q
strncpy(mszNetGate, pNetGate, 98);0 {+ O' L: r* U: X ]
X0 P2 ?# ]. b* n: w$ R9 t) @) N
int nIP, nMask, nGate;
$ x2 u- Q$ N0 c
. U' `' c) U8 f0 T2 U nIP = strlen(mszIPAddress);$ s' |7 O) i5 E+ \3 } V! R
nMask = strlen(mszNetMask);0 C. L) M) F6 f
nGate = strlen(mszNetGate);( J( o+ o$ Z9 T
+ a# D6 ]8 [( Z6 e R2 R/ H *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0) K& T, T7 z+ F$ {+ n
nIP += 2;
7 w1 G3 b! p t! c9 s& N& h- u
A2 G8 ^! s; Q; J' ~: j *(mszNetMask + nMask + 1) = 0x00;
' Z j2 D- I9 D! f$ F: @8 V nMask += 2;
2 T+ f v e& v4 @: S4 d D B8 m) v' Y
- V* p/ s: L1 u( r+ P. A *(mszNetGate + nGate + 1) = 0x00;
, F$ F" D9 D2 G! D, [ nGate += 2;$ x! F) W6 C) y8 ?- t8 x- V0 o
2 C! r# Z/ ~( a7 d/ x5 a9 o# a
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
+ A, k2 |4 X! |4 s RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);% g% O" ~# @) o: }8 `% t
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
) T4 b( J3 {3 z1 g- z; [
' F6 u$ i7 G! K9 e: T1 R' M RegCloseKey(hKey);+ d( u6 w0 U3 m
. e o# w: B8 u, D5 l" m return TRUE;
& y2 P- Z- {/ r4 e}
" v& _' @. Q; G1 M' p; N2 y) b8 Y) G7 u! z. P
三、调用DhcpNotifyConfigChange通知配置的改变5 n; G* E# |: ]: Z
& u% a- d I0 T% X, a0 j# x, b( ~1 N未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(7 d7 S* N+ {: S( N& K5 @ b6 P
LPWSTR lpwszServerName, // 本地机器为NULL) Z% g* T+ X/ G0 f, o
LPWSTR lpwszAdapterName, // 适配器名称
: P$ K6 { {. c6 z! v+ Z' k BOOL bNewIpAddress, // TRUE表示更改IP' l6 C' u! n% c8 d) L8 Q
DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0, V) N5 q' ?( h$ t
DWORD dwIpAddress, // IP地址
' {- }/ _2 Q$ S) Y/ k5 {0 b DWORD dwSubNetMask, // 子网掩码/ R# i) |$ h6 R5 p
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
: k" ?! r! z$ Q# u& K
( F% C5 N3 h. R- x: ?; _. E具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask), s- Q# D$ a+ g) A
{' _2 T7 K: R% k, ^' S
BOOL bResult = FALSE;
' @3 @9 H N9 R1 |" O HINSTANCE hDhcpDll;
m6 J4 Z% }2 B5 g0 X- H: o. m( K DHCPNOTIFYPROC pDhcpNotifyProc;
/ }3 H( J2 M; s* _* i# _: |; u WCHAR wcAdapterName[256];3 _2 A) O( S3 N
; M! w' H3 g3 j4 f: R8 I5 @ MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
- f0 B j/ @( M" z8 T E3 ?9 w! V2 k
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
3 k, d2 N% J% u) ?% T3 b# s! ^6 B return FALSE;
5 d8 S( u, f5 |) A( w
5 q! }, n e5 G7 K K* c3 h if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
) X( D0 K! I9 C& q if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)1 m( J2 d# l3 \+ h& X
bResult = TRUE;
" D( H; J8 [ v. W5 [, U, t5 D% w% ]" T" j' B& ~# N; i! G9 j) I$ N
FreeLibrary(hDhcpDll);- k v3 O% f& i2 z
return bResult;3 K6 M R0 A- d/ G, D/ ^) C7 y
} |
|