Коды ошибок winapi

Опубликовано:

Исправлено:

Версия документа: 1

Когда ты вызываешь функцию Windows, она проверяет переданные ей параметры, а затем пытается выполнить свою работу. Если ты передал недопустимый параметр или если данную операцию нельзя выполнить по какой‐то другой причине, она возвращает значение, свидетельствующее об ошибке.

Типы данных для возвращаемых значений

Большинство функций Windows возвращают следующие типы:

Процедуры:
Подпрограммы‐процедуры Sub не возвращают значений. Такие функции всегда (или почти всегда) выполняется успешно, хотя их количество в Windows очень мало. Пример: функция ExitProcess.
BOOL или Boolean:
Если вызов функции оканчивается неудачей, то возвращается ложь False (она же 0), в остальных случаях возвращается любое другое число, отличное от нуля. Однако не пытайся сравнить это число с True, лучше просто сравнивать с нулём.
HANDLE:
Если вызов функции оканчивается неудачей, то обычно возвращается NULL, что эквивалентно нулю, в остальных случаях возвращаемое значение идентифицирует объект, которым ты можешь манипулировать. Однако некоторые функции вместо NULL в случае ошибки возвращают константу INVALID_HANDLE_VALUE, например, функция CreateFile. В документации для каждой функции чётко указано, что именно она возвращает при ошибке: NULL или INVALID_HANDLE_VALUE.
PVOID или Any Ptr:
Если вызов функции оканчивается неудачей, то возвращается NULL, в остальных случаях PVOID сообщает адрес блока данных в памяти.
HRESULT:
Если вызов функции оканчивается неудачей, то возвращается ошибочный код HRESULT, в остальных случаях значение говорит об успехе операции. Подробнее о HRESULT →
Integer, Long или DWORD:
Это значение — «крепкий орешек». Функции, которые возвращают значения каких‐либо счётчиков, обычно возвращают Integer, Long или DWORD. Если по какой‐либо причине функция не сумела сосчитать то, что ты хотел, она обычно возвращает 0 или -1, всё зависит от конкретной функции. Лучше всего проверь в документации, каким именно значением функция уведомляет об ошибке.

Почему же произошла ошибка?

При возникновении ошибки необходимо разобраться почему вызов данной функции оказался неудачен. За каждой ошибкой закреплён свой код — 32‐битное целое число.

Функция Windows, обнаружив ошибку, через механизм локальной памяти потока сопоставляет соответствующий код ошибки с вызывающим потоком. Это позволяет потокам работать независимо друг от друга, не вмешиваясь в чужие ошибки. Когда функция вернёт управление, её возвращаемое значение будет указывать на то, что произошла какая‐то ошибка. Какая именно — можно узнать, вызвав функцию GetLastError.

Declare Function GetLastError()As DWORD

Она просто возвращает числовое значение, характеризующее код ошибки.

Список кодов ошибок лежит в заголовочной файле win\winerror.bi. Здесь приведена его небольшая часть, чтобы примерно представлять, на что он похож:

Const ERROR_SUCCESS = 0
Const NO_ERROR = 0
Const ERROR_INVALID_FUNCTION = 1
Const ERROR_FILE_NOT_FOUND = 2
Const ERROR_PATH_NOT_FOUND = 3
Const ERROR_TOO_MANY_OPEN_FILES = 4
Const ERROR_ACCESS_DENIED = 5
Const ERROR_INVALID_HANDLE = 6

Функцию GetLastError необходимо вызывать сразу же после неудачного вызова функции Windows, иначе код ошибки может быть потерян.

Некоторые функции Windows всегда завершаются успешно, но по разным причинам. Например, попытка создать объект ядра «событие» с определённым именем может быть успешна потому, что оно действительно создано, либо потому, что такой объект уже существует. Но иногда нужно знать причину успеха. Для возврата этой информации корпорация Microsoft предпочла использовать механизм установки кода последней ошибки. Так что и при успешном выполнении некоторых функций ты можешь использовать GetLastError и получать дополнительную информацию. К таким функциям относится, например, CreateEvent.

Ты наверняка спросишь, составит ли корпорация Microsoft полный список всех кодов ошибок, возможных в каждой функции. Ответ: нет. Такого списка никогда не будет, уж слишком сложно его составлять и поддерживать для всё новых и новых версий системы.

Проблема с подобным списком ещё и в том, что ты вызываешь одну функцию, а она может обратиться к другой, та — к следующей и так далее. Любая из этих функций может завершиться неудачно и по самым разным причинам. Иногда функция более высокого уровня сама справляется с ошибкой в одной из вызванных ею функций, и в конечном счёте выполняет то, что от неё хотели. В общем, для создания такого списка пришлось бы проследить цепочки вызовов в каждой функции, что очень трудно. А с появлением новой версии операционной системы цепочки вызовов пришлось бы пересматривать заново.

Определение собственных кодов ошибок

Механизм установки кода ошибки можно использовать и в собственных функциях. Предположим, ты пишешь библиотечную функцию, к которой будут обращаться другие части программы или вообще другие программы. Вызов этой функции по каким‐либо причинам может оказаться неудачным и тебе придётся тоже сообщать об этом. С этой целью ты просто устанавливаешь код последней ошибки в потоке и возвращаешь значение False, INVALID_HANDLE_VALUE, NULL или что‐то другое, более подходящее в твоём случае.

SetLastError

Чтобы установить код последней ошибки вызывай функцию SetLastError и передай ей нужной число.

Declare Sub SetLastError( _
    ByVal dwErrorCode As DWORD _
)

Можно использовать коды ошибок, уже определённые в winerror.bi, если они подходят. Если ты считаешь, что ни один из кодов ошибок из winerror.bi не годится для ошибки, возможной в твоей функции, можно определить свой код.

Формат кода ошибки

Код ошибки представляет 32‐битное беззнаковое число, которое разбито на поля:

Биты числа 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
Описание Степень тяжести Кем определён Зарезервировано Подсистема (facility code) Код ошибки
Биты 30 и 31:
Представляют собой степень тяжести ошибки. В двоичном виде: 00 — успех, 01 — информация, 10 — предупреждение, 11 — ошибка.
Бит 29:
Корпорация Microsoft обещала, что никогда не будет его устанавливать. Следовательно, если ты определяешь собственный код ошибки, то установи этот бит в 1 для гарантии, что твой код ошибки не будет конфликтовать с кодами, определёнными Microsoft.
Бит 28:
Зарезервирован. Должен быть 0.
Биты с 16 по 27:
Код подсистемы (facility code). Определяется корпорацией Microsoft. Указывает на компонент операционной системы, вызвавший ошибку.
Биты с 0 по 15:
Код ошибки. Определяется корпорацией Microsoft или пользователем.

Подробнее об этих полях будет рассказано в следующих статьях. На данный момент единственное важное для тебя поле — это бит 29. Чтобы гарантировать непересекаемость кодов ошибок от Microsoft, установи его в 1. В переводе на числа это означает, что твой код ошибки должен быть больше, чем &h20000000 или 536870912 в десятичном виде.

Получение описания ошибки

Для получения текстового описания ошибки подойдёт функция FormatMessage. Использовать её можно так:

#include "windows.bi"

Const BufferSize As Integer = 4096 - 1

' Строка с ошибкой
Dim ErrorMessage As WString * (BufferSize + 1) = Any

' Вызов функции с неправильным параметром
GetProcessId(NULL)

' Получить код ошибки
Dim dwError As DWORD = GetLastError()

' Получить строку по коду ошибки
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @ErrorMessage, BufferSize, NULL)

' Выводим описание ошибки на консоль
Print ErrorMessage

Читайте также

Дерево исходных кодов ядра

Дерево исходных кодов ядра
Дерево исходных кодов ядра содержит ряд каталогов, большинство из которых также содержит подкаталоги. Каталоги, которые находятся в корне дерева исходных кодов, и их описание приведены в табл. 2.1.Таблица 2.1. Каталоги в корне дерева исходных

Использование дерева каталогов исходных кодов ядра

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

Компиляция вне дерева исходных кодов ядра

Компиляция вне дерева исходных кодов ядра
Если вы предпочитаете разрабатывать и поддерживать ваш модуль отдельно от дерева исходных кодов ядра и жить жизнью аутсайдера, просто создайте файл Makefile следующего вида в том каталоге, где находится модуль.obj-m := fishing.oТакая

Коды ошибок удаленного доступа Windows

Коды ошибок удаленного доступа Windows
Если модем не соединяется с Интернетом, то на экране появляется не только сообщение об ошибке, но и ее номер, по которому можно гораздо точнее диагностировать проблему, возникшую при интернет-подключении.Наиболее типичные ошибки

14.9.3. Получение и установка кодов завершения

14.9.3. Получение и установка кодов завершения
Метод exit возбуждает исключение SystemExit и в конечном счете возвращает указанный код завершения операционной системе (или тому, кто его вызвал). Этот метод определен в модуле Kernel. Метод exit! отличается от него в двух отношениях: он не

Роль кодов операций CIL

Роль кодов операций CIL
После определения компоновочного блока .NET, пространства имен и набора типов в терминах GIL с использованием различных директив и связанных атрибутов остается одно – предложить программную логику реализации типа. Это является задачей кодов

Анализ кодов операций CIL

Анализ кодов операций CIL
Заключительной темой нашего обсуждения в этой главе в отношении программного кода CIL будет роль кодов операций. Напомним, что код операции – это просто лексема CIL, используемая для построения логики реализации данного члена. Полный набор кодов

Модули внешних кодов

Модули внешних кодов
Firebird может расширить свои возможности путем доступа к определенным пользователям подпрограммам, написанным на включающем языке программирования и скомпилированным во внешние библиотеки общего доступа. Этот раздел содержит рассмотрение некоторых

Использование именованных сущностей вместо кодов символов

Использование именованных сущностей вместо кодов символов
Это требование связано с желанием пользователей видеть в выходящем документе вместо сущности   ее более привычный вариант  . В настоящее время приходится прибегать ко всяким хитростям вроде<xsl:text

Расшифровка.

Расшифровка.
Открываем полученное зашифрованное сообщение и нажимаем на второй справа значок на панели Outlook Express, либо на команду меню PGP decrypt message. Через несколько секунд сообщение будет расшифровано и появится в окошке.Существует еще один способ использования PGP, который

Ошибки Панели задач Windows

Ошибки Панели задач Windows
Казалось бы, что может быть проще, чем отображение нескольких кнопок и значков на Панели задач? Оказывается, все совсем не так просто. Перечислю некоторые ошибки, иногда возникающие на Панели задач.• Исчезновение надписи Пуск (в английской версии

Глава 6 Коды ошибок Windows

Глава 6
Коды ошибок Windows

Диалоговые окна
В диалоговых окнах обычно выводится код ошибки и ее краткое описание (рис. 6.1). Далеко не всегда короткого описания хватает, чтобы понять, что же случилось, и устранить причину ошибки. А иногда описание непонятно, потому что оно на

Время на прочтение
2 мин

Количество просмотров 10K

Здраствуйте!

Представляю обзор функций для получения текста ошибок из их кодов, который представлен в программе Error Lookup.

1. FormatMessage

Эта функция не такая уж и простая как может показаться (большая часть функционала в вышеупомянутой программе реализована через неё, т.к. эту функцию можно настроить на получение НЕ только системных кодов ошибок, см. пункт 2). По умолчанию функция выдаёт код системной ошибки.

Пример:
Функция получает текст ошибки из кода системных ошибок

// пример получения текста системной ошибки
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 1337, 0, lpszBuffer, cchBuffer, NULL);

printf("Error Code: %d\nError Name: %s", 1337, lpszBuffer);

Результат:

Error Code: 1337
Error Text: Идентификатор безопасности имеет неверную структуру.

2. FormatMessage + FORMAT_MESSAGE_FROM_HMODULE

При установленном флаге FORMAT_MESSAGE_FROM_HMODULE можно загрузить список ошибок из модуля (DLL) в котором находится список ошибок:

  • ntdll.dll — список ошибок NTSTATUS
  • wininet.dll — список ошибок Wininet
  • pdh.dll — список ошибок Performance Data Helper
  • … допишите в комментариях если знаете ещё

Также этот метод можно использовать и в своих проектах, нужно лишь упаковать ресурс типа message table внутрь библиотеки (спасибо ertaquo)

Пример:
В этом примере база ошибок загружается из файла

ntdll.dll

// загружаем ntdll.dll для получения текста NTSTATUS ошибки
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, LoadLibrary("ntdll.dll"), -1072037872, 0, lpszBuffer, cchBuffer, NULL);

printf("Error Code: %d\nError Name: %s", -1072037872, lpszBuffer);

Результат:

Error Code: -1072037872
Error Text: Служба журнала обнаружила попытку ошибочного выделения или освобождения зарезервированного пространства.

3. DXGetErrorString & DXGetErrorDescription

  • DXGetErrorString — функция для получения имени ошибки (например ERROR_INVALID_SID)
  • DXGetErrorDescription — функция для получения текста ошибки (например The security ID structure is invalid.)

Пример:
Пример получения ошибки DirectX:

// получение текста DirectX ошибки
printf("Error Code: %d\nError Name: %s\nError Text: %s", 1337, DXGetErrorString((HRESULT)1337), DXGetErrorDescription((HRESULT)1337));

Результат:

Error Code: 1337
Error Name: ERROR_INVALID_SID
Error Text: The security ID structure is invalid.

4. RasGetErrorString

Эта функция для получает текст ошибки из библиотеки функций RAS

Пример:
Функция получает текст ошибки из кода RAS ошибок

// пример получения текста RAS ошибки
RasGetErrorString(633, lpszBuffer, cchBuffer);

printf("Error Code %d\nError Text: %s", 633, lpszBuffer);

Результат:

Error Code: 633
Error Text: Модем или другое устройство связи уже используется или не настроено.

5. GetIpErrorString

Эта функция для получения текста ошибки из библиотеки функций IP Helper Library

Пример:
Функция получает текст ошибки

// получаем текст ошибки IP Helper Library
GetIpErrorString(12, lpszBuffer, cchBuffer);

printf("Error Code %d\nError Text: %s", 12, lpszBuffer);

Результат:

Error Code: 12
Error Text: General failure.

Бонус
  • Структура Message Table (см. пункт 2)
  • Пример разбора Message Table

Ссылки на скачивание программы
  • Setup
  • Portable
  • Source (C++)

Понравилась статья? Поделить с друзьями:
  • Коды ошибок wiki
  • Коды ошибок volvo fh4
  • Коды ошибок volvo fh16
  • Коды ошибок whirlpool awe 2215
  • Коды ошибок volvo fh12 d12a