previous page
next page

CComCoClass Revisited

Earlier in this chapter, you saw how deriving from CComCoClass provided your class with a default implementation of a class factory, as well as default support for aggregation.

CComCoClass provides aggregation support via inheritance of the DECLARE_AGGREGATABLE macro's typedef of _CreatorClass. It also provides the default implementation of a class factory via inheritance of the DECLARE_CLASS_FACTORY macro's _ClassFactoryCreatorClass typedef.

The Error Methods

CComCoClass also provides a number of other useful static methods. Six of the methods are overloaded and call Error. They set up the COM Error object using its IErrorInfo interface to provide rich error information to the client. To call Error, your object must implement the ISupportErrorInfo interface.

When the hRes parameter is nonzero, Error returns the value of hRes. When hRes is zero, the first four versions of Error return DISP_E_EXCEPTION. The remaining two functions return the result of the macro MAKE_HRESULT(3, FACILITY_ITF, nID), creating a custom failure hrESULT.

static HRESULT WINAPI                                            
Error(LPCOLESTR lpszDesc, const IID& iid = GUID_NULL,            
    HRESULT hRes = 0);                                           
                                                                 
static HRESULT WINAPI                                            
Error(LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
      const IID& iid = GUID_NULL, HRESULT hRes = 0);             
                                                                 
static HRESULT WINAPI                                            
Error(LPCSTR lpszDesc, const IID& iid = GUID_NULL,               
    HRESULT hRes = 0);                                           
                                                                 
static HRESULT WINAPI                                            
Error(LPCSTR lpszDesc, DWORD dwHelpID, LPCSTR lpszHelpFile,      
      const IID& iid = GUID_NULL, HRESULT hRes = 0);             
                                                                 
static HRESULT WINAPI                                            
Error(UINT nID, const IID& iid = GUID_NULL, HRESULT hRes = 0,    
      HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());   
                                                                 
static HRESULT WINAPI                                            
Error(UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile,          
      const IID& iid = GUID_NULL, HRESULT hRes = 0,              
      HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());   

It might seem odd that ATL includes the Error functionality in CComCoClass instead of in a more widely applicable place, such as CComObjectRootEx. The reason for this placement is that COM error reporting needs a CLSID, and the CLSID is stored in CComCoClass. If you need to generate rich error information when your class isn't derived from CComCoClass, you can always call the ATL helper function AtlReportError. The CComCoClass::Error methods all use this helper function.

inline HRESULT WINAPI AtlReportError(const CLSID& clsid,       
     UINT nID,                                                 
     const IID& iid = GUID_NULL,                               
     HRESULT hRes = 0,                                         
     HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());  
                                                               
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,       
    UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile,          
    const IID& iid = GUID_NULL,                                
    HRESULT hRes = 0,                                          
    HINSTANCE hInst = _AtlBaseModule.GetResourceInstance());   
                                                                
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,       
    LPCSTR lpszDesc,                                           
    DWORD dwHelpID, LPCSTR lpszHelpFile,                       
    const IID& iid = GUID_NULL,                                
    HRESULT hRes = 0);                                         
                                                                
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,       
    LPCSTR lpszDesc,                                           
    const IID& iid = GUID_NULL, HRESULT hRes = 0);             
    inline HRESULT WINAPI AtlReportError(const CLSID& clsid,   
    LPCOLESTR lpszDesc,                                        
    const IID& iid = GUID_NULL, HRESULT hRes = 0);             
                                                                   
inline HRESULT WINAPI AtlReportError(const CLSID& clsid,       
    LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile,
    const IID& iid = GUID_NULL, HRESULT hRes = 0);             

The Instantiation Methods

CComCoClass also provides two useful overloaded CreateInstance methods that create an instance of your class, one for creating an aggregated instance of your class and one that creates a nonaggregated instance:

template <class Q>                                               
static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) {     
  return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q),
    (void**) pp);                                                
}                                                                
                                                                 
template <class Q>                                               
static HRESULT CreateInstance(Q** pp) {                          
  return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q),     
    (void**) pp);                                                
}                                                                

You use these two methods like this.

ISpeaker* pSpeaker;
// Creates non-aggregated instance
HRESULT hr = CDemagogue::CreateInstance (&pSpeaker);
// Creates aggregated instance (assuming the class supports aggregation
HRESULT hr = CDemagogue::CreateInstance (punkOuter, &pSpeaker);

Note that the use of the __uuidof operator in the template functions means that you do not have to specify the interface ID for the interface that you want on the newly instantiated object. The compiler gets the ID from the type of the interface pointer variable you pass as an argument to the CreateInstance method.


previous page
next page
Converted from CHM to HTML with chm2web Pro 2.75 (unicode)