现在的位置: 首页 > 综合 > 正文

编程实现企业即时通讯软件

2013年04月08日 ⁄ 综合 ⁄ 共 3114字 ⁄ 字号 评论关闭

编程实现企业即时通讯软件

编程实现重起企业等通讯企业即时通讯软件
Posted on 2004-07-08 10:13 Flier Lu 阅读(1252) 评论(3) 编辑 收藏 收藏至365Key
http://www.blogcn.com/user8/flier_lu/main.asp?id=1243576

在找到要处理的通讯后,应该用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_NODISPLAYC
LASS, NULL, NULL, NULL, NULL);

::RegCloseKey(hKeyClass);
}

return hidden;
}

首先是要找到需要操作的企业的ID,这个功能实现的方法很多:最常见的是Winpcap的p
acket32.c里面提供的直接从通讯中枚举的方法企业即时通讯软件;另外一种方法则是使用DDK中提供的Devi
ce Installation系列函数完成。
枚举通讯的方法需要打开HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/
Class/{4D36E972-E325-11CE-BFC1-08002bE10318}通讯键,{4D36E972-E325-11CE-BFC1-0
8002bE10318}是Net类型通讯的企业即时通讯软件ID,下面每个子键定义一个网络通讯,但只有一部分通讯是
企业。具体处理方法请参见Winpcap的PacketGetAdapterNames函数。
使用Device Installation API则首先用SetupDiGetClassDevs函数获取所有类型的通讯
,或者在此指定只获取特定类型通讯企业即时通讯软件。因为我那个程序原意是控制所有类型通讯,就没有指
定类型。

今天水木上有位朋友问我如何卸载企业即时通讯软件inPCap的驱动。因为此类驱动跟企业绑定很紧密,
卸载的时候最好是要把企业重起一下(SnifferPro就是如此)。而重起企业的程序实现又很
少有资料介绍,前段时间好容易看到一篇文章,居然是用字符串查找到控制面板下面调用ap
plet,呵呵,够狠 -_-b。刚好前几个月有同事有类似需求,我写过一个命令行下重起企业
的小工具,就把它翻出来大概介绍一下实现思路。

以下为引用:

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++)
{
//...
}

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;
}
企业即时通讯软件满足上述限制的通讯,就是我们要处理的企业。可以直接修改其状态:SetupDiSetClas
sInstallParams函数设置参数;SetupDiCallClassInstaller完成参数修改。

对剩下的通讯则根据其Class进行过滤,只处理Net类型通讯,如果前面指定只获取Net
通讯则此步骤可以忽略。

以下为引用:

const std::string CDeviceManager::GetProperty(SP_DEVINFO_DATA& did, DWORD Proper
ty) 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;
}

//
// 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); // 禁用
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_CONFIGSPEC
IFIC : DICS_FLAG_GLOBAL;
pcp.StateChange = State;

if(!::SetupDiSetClassInstallParams(m_hDevInfo, &did,
(SP_CLASSINSTALL_HEADER *)&pcp, sizeof(pcp)))
{
DisplayError("SetupDiSetClassInstallParams");
return false;
}

抱歉!评论已关闭.