|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:" `7 v5 H3 B; v! C5 J
% p4 i0 y/ W0 m* n+ P5 X9 n5 G1 q一、获取适配器名称' T& ]- P) e1 b! b/ L5 i0 D8 q
0 Y: {4 ]7 U3 T
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
3 E8 }' k: t" I7 o6 I9 O' y! {9 v8 g' k$ K
1.1 调用IP helper API取得适配器名称
$ B$ w: O# r& y
" V& n) N2 ~1 P! OULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
! ?# X* {( \" Y4 {IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];& }3 _( q* O c/ a' }/ F( f
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
/ C& Y. F4 E/ Z6 w j# |- q+ S{
8 e. C p/ M; m delete pAdapterInfo;
# L T" H* F& T8 p9 d k+ N pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
: ?) G6 q/ J! z9 z* S) D2 a pAdapterInfoBkp = pAdapterInfo;
! n1 f" g% e: ^0 D}2 i8 u) O R9 x% \) Q
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
; l0 c9 [" q, `- w2 A( j8 Z) w* r{5 t8 g5 k7 f' Q6 P% m6 w' T: M8 J% \
do{ // 遍历所有适配器6 d' W& N) l" {5 B
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
) I: T& a9 j% b+ w7 g! {, { { {0 F( K5 ^/ ?* C* Z
// pAdapterInfo->Description 是适配器描述& D) \6 y w- ?; v6 p; q
// pAdapterInfo->AdapterName 是适配器名称/ l" y9 ]% r/ t% v0 K [
}% D4 H# [9 e! N) j9 A$ M% A; h
pAdapterInfo = pAdapterInfo->Next;# C `+ ~7 q" q# ~) K1 R0 Q
}while(pAdapterInfo);
# _! L( o% w8 h3 [3 F) a}2 I8 C; Z% e3 {, V( l9 N6 Q
delete pAdapterInfoBkp;
6 s* ] Q6 r- U
& f; R( W$ R- K4 U; A" I1.2 读取注册表取得适配器名称
{; W5 q: J$ R, T. E; u
4 q# W! X& ~( o$ R" @在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; z$ Z4 b. J5 G/ i+ ~; m
- p$ E) C3 C5 o2 f: I J4 ]
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
! ~7 }4 [$ d$ J! A; g "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",* t% s8 o" f! o j7 x# C
0,
- T) M' z5 r, y3 v KEY_READ,; D/ I! \5 E v8 p7 `% w. ]
&hKey) != ERROR_SUCCESS)# O8 _ T* f7 a O7 j& Q
return FALSE;
3 j$ }9 a1 ~/ b# Q
' |2 n/ D" h# N% F: kDWORD dwIndex = 0;# R2 p# g% d4 m* i3 E! r: I
DWORD dwBufSize = 256;+ ^/ P. q+ @! U6 C3 k: ?( S6 u
DWORD dwDataType;% I! O6 q6 ~- {: o e
char szSubKey[256];$ T% l6 B3 j4 X I2 b0 ~' n$ I% r
unsigned char szData[256];
" Q" e+ ^* u1 }2 L5 v1 u% b0 C( R4 \) P: c$ K
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS), w1 r' {4 u+ ^8 R6 j# P
{. ]1 q* f* r5 g3 A5 H# [
if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
1 ]# [, E+ K/ ~( P: z { / A0 Y, Y, V x% k
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)# V" Q" r: O% `& _8 q8 W# T1 a
{3 X: y3 L( c) U% |
dwBufSize = 256;
. Z/ U* o- o/ z% E. k if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
; ?+ Q I" K: \: U/ N0 D {
# ^% t/ Z) B# Z: k) J" `7 y if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
! ]8 |1 r6 k) e1 L) N {- ~ c9 q6 f# S
dwBufSize = 256;$ B# W6 ?' S; y/ i+ O
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
& A/ f; S+ t" h, [. K1 D& G {
; g; o1 S& [ L+ }! | // szData 中便是适配器详细描述
" d* ]3 F% t9 f& t) t5 Z& S9 U# f dwBufSize = 256;8 t) t; r- `- E# p8 q/ U) x. \, z& I
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)4 n( ^" V$ I4 b: d+ s
{7 ~. A n3 r- C/ x( B
// szData 中便是适配器名称6 @9 x7 n1 [) J% |: j1 V( _
}
; e: H+ A0 L/ D }
' ` T* k; O7 o$ X- J }" P9 [9 z* K2 U$ J; x, ~
}+ |% |" w- @5 R0 A" ~9 f; ~
RegCloseKey(hNdiIntKey);
' j! C3 i) y; L& f8 _, [( V5 b7 N }
: d4 D% B& A- V7 b) J/ l. P, |- O RegCloseKey(hSubKey);+ E% ~5 T4 R2 ?( d1 }
}" j! O6 Q2 C+ I |, J6 S2 }
( [" G9 S: H# f: |
dwBufSize = 256;
# N5 u4 A2 Q; M3 E7 ]} /* end of while */
! x# V, d9 o* S% u4 B . ^, z( v0 L( @
RegCloseKey(hKey);! M4 D) i" O. Y
二、将IP信息写入注册表
0 @$ O% f% J) h g z6 ]% I3 w S) ^
0 G' C+ F8 t! ]& x代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)# H) p2 C1 h) T0 P
{
& q9 S3 o8 U% o1 a8 A HKEY hKey;6 |" r. w' a4 c" Y+ m- e( k5 Q
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
6 Y9 q: K% H* A: n# t8 p( T+ |' O strKeyName += lpszAdapterName;7 b6 f* \5 P; Q4 T) S0 F$ U2 Z
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,2 J+ L8 I4 F f" c6 O) ]& o
strKeyName.c_str(),
) D! s1 b' v6 P 0,
) I% }; Y q; A KEY_WRITE,- G% t, k. j V8 s% f. a3 i
&hKey) != ERROR_SUCCESS)
3 \$ L0 G$ |& ^& I return FALSE;. c1 V6 N* o- `& {
* q' H8 P0 R4 H char mszIPAddress[100];& P5 W) F H8 |& r2 o f' |$ ?
char mszNetMask[100];; }$ J; _! X$ `8 i3 y: k2 t
char mszNetGate[100];
/ q) H+ n, n2 x+ k; {
6 f7 o. U9 z' i5 E strncpy(mszIPAddress, pIPAddress, 98); M) S+ B0 P& |% `! @5 I j
strncpy(mszNetMask, pNetMask, 98);
6 P' R0 Q, V) M( M% A! J( B strncpy(mszNetGate, pNetGate, 98);. S* D( Z4 H" r6 O" B
- b: ?0 n1 T- n6 }/ {" d
int nIP, nMask, nGate;& A5 n6 y* S" ?. }7 ^% ]
8 B% S1 H/ g Q
nIP = strlen(mszIPAddress);( c8 u4 P( t* O8 [) y4 `4 D
nMask = strlen(mszNetMask);$ N6 }7 l+ i( j5 H4 V1 l5 L5 {
nGate = strlen(mszNetGate);4 g1 E. A0 N3 A' N' n# X
: X( }/ n( ?: Q# H) G: d
*(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个08 k1 u3 h1 A: A
nIP += 2;( j0 x/ v. b4 {+ J
5 H$ G4 a9 f- W. j% o
*(mszNetMask + nMask + 1) = 0x00;0 D! w; U) X, W% X! S' I
nMask += 2;
, J7 ^! T# M% Z( s1 j. g. U/ p
+ M# b( H: L# K" U+ l$ _ *(mszNetGate + nGate + 1) = 0x00;
9 B3 M& ]3 A6 K$ W/ u3 @5 H nGate += 2;2 k8 c0 S* k9 ?& @6 O( k
6 z3 H! I' P9 u8 W: z. ? RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);- \' r! ?% j' C( q7 y5 O1 B
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);5 j% V# p: v1 f8 I; s7 C7 f
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);& P( ], k1 t2 q5 [
6 o' W$ j; l) C& b RegCloseKey(hKey);
' n& Y1 o/ U; {) @
! J7 q$ e0 F4 o, c" U3 g return TRUE;
4 G5 q# U" ~7 t: U6 x; q2 `}; S' j4 I9 W7 h5 M: H1 t
2 U ^6 V: c. w) ^ w' _
三、调用DhcpNotifyConfigChange通知配置的改变
/ K6 q- o6 s( C2 T% B/ ?/ ^! I& |; A0 P( v/ m9 D
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
& {6 p5 i6 y" _& R) d LPWSTR lpwszServerName, // 本地机器为NULL
. T, `9 Q" V9 \4 G+ E! d& J LPWSTR lpwszAdapterName, // 适配器名称) m6 j! u3 Y7 ^" {6 _8 |9 L0 N
BOOL bNewIpAddress, // TRUE表示更改IP5 l( Q l5 ?7 G6 X9 m
DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
$ P7 A. O, l( [2 l DWORD dwIpAddress, // IP地址
* d4 |: h0 {) O$ l DWORD dwSubNetMask, // 子网掩码7 f5 i+ n5 e( ^- W- e* c# h9 h
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP: x. {9 B4 }8 ~0 W- b b j
2 ~5 l+ T1 p( X' m. |具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
* }. A1 V* ^1 g% ]; f{
+ r) }: s3 k' D( z7 s" u BOOL bResult = FALSE;7 m3 p, x% x* d) J: W# U
HINSTANCE hDhcpDll;
" i+ U3 u, w4 i A2 q. b" Z DHCPNOTIFYPROC pDhcpNotifyProc;
- j, `4 |8 o1 G$ `9 _0 k! `9 Y+ W0 ? WCHAR wcAdapterName[256];1 |5 @" w4 o% W6 B
" K1 z! x5 u7 }8 Y) @. X4 k
MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);6 o$ d D0 b( n; ^ Z# ]) k
4 I1 D: h4 X3 ^/ X- Y4 q$ ~5 b if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
, k" \# a: K4 B( o P ?# L return FALSE;5 Y) v5 {5 e, q3 G" Y6 b7 [
" D( B. _* _% s) w if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
4 W V j6 S( g0 `4 H( T if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)5 D( b/ G- k/ M6 T! R0 U7 }
bResult = TRUE;
6 T6 S! Y: H) ~0 w8 f, l' n8 d5 ^' g
FreeLibrary(hDhcpDll);' t+ \; t! {& ?
return bResult;
# o! E3 |& Q4 Q( q. x( e: b$ f- u} |
|