Click here to Skip to main content
12,625,912 members (28,903 online)
Click here to Skip to main content

Stats

150.8K views
1.4K downloads
83 bookmarked
Posted

ATL/AUX Library

, 17 Mar 2000 CPOL
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)

Share

About the Author

Andrew Nosenko
Engineer
Australia Australia
No Biography provided

You may also be interested in...

Pro
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 18 Mar 2000
Article Copyright 2000 by Andrew Nosenko
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid