Подтвердить что ты не робот

Ошибки в Windows - DWORD (GetLastError) против HRESULT и LSTATUS

Я занимаюсь программированием в Win32 + WTL, и я смущен доступными типами ошибок.

В общем, я хочу проверить наличие ошибки и передать ее AtlGetErrorDescription (который вызывает FormatMessage).

Мои вопросы:

  • Какая разница между:

    • DWORD, возвращенный GetLastError.
    • HRESULT, возвращаемый, например, обертка CAtlFile, которая использует HRESULT_FROM_WIN32 для преобразования из DWORD.
    • LSTATUS, возвращаемый, например, RegCreateKeyEx.
  • Какие типы ошибок я могу передать на FormatMessage? Его подпись указывает, что она принимает HRESULT, но есть много примеров, где возвращаемое значение GetLastError напрямую передается FormatMessage.

4b9b3361

Ответ 1

Они просто отражают различные API, используемые в Windows:

  • GetLastError() возвращает код ошибки winapi. Простое число, начинающееся с 1. Обычно они отображаются из базового кода ошибки api. Как и ERROR_FILE_NOT_FOUND, отображается код ошибки драйвера файловой системы STATUS_OBJECT_NAME_NOT_FOUND. Коды ошибок Winapi объявляются в файле заголовка WinError.h SDK. Вы можете рассчитывать на получение описательной строки из FormatMessage() с параметром FORMAT_MESSAGE_FROM_SYSTEM.

  • HRESULT - код ошибки COM. Он состоит из трех основных частей, высокие биты указывают на степень тяжести, средние биты кодируют объект, который указывает источник ошибки, а младшие 16 бит кодируют номер ошибки. Макрос HRESULT_FROM_WIN32() является вспомогательным макросом для сопоставления кода ошибки winapi с кодом ошибки COM. Он просто устанавливает серьезность "fail", код объекта - 7 (winapi) и копирует код ошибки в младшие бит. Существует много возможных COM-кодов ошибок, и только некоторые из них конвертируются в строку с помощью FormatMessage(). Вы должны использовать интерфейс ISupportErrorInfo, чтобы спросить, может ли COM-сервер предоставить описание ошибки через IErrorInfo.

  • LSTATUS неясен, RegCreateEx фактически возвращает LONG, только код ошибки winapi. Он появляется в некоторых функциях оболочки оболочки, например SHGetValue(). Мне часто очень непонятно, почему команда оболочки делает то, что она делает.

  • Не упоминается в вашем вопросе, но стоит отметить коды ошибок, сгенерированные родным api. Они задокументированы в заголовке SDK ntstatus.h. Предполагается, что winapi обертывает собственный api, но эти коды ошибок иногда выглядят вокруг краев, особенно в исключениях. Большинство программистов видели код исключения 0xc0000005 (STATUS_ACCESS_VIOLATION). 0xc00000fd соответствует этому имени сайта. FormatMessage() может преобразовывать общие в строку, если не был создан код ошибки, созданный драйвером. Существует несколько apis, которые используют эти коды ошибок, даже если они запускаются в пользовательском режиме. Обычными примерами являются WIC и Media Foundation, иначе без сильного намека на то, почему они предпочитают это таким образом. Получение строки для такого кода ошибки требует использования FormatMessage с параметром FORMAT_MESSAGE_FROM_HMODULE.