Функция RtlQueryRegistryValues (wdm.h)
Подпрограмма RtlQueryRegistryValues позволяет вызывающей объекту запрашивать несколько значений из поддеревья реестра с помощью одного вызова.
Синтаксис
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
Указывает, является ли Path абсолютным путем реестра или относительно предопределенного пути в качестве одного из следующих значений.
Значение | Значение |
---|---|
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 можно изменить с помощью bitwise-ORing с одним из следующих флагов.
Flag | Значение |
---|---|
RTL_REGISTRY_OPTIONAL | Указывает, что ключ, на который ссылается этот параметр, и параметр Path являются необязательными. |
RTL_REGISTRY_HANDLE | Указывает, что параметр Path фактически является дескриптором реестра для использования. |
[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. Каждая такая запись должна указывать путь относительно пути , указанного в вызове RtlQueryRegistryValues. |
RTL_QUERY_REGISTRY_TOPKEY | Сбрасывает текущий дескриптор раздела реестра до исходного, заданного параметрами RelativeTo и Path . Это полезно для возврата к исходному узлу после убывания по подразделам с флагом RTL_QUERY_REGISTRY_SUBKEY. |
RTL_QUERY_REGISTRY_REQUIRED | Указывает, что это значение реестра должно существовать, если DefaultType = REG_NONE; В противном случае, если он не найден, RtlQueryRegistryValues немедленно завершает работу с кодом состояния STATUS_OBJECT_NAME_NOT_FOUND. Этот выход происходит, если член Name имеет значение NULL , а текущий ключ не имеет подразделов или если Name указывает несуществующий подраздел. (Если этот флаг не указан, то при отсутствии совпадений для имени, отличного от NULL, подпрограмма использует элемент DefaultValue в качестве значения. Если имя имеет значение NULL, а текущий ключ не имеет подразделов, подпрограмма просто пропускает запись таблицы.) |
RTL_QUERY_REGISTRY_NOVALUE | Указывает, что, несмотря на отсутствие имени для этой записи таблицы, все, что нужно вызывающему объекту, является обратным вызовом, то есть вызывающий объект не хочет перечислять все значения в текущем ключе. 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 не используется (и должен иметь значение NULL), а EntryContext указывает на буфер для хранения значения. Если вызывающий объект устанавливает этот флаг, вызывающий объект должен дополнительно установить флаг RTL_QUERY_REGISTRY_TYPECHECK для защиты от переполнения буфера. Дополнительные сведения см. в разделе «Примечания». |
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. Дополнительные сведения см. в подразделе "Примечания".
Имя
Это имя значения, которое запрашивает вызывающий объект. Если name имеет значение NULL, функция QueryRoutine , указанная для этой записи таблицы, вызывается для всех значений, связанных с текущим разделом реестра. Если установлен флаг RTL_QUERY_REGISTRY_DIRECT, необходимо указать значение name, отличное от NULL.
EntryContext
Если установлен флаг RTL_QUERY_REGISTRY_DIRECT, это указатель на буфер для хранения результата операции запроса для этого ключа. В противном случае это значение передается как параметр EntryContextобъекта QueryRoutine.
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. В противном случае тип данных, на который указывает DefaultData, должен соответствовать типу значения реестра, заданному элементом DefaultType . Дополнительные сведения о типах значений реестра см. в определении параметра Type в KEY_VALUE_BASIC_INFORMATION.
DefaultLength
Указывает длину элемента DefaultData в байтах. Если defaultType имеет значение REG_SZ, REG_EXPAND_SZ или REG_MULTI_SZ, вызывающие стороны могут при необходимости указать ноль, чтобы указать, что значение RtlQueryRegistryValues должно вычислять длину на основе значения данных по умолчанию. Если DefaultType = REG_NONE, этот элемент игнорируется.
[in, optional] Context
Задает значение, передаваемое в качестве параметра 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 | Параметр Path не соответствует допустимому ключу или обработка таблицы запросов завершается записью с установленным флагом RTL_QUERY_REGISTRY_REQUIRED и соответствующий ключ не найден. Это происходит, если элемент Name имеет значение NULL , а текущий ключ не имеет подразделов или если name указывает несуществующий подраздел. |
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, код ошибки игнорируется.)
Комментарии
Вызывающий объект задает начальный путь к ключу и таблицу. Таблица содержит одну или несколько записей, описывающих значения ключей и имена подразделов, в которых заинтересован вызывающий объект. Таблица завершается записью с элементом QueryRoutineNULL и элементом NULLName. Таблица должна быть выделена из непагрегированного пула.
Драйверы в режиме ядра должны указывать флаг RTL_QUERY_REGISTRY_NOEXPAND, чтобы предотвратить вызов подпрограмм переменных среды. Эти подпрограммы являются небезопасными, поэтому драйверы в режиме ядра не должны их использовать.
Внимание!
Если вы используете флаг RTL_QUERY_REGISTRY_DIRECT, ненадежное приложение в пользовательском режиме может вызвать переполнение буфера. Переполнение буфера может произойти, если драйвер использует этот флаг для чтения значения реестра, которому присвоен неправильный тип. Во всех случаях драйвер, использующий флаг RTL_QUERY_REGISTRY_DIRECT, должен дополнительно использовать флаг RTL_QUERY_REGISTRY_TYPECHECK, чтобы предотвратить такие переполнения.
Если флаг RTL_QUERY_REGISTRY_TYPECHECK задан в записи таблицы, вызывающий объект должен указать ожидаемый тип REG_XXX в 8 наиболее значимых битах (MSB) 32-разрядного элемента DefaultType записи таблицы. Как показано в следующем примере кода, константу RTL_QUERY_REGISTRY_TYPECHECK_SHIFT, которая определена как 24, можно использовать в качестве количества сдвига, необходимого для размещения ожидаемого типа REG_XXX в 8 MSB элемента 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).
Только системные кусты являются доверенными. Вызов 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 Driver Kit (WDK) 8 флаг RTL_QUERY_REGISTRY_TYPECHECK определяется в файле заголовка Wdm.h следующим образом:
#define RTL_QUERY_REGISTRY_TYPECHECK 0x00000100
Если в записи не указан флаг RTL_QUERY_REGISTRY_DIRECT, RtlQueryRegistryValues использует указанную функцию QueryRoutine , чтобы сообщить вызывающей объекту имя, тип, данные и длину данных в байтах. Если элемент Name записи имеет значение NULL, RtlQueryRegistryValues сообщает о каждом прямом подразделе ключа. Если тип ключа — REG_MULTI_SZ и флаг RTL_QUERY_REGISTRY_NOEXPAND не указан, подпрограмма вызывает QueryRoutine отдельно для каждой отдельной строки; в противном случае подпрограмма сообщает об этом в виде одного значения. Если запись задает флаг RTL_QUERY_REGISTRY_DIRECT, RtlQueryRegistryValues сохраняет значение ключа в буфере, на который указывает элемент EntryContext записи. Формат возвращаемых данных выглядит следующим образом.
Тип данных key | Как возвращаются данные |
---|---|
Строка Юникода, заканчивающаяся null (например, REG_SZ, REG_EXPAND_SZ). | EntryContext должен указывать на инициализированную структуру UNICODE_STRING . Если элемент BufferUNICODE_STRING имеет значение NULL, подпрограмма выделяет хранилище для строковых данных. В противном случае строковые данные сохраняются в буфере, на который указывает Buffer . |
REG_MULTI_SZ | Для этого типа данных ключа необходимо указать флаг RTL_QUERY_REGISTRY_NOEXPAND. EntryContext указывает на инициализированную структуру UNICODE_STRING . Подпрограмма сохраняет значение ключа в виде одного строкового значения. Каждый отдельный компонент в строке завершается нулевым значением. Если элемент BufferUNICODE_STRING имеет значение NULL, подпрограмма выделяет хранилище для строковых данных. В противном случае строковые данные сохраняются в буфере, на который указывает Buffer . |
Нестрока данных с размером, в байтах, <= sizeof(ULONG) | Значение хранится в расположении памяти, заданном параметром EntryContext. |
Нестрока данных с размером, в байтах, >sizeof(ULONG) | Буфер, на который указывает EntryContext, должен начинаться со значения LONG со знаком. Величина значения должна указывать размер буфера в байтах. Если знак значения отрицательный, RtlQueryRegistryValues будет хранить только данные значения ключа. В противном случае он будет использовать первый ULONG в буфере для записи длины значения в байтах, второй ULONG для записи типа значения, а остальную часть буфера для хранения данных значения. |
Если ошибка возникает на любом этапе обработки таблицы запроса, RtlQueryRegistryValues прекращает обработку таблицы и возвращает состояние ошибки.
Описание возможных значений REG_XXX см. в разделе ZwSetValueKey.
Требования
Требование | Значение |
---|---|
Целевая платформа | Универсальное |
Верхняя часть | wdm.h (включая Wdm.h, Ntddk.h, Ntifs.h) |
Библиотека | Ntoskrnl.lib |
DLL | Ntoskrnl.exe |
IRQL | PASSIVE_LEVEL |
См. также раздел
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по