Click to search the site Click to log in
Online articles
Download free tools
Support pages, per product
Services
Frequently asked questions, per product
How to correctly translate an error code into an error message
Author: George Mihaescu
Published: September 22, 2002
Category: Implementation technique / Win32
Notes:
Description: This brief article describes how to translate a system error code (such as the value returned by the GetLastError Win32 function) into the equivalent user-readable explanation, then explains how the same can be done for your own error codes. This technique allows for a consistent translation of error codes in error text messages throughout an application.
View count: 53,700
Comments: 0 Read comments or post your own

  Print viewOpens in new window
 How to correctly translate an error code into an error message

How to correctly translate an error code into an error message

 

By George Mihaescu

 

Summary: this is a quick programming tip describing the correct way to translate the error code of a function call (either Windows API or user-function) into a message that can be displayed to the user or logged.

The Problem

You have a Win32 application in which an error code returned by a function must be translated into a user-friendly text message (e.g. for display or logging purposes).

The Solution

Use the FormatMessage Win32 API. This function works with both the Win32 error codes, and error codes from your own functions – however the parameters passed to the function are slightly different in each case.

 

When you need to get the message corresponding to a system (Win32) error code, use the following:

 

//get the error code from the last function call

LONG err = ::GetLastError ();

 

//translate the error code into a message

void* p_text;

DWORD count = ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |

                                FORMAT_MESSAGE_FROM_SYSTEM |

                                FORMAT_MESSAGE_MAX_WIDTH_MASK,

                                NULL,

                                err,

                                MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),

                                (LPTSTR) &p_text,

                                0,

                                NULL);

 

//...display / log the message in p_text buffer here

 

//free buffer

::LocalFree (p_text);

 

When you need to get the message corresponding to one of your own functions, replace the flag FORMAT_MESSAGE_FROM_SYSTEM in the first parameter with the flag FORMAT_MESSAGE_FROM_HMODULE and the second parameter from NULL to an actual handle (HMODULE) of the module that contains the message table with the error messages. This handle may be kept NULL if the error messages are contained within the calling process application file.

 

Note that the message table with your own error message is not the same with a string table resource. The message table is a special type of resource that must be added to the resources of a module using the Microsoft Message Compiler (mc.exe). Use the following steps to create a MESSAGETABLE resource:

 

1.    Create a text file (e.g. MyMessages.mc) with the actual messages corresponding to error codes in your code. For example:

; // MyMessages.mc

 

; // Header defining the Severities, Facilities and Languages

 

MessageIdTypedef=LONG

 

SeverityNames=

(

 Success=0x0:STATUS_SEVERITY_SUCCESS

 Informational=0x1:STATUS_SEVERITY_INFORMATIONAL

 Warning=0x2:STATUS_SEVERITY_WARNING

 Error=0x3:STATUS_SEVERITY_ERROR

)

 

FacilityNames=

(

 Application=0x0:FACILITY_APPLICATION

 Libraries=0x1:FACILITY_LIBRARIES

 Network=0x2:FACILITY_NETWORK

)

 

LanguageNames=(English=0x409:MSG00409)

; //Add other language definitions here

 

; //Actual message definitions (add Language=...,

; //then the text on next line, then . on the next line for

; //translations in other languages

 

MessageId=0x1

Severity=Error

Facility=Application

SymbolicName=GM_APP_MSG_OPERATION_FAILED

 

Language=English

The operation you have chosen failed.

.

 

2.    Compile this file through the message compiler:

mc.exe -U MyMessages.mc

If your .mc file is Unicode, also add the –u switch to the mc.exe command line. The –U switch forces the output to be Unicode (even is the .mc file used as input is not).
This produces the files: MyMessages.h, MyMessages.rc, MSG00409.bin (there may be more .bin files, one for each language defined in the header of the .mc text file).
The header file (MyMessages.h) defines the symbolic constants for the error codes (so that you can include this header in you code and refer to the error codes as symbolic constants – unfortunately they are defined as macros so you may run into collisions, so use symbolic names that reduce that chance in the .mc file, e.g.: SymbolicName=GM_APP_MSG_OPERATION_FAILED.
The .bin files are binaries containing the compiled text messages in a particular language (there is one .bin file per each language defined in the header of the .mc file).
The .rc file is a standard resource file that must be included in the .rc file of the module you want to contain the error messages. It simply forces the .rc file to include the .bin file(s) with the compiled messages.

3.    Include the .rc file resulted from above into the module’s .rc file:
#include "MyMessages.rc"

4.    Use code similar to the one below to retrieve your message:

 

//user-defined error code

LONG err = GM_APP_MSG_OPERATION_FAILED;

 

void* p_text;

DWORD count = ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |

                                FORMAT_MESSAGE_FROM_HMODULE |

                                FORMAT_MESSAGE_MAX_WIDTH_MASK,

                                NULL,

                                err,

                                MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),

                                (LPTSTR) &p_text,

                                0,

                                NULL);

 

//...display / log the message in p_text buffer here

 

//free buffer

::LocalFree (p_text);

 

 


Reader comments:
Name: (optional)
Verification text:    
(type as in image next to it)
Comment: max 2,000 characters; for security reasons no active content / no HTML formatting is supported.
Please stick to the subject of the article; comments are reviewed and unrelated / inappropriate ones will be deleted.

Copyright 2308 registered users, 24 users online now