本文是通过禁用启用网卡让IP设置生效,因为使用DhcpNotifyConfigChange方法效果不好,且容易发生溢出问题
typedef int (CALLBACK* DHCPNOTIFYPROC)(LPWSTR, LPWSTR, BOOL, DWORD, DWORD, DWORD, int); typedef struct tagAdapterInfo { string strName;// 适配器名称 string strDriverDesc;// 适配器描述 string strIP; // IP地址 string strNetMask;// 子网掩码 string strNetGate;// 网关 }ADAPTER_INFO; BOOL GetAdapterInfo(); BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex = 0); vector<ADAPTER_INFO*> AdapterInfoVector; //----------------------------------------------------------------- // 取得所有网卡信息 //----------------------------------------------------------------- BOOL GetAdapterInfo() { // 这里的代码适合WINDOWS2000,对于NT需要读取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards HKEY hKey, hSubKey, hNdiIntKey; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}", 0, KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE; DWORD dwIndex = 0; DWORD dwBufSize = 256; DWORD dwDataType; char szSubKey[256]; unsigned char szData[256]; while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS) { if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS) { dwBufSize = 256; if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) { if(strcmp((char*)szData, "ethernet") == 0)//判断是不是以太网卡 { dwBufSize = 256; if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) { ADAPTER_INFO *pAI = new ADAPTER_INFO; pAI->strDriverDesc = (LPCTSTR)szData; dwBufSize = 256; if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) { pAI->strName = (LPCTSTR)szData; RegGetIP(pAI, (LPCTSTR)szData); } AdapterInfoVector.push_back(pAI);// 加入到容器中 } } } RegCloseKey(hNdiIntKey); } RegCloseKey(hSubKey); } dwBufSize = 256; } /* end of while */ RegCloseKey(hKey); return TRUE; } //----------------------------------------------------------------- // 得到注册表中的IP信息 // nIndex暂时未处理 //----------------------------------------------------------------- BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex/* =0 */) { ASSERT(pAI); HKEY hKey; string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; strKeyName += lpszAdapterName; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, strKeyName.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) return FALSE; unsigned char szData[256]; DWORD dwDataType, dwBufSize; dwBufSize = 256; if(RegQueryValueEx(hKey, "IPAddress", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) pAI->strIP = (LPCTSTR)szData; dwBufSize = 256; if(RegQueryValueEx(hKey, "SubnetMask", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) pAI->strNetMask = (LPCTSTR)szData; dwBufSize = 256; if(RegQueryValueEx(hKey, "DefaultGateway", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS) pAI->strNetGate = (LPCTSTR)szData; RegCloseKey(hKey); return TRUE; } //----------------------------------------------------------------- // 设置注册表中的IP信息 //----------------------------------------------------------------- BOOL RegSetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress) { HKEY hKey; string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; strKeyName += lpszAdapterName; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, strKeyName.c_str(), 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE; char mszIPAddress[100]; char mszNetMask[100]; char mszNetGate[100]; char szDnsAddr[100]; strncpy(mszIPAddress, pIPAddress, 98); strncpy(mszNetMask, pNetMask, 98); strncpy(mszNetGate, pNetGate, 98); strncpy(szDnsAddr, pDnsAddress, 98); int nIP, nMask, nGate,nDnsAddr; int enableDHCP=0; nIP = strlen(mszIPAddress); nMask = strlen(mszNetMask); nGate = strlen(mszNetGate); nDnsAddr = strlen(szDnsAddr); *(mszIPAddress + nIP + 1) = 0x00; nIP += 2; *(mszNetMask + nMask + 1) = 0x00; nMask += 2; *(mszNetGate + nGate + 1) = 0x00; nGate += 2; *(szDnsAddr + nDnsAddr + 1) = 0x00; nDnsAddr += 2; RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP); RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask); RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate); RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr); RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) ); RegCloseKey(hKey); return TRUE; } //----------------------------------------------------------------- // 设置注册表中DHCP //----------------------------------------------------------------- BOOL RegSetDHCPIP(LPCTSTR lpszAdapterName, int nIndex) { HKEY hKey; string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; strKeyName += lpszAdapterName; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, strKeyName.c_str(), 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE; int enableDHCP=1; char mszIPAddress[100]; char mszNetMask[100]; char mszNetGate[100]; char szDnsAddr[100]; strncpy(mszIPAddress, "0.0.0.0", 98); strncpy(mszNetMask, "0.0.0.0", 98); strncpy(mszNetGate, "", 98); strncpy(szDnsAddr, "", 98); int nIP, nMask, nGate,nDnsAddr; nIP = strlen(mszIPAddress); nMask = strlen(mszNetMask); nGate = strlen(mszNetGate); nDnsAddr=strlen(szDnsAddr); *(mszIPAddress + nIP + 1) = 0x00; nIP += 2; *(mszNetMask + nMask + 1) = 0x00; nMask += 2; *(mszNetGate + nGate + 1) = 0x00; nGate += 2; *(szDnsAddr + nDnsAddr + 1) = 0x00; nDnsAddr += 2; RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP); RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask); RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate); RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr); int errCode = RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) ); RegCloseKey(hKey); return TRUE; } //----------------------------------------------------------------- // 通知IP地址的改变 //----------------------------------------------------------------- BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask) { BOOL bResult = FALSE; HINSTANCE hDhcpDll; DHCPNOTIFYPROCpDhcpNotifyProc; WCHAR wcAdapterName[256]; MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256); if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL) return FALSE; if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL) if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, NULL,NULL, 0) == ERROR_SUCCESS) bResult = TRUE; FreeLibrary(hDhcpDll); return bResult; } //----------------------------------------------------------------- // 设置IP地址 // 如果只绑定一个IP,nIndex = 0,暂时未处理一个网卡绑定多个地址 //----------------------------------------------------------------- BOOL SetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress) { if(!RegSetIP(lpszAdapterName, nIndex, pIPAddress, pNetMask, pNetGate,pDnsAddress)) return FALSE; //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃) //if(!NotifyIPChange(lpszAdapterName, nIndex, pIPAddress, pNetMask)) // return FALSE; //通过禁用启用网卡实现IP立即生效 list<TNetCardStruct> cardList; EnumNetCards(&cardList); if(!cardList.empty()) { NetCardStateChange(&cardList.front(),FALSE); Sleep(10); NetCardStateChange(&cardList.front(),TRUE); } return TRUE; } //----------------------------------------------------------------- // 设置DHCP IP地址 //----------------------------------------------------------------- BOOL SetDHCPIP(LPCTSTR lpszAdapterName, int nIndex) { if(!RegSetDHCPIP(lpszAdapterName, nIndex)) return FALSE; //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃) //if(!NotifyDHCPIPChange(lpszAdapterName, nIndex)) // return FALSE; //通过禁用启用网卡实现IP立即生效 list<TNetCardStruct> cardList; EnumNetCards(&cardList); if(!cardList.empty()) { NetCardStateChange(&cardList.front(),FALSE); Sleep(10); NetCardStateChange(&cardList.front(),TRUE); } return TRUE; }
/*******************************************************网卡禁用启用操作*************************************************/
NetCard.h
#ifndef NETCARD_H_H #define NETCARD_H_H #include <Windows.h> #include <SetupAPI.h> #include <cfgmgr32.h> #include <list> using namespace std; // cfgmgr32.h 在Microsoft Windows 2000 DDK 中. // 要用 CM_Get_DevNode_Status() 来查询状态. //--------------------------------------------------------------------------- typedef struct NetCardStruct { DWORD Id; // 网卡设备号 string Name; // 网卡名 bool Disabled; // 当前是否禁用 bool Changed; // 是否更改过 }TNetCardStruct; typedef TNetCardStruct* PNetCardStruct; /*******************函数声明***********************************/ static bool GetRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, ULONG Property, PVOID Buffer, PULONG Length) ; void EnumNetCards(list<TNetCardStruct> *NetDeviceList); bool NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled) ; /**************************************************************/ #endif
#include "stdafx.h" #include <SetupAPI.h> #include <cfgmgr32.h> #include <list> #include <Windows.h> #include <SetupAPI.h> #include "NetCard.h" //--------------------------------------------------------------------------- // EnumNetCards 枚举出网卡 //--------------------------------------------------------------------------- void EnumNetCards(list<TNetCardStruct> *NetDeviceList) { string DevValue; PNetCardStruct NetCard; DWORD Status, Problem; LPTSTR Buffer = NULL; DWORD BufSize = 0; HDEVINFO hDevInfo = 0; hDevInfo=SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES); if(INVALID_HANDLE_VALUE==hDevInfo) return; SP_DEVINFO_DATA DeviceInfoData ={sizeof(SP_DEVINFO_DATA)}; HKEY hKeyClass; char DeviceName[200]; for(DWORD DeviceId=0;SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData);DeviceId++) { if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS) continue; if(GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS , &Buffer, (PULONG)&BufSize)) DevValue = string(Buffer); if (strcmp(DevValue.c_str(),"Net") == 0) { DevValue = ""; if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME , &Buffer, (PULONG)&BufSize)) DevValue = Buffer; if (strcmp(DevValue.c_str(),"ROOT") != 0) { NetCard = new TNetCardStruct; NetCard->Id = DeviceId; NetCard->Name = "<Unknown Device>"; if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER , &Buffer, (PULONG)&BufSize)) if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC , &Buffer, (PULONG)&BufSize)) NetCard->Name = Buffer; NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem); NetCard->Changed = false; NetDeviceList->push_back(*NetCard); } } } } //--------------------------------------------------------------------------- bool GetRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, ULONG Property, PVOID Buffer, PULONG Length) { while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet, DeviceInfoData, Property, NULL, (BYTE *)*(TCHAR **)Buffer, *Length, Length)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (*(LPTSTR *)Buffer) LocalFree(*(LPTSTR *)Buffer); *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR,*Length); } else return false; } return (*(LPTSTR *)Buffer)[0]; } //--------------------------------------------------------------------------- // NetCardStateChange 网卡的启用与禁用 // NetCardPoint 是 PNetCardStruct 的指针. // Enabled true = 启用 false = 禁用 //--------------------------------------------------------------------------- bool NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled) { PNetCardStruct NetCard = (PNetCardStruct)NetCardPoint; DWORD DeviceId = NetCard->Id; HDEVINFO hDevInfo = 0; if (INVALID_HANDLE_VALUE == (hDevInfo = SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT |DIGCF_ALLCLASSES))) return false; SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)}; DWORD Status, Problem; if (!SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData)) return false; if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS) return false; SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)}; PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_GLOBAL; if (Enabled) { if (!((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem))) { NetCard->Disabled = false; return false; } PropChangeParams.StateChange = DICS_ENABLE; } else { if ((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem)) { NetCard->Disabled = true; return false; } if (!((Status & DN_DISABLEABLE) && (CM_PROB_HARDWARE_DISABLED != Problem))) return false; PropChangeParams.StateChange = DICS_DISABLE; } if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams))) return false; if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DeviceInfoData)) return false; if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) == CR_SUCCESS) NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem); return true; }
GetAdapterInfo(); char szIP[16]="111.111.111.11"; char szMask[16]="255.255.255.10"; char szGate[16]="111.111.111.1"; char dnsAddress[16]="222.222.222.1"; unsigned char *pIP, *pMask, *pGate; DWORD dwIP, dwMask, dwGate; if(SetIP(AdapterInfoVector[0]->strName.c_str(), 0, szIP, szMask, szGate,dnsAddress) == TRUE) ::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION); else ::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);
GetAdapterInfo(); if(SetDHCPIP(AdapterInfoVector[0]->strName.c_str(), 0 ) == TRUE) ::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION); else ::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);