金山卫士开源软件之旅(三) netmon下FwProxy工程的解析----COM组件的管理模式
2012-04-09 09:23
330 查看
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
类似于MFC中加入COM,由放多的宏实现COM的定义和接口的声明。在金山卫士中也采用了MFC中加入COM的方法,这大大减少了开发COM的难度。
1、COM组件的管理模式。(单件模式)
FwProxy创建的dll为COM组件,它的COM创建方法与一般方法类似,但管理方法却采用单件模式,这值得我们学习。
先从最根的def文件开始吧.
它是从fwproxy.cpp文件里的DECLARE_DLLEXPORTS();定义的,我们来看看此宏做了什么
主要分析IMPLEMENT_KSDLLGETCLASSOBJECT,此宏分解开来是调用了COM工厂里的接口。
GlobalFactory是一个KFactory类的单件模式的包装。
单件类SingletonHoder值得我们学习。eg:给出接口Instance();返回实例的引用。
单件模式的实现主要通过以下两个函数:
2、COM组件的管理模式。(内部GUID自我维护)
我们来看一下维护这些GUID的窗口是什么,是一个map,KMODULEINFOMAP m_ComponentMap;
它的主要接口是
这是创建实例的函数。
那么大家一定有疑问COM组件的注册在哪里呢?
是的,这里有些人可能发现了KFactory中的一个成员函数KSRESULT Register(KMODULEINFO Info).
那么调用它的地方在哪里呢?
刚开始调用的地方是在fwproxy.cpp文件里的
通过构造的对象RegisterDummy中的构造函数把此CLSID(通过GetCLSID获得)和自己的创建对象方法指针(CreateInstance)注册.(其实是把它放到COM管理中去)
Register其实就是往自己的COM接口库里insert数据.
以上红色部分指的获得方法大家可以参照我的下一篇文章<<金山卫士开源软件之旅(四) /article/2054736.html>>
类似于MFC中加入COM,由放多的宏实现COM的定义和接口的声明。在金山卫士中也采用了MFC中加入COM的方法,这大大减少了开发COM的难度。
1、COM组件的管理模式。(单件模式)
FwProxy创建的dll为COM组件,它的COM创建方法与一般方法类似,但管理方法却采用单件模式,这值得我们学习。
先从最根的def文件开始吧.
EXPORTS KSDllGetClassObject @1 PRIVATE KSDllGetClassCount @2 PRIVATE KSDllGetClassInfo @3 PRIVATE KSDllCanUnloadNow @4 PRIVATE
它是从fwproxy.cpp文件里的DECLARE_DLLEXPORTS();定义的,我们来看看此宏做了什么
#define DECLARE_DLLEXPORTS() \ IMPLEMENT_KSDLLGETCLASSOBJECT() \ IMPLEMENT_KSDLLGETCLASSCOUNT() \ IMPLEMENT_KSDLLGETCLASSINFO() \ IMPLEMENT_KSDLLCANUNLOADNOW()
主要分析IMPLEMENT_KSDLLGETCLASSOBJECT,此宏分解开来是调用了COM工厂里的接口。
#define IMPLEMENT_KSDLLGETCLASSOBJECT() \ extern "C" \ KSRESULT __stdcall KSDllGetClassObject(const KSCLSID &clsid, const KSIID &riid , void **ppv) \ {\ return GlobalFactory::Instance().CreateInstance(clsid,riid, ppv); \ }
GlobalFactory是一个KFactory类的单件模式的包装。
typedef SingletonHolder_Static<KFactory> GlobalFactory;
单件类SingletonHoder值得我们学习。eg:给出接口Instance();返回实例的引用。
////////////////////////////////////////////////////////////////////////// //这个单件模板可以被静态(或全局)对象的构造函数调用,因为KSComThreadMutex没有构造函数, //是通过内部的标记判断是否初始化,如果没有初始化则进行初始化,但是由于第一次调用到时才进行 //KSComThreadMutex的初始化,当不是被静态(或全局)对象的构造函数调用时,如果多线程同时调用 //Instance()函数,有被初始化两次的可能. template<class T> class SingletonHolder_Static { public: typedef T* volatile _PtrInstanceType; static T& Instance(); private: SingletonHolder_Static(){}; SingletonHolder_Static(const SingletonHolder_Static&){}; SingletonHolder_Static& operator = (const SingletonHolder_Static&){}; // ~SingletonHolder() // { // m_pInstance = 0; // m_destroyed = true; // }; static void MakeInstance(); static void DestroySingleton(); static void OnDeadReference(); struct _Lock { _Lock() { m_Lock.Lock(); } ~_Lock() { m_Lock.Unlock(); } }; friend struct _Lock; private: static KSComThreadMutex m_Lock; static _PtrInstanceType m_pInstance; static bool m_destroyed; };
单件模式的实现主要通过以下两个函数:
template<class T> inline T& SingletonHolder_Static<T>::Instance() { if (!m_pInstance) { MakeInstance(); } return *m_pInstance; } ////////////////////////////////////////////////////////////////////////// //MakeInstance() template<class T> inline void SingletonHolder_Static<T>::MakeInstance() { //KSClassLockGuard<T> guard; _Lock guard; //防止多线程时初始化两次 if (!m_pInstance) { if (m_destroyed) { OnDeadReference(); } //static T TheInstance; //m_pInstance = &TheInstance; m_pInstance = new T; m_destroyed = false; atexit(DestroySingleton); } }
2、COM组件的管理模式。(内部GUID自我维护)
我们来看一下维护这些GUID的窗口是什么,是一个map,KMODULEINFOMAP m_ComponentMap;
class KFactory { #if _MSC_VER >= 1400 template<class T> friend class SingletonHolder_Static; #else friend class SingletonHolder_Static<KFactory>; #endif public: typedef std::map< KSCLSID, KMODULEINFO > KMODULEINFOMAP; private: KMODULEINFOMAP m_ComponentMap;
它的主要接口是
KSRESULT CreateInstance(const KSCLSID &clsid, const KSIID &riid, void **ppv) { //try //{ KMODULEINFOMAP::iterator iter = m_ComponentMap.find(clsid); if (iter != m_ComponentMap.end()) { KSRESULT hRes = (iter->second).m_pfnCreateInstance(riid, ppv); return hRes; } else { return NTE_NOT_FOUND; } //} //catch(...) //{ // SCOM_ASSERT_MESSAGE(SCOM_ASSERT_TEXT("CreateInstance failed.Maybe you haven't Initialized SCOM library"), false); // return E_FAIL; //} }
这是创建实例的函数。
那么大家一定有疑问COM组件的注册在哪里呢?
是的,这里有些人可能发现了KFactory中的一个成员函数KSRESULT Register(KMODULEINFO Info).
那么调用它的地方在哪里呢?
刚开始调用的地方是在fwproxy.cpp文件里的
REGISTER_TO_FACTORY(CFwProxy,"IFwProxy.1"); REGISTER_TO_FACTORY(CFwInstaller,"IFwInstaller.1");
//产生静态对象的宏 #define REGISTER_TO_FACTORY(_class, _ProgID) \ static RegisterDummy dummy##_class(_class::GetCLSID(), _class::CreateInstance, _ProgID, 0);
通过构造的对象RegisterDummy中的构造函数把此CLSID(通过GetCLSID获得)和自己的创建对象方法指针(CreateInstance)注册.(其实是把它放到COM管理中去)
Register其实就是往自己的COM接口库里insert数据.
//注册组件信息的类 class RegisterDummy { public: RegisterDummy(const KSCLSID& clsid, _SCOM_CREATORFUNC *pfnCreateInstance, const char *pszProgID, DWORD dwProperty) { m_MoudleInfo.m_CLSID = clsid; m_MoudleInfo.m_pfnCreateInstance = pfnCreateInstance; m_MoudleInfo.m_pszProgID = pszProgID; m_MoudleInfo.m_dwProperty = dwProperty; GlobalFactory::Instance().Register(m_MoudleInfo); }
KSRESULT Register(KMODULEINFO Info) { std::pair<KMODULEINFOMAP::iterator, bool> RetPair = m_ComponentMap.insert( KMODULEINFOMAP::value_type(Info.m_CLSID, Info) ); //m_ComponentMap[Info.m_CLSID] = Info; if(RetPair.second) { return S_OK; }
以上红色部分指的获得方法大家可以参照我的下一篇文章<<金山卫士开源软件之旅(四) /article/2054736.html>>
相关文章推荐
- 金山卫士开源软件之旅(三) netmon下FwProxy工程的解析----COM组件的管理模式
- 金山卫士开源软件之旅(四) netmon下FwProxy工程的解析---接口实现及接口使用方法
- 金山卫士开源软件之旅(八) netmon下netmon工程的解析---netmon.exe的启动过程分析
- 金山卫士开源软件之旅(七) netmon下netmon工程的解析---接口KTdiDriverProxy的实现
- 黑莓9000(DM6.0+ROM5.0)解决媒体文件管理问题――工程模式开启大容量存储模式
- 凯云水利水电工程造价管理系统 技术解析(五) 取费管理(二)
- 凯云水利水电工程造价管理系统 技术解析(八) 机械单价(三)
- 凯云水利水电工程造价管理系统 技术解析(七) 机械单价(二)
- 金山卫士开源软件之旅(八) netmon下netmon工程的解析---netmon.exe的启动过程分析
- 凯云水利水电工程造价管理系统 技术解析(四)取费管理(一)
- 凯云水利水电工程造价管理系统技术解析(二) 项目属性
- VMware三种网络模式解析及利用远程登录管理工具连接虚拟机中的Linux
- catia设置技巧教程:进入管理模式VS工程图模板(如何进入管理模式)
- KVM虚拟机存储管理:三大存储模式性能解析对比
- 第127讲:Hadoop集群管理之安全模式解析及动手实战学习笔记
- 凯云水利水电工程造价管理系统 技术解析(十一) 中间单价(二)
- 工程文件管理之makefile最简单模式
- 凯云水利水电工程造价管理系统 技术解析(六) 机械单价(一)
- 凯云水利水电工程造价管理系统 技术解析(九)机械单价(四)
- 凯云水利水电工程造价管理系统 技术解析(三)项目属性(二)