|
设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的API hcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:+ o ~. e% b7 w9 g
0 Z# n1 \$ T5 B7 ~0 U0 w1 X
一、获取适配器名称. u0 T b6 J5 C" A+ a5 |
; y) W& a* r% ?$ }
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
, H( N% x1 D3 `6 L W' f; u8 F! [$ L2 D$ K) F; M
1.1 调用IP helper API取得适配器名称
& D C" @+ p- V; }
8 E% I) J0 L& b8 j8 s, ^9 IULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);. e' c1 c, S5 e2 c# X3 \- X+ T
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
: ~6 Z- T& u3 h3 a- i& Eif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大 K7 m8 r/ v5 c& w. L
{9 r; ^2 ?0 }9 ~- z& v; |
delete pAdapterInfo;5 @& k, }5 @' G; p
pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
' }4 d% ~' ~; t2 ^& w* U pAdapterInfoBkp = pAdapterInfo;
, D9 t3 V- f5 K+ g7 V j}/ y' r' e2 z. O. W _* o% d
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
7 g: g& L0 J3 K' {' v: w{
( s! K2 a" A" C/ l! Z do{ // 遍历所有适配器
, R: {5 f% d5 ?4 b; w if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET) // 判断是否为以太网接口! u5 d9 o, Y( J- Y# x5 D2 u
{
) G% ^* ^# J9 c/ c" u; _8 ] // pAdapterInfo->Description 是适配器描述
% \: ]# E" x3 q, Z! Q# q, W# ^ // pAdapterInfo->AdapterName 是适配器名称5 Z5 w( d; M7 H& G k8 q
}- R$ d# {0 G3 k
pAdapterInfo = pAdapterInfo->Next;
7 S# L9 h* J8 u }while(pAdapterInfo);
+ o {: i7 `) b8 `}/ {7 Z; Y5 H5 C0 Z0 z( Y
delete pAdapterInfoBkp;
3 y- G" B3 W+ r; [
3 `7 ?, C5 D- u5 r9 X- Y1 C% h, f1.2 读取注册表取得适配器名称
$ `% T7 a A) S& c6 G2 `" }4 u+ 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;
* q2 S q& z0 n; a# p/ W, x
% m, e4 k8 i: e2 |9 Kif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
* u7 `" u3 _/ |, x; ?! t9 ^ "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",$ e; b) K; \4 Y2 L* D8 |) t* @, w
0,
/ G+ [% o7 s: [ KEY_READ,
6 }8 |4 k% m+ S+ B2 _ &hKey) != ERROR_SUCCESS)
' U: `5 ^5 h$ M8 e4 s$ ` return FALSE;0 N) e: Q! d( O- ]3 C
+ B* h) h) F0 ?' XDWORD dwIndex = 0;
; R$ Q7 N- J$ h9 q" n; `. }: FDWORD dwBufSize = 256;. `+ Y' i7 P7 `$ M
DWORD dwDataType;
) s B( n8 \3 u3 m7 z' g% \char szSubKey[256]; A0 H$ N% B5 U' B
unsigned char szData[256];& l* Z3 f' k8 M0 }+ m9 v
% W8 P& |( r( W. r; t5 B* m1 o
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)0 T* Y5 |# k, Q% v& \2 O1 `8 Z) J
{
% q; F( b4 v% o* ^6 ]; Q if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)! n$ L# N5 e7 t
{
$ m/ c4 o& c0 n; R4 O5 W- s if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)" |2 e" Q+ l/ t Y W% y4 o9 t- D5 i2 [
{
6 u7 X8 U: ~2 _/ ~ dwBufSize = 256;
. h% l- y8 i' p if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
9 W. }8 O; ]. I7 M {: [2 I1 x" }2 Q0 E% F
if(strcmp((char*)szData, "ethernet") == 0) // 判断是不是以太网卡
) d: Y4 y. _ D/ Z ?& m7 d {
* T0 H5 u$ u4 `& Q0 K1 i dwBufSize = 256;
* U" ]/ J* G0 C* i0 i; x. }3 _ if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)2 l& ]# ~6 K; B! I3 d9 [
{
1 A+ N) R2 N) L3 e3 I // szData 中便是适配器详细描述% k' {6 U6 ~3 Y/ R5 c7 t
dwBufSize = 256;1 I$ {4 U! E: `8 Q* ^( B# C
if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
2 G$ c* ?0 \, s {
5 e+ q. f6 P& w' @1 \$ S; I9 x4 L // szData 中便是适配器名称
: A& k4 \9 I8 c! T3 D$ J- e6 r3 S }
& ?2 W: a5 H8 p$ u. r1 a }$ o$ i3 g: e( n
}1 f) k; T$ B/ t' T$ c6 S
}
2 K- o h3 F" I, @6 Q RegCloseKey(hNdiIntKey);
5 O, a+ ]3 O$ `- A$ s2 V% G+ v9 g }
( o9 M2 I2 `! I. ^! }9 M RegCloseKey(hSubKey);
0 z9 h( y/ K9 B! r }
# f8 Q' C0 `( ? I- u
! q4 g; |' N2 [$ p dwBufSize = 256;5 \2 f9 I- w+ o- X7 ^ u
} /* end of while */. x/ G# L" }+ E/ b
' S* \- @0 R7 _- z
RegCloseKey(hKey);
; w U$ m+ m5 i二、将IP信息写入注册表
) ?' D _( |2 [: A4 }6 u; V7 x6 `6 p
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
: f- x% W$ _+ P+ ]% P1 U{1 M# s; y& _7 N
HKEY hKey;1 g2 V7 @6 |) p* ~+ ^
string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
5 _4 C* N7 j7 |$ O0 X! n strKeyName += lpszAdapterName;- F2 a) y" T* j6 K! D
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
$ i7 _* X5 Y/ A: Y9 G" ]" L strKeyName.c_str(),
, `- _* R7 r0 G+ ~- I' Y! I5 E 0,
& |) v/ b8 @; H4 N" C1 U0 K; w KEY_WRITE,
" \' }. B% r. G( |8 I8 o" D5 m &hKey) != ERROR_SUCCESS): n/ j }5 _& L+ I
return FALSE;0 w8 T1 r0 L! Z; i
$ W4 R1 j2 x! N
char mszIPAddress[100];
' W+ a7 s' o4 e5 [9 Q8 C char mszNetMask[100];1 J+ F6 y# T* G2 g
char mszNetGate[100]; p, W1 }* a6 @/ @5 f+ z$ {
% Y: m+ h, p5 ]4 B& u! I( q7 { strncpy(mszIPAddress, pIPAddress, 98);6 D( X: q' j& m9 d6 H) P
strncpy(mszNetMask, pNetMask, 98);/ ]) ^; J8 L' W( E% }
strncpy(mszNetGate, pNetGate, 98);% U$ i( |4 V0 `/ }# Y
, K5 s+ n, N9 [% ]- g5 M
int nIP, nMask, nGate;4 w' h0 F: d. { p
, M- @/ ]) l, k6 I8 p nIP = strlen(mszIPAddress);
6 M% k5 x' U* ~% ?9 W I nMask = strlen(mszNetMask);
8 v9 m+ |+ O% c nGate = strlen(mszNetGate);% n1 @( n( [9 ~8 C/ @: H
* M; X! I7 c! T6 k *(mszIPAddress + nIP + 1) = 0x00; // REG_MULTI_SZ数据需要在后面再加个0
3 @- H+ D0 d! Z V nIP += 2;; P% V2 P+ @% }5 N/ w. Z# s
/ Y C! F; g& j! ]; p5 x *(mszNetMask + nMask + 1) = 0x00;' \( S8 A W! l8 o) d! V5 I/ E \! `
nMask += 2;
9 l# O# x8 v2 D* Z
$ |7 o7 j/ ]: X j4 ~" a *(mszNetGate + nGate + 1) = 0x00;* c a% |: j. o" M/ Z9 ^ K( s# [, V
nGate += 2;
/ g% |" R3 _0 b6 ~& t
4 \ c/ ~# P( e) l# z9 V: ~4 Y RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);5 F1 h4 c8 j( @( F; S' j1 u+ z
RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);. B2 ]- m- O7 @2 y) Y
RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);- h4 ]. c: i; d, A% {+ i
3 u7 f6 w( y4 t, \+ S* `' _% f: j
RegCloseKey(hKey);
" ]. z' w1 ]+ t/ d: B [$ J! M& E
9 N9 J2 }# ]3 o return TRUE;) ]1 E/ s4 y: }8 T6 Q+ Y
}
' Z9 m8 G1 \ o- ?2 b$ ~% M$ S! W% \- F; c7 L
三、调用DhcpNotifyConfigChange通知配置的改变2 g2 G' a) I% }$ W
( y6 s% g! h3 v
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
$ e2 }* M* j7 y3 C! L$ }+ e LPWSTR lpwszServerName, // 本地机器为NULL
: x, \! s) H" {7 V1 K; U LPWSTR lpwszAdapterName, // 适配器名称
4 i& _( c, g% P1 k8 ]. _3 b" A) t BOOL bNewIpAddress, // TRUE表示更改IP
, \1 h! K1 r' H, q DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为00 k( u1 o' t5 b" y( `: D
DWORD dwIpAddress, // IP地址
# z% y9 ~* h( c( s DWORD dwSubNetMask, // 子网掩码
( v+ O# R% \$ a7 E5 d int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
: i, r% n: c" X
3 I9 ]' E6 |! H) S具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)3 ~# q: @! v3 f( H6 T
{! }7 f, ]8 P+ J1 `( ]; i& r! a
BOOL bResult = FALSE;
3 u# v: k$ ?" F# c' q HINSTANCE hDhcpDll;! Q; ]# ]1 L, w& s7 \5 ~4 x, i' d
DHCPNOTIFYPROC pDhcpNotifyProc;
, y: B! D& G9 W; m WCHAR wcAdapterName[256];
& j& z% k6 K9 k! [
4 Y4 Z4 b) H1 `' w& G MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);" Q: G' u' ^: d2 q" Y; `# V, r
0 m" K$ @9 `. D6 ` F1 f5 ] if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
5 O, S' w. Q" |3 R, F return FALSE;
2 g& ^6 ?& W1 ]2 o/ Q% z+ R) H h% i% |/ J
if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
, |/ Y) C" ?8 a( ^4 ^ if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)4 \) l. ^- d# ~" f4 w/ u. F7 `$ }
bResult = TRUE;
( n0 A( M: ~; ~
1 |6 J3 d8 z" D+ W FreeLibrary(hDhcpDll);
' C& K/ b" F. {: c: a- m9 d return bResult;
( [8 t; S" z# S- U' D, j8 S( ]2 }$ ?} |
|