|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
K _# T4 U0 O1 E/ R" u0 J4 E% \0 H# O' ^$ w7 W# [0 \6 ?# A
一、获取适配器名称
3 ^! o& G S6 m2 a6 {$ S" e9 Q5 {' u- k, Y% H7 h! o
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
5 {/ F0 X+ G3 r3 P) s3 F. j
+ a" w( ]. z" Y0 ^8 L/ R, J1.1 调用IP helper API取得适配器名称
4 [+ L% y: X' Z1 _# b J5 ~& [/ Z: y
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
- L4 s% V) [* T7 H/ n, SIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
( l0 s9 e1 k: vif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
+ R/ ^) G( V. q7 O' d{; i5 S5 T0 I; F1 y) k
delete pAdapterInfo;
0 I# D$ U+ ~7 l+ A! v9 h- W/ { pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
4 j4 f+ l' u C0 z9 Y pAdapterInfoBkp = pAdapterInfo;
9 L# N. J4 N& H9 I! e}
- ]0 F1 o/ L: Wif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
* D3 D/ c4 b/ N/ V) J& c4 `{! y$ S! Z. j, x' q6 Q2 @; {) u: T- d
do{ // 遍历所有适配器
8 w. ]1 o9 d7 `9 V+ n- T0 \ m if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口( ?9 b% F ~. z; D: T6 U
{
# ~+ \ q- q( ^9 Y" e, ~* c // pAdapterInfo->Description 是适配器描述# t- k h- L5 `
// pAdapterInfo->AdapterName 是适配器名称
2 }' B- L% _" C" P% @1 ~& X }
8 o' n% |7 X6 a( e+ g pAdapterInfo = pAdapterInfo->Next;
( @6 r g, `0 F" I5 H }while(pAdapterInfo);
! O: u Y6 x( j; o2 j3 Z/ _}
9 `/ J& p8 l2 C. Z7 @delete pAdapterInfoBkp;
J' m" _" Y! i. V5 {
. `7 o6 L$ z2 F3 s7 N1 |* v1.2 读取注册表取得适配器名称
' _: U* I' @% B5 r: ^2 d
! G) F/ E7 c6 |7 `; R" C在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;2 t8 C: b4 L" n% ~3 e
9 C, Q, y2 F2 v
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 ~- ?& v2 m, q# @ `
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",# }8 G2 u. e( m9 s) Q. Y+ a6 _" x7 h
0,% A u* F4 |. K7 |" T0 m, K
KEY_READ,0 K. a3 c9 {* @& i0 [" o W# y
&hKey) != ERROR_SUCCESS)
6 O- k- @% F" \5 l- x; C return FALSE;+ l. Z( B5 Z' \5 r
' x/ `0 X0 I! E% h7 s2 e
DWORD dwIndex = 0;
1 T: c& |3 L. rDWORD dwBufSize = 256;4 J/ C2 o/ h* ^" B
DWORD dwDataType;0 V4 `( ]) y! G6 t
char szSubKey[256];* \3 \9 H. X6 P. d2 E5 x- a, x9 }
unsigned char szData[256];
: C7 ~9 H! U6 b, N/ W4 e
( y* h9 H' \- |0 Jwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)3 v0 o& H+ @! a& G( W) w
{
6 k/ y+ @2 Z( a; Q" r# u0 V3 } if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS); ]5 J$ z" ]6 S; O& c( |
{ # y6 i* ~( b4 T3 |* l
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
& B6 e0 E; I9 ^" n( P; x2 b' \ {) s! R6 b+ b5 T9 L% f Q
dwBufSize = 256;
; e+ g+ A4 F# k( ?8 O# _ if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)5 ?2 n6 x" S( I0 K7 v X# C
{, j# d' f5 m, T' e3 E% i
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
% _6 Z- {" C# E/ ]6 [. E7 h {* l, A! g2 r( Y- B
dwBufSize = 256;
+ R7 z# X/ g- a$ U+ p, c* C# a$ r! C if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)' ]2 N; W0 Q/ R6 C7 x3 M2 R& _2 z% g
{6 v1 N; t2 g5 k5 W( `
// szData 中便是适配器详细描述, V" x' m' D* U
dwBufSize = 256; G# o b$ M$ z& @
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
2 c. h0 Z0 v5 G* J4 j+ m9 X+ q- y$ D {+ s: E4 f0 F4 t; y
// szData 中便是适配器名称$ u- R2 W- B2 z; Z8 }7 q
}
: a. f/ H/ ? E9 o/ Y }7 \+ t) e$ L+ P: O
}
$ w8 c" x5 C9 p! a: X/ r( M L }5 p* e2 x2 ~& ]$ A) u
RegCloseKey(hNdiIntKey);
; f' M. T7 h5 U1 H# N }
$ C8 N* }: e% a) l RegCloseKey(hSubKey);
5 N: K) w- x5 Z; d! @+ @& j }- k Y* V$ E# X; s) n
4 b" i. c% W, Z$ u* V; i1 ^
dwBufSize = 256;( p& J8 N' J+ T. {9 p1 F
} /* end of while */3 h1 J& W. b$ W! w, M
) c) f) m7 F/ y: @RegCloseKey(hKey);" Z L( v6 w- s
二、将IP信息写入注册表$ e1 R7 a7 {9 M( R5 E- j5 B
5 E7 ~! g8 F& a7 A/ |1 O) |7 B6 ]6 C代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)8 \* \2 \# N/ y- [7 z& F
{
L; o4 c) s. d" Y+ G HKEY hKey;
4 J8 \2 C, E w" p string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";& _7 w5 g% V% j' r. N! L
strKeyName += lpszAdapterName;! u, U0 u) e$ R' H2 U# I5 n
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,/ U* v6 j, Q' _. _( n: K1 x1 T$ E5 U" v
strKeyName.c_str(),: P7 i( m) d0 [; l$ l
0,
, R- J1 X% F V* c _: X/ a* J- r KEY_WRITE,) s5 ~( P+ P7 p6 A% S
&hKey) != ERROR_SUCCESS)
" `6 N; \( X% p1 a5 @ return FALSE;* m7 b, o1 n% \( U6 d) @% \ O# w
2 t' g( @) K7 P9 U: q char mszIPAddress[100];
$ U! t0 X% U( ?# h2 T7 o char mszNetMask[100];
9 M- K- T4 O# w char mszNetGate[100];
) Z9 X, h5 R5 S5 r9 m
- K$ W7 u5 M. {9 _/ K9 X4 r4 ] strncpy(mszIPAddress, pIPAddress, 98);$ e3 F) x5 x4 G) C% c6 a* F
strncpy(mszNetMask, pNetMask, 98);
$ O5 L- E- w! f strncpy(mszNetGate, pNetGate, 98);
) F7 ?# S! y/ {9 z( z
+ g0 u# t! }( V; Y/ \: k int nIP, nMask, nGate;
0 a/ x9 g. s( r; r9 {3 N h; R
nIP = strlen(mszIPAddress);
9 D9 F5 A: u+ E4 [ nMask = strlen(mszNetMask);* V* L8 X' ~. e! D5 A. X3 h
nGate = strlen(mszNetGate);1 A2 B+ @6 U1 v+ ?8 C1 z8 o
p6 K6 l' j# } E6 l *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个05 O6 x) J( x1 o& M
nIP += 2;
% {; e" C! G8 E' D4 R, U
" g1 J. ~9 y; y/ }8 V *(mszNetMask + nMask + 1) = 0x00;: M$ K; _! w" o: E; L
nMask += 2;) K# d+ n$ A9 ], i2 P" k: x
8 c% Y& U$ f) e1 M% k( N
*(mszNetGate + nGate + 1) = 0x00;( S' s2 s: O) r; q, Y" b6 d+ S B$ v
nGate += 2;! {, H6 Z0 n: ]! x
S- d6 s; n7 Q. K' @ RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);, P0 f, L4 C6 F1 ~' ^; I. p
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);' _" L3 ]; }% y. z
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);: n6 o; ]# i& j- ?
( n$ w/ ^: Q) g RegCloseKey(hKey);
a1 P4 \! c: \6 R
+ v$ B/ Q$ d* U: E( L) \$ j5 f return TRUE;
1 M1 S* M' f* ?# X}0 M0 H C: b A% ~5 w" Y; D& Y4 w
2 }1 h+ p8 ?$ F. I6 {/ j三、调用DhcpNotifyConfigChange通知配置的改变
i' e5 D, K: o( |* f$ ]7 ^& ~) \4 G( x7 z8 {2 ~! `
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
4 n9 u2 ?# f( u4 {4 n: T" k3 K LPWSTR lpwszServerName, // 本地机器为NULL1 c7 X+ ?' w2 E4 I$ Q
LPWSTR lpwszAdapterName, // 适配器名称
% Q h1 n/ B# d: d S BOOL bNewIpAddress, // TRUE表示更改IP0 `. v: v+ Y8 E
DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
% V" ?% E9 V4 N DWORD dwIpAddress, // IP地址, p# X' t# A* ~. B/ K8 X
DWORD dwSubNetMask, // 子网掩码
$ Y! ~; } L7 x& \) R int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP5 K+ E- _7 ?, T6 b9 G+ {
% X, T( T4 M* E: A5 K6 U5 M具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
8 i" m5 ~8 |5 d8 y. C# ]{
0 d p8 l j- c% m: a1 s" @ BOOL bResult = FALSE;+ z! E3 K& |2 |4 i
HINSTANCE hDhcpDll;
# d/ F3 G7 R/ ^% H- I" q O DHCPNOTIFYPROC pDhcpNotifyProc;
* e* e' E; ?1 |" o. G0 F8 U+ ]) n7 u! p, \ WCHAR wcAdapterName[256];
& V1 ~' T# V# c1 Z
8 V. M2 D/ j7 @5 ~ MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);0 B6 h2 Y [# B
% T- @/ E9 C9 R9 @& ? if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
$ K1 S: |$ q' b% ?8 d& x return FALSE;, g5 N1 R# U( G- z
1 T9 X- s( ]9 b; X: \ p if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
2 B; B# q& R, y) k* O if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)0 v9 @! I' G: G! x* n
bResult = TRUE;
: Z4 k5 U9 L: v, _/ a% p8 p% m4 ]+ E/ j' Q$ I# J m6 o
FreeLibrary(hDhcpDll);
7 i) a/ J) @$ c2 h return bResult;; f, t3 O7 ~ E6 U' V( i
} |
|