The RtlQueryRegistryValues routine allows the caller to query several values from the registry subtree with a single call.
NTSTATUS
RtlQueryRegistryValues(
IN ULONG RelativeTo,
IN PCWSTR Path,
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
IN PVOID Context,
IN PVOID Environment OPTIONAL
);
| 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. (For a system process, this is \Users\.Default.) | |
The RelativeTo value can be modified by ORing it with one of the following flags.
| 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. | |
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;
A QueryRoutine function is declared as follows:
NTSTATUS
QueryRoutine (
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
);
| 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, RtlQueryRegistryValues immediately exits with a status code of STATUS_OBJECT_NAME_NOT_FOUND. This occurs if the Name member is NULL and the current key has no subkeys, or if Name specifies a nonexistent subkey. (If this flag is not specified, then when no match is found for a non-NULL Name, the routine uses the DefaultValue member as the value. When Name is NULL and the current key has no subkeys, the routine simply skips that table entry.) | |
| 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. 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 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 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 member is ignored, and the EntryContext points to the buffer to store the value. | |
| RTL_QUERY_REGISTRY_DELETE | |
| This is used to delete value keys after they have been queried. | |
RtlQueryRegistryValues returns an NTSTATUS code. The possible return values include:
RtlQueryRegistryValues also terminates processing of the table if the QueryRoutine function for a table entry returns an NTSTATUS error code, and returns that error code as its result. (With one exception: If QueryRoutine returns STATUS_BUFFER_TOO_SMALL, the error code is ignored.)
Declared in wdm.h and ntddk.h. Include wdm.h or ntddk.h.
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. The table is terminated by an entry with a NULL QueryRoutine member and a NULL Name member. The table must be allocated from nonpaged pool.
If an entry does not specify the RTL_QUERY_REGISTRY_DIRECT flag, RtlQueryRegistryValues uses the specified QueryRoutine function to report the value name, type, data, and data length, in bytes, to the caller. If the Name member of the entry is NULL, RtlQueryRegistryValues reports every direct subkey of the key. If the key type is REG_MULTI_SZ and the RTL_QUERY_REGISTRY_NOEXPAND flag not is specified, the routine calls QueryRoutine separately for each individual string; otherwise the routine reports it as a single value. If an entry specifies the RTL_QUERY_REGISTRY_DIRECT flag, RtlQueryRegistryValues stores the value of the key in the buffer pointed to by the entry's EntryContext member. The format of the returned data is as follows.
| Key data type | How data is returned |
|---|---|
| A zero-terminated Unicode string (such as REG_SZ, REG_EXPAND_SZ). | EntryContext must point to an initialized UNICODE_STRING structure. If the Buffer member of UNICODE_STRING is NULL, the routine allocates storage for the string data. Otherwise, it stores the string data in the buffer that Buffer points to. |
| REG_MULTI_SZ | You must specify the RTL_QUERY_REGISTRY_NOEXPAND flag for this key data type. EntryContext points to an initialized UNICODE_STRING structure. The routine stores the key value as a single string value. Each individual component within the string is terminated by a zero.
If the Buffer member of UNICODE_STRING is NULL, the routine allocates storage for the string data. Otherwise, it stores the string data in the buffer that Buffer points to. |
| Nonstring data with size, in bytes, <= sizeof(ULONG) | The value is stored in the memory location specified by EntryContext. |
| Nonstring data with size, in bytes, > sizeof(ULONG) | The buffer pointed to by EntryContext must begin with a signed LONG value. The magnitude of the value must specify the size, in bytes, of the buffer. If the sign of the value is negative, RtlQueryRegistryValues will only store the data of the key value. Otherwise, it will use the first ULONG in the buffer to record the value length, in bytes, the second ULONG to record the value type, and the rest of the buffer to store the value data. |
If an error occurs at any stage of processing of the query table RtlQueryRegistryValues stops processing the table and returns the error status.
See ZwSetValueKey for a description of the possible REG_XXX values.
Callers of RtlQueryRegistryValues must be running at IRQL = PASSIVE_LEVEL.
RtlZeroMemory, ZwEnumerateKey, ZwEnumerateValueKey, ZwSetValueKey