金山卫士开源软件之旅(四) netmon下FwProxy工程的解析---接口实现及接口使用方法

2023-11-04

 转载请标明是引用于 http://blog.csdn.net/chenyujing1234

上一篇文章<<金山卫士开源软件之旅(三) netmon下FwProxy工程的解析----COM组件的管理模式>>中讲到如何去实现CFwProxy::GetCLSID与CFwProxy::CreateInstance.

这里做继续介绍.

FwProxy主要是防火墙的设计及驱动的加安装卸载。这里涉及两个类CFwInstaller和CFwProxy.

1 、CFwinstaller接口的实现逻辑。

     下面是此类的COM实现宏接口,有编译之美供我们学习。

实现的GetCLSID和CreateInstance就是给前面注册用的。一旦此DLL注册后,其它应用程序就能得到CFwInstaller 的接口了.

CLSID_IFwInsallerImpl在KingSoft\oss\pcmanager\src\import\kpfw\fwproxy_public.h文件中定义

 

class CFwInstaller : 
	public IFwInstaller,
	public KSComRoot<CFwInstaller> 
{

       	// 实现GetCLSID函数数,返回CLSDI
	KS_DEFINE_GETCLSID(CLSID_IFwInstallerImpl);
	// 实现AddRef( Release(  CreateInstance(三个函数
	DECLARE_INDEPENDENT_OBJECT();

	// 实现QueryInterface函数
	KSCOM_QUERY_BEGIN
	KSCOM_QUERY_ENTRY( IFwInstaller )
	KSCOM_QUERY_END

对于三个宏,我们继续分析:

//m_RefCnt是由public KSComRoot<CFwInstaller>得到的
#define IMPLEMENT_INDEPENDENT_ADDREF() \
unsigned long __stdcall AddRef()    \
{                                   \
	KS_ASSERT(long(m_RefCnt) >= 0); \
	long lRefCnt = ++m_RefCnt;      \
	if (1 == lRefCnt)				\
	{								\
		GlobalFactory::Instance().Lock();\
	}								\
	return lRefCnt;					\
}


 

// _ComType 是由public KSComRoot<CFwInstaller>得到的
#define IMPLEMENT_SINGLETON_CREATOR()           \
static KSRESULT __stdcall CreateInstance(const KSIID &riid, void **ppv)\
{                                               \
	KS_ASSERT(ppv != NULL);                     \
	_ComType *p = NULL;                         \
	p = &SingletonHolder<_ComType>::Instance(); \
	KSRESULT hRes;                              \
	hRes = p->QueryInterface(riid, ppv);        \
	return hRes;\
}


 

//
//QueryInterface实现宏,一个QueryInterface实现可以如下
//KSCOM_QUERY_BEGIN;
//KSCOM_QUERY_ENTRY(IFaceSample);
//KSCOM_QUERY_END;
#define KSCOM_QUERY_BEGIN  public:          \
KSRESULT __stdcall QueryInterface(const KSIID &riid, void **ppv)\
{                                           \
    KSRESULT res = S_OK;                    \
    if (riid == KS_IIDOF(IUnknown)){      \
    *ppv = reinterpret_cast<IUnknown*>(this);


#define KSCOM_QUERY_ENTRY(_interface)       \
    }                                       \
    else if(riid == KS_IIDOF(_interface)){  \
    *ppv = static_cast<_interface*>(this); 
    

#define KSCOM_QUERY_ENTRY2(_interface, _derived)  \
    }                                             \
    else if(riid == KS_IIDOF(_interface)){        \
    *ppv = static_cast<_interface*>(static_cast<_derived*>(this));


#define KSCOM_QUERY_END   \
    }                     \
    else                  \
    {                     \
    *ppv = NULL;          \
    return E_NOINTERFACE; \
    }                     \
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();\
    return res;           \
}


 这样其他模块通过CLSID_IFwInstanceImpl就能得到CFwInstaller

接口,然后调用  CFwInstaller的三个public接口(由纯虚函数IFwInstaller继承得到的)。而把三个接口函数里用到的其它逻辑接口放到了protected:里.

class CFwInstaller : 
	public IFwInstaller,
	public KSComRoot<CFwInstaller> 
{
public:
    CFwInstaller();
    virtual ~CFwInstaller();

    STDMETHODIMP Install();
    STDMETHODIMP UnInstall();
    STDMETHODIMP SetConfig( DWORD dwEnableFlag, DWORD dwRequestFlag );


===============================================================================================

对于CFwProxy类的实现,同样有上述的特点。

(CFwProxy有一个函数相当重要: STDMETHODIMP CFwProxy::Initialize(IFwEvent* piEvent))

//
// 找开设备 L"\\\\.\\KTdiFilt"
// 通过判断Dump数据,是否有不兼容设备来判断是否能够加载
// 通过打开的设备注册事件TDI_EVENT_REGISTER
// 启动工作线程,通过等待刚刚注册的三个事件m_hExitEvent;m_hCommEvent;m_hActiveEvent;
// 当事件被激活时去获得相应的反馈信息,并把结果反馈给IFwEvent
STDMETHODIMP CFwProxy::Initialize(IFwEvent* piEvent)
{

.....

}

IFwEvent可以是KTdiDriverProxy,因为

HRESULT KTdiDriverProxy::Init(KProcessInfoMgr* pProcessMgr, KModuleMgr* pModuleMgr, KUrlMonCfg* pUrlCfgMon)
{

......

     if ( m_pFwProxy->Initialize( this ) != S_OK )
     {

......

    // 启动驱动服务 L"kmodurl"
     if ( !StartDriverSvr(TDI_FILTER_DRIVER) )

     }

     // 通过m_pFwProxy去通知设备全能防火墙
     m_pFwProxy->EnableFirewall();

}

 

这里我们总结出CFwInstaller类的COM接口代码的书写很工整,相当紧凑。如果遵循了这个规则,以后的扩展只要写各个类的逻辑就可以了。

COM维护相当方便。

 

2、在其他模块中使用此类COM的方法.

如果大家搜索CLSID_IFwProxyImp,那么可以找到加载上述讲到的FwProxy编译出来的FwProxy.dll接口的地方.

\oss\pcmanager\src\src_kpfw\netmon\netmon\urlmon\kdriverproxy.cpp

得到的接口放到了

IFwProxy *    m_pFwProxy;

 

HRESULT	KTdiDriverProxy::Init(KProcessInfoMgr* pProcessMgr, KModuleMgr* pModuleMgr, KUrlMonCfg* pUrlCfgMon)
{
	kws_log(TEXT("KTdiDriverProxy::Init begin"));
	m_pProcessMgr = pProcessMgr;
	m_pModuleMgr = pModuleMgr;
	m_pUrlCfgMon = pUrlCfgMon;

	// 启动驱动,如果发现没有安装,那么自动安装驱动,并且启动驱动
	if ( !LoadInterface(CLSID_IFwProxyImp, (VOID**)&m_pFwProxy) )
	{
		kws_log(TEXT("KTdiDriverProxy::Init LoadInterface failed"));
		return E_FAIL;
	}

 

来看一下LoadInterface的实现,它加载了DLL里的四个接口:

"KSDllGetClassObject"

"KSDllGetClassCount"

"KSDllGetClassInfo"

"KSDllCanUnloadNow"

最后调用GetClassObject便得到我们的接口

BOOL KTdiDriverProxy::LoadInterface(const GUID& iid,  void** pInterface )
{
	static KSDll dll;
	static BOOL b = FALSE;

	if (!b)
	{
		WCHAR wszProxy[MAX_PATH + 1] = { 0 };

		GetModuleFileName(NULL, wszProxy, MAX_PATH);
		*(wcsrchr(wszProxy, L'\\')) = 0L;
		wcscat_s(wszProxy, MAX_PATH, L"\\fwproxy.dll");

		if (S_OK == dll.Open(wszProxy))
			b = TRUE;
	}

	if (!b)
		return FALSE;

	return dll.GetClassObject(iid, iid, pInterface) == S_OK;
}



通过这种方式,即使多次调用LoadInterface(CLSID_IFwProxyImp, (VOID**)&m_pFwProxy)

也不会产生多个对象,因为里面采用了单件模式。

例如在上述使用的同一文件处又调用了此接口,并使用此接口的方法来操作了注册表。

BOOL KTdiDriverProxy::DoCheckForceDisableTDI()
{
	WCHAR bufPath[MAX_PATH] = {0};
	::GetModuleFileName(NULL, bufPath, MAX_PATH);
	::PathRemoveFileSpecW(bufPath);
	::PathAppend(bufPath, TEXT("AppData\\msg.ini"));
	int nNotify = GetPrivateProfileIntW(TEXT("netmon"), TEXT("forcedisabletdi"), 0, bufPath);

	IFwProxy* pProxy  = NULL;
	if ( !LoadInterface(CLSID_IFwProxyImp, (VOID**)&pProxy) )
	{
		kws_log(TEXT("KTdiDriverProxy::DoCheckForceDisableTDI LoadInterface failed"));
		return FALSE;
	}
	pProxy->SetForceDisableTdi(nNotify);
	pProxy->Release();
	return TRUE;
}

 

感谢一直支持我博客的朋友们,也请大家继续关注我的专栏,我一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。

开发的路还很长很长,非常希望能和大家一起交流,共同学习,共同进步。

大家看过后觉得值得一看的话,可以顶一下这篇文章,你们的支持是我继续写下去的动力~

如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。

最后,谢谢你们一直的支持~~~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

金山卫士开源软件之旅(四) netmon下FwProxy工程的解析---接口实现及接口使用方法 的相关文章

  • 是什么破坏了 .net 二进制 (dll) 接口

    考虑两个 net dll 首先 application dll 包含主要业务逻辑和数据访问代码 第二个 webservice dll 主要由 WebMethod 组成 这些 WebMethod 链接到 application dll 的对象
  • 如何将依赖项注入到实现接口的类中?

    我知道接口不能定义构造函数 强制所有类实现接口并以统一契约接收其依赖项的最佳实践是什么 我知道整数可以通过属性将依赖项注入到对象中 但通过构造函数传递它们对我来说更有意义 那么如何DI呢 我知道你说过你想要一份稳定的合同 但有一个优势not
  • Golang 函数指针作为结构的一部分

    我有以下代码 type FWriter struct WriteF func p byte n int err error func self FWriter Write p byte n int err error return self
  • 为什么接口变量默认是static和final?

    为什么Java中接口变量默认是static和final 来自 Philip Shaw 的 Java 界面设计常见问题解答 接口变量是静态的 因为 Java 接口不能以其自身的方式实例化 变量的值必须在不存在实例的静态上下文中分配 Final
  • 为什么我们要实现接口?

    实现接口只是提供方法的骨架 如果我们知道该方法的确切签名行 在这种情况下实现接口有什么要求 这是Interface已经实现的情况 interface IMy void X public class My IMy public void X
  • 具有混合成员类型的通用 TypeScript 接口

    对于几个 HTML 表单 我想配置输入并处理它们的值 我的类型具有以下结构 您可以将其复制到 TypeScript Playgroundhttp www typescriptlang org play http www typescript
  • JDK 8 中的默认值是 Java 中多重继承的一种形式吗?

    JDK 8 中的一项新功能允许您添加到现有接口 同时保留二进制兼容性 语法就像 public interface SomeInterface void existingInterface void newInterface default
  • 将接口作为参数传递给扩展方法

    我使用扩展方法来扩展 html 助手来制作 RSS 转发器 public static string RSSRepeater this HtmlHelper html IEnumerable
  • 桌面 webkit 相当于 Android 的 addJavascriptInterface()?

    在研究 Android UI 可能性时 我发现了一种名为 addJavascriptInterface 的方法的文档 该方法允许您将 Android Java 对象上的方法公开给 UI 的 WebView 组件中的 Javascript 这
  • Moq-ing 类或接口有什么区别?

    我一直在使用moq http code google com p moq 在我的单元测试中模拟对象 我在关于最小起订量的网站上看到它能够模拟类和接口 有一天 我与我的一位同事进行了讨论 他们表示没有理由模拟类 我应该只模拟接口 我对此并没有
  • 使用Java查找无线网络的SSID

    我们正在做一个用 Java 编码的项目 为 JRE 1 6 编译 需要一些帮助 一个有点但明显复杂的功能 我们希望在连接特定无线网络时执行特定操作 例如当连接的 SSID myNetworkAtHome 或类似名称时 在浏览了这个网站 谷歌
  • 界面与组合

    我想我理解接口和抽象之间的区别 抽象设置默认行为 在纯抽象的情况下 行为需要由派生类设置 接口是您所需要的 无需基类的开销 那么接口相对于组合的优势是什么 我能想到的唯一优点是在基类中使用受保护的字段 我缺少什么 你的标题没有意义 你的解释
  • 删除接口中的冗余类型

    我有以下接口 public interface IRevision
  • Android proguard Javascript 接口问题

    我的项目在使用 proguard 进行混淆后因 javascriptinterface 失败 这是包含混淆器配置的一些建议的链接 但它在我的情况下不起作用 http groups google com group android devel
  • C# 中 getter 和 setter 的接口

    当我读到这里时http msdn microsoft com en us library 75e8y5dd 28v VS 100 29 aspx http msdn microsoft com en us library 75e8y5dd
  • AXI4 流接口:如何在 HLS 中管理浮点数组以生成硬件加速器并在 RTL 项目中安全地连接它们?

    最后 我想做的是使用 Vivado Design Suite 中具有单精度浮点数组的流接口来构建硬件加速器 HLS 用户指南UG902 http www xilinx com support documentation sw manuals
  • Java中接口作为方法参数

    前几天去面试 被问到了这样的问题 问 反转链表 给出以下代码 public class ReverseList interface NodeList int getItem NodeList nextNode void reverse No
  • Delphi 中表单分发与其生命周期相关的接口对象的安全方法?

    我有一个 Delphi 表单 它提供接口对象背后的功能 代码的其他部分也通过属于该表单的属性获取引用 我无法将接口功能委托给子对象 因为太多的功能是由表单上的控件 组件提供的 我无法使用 TAggregateObject 或 TContai
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder
  • 验证 C# 中的属性

    让我们建议我有一个接口并从中继承类 internal interface IPersonInfo String FirstName get set String LastName get set internal interface IRe

随机推荐

  • 2022年CCCC天梯赛题解

    L1 1今天我要赢 原题链接 代码 include
  • Java中计时函数

    Java计时函数currentTimeMills System currentTimeMills 计时精确到毫秒级 跟计算机以1970年1月1日0时为计时起点一样 该函数方法统计的也是从1970年1月1日0时开始 到程序运行到该函数时刻的毫
  • Parameter 1 of constructor in xxx required a bean of type xxx‘ that could not be found.已经解决

    使用Mybatis Plus 时遇到问题Parameter 1 of constructor in xxx required a bean of type xxx that could not be found 已经解决 错误截图 错误原因
  • FPGA图像处理系列——乒乓球追踪设计实例

    注 本博文将讲解一个FPGA设计图像处理系统实例 此实例的功能为高速追踪乒乓球 读者可以参考本博文的算法思路 工程框架 但博主并不提供工程 当前 实用的图像处理系统都要求高速处理 目前广泛采用软件进行处理 但软件处理存在速度 成本的问题 近
  • MFC中CListCtrl改变选中行(选中列)的颜色实现选中高亮的效果

    在项目中遇到了这样的需求 需要对选中行进行高亮 查了一下相关的资料 记录一下自己采用的方法 先在List控件所在类中 这里是CListshow 继承于CListCtrl 添加两个变量SelectRow和SelectCol 用于保存鼠标点击的
  • QEMU虚拟机中如何安装Virtio驱动

    在计算机虚拟化中 Virtio是一种半虚拟化解决方案 即需要对Guest OS进行一定的修改 安装相应的驱动程序 能够对虚拟机的I O性能进行大幅的提升 在QEMU KVM的环境中 Virtio的后端驱动由QEMU程序提供 不需要额外的安装
  • 不要把领导当成客户

    以客户为中心的思想 几乎在所有公司都会被提及和执行 他的终极目标是和客户达成共赢 但是 并不是所有人都理解了以客户为中心 我今天想说的是来源于我们的一次工作讨论 几位新同事在分享服务案例的时候 提到自己的客户 经常把经理当成客户 他们是这样
  • python3 numpy安装 linux_Centos7安装python3、numpy、scipy、matplotlib、pandas等

    centos 7 已经自带 python 2 7 15 这里需要安装 python 3 root pwm python Python 2 7 15 Anaconda Inc default Dec 14 2018 19 04 19 GCC
  • 图(3)--拓扑排序与关键路径

    一 拓扑排序 1 定义 拓扑排序可以理解为在有向图无环图AOV 网 Activity On Vertex 用图的顶点表示活动 用弧表示活动之间的优先级 中排成一个具有前后次序的线性序列 2 实现方式 1 输入AOV网络 令 n 为顶点个数
  • 谷歌插件下载

    谷歌插件下载 在这个网站 https www extfans com 搜索下载 解压后得到xxx crx文件 将xxx crx后缀名改为xxx zip 解压xxx zip 得到xxx文件夹 在谷歌浏览器扩展程序中加载上面解压的文件夹
  • 面试题汇总(二)容器

    容器 18 java 容器都有哪些 常用容器的图录 19 Collection 和 Collections 有什么区别 java util Collection 是一个集合接口 集合类的一个顶级接口 它提供了对集合对象进行基本操作的通用接口
  • linux的相关知识

    本节内容我们主要介绍linux 的基本概念 shell的相关命令 一 Linux的基本知识 1 什么是Linux Linux是一套免费使用和自由传播的类Unix操作系统 是一个多用户 多任务 支持多线程和多CPU的操作系统 它能运行主要的U
  • 渲染方程的一点介绍

    来自 GAMES101 现代计算机图形学入门 闫令琪 哔哩哔哩 bilibili 反射方程 入射 反射 出射 没毛病 光线只弹射一次 入射光都来自光源 没毛病 但是 光线可能弹射的不止一次 这个入射 除了来自光源 还可能来自其它物体的反射
  • wpf RadioButton自定义样式 圆角/直角变化 背景色渐变

    样式部分
  • Oracle如何删除表空间

    1 删除无任何数据对象的表空间 用drop tablespace xxx 删除需要删除的表空间 2 删除有任何数据对象的表空间 使用drop tablespace xxx including contents and datafiles
  • Vue中页面生成二维码以及二维码图片下载

    有的场景中需要通过接口数据将内容生成二维码实现步骤如下 一 安装 qrcodejs2 包 二 import QRCode from qrcodejs2 页面中引入 QRCode 三 二维码创建 二维码占位 div div 代码生成 var
  • python中获取当前日期

    datetime 日期时间模块 提供多种方法操作日期和时间 strftime 对日期时间格式化 获取今天的日期 昨天的日期 格式化的日期 gt gt gt import datetime gt gt gt today datetime da
  • 遇到了 “遇到以零作除数错误” 的问题

    开发的时候 写了个很简单的Sql 大概就是 总数除以数量 得出的平均值 看起来很平常是不是 简单来说就是 Total Count 嘛 最多转个2位小数用Convert就完事了对不对 但是呢 有些数据的Count值本身是就是0的 然后就会报遇
  • docker gpu 创建 训练环境_基于虚拟化的模型训练平台实践

    写在前面 近几年 人工智能快速发展 与各行各业的结合也成为业界不断探索的方向 在金融科技领域 风控逐步从传统风控转向大数据风控以及智能风控 主要通过人工智能核心技术 知识图谱 机器学习 深度学习 作为主要驱动力 为金融业的各参与主体 各业务
  • 金山卫士开源软件之旅(四) netmon下FwProxy工程的解析---接口实现及接口使用方法

    转载请标明是引用于 http blog csdn net chenyujing1234 上一篇文章 lt lt 金山卫士开源软件之旅 三 netmon下FwProxy工程的解析 COM组件的管理模式 gt gt 中讲到如何去实现CFwPro