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.