Description of COM principle

来源:互联网 发布:伯爵表 知乎 编辑:程序博客网 时间:2024/05/17 07:54

转自;http://blog.csdn.net/guogangj/article/details/1801788

Description of COM principle

 

I was completely overwhelmed by COM technology. It is very difficult to understand. I think its mechanism can confuse all beginners. ATL is a good solution for COM, but it is not a good way to break the barrier. So I want to write an article about the simplest COM. If you have read many articles about COM, but you still feel difficult to know it, this article is for you.

 

This article is about creating an in-process COM object without ATL and I will explain the detail of COM mechanism.

 

The four functions in the DLL

 

Use Depends to open a COM DLL. And then you will find there are four exported functions in this DLL. For example:

 

These four functions are not called by the client directly but called by the COM Library. What’s the COM Library? It’s the library of COM support on Microsoft Windows. It’s very important. Without it, our COM is not exactly COM. J According to the COM Library’s rule, we must do some jobs. Implementation of these four functions is one of these jobs. Of course, you must follow the COM Library’s rule. Without ATL, we can implement them manually. There is a description of these four functions below:

DllGetClassObject

This is the most important function. It creates the Class Factory, and returns the IFactory interface to the COM Library.

DllRegisterServer

Write some information to the Windows Register. COM Library will find this information when it needs. Our Windows has a tool called Regsvr32. If we want to register a COM DLL, we can use this command:regsvr32 ACOMDLL.dll

DllUnRegisterServer

This is the reverse operation of DllRegisterServer. If we want to unregister a COM DLL, we can use this command:regsvr32 -u ACOMDLL.dll

DllCanUnloadNow

To detect if this DLL can be unloaded. It returns true if there is no reference to the objects of this DLL, otherwise it returns false.

 

The process of COM calling

 

The following figure describes the process of COM calling. Drawing this figure is not an easy job. Will you applaud for me?J

All things are very clear on the figure above. You can find when dose the COM Library call the DllGetClassObject and DllCanUnloadNow. Are you clear? I assume so.

 

The things we must implement

 

Now, you know the process of COM calling. Question, how many things shall we prepare for our COM? Please think about that for a while.

 

OK, I think we need the following items:

 

1, A DLL. Yes, we need a DLL. And how can we create a DLL? Many articles have discussed this issue. I won’t repeat. But please remember. You should export the four functions discussed above.

 

2, Create a COM Class. This is complex. But in this DEMO article, it’s very simple. We won’t implement any complex function. We just write something to test. Please remember, our COM Class must be derived from some Interface. This is a very simple example:

class ISomeInterface : public IUnknown

{

     public:

         virtual HRESULT SomeFunction()=0;

};

 

class CACom : public ISomeInterface

{

protected:

     ULONG m_Ref;

public:

     CACom();

     ~CACom();

     HRESULT QueryInterface(REFIID iid, void **ppv);

     ULONG AddRef();

     ULONG Release();

     HRESULT SomeFunction( ) ;

};

 

3, Implement the DllGetClassObject function. Because the four functions are called by the COM Library, we must follow its rule. We can define a Factory in this way:

class CAComFactory : public IClassFactory;

IClassFactory is defined in the UNKNWN.h head file. It’s a pure virtual class derived from IUnknown. Its prototype is:

MIDL_INTERFACE("00000001-0000-0000-C000-000000000046")

IClassFactory : public IUnknown

{

public:

       virtual HRESULT CreateInstance(IUnknown *pUnkOuter, REFIID riid, void *ppvObject) = 0;

       virtual HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) = 0;

};

And this is the prototype of CAComFactory:

class CAComFactory : public IClassFactory

{

protected:

       ULONG m_Ref;

public:

       CAComFactory();

       ~CAComFactory();

       HRESULT QueryInterface(REFIID, void **ppv);

       ULONG AddRef();

       ULONG Release();

       HRESULT CreateInstance(IUnknown *, REFIID iid, void **ppv);

       HRESULT LockServer(BOOL);

};

We must implement it. In CreateInstance:

HRESULT CAComFactory::CreateInstance(IUnknown * pUnkOuter, REFIID iid, void **ppv)

{

       CACom  *pObj;

       HRESULT hr=E_OUTOFMEMORY;

       *ppv=NULL;

       if (NULL != pUnkOuter)

              return CLASS_E_NOAGGREGATION;

       pObj=new CACom();

       if (NULL==pObj)

            return hr;

       pObj->AddRef(); // Ref++. ==1

       hr=pObj->QueryInterface(iid, ppv); //Ref++. ==2

     pObj->Release();   // Ref--. ==1

     return hr;

}

Remember, function CreateInstance can be called by either COM Library or Client. If the Client uses CoGetClassObject, it should call IClassFactory::CreateInstance explicitly to get the COM object. If the Client uses CoCreateInstance, the COM Library would call IClassFactory::CreateInstance and return the COM object to the Client.

 

DllGetClassObject is used to create the Factory. We can implement the DllGetClassObject function like that:

HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)

{

     if (clsid == CLSID_CompACom)

     {

         CAComFactory *pFactory = new CAComFactory;

         if (pFactory == NULL)

              return E_OUTOFMEMORY ;

         HRESULT result = pFactory->QueryInterface(iid, ppv);

         return result;

     }

     else

         return CLASS_E_CLASSNOTAVAILABLE;

}

OK, OK, I think I have talked too much about this item. But it’s complex. Now, let move to the next item. Relax. It’s close to the end.

 

4, Implement DllRegisterServer and DllUnRegisterServer. Both they are register operators. I won’t write the detail operations there. I only prompt that you can use the functions such as RegCreateKeyEx, RegSetValueEx, RegDeleteKey to achieve this task.

The location you should operate in the register is:

/HKEY_CLASSES_ROOT/CLSID/{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}/

This table is the values we concern:

Name

Type

Comment

(Default)

REG_SZ

Short comment about this component

InprocServer32/(Default)

REG_SZ

The DLL’s location

ProgID/(Default)

REG_SZ

The component’s name. (Unique)

 

Summary

 

The client uses the COM Library to access the component. The COM Library uses the four exported functions to operate the DLL. And the DLL must follow some rule to fit the COM Library. What we discussed is the rule and the process. That’s so-called mechanism.

 

OK, that’s enough. I cannot continue because of my limit on this topic. But you can contact me if you have any question.

 

The last, this is my first technical article in English, I hope you like it.

0 0