|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
% S% R! v. K$ D$ V4 I% V5 z' p% E, ]
一、获取适配器名称
. G( x! N j; Q2 C5 h4 V M
7 M! f9 w7 x* y& J& O( A N这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
4 }- K, u; l! c N
' |8 Z# `9 H/ g B5 I7 {4 l1.1 调用IP helper API取得适配器名称 " w( J2 o5 ~& k1 z/ C" I: k/ u
! r( e2 \! x! [" J6 z3 xULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
' B5 a( T1 N; O) BIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];, j0 l; |6 x; c5 o& U% S
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大' u8 o) b, |9 k3 N* d6 C
{: y% u" x, c( D6 {8 I
delete pAdapterInfo;! W. A' ]$ v! ~; O2 H' [' L. z- V
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
! b; w' J3 @6 c6 P, H/ @3 u B4 n pAdapterInfoBkp = pAdapterInfo;# _) O5 G* \# X1 k
}
* W! L8 w" ]5 \( n. bif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )& ^& u" u p: a6 [9 A
{
d3 m+ }" S+ { do{ // 遍历所有适配器
0 o* A! m7 l. S; _ if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
2 ` ?# e6 E! j* y+ o p' a {
# y' i6 a+ X z8 ~+ {6 h9 B // pAdapterInfo->Description 是适配器描述+ \* O0 W* R8 N# `. [
// pAdapterInfo->AdapterName 是适配器名称
+ t% M* P5 \6 p }$ i5 y! |3 z% }1 U- F8 N
pAdapterInfo = pAdapterInfo->Next;
$ f/ L$ M& r* f8 ~ g0 o }while(pAdapterInfo);
' K& A: j. o \}
$ B6 `* V; x8 N4 b' jdelete pAdapterInfoBkp;2 W6 j1 W) l" f! ]- y% O9 w7 ]4 O
0 b! m) r# }5 A/ p2 v! K
1.2 读取注册表取得适配器名称% w7 a7 B2 a/ d& y( u/ T
# D! G2 G* H. E. a) A" @
在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 W% c* a% E1 b# W& g; o2 k+ s2 s
8 N5 _1 O1 }8 t3 |5 L* q. D# y5 q% ?+ vif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,7 a, ^ p0 S+ O( n% v- W! D
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",2 t9 _6 a, C% _* }- ~
0,) K, {. O1 X/ @+ ]7 ?5 A( L
KEY_READ,
7 f. e9 z T5 r &hKey) != ERROR_SUCCESS)9 d3 f# x. e8 E
return FALSE;5 ], G0 B" b( z+ c9 i, t4 I
% o* C9 F" _: s9 U- a' rDWORD dwIndex = 0;& k2 \9 y9 i4 N8 B3 J
DWORD dwBufSize = 256;
# F$ V: h w3 {$ ]DWORD dwDataType;
! g# c5 L3 z* N3 ichar szSubKey[256];1 F& h3 x; a6 P
unsigned char szData[256];
5 C1 g# N& `! J* {
$ T3 g6 K/ t2 \: R* Uwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)* I; N8 L$ [ D7 z5 C, J( W
{7 Y0 \5 w- ?3 b, y4 i2 p
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
; v/ ` h4 L! D, Z { - R" C# z, X. u3 n# Z" U
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
: z, f! x* J& [% \3 S3 p1 T9 u {
. h% z$ q% P3 E% N( W dwBufSize = 256;
4 [, H! K" y/ w) g$ s if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) _- m0 ^& ~- _% b1 o
{7 {) h4 H4 W3 V( t( t$ ~
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡+ O7 C, k8 ^* g T5 s
{. ?3 O I" V9 \$ \1 S
dwBufSize = 256;! V( l) A4 ~' @; M) M* D) S
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)% ~, |- k7 V) B0 _4 G! J" I
{5 i3 t0 W, _ A. C4 p8 W+ K5 Z
// szData 中便是适配器详细描述# P3 v. j! {- [
dwBufSize = 256;
) U) V+ c. R7 Z7 Y: l2 R, O1 g* j if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
3 B$ X! Y9 F( u$ ] p" B I {4 g4 K$ _1 F% h% Z, j+ _6 D6 ^
// szData 中便是适配器名称# N U1 N9 f9 ^' M& R1 _
}
9 P9 G8 v$ A1 [ K }
* X9 Y/ }8 U* |$ C8 x' k, ] }" H$ b& }! O/ r! V7 f3 |7 ^
}4 ^0 U0 |5 R9 W# a8 J
RegCloseKey(hNdiIntKey);
, u7 d0 Q! ` E: H& f }
* ^( M6 p0 c/ r RegCloseKey(hSubKey);+ H n0 x4 n) L5 \) m" A9 m6 Z. u; K8 z
}4 }5 F7 H, D! |/ r
5 K+ f4 c- l! [$ K dwBufSize = 256;0 `1 G0 R! Q3 G! h4 D% I
} /* end of while */
* g' c' D0 \/ W% |; m5 M! S
3 w1 e- S4 o& N* S1 X: FRegCloseKey(hKey);
, @9 D. T2 i4 ]9 _5 G4 f二、将IP信息写入注册表2 h# B' j+ m5 F8 X
x0 D& w: k& ^+ w! s( n代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)* [' t r: O% a- a6 T1 u0 {4 Q8 Y
{9 `3 Q& H6 N+ ^2 a& P, _& t! s
HKEY hKey;
; E+ V: x! s' ^" Z) D string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
1 r' e8 r3 n; E* _# z3 Z" L strKeyName += lpszAdapterName;
. v9 s! y: Z# v8 t, n if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,. V2 a8 _& g5 ~$ ~# P2 u% z
strKeyName.c_str(),
- G# r+ }0 f. t6 S) _ 0,
# s: `; X' J" \4 l3 I KEY_WRITE,
/ A# f' ]9 L* i2 J &hKey) != ERROR_SUCCESS)
8 Z' V, ?. ]3 b# e% J" x return FALSE;2 ^0 W w- A: h
: @1 }, j/ p; o, s
char mszIPAddress[100];! A; E) X* X) G4 e+ c% c9 ]
char mszNetMask[100];
3 S( ]! e. b: x: p3 K char mszNetGate[100];
7 x: l: a5 j. K, C" {* b/ g0 j* B; b. R# E4 f& s; ^1 ?5 V! k% [3 p% R" I
strncpy(mszIPAddress, pIPAddress, 98);1 {' _, @! x/ o* D1 n2 k
strncpy(mszNetMask, pNetMask, 98);4 b: {4 Z. E" R
strncpy(mszNetGate, pNetGate, 98);
' x- G7 g! k* Z5 i8 p% Q
: H: m5 m: S$ @' Q' g- J4 b int nIP, nMask, nGate;
* O* S. i R' j/ d
/ h* I# _# j4 {& W nIP = strlen(mszIPAddress);
* ] Z3 I8 a$ l U# n nMask = strlen(mszNetMask);$ _ e j4 u/ ?+ F d$ {4 S: x
nGate = strlen(mszNetGate);& K' q L& b7 P8 N4 F
9 P: F: r7 d7 G' [. q *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个02 e. p! ]# g" c3 |. r9 g
nIP += 2;" F# ~! r3 {5 ^9 m4 x1 }0 a
6 q4 ]5 m3 K* p *(mszNetMask + nMask + 1) = 0x00;9 j8 O1 x& f. Q1 j6 Z
nMask += 2;
0 G h; v$ k/ A8 W; C: r
: U( R- \2 n4 _5 u) y( z8 p% @ *(mszNetGate + nGate + 1) = 0x00;& A0 h5 g9 k$ p! Y: ?3 v4 V
nGate += 2;
, {/ m, u8 |5 O5 [ " | H- ]4 F% a( E
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);! g0 b7 L# z; o- `/ V Y% e
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask); \( D, r3 Z+ E2 A% G" N' ^
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);- V% d& r! N4 ^$ i" p; s
0 d7 \7 h& G: y* w& y1 v8 i
RegCloseKey(hKey);
: G. g/ u6 L- }
; m' B& v5 d4 s- k; o* ]" n return TRUE;' B. Q9 t# g2 i0 L& S
}
# Q; I$ M0 z; D( q2 B8 ~0 ?
& o5 q4 n9 e3 A' d: R. e' P. J. v三、调用DhcpNotifyConfigChange通知配置的改变) O0 f: j4 k; M; `7 ^; {) [: d
$ w( o2 l3 C( W; q9 q+ M6 }未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
1 b0 N$ o' Z9 h3 H) V/ d% P- h: n9 m( D LPWSTR lpwszServerName, // 本地机器为NULL
a' C- R) S- N: }$ g: h" \ LPWSTR lpwszAdapterName, // 适配器名称
. E1 z/ M* P( u2 z2 ^ BOOL bNewIpAddress, // TRUE表示更改IP
5 s7 `+ w8 t; Q3 S& T( o DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
6 r8 y2 D& I2 }, ?: M# b DWORD dwIpAddress, // IP地址' @/ @9 o' o/ q
DWORD dwSubNetMask, // 子网掩码! ~* T4 U2 U" ?3 ^( X! Z6 y- E
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP) Q( } V* K( X2 J2 D. P9 b
- Y* ~: D; k( Z1 {* \
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)3 o/ x+ b0 L/ K# ?) o
{5 q& H8 \/ Z6 @ J+ Y
BOOL bResult = FALSE;( c, b4 ^ s( N
HINSTANCE hDhcpDll;
( G6 C% _# g0 E9 G8 ] DHCPNOTIFYPROC pDhcpNotifyProc;
" \ H0 p1 f( ` M" G, _) @ WCHAR wcAdapterName[256];/ L/ U" E2 [, O8 c8 z# @- s0 E
( ~: B- B) _: l- ~. o$ I MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);) }( Z7 V* {# c# y1 Z3 g& A7 a
. d( r2 G" d# _# i
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)6 c" Q& a; D+ S+ ]
return FALSE;; N; r3 H: j8 F$ G
) k$ a- S8 _: Z& V* p
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
$ Y4 d R9 ^2 H7 j if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
% {4 k* ^2 c. L' d0 x bResult = TRUE;
9 w) i2 C% \* W( F8 n8 n+ Z" E) T$ m/ y. i
FreeLibrary(hDhcpDll);( c+ g4 K6 L: L1 d; q" H9 Q
return bResult;$ E& w% K: d4 T* d2 G7 T
} |
|