функция обратного вызова EX_CALLBACK_FUNCTION (wdm.h)
Подпрограмма RegistryCallback драйвера фильтра может отслеживать, блокировать или изменять операцию реестра.
Синтаксис
EX_CALLBACK_FUNCTION ExCallbackFunction;
NTSTATUS ExCallbackFunction(
[in] PVOID CallbackContext,
[in, optional] PVOID Argument1,
[in, optional] PVOID Argument2
)
{...}
Параметры
[in] CallbackContext
Значение, переданное драйвером в качестве параметра Contextв CmRegisterCallback или CmRegisterCallbackEx при регистрации этой подпрограммы RegistryCallback .
[in, optional] Argument1
REG_NOTIFY_CLASS типизированное значение, указывающее тип выполняемой операции реестра и то, вызывается ли подпрограмма RegistryCallback до или после выполнения операции реестра.
[in, optional] Argument2
Указатель на структуру, содержащую сведения, относящиеся к типу операции реестра. Тип структуры зависит от REG_NOTIFY_CLASS типизированного значения аргумента Argument1, как показано в следующей таблице. Сведения о том, какие REG_NOTIFY_CLASS типизированные значения доступны для каких версий операционной системы, см. в разделе REG_NOTIFY_CLASS.
Начиная с Windows 7, фактическая структура данных, передаваемая, когда класс уведомления — RegNtPreCreateKeyEx или RegNtPreOpenKeyEx, является версией V1 этой структуры, REG_CREATE_KEY_INFORMATION_V1 или REG_OPEN_KEY_INFORMATION_V1 соответственно. Проверьте зарезервированный элемент, чтобы определить версию структуры.
номер версии; | Имя структуры |
---|---|
0 | REG_CREATE_KEY_INFORMATION и REG_OPEN_KEY_INFORMATION |
1 | REG_CREATE_KEY_INFORMATION_V1 и REG_OPEN_KEY_INFORMATION_V1 |
Возвращаемое значение
Дополнительные сведения о том, когда подпрограмма RegistryCallback должна возвращать каждое из этих значений состояния, см. в разделе Фильтрация вызовов реестра.
Комментарии
Чтобы получать уведомления об операциях реестра, компонент режима ядра (например, компонент драйвера пакета антивирусного программного обеспечения) может вызывать CmRegisterCallback или CmRegisterCallbackEx для регистрации подпрограммы RegistryCallback .
Подпрограмма RegistryCallback может проверять содержимое входных и выходных буферов, предоставленных для операций реестра. Операция реестра может быть инициирована приложением пользовательского режима, которое вызывает подпрограмму реестра в пользовательском режиме (например , RegCreateKeyEx или RegOpenKeyEx) или драйвером, который вызывает подпрограмму реестра в режиме ядра (например , ZwCreateKey или ZwOpenKey). Входной буфер — это буфер памяти, предоставляемый инициатором, из которого реестр считывает входные данные для операции. Выходной буфер — это буфер, предоставляемый инициатором, в который реестр записывает выходные данные, запрошенные инициатором.
Перед вызовом подпрограммы RegistryCallback ядро проверяет (для проверки выравнивания и доступности) все члены структур Argument2 , которые указывают на выходные буферы в памяти пользовательского режима, но не фиксируют выходные буферы пользовательского режима в системной памяти. Подпрограмма обратного вызова должна заключать любой доступ к выходному буферу в блок try/except . Если подпрограмме обратного вызова необходимо передать указатель выходного буфера на системную подпрограмму (например, ZwOpenKey), а буфер находится в памяти в пользовательском режиме, подпрограмма обратного вызова должна сначала записать буфер.
Обработка входных буферов зависит от версии Windows. Начиная с Windows 8, ядро фиксирует все входные буферы, на которые указывают члены структур Argument2, в системной памяти перед вызовом подпрограммы RegistryCallback. В версиях Windows до Windows 8 ядро проверяет все члены структур Argument2, которые указывают на входные буферы в памяти пользовательского режима, но захватывает только некоторые из этих буферов в системной памяти. В этих более ранних версиях Windows подпрограмма обратного вызова должна заключать любой доступ к входным буферам в блок try/except . Кроме того, если подпрограмме обратного вызова необходимо передать указатель входного буфера на системную подпрограмму (например, ZwOpenKey), а буфер находится в памяти в пользовательском режиме, подпрограмма обратного вызова должна сначала записать буфер.
В следующей таблице перечислены требования к доступу к буферу с помощью подпрограммы RegistryCallback .
Тип буфера | Версия Windows | Указатель буфера, переданный в подпрограмму обратного вызова | Безопасный прямой доступ к процедуре обратного вызова? | Безопасно передавать системные подпрограммы (например , ZwOpenKey)? |
---|---|---|---|---|
Входные данные в пользовательском режиме | Windows 8 и более поздние версии | Указывает на захваченные данные. | Да | Да |
Входные данные в пользовательском режиме | Windows 7 и более ранние версии | Указывает на захваченные данные или исходный буфер пользовательского режима. | Нет. Должен считываться в разделе try/except. | Нет. Необходимо выделить память ядра, скопировать данные из исходного буфера в режиме try/except и передать скопированные данные в системную подпрограмму. |
Выходные данные в пользовательском режиме | Все | Указывает на исходный буфер пользовательского режима. | Нет. Должен выполнять запись в разделе try/except. | Нет. Необходимо выделить память ядра, передать память ядра системной подпрограмме и скопировать результаты обратно в исходный буфер в режиме try/except. |
Входные и выходные данные в режиме ядра | Все | Указывает на исходный буфер режима ядра. | Да | Да |
Дополнительные сведения о подпрограммах RegistryCallback и драйверах фильтров реестра см. в разделе Фильтрация вызовов реестра.
RegistryCallback выполняется в IRQL = PASSIVE_LEVEL и в контексте потока, выполняющего операцию реестра.
Примеры
Чтобы определить подпрограмму обратного вызова RegistryCallback , необходимо сначала предоставить объявление функции, определяющее тип определяемой процедуры обратного вызова. Windows предоставляет набор типов функций обратного вызова для драйверов. Объявление функции с помощью типов функций обратного вызова помогает анализу кода для драйверов, средству проверки статических драйверов (SDV) и другим средствам проверки находить ошибки, и это требование для написания драйверов для операционной системы Windows.
Например, чтобы определить подпрограмму обратного вызова RegistryCallback с именем MyRegistryCallback
, используйте тип EX_CALLBACK_FUNCTION, как показано в следующем примере кода:
EX_CALLBACK_FUNCTION MyRegistryCallback;
Затем реализуйте процедуру обратного вызова следующим образом:
_Use_decl_annotations_
NTSTATUS
MyRegistryCallback(
PVOID CallbackContext,
PVOID Argument1,
PVOID Argument2
)
{
// Function body
}
Тип функции EX_CALLBACK_FUNCTION определяется в файле заголовка Wdm.h. Чтобы более точно определить ошибки при запуске средств анализа кода, обязательно добавьте заметку Use_decl_annotations в определение функции. Заметка Use_decl_annotations гарантирует использование заметок, которые применяются к типу функции EX_CALLBACK_FUNCTION в файле заголовка. Дополнительные сведения о требованиях к объявлениям функций см. в разделе Объявление функций с помощью типов ролей функций для драйверов WDM. Сведения о Use_decl_annotations см. в статье О поведении функции.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Поддерживается начиная с Windows XP (см. раздел Возвращаемое значение). |
Целевая платформа | Персональный компьютер |
Верхняя часть | wdm.h (включая Wdm.h, Ntddk.h, Ntifs.h) |
IRQL | Вызывается на PASSIVE_LEVEL (см. раздел "Примечания"). |