首先是要找到需要操作的网卡的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);
然后使用setupdienumdeviceinfo枚举类型中所有的设备
以下为引用:
sp_devinfo_data did = { sizeof(sp_devinfo_data) };
for(int i=0; ::setupdienumdeviceinfo(m_hdevinfo, i, &did); i++)
{
//...
}
在找到要处理的设备后,应该用cm_get_devnode_status函数和注册表获取其状态,忽略被隐藏的设备。
以下为引用:
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;
}
对剩下的设备则根据其class进行过滤,只处理net类型设备,如果前面指定只获取net设备则此步骤可以忽略。
以下为引用:
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)
{
// ...
}
满足上述限制的设备,就是我们要处理的网卡。可以直接修改其状态:setupdisetclassinstallparams函数设置参数;setupdicallclassinstaller完成参数修改。
以下为引用:
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); // 禁用
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!


