Функция RtlQueryRegistryValues (wdm.h)
Подпрограмма
Синтаксис
NTSYSAPI NTSTATUS RtlQueryRegistryValues(
[in] ULONG RelativeTo,
[in] PCWSTR Path,
[in, out] PRTL_QUERY_REGISTRY_TABLE QueryTable,
[in, optional] PVOID Context,
[in, optional] PVOID Environment
);
Параметры
[in] RelativeTo
Указывает, является ли пути абсолютным путем реестра или относительно предопределенного пути в качестве одного из следующих.
Ценность | Значение |
---|---|
RTL_REGISTRY_ABSOLUTE | Путь — абсолютный путь к реестру. |
RTL_REGISTRY_CONTROL | Путь относительно \Registry\Machine\System\CurrentControlSet\Control. |
RTL_REGISTRY_DEVICEMAP | Путь относительно \Registry\Machine\Hardware\DeviceMap. |
RTL_REGISTRY_SERVICES | Путь относительно \Registry\Machine\System\CurrentControlSet\Services. |
RTL_REGISTRY_USER | Путь относительно \Registry\User\CurrentUser. (Для системного процесса это \User\. По умолчанию.) |
RTL_REGISTRY_WINDOWS_NT | Путь относительно \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion. |
Значение RelativeTo можно изменить побитовой инструкцией-ORing с одним из следующих флагов.
Флаг | Значение |
---|---|
RTL_REGISTRY_OPTIONAL | Указывает, что ключ, на который ссылается этот параметр, и параметр пути |
RTL_REGISTRY_HANDLE | Указывает, что параметр пути |
[in] Path
Указатель на абсолютный путь реестра или путь относительно известного расположения, указанного параметром RelativeTo. Обратите внимание, что имена ключей в таком пути должны быть известны вызывающей, включая последний ключ в пути. Если указан флаг RTL_REGISTRY_HANDLE, этот параметр является дескриптором реестра для запроса непосредственно открытого ключа.
[in, out] QueryTable
Указатель на таблицу с одним или несколькими именами значений и именами вложенных ключей, в которых заинтересован вызывающий объект. Каждая запись таблицы содержит адрес указанной вызывающей функции QueryRoutine, которая будет вызываться для каждого имени значения, существующего в реестре. Таблица должна быть завершена с записью NULL таблицы, которая является записью таблицы с элементом NULLQueryRoutine и элементом NULLName. Структура записей таблицы запросов определяется следующим образом:
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;
Если вызывающий объект выделяет хранилище для таблицы запросов, на которую указывает параметр QueryTable, вызывающий объект отвечает за освобождение этого хранилища после возврата вызова RtlQueryRegistryValues.
QueryRoutine
Адрес функции QueryRoutine, которая вызывается с именем, типом, данными и длиной данных реестра. Если этот элемент и элемент Name являются null, он помечает конец таблицы.
Функция QueryRoutine объявлена следующим образом:
NTSTATUS
QueryRoutine (
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
);
Дополнительные сведения см. в разделе QueryRoutine.
Флаги
Флаги для управления интерпретацией оставшихся элементов структуры RTL_QUERY_REGISTRY_TABLE. Для этого элемента определены следующие биты флагов.
Ценность | Значение |
---|---|
RTL_QUERY_REGISTRY_SUBKEY |
имя этой записи таблицы — это еще один путь к разделу реестра, а все следующие записи таблицы предназначены для этого ключа, а не ключа, указанного параметром path. Это изменение фокуса длится до конца таблицы или до тех пор, пока не будет замечена другая RTL_REGISTRY_SUBKEY или RTL_QUERY_REGISTRY_TOPKEY запись. Каждая такая запись должна указывать путь относительно пути |
RTL_QUERY_REGISTRY_TOPKEY | Сбрасывает текущий дескриптор раздела реестра до исходного, указанного параметрами RelativeTo и path. Это полезно для возврата к исходному узлу после убывания в подразделы с флагом RTL_QUERY_REGISTRY_SUBKEY. |
RTL_QUERY_REGISTRY_REQUIRED | Указывает, что это значение реестра должно существовать, если DefaultType = REG_NONE; в противном случае, если он не найден, RtlQueryRegistryValues немедленно завершает работу с кодом состояния STATUS_OBJECT_NAME_NOT_FOUND. Это происходит, если элемент NameNULL, а текущий ключ не имеет вложенных ключей или если Name указывает несуществующий подраздел. (Если этот флаг не указан, то при отсутствии совпадения дляNULLNameподпрограмма использует элемент DefaultValue в качестве значения. Если имяnull, а текущий ключ не имеет вложенных ключей, подпрограмма просто пропускает эту запись таблицы.) |
RTL_QUERY_REGISTRY_NOVALUE | Указывает, что несмотря на отсутствие name для этой записи таблицы, все, что вызывающий объект хочет, является обратным вызовом: то есть вызывающий объект не хочет перечислять все значения в текущем ключе. QueryRoutine вызывается с NULL для ValueData, REG_NONE для ValueTypeи ноль для ValueLength. |
RTL_QUERY_REGISTRY_NOEXPAND | Для значения реестра типа REG_EXPAND_SZ или REG_MULTI_SZ этот флаг переопределяет поведение по умолчанию, которое необходимо предварительно обработать значение реестра перед вызовом подпрограммы QueryRoutine. По умолчанию RtlQueryRegistryValues расширяет ссылки на переменные среды в значениях REG_EXPAND_SZ и перечисляет каждую строку, завершающуюся значением NULL, в REG_MULTI_SZ в отдельном вызове QueryRoutine, чтобы строки отображались как REG_SZ значения, имеющие те же ValueName. Если этот флаг задан, QueryRoutine получает необработанное значение REG_EXPAND_SZ или REG_MULTI_SZ из реестра. Дополнительные сведения о форматах данных для этих значений см. в KEY_VALUE_BASIC_INFORMATION. |
RTL_QUERY_REGISTRY_DIRECT | Элемент queryRoutine |
RTL_QUERY_REGISTRY_TYPECHECK | Используйте этот флаг с флагом RTL_QUERY_REGISTRY_DIRECT, чтобы убедиться, что тип REG_XXX сохраненного значения реестра соответствует типу вызывающего объекта. Если типы не соответствуют, вызов завершается ошибкой. Дополнительные сведения см. в разделе "Примечания". |
RTL_QUERY_REGISTRY_DELETE | Этот флаг используется для удаления ключей значений после запроса. |
Начиная с Windows 2000 поддержка папки "Входящие" предоставляется для всех битов флагов в предыдущей таблице, за исключением RTL_QUERY_REGISTRY_TYPECHECK. Поддержка папки "Входящие" для RTL_QUERY_REGISTRY_TYPECHECK доступна начиная с Windows 8. Для более ранних версий Windows поддержка RTL_QUERY_REGISTRY_TYPECHECK предоставляется через Центр обновления Windows. Дополнительные сведения см. в разделе "Примечания".
Имя
Это имя значения, запрашиваемого вызывающим элементом. Если имяNULL, функция QueryRoutine, указанная для этой записи таблицы, вызывается для всех значений, связанных с текущим разделом реестра. Если установлен флаг RTL_QUERY_REGISTRY_DIRECT, необходимо указать значение, отличное отNULL для Name.
EntryContext
Если установлен флаг RTL_QUERY_REGISTRY_DIRECT, это указатель на буфер для хранения результата операции запроса для этого ключа. В противном случае это значение передается в качестве параметра EntryContextQueryRoutine.
DefaultType
Наименьший байт этого элемента указывает тип возвращаемых данных REG_XXX, если не найден соответствующий ключ, а флаг RTL_QUERY_REGISTRY_REQUIRED не указан. Укажите REG_NONE для типа по умолчанию. Если установлен флаг RTL_QUERY_REGISTRY_TYPECHECK, самый значительный байт этого члена указывает тип REG_XXX хранящегося значения реестра, которое ожидает вызывающий элемент. Биты от 8 до 23 этого элемента зарезервированы и должны быть нулевыми.
DefaultData
Указатель на возвращаемое значение по умолчанию, если не найден соответствующий ключ, и флаг RTL_QUERY_REGISTRY_REQUIRED не указан. Этот элемент игнорируется, если DefaultType = REG_NONE. В противном случае тип данных, на которые указывает
DefaultLength
Указывает длину в байтах элемента DefaultData. Если DefaultType REG_SZ, REG_EXPAND_SZ или REG_MULTI_SZ вызывающие элементы могут указывать ноль, чтобы указать, RtlQueryRegistryValues должен вычислить длину на основе значения данных по умолчанию. Если DefaultType = REG_NONE, этот элемент игнорируется.
[in, optional] Context
Указывает значение, переданное в качестве параметра контекста контекста функции QueryRoutine при каждом вызове.
[in, optional] Environment
Указатель на среду, используемую при расширении значений переменных в значениях реестра REG_EXPAND_SZ или указатель NULL (необязательно).
Возвращаемое значение
RtlQueryRegistryValues возвращает код NTSTATUS. Возможные возвращаемые значения:
Возвращаемый код | Описание |
---|---|
STATUS_SUCCESS | Вся таблица запросов успешно обработана. |
STATUS_INVALID_PARAMETER | Обработка таблицы запроса завершается недопустимой записью таблицы. Запись таблицы может быть недопустимой, если указанные флаги требуют queryRoutine или элемента Name неNULL, но было указано ЗНАЧЕНИЕ NULL. |
STATUS_OBJECT_NAME_NOT_FOUND | Параметр пути |
STATUS_BUFFER_TOO_SMALL | Флаг RTL_QUERY_REGISTRY_DIRECT задан, а буфер, указанный EntryContext, слишком мал для хранения данных значения ключа. |
STATUS_OBJECT_TYPE_MISMATCH | Флаг RTL_QUERY_REGISTRY_TYPECHECK задан, а тип хранимого значения реестра не соответствует типу вызывающего объекта. |
RtlQueryRegistryValues также завершает обработку таблицы, если функция QueryRoutine для записи таблицы возвращает код ошибки NTSTATUS и возвращает этот код ошибки в качестве результата. (За одним исключением: если QueryRoutine возвращает STATUS_BUFFER_TOO_SMALL, код ошибки игнорируется.)
Замечания
Вызывающий объект задает начальный путь ключа и таблицу. Таблица содержит одну или несколько записей, описывающих ключевые значения и имена подразделов, в которых заинтересован вызывающий объект. Таблица завершается записью с элементом NULLQueryRoutine и элементом NULLName. Таблица должна быть выделена из непагированного пула.
Драйверы режима ядра должны указывать флаг RTL_QUERY_REGISTRY_NOEXPAND, чтобы предотвратить вызов подпрограмм переменных среды. Эти подпрограммы небезопасны, поэтому драйверы в режиме ядра не должны использовать их.
Осторожность
Если вы используете флаг RTL_QUERY_REGISTRY_DIRECT, ненадежное приложение в режиме пользователя может вызвать переполнение буфера. Переполнение буфера может произойти, если драйвер использует этот флаг для чтения значения реестра, к которому назначен неправильный тип. Во всех случаях драйвер, использующий флаг RTL_QUERY_REGISTRY_DIRECT, должен дополнительно использовать флаг RTL_QUERY_REGISTRY_TYPECHECK для предотвращения таких переполнений.
Если флаг RTL_QUERY_REGISTRY_TYPECHECK задан в записи таблицы, вызывающий объект должен указать ожидаемый тип REG_XXX в 8 наиболее важных битах (MSBS) 32-разрядной DefaultType элемент записи таблицы. Как показано в следующем примере кода, константу RTL_QUERY_REGISTRY_TYPECHECK_SHIFT, определяемую как 24, можно использовать в качестве количества сдвигов, необходимых для размещения ожидаемого REG_XXX типа в 8 MSBS элемента DefaultType.
RTL_QUERY_REGISTRY_TABLE QueryRegTable[2];
...
QueryRegTable[0].DefaultType = (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE;
...
QueryRegTable[1].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE;
...
Начиная с Windows 8, если RtlQueryRegistryValues обращается к ненадежному кусту, а вызывающий задает флаг RTL_QUERY_REGISTRY_DIRECT для этого вызова, вызывающий объект должен дополнительно задать флаг RTL_QUERY_REGISTRY_TYPECHECK. Нарушение этого правила вызовом из пользовательского режима вызывает исключение. Нарушение этого правила вызовом из режима ядра вызывает проверку ошибки 0x139 (KERNEL_SECURITY_CHECK_FAILURE).
Доверенными являются только системные hives. Вызов RtlQueryRegistryValues, который обращается к системным кустам, не вызывает исключение или ошибку, если установлен флаг RTL_QUERY_REGISTRY_DIRECT, и флаг RTL_QUERY_REGISTRY_TYPECHECK не задан. Однако, как рекомендуется, флаг RTL_QUERY_REGISTRY_TYPECHECK всегда следует задать, если установлен флаг RTL_QUERY_REGISTRY_DIRECT.
Аналогичным образом, в версиях Windows до Windows 8, как рекомендуется, вызов RtlQueryRegistryValues, который задает флаг RTL_QUERY_REGISTRY_DIRECT, должен дополнительно задать флаг RTL_QUERY_REGISTRY_TYPECHECK. Однако неисполнение этой рекомендации не приводит к исключению или проверке ошибок.
Ниже приведен список системных кустов:
\REGISTRY\MACHINE\HARDWARE
\REGISTRY\MACHINE\SOFTWARE
\REGISTRY\MACHINE\SYSTEM
\REGISTRY\MACHINE\SECURITY
\REGISTRY\MACHINE\SAM
Поддержка флага RTL_QUERY_REGISTRY_TYPECHECK доступна через Центр обновления Windows для Windows 7, Windows Vista, Windows Server 2003 и Windows XP. Дополнительные сведения об этом обновлении см. в уязвимостях в ядре Windows, которые могут разрешить повышение привилегий (2393802). В версиях этих операционных систем, которые не имеют этого обновления, вызывающий объект может использовать флаг RTL_QUERY_REGISTRY_TYPECHECK. Однако этот флаг игнорируется подпрограммой RtlQueryRegistryValues.
Начиная с пакета драйверов Windows (WDK) 8, флаг RTL_QUERY_REGISTRY_TYPECHECK определен в файле заголовка Wdm.h следующим образом:
#define RTL_QUERY_REGISTRY_TYPECHECK 0x00000100
Если запись не указывает флаг RTL_QUERY_REGISTRY_DIRECT, RtlQueryRegistryValues использует указанную функцию QueryRoutine, чтобы сообщить имя значения, тип, данные и длину данных в байтах вызывающей функции. Если элемент имени
Тип данных ключа | Как возвращаются данные |
---|---|
Строка Юникода с завершением null (например, REG_SZ, REG_EXPAND_SZ). | EntryContext должен указывать на инициализированную структуру UNICODE_STRING. Если элемент буфера UNICODE_STRINGNULL, подпрограмма выделяет хранилище строковых данных. В противном случае данные строки хранятся в буфере, на который буфер указывает. |
REG_MULTI_SZ | Необходимо указать флаг RTL_QUERY_REGISTRY_NOEXPAND для этого типа данных ключа. EntryContext указывает на инициализированную структуру UNICODE_STRING. Подпрограмма сохраняет значение ключа в виде одного строкового значения. Каждый отдельный компонент в строке завершается нулем. Если элемент буфера UNICODE_STRINGNULL, подпрограмма выделяет хранилище строковых данных. В противном случае данные строки хранятся в буфере, на который буфер указывает. |
Нестроковые данные с размером, в байтах, <= sizeof(ULONG) | Значение хранится в расположении памяти, указанном EntryContext. |
Нестроковые данные с размером, в байтах, >sizeof(ULONG) | Буфер, на который указывает EntryContext, должен начинаться со подписанного значения LONG. Величина значения должна указывать размер буфера в байтах. Если знак значения отрицательный, RtlQueryRegistryValues будет хранить только данные значения ключа. В противном случае он будет использовать первый ULONG в буфере для записи длины значения в байтах, второй ULONG для записи типа значения и остальной части буфера для хранения данных значений. |
Если ошибка возникает на любом этапе обработки таблицы запросов, RtlQueryRegistryValues перестает обрабатывать таблицу и возвращает состояние ошибки.
Описание возможных значений REG_XXX см. в ZwSetValueKey.
Требования
Требование | Ценность |
---|---|
целевая платформа | Всеобщий |
заголовка | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
библиотеки |
Ntoskrnl.lib |
DLL | Ntoskrnl.exe |
IRQL | PASSIVE_LEVEL |