|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:4 ?# K+ x, v+ [, S$ @7 L; f7 z: Z
! O, O4 e) S7 M8 U7 j一、获取适配器名称. ?8 ^5 m( d0 e. w+ \
0 m b. t% R( R* C3 A2 z
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:0 c( T6 n# u3 V+ y; k
7 |! a1 a8 e% R0 G. K: s1.1 调用IP helper API取得适配器名称
. X6 _) U9 R/ g
$ }2 a. Y V; q; F8 zULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
4 `8 `2 r# N, i6 o; ]IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];& v( j( W" u0 j0 f$ K2 [' i* U
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大( h/ _& b" I- C- \, a! M
{$ A. G; [* R" T/ [
delete pAdapterInfo;
" g1 b9 s; z0 l3 Z% n9 M8 Q" C pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];5 x* {5 q% M! g5 m k3 h: t9 t& T
pAdapterInfoBkp = pAdapterInfo;
8 O" [# L: o ]; o* s}3 S$ D6 p& \8 L$ J
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
" B2 p5 V) |5 u7 e. P9 R{% E. P; n2 k) s7 \; m2 _( z$ M
do{ // 遍历所有适配器
) D, V2 i# B, a" [. x3 b if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
' p/ l3 H9 K3 \' f; { {
O5 M# n' z$ f0 S6 T/ @- I, w // pAdapterInfo->Description 是适配器描述/ t$ x" e2 B4 D
// pAdapterInfo->AdapterName 是适配器名称$ R/ P3 E: T. l" v* i9 B
}
& h; c; T* F+ Y/ S6 I pAdapterInfo = pAdapterInfo->Next;
j) Q5 v6 f2 t$ B% n8 V2 H W9 R( X }while(pAdapterInfo);
, k3 e( o& y- }& f+ t# o8 T}
) _! Y5 \* o. kdelete pAdapterInfoBkp;
) W: s% c+ F8 N% [
, E) e- s5 ]$ d9 r+ b8 D8 G1.2 读取注册表取得适配器名称
" x3 I" k8 C) ^) f6 N" r4 \
; ^- v* k* Z8 @: Z( D8 Z2 Q在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;
; ^% F, F* T) D- e1 u" i' v& @3 u* r0 o& @2 q' d
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 e$ B) }3 C3 Y: m "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",. T" I6 y: M2 ?! x: @% J; v/ J
0,
2 i5 E E$ n% k, g5 \; E8 l KEY_READ,# N7 [; A+ ], m, Q
&hKey) != ERROR_SUCCESS)2 C7 |* j* V6 S- g; O0 r
return FALSE;9 A& ?+ _4 s. S# p' n6 L7 w
; o: F4 ]+ @) ^
DWORD dwIndex = 0;0 v1 j! H1 ~; B4 Q; o3 T
DWORD dwBufSize = 256;
( K4 l" ]3 n, N4 p6 ^% H$ qDWORD dwDataType;
' u& S g: R5 R( K6 D! N: jchar szSubKey[256];
7 T! n% W# O2 ^( a5 Bunsigned char szData[256];
5 Q4 y+ k/ d/ d8 j! ?. h M
- M% ]% p+ F( _3 R" nwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
9 M. Q; y- k1 F- S) X7 o, `7 \& e{
/ K4 ]' l2 p- @* H8 S" @% Q if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)8 [& J" N# E* C+ X# N* F+ M
{
9 }9 ^* l! ^& U if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
8 A9 R& H" ^/ |# v( x( O {+ g/ Z5 y+ C1 Z* K
dwBufSize = 256;
5 J' x( {# p0 s" [ if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
3 c4 L' d# D: K5 A5 G; i {* u, U$ R3 P* g' }2 R- N; d
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡. _5 u9 o6 T* g/ [3 z; k
{, S% [* E0 A0 m/ P+ Q( T
dwBufSize = 256;6 o- L, C4 {" o7 @* n
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
/ R- X7 T" ]' [7 X1 g0 X% F {
$ \2 _- X' K# N& \ // szData 中便是适配器详细描述
- W5 g; w Q; h dwBufSize = 256;3 W; t9 A+ J$ }& ^" C2 P6 V6 I
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) [" y+ K) Z1 e) b
{
! g. J; f; p' v7 [4 C // szData 中便是适配器名称
; E6 A) ]9 k: E! P5 j; Z2 E( R& s9 I }2 f0 Y. l1 R4 o. I h
}& G L# ^5 e4 u* `) s
}
! l! h" c8 M1 e5 x$ } }
' r! _) m. a0 }8 j, [3 J RegCloseKey(hNdiIntKey);( y2 W$ g, M$ z% {
}) p& c) k1 n5 e. C) |+ t
RegCloseKey(hSubKey);
/ c# L, c6 \. @2 R0 w$ B }
3 p3 f/ ?( l4 H. P3 b# ^& J+ z' h* v
dwBufSize = 256;
- a3 k, ^: N; F7 x1 E} /* end of while */
# r! a( A/ q$ t5 W( F2 ] ^% D/ ^ ! r( T, x5 y7 V, ?, Q) r
RegCloseKey(hKey);$ |( X& v# `% L% `
二、将IP信息写入注册表5 C7 W& U! w% ~' i
; X$ t F0 g, K( }
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)9 b1 S1 m, w. w, j# Y( o1 Y
{5 ^7 g" c) c: D' J5 y# f5 O/ x
HKEY hKey;
u9 i/ g# l3 a! v4 P y& H3 n6 R string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
4 O m% M5 j) e' D# l, ^ strKeyName += lpszAdapterName;
+ t* \+ O; G, [' n if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
! ~7 j* h$ O1 r/ E/ p0 L" n strKeyName.c_str(),! V: l% t/ e0 [1 n
0,
/ R8 g6 r6 S( T% [! f. D KEY_WRITE,9 a. N; X7 M0 v: B d( n! p6 I
&hKey) != ERROR_SUCCESS)
4 `+ a2 K3 B6 H$ k& T return FALSE;6 ]% a0 K/ F- W$ Q7 H
8 x v# G* z& K: O/ f: @4 _! r% w
char mszIPAddress[100];
7 ~$ z8 J! i& H. `9 P( D- i% _ char mszNetMask[100];
n1 ?$ ^4 @5 D4 Q6 e3 n1 H char mszNetGate[100];
# ] v, S' K, X" y/ i6 w2 l; p2 ^% D8 v6 Q/ X$ }
strncpy(mszIPAddress, pIPAddress, 98);
9 u4 {0 N0 m. z$ j) _ strncpy(mszNetMask, pNetMask, 98);* F# \) z* {( _! S: S
strncpy(mszNetGate, pNetGate, 98);4 `& x) V; u y0 _; E% j1 v* s3 w
1 l. _( X5 p; p
int nIP, nMask, nGate;3 [) ]7 n9 h9 ?
7 S O# _1 b$ Z l
nIP = strlen(mszIPAddress);0 C2 Y! Y5 Q4 v+ r: k
nMask = strlen(mszNetMask);8 S: k0 L9 ]1 h1 C3 ?" ^' Q. B
nGate = strlen(mszNetGate);
' y* N3 \# p8 j. s( B- Y) i: B6 P( R5 Q3 e" u9 T
*(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
- B5 P$ b5 S/ B6 F9 t: E7 X- Z3 v nIP += 2;) v( g' S0 c% Q v1 j- j. m
+ T# f( L1 p" k/ h
*(mszNetMask + nMask + 1) = 0x00;: l7 z" }4 [) l+ u, P
nMask += 2;) s, I% V! j* L/ V% F& \
. l% V5 \* N# G9 Q7 E" t
*(mszNetGate + nGate + 1) = 0x00;
5 m2 Z( J6 Q* O% ]5 s nGate += 2;
, f1 o. u. r* h1 X8 e " T. E7 G; }) p" |% g& j
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
* |5 ^# I r) \" V* \ RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);/ S Z6 \3 r0 [8 D4 C
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);9 h9 B2 h7 m$ S' g E- F/ l4 ^
( j n3 d% T9 u9 @' C RegCloseKey(hKey);4 ?- q; @! R& c' Q
7 j- s& T, R* L6 [% j return TRUE;
& I6 Z% |0 H; F% I}
4 ], X* V# b' V/ r X. o5 Z2 ?% z8 q6 N& w$ K* i0 {
三、调用DhcpNotifyConfigChange通知配置的改变' I7 m2 b7 X' v2 H
0 H* N( o0 ^6 E$ ^: `" o8 N未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(5 G+ E; Q- K6 f0 M
LPWSTR lpwszServerName, // 本地机器为NULL; |6 A% c3 a# ?4 x+ K+ P
LPWSTR lpwszAdapterName, // 适配器名称. Y7 V2 Y# C" I' ~( z$ B. F6 e) e; c
BOOL bNewIpAddress, // TRUE表示更改IP
8 t0 N3 J. M+ r; \ DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0- ]9 b) c/ I" z8 I( F: v: \
DWORD dwIpAddress, // IP地址* u0 ]2 M# w# R7 d+ ^) z% {
DWORD dwSubNetMask, // 子网掩码0 o- d% W/ a6 y, U
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP" O( {4 l: ^ |2 a
9 p1 ]. r, C- c' ^ c具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)# }' D2 S! L2 n' ~; R
{
) [% s. S* J: b6 ^ BOOL bResult = FALSE;
1 n) W) N/ o' J+ \9 @" L5 }) e HINSTANCE hDhcpDll;2 T$ l) q6 S5 P
DHCPNOTIFYPROC pDhcpNotifyProc;! w2 ], w4 R0 x2 a* Q. V& C- o
WCHAR wcAdapterName[256];: {' r5 e- a! U1 b" o
/ }8 k5 y& N7 X2 ^ MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);$ W$ T/ A* [7 ~3 W. P
+ p0 M c" ~- O1 W- s if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)2 N4 q9 B! g5 @3 c: b
return FALSE;
+ c5 W+ M: l8 g8 X
" T( Z7 w, o) @8 _ if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
+ C, U6 u' V6 d- m if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
; [$ z% V" {# O; |/ X6 m0 q bResult = TRUE;
# g2 w" D3 f, h- V V, l$ |! I1 T O" c% l8 y- f% W8 _
FreeLibrary(hDhcpDll);
* I$ {# x: b" Y& z return bResult;
: T' S- t8 B R0 s' l} |
|