|
|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:2 W. q! S2 N2 G& ^9 q
5 j: x+ P( V' u% K6 p0 ]一、获取适配器名称6 F0 Y1 T- v0 \/ A
. n# k7 z" T0 Z+ u这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
v2 f2 H2 M# u/ @- Y1 n' c
2 T# w6 Q; \" M6 H1 K: i1.1 调用IP helper API取得适配器名称
0 x' ?4 l! z$ Q Y( {; [& z6 w
/ J1 `4 K$ Z7 N/ HULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);5 L& H+ j5 v* }' s) ^: H8 L. t8 f
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
9 L# d9 Q2 b/ U6 Gif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大5 O J" H7 u% q9 W
{
& d. B; q4 s( O8 ^. {1 } delete pAdapterInfo;$ ~& {. @6 D+ _% @8 Q* X5 u( U
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];* z) n2 ~7 L" H# X( F
pAdapterInfoBkp = pAdapterInfo;
; p% I4 W/ K. {0 y& U% g' Y}6 }! ^, O- o2 v A# Z
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )$ i' b" l2 E- u# r& ~' D. m
{; s& J5 B: }6 E* w9 t' Q! O
do{ // 遍历所有适配器, w2 r! `2 ^' C( M
if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口
* A; r3 p' R9 Y$ |6 r {
2 q% M/ e+ P% M% m1 T ~& N) H // pAdapterInfo->Description 是适配器描述1 l2 G0 ~% k9 L) j
// pAdapterInfo->AdapterName 是适配器名称% A+ q" e! G' C. e) X6 U/ T
}) z2 t+ T# m* A' @5 t3 ?& s4 M( T
pAdapterInfo = pAdapterInfo->Next;
9 \1 l7 I% Z0 ?6 _ }while(pAdapterInfo);
" b1 F, ?! Z& A3 f& O3 z! \}
) d& s8 e3 B( |9 F8 ]delete pAdapterInfoBkp;
, L" f4 p) a: f% e% f3 h, f" O5 f7 Z; m1 }
1.2 读取注册表取得适配器名称+ ~2 G- h; c; G6 \$ ?
6 R# }$ v. O& m0 H在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: p: w, q. R- e; Q, T! f6 j; B6 ^3 `. V# z" G' B5 d i0 t
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,5 u5 _# Q6 J F
"System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
$ b) L! w% o# ? 0,* R+ I. F V6 [
KEY_READ,
7 W$ C4 F n# b& o" `, ` &hKey) != ERROR_SUCCESS), r' b# Z; z7 M U
return FALSE;
; D8 G/ m% l6 |3 e1 `7 W! f4 M
( Z6 E9 |& i$ p4 b) L9 \DWORD dwIndex = 0;8 t# l1 p P7 x7 J$ H
DWORD dwBufSize = 256;4 p2 y4 a5 K1 j( M, F/ L
DWORD dwDataType;
: L, s& Q6 D/ M; nchar szSubKey[256];1 B1 t* s# |8 }: ^0 I
unsigned char szData[256];
4 z" Y9 s6 R+ P* Y; v& c; ?
* N3 f6 L: Y2 t8 qwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)% m$ T8 n& X, ]5 I% h
{
7 M# q O! S2 a6 o5 V: j% k if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)1 }6 _! \6 p7 m( z# V9 i! I9 A
{ $ d9 L3 Q; C" L5 g
if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)+ f7 V4 s' [. W% v* g
{
a1 x9 s0 ?; V7 C. L dwBufSize = 256;
( \2 | w3 v9 ~4 v/ _ if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)! Y5 N. L3 b2 A. p! z' A
{
3 U( L& c& n) [. L" a; ?# U; { if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
& w- `7 [5 o! ]2 L8 H0 B) |; y {
& c* E5 L: H! a# I dwBufSize = 256;2 G( v" E2 ~$ f9 E
if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
% ^1 S3 L3 x6 H: i. Z {7 M1 J; W! m2 } z
// szData 中便是适配器详细描述- }2 @* J# O! k" a p% S& Z4 ~
dwBufSize = 256;
3 V! h& d* z8 w* v if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
; J2 a! h+ L7 R. n {9 F: R7 F7 ~8 H1 H+ P3 J& \* F
// szData 中便是适配器名称9 ^, _. b- ^% f7 v S8 X
}
/ \& X* Q' }/ ~; s# o* [7 L+ U }% F2 y6 \' U: j
}
& r* V0 F4 C, d4 N }3 L& Z/ x. Y3 O ?* Y E
RegCloseKey(hNdiIntKey);
7 M8 M! D, ^6 i" ~) s$ p/ X5 r }
/ s3 S' l; w( o! m4 g RegCloseKey(hSubKey);
* q$ b! J/ p- J" h2 D) R- U' t: d }
6 n- v9 ~5 C! Q( ?0 ?/ n2 w9 r$ I0 c
dwBufSize = 256;
( n7 S F9 j9 k, ?6 s, d& O# u; C} /* end of while */
) D7 Z9 ^6 D& _; N! Q
2 v; ~7 l, S* I& ]# d' u; ~ J7 XRegCloseKey(hKey);) t( O: O" m1 b& i$ U' t
二、将IP信息写入注册表5 z' i% A9 C/ ?' f3 G' }" ^
) g, N/ r7 Y" |' M代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)3 m) m3 g, K, ^0 m' @1 Q
{
1 m, _# x' ^5 i! l' O, h+ I/ c' n HKEY hKey;& a7 W2 S7 ~6 o$ x6 F- O
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
/ w0 d; o/ I3 K( l6 J/ D; Z& t | strKeyName += lpszAdapterName;5 x9 S7 g! ]# D+ J# A+ g2 I2 @
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
2 Y; z% P: s4 Z* i: Z/ ? strKeyName.c_str(),
/ J- P: Q1 H+ h" j0 `: { 0,
/ c& {. d: V0 _; q( J% w KEY_WRITE,4 J- i2 K2 ]# {+ ` F U% {; }
&hKey) != ERROR_SUCCESS): @# P0 F B! L( U- T; O# I
return FALSE;1 l- z( t8 f+ d8 B
# w6 i. e: H6 g% `+ y& l char mszIPAddress[100];. K- _7 D g, A3 M+ K
char mszNetMask[100];
. t! f% d: y$ G char mszNetGate[100];
$ ]# e: k# V7 I! j, f2 G
. v4 ]: t+ b7 Z7 F7 Z strncpy(mszIPAddress, pIPAddress, 98);
% H# h1 A+ Y/ U( s0 B. ~$ T strncpy(mszNetMask, pNetMask, 98);. A' _+ j' G" e) Z' z% X, ^6 Z* b5 _
strncpy(mszNetGate, pNetGate, 98);6 a! x. K/ f% }
5 E, d7 p$ S: ^$ S int nIP, nMask, nGate;3 C) H+ c* h) z U4 ?& y
# v' n) T# [: P+ |# ? nIP = strlen(mszIPAddress);: t! B1 \; ], B# O) a; t" E
nMask = strlen(mszNetMask);6 g" |$ F# `; C) r" m8 r
nGate = strlen(mszNetGate);
3 `7 `! I0 h8 U* J& }" P0 ~, i. b7 b& Y2 K. O# f1 J, |. g' d
*(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
* y1 C& Y4 v! l" g' B nIP += 2;7 T" n7 T' R* S- Y
4 D' x' k6 K$ C Q5 S" [8 s *(mszNetMask + nMask + 1) = 0x00;
" R$ d, G; C' _! W( `6 \: J2 ] nMask += 2;/ h) j7 j$ v% ^& p
. Z1 ?4 e k/ y+ S, b
*(mszNetGate + nGate + 1) = 0x00;
$ U4 e! q! w+ V, C0 z; G- q nGate += 2;
( j! v; A# `: }. m4 Q # C) l# j# ]) P4 I$ f+ C- D: M
RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);7 O! e6 F; Z+ U* h( m# T& i
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
: d2 h4 L7 [# u# a+ c RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
- \3 G4 W9 s" q D+ r; s: ?* m
7 v" j' o5 ~% n7 k RegCloseKey(hKey);
& r9 V3 r* d. |0 \% P; K# P* T/ \+ a; k U7 ~1 A+ }
return TRUE;
* \* s9 I: w, y, M. d}+ Q4 n0 p+ Y# X; b" t& e& _& `
) {# U1 m+ `: V# a* g9 ~8 v
三、调用DhcpNotifyConfigChange通知配置的改变- @- g2 Z# b3 k; r; Q
: m% G- k) y% o+ k1 x; P
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(3 v# d* {) ?: o4 \( E
LPWSTR lpwszServerName, // 本地机器为NULL
' t% l9 F7 I! q4 C9 z! g9 p% L LPWSTR lpwszAdapterName, // 适配器名称
, B2 ?# `: Q3 E$ L2 |3 B; R* l BOOL bNewIpAddress, // TRUE表示更改IP
5 ^( g: ^2 D+ ~- v' n) V DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
' }# ]: x, |0 g( u/ l' d) N- d DWORD dwIpAddress, // IP地址$ R% R1 G1 N% y' ^' d1 {# _6 L
DWORD dwSubNetMask, // 子网掩码1 a0 ~9 y2 A. q
int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
- l2 S+ F$ S' Q* y$ t
5 N6 ^, l; R/ }" {9 ]4 K具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
0 O& Y+ r7 m7 v# F{2 l& _" {& P6 w8 b! I8 h
BOOL bResult = FALSE;
$ t0 G4 f+ Z/ l/ _! ?; Q HINSTANCE hDhcpDll;) d% F9 l0 @! ?1 [& k& T
DHCPNOTIFYPROC pDhcpNotifyProc;6 s9 W4 A5 Y. C1 g$ c+ n2 C9 M
WCHAR wcAdapterName[256];/ ^* t! p% y: S
$ i4 F6 J0 X# K MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);' L0 ?# k0 b! A y( t; a
7 S- r, @* s2 O! {* b5 r/ X- C) o if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
9 d5 n4 r6 J9 N: O5 _, R0 }/ L return FALSE;5 r7 J# Y! I! d
, [' L& q7 f, j: F( o if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)- f" y5 w J1 ]9 K3 n1 y! M( P
if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)- r0 S1 u3 n) L& A4 C
bResult = TRUE;
/ T1 ~, N. l1 G( s) ?5 u+ H+ h/ \# h3 r5 i. ~2 a( l
FreeLibrary(hDhcpDll);6 R7 i) _7 ^% }* ]4 k/ L/ n0 }
return bResult;
) V0 ^- o6 q. _6 b} |
|