RegistryCallback routine
过滤器驱动程序的常规RegistryCallback可以监视,阻止或修改一个注册表操作。
句法
NTSTATUS CmRegisterCallback( _In_ PEX_CALLBACK_FUNCTION Function, _In_opt_ PVOID Context, _Out_ PLARGE_INTEGER Cookie );
参数
-
CallbackContext [输入]
-
该驱动程序作为上下文参数传递的值CmRegisterCallback或CmRegisterCallbackEx当它注册了这个RegistryCallback程序。
ARGUMENT1 [中,可选]
-
一个REG_NOTIFY_CLASS标识正在执行以及是否RegistryCallback例程正在之前或执行注册表操作之后称为注册表操作的类型-typed值。
ARGUMENT2 [中,可选]
-
一个指向包含特定于注册表操作的类型信息的结构。 结构类型取决于为ARGUMENT1的REG_NOTIFY_CLASS类型的值,如所示的下表。 有关哪些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
返回值
-
Windows XP和Windows Server 2003中:
-
如果RegistryCallback例程返回STATUS_SUCCESS,配置管理器继续处理注册表操作。
如果RegistryCallback程序返回该状态值NT_SUCCESS ( 状态 )等于FALSE,配置管理器停止处理注册表操作,并返回指定的返回值调用线程。
Windows Vista和更高版本:
-
如果RegistryCallback例程返回STATUS_SUCCESS,配置管理器继续处理注册表操作。
如果RegistryCallback例程返回STATUS_CALLBACK_BYPASS,配置管理器停止处理注册表操作,并返回STATUS_SUCCESS调用线程。
如果RegistryCallback程序返回该状态值NT_SUCCESS ( 状态 )等于FALSE(除STATUS_CALLBACK_BYPASS),配置管理器停止处理注册表操作,并返回指定的返回值调用线程。
有关当RegistryCallback例程应该返回这些状态值的更多信息,请参阅过滤注册表调用 。
备注
被通知的注册表操作,内核模式组件(如防病毒软件的驱动程序部分)可以调用CmRegisterCallback或CmRegisterCallbackEx注册一个RegistryCallback程序。
该RegistryCallback例程可以检查被注册表操作供给的输入和输出缓冲器的内容。 注册表操作可以通过调用一个用户模式注册表例程(如用户模式的应用程序被启动RegCreateKeyEx或RegOpenKeyEx )或通过调用一个内核模式注册表例程(例如驾驶ZwCreateKey函数或ZwOpenKey函数 )。 输入缓冲器是通过从该操作的注册表中读取输入数据的发起者提供的存储器缓冲器。 输出缓冲器是由成写入注册表由发起请求的输出数据的发起者提供的缓冲器。
调用RegistryCallback例程之前,内核探针(验证对准和可访问),该指向输出缓冲器中的用户模式存储器的ARGUMENT2结构的所有成员,但在系统存储器不能捕获用户模式输出缓冲器。 回调函数必须用一个输出缓冲区的一个尝试任何访问/ except块。 如果回调例程需要输出缓冲器指针传递到一个系统程序(例如,ZwOpenKey函数 ),和缓冲液是在用户模式存储器,回调例程必须先捕获缓冲器。
输入缓冲器的处理依赖于Windows版本。 与Windows 8开始,内核捕获所有输入缓冲区指向在系统内存中ARGUMENT2结构的成员调用RegistryCallback程序之前。 在Windows 8之前的Windows版本,内核探针指向输入缓冲器在用户模式下内存ARGUMENT2结构的所有成员,但只抓住了一些在系统内存中这些缓冲区。 在这些早期版本的Windows,回调函数必须将输入缓冲器在try / except块任何访问。 此外,如果回调例程需要输入缓冲器指针传递到一个系统程序(例如,ZwOpenKey函数),和缓冲液是在用户模式存储器,回调例程必须先捕获缓冲器。
下表概括了对缓冲器访问由RegistryCallback常规的要求。
缓冲类型 | Windows版本 | 缓冲区指针传递给回调例程 | 安全的回调例程直接访问? | 安全传递到系统例程(如ZwOpenKey函数 )? |
---|---|---|---|---|
用户模式输入 | Windows 8和更高版本 | 点捕获的数据。 | 是 | 是 |
用户模式输入 | Windows 7和更早 | 点捕获的数据或原用户模式缓冲区。 | 号必须在尝试/读取时除外。 | 号必须分配内核内存,从原来的缓冲下试/复制数据,除了和复制的数据传递到系统程序。 |
用户模式输出 | 所有 | 指向原来的用户模式缓冲区。 | 号必须在尝试写/除外。 | 号必须分配内核内存,内核内存传递给系统例行程序,和/结果复制回原来的缓冲区下试除。 |
内核模式的输入和输出 | 所有 | 指向原来的内核模式缓冲区。 | 是 | 是 |
有关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参数1, PVOID ARGUMENT2 ) { //函数体 }
该EX_CALLBACK_FUNCTION功能类型是在WDM.H头文件中定义。 为了更准确地识别错误,当您运行的代码分析工具,一定要在_Use_decl_annotations_注释添加到您的函数定义。 所述_Use_decl_annotations_注解确保用于应用到在头文件的EX_CALLBACK_FUNCTION功能类型的注释。 有关函数声明的要求的更多信息,请参阅通过使用功能角色类型为WDM驱动程序函数声明 。 有关_Use_decl_annotations_信息,请参见注解功能的行为 。
要求
目标平台 |
|
---|---|
版 | 支持从Windows XP(请参阅返回值一节)。 |
头 |
|
IRQL | 在PASSIVE_LEVEL调用(见注释部分)。 |