Опубликовано:
Исправлено:
Версия документа: 1.0
Тип данных HRESULT
HRESULT содержит информацию о результате вызова функции. Хотя из названия HRESULT можно было бы заключить, что это описатель (Handle) результата, на самом деле это не так. Название возникло по историческим причинам, просто расшифровывай его как «вот результат» (here is the result). HRESULT похож на код ошибки Windows, но это не одно и то же, и смешивать их не следует.
Внутреннее устройство HRESULT
В заголовочном файле winnt.bi
(входит в windows.bi
) тип данных HRESULT описан как 32‐битное знаковое целое число:
Type HRESULT As LONG
Детальный разбор
Биты числа | 31 | 30 | 29 | 28 | 27 | 26 25 24 23 22 21 20 19 18 17 16 | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
---|---|---|---|---|---|---|---|
Описание | Severity | R | C | N | r | Facility | Код возврата |
- Бит 31:
- Признак критичности: 1 если произошла ошибка, 0 при успешном результате.
- Биты с 30 по 27:
- Зарезервированы.
- Биты с 26 по 16:
- Идентификатор средства: какая часть операционной системы выдаёт данный код возврата.
- Биты с 15 по 0:
- Код ошибки или причина успеха. Определяется корпорацией Microsoft или пользователем.
Признак критичности
Бит 31 (Severity) — это признак критичности. Позволяет использовать HRESULT для индикации как успешного выполнения функций, так и при ошибке.
Константа критичности | Значение | Описание |
---|---|---|
SEVERITY_SUCCESS | 0 | Функция отработала успешно |
SEVERITY_ERROR | 1 | Функция завершилась ошибкой |
Идентификатор средства
Пятнадцать битов — с 30-го по 16-й — содержат идентификатор средства (Facility). Он указывает, какая часть операционной системы выдаёт данный код возврата. Поскольку операционную систему разрабатывает корпорация Microsoft, она зарезервировала право определения идентификаторов средств за собой.
Константа идентификатора средства | Значение | Источник ошибки |
---|---|---|
FACILITY_NULL | 0 | Стандартные коды возврата |
FACILITY_RPC | 1 | Удалённый вызов процедур RPC |
FACILITY_DISPATCH | 2 | Объект автоматизации |
FACILITY_STORAGE | 3 | Хранилище OLE |
FACILITY_ITF | 4 | COM или OLE интерфейс сторонних разработчиков |
FACILITY_WIN32 | 7 | Декорированная ошибка функций Windows |
FACILITY_WINDOWS | 8 | Подсистема Windows |
FACILITY_SECURITY | 9 | Уровень безопасности |
В том случае, если стандартных значений недостаточно, то при создании собственных HRESULT следует устанавливать идентификатор средства в FACILITY_ITF.
Смысл кода возврата, отмеченного с помощью FACILITY_ITF, специфичен для возвращающих его функций и является уникальным только в пределах данной функции. Одно и то же значение кода возврата в FACILITY_ITF, возвращаемое двумя различными функциями, может иметь разные значения.
Иногда функция вызывает другие функции, возвращающие HRESULT и отмеченные FACILITY_ITF. В этом случае такие коды возврата следует преобразовывать в специфичные для твоей функции; не следует отдавать их «как есть».
Все COM‐определённые коды FACILITY_ITF имеют значение кода в диапазоне &h0000-&h01FF. Хотя использование любых кодов в FACILITY_ITF является законным, рекомендуется использовать только значения кода в диапазоне &h0200-&hFFFF для уменьшения путаницы с любыми COM‐определёнными ошибками.
Некоторые предопределённые HRESULT
В таблице приведены часто используемые константы HRESULT. По соглашению в названиях успешных кодов содержится S_, а в названиях кодов ошибок E_.
Константа | Значение | Описание |
---|---|---|
S_OK | &h00000000 | Функция отработала успешно. В некоторых случаях этот код также означает логическую истину. |
S_FALSE | &h00000001 | Функция отработала успешно и возвращает логическую ложь. Это несколько противоречит обычной практике программирования, где 0 — это ложь, а не-0 — истина. |
E_PENDING | &h8000000A | Данные, необходимые для завершения операции, пока отсутствуют. |
E_NOTIMPL | &h80004001 | Метод не реализован. |
E_NOINTERFACE | &h80004002 | Запрашиваемый интерфейс не поддерживается. |
E_POINTER | &h80004003 | Указатель недействителен. |
E_ABORT | &h80004004 | Операция прервана. |
E_FAIL | &h80004005 | Ошибка по неуказанной причине. |
E_UNEXPECTED | &h8000FFFF | Произошёл катастрофический сбой. |
E_ACCESSDENIED | &h80070005 | Доступ запрещён. |
E_HANDLE | &h80070006 | Описатель недействителен. |
E_OUTOFMEMORY | &h8007000E | Невозможно выделить память. |
E_INVALIDARG | &h80070057 | Один или несколько аргументов неправильные. |
Большой и длинный список HRESULT можно найти в статье на MSDN «HRESULT Values».
Использование HRESULT
Макросы SUCCEEDED и FAILED
Для проверки успешного или ошибочного результата функции нельзя сравнивать HRESULT с каким‐либо одним кодом. Например, если функция завершилась успешно, то нельзя ожидать возврата только S_OK, и наоборот — при ошибке нелья ждать только E_FAIL. Следует использовать предопределённые макросы SUCCEEDED и FAILED.
' Вызываем функцию и получаем HRESULT:
Dim hr As HRESULT = SomeFunction(param)
' Не делай так:
If hr = E_FAIL Then
Print "Ошибка"
End If
If hr = S_OK Then
Print "Успешно"
End If
' Следует делать так:
' Проверка на ошибку:
If FAILED(hr) Then
Print "Ошибка"
End If
' Проверка на успех:
If SUCCEEDED(hr) Then
Print "Успешно"
End If
Макрос HRESULT_CODE
Получает код возврата.
Dim hr As HRESULT = SomeFunction(param)
Dim Code As Integer = HRESULT_CODE(hr)
Макрос HRESULT_FACILITY
Получает идентификатор средства.
Dim hr As HRESULT = SomeFunction(param)
Dim Facility As Integer = HRESULT_FACILITY(hr)
Макрос HRESULT_SEVERITY
Получает признак критичности.
Dim hr As HRESULT = SomeFunction(param)
Dim Severity As Integer = HRESULT_SEVERITY(hr)
Макрос MAKE_HRESULT
Создаёт собственный HRESULT. Все идентификаторы средств зарезервировала за собой корпорация Microsoft, поэтому стороннему разработчику следует использовать FACILITY_ITF, а код возврата начинать с &h0200.
' Создаём собственный HRESULT с ошибкой:
Const CUSTOM_E_PROTOCOLPERMISSION As HRESULT = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, &h0201)
' Создаём собственный HRESULT с успехом:
Const CUSTOM_S_PROTOCOLACCESS As HRESULT = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, &h0201)
При именовании констант собственных HRESULT хорошей практикой является приписывание слева имени компонента или приложения. Например:
AIRPLANE_E_LANDINGWITHGEARUP
HELICOPTER_S_ROTORRPMGREEN
Макрос HRESULT_FROM_WIN32
Создаёт HRESULT из ошибки Windows. В этом случае признак критичности автоматически принимает значение SEVERITY_ERROR, а идентификатор средства — FACILITY_WIN32.
' Получаем код ошибки Windows:
Dim dwError As DWORD = GetLastError()
' Упаковываем его в HRESULT:
Dim hr As HRESULT = HRESULT_FROM_WIN32(dwError)