您的位置:首页 > 其它

金山卫士开源软件之旅(三) netmon下FwProxy工程的解析----COM组件的管理模式

2014-01-21 01:08 351 查看
类似于MFC中加入COM,由放多的宏实现COM的定义和接口的声明。在金山卫士中也采用了MFC中加入COM的方法,这大大减少了开发COM的难度。

1、COM组件的管理模式。(单件模式)

FwProxy创建的dll为COM组件,它的COM创建方法与一般方法类似,但管理方法却采用单件模式,这值得我们学习。

先从最根的def文件开始吧.

[cpp] view
plaincopy

EXPORTS

KSDllGetClassObject @1 PRIVATE

KSDllGetClassCount @2 PRIVATE

KSDllGetClassInfo @3 PRIVATE

KSDllCanUnloadNow @4 PRIVATE

它是从fwproxy.cpp文件里的DECLARE_DLLEXPORTS();定义的,我们来看看此宏做了什么

[cpp] view
plaincopy

#define DECLARE_DLLEXPORTS() \

IMPLEMENT_KSDLLGETCLASSOBJECT() \

IMPLEMENT_KSDLLGETCLASSCOUNT() \

IMPLEMENT_KSDLLGETCLASSINFO() \

IMPLEMENT_KSDLLCANUNLOADNOW()

主要分析IMPLEMENT_KSDLLGETCLASSOBJECT,此宏分解开来是调用了COM工厂里的接口。

[cpp] view
plaincopy

#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类的单件模式的包装。

[cpp] view
plaincopy

typedef SingletonHolder_Static<KFactory> GlobalFactory;

单件类SingletonHoder值得我们学习。eg:给出接口Instance();返回实例的引用。

[cpp] view
plaincopy

//////////////////////////////////////////////////////////////////////////

//这个单件模板可以被静态(或全局)对象的构造函数调用,因为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;

};

单件模式的实现主要通过以下两个函数:

[cpp] view
plaincopy

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;

[cpp] view
plaincopy

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;

它的主要接口是

[java] view
plaincopy

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文件里的

[cpp] view
plaincopy

REGISTER_TO_FACTORY(CFwProxy,"IFwProxy.1");

REGISTER_TO_FACTORY(CFwInstaller,"IFwInstaller.1");

[cpp] view
plaincopy

//产生静态对象的宏

#define REGISTER_TO_FACTORY(_class, _ProgID) \

static RegisterDummy dummy##_class(_class::GetCLSID(), _class::CreateInstance, _ProgID, 0);

通过构造的对象RegisterDummy中的构造函数把此CLSID(通过GetCLSID获得)和自己的创建对象方法指针(CreateInstance)注册.(其实是把它放到COM管理中去)

Register其实就是往自己的COM接口库里insert数据.

[cpp] view
plaincopy

//注册组件信息的类

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;

<span style="color:#000000;">GlobalFactory::Instance().Register(m_MoudleInfo);

</span> }

[cpp] view
plaincopy

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>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐