|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:* o' ^" u+ f, R) R$ A8 t
/ t/ E) R3 c/ Q" r' [4 Z, u3 d
一、获取适配器名称1 z( b2 y* A' @2 x. q! L9 f i2 E
+ H, I8 k6 R! v2 K% p# ?这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:* c S7 E1 y5 Z7 P6 [
- I* k+ C2 I; Y: X% Z1.1 调用IP helper API取得适配器名称
" f2 |& J9 E7 q) X9 D3 v: F) E5 x2 O$ y2 {6 ~) i
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
4 Q2 |/ L9 L; G; C2 a, YIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];- z2 \( @# a7 |/ z |7 u" ~
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
$ ? l1 W6 |2 h7 u$ |7 p8 e{
4 I. \5 b& ?- O" z! R delete pAdapterInfo;
! A# f: B& j" I3 q* E pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];6 @+ v- a8 f* |0 H5 L9 C4 g8 s
pAdapterInfoBkp = pAdapterInfo;' c( w2 g0 Z1 D3 {( D5 r7 Q8 `$ p
}
7 B/ C" w; F7 W( M: I! Nif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )$ H4 I) d9 s$ N
{
' Y+ E- O0 ~2 E& b5 h# I8 H, u do{ // 遍历所有适配器
: X# a' \+ F3 \' K8 v4 J if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
* f4 c- v, J& T/ p# b4 J' m; [! i {
w) {8 w) C: e" M // pAdapterInfo->Description 是适配器描述. R& i; H2 `9 G# t
// pAdapterInfo->AdapterName 是适配器名称8 z, l' X1 W* |
}' k1 ?- V7 c0 h$ b; A! m
pAdapterInfo = pAdapterInfo->Next;6 V$ v* a, B# U/ Z) p
}while(pAdapterInfo);
4 l; s" J# }6 ~0 Q* o}
6 Q, c/ M; C) K& K. rdelete pAdapterInfoBkp;6 v& B: y( z4 l h
0 {9 w: F$ d) ~; d& e( u+ |5 J1.2 读取注册表取得适配器名称$ t; r7 b; [" Z! L
% `1 Z! h# c, l) `3 ?5 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;+ V! M4 S: f- y& K
# Q3 G$ x, w" m4 h( C
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,, b# i' o7 u6 {# k
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",7 v+ T. I: z0 _5 F
0,
3 r- R9 c- }5 H5 _% v4 v* [ KEY_READ,
1 L7 I+ U! j! y1 O" H; T &hKey) != ERROR_SUCCESS)& r; D D9 v+ f" f
return FALSE;
0 ?, z' l1 J, i8 c
$ _5 Z9 ~6 I8 L1 @DWORD dwIndex = 0;0 `! l: M1 v- z$ P9 `
DWORD dwBufSize = 256;
6 J3 _+ O7 B! A$ wDWORD dwDataType;
8 @3 Z) y9 x) @1 i$ m) j2 \. schar szSubKey[256];
9 b5 [0 L0 c' gunsigned char szData[256];
$ j9 ?0 A- i( W. H+ S4 @+ W) A! A1 U% p% S( w I2 X
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
9 i$ X4 |6 D2 P9 H$ F{
) m* P @9 d# a2 I if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
* q* d: X$ q! f { 4 S7 X) M. @* L3 G0 [
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
$ M2 w. g* @$ A/ c# s- l$ T {
6 v: Z1 r" ^- Z8 P$ w) v dwBufSize = 256; s: T$ g( y' M/ [; U+ i x
if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
! l1 S9 D0 E5 V% M9 _9 u6 n {) s( U( Z' }# q
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
2 }7 Q( z( T$ S4 ^0 q {. N. Y! V; h( G
dwBufSize = 256;+ N( E+ z; \; M' v5 T$ h& ^
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! V3 ?& P+ H L+ S& w& }# w
{
. f7 Q8 @; n( h // szData 中便是适配器详细描述5 h; M8 `6 c, `- ]5 J+ c9 f% f
dwBufSize = 256;
: g9 X. ^& j0 b, _ if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)3 H. V1 [/ U/ @/ D- M
{
, c" y& d% p1 k" |) w* D // szData 中便是适配器名称& N! U! u* S' V6 W! j* z/ q7 u* `
}1 x5 e [4 l B
}5 x ]! Z$ i- M3 { s D1 k
}) [6 A1 w; {7 C9 L+ e: @5 C9 J
}# d$ y5 e3 b" R
RegCloseKey(hNdiIntKey);
1 Y U5 ~" D) @6 ? }
' z8 s. d" R, a& S" e RegCloseKey(hSubKey);$ l! m2 r- J# o- ~( I1 P3 Y: K
}
v: p% y- n) S1 O3 D8 G+ A0 k) a6 J8 t
dwBufSize = 256;4 P6 T' u7 ~. M$ h6 {+ {3 G
} /* end of while */
5 d9 f: @2 E, f$ h
+ p1 \# {6 G5 X$ G) b* J7 ~0 [4 t& gRegCloseKey(hKey);
3 O! J x- N& R9 \, ]二、将IP信息写入注册表
. m1 N$ } w9 k5 A7 g; f1 W, U. s% M$ {0 v# f* P7 o9 P1 b- N0 k
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)% V) d2 [5 Q+ m
{
; m: C4 b. i( S6 j HKEY hKey;
3 ]# B9 M4 d& w" z) ^( j string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";) f `* @4 `9 j; [- u
strKeyName += lpszAdapterName;
6 N$ q; t6 ~/ R& `( ]/ ^( y if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 ^, i& t) O- C* E
strKeyName.c_str(),
: z9 D( v- Y0 _( g% `# e4 p& P; Y 0,+ V$ S5 R" h* v- i1 A1 |% {( \! C
KEY_WRITE,
- Y b! k4 J3 \) W: Z5 t &hKey) != ERROR_SUCCESS)
; N& q \% \ z( B1 t5 d return FALSE;
) G7 ]* F0 o% ]8 k3 a& [+ ]
4 f/ K- O- P1 T, D; a char mszIPAddress[100];
& L/ C' A1 m* c: _ char mszNetMask[100];
* e7 S- ]* G7 g, p" L6 l' J5 @ char mszNetGate[100];% q8 j4 c4 `; k' d# O
3 {' F u. f0 [) Y1 f
strncpy(mszIPAddress, pIPAddress, 98);. K: g$ U: {' r6 v0 X: P& d; F* i4 A
strncpy(mszNetMask, pNetMask, 98);
; w! P, }9 Y: d" `' C; `- c& t7 [ strncpy(mszNetGate, pNetGate, 98);
/ z' ~+ p' Y8 w& e1 j$ F
1 S9 ~7 J% \# Z, [* B; M int nIP, nMask, nGate;
8 Y$ k0 f6 B! L+ y: `' b+ L& ?' O, `; q, ^9 N& x) N
nIP = strlen(mszIPAddress);
* N7 k8 C4 w: c2 t+ P0 m nMask = strlen(mszNetMask);
5 O3 E9 {% o' C4 b7 n8 q3 { nGate = strlen(mszNetGate);
$ ]" _4 f; R5 | V2 G. Q) P7 K4 A$ X) M" F8 @
*(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
7 `& q7 ?. n. A nIP += 2;
- C8 l% Q" r6 u, Q9 t* G: q6 e
" u; Q4 z& P0 G- U *(mszNetMask + nMask + 1) = 0x00;, `4 u) X2 G# Z# w! u
nMask += 2;
4 n: n! l2 [4 V' |3 Q* F8 h4 y5 t1 n* W* v; y- _( g% B4 b
*(mszNetGate + nGate + 1) = 0x00;* d) m3 u j' H2 M
nGate += 2;# c1 y9 P8 u" j, \! R1 I E8 U
" a6 p l3 u* }6 a4 n RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
6 M8 U1 v# C7 k" s RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
; A8 q$ U( j! f3 {& U1 ]- L: T. ^ RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);$ ]. c K/ G) g/ `) D
3 B5 H4 {6 T4 M4 S RegCloseKey(hKey);
9 w1 t" J! ?' W7 a$ ]* H3 N3 _8 _0 ^% L t% K
return TRUE;- F9 z* E+ k7 r9 A% Q+ \
}
) \$ N6 ~/ t9 w# D' M1 i
& `& C# T( w$ I: S. V三、调用DhcpNotifyConfigChange通知配置的改变
$ \1 }, s& k# X% n* H$ X |% G3 N9 E' m! e0 p
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
0 w# u6 |8 M- k" z LPWSTR lpwszServerName, // 本地机器为NULL5 r, ?% |! T, w7 b/ W" J; `
LPWSTR lpwszAdapterName, // 适配器名称
6 `4 }8 k+ c/ r BOOL bNewIpAddress, // TRUE表示更改IP6 r( S! D* d% c7 p/ C) j
DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
: J: C) D6 h, n- y( E- O DWORD dwIpAddress, // IP地址5 ^& M% g6 n; ^
DWORD dwSubNetMask, // 子网掩码
W1 P* r9 s: R2 _5 S int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
8 u; Q+ }5 X; O7 e% d% N
' h/ G! [4 r$ ^8 o. K2 s! Y" i具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)4 S( ^* x" W% L) e2 i O$ D" S
{
5 x% s( X$ u, k/ M% M BOOL bResult = FALSE;
8 \9 O1 d5 `2 b6 h) | HINSTANCE hDhcpDll;
3 @$ U: }9 u- V6 w! n6 n( K DHCPNOTIFYPROC pDhcpNotifyProc;
5 E* U4 d# [; H" v) @& j WCHAR wcAdapterName[256];1 i! H7 `- f' \
$ ^) ^3 l1 s4 v. g" @2 q MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);. L3 G( e8 D2 [$ V
/ ^. M$ z0 g& a i2 V. G if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
. ]# P! S" _" m% f" X0 D" c a return FALSE;
8 y0 y. u( H- m0 t( b0 X' a& D+ |0 }2 M0 A( O2 ~+ C' u
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
% w, V) @7 u1 {! Q3 Y if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
, Y* l* F/ e5 B2 x+ X bResult = TRUE;# ^8 Z P# h# g: s) e
: V; V6 @4 Y& j n
FreeLibrary(hDhcpDll);, z" }0 { p ?* b7 \. J* M; s
return bResult;& p6 z5 ~# Y7 u4 }. X
} |
|