The first function called in a COM dll when instantiating the COM object

When a program calls the COM lib function CoCreateInstance, what will happen? What work does CoCreateInstance do? How does CoCreateInstance work? The function has a parameter classid. The function looks the class id up in the registry to get the corresponding dll, loads that dll, resolves the address of the pre-known function  DllGetClassObject in that dll, and calls that function passing the parameters classid and the interface id of IID_IClassFactory(00000001-0000-0000-C000-000000000046):

STDAPI DllGetClassObject(const GUID &clsid, const GUID &iid, void** ppv)

The GUID structure accommodates the class id or the interface ID. It is kind of special. It has 4 members: Data1,Data2,Data3, and Data4. Data1 is of type unsigned long(4 bytes) containing the first 8 hex digits of the UUID. Data2 is of type unsigned short holding the second group of 4 hex digits of the UUID. Data3 is of type unsigned short holding the third group of 4 hex digits of the UUID. Data4 is a char array, the first two bytes hold the fourth group of 4 hex digits of the UUID and the remaining chars holds the remaining 12 hex digits of the UUID.

The DllGetClassObject need be existent in the dll but needn’t be exported. It is called to instantiate the class factory class QClassFactory and return the IID_IClassFactory interface of the instantiated class factory object. We can see now the clsid is not bound to some class. It is not the class id of QClassFactory. DllGetClassObject can create an object of any class as the class factory. clsid is just used to bind to a dll (through registry) so far.

The QClassFactory is not the real class factory that creates your class doing the real job. The real class factory class is QAxDefaultFactory (inherited from QAxFactory) defined in qaxfactory.h. This class knows(binds) to the class defined in your own project so you can use its member function createObject to create the object of your own class. Why does this class know your class? Because when defining QAxDefaultFactory, we provide our class name(like MyClassBinder) together with the CLASSID,InterfaceID,TypeLibID, and EventID. The QClassFactory is just used to implement the IClassFactory2 interface so the QAxDefaultFactory does not need to do the COM stuff. The constructor of QClassFactory will call the qAxFactory function (in qaxserver.cpp) to create the real class factory(QAxDefaultFactory  object) and save it to the static variable: qax_factory(in qaxserver.cpp). After creating the real class factory, QClassFactory compares the clsid with the class id bound to the real factory. If they match, the class name bound to the real factory is also bound to QClassFactory so from now on, the QClassFactory also becomes the factory of the class(like MyClassBinder).

Using the IID_IClassFactory interface returned by the DllGetClassObject function, COM lib can create(QClassFactory ::CreateInstance) the COM class now as per the COM spec. The aim is to obtain the IUnknown interface(00000000-0000-0000-C000-000000000046) of the COM class. After all, the fourth parameter when calling the CoCreateInstance function requires the IUnknown interface. Since QClassFactory has known the class MyClassBinder in the last step, it can create the object of this class(actually QAxServerBase object that controls its member qt – the MyClassBinder object, see CreateInstanceHelper in qaxserverbase.cpp) which is the COM class in the COM spec. The controlling object has a aggregatedObject pointer pointing to the MyClass object created by the  MyClassBinder object. We query the IUnkown interface of the created COM class object and return it to the COM lib. Finally, the CoCreateInstance can return with the obtained IUnkown interface of the created COM class object(the QAxServerBase object). Note that the QAxServerBase class implements many COM interfaces so our class MyClassBinder or MyClass do not need to implement them again.

In summary, as per the COM spec, Qt implements the QClassFactory as the class factory class and QAxServerBase as the COM class. But QClassFactory is just a wrapper of the real class factory QAxDefaultFactory , and QAxServerBase  is just a wrapper of the real COM class MyClassBinder.

The QAxServerBase  object delegates the IUnknown interface and transfers other interface queries to its aggregated object(MyClass). But MyClass usually only implements the interfaces that are doing the real job. Other unimplemented interfaces such as IID_IDispatch,IID_IAxServerBase,IID_IOleObject,IID_IConnectionPointContainer,IID_IProvideClassInfo,IID_IProvideClassInfo2,IID_IPersist,IID_IPersistStream,IID_IPersistStreamInit,IID_IPersistStorage,IID_IPersistPropertyBag,IID_IPersistFile,IID_IViewObject,IID_IViewObject2,IID_IOleControl,IID_IOleWindow,IID_IOleInPlaceObject,IID_IOleInPlaceActiveObject,IID_IDataObject by MyClass are also provided by QAxServerBase including the interface ID defined in the definition of QAxDefaultFactory which is actually an IDispatch interface.

In COM client, the COM class MyClassBinder is usually wrapped by a QAxObject(or QAxWidget) class which has methods to facilitize the creation(QAxBase::setControl(“classid”))/method calls of the COM class.

 

 

 

 

Did you like this?
Tip admin with Cryptocurrency

Donate Bitcoin to admin

Scan to Donate Bitcoin to admin
Scan the QR code or copy the address below into your wallet to send some bitcoin:

Donate Bitcoin Cash to admin

Scan to Donate Bitcoin Cash to admin
Scan the QR code or copy the address below into your wallet to send bitcoin:

Donate Ethereum to admin

Scan to Donate Ethereum to admin
Scan the QR code or copy the address below into your wallet to send some Ether:

Donate Litecoin to admin

Scan to Donate Litecoin to admin
Scan the QR code or copy the address below into your wallet to send some Litecoin:

Donate Monero to admin

Scan to Donate Monero to admin
Scan the QR code or copy the address below into your wallet to send some Monero:

Donate ZCash to admin

Scan to Donate ZCash to admin
Scan the QR code or copy the address below into your wallet to send some ZCash:

Leave a Reply