|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:" c( {' i* f7 o
* [4 ]$ l6 C0 u1 ?6 e) k% B
一、获取适配器名称
( N, g) ^! f/ {( \- k2 ]* z) U' ]( |: T& x9 Y) V V7 i8 l
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
3 y; b/ }' }! c4 r! L* U* c5 y7 Y1 P% I4 P
1.1 调用IP helper API取得适配器名称 4 B9 t8 |2 ~, g6 T$ ?5 I' `
c- q% `: f8 SULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);1 T. a5 d: p3 g! \
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
Y5 i9 b B7 b# l% Rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
9 O# l5 e j/ d! {3 b{5 z/ u7 U( Q/ N Y( J! ?
delete pAdapterInfo;" \6 J) z% f( x! q# D
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
* B: y, O& d' E, | pAdapterInfoBkp = pAdapterInfo;
* E) C- z# R/ l}
5 Y" m1 j# M3 m; e0 rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS ) X9 p8 d2 X- |; L8 K9 w
{
/ o5 k4 C6 i( g" h* b0 g1 D do{ // 遍历所有适配器
# a) ~6 P+ w, d/ q if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口& x* h- a7 ~ Q! h( X
{
+ Z& T" ~" w' _3 O2 l // pAdapterInfo->Description 是适配器描述2 @% T8 ?+ P! {" a
// pAdapterInfo->AdapterName 是适配器名称
" g3 {; y0 ?6 j! O$ b- R ? }* g7 B1 ^6 ]$ e' ?& @' }
pAdapterInfo = pAdapterInfo->Next;
& C/ G2 Z( [7 c! S }while(pAdapterInfo);( z2 U% N6 x! l s
}$ x5 _! W3 m/ `2 G5 R" T
delete pAdapterInfoBkp;. Z4 s# s" Q4 B0 J
9 ~0 @) k" W) T
1.2 读取注册表取得适配器名称
2 W/ l/ `. b5 Q1 p6 P
2 T) }+ Y4 r& A& s# R2 N# o在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;; o( d# ]# I. ~% }) S* r
; p* z% P9 P- x" d) M. m3 [
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, D2 ~( ~" ~' [) r9 R
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",- G+ T2 o! g3 ]8 I; q
0,
% y( S( q( O1 z* t% V- Q KEY_READ,
% D! D; H' ~7 v& _( U* k* S! T &hKey) != ERROR_SUCCESS)& Z8 i m( O4 h4 M% s" H k
return FALSE;
% _: M# U, A7 J0 I2 A& E& z6 t3 @* q. T
DWORD dwIndex = 0;
/ H, H; D0 G+ VDWORD dwBufSize = 256;' q( D p& e# O& |5 L) D2 O
DWORD dwDataType; y. V8 p# u) m' [, c
char szSubKey[256];
( J0 `( A+ d/ c& c4 k" J2 q" b8 G/ |unsigned char szData[256]; l5 {4 m [5 B( B9 b$ h! o
, I5 N( z( p6 N& Mwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)! r3 P# Z& v* J- e) X- y
{
1 G2 g9 e8 Q! B if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)1 _" I+ D& I( r
{ 9 ]% ? v; h U, @2 J* u1 N9 P3 j
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
5 Q0 z; b% G" c- y6 Q! i4 d- ] {& @2 c' b; L& ~) ?: H, o
dwBufSize = 256;
1 t4 M8 b3 ~) D J5 { if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)1 h5 O9 r8 I* i0 B* Y
{: @1 T, J7 A0 w
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
- Y" _: p, C0 J( k/ t% s {. X; y5 s& F% I) ]2 F
dwBufSize = 256;- ?) c' L: |4 P. ^4 F
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)3 M- M: X/ L% h' v. K+ @2 v
{
$ x9 N1 }% s4 [% R; ~ // szData 中便是适配器详细描述
9 M ^" q, q# x6 K! r; D dwBufSize = 256;
4 [* ^/ I0 }1 E if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)" Q3 C, Q) u7 r5 w
{
# }+ s) a1 H1 L* i! { // szData 中便是适配器名称
o7 R$ ]5 G1 F+ C, \5 P }
F% W* C, O1 B( J. L' c }5 [: j; a; T# Q# V7 E" x# l. b
}
4 N0 ]0 `& t$ s C9 v8 _* t1 s }- G% c5 h5 o) }
RegCloseKey(hNdiIntKey);7 m3 ]* [7 e& E! y8 |' D5 w
}
# W: N7 h# k. A8 u5 {9 d( N RegCloseKey(hSubKey);/ x- Y5 k0 |2 I4 X+ h' v: L6 M
}* ?* n% [: b" L, Z7 F+ R9 [. V2 W
5 V4 o# {4 H# j. r
dwBufSize = 256;( [* H/ t: X9 A
} /* end of while */
/ N. c; G. R- |" e/ m! k) l; o6 f5 }
4 ]) M( g$ i5 |: N/ G, s1 V; O" @RegCloseKey(hKey);/ v" L( q& l) Y2 V7 b
二、将IP信息写入注册表* \4 D3 m/ X$ {( m
& L1 t8 ~6 \- h' |7 Y3 [( J代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
6 ] m. f; w3 v$ R4 v6 Q{
; x7 D8 I6 C1 Q' e HKEY hKey;
! S" Z" W4 L( b5 _9 c5 [ string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";% h- Y0 Q& H9 `7 O# \2 Q" z
strKeyName += lpszAdapterName;8 u2 }. g* B& m4 @
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
# A/ a2 @* U1 w$ g- f strKeyName.c_str(),9 a5 C3 x# E: M X" M$ ^/ p
0,
. y4 |# b' R; T3 _# i% d# @ KEY_WRITE,
- G( e+ X0 H; Y% Q &hKey) != ERROR_SUCCESS)4 [7 \, j) l0 @3 l
return FALSE;' o. ~$ r6 u$ s H% w; A8 M
: N6 \' c& u) } char mszIPAddress[100];
) \7 O }+ F# _9 {2 X" c6 i( d: `3 B char mszNetMask[100];1 c1 f/ Z! F) Y9 @. T/ H
char mszNetGate[100];
3 B6 K8 e. U% s8 b$ x2 o" E. I/ D0 Y. G4 m# l8 N" Z, q) [ k0 t
strncpy(mszIPAddress, pIPAddress, 98);( L1 U) k6 j7 Y! x: o9 {
strncpy(mszNetMask, pNetMask, 98);4 @: `& Z. D" h, _- C3 ]" i
strncpy(mszNetGate, pNetGate, 98);1 K( f/ M8 c) [
( u1 C, p7 ]3 \! A4 u2 M9 n, M int nIP, nMask, nGate;- y: e1 R) P6 I k
& Y6 H; L& ~+ o8 d& ^- O# F* R5 y nIP = strlen(mszIPAddress);
& F! I7 u4 T6 W' j7 } nMask = strlen(mszNetMask);
2 M4 Q7 s1 S6 U& r( D% M nGate = strlen(mszNetGate);
6 Y E. Q! N9 a0 W2 {- `; N
8 H( @2 d- t! Y/ G *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
" w) l( c# `% O$ ?8 b% L nIP += 2;8 b i1 u1 J- ]) v1 \8 g; i1 O. @$ H; a
& [2 V$ x. V; b+ N# K) r4 z* l
*(mszNetMask + nMask + 1) = 0x00;
1 E6 n! v/ u" x) M/ z& p7 B nMask += 2;
0 R0 [# }& ?# S `. R9 w
$ K: O8 i6 M& J( V; z$ B *(mszNetGate + nGate + 1) = 0x00;
' c2 Z$ ?/ T. w4 }1 _6 P nGate += 2;
" j" \. A: u9 E3 ^9 i, ^$ o0 F 3 P. B/ u1 {/ e- N* D
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
" `5 o0 [& ~3 p7 r4 L$ } RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);) l- D1 h$ f9 f; \5 w5 ^! x
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);, P4 ]. x0 V% j; k
B* [$ m, | J6 U
RegCloseKey(hKey);
, {% B b3 ^' I1 f
) n7 E0 A* V# a# q# n W* [ return TRUE;
- a# h8 t6 g! g% V+ Z+ j}9 Y$ \; d7 E# o. H$ T
7 l6 n: T6 K O
三、调用DhcpNotifyConfigChange通知配置的改变
# ^5 n6 l- ^& j% f& Z0 s' i: b5 j+ k3 G: M
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange($ v+ G# e2 L$ `- x R2 k# U
LPWSTR lpwszServerName, // 本地机器为NULL2 c/ V! s) e6 \1 ]+ @; d* f
LPWSTR lpwszAdapterName, // 适配器名称9 O) K" @% z: T. z7 w% g4 e
BOOL bNewIpAddress, // TRUE表示更改IP
; w- j3 J; b: m DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0" B3 A/ A) w `0 H5 \. p Q
DWORD dwIpAddress, // IP地址0 X, m; V0 ?+ @: s) o. Z
DWORD dwSubNetMask, // 子网掩码
/ A' k# `8 G3 O- i" d int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP6 o7 B" x) ?8 x
8 a, I9 }7 ~7 Y8 b0 X+ b( m具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
. x3 _& t1 Q9 S5 `) s4 C) Q{
- W5 y2 j8 g2 a, Q BOOL bResult = FALSE;
F' u8 H% c8 s HINSTANCE hDhcpDll;' _( l9 h. W1 M3 M# c
DHCPNOTIFYPROC pDhcpNotifyProc;
" y, v! M/ k# H5 d d* {% K- g WCHAR wcAdapterName[256];
" W$ K* b& y* \ % _! x+ m( i" _) j8 F, j/ S0 [8 D! M3 `
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
% [, @$ X& L) M4 V8 G) a
$ I+ R4 n' |( ~' y+ f* u if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
) t1 Y7 g5 ]7 F8 f3 A1 ? return FALSE;
6 Q2 l( {8 I$ A! t/ ]' R& C4 C$ e. ^3 t$ I4 |: g0 s' M
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
* l+ F2 Z( l$ ]0 c( N7 p# ]6 s! e if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)3 K) W3 L) j" p' z1 F! G- t7 d
bResult = TRUE;6 K2 x* x- R% w
' U8 n3 _9 U* j2 _$ q FreeLibrary(hDhcpDll);
/ V( n n$ @) c1 G& e' a6 ^1 O return bResult;
3 O2 ?# T7 Y- x} |
|