|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:# `2 x3 F3 N, R1 U
) h! g0 x3 c7 |一、获取适配器名称' Q6 w' O4 Z& E
|6 I+ B ^) T( V, u8 X8 u6 s3 j
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:% f: p q! @5 m, \7 m
7 z# m4 N) A; W3 O7 I
1.1 调用IP helper API取得适配器名称
! ^! O# c5 q( B0 i8 v% ^! R/ v: X4 e/ b0 m
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
* m7 `# c: j8 J' j; X) XIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
0 I; W; b2 o& O) f' `9 ~' E& M! eif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
, ` Q8 M2 o/ Y{) H: @. f5 T" D1 r- x+ p) }
delete pAdapterInfo;
( y- G4 i1 u" O/ n& f9 b6 @' z pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
/ o, O2 u8 p6 O pAdapterInfoBkp = pAdapterInfo;/ C7 x- S$ t. E1 b X
}" f3 e7 S1 w. C$ C% z+ g, c
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
& g3 L$ P1 x }/ x{
+ J) p0 B) V! k: }: h O: J# a* T do{ // 遍历所有适配器
; p3 _* Y. m7 Q( u+ r1 o if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口( Z' {3 G" v& }% W& g" v% V
{
/ O+ [/ J- L4 N# R$ p6 X6 Z6 H // pAdapterInfo->Description 是适配器描述
& a: I' Q7 z2 Q) I5 k2 a; x& W // pAdapterInfo->AdapterName 是适配器名称
: T; `4 m* \$ R' ]8 ^ v: t }: b6 P4 Q3 J1 {1 n7 x+ @+ Z, F y
pAdapterInfo = pAdapterInfo->Next;
% {) M7 o! K% |! J }while(pAdapterInfo);* M# f& R* n9 |, w5 M/ O# \
}
, \, F& W: Q. o2 O) M ]delete pAdapterInfoBkp;& `. p$ `* c& ^+ Y" P; }
o( P# d+ }( ]/ \1.2 读取注册表取得适配器名称( K2 s" r9 E9 h" x
- \: K* y( f, u! ?( w7 J在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;
% W: h( @- n% V& m
2 h8 E* M( ~1 c) e1 M: j3 Yif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,- U1 A# M* V2 [ R
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
* y! x5 D4 P+ W+ t 0,4 @4 q5 m: ^& |" V0 f6 S! D
KEY_READ,
! Y4 @, L1 e& F* M# j w &hKey) != ERROR_SUCCESS)
2 w o' d7 A, r1 n& ?1 [ return FALSE;
8 C3 b& Z! }& y2 A c, y" V
# P. g) I' c" L; ODWORD dwIndex = 0;
8 G8 @) g; T+ q) `$ m9 bDWORD dwBufSize = 256;
% `) r' `0 H0 s8 ~! ?( a, ^DWORD dwDataType; r" i1 E( ? U# ~& Y' D6 r1 [
char szSubKey[256];
- ~8 J- U, @' X7 S* tunsigned char szData[256];5 f% _) l% @& N r% d o+ _: N: @8 @
& Q% y& a9 I0 A" g8 S
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
4 ^; ~2 k4 J/ C6 e{
' M8 G7 L9 Y+ T. @( z if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
- E- m' D! y) `0 i, Z {
+ C) W/ H: S( s0 l" ~9 j8 s if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)* ^2 K# p/ Z5 @3 p4 C. j
{
1 [6 k/ W5 E6 d M3 K5 U% L dwBufSize = 256;
' ^7 Y x. X! M if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)) Z. ~, C) T$ p8 ]" e3 u. }
{
4 N1 {" Y4 V, e! J3 I! i if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡& z, o* k8 x# a, I B! U
{
* I: A8 b) ]2 Z- e+ |' b+ k& c6 ^ dwBufSize = 256;
( {) U% t1 K0 h! l u/ ~ if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
* k2 u* d( C* \) v {4 t/ [# s! d; M: J7 M5 p
// szData 中便是适配器详细描述+ q' c& m0 n/ r% P1 E* ^7 t. ]0 Z
dwBufSize = 256;# U r3 Y- a/ W0 I _
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)9 J2 q/ O7 H- T5 \5 h+ L* w
{. M& {$ z1 g+ m' P2 V5 q2 i& B7 E
// szData 中便是适配器名称
/ i+ {8 g5 ]4 L5 D" E% S1 z- u }
# Q6 v/ w- o! _# P4 s }
/ V9 x3 M$ d6 N8 a4 f }. y) d9 q9 J( U/ N# @! K, Y u
}
. ^% l1 A+ h. z RegCloseKey(hNdiIntKey);4 y# F a. T& F! p" t& D
}
: X+ x8 C- t/ y0 H4 }+ k* s6 s; G RegCloseKey(hSubKey);6 J# j; y5 B4 k; k K9 {8 s u& d; r
}
( Q! X+ f7 _4 C; X; Q+ v) I! G9 _0 f: Y4 P/ y! t* c+ S6 h/ a& g8 b$ h
dwBufSize = 256;' n# y; B2 Y) }; Y# {
} /* end of while */
3 j" |5 r+ \# ~/ q! }% ^6 z' {
1 }( C, e/ ~7 _; d: l {RegCloseKey(hKey);" X' U9 y3 M, A* G, m% D1 I
二、将IP信息写入注册表
{, g. J' n2 e6 {/ b9 u" e, R6 B( j4 v x
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
0 `+ M; G' U7 ?6 d. c# \" G/ m{
+ ~8 n7 S) I3 n* j A9 m m HKEY hKey;$ ~) j0 \5 R8 O0 i; n
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";+ u% u9 C, s0 l0 O! h( V! P# u# ?
strKeyName += lpszAdapterName;
5 X% K/ @- z- U if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,$ B% j, R8 {) p$ S) r& v! `
strKeyName.c_str(),7 b, a0 b* e/ Q: }; U; W( U
0,
: }, e7 Q; g# A KEY_WRITE,3 K* }7 l( h' L6 z/ y+ r0 F
&hKey) != ERROR_SUCCESS)# Q5 t K$ \9 i3 V; W; e
return FALSE;6 N! K4 Y3 O( n. o# m
% ?6 m0 W& a; n+ F5 w
char mszIPAddress[100];9 H @! C8 k- `) X, }% S1 V. b. @
char mszNetMask[100]; O# ~4 k; t# z u8 C& I
char mszNetGate[100];7 u5 O4 \1 `5 c2 F9 v
& T j, I- K+ J strncpy(mszIPAddress, pIPAddress, 98);# [/ {; f) z6 X6 q. @& B
strncpy(mszNetMask, pNetMask, 98); m% {! g3 X, m0 Q1 {- H- I6 @% T
strncpy(mszNetGate, pNetGate, 98);
% f' c, H. o4 y2 V) L' T* O: |; k, w Y# ?" a+ V
int nIP, nMask, nGate;
1 ]- V4 z+ r0 Q# s4 d
" ^3 `7 \8 `. g) u. } nIP = strlen(mszIPAddress);% a2 P5 H/ Q! H$ R) t
nMask = strlen(mszNetMask);, C" O( P. J: Y1 D
nGate = strlen(mszNetGate);; q" Z5 G2 h0 u+ a' v7 S! \
d0 J% J" i6 @) V *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
7 N4 B7 `9 H* B! }6 Q nIP += 2;
2 u7 y' X) |. f$ t$ p& V6 z( L0 V$ H- ~7 |
*(mszNetMask + nMask + 1) = 0x00;
* T3 H" W( z& ^0 S2 x nMask += 2;# I# h4 t9 C9 [0 W. f! C/ n
" H% ]* @" m- @: L0 z2 S, a4 @- @
*(mszNetGate + nGate + 1) = 0x00;
# L A6 B/ v* u: j$ I8 T nGate += 2;
: i9 A' u! K0 G4 I: \/ }: S& l8 S ( J# t! u2 w' X2 Y* G& M, L
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);, {* ?% M; I: _+ ?/ s8 f) C
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);1 c, |; ^! U; f6 B' G5 G3 I
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);& P5 o! u5 ?5 s
: m: L/ F; L/ Z- p0 D% T RegCloseKey(hKey);
2 {( y- p5 b1 e! j) k4 D& r1 A$ Q9 b; e3 v/ Y9 j
return TRUE;' ^, I8 [/ I. q6 X/ `7 J6 j
}8 Y) H+ d% B d- S' }
( L( P: C# g# ^% O* F0 f- i* M
三、调用DhcpNotifyConfigChange通知配置的改变: x- z- G! x# @# }, B
. x" Y1 m: x& s g+ ^未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
+ ~; m( K2 r' r' l1 ^ LPWSTR lpwszServerName, // 本地机器为NULL( P% i) ?- d- i, G7 x
LPWSTR lpwszAdapterName, // 适配器名称1 f; G1 ]8 i5 y9 N" c' o
BOOL bNewIpAddress, // TRUE表示更改IP
1 Y3 ?" m- e( z: D* v DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
* E6 i( G; t& T9 n DWORD dwIpAddress, // IP地址9 O; A' u' l$ K) {% u
DWORD dwSubNetMask, // 子网掩码" X, [- E0 `8 e: _+ C: N
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP8 @ N, h6 K( l- H2 H$ J0 o
0 ~% k8 q8 L X) @4 d具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
( v/ R8 u6 _* s{& P! Z" j! }$ H& ]6 O, w
BOOL bResult = FALSE;7 `: F1 ?5 @. O5 x/ M
HINSTANCE hDhcpDll;5 ~. R% @7 q+ M, S; A) g0 A
DHCPNOTIFYPROC pDhcpNotifyProc;' l+ j, J4 ?' K% g3 K5 t! Z* }
WCHAR wcAdapterName[256];
9 w8 S6 g1 g5 {2 t2 c" ~ % @" @5 X1 I- U" M" J7 ~
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
1 ^$ r: y" c6 M1 ^& \1 G, c2 c2 q2 b
if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
. i# L$ I' f& j) @% K return FALSE;
0 j8 ?8 D: F9 |% ` M3 W
, C) n' T& e1 O/ S1 A if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
$ O5 ]& G- m& K if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)6 @* I) p. X+ t6 b; \5 A2 [# _
bResult = TRUE;. R# g. q8 e, w" [6 Y" O& {- f) @
$ |) y' g: J8 E( l) [ FreeLibrary(hDhcpDll);- H# J5 X' X& ^1 h2 J' v# [% l* g
return bResult;
% u: x3 [3 w& T} |
|