65.9K
CodeProject is changing. Read more.
Home

Easy handling number of HRESULTs

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (6 votes)

Jun 15, 2002

viewsIcon

61247

Handling HRESULT return values with TRY_HRESULT/CATCH_HRESULT macros

Introduction

Handling HRESULT return values is always hard job for creative programmers. I found a solution which uses exceptions mechanism and all HRESULTs can be handled at once. It's simple - override the operator = for function calls and use it for error handling.

TRY/CATCH HRESULT macros

void OutputHresult(HRESULT hr, UINT nTextID);
#define TRY_HRESULT(hr) HRESULT_EX hr; try {
#define CATCH_HRESULT(hr, nTextID) } catch(HRESULT hr) 
    { if(hr != S_OK) OutputHresult(hr, nTextID); }

struct HRESULT_EX
{
    void operator = (const HRESULT& hr)
    { 
        if(FAILED(hr))
            throw hr;
    }
};

void OutputHresult(HRESULT hr, UINT nTextID)
{
    CString sText = (LPCSTR)nTextID;
    LPTSTR szError;
    if(HRESULT_FACILITY(hr) == FACILITY_WINDOWS)
        hr = HRESULT_CODE(hr);
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPTSTR)&szError, 0, NULL);
    CHAR s[MAX_PATH];
    sprintf(s, "%s\n\nError number 0x%x\n%s", 
        sText, hr, szError);
    MessageBox(NULL, s, "Error", 
        MB_ICONWARNING);
    LocalFree(szError);
}

Standard HRESULT return values handling

#include <afxoledb.h>

HRESULT OpenDatabase()
{
    HRESULT hr;

    CDataSource db;
    CSession session;

    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(
        DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE,
        "MyDatabase");
    dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
    dbinit.AddProperty(DBPROP_INIT_LCID, (long)1029);

    hr = db.OpenWithServiceComponents("MSDASQL.1",
        &dbinit);
    if(FAILED(hr)) // check for errors
        return hr;

    hr = session.Open(db);
    if(FAILED(hr)) // check for errors
        return hr;

    return hr;
}

HRESULT handling with TRY_HRESULT/CATCH_HRESULT macros

bool OpenDatabase2()
{
    bool bRetVal = false;

    // --- begin of HRESULT checking ---

    TRY_HRESULT(hr)                          
        // try statement, HRESULT_EX definition

        CDataSource db;
    CSession session;

    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(
        DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE, 
        "MyDatabase");
    dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
    dbinit.AddProperty(DBPROP_INIT_LCID, (long)1029);

    hr = db.OpenWithServiceComponents(
        "MSDASQL.1", &dbinit);
    // do not need to check for errors
    hr = session.Open(db);
    // do not need to check for errors

    bRetVal = true; // all HRESULTs succeeded

    CATCH_HRESULT(hr, IDS_ERROR_HR_OLEDB) // catch statement

        // --- end of HRESULT checking ---

        return bRetVal;
}