Чтение данных обратного вызова проверки ошибок

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

KBUGCHECK_CALLBACK_ROUTINE использования BugCheckCallback
Данные, записанные этой подпрограммой, становятся частью данных обратного вызова. Данные не включаются в файл аварийного дампа.

Использование BugCheckSecondaryDumpDataCallbackKBUGCHECK_REASON_CALLBACK_ROUTINE
Данные, записанные этой подпрограммой, становятся частью дополнительных данных обратного вызова. Данные включаются в файл аварийного дампа.

BugCheckAddPagesCallback use KBUGCHECK_REASON_CALLBACK_ROUTINE
Страницы, указанные этой подпрограммой, становятся частью данных обратного вызова. Данные на этих страницах включаются в файл аварийного дампа.

Объем данных обратного и вторичного обратного вызова, доступных отладчику, зависит от нескольких факторов.

  • Если выполняется динамическая отладка системы со сбоем, будут доступны данные обратного вызова, которые уже были записаны BugCheckCallback или указаны в BugCheckAddPagesCallback . Дополнительные данные обратного вызова будут недоступны, так как они не хранятся в фиксированном расположении памяти.

  • При отладке полного дампа памяти или дампа памяти ядра будут доступны данные обратного вызова, указанные в BugCheckAddPagesCallback , и дополнительные данные обратного вызова, записанные BugCheckSecondaryDumpDataCallback . Данные обратного вызова, записанные BugCheckCallback , будут недоступны.

  • При отладке небольшого дампа памяти данные обратного вызова будут недоступны. Будут доступны дополнительные данные обратного вызова.

Дополнительные сведения об этих размерах файлов дампа см. в разделе Варианты файлов дампа Kernel-Mode .

Отображение данных обратного вызова

Для отображения ошибок проверка данных обратного вызова можно использовать расширение !bugdump.

Без параметров !bugdump будет отображать данные для всех обратных вызовов.

Чтобы просмотреть данные для одной конкретной процедуры обратного вызова, используйте компонент !bugdump, где Component — это тот же параметр, который был передан в KeRegisterBugCheckCallback при регистрации этой подпрограммы.

Отображение дополнительных данных обратного вызова

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

Каждый блок вторичных данных обратного вызова идентифицируется тегом GUID. Этот тег задается полем Guidпараметра (KBUGCHECK_SECONDARY_DUMP_DATA)ReasonSpecificData , переданного в BugCheckSecondaryDumpDataCallback.

Команда .enumtag (Перечислить вторичные данные обратного вызова) не является очень точным инструментом. Он отображает каждый дополнительный блок данных с тегом, а затем данные в шестнадцатеричном формате и ASCII. Обычно полезно только определить, какие теги фактически используются для вторичных блоков данных.

Чтобы использовать эти данные более практичным способом, рекомендуется написать собственное расширение отладчика. Это расширение должно вызывать методы в файле заголовка dbgeng.h. Дополнительные сведения см. в разделе Написание новых расширений отладчика.

Если вы знаете тег GUID вторичного блока данных, расширение должно использовать метод IDebugDataSpaces3::ReadTagged для доступа к данным. Его прототип выглядит следующим образом:

STDMETHOD(ReadTagged)(
    THIS_
    IN LPGUID Tag,
    IN ULONG Offset,
    OUT OPTIONAL PVOID Buffer,
    IN ULONG BufferSize,
    OUT OPTIONAL PULONG TotalSize
    ) PURE; 

Ниже приведен пример использования этого метода:

UCHAR RawData[MY_DATA_SIZE];
GUID MyGuid = .... ;

Success = DataSpaces->ReadTagged(  &MyGuid,  0,  RawData,
                                   sizeof(RawData),  NULL); 

Если указать bufferSize , который слишком мал, readTagged будет выполнено успешно, но будет записывать в буфер только запрошенное количество байтов. Если указать bufferSize слишком большого размера, readTagged завершится успешно, но запишет в буфер только фактический размер блока. Если указать указатель для TotalSize, ReadTagged будет использовать его для возврата размера фактического блока. Если доступ к блоку невозможен, ReadTagged вернет код состояния сбоя.

Если два блока имеют идентичные теги GUID, возвращается первый соответствующий блок, а второй блок будет недоступен.

Если вы не уверены в теге GUID блока, можно использовать методы IDebugDataSpaces3::StartEnumTagged, IDebugDataSpaces3::GetNextTagged и IDebugDataSpaces3::EndEnumTagged для перечисления блоков с тегами. Их прототипы:

STDMETHOD(StartEnumTagged)(
    THIS_
    OUT PULONG64 Handle
    ) PURE;

STDMETHOD(GetNextTagged)(
    THIS_
    IN ULONG64 Handle,
    OUT LPGUID Tag,
    OUT PULONG Size
    ) PURE;

STDMETHOD(EndEnumTagged)(
    THIS_
    IN ULONG64 Handle
    ) PURE;

Отладка процедур обратного вызова

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

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