使用驱动程序定义的回调对象

若要使用由另一个驱动程序定义的回调对象,驱动程序会打开该对象,然后注册一个在触发回调时要调用的例程,如下图所示。 请求通知的驱动程序必须知道回调对象的名称,并且必须了解传递给回调例程的参数的语义。

说明回调通知注册的示意图。

驱动程序必须先调用 InitializeObjectAttributes 以创建属性块,并指定对象的名称,然后才能打开对象。 在具有指向属性块的指针后,它会调用 ExCreateCallback,传递属性指针、接收回调句柄的位置,以及 Create 参数的 FALSE,指示它需要现有回调对象。

然后,驱动程序可以使用返回的句柄调用 ExRegisterCallback 来注册其回调例程。

回调例程具有以下原型:

typedef VOID (*PCALLBACK_FUNCTION ) (
    IN PVOID CallbackContext,
    IN PVOID Argument1,
    IN PVOID Argument2
    );

CallbackContext 参数是每次调用回调例程时要传递给它的上下文指针。 通常,此参数是指向上下文数据块的指针,如果可以在DISPATCH_LEVEL调用例程,则调用方应从非分页池分配该块。 这两个参数由创建回调的组件定义。 通常,参数提供有关触发回调的条件的信息。

当回调的创建者触发通知时,系统会调用已注册的例程,将指针传递给上下文和两个参数。 参数的值由创建回调的组件提供。 回调例程在创建驱动程序触发通知的同一 IRQL 中调用,始终为 IRQL <= DISPATCH_LEVEL。

在其回调例程中,驱动程序可以针对当前条件执行所需的任何任务。

当驱动程序不再需要通知时,它应调用 ExUnregisterCallback ,以从已注册的回调列表中删除其例程并删除其对回调对象的引用。