RtlQueryRegistryValues

NTSTATUS
    RtlQueryRegistryValues(

        IN ULONG  RelativeTo,
        IN PWSTR  Path,
        IN PRTL_QUERY_REGISTRY_TABLE  QueryTable,
        IN PVOID  Context,
        IN PVOID  Environment                     /* optional */
        );

RtlQueryRegistryValues allows the caller to query several values from the registry subtree with a single call.

Parameters

RelativeTo
Specifies whether Path is an absolute registry path or is relative to a predefined path as one of the following:

Value

Meaning

RTL_REGISTRY_ABSOLUTE

Path is an absolute registry path.

RTL_REGISTRY_SERVICES

Path is relative to \Registry\Machine\System\CurrentControlSet\Services.

RTL_REGISTRY_CONTROL

Path is relative to \Registry\Machine\System\CurrentControlSet\Control.

RTL_REGISTRY_WINDOWS_NT

Path is relative to \Registry\Machine\Software\Microsoft\
Windows NT\CurrentVersion
.

RTL_REGISTRY_DEVICEMAP

Path is relative to \Registry\Machine\Hardware\DeviceMap.

RTL_REGISTRY_USER

Path is relative to \Registry\User\CurrentUser.

RTL_REGISTRY_OPTIONAL

Specifies that the key referenced by this parameter and the Path parameter are optional.

RTL_REGISTRY_HANDLE

 

Specifies that the Path parameter is actually a registry handle to use. This value is optional.

Path
Points to either an absolute registry path or a path relative to the known location specified by the RelativeTo parameter. Note that the names of keys in such a path must be known to the caller, including the last key in the path. If the RTL_REGISTRY_HANDLE flag is specified, this parameter is a registry handle for an already opened key to be queried directly.
QueryTable
Points to a table of one or more value names and subkey names in which the caller is interested. Each table entry contains a caller-supplied QueryRoutine that will be called for each value name that exists in the registry. The table must be terminated with a NULL table entry, which is a table entry with a NULL QueryRoutine and a NULL Name field. The QueryTable structure is defined as follows:
typedef struct _RTL_QUERY_REGISTRY_TABLE {
    PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
    ULONG Flags;
    PWSTR Name;
    PVOID EntryContext;
    ULONG DefaultType;
    PVOID DefaultData;
    ULONG DefaultLength;
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;

This routine is called with the name, type, data, and data length of a registry value. If this field is NULL, it marks the end of the table.

A caller-supplied QueryRoutine is declared as follows:

NTSTATUS
(*PRTL_QUERY_REGISTRY_ROUTINE)(
    IN PWSTR ValueName,
    IN ULONG ValueType,
    IN PVOID ValueData,
    IN ULONG ValueLength,
    IN PVOID Context,
    IN PVOID EntryContext
    );

The remaining members of the QueryTable structure include the following.

Flags
Control how the remaining fields are to be interpreted, as follows:

Value

Meaning

RTL_QUERY_REGISTRY_SUBKEY

The Name of this table entry is another path to a registry key, and all following table entries are for that key rather than the key specified by the Path parameter. This change in focus lasts until the end of the table or until another RTL_REGISTRY_SUBKEY or RTL_QUERY_REGISTRY_TOPKEY entry is seen. Each such entry must specify a path that is relative to the Path specified in the call to RtlQueryRegistryValues.

RTL_QUERY_REGISTRY_TOPKEY

Resets the current registry key handle to the original one specified by the RelativeTo and Path parameters. This is useful for getting back to the original node after descending into subkeys with the RTL_QUERY_REGISTRY SUBKEY flag.

RTL_QUERY_REGISTRY_REQUIRED

Specifies that this value is required and, if it is not found, STATUS_OBJECT_NAME_NOT_FOUND is returned. This is used for a table entry that specifies a NULL Name so that RtlQueryRegistryValues will enumerate all of the value names under a key and return STATUS_OBJECT_NAME_NOT_FOUND only if there are no value keys under the current key.

RTL_QUERY_REGISTRY_NOVALUE

Specifies that even though there is no Name for this table entry, all the caller wants is a callback: that is, the caller does not want to enumerate all the values under the current key. The QueryRoutine is called with NULL for ValueData, REG_NONE for ValueType, and zero for ValueLength.

RTL_QUERY_REGISTRY_NOEXPAND

Specifies that, if the type of this registry value is REG_EXPAND_SZ or REG_MULTI_SZ, RtlQueryRegistryValues is not to do any preprocessing of these registry values before calling the QueryRoutine. By default, RtlQueryRegistryValues expands environment variable references into REG_EXPAND_SZ values, enumerates each zero-terminated string in a REG_MULTI_SZ value, and calls the QueryRoutine once with each, making it look like there is more than one REG_SZ value with the same ValueName.

RTL_QUERY_REGISTRY_DIRECT

The QueryRoutine is ignored, and the EntryContext points to the location to store the value. For zero-terminated strings, EntryContext points to a UNICODE_STRING structure that describes the maximum size of the buffer. If the Buffer is NULL, a buffer is allocated.

RTL_QUERY_REGISTRY_DELETE

This is used to delete value keys after they have been queried.

Name
This is the name of a Value that the caller queried. If Name is NULL, the QueryRoutine specified for this table entry is called for all values associated with the current registry key.
EntryContext
This is an arbitrary 32-bit field that is passed uninterpreted each time the QueryRoutine is called.
DefaultType
Specifies the REG_xxx type of the data to be queried if Flags is not set with RTL_REGISTRY_REQUIRED; otherwise, zero.
DefaultData
Points to default value(s) for a named value entry of the DefaultType if it is not already in the registry under Name and if Flags is not set with RTL_REGISTRY_REQUIRED; otherwise, NULL.
DefaultLength
If there is no value name that matches the name given by the Name, and the DefaultType field is not REG_NONE, the QueryRoutine for this table entry is called with the contents of the following fields as if the value had been found in the registry. If the DefaultType is REG_SZ, REG_EXPANDSZ, or REG_MULTI_SZ and the DefaultLength is zero, the value of DefaultLength will be computed based on the length of the Unicode string pointed to by DefaultData.
Context
Points to a context that is passed, uninterpreted, when each QueryRoutine is called.
Environment
Points to the environment used when expanding variable values in REG_EXPAND_SZ registry values, or a NULL pointer (optional).

Return Value

RtlQueryRegistryValues returns STATUS_SUCCESS if the entire QueryTable was processed successfully. If an error occurs, RtlQueryRegistryValues returns an error status such as:

STATUS_INVALID_PARAMETER
STATUS_OBJECT_NAME_NOT_FOUND
STATUS_XXX (an error status from a user-supplied QueryRoutine)

Comments

The caller specifies an initial key path and a table. The table contains one or more entries that describe the key values and subkey names in which the caller is interested. RtlQueryRegistryValues starts at the initial key and enumerates the entries in the table.

For each entry specifying a value name or subkey name that exists in the registry, RtlQueryRegistryValues calls the QueryRoutine associated with each table entry. Each entry’s caller-supplied QueryRoutine is passed the value name, type, data, and data length.

When building the QueryTable, be sure to allocate an entry for each value being queried, plus a NULL entry at the end. Zero the table and then initialize the entries.

If an error occurs at any stage of processing the QueryTable, RtlQueryRegistryValues stops processing the table and returns the error status.

Callers of RtlQueryRegistryValues must be running at IRQL PASSIVE_LEVEL.

See Also

RtlZeroMemory, ZwEnumerateKey, ZwOpenKey