|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
1 r4 `- |7 K( D/ `& R* d+ G6 B: \# H+ s8 s0 {$ W
一、获取适配器名称
8 K/ P; `0 L" ^9 }# R5 L/ ^ m" O9 F6 K$ e
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:2 M8 C0 O) d3 _8 [
$ x+ f8 s' {+ E+ u! A1 p1 ^
1.1 调用IP helper API取得适配器名称
& E- q3 T' `. n8 _: v- U6 Q% |9 k
1 i0 p3 O4 F& \6 ^ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);' X. \& x/ A8 B2 D0 e8 c
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];6 h# W; m1 U& O5 ~' [! o4 a/ ?3 i
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大1 ~ v# h5 V2 Q" U- N4 e
{8 Y( X' D- e9 ?/ D
delete pAdapterInfo;7 J) Y. ]3 d6 H
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
6 |6 P& ^, q$ K+ j' X& w pAdapterInfoBkp = pAdapterInfo;
9 ]1 a1 s. M' [+ k}5 b7 ~, a( m* ]6 q4 V
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
6 I; d& X J' d8 a8 F- }{/ P( F6 [" a; r/ f8 I$ m& O6 s
do{ // 遍历所有适配器
6 O" j) \% J% ?3 f$ h if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
6 n2 f5 q8 h! j# B# o& |# ? {& p4 ~2 y+ ~3 ~/ h
// pAdapterInfo->Description 是适配器描述
( R; A) r% s9 E# O( B // pAdapterInfo->AdapterName 是适配器名称
( B4 l; {6 m4 {- H9 B }# F1 m0 _/ S: R/ Z/ b& Z
pAdapterInfo = pAdapterInfo->Next;% J5 @% f+ D! ^
}while(pAdapterInfo);5 n! Y4 ^8 H, F% \' Z
}2 Z" X6 U) F8 j0 g% i
delete pAdapterInfoBkp;
# A5 {' c0 ~/ @5 n0 I3 y$ }" M& O7 u# Y/ m0 y# X/ C8 ^: m5 t
1.2 读取注册表取得适配器名称7 m1 g8 {" { [9 u
2 n4 K1 S9 N: P
在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;6 O% Y2 x Y; E
% @9 A. I" Q8 b$ T7 L/ Y# W7 E
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,% L# N6 @6 |; Q' ~( r
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
1 N7 C1 g4 L5 H! t, J* c 0,
" h+ U7 |1 U/ h6 U KEY_READ,
! Y, i7 a/ @# F$ o! u &hKey) != ERROR_SUCCESS)# `: p) g: y0 ]
return FALSE;6 H9 {) s. h+ G9 w
8 U2 ]$ L0 I8 t9 R
DWORD dwIndex = 0;3 }& @& f) }# W) ]* ]( Y* q* T
DWORD dwBufSize = 256;
: p0 [' n1 k8 d0 {) C: PDWORD dwDataType;
s" M# M6 S' G5 _char szSubKey[256];
/ F( T4 E. t# l$ m! Bunsigned char szData[256];
7 }4 |. F# T8 y' a5 B7 L1 ~
& n! ?' o$ b, Z! x3 Xwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS): v. a0 f( V! R3 H* \% t2 Y
{7 T: r. T$ j/ e7 _
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
! H7 P c E" i! M$ G0 g( Y0 O {
8 F- V7 R% c. T$ D1 T' I/ |3 `* [ if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS) r1 O! c1 K+ ^* Q1 G( D
{
. B& n0 s# c( A2 c. d dwBufSize = 256;9 g( f) y. q$ l: p- `' s1 Q0 W
if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
* i" Z9 ~6 s8 c( [" q {4 [/ n+ @" m% L3 e# \
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
! r6 p" X4 ~( [7 x; M" M {3 O/ t$ w. s' p2 x9 H
dwBufSize = 256;
* x, Y6 H; w2 B, p( [ if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
# D1 \1 D+ y- n9 e A {: a7 ?/ P/ b; ?, w4 O6 x
// szData 中便是适配器详细描述+ }* _5 n, v2 E6 c8 |( y
dwBufSize = 256;/ h( K8 Z+ L e* l+ D
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS). A" B! @ R; G; s' D
{
6 D; E, P7 n4 l& f0 f( r, G // szData 中便是适配器名称
0 d( Q2 N# N/ \4 e$ q2 N- l+ y }, C- U! V0 O3 b! @2 Q1 [- Y) W/ U
}/ c( }3 j( g: h( _
}
- K _/ k" _+ d1 B" Y }7 B5 E2 V; ^: j5 K# ?. l
RegCloseKey(hNdiIntKey);: L" r& e' m1 H$ H" `
}
- P- Q3 M; Z% F) w0 ]5 f0 M) c" N RegCloseKey(hSubKey);
) r3 ~1 \' S; m5 ^& t }
* T) _2 H8 X7 g' ^/ s) {1 ~- u, C7 m' T# ?4 K" H
dwBufSize = 256;9 e& c" y( Z& s1 D S
} /* end of while */
i: T( F# ^! c
' b; ]' ^* x& S! w! e1 lRegCloseKey(hKey);5 [# @3 {6 i9 [, [% K7 x
二、将IP信息写入注册表2 P) X8 e2 o$ ^1 a
. L# g7 x; W) X6 d2 x代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
) G5 X: ~8 t6 Y% V9 F8 t. P1 d{
% j8 }6 x4 k7 x, G& ? HKEY hKey;/ v1 J; `( g4 }8 ]# z/ |8 @! Q
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";( e, z& b8 z0 M0 Z
strKeyName += lpszAdapterName;
) ^ \: @6 P. g if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
( \7 O' S* Q# o4 a% a0 c strKeyName.c_str(),
8 R6 {" N4 }, d( @3 Q& e( M 0,
5 y% b* [; M, K, H( S KEY_WRITE,
9 H9 f2 j( S; a) x &hKey) != ERROR_SUCCESS)
6 U, m( W7 d1 E1 \ Y return FALSE;0 l$ i; ?% K, Q; v# e7 ?
3 P+ A; q9 z* @ char mszIPAddress[100];: T, ] y* `& n5 B( h+ A
char mszNetMask[100]; n- \6 ~9 _, \! X2 J0 Y Y
char mszNetGate[100];: U: W' x4 p$ f8 W6 H% H9 m
O8 |& q8 T0 R! p5 \ strncpy(mszIPAddress, pIPAddress, 98);
2 T" r8 _) [" J9 x strncpy(mszNetMask, pNetMask, 98);1 w9 b( h- r! E/ ~* _; e6 K( B+ z' K
strncpy(mszNetGate, pNetGate, 98); N; X0 a7 [: `; D7 |, y
7 x# ^( x' u( U2 y, G/ a& z! ?: ~ int nIP, nMask, nGate;7 O6 L% w) x2 ], h) H6 G
3 O. q# Y3 F; N nIP = strlen(mszIPAddress);8 U$ d$ V" }' }) u+ R
nMask = strlen(mszNetMask);6 {3 e% u0 L0 Q7 y( f7 o- L' K
nGate = strlen(mszNetGate);; U! V( z, Y! ?3 v3 X T0 I
- ~/ ] A" a! J6 W4 U *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0! C* o) x1 y6 D5 F% p; T
nIP += 2;
2 u% u M9 S$ Q/ n5 q5 F
, w8 f3 ~, L' e! i *(mszNetMask + nMask + 1) = 0x00;
1 X5 ]6 b( ]3 p- v nMask += 2;1 J! j% ^' g4 ~: }" Q1 i0 f/ m
$ I: K. I! g ?9 G" z *(mszNetGate + nGate + 1) = 0x00;$ z. v* `: q: m$ r
nGate += 2;
( L- R6 Z' o1 h' {) c
! n, O* A1 S7 |0 {9 M0 }# q RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
& K P; v! r/ a! H# H2 [9 S3 e RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);7 i' a6 T) u) j! j) M
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
1 |4 k% m( y* n. W$ T1 U
! x/ e/ G9 T& g1 k) [3 G RegCloseKey(hKey);
- S. R& e5 j8 |1 a9 H
, ?) w2 d; s/ J+ v return TRUE;
' E% `: v1 M3 x5 J0 n}- v- a3 k, c) b
k$ C: d( u3 k/ e
三、调用DhcpNotifyConfigChange通知配置的改变
' Q4 }; V0 M: M3 N* G+ R2 ~- }; [/ b3 D, s
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(. R! c: ~4 ^' G5 n$ p2 E; t
LPWSTR lpwszServerName, // 本地机器为NULL
. w; G+ B8 j; T( l% g& E LPWSTR lpwszAdapterName, // 适配器名称
$ f4 @& C5 D: K1 }; U) J& C+ C- L BOOL bNewIpAddress, // TRUE表示更改IP
3 |% @8 R& `! y4 ?+ S% @4 l DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
3 v$ F& V! R7 ?2 p0 J3 G: N- r2 K- U DWORD dwIpAddress, // IP地址
) r$ ~: P0 ^; v DWORD dwSubNetMask, // 子网掩码
5 U8 T+ y1 |1 }1 u) H int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP! K! y" L1 l: n$ V
5 f9 g# i" ^; q* K% x具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)8 i6 O- m8 w& v) X u
{
) |9 ?' _' A0 ` BOOL bResult = FALSE;' ]# h3 X' w' }( C* G3 I# g: Y# s
HINSTANCE hDhcpDll;
4 g- ]5 W4 c0 {. S1 c2 J$ ?8 i DHCPNOTIFYPROC pDhcpNotifyProc;
( v5 m. v+ q1 M: ?3 { WCHAR wcAdapterName[256];! [3 v. X6 z! z& O# {( D7 v. w& X
6 |% E. b1 s/ F
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
8 v( S% }" W7 m, ]( I9 j6 \- Y' {6 w. }5 `, a1 I+ K" b* j
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
2 n& T0 A$ \6 M; h/ i8 V8 E7 ?/ A return FALSE;
C" g4 y' c- t, t
2 N$ m E3 p# m if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
% Y( U, Z2 E C/ V. U$ \0 P3 j if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)% q# z$ M" Z4 K6 z7 t* @9 V4 R4 a
bResult = TRUE;
' I" M4 @' O$ \) G6 o1 b9 Q; [. o$ i7 `* d5 n0 b) t
FreeLibrary(hDhcpDll);
$ ^* W0 f/ A$ M8 n* j# B return bResult;
+ H) w1 T1 f: R% Z" g} |
|