编程实现重起网卡等设备
2006-04-26 08:51
375 查看
今天水木上有位朋友问我如何卸载WinPCap的驱动。因为此类驱动跟网卡绑定很紧密,卸载的时候最好是要把网卡重起一下(SnifferPro就是如此)。而重起网卡的程序实现又很少有资料介绍,前段时间好容易看到一篇文章,居然是用字符串查找到控制面板下面调用applet,呵呵,够狠 -_-b。刚好前几个月有同事有类似需求,我写过一个命令行下重起网卡的小工具,就把它翻出来大概介绍一下实现思路。
首先是要找到需要操作的网卡的ID,这个功能实现的方法很多:最常见的是Winpcap的packet32.c里面提供的直接从注册表中枚举的方法;另外一种方法则是使用DDK中提供的Device Installation系列函数完成。
枚举注册表的方法需要打开HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E972-E325-11CE-BFC1-08002bE10318}注册表键,{4D36E972-E325-11CE-BFC1-08002bE10318}是Net类型设备的ID,下面每个子键定义一个网络设备,但只有一部分设备是网卡。具体处理方法请参见Winpcap的PacketGetAdapterNames函数。
使用Device Installation API则首先用SetupDiGetClassDevs函数获取所有类型的设备,或者在此指定只获取特定类型设备。因为我那个程序原意是控制所有类型设备,就没有指定类型。
然后使用SetupDiEnumDeviceInfo枚举类型中所有的设备
在找到要处理的设备后,应该用CM_Get_DevNode_Status函数和注册表获取其状态,忽略被隐藏的设备。
对剩下的设备则根据其Class进行过滤,只处理Net类型设备,如果前面指定只获取Net设备则此步骤可以忽略。
满足上述限制的设备,就是我们要处理的网卡。可以直接修改其状态:SetupDiSetClassInstallParams函数设置参数;SetupDiCallClassInstaller完成参数修改。
http://www.blogcn.com/user8/flier_lu/blog/1243576.html
首先是要找到需要操作的网卡的ID,这个功能实现的方法很多:最常见的是Winpcap的packet32.c里面提供的直接从注册表中枚举的方法;另外一种方法则是使用DDK中提供的Device Installation系列函数完成。
枚举注册表的方法需要打开HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E972-E325-11CE-BFC1-08002bE10318}注册表键,{4D36E972-E325-11CE-BFC1-08002bE10318}是Net类型设备的ID,下面每个子键定义一个网络设备,但只有一部分设备是网卡。具体处理方法请参见Winpcap的PacketGetAdapterNames函数。
使用Device Installation API则首先用SetupDiGetClassDevs函数获取所有类型的设备,或者在此指定只获取特定类型设备。因为我那个程序原意是控制所有类型设备,就没有指定类型。
以下为引用: HDEVINFO m_hDevInfo = ::SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); |
以下为引用: SP_DEVINFO_DATA did = { sizeof(SP_DEVINFO_DATA) }; for(int i=0; ::SetupDiEnumDeviceInfo(m_hDevInfo, i, &did); i++) { //... } |
以下为引用: bool CDeviceManager::IsClassHidden(const GUID *ClsGuid) const { HKEY hKeyClass = ::SetupDiOpenClassRegKey(ClsGuid, KEY_READ); bool hidden = false; if(INVALID_HANDLE_VALUE != hKeyClass) { hidden = ERROR_SUCCESS == ::RegQueryValueEx(hKeyClass, REGSTR_VAL_NODISPLAYCLASS, NULL, NULL, NULL, NULL); ::RegCloseKey(hKeyClass); } return hidden; } DWORD dwStatus = 0, dwProblem = 0; if(CR_SUCCESS != ::CM_Get_DevNode_Status(&dwStatus, &dwProblem, did.DevInst,0)) { DisplayError("CM_Get_DevNode_Status"); continue; } if(dwStatus & DN_NO_SHOW_IN_DM || IsClassHidden(&did.ClassGuid)) { continue; } |
以下为引用: const std::string CDeviceManager::GetProperty(SP_DEVINFO_DATA& did, DWORD Property) const { std::string buf; DWORD dwLength = 0; while(!::SetupDiGetDeviceRegistryProperty(m_hDevInfo, &did, Property, NULL, (PBYTE)buf.c_str(), buf.size(), &dwLength)) { if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { buf.resize(dwLength * sizeof(wchar_t)); std::fill(buf.begin(), buf.end(), '/0'); } else { break; } } buf.resize(strlen(buf.c_str())); return buf; } if(stricmp(GetProperty(did, SPDRP_CLASSGUID).c_str(), "{4d36e972-e325-11ce-bfc1-08002be10318}") == 0) { // ... } |
以下为引用: bool CDeviceManager::ChangeDeviceState(SP_DEVINFO_DATA& did, DWORD State) const { SP_PROPCHANGE_PARAMS pcp = {sizeof(SP_CLASSINSTALL_HEADER)}; pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; pcp.Scope = (State == DICS_START || State == DICS_STOP )? DICS_FLAG_CONFIGSPECIFIC : DICS_FLAG_GLOBAL; pcp.StateChange = State; if(!::SetupDiSetClassInstallParams(m_hDevInfo, &did, (SP_CLASSINSTALL_HEADER *)&pcp, sizeof(pcp))) { DisplayError("SetupDiSetClassInstallParams"); return false; } // // Call the ClassInstaller and perform the change. // if(!::SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, m_hDevInfo, &did)) { DisplayError("SetupDiCallClassInstaller"); } return true; } ChangeDeviceState(did, DICS_STOP); // 停止 ChangeDeviceState(did, DICS_START); // 启动 ChangeDeviceState(did, DICS_ENABLE); // 启用 ChangeDeviceState(did, DICS_DISABLE); // 禁用 |
相关文章推荐
- 编程实现重起网卡等设备
- 编程实现重起网卡等设备
- Android编程获取设备MAC地址的实现方法
- iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(Swift 优化版)
- iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)
- 如何在 Windows Mobile (WinCE 5.0) 中用Vc++编程查找并连接周围的蓝牙(Bluetooth)设备并实现数据通信
- 《在WinCE5中编程查找并连接周围的蓝牙设备并实现通信》一文配套原码的修正
- 利用eNSP的桥接虚拟网卡实现在虚拟机上对设备的Telnet带内管理
- 编程实现启用禁用网卡
- 编程实现启用禁用网卡
- 自己编程实现简单的字符设备架构
- 嵌入式 获取网卡设备以及IP和MAC地址示例以及网络编程之ioctl小结
- 利用网卡地址和OpenUDID,实现获取设备唯一标识的一种方案
- 利用网卡地址和OpenUDID,实现获取设备唯一标识的一种方案
- VC编程实现与usb设备通信:计算机向单片机发送
- 大家都在转载的Linux声音设备编程——可我却实现不了
- 如何在 Windows Mobile (WinCE 5.0) 中用Vc++编程查找并连接周围的蓝牙(Bluetooth)设备并实现数据通信
- 编程实现Windows下重启网卡(网络链接)
- 如何编程实现启用禁用网卡
- 转:如何编程实现启用禁用网卡