Welcome to The Emission Locus Sign in | Join | Help

Workaround for bug in FormatMessage API

The FormatMessage API appears to have a bug that causes its behaviour to not match its documentation.

This occurs when the specified module does not have a MESSAGETABLE resource and both the FORMAT_MESSAGE_FROM_HMODULE and FORMAT_MESSAGE_FROM_SYSTEM flags are specified. Instead of continuing the search in the system modules the API fails and GetLastError() returns ERROR_RESOURCE_TYPE_NOT_FOUND (1813).

Here's the workaround:

HRESULT hr= E_ACCESSDENIED; //or whatever
_bstr_t rv; //for the error text

//
//NOTE: FormatMessage will fail if the FORMAT_MESSAGE_FROM_HMODULE
//      flag is specified and the module does not have a MESSAGETABLE
//      resource, even if FORMAT_MESSAGE_FROM_SYSTEM is specified!
//
const DWORD moduleFlags= (  FORMAT_MESSAGE_ALLOCATE_BUFFER  |
                            FORMAT_MESSAGE_FROM_HMODULE     |
                            FORMAT_MESSAGE_MAX_WIDTH_MASK);

const DWORD systemFlags= (  FORMAT_MESSAGE_ALLOCATE_BUFFER  |
                            FORMAT_MESSAGE_FROM_SYSTEM      |
                            FORMAT_MESSAGE_MAX_WIDTH_MASK);

CHeapPtr<WCHAR, CLocalAllocator> msg;
if (!::FormatMessage(moduleFlags, GetModuleHandle(NULL),
        (DWORD)errorCode, 0, (LPWSTR)&msg, 0, NULL))
{
    ::FormatMessage(systemFlags, NULL, (DWORD)errorCode, 0,
            (LPWSTR)&msg, 0, NULL);
}

rv= msg;

Note: the code uses the ATL CHeapPtr and CLocalAllocator classes.

Published Monday, November 28, 2005 6:59 AM by john

Comments

Anonymous comments are disabled