EX_CALLBACK_FUNCTION callback function (wdm.h)

A filter driver's RegistryCallback routine can monitor, block, or modify a registry operation.

Syntax

EX_CALLBACK_FUNCTION ExCallbackFunction;

NTSTATUS ExCallbackFunction(
  [in]           PVOID CallbackContext,
  [in, optional] PVOID Argument1,
  [in, optional] PVOID Argument2
)
{...}

Parameters

[in] CallbackContext

The value that the driver passed as the Context parameter to CmRegisterCallback or CmRegisterCallbackEx when it registered this RegistryCallback routine.

[in, optional] Argument1

A REG_NOTIFY_CLASS-typed value that identifies the type of registry operation that is being performed and whether the RegistryCallback routine is being called before or after the registry operation is performed.

[in, optional] Argument2

A pointer to a structure that contains information that is specific to the type of registry operation. The structure type depends on the REG_NOTIFY_CLASS-typed value for Argument1, as shown in the following table. For information about which REG_NOTIFY_CLASS-typed values are available for which operating system versions, see REG_NOTIFY_CLASS.

REG_NOTIFY_CLASS value Structure type
RegNtDeleteKey REG_DELETE_KEY_INFORMATION
RegNtPreDeleteKey REG_DELETE_KEY_INFORMATION
RegNtPostDeleteKey REG_POST_OPERATION_INFORMATION
RegNtSetValueKey REG_SET_VALUE_KEY_INFORMATION
RegNtPreSetValueKey REG_SET_VALUE_KEY_INFORMATION
RegNtPostSetValueKey REG_POST_OPERATION_INFORMATION
RegNtDeleteValueKey REG_DELETE_VALUE_KEY_INFORMATION
RegNtPreDeleteValueKey REG_DELETE_VALUE_KEY_INFORMATION
RegNtPostDeleteValueKey REG_POST_OPERATION_INFORMATION
RegNtSetInformationKey REG_SET_INFORMATION_KEY_INFORMATION
RegNtPreSetInformationKey REG_SET_INFORMATION_KEY_INFORMATION
RegNtPostSetInformationKey REG_POST_OPERATION_INFORMATION
RegNtRenameKey REG_RENAME_KEY_INFORMATION
RegNtPreRenameKey REG_RENAME_KEY_INFORMATION
RegNtPostRenameKey REG_POST_OPERATION_INFORMATION
RegNtEnumerateKey REG_ENUMERATE_KEY_INFORMATION
RegNtPreEnumerateKey REG_ENUMERATE_KEY_INFORMATION
RegNtPostEnumerateKey REG_POST_OPERATION_INFORMATION
RegNtEnumerateValueKey REG_ENUMERATE_VALUE_KEY_INFORMATION
RegNtPreEnumerateValueKey REG_ENUMERATE_VALUE_KEY_INFORMATION
RegNtPostEnumerateValueKey REG_POST_OPERATION_INFORMATION
RegNtQueryKey REG_QUERY_KEY_INFORMATION
RegNtPreQueryKey REG_QUERY_KEY_INFORMATION
RegNtPostQueryKey REG_POST_OPERATION_INFORMATION
RegNtQueryValueKey REG_QUERY_VALUE_KEY_INFORMATION
RegNtPreQueryValueKey REG_QUERY_VALUE_KEY_INFORMATION
RegNtPostQueryValueKey REG_POST_OPERATION_INFORMATION
RegNtQueryMultipleValueKey REG_QUERY_MULTIPLE_VALUE_KEY_INFORMATION
RegNtPreQueryMultipleValueKey REG_QUERY_MULTIPLE_VALUE_KEY_INFORMATION
RegNtPostQueryMultipleValueKey REG_POST_OPERATION_INFORMATION
RegNtPreCreateKey REG_PRE_CREATE_KEY_INFORMATION
RegNtPreCreateKeyEx REG_CREATE_KEY_INFORMATION**
RegNtPostCreateKey REG_POST_CREATE_KEY_INFORMATION
RegNtPostCreateKeyEx REG_POST_OPERATION_INFORMATION
RegNtPreOpenKey REG_PRE_OPEN_KEY_INFORMATION**
RegNtPreOpenKeyEx REG_OPEN_KEY_INFORMATION
RegNtPostOpenKey REG_POST_OPEN_KEY_INFORMATION
RegNtPostOpenKeyEx REG_POST_OPERATION_INFORMATION
RegNtKeyHandleClose REG_KEY_HANDLE_CLOSE_INFORMATION
RegNtPreKeyHandleClose REG_KEY_HANDLE_CLOSE_INFORMATION
RegNtPostKeyHandleClose REG_POST_OPERATION_INFORMATION
RegNtPreFlushKey REG_FLUSH_KEY_INFORMATION
RegNtPostFlushKey REG_POST_OPERATION_INFORMATION
RegNtPreLoadKey REG_LOAD_KEY_INFORMATION
RegNtPostLoadKey REG_POST_OPERATION_INFORMATION
RegNtPreUnLoadKey REG_UNLOAD_KEY_INFORMATION
RegNtPostUnLoadKey REG_POST_OPERATION_INFORMATION
RegNtPreQueryKeySecurity REG_QUERY_KEY_SECURITY_INFORMATION
RegNtPostQueryKeySecurity REG_POST_OPERATION_INFORMATION
RegNtPreSetKeySecurity REG_SET_KEY_SECURITY_INFORMATION
RegNtPostSetKeySecurity REG_POST_OPERATION_INFORMATION
RegNtCallbackObjectContextCleanup REG_CALLBACK_CONTEXT_CLEANUP_INFORMATION
RegNtPreRestoreKey REG_RESTORE_KEY_INFORMATION
RegNtPostRestoreKey REG_POST_OPERATION_INFORMATION
RegNtPreSaveKey REG_SAVE_KEY_INFORMATION
RegNtPostSaveKey REG_POST_OPERATION_INFORMATION
RegNtPreReplaceKey REG_REPLACE_KEY_INFORMATION
RegNtPostReplaceKey REG_POST_OPERATION_INFORMATION
RegNtPreQueryKeyName REG_QUERY_KEY_NAME
RegNtPostQueryKeyName REG_POST_OPERATION_INFORMATION
RegNtPreSaveMergedKey REG_SAVE_MERGED_KEY_INFORMATION
RegNtPostSaveMergedKey REG_POST_OPERATION_INFORMATION

Starting with Windows 7, the actual data structure passed in when the notify class is RegNtPreCreateKeyEx or RegNtPreOpenKeyEx is the V1 version of this structure, REG_CREATE_KEY_INFORMATION_V1 or REG_OPEN_KEY_INFORMATION_V1, respectively. Check the Reserved member to determine the version of the structure.

Version number Structure name
0 REG_CREATE_KEY_INFORMATION and REG_OPEN_KEY_INFORMATION
1 REG_CREATE_KEY_INFORMATION_V1 and REG_OPEN_KEY_INFORMATION_V1

Return value

For more information about when a RegistryCallback routine should return each of these status values, see Filtering Registry Calls.

Remarks

To be notified of registry operations, a kernel-mode component (such as the driver component of an antivirus software package) can call CmRegisterCallback or CmRegisterCallbackEx to register a RegistryCallback routine.

The RegistryCallback routine can inspect the contents of the input and output buffers that are supplied for registry operations. A registry operation can be initiated by a user-mode application that calls a user-mode registry routine (such as RegCreateKeyEx or RegOpenKeyEx) or by a driver that calls a kernel-mode registry routine (such as ZwCreateKey or ZwOpenKey). An input buffer is a memory buffer supplied by the initiator from which the registry reads input data for the operation. An output buffer is a buffer supplied by the initiator into which the registry writes output data requested by the initiator.

Before calling the RegistryCallback routine, the kernel probes (to verify alignment and accessibility) all members of the Argument2 structures that point to output buffers in user-mode memory, but does not capture user-mode output buffers in system memory. The callback routine must enclose any access of an output buffer in a try/except block. If the callback routine needs to pass an output buffer pointer to a system routine (for example, ZwOpenKey), and the buffer is in user-mode memory, the callback routine must first capture the buffer.

The handling of input buffers depends on the Windows version. Starting with Windows 8, the kernel captures all input buffers pointed to by members of the Argument2 structures in system memory before calling the RegistryCallback routine. In versions of Windows before Windows 8, the kernel probes all members of the Argument2 structures that point to input buffers in user-mode memory, but captures only some of these buffers in system memory. In these earlier versions of Windows, the callback routine must enclose any access of an input buffer in a try/except block. Additionally, if the callback routine needs to pass an input buffer pointer to a system routine (for example, ZwOpenKey), and the buffer is in user-mode memory, the callback routine must first capture the buffer.

The following table summarizes the requirements for buffer accesses by the RegistryCallback routine.

Buffer type Windows version Buffer pointer passed to callback routine Safe for callback routine to directly access? Safe to pass to system routines (such as ZwOpenKey)?
User-mode input Windows 8 and later Points to captured data. Yes Yes
User-mode input Windows 7 and earlier Points to captured data or original user-mode buffer. No. Must read under try/except. No. Must allocate kernel memory, copy data from the original buffer under try/except, and pass the copied data to the system routine.
User-mode output All Points to original user-mode buffer. No. Must write under try/except. No. Must allocate kernel memory, pass kernel memory to the system routine, and copy the results back to the original buffer under try/except.
Kernel-mode input and output All Points to original kernel-mode buffer. Yes Yes

For more information about RegistryCallback routines and registry filter drivers, see Filtering Registry Calls.

A RegistryCallback executes at IRQL = PASSIVE_LEVEL and in the context of the thread that is performing the registry operation.

Examples

To define a RegistryCallback callback routine, you must first provide a function declaration that identifies the type of callback routine you're defining. Windows provides a set of callback function types for drivers. Declaring a function using the callback function types helps Code Analysis for Drivers, Static Driver Verifier (SDV), and other verification tools find errors, and it's a requirement for writing drivers for the Windows operating system.

For example, to define a RegistryCallback callback routine that is named MyRegistryCallback, use the EX_CALLBACK_FUNCTION type as shown in this code example:

EX_CALLBACK_FUNCTION MyRegistryCallback;

Then, implement your callback routine as follows:

_Use_decl_annotations_
NTSTATUS 
  MyRegistryCallback(
    PVOID  CallbackContext,
    PVOID  Argument1,
    PVOID  Argument2 
    )
  {
      // Function body
  }

The EX_CALLBACK_FUNCTION function type is defined in the Wdm.h header file. To more accurately identify errors when you run the code analysis tools, be sure to add the Use_decl_annotations annotation to your function definition. The Use_decl_annotations annotation ensures that the annotations that are applied to the EX_CALLBACK_FUNCTION function type in the header file are used. For more information about the requirements for function declarations, see Declaring Functions by Using Function Role Types for WDM Drivers. For information about Use_decl_annotations, see Annotating Function Behavior.

Requirements

Requirement Value
Minimum supported client Supported starting with Windows XP (see Return Value section).
Target Platform Desktop
Header wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
IRQL Called at PASSIVE_LEVEL (see Remarks section).

See also

CmRegisterCallback

CmUnRegisterCallback

ProbeForRead

REG_NOTIFY_CLASS

ZwOpenKey