]>Тип данных HRESULT

Тип данных HRESULT

Аватар пользователя mabu

HRESULT содержит информацию о результате вызова функции. Хотя из названия HRESULT можно было бы заключить, что это описатель (Handle) результата, на самом деле это не так. Название возникло по историческим причинам, просто расшифровывай его как «вот результат» (here is the result). HRESULT похож на код ошибки Windows, но это не одно и то же, и смешивать их не следует.

  1. Внутреннее устройство HRESULT
    1. Детальный разбор
    2. Признак критичности
    3. Идентификатор средства
    4. Некоторые предопределённые HRESULT
  2. Использование HRESULT
    1. Макросы SUCCEEDED и FAILED
    2. Макрос HRESULT_CODE
    3. Макрос HRESULT_FACILITY
    4. Макрос HRESULT_SEVERITY
    5. Макрос MAKE_HRESULT
    6. Макрос HRESULT_FROM_WIN32

Внутреннее устройство HRESULT

В заголовочном файле «winerror.bi» Windows тип данных HRESULT описан как 32‐битное целое число.

Детальный разбор

Биты числа313029282726252423222120191817161514131211109876543210
ОписаниеSeverityFacilityCode
Бит 31
Признак критичности: 1 если произошла ошибка, 0 при успешном результате.
Биты с 30 по 16
Идентификатор средства: какая часть операционной системы выдаёт данный код возврата.
Биты с 15 по 0
Собственно код возврата.

Признак критичности

Бит 31 (Severity) — это признак критичности. Позволяет использовать HRESULT как результат индикации как успешного выполнения функций, так и при ошибке.

Константа критичностиЗначениеОписание
SEVERITY_SUCCESS0Функция отработала успешно
SEVERITY_ERROR1Функция завершилась ошибкой

Идентификатор средства

Пятнадцать битов — с 30-го по 16-й — содержат идентификатор средства (Facility). Он указывает, какая часть операционной системы выдаёт данный код возврата. Поскольку операционную систему разрабатывает корпорация Microsoft, она зарезервировала право определения идентификаторов средств за собой.

Константа идентификатора средстваЗначениеИсточник ошибки
FACILITY_NULL0Стандартные коды возврата
FACILITY_RPC1Удалённый вызов процедур RPC
FACILITY_DISPATCH2Объект автоматизации
FACILITY_STORAGE3Хранилище OLE
FACILITY_ITF4COM или OLE интерфейс сторонних разработчиков
FACILITY_WIN327Декорированная ошибка функций Windows
FACILITY_WINDOWS8Подсистема Windows
FACILITY_SECURITY9Уровень безопасности
FACILITY_SSPI9Уровень безопасности
FACILITY_CONTROL10Уровень управления
FACILITY_CERT11Центр сертификации
FACILITY_INTERNET12Компонент Wininet
FACILITY_MEDIASERVER13Windows Media Server
FACILITY_MSMQ14Очередь сообщений
FACILITY_SETUPAPI15Setup API
FACILITY_SCARD16Подсистема смарт‐карт
FACILITY_COMPLUS17COM+

В том случае, если стандартных значений недостаточно, то при создании собственных HRESULT следует устанавливать идентификатор средства в FACILITY_ITF.

Смысл кода возврата, отмеченного с помощью FACILITY_ITF, специфичен для возвращающих его функций и является уникальным только в пределах данной функции. Иногда функция вызывает другие функции, возвращающие HRESULT и отмеченные FACILITY_ITF. В этом случае такие коды возврата следует преобразовывать в специфичные для твоей функции; не следует отдавать их «как есть».

Некоторые предопределённые HRESULT

В таблице приведены часто используемые константы HRESULT. По соглашению в названиях успешных кодов содержится S_, а в названиях кодов ошибок E_.

КонстантаЗначениеОписание
S_OK&h00000000Функция отработала успешно. В некоторых случаях этот код также означает логическую истину.
S_FALSE&h00000001Функция отработала успешно и возвращает логическую ложь. Это несколько противоречит обычной практике программирования, где 0 — это ложь, а не-0 — истина.
E_FAIL&h80004005Ошибка по неуказанной причине.
E_ABORT&h80004004Операция прервана.
E_ACCESSDENIED&h80070005Доступ запрещён.
E_HANDLE&h80070006Описатель недействителен.
E_INVALIDARG&h80070057Один или несколько аргументов неправильные.
E_NOINTERFACE&h80004002Запрашиваемый интерфейс не поддерживается.
E_NOTIMPL&h80004001Метод не реализован.
E_OUTOFMEMORY&h8007000EНевозможно выделить память.
E_POINTER&h80004003Указатель недействителен.
E_UNEXPECTED&h8000FFFFНеожиданная ошибка.

Большой и длинный список HRESULT можно найти в статье на MSDN «HRESULT Values».

Использование HRESULT

Макросы SUCCEEDED и FAILED

Для проверки успешного или ошибочного результата функции нельзя сравнивать HRESULT с каким‐либо одним кодом. Например, если функция завершилась успешно, то нельзя ожидать возврата только S_OK, и наоборот — при ошибке нелья ждать только E_FAIL. Следует использовать предопределённые макросы SUCCEEDED и FAILED.

Код FreeBASIC
' Вызываем функцию и получаем HRESULT:
Dim hr As HRESULT = SomeFunction(param)

' Не делай так:
If hr = E_FAIL Then
&t;Print "Ошибка"
End If
If hr = S_OK Then
&t;Print "Успешно"
End If

' Следует делать так:

' Проверка на успех:
If SUCCEEDED(hr) Then
&t;Print "Успешно"
End If

' Проверка на ошибку:
If FAILED(hr) Then
&t;Print "Ошибка"
End If

Макрос HRESULT_CODE

Получает код возврата.

Код FreeBASIC
Dim hr As HRESULT = SomeFunction(param)
Dim Code As Integer = HRESULT_CODE(hr)

Макрос HRESULT_FACILITY

Получает идентификатор средства.

Код FreeBASIC
Dim hr As HRESULT = SomeFunction(param)
Dim Facility As Integer = HRESULT_FACILITY(hr)

Макрос HRESULT_SEVERITY

Получает признак критичности.

Код FreeBASIC
Dim hr As HRESULT = SomeFunction(param)
Dim Severity As Integer = HRESULT_SEVERITY(hr)

Макрос MAKE_HRESULT

Создаёт собственный HRESULT. Все идентификаторы средств зарезервировала за собой корпорация Microsoft, поэтому стороннему разработчику следует использовать FACILITY_ITF.

Код FreeBASIC
' Создаём собственный HRESULT с ошибкой:
Const CUSTOM_E_PROTOCOLPERMISSION As HRESULT = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 1)

' Создаём собственный HRESULT с успехом:
Const CUSTOM_S_PROTOCOLACCESS As HRESULT = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 1)

При именовании констант собственных HRESULT хорошей практикой является приписывание слева имени компонента или приложения. Например:

Код FreeBASIC
AIRPLANE_E_LANDINGWITHGEARUP
HELICOPTER_S_ROTORRPMGREEN

Макрос HRESULT_FROM_WIN32

Создаёт HRESULT из ошибки Windows. В этом случае признак критичности автоматически принимает значение SEVERITY_ERROR, а идентификатор средства — FACILITY_WIN32.

Код FreeBASIC
' Получаем код ошибки Windows:
Dim dwError As DWORD = GetLastError()

' Упаковываем её в HRESULT:
Dim hr As HRESULT = HRESULT_FROM_WIN32(dwError)

Поделись ссылочкой в социальных сетях