Click here to Skip to main content
15,885,365 members
Articles / Desktop Programming / ATL

ATL/AUX Library

Rate me:
Please Sign up or sign in to vote.
4.11/5 (5 votes)
17 Mar 2000CPOL 184.6K   1.5K   84  
A set of VC++ helpers and patterns to help automate some routine coding tasks.
////////////////////////////////////////////////////////////////////////////////
// ATL/AUX -- COM/C++ Exception handling & diagnostics
// Copyright (c) by Andrew Nosenko (andien@geocities.com), 1999
// http://www.geocities.com/~andien/atlaux.htm
// Version: 1.00.0001

/* Change Log:
1.00.0001
  - _CATCH_ANY added / catch(...) /
  - _CATCH_ALL() is defined as _CATCH_COM() _CATCH_AFX() _CATCH_ANY() 
1.00.0000
  - initial release
*/

#pragma once
#ifndef _AUXEH_H
#define _AUXEH_H

#ifndef _INC_COMDEF 
  #error You should #include <comdef.h> (VC COM support) before.
#endif

#ifndef _AUX_ATL_INDEPENDENT
  #error You should #include <AtlAux.h> (ATL/AUX main header) before.
#endif

#if (_MSC_VER >= 1200)  // VC6 or greater
  #pragma warning(push)
#endif    
#pragma warning(disable : 4290) // C++ Exception Specification ignored

inline AUXAPI_(void) AuxSetComErrorInfo(const _com_error& e) throw() {
  IErrorInfo* pErrorInfo = e.ErrorInfo();
  SetErrorInfo(0, pErrorInfo);
  if ( pErrorInfo ) 
    pErrorInfo->Release();
}

inline AUXAPI_(void) AuxRaiseComError(HRESULT hr) throw(_com_error) {
  void __stdcall _com_raise_error(HRESULT, IErrorInfo*) throw(_com_error); // from COMMSUPP.LIB
  IErrorInfo* pErrorInfo = NULL;
  GetErrorInfo(0, &pErrorInfo);
  if ( pErrorInfo ) {
    // cannot check for ISupportErrorInfo as there is no the interface
    // but put a simple check for FACILITY_DISPATCH:
    // isn't it a trashy ErrorInfo?
    if ( HRESULT_FACILITY(hr) != FACILITY_DISPATCH ) {
      // yes, don't consider it
      // SetErrorInfo(0, pErrorInfo);
      pErrorInfo->Release();
      pErrorInfo = NULL;
    }
  }
  _com_raise_error(hr, pErrorInfo); // pass pErrorInfo ownership
}

#define _CATCH_COM() \
  catch (_com_error& e) { \
    AuxSetComErrorInfo(e); \
    return _HR(e.Error()); } 

#define _CATCH_ANY() \
  catch ( ... ) { \
    HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); \
    if ( hr == NOERROR ) hr = E_UNEXPECTED; \
    return _HR(hr); }

#ifdef __AFX_H__ // handle MFC CException

// set COM ErrorInfo from AFX CException
inline AUXAPI_(void) AuxSetAfxErrorInfo(CException* e) throw() {
  ICreateErrorInfo* pICEI = NULL;
  if ( SUCCEEDED(CreateErrorInfo(&pICEI)) )
  {
    USES_CONVERSION;
    TCHAR szBuff[_AUX_MAX_DESC_TEXT]; szBuff[0] = '\0';
    UINT nHelpContext = 0;
    e->GetErrorMessage(szBuff, _countof(szBuff), &nHelpContext);
    CWinApp* pApp = AfxGetApp();
    ASSERT(pApp);
    pICEI->SetSource(T2OLE(pApp->m_pszAppName));
    pICEI->SetDescription(T2OLE(szBuff));
    if ( nHelpContext != 0 && pApp->m_pszHelpFilePath != NULL )
    {
      pICEI->SetHelpContext(0x00030000UL+nHelpContext); // HID_BASE_PROMPT
      pICEI->SetHelpFile(T2OLE(pApp->m_pszHelpFilePath));
    }
		pICEI->SetGUID(IID_NULL);
    IErrorInfo* pErrorInfo = NULL;
    if ( SUCCEEDED(pICEI->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo)) ) {
      SetErrorInfo(0, pErrorInfo);
      pErrorInfo->Release();
    }
    pICEI->Release();
  }
}

#define _CATCH_AFX() \
  catch ( CException* e ) { \
    AuxSetAfxErrorInfo(e); \
    e->Delete(); \
    return _HR(DISP_E_EXCEPTION); }

#define _SAFE_AFX(exp) \
  try { exp; } _CATCH_AFX()

// helper for _ON_ERROR
#define _ON_ERROR_CATCH_AFX() \
  catch ( CException* e ) { \
    AuxSetAfxErrorInfo(e); \
    e->Delete(); \
    $hr = DISP_E_EXCEPTION; }

#else // no __AFX_H__

#define _CATCH_AFX()
#define _ON_ERROR_CATCH_AFX()

#endif // __AFX_H__

#define _CATCH_ALL() \
  _CATCH_COM() _CATCH_AFX() _CATCH_ANY() 
    
#define _THROW(exp) \
  { HRESULT $hr = (exp); if ( _FAILED($hr) ) AuxRaiseComError($hr); }
  
#define _SAFE(exp) \
  try { exp; } _CATCH_COM()

#define _SAFE_ALL(exp) \
  try { exp; } _CATCH_ALL()

// _ON_ERROR is the universal facility to handle both HRESULT and exception errors.
// The original idea by Dr. John F. Holliday <jholliday@lexcel.com>
// As John noted, this is a real time saver for finding subtle errors that only 
// appear as exceptions. The downside is the amount of code that it generates.
//
// Example:
// _ON_ERROR(p->Test1(), return $hr);
// _ON_ERROR(p->Test2(), return E_FAIL);
// _ON_ERROR(p->Test3(), goto error);

#define _ON_ERROR(exp, action) \
  { \
    HRESULT $hr; \
    try { $hr = (exp); } \
    catch ( _com_error& e ) { \
      AuxSetComErrorInfo(e); \
      $hr = e.Error(); \
    } \
    _ON_ERROR_CATCH_AFX() \
    catch ( ... ) { \
      $hr = HRESULT_FROM_WIN32(GetLastError()); \
      if ( $hr == NOERROR ) $hr = E_UNEXPECTED; \
    } \
    if _FAILED($hr) { action; } \
  }

#if (_MSC_VER >= 1200)  // VC6 or greater
  #pragma warning(pop)
#endif    

#endif // _AUXEH_H

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions