Из книги Windows через C / C ++:

enter image description here

Хорошо, я пытаюсь получить код любой системной ошибки от Microsoft и проанализировать его поля:

HANDLE hMutex = OpenMutex(0, FALSE, _T("12345")); // some unexisting object 
if (NULL == hMutex) {
    DWORD errCode = GetLastError(); // I get 0x00000002 here
    PTSTR msg = NULL;
    LCID langId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
    DWORD result = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errCode, langId, (PTSTR)&msg, 0, NULL);
    wcerr << msg << endl;
    return 2;
}

Мое значение errCode - 0x00000002, но я ожидал, что в поле severinity будет 3 (ошибка) и некоторое значение поля код объекта ...

Почему в полученном результате нет значений в этих полях?

0
Andrey Bushman 27 Окт 2015 в 21:38

2 ответа

Лучший ответ

Цитируемый вами текст описывает коды ошибок NTSTATUS. Это коды ошибок на уровне ядра. Некоторую документацию можно найти здесь: Определение новых значений NTSTATUS .

Однако GetLastError возвращает коды ошибок Win32. Это просто разные звери из кодов NTSTATUS. У них нет кодов серьезности или возможности.

MSDN сообщает this о кодах ошибок Win32:

Коды ошибок Win32 - это 16-битные значения, расширенные до 32-битных с нулевым заполнением, и они могут быть возвращены методами или в структурах. Как правило, они не могут быть расширены поставщиком.

Ваш код ошибки: ERROR_FILE_NOT_FOUND который явно не вписывается в таблицу в вашем ответе, поскольку имеет серьезность 0, что означает успех.

2
David Heffernan 27 Окт 2015 в 18:56

Если вы введете около 26000 строк в winerror.h, вы найдете расположение полей кода ошибки. Она отличается от приведенной выше таблицы 1-2. Пример: объект - это биты 26–16, а бит 26 отделяет Microsoft от других кодов, по 1024 кода объекта каждый.

Рядом с макетом находятся определения SUCCEEDED (hr) и FAILED (hr). Но что более интересно, чуть ниже них - определения, относящиеся к наборам кодов ошибок.

HRESULT_FROM_WIN32(unsigned long x)
HRESULT_FROM_NT(x)

Например, CreateFile () может вернуть 16-битный код ошибки.

#define ERROR_ACCESS_DENIED              5L

И вы используете HRESULT_FROM_WIN32 (x), чтобы превратить его в HRESULT

#define E_ACCESSDENIED                   _HRESULT_TYPEDEF_(0x80070005L)

Между тем, _open () может вернуть свой собственный 16-битный код ошибки из кодов ошибок, совместимых с XENIX, определенных в errno.h.

#define EACCES          13

Основная проблема / проблема заключается в том, что существует несколько наборов кодов ошибок. Вы не можете просто использовать HRESULT_FROM_WIN32 с каждой возвращаемой ошибкой. Наборы перекрываются численно, и вам нужно знать вызов API, который вызвал ошибку, чтобы узнать, какую карту кода ошибки использовать.

Наконец, хотя ошибки COM - это 32-битные коды ошибок Windows, этот формат / макет кода ошибки возник не из COM. Они предшествовали COM. Я бы просто назвал их HRESULTS.

1
Henri Socha 19 Ноя 2015 в 18:55