Каково правило угона кодов ошибок Windows для возврата из моего собственного кода? - PullRequest
4 голосов
/ 16 марта 2012

Могут ли коды ошибок, определенные в WinError.h, быть взломаны и возвращены моим собственным кодом?

Существует несколько общих Win32 определенных кодов ошибок:

  • ERROR_FILE_NOT_FOUND: "Системе не удается найти указанный файл."

что, конечно, я мог бы использовать для своих собственных целей, когда файл не найден.

Тогда есть еще несколько общих ошибок:

  • ERROR_ACCESS_DENIED: «Доступ запрещен».

но обычно считается, что эта ошибка возникает при попытке доступа к файлу. у меня может быть функция HttpGet(), которая возвращает ERROR_ACCESS_DENIED, если сервер возвращает 401.

Но тогда есть коды, которые определены как предназначенные для определенной цели. Представьте, что моя функция HttpGet() выдает ошибку, если сертификат https не является поддерживаемым нами типом:

  • ERROR_IPSEC_IKE_INVALID_CERT_TYPE: "Недействительный тип сертификата"

за исключением того, что в WinError.h код довольно четко определен как принадлежащий IPSec:

///////////////////////////////////////////////////
//                                               //
//           Start of IPSec Error codes          //
//                                               //
//                 13000 to 13999                //
///////////////////////////////////////////////////

...

//
// MessageId: ERROR_IPSEC_IKE_INVALID_CERT_TYPE
//
// MessageText:
//
// Invalid certificate type
//
#define ERROR_IPSEC_IKE_INVALID_CERT_TYPE 13819L

Но текст ошибки - именно то, что я хочу!

У нас есть финансовая система, которая требует, чтобы второй пользователь одобрил транзакцию; это означает, что введенные учетные данные должны отличаться от имени первого лица:

  • MK_E_MUSTBOTHERUSER: «Для успешного выполнения операции требуется ввод пользователя»

или, возможно:

  • ERROR_LOGON_TYPE_NOT_GRANTED: "Ошибка входа: пользователю не предоставлен запрошенный тип входа на этом компьютере."

я чувствую, что запись через WinError, вишнёвые коды ошибок по строке 1069 *, которую они показывают, и повторное использование их для указания на ошибки, для которых они не были предназначены, - это что-то Raymond дал бы мне пощечину.

Являются ли коды ошибок Windows свободно доступным «пулом» кодов ошибок? Или все коды ошибок Windows должны быть возвращены только из кода Microsoft?

Если я создаю HRESULTS, мне нужно использовать некоторый код. И было бы здорово, если бы пользователь мог позвонить FormatMessage, чтобы превратить мой HRESULT в строку. (Тем более, что мое возвращение HRESULT может быть либо моим собственным кодом, либо HRESULT, который был возвращен мне из кода Microsoft).

Ответы [ 3 ]

4 голосов
/ 17 марта 2012

Когда вы определяете свои собственные коды HRESULT, рекомендуется использовать FACILITY_ITF и определять свои коды в этом диапазоне определяемых приложением кодов. Да, коды могут перекрываться между приложениями, но вы также можете предоставить дополнительное описательное сообщение через SetErrorInfo API и указать поддержку путем реализации ISupportErrorInfo, если вы реализуете объект / интерфейс COM.

Отрывок из книги COM+ Programming объясняет это более подробно: Программирование на COM +: практическое руководство с использованием Visual C ++ и ATL (стр. 67).

Проще, чем вы, вы можете использовать свой собственный код объекта, и он может отличаться в разных модулях, поэтому вы можете легко определить, какой модуль является источником проблемы.

Если вы поместите ресурс MESSAGETABLE в свой двоичный файл, API FormatMessage сможет разрешать HRESULT и извлекать текст описания для отдельных кодов, как это происходит с обычными кодами ошибок Windows (приложение все равно должно предоставлять дескриптор модуля для API-функция).

См. Также: Создание собственного HRESULT?


O.P. Edit:

От Microsoft Открытая спецификация протокола HRESULT s

2,1 HRESULT

Пространство нумерации HRESULT расширяется поставщиком. Поставщики могут предоставить свои собственные значения для этого поля, если установлен бит C (0x20000000), указывающий, что это код клиента.

C (1 бит) : Заказчик. Этот бит указывает, является ли значение пользовательским или Microsoft. Бит устанавливается для пользовательских значений и сбрасывается для Microsoft. <1>

<1> Раздел 2.1 : Все значения HRESULT , используемые Microsoft, имеют бит C сброшенный.

Это означает, что я могу составить любой HRESULT, который мне нравится, если я установлю бит C . На практике это означает, что я могу любой любой код , который мне нравится, например ::

E_LOGON_FAILURE = 0xA007052E;

Конечно, я не нашел это число случайно.

Сначала я установил старший бит на 1, чтобы указать на ошибку:

0x80000000

Затем я "выбираю" код ошибки, например, 1326 (0x52E hex) :

0x8000052E

Тогда мне нужно выбрать объект. Давайте оооочень, не знаю, семь :

0x8007052E

Наконец, я установил Customer bit , чтобы указать, что это не определенный Microsoft HRESULT:

0xA007052E

И, по совпадению, все до последнего шага - это смелость макроса Microsoft HRESULT_FROM_WIN32:

Сопоставляет системный код ошибки со значением HRESULT.

 HRESULT HRESULT_FROM_WIN32(DWORD x);
3 голосов
/ 17 марта 2012

Не идите по этому пути, а просто определите свой собственный.

Повторное использование самих кодов бессмысленно, так как наличие ваших собственных кодов - всего один #define.

Повторное использование строк ошибок тоже не очень хорошая идея:

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

  • Microsoft может изменить текст по своему усмотрению, с новымвыпуск Windows или с обновлением.Например, если вы использовали ERROR_IPSEC_IKE_INVALID_CERT_TYPE для обозначения ошибок сертификата HTTPS, а Microsoft решила исправить их смутное сообщение, в котором говорилось бы «Недопустимый IPSEC IKE тип сертификата»?(Я вообще не знаю, что такое IKE, и имею лишь смутное представление о IPSEC, но вы понимаете, в чем дело.)

  • У вас не будет возможности настроить ошибкусообщения должны быть более понятными или более конкретными.

  • Как только пользователи вашего API начнут использовать FormatMessage, вы навсегда будете привязаны к набору кодов ошибок и сообщений, которые предоставляет Microsoft.

Если вы уже знаете, что Раймонд Чен даст вам пощечину, почему вы об этом даже думаете?;)

0 голосов
/ 17 марта 2012

Я думаю, что, возможно, нашел свой собственный ответ, фактически , читая документацию :

Коды системных ошибок

Коды системных ошибок очень широки. ... Поскольку эти коды определены в WinError.h для любого пользователя, иногда коды возвращаются несистемным программным обеспечением.

Хотя только ошибка коды описаны как таковые (т.е. положительные числа от 0-15999).

Но тот же дух начинаетсяприменить к кодам ошибок COM:

  • E_NOTIMPL: 0x80004001 Не реализовано
  • E_INVALIDARG: 0x80070057 Один или несколько аргументов недействительны
  • E_FAIL: 0x80004005 Неуказанная ошибка ( Страшная ошибка 80004005, ошибка )

Фактически это 1045 * отображение Delphi , которое преобразует любое универсальное исключение в

  • E_UNEXPECTED 0x8000FFFF Катастрофический сбой

Так что вполне ожидаемоиспользуйте коды Microsoft HRESULT.


У вас также есть HRESULT, которые HRESULT формулируют стандартные коды ошибок Win32 , например, E_HANDLE - это обертка вокруг ERROR_INVALID_HANDLE (6):

E_HANDLE = 0x80070006;   //Invalid handle

Это делается с помощью макроса HRESULT_FROM_WIN32.

Хотя использование Microsoft HRESULTS за пределами общих возможностей может быть морально сомнительным:

  • FACILITY_NULL Для широко применяемых общих кодов состояния, таких как S_OK.
  • FACILITY_RPC Для кодов состояния, возвращаемых при удаленных вызовах процедур.
  • FACILITY_DISPATCHДля ошибок интерфейса IDispatch с поздним связыванием.
  • FACILITY_ITF Для большинства кодов состояния, возвращаемых из методов интерфейса.Фактическое значение ошибки определяется интерфейсом.То есть два HRESULT с одинаковым 32-битным значением, возвращаемым из двух разных интерфейсов, могут иметь разные значения.
  • FACILITY_WIN32 Используется для предоставления средств обработки кодов ошибок из функций в API Windows как HRESULT.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...