Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Handling error results

Status
Not open for further replies.

btaber

Programmer
May 26, 2002
307
0
0
US
First of all, I am not much of a C programmer..

How can I do a lookup of error text based on a hex result? I need to modify an existing prog to get some better information from errors returned. Errors from a dll are returned in hex, and I have a header file that containes all the error defines, some of them are:

Code:
#define hrNyi                            ((HRESULT)0xC0000001L)
#define hrCBDatabaseInUse                ((HRESULT)0xC7FE1F41L)
#define hrCBDatabaseNotFound             ((HRESULT)0xC7FE1F42L)

How can I use these to get better error messages? If I can't use these, what can I do?

 
Are those Windows error codes or custom error codes?
If they're standard Windows error codes, you can use FormatMessage() to get a text description of the error.
 
The way I'd normally approach this is to use macros. Not everyone's cup of tea but here goes.

1) Pick a macro name, say HRERR. Something short otherwise you'll get pissed off writing it.
2) Define all the errors in a file but do not define HRERR.
Code:
HRERR(hrNyi,0xC0000001L,"whateverNYI means")
HRERR(hrCBDatabaseInUse,0xC7FE14F1L,"Database in use")
...
Say we call this file HRERRInc.h
3) Create a file for the error codes, say HERR.h
Code:
#ifndef HERR_h
#define HERR_h
#define HRERR(tag,val,msg) extern const HRESULT tag;
#include "HRERRInc.h"
#undef HRERR
/* Print the string */
extern void HRERRTerse(HRESULT hres);
extern void HRERRVerbose(HRESULT hres);
#endif
This will be included by all files using the error codes
4) Create a file for the values of the codes. HERR.c
Code:
#define HRERR(tag,val,msg) const HRESULT tag = (HRESULT)val;
#include "HRERRInc.h"
#undef HRERR

/* Terse error message */
void HRERRTerse (HRESULT hres)
{
   switch (hres)
   {
#define HRERR(tag,val,msg) \
   case val: \
      printf (#tag "\n"); \
      break;
#include "HRERRInc.h"
#undef HRERR

   default:
      printf ("Unknown code %08X\n", hres);
      break;
   }
}
/* Verbose error message */
void HRERRVerbose (HRESULT hres)
{
   switch (hres)
   {
#define HRERR(tag,val,msg) \
   case val: \
      printf (msg "\n"); \
      break;
#include "HRERRInc.h"
#undef HRERR

   default:
      printf ("Unknown code %08X\n", hres);
      break;
   }
}

And that's it. The advantages are

a) If you need to add a new message, you only have to add it to HERRInc.h and rebuild
b) If you wish to see where hrNYI is used, it will show up when you grep for it. There is a temptation to do this
Code:
HRERR(NYI,...)
...
#define HRERR(tag,val,msg) const HRESULT hr##tag = (HRESULT) val;
but it causes problems in maintenance in that nobody can find where hrNYI is defined. It is one of the reasons why not many coders like macros
c) If you wish to add a second language or change the language of the messages, the mods are localized to a few files.

I've been using this technique since 1988 when I first learnt C. SOme love it, others hate it.
 
I hate having lots of #define's since it can cause really annoying conflicts if someone decides to use the same name for a function or variable.

I use enums whenever I can, and I usually do something like this:
Code:
const char* ErrorToString( int  err )
{
   switch ( err )
   {
   case hrNyi:
      return "An hrNyi error occurred!";
   case hrCBDatabaseInUse:
      return "The database is in use!";
   case hrCBDatabaseNotFound:
      return "Database not found!";
   }

   return "Unknown error code!";
}
 
The API for the dll says that I can use the standard FormatMessage API to get the error text. The result codes are custom codes, not windows codes. The codes are all defined in a .h file, but I am not sure how to use them. FormatMessage has an option of FORMAT_MESSAGE_FROM_HMODULE, and I have tried that, but it returns null, and GetLastError after that returns "The specified resource type cannot be found in the image file". How do I add the .h defines as a proper resource in my exe?
 
Is your second parameter for FormatMessage correct? I've never tried this option before but the help says it has to be a handle to the module. Have a look at for an example. You may need the full path of the DLL.
 
Beautiful!!! that is what I was looking for... I did not realize I had to specify the handle to LoadLibrary...

Thanks xwb!

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top