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))
return hr;
hr = session.Open(db);
if(FAILED(hr))
return hr;
return hr;
}
HRESULT handling with TRY_HRESULT/CATCH_HRESULT macros
bool OpenDatabase2()
{
bool bRetVal = false;
TRY_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);
hr = session.Open(db);
bRetVal = true;
CATCH_HRESULT(hr, IDS_ERROR_HR_OLEDB)
return bRetVal;
}