Função RtlQueryRegistryValues (wdm.h)

A rotina RtlQueryRegistryValues permite que o chamador consulte vários valores da subárvore do Registro com uma única chamada.

Sintaxe

NTSYSAPI NTSTATUS RtlQueryRegistryValues(
  [in]           ULONG                     RelativeTo,
  [in]           PCWSTR                    Path,
  [in, out]      PRTL_QUERY_REGISTRY_TABLE QueryTable,
  [in, optional] PVOID                     Context,
  [in, optional] PVOID                     Environment
);

Parâmetros

[in] RelativeTo

Especifica se Path é um caminho absoluto do Registro ou se é relativo a um caminho predefinido como um dos seguintes.

Valor Significado
RTL_REGISTRY_ABSOLUTE Path é um caminho absoluto do Registro.
RTL_REGISTRY_CONTROL O caminho é relativo a \Registry\Machine\System\CurrentControlSet\Control.
RTL_REGISTRY_DEVICEMAP O caminho é relativo a \Registry\Machine\Hardware\DeviceMap.
RTL_REGISTRY_SERVICES O caminho é relativo a \Registry\Machine\System\CurrentControlSet\Services.
RTL_REGISTRY_USER O caminho é relativo a \Registry\User\CurrentUser. (Para um processo do sistema, este é \User\. Padrão.)
RTL_REGISTRY_WINDOWS_NT O caminho é relativo a \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion.

O valor RelativeTo pode ser modificado por bit a bit-ORing com um dos sinalizadores a seguir.

Sinalizador Significado
RTL_REGISTRY_OPTIONAL Especifica que a chave referenciada por esse parâmetro e o parâmetro Path são opcionais.
RTL_REGISTRY_HANDLE Especifica que o parâmetro Path é, na verdade, um identificador do Registro a ser usado.

[in] Path

Ponteiro para um caminho absoluto do Registro ou um caminho relativo ao local conhecido especificado pelo parâmetro RelativeTo . Observe que os nomes das chaves nesse caminho devem ser conhecidos pelo chamador, incluindo a última chave no caminho. Se o sinalizador RTL_REGISTRY_HANDLE for especificado, esse parâmetro será um identificador do Registro para que uma chave já aberta seja consultada diretamente.

[in, out] QueryTable

Ponteiro para uma tabela de um ou mais nomes de valor e nomes de subchave nos quais o chamador está interessado. Cada entrada de tabela contém o endereço de uma função QueryRoutine fornecida pelo chamador que será chamada para cada nome de valor que existe no Registro. A tabela deve ser encerrada com uma entrada de tabela NULL, que é uma entrada de tabela com um membro NULLQueryRoutine e um membro nomeNULL. A estrutura para entradas de tabela de consulta é definida da seguinte maneira:

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;

Se o chamador alocar armazenamento para a tabela de consulta apontada pelo parâmetro QueryTable , o chamador será responsável por liberar esse armazenamento após o retorno da chamada RtlQueryRegistryValues .

QueryRoutine

O endereço de uma função QueryRoutine que é chamada com o nome, o tipo, os dados e o comprimento dos dados de um valor do Registro. Se esse membro e o membro Name forem NULL, ele marcará o final da tabela.

Uma função QueryRoutine é declarada da seguinte maneira:

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

Para obter mais informações, consulte QueryRoutine.

Flags

Sinalizadores para controlar como os membros restantes da estrutura RTL_QUERY_REGISTRY_TABLE devem ser interpretados. Os bits de sinalizador a seguir são definidos para esse membro.

Valor Significado
RTL_QUERY_REGISTRY_SUBKEY O Nome dessa entrada de tabela é outro caminho para uma chave do Registro e todas as entradas de tabela a seguir são para essa chave em vez da chave especificada pelo parâmetro Path . Essa alteração no foco dura até o final da tabela ou até que outra entrada RTL_REGISTRY_SUBKEY ou RTL_QUERY_REGISTRY_TOPKEY seja vista. Cada entrada deve especificar um caminho relativo ao Caminho especificado na chamada para RtlQueryRegistryValues.
RTL_QUERY_REGISTRY_TOPKEY Redefine o identificador de chave do Registro atual para o original especificado pelos parâmetros RelativeTo e Path . Isso é útil para voltar ao nó original depois de descer em subchaves com o sinalizador RTL_QUERY_REGISTRY_SUBKEY.
RTL_QUERY_REGISTRY_REQUIRED Especifica que esse valor do Registro deve existir se DefaultType = REG_NONE; caso contrário, se não for encontrado, RtlQueryRegistryValues sairá imediatamente com um código status de STATUS_OBJECT_NAME_NOT_FOUND. Essa saída ocorrerá se o membro Name for NULL e a chave atual não tiver subchaves ou se Name especificar uma subchave inexistente. (Se esse sinalizador não for especificado, quando nenhuma correspondência for encontrada para um Nome não NULL, a rotina usará o membro DefaultValue como o valor. Quando Nome é NULL e a chave atual não tem subchaves, a rotina simplesmente ignora essa entrada de tabela.)
RTL_QUERY_REGISTRY_NOVALUE Especifica que, embora não haja Nenhum Nome para essa entrada de tabela, tudo o que o chamador deseja é um retorno de chamada: ou seja, o chamador não deseja enumerar todos os valores sob a chave atual. QueryRoutine é chamado com NULL para ValueData, REG_NONE para ValueType e zero para ValueLength.
RTL_QUERY_REGISTRY_NOEXPAND Para um valor de registro do tipo REG_EXPAND_SZ ou REG_MULTI_SZ, esse sinalizador substitui o comportamento padrão, que é pré-processar o valor do Registro antes de chamar a rotina QueryRoutine . Por padrão, RtlQueryRegistryValues expande referências de variável de ambiente em valores REG_EXPAND_SZ e enumera cada cadeia de caracteres terminada em nulo em um valor de REG_MULTI_SZ em uma chamada QueryRoutine separada, para que as cadeias de caracteres sejam apresentadas como valores REG_SZ que tenham o mesmo ValueName. Se esse sinalizador for definido, QueryRoutine receberá o valor bruto REG_EXPAND_SZ ou REG_MULTI_SZ do registro. Para obter mais informações sobre os formatos de dados desses valores, consulte KEY_VALUE_BASIC_INFORMATION.
RTL_QUERY_REGISTRY_DIRECT O membro QueryRoutine não é usado (e deve ser NULL) e EntryContext aponta para o buffer para armazenar o valor. Se o chamador definir esse sinalizador, o chamador também deverá definir o sinalizador RTL_QUERY_REGISTRY_TYPECHECK para proteger contra o estouro do buffer. Para obter mais informações, consulte a seção Comentários.
RTL_QUERY_REGISTRY_TYPECHECK Use esse sinalizador com o sinalizador RTL_QUERY_REGISTRY_DIRECT para verificar se o tipo REG_XXX do valor do registro armazenado corresponde ao tipo esperado pelo chamador. Se os tipos não corresponderem, a chamada falhará. Para obter mais informações, consulte a seção Comentários.
RTL_QUERY_REGISTRY_DELETE Esse sinalizador é usado para excluir chaves de valor depois de serem consultadas.

A partir do Windows 2000, o suporte à caixa de entrada é fornecido para todos os bits de sinalizador na tabela anterior, com exceção de RTL_QUERY_REGISTRY_TYPECHECK. O suporte à caixa de entrada para RTL_QUERY_REGISTRY_TYPECHECK está disponível a partir do Windows 8. Para versões anteriores do Windows, o suporte para RTL_QUERY_REGISTRY_TYPECHECK é fornecido por meio de Windows Update. Para obter mais informações, consulte Comentários.

Nome

Esse é o nome de um Valor que o chamador consultou. Se Name for NULL, a função QueryRoutine especificada para esta entrada de tabela será chamada para todos os valores associados à chave do Registro atual. Se o sinalizador RTL_QUERY_REGISTRY_DIRECT estiver definido, um valor não NULL para Name deverá ser fornecido.

EntryContext

Se o sinalizador RTL_QUERY_REGISTRY_DIRECT estiver definido, este será um ponteiro para o buffer para armazenar o resultado da operação de consulta para essa chave. Caso contrário, esse valor será passado como o parâmetro EntryContext de QueryRoutine.

DefaultType

O byte menos significativo desse membro especifica o tipo REG_XXX dos dados a serem retornados, se nenhuma chave correspondente for encontrada e o sinalizador RTL_QUERY_REGISTRY_REQUIRED não for especificado. Especifique REG_NONE para nenhum tipo padrão. Se o sinalizador RTL_QUERY_REGISTRY_TYPECHECK estiver definido, o byte mais significativo desse membro especificará o tipo REG_XXX do valor do registro armazenado esperado pelo chamador. Os bits de 8 a 23 deste membro são reservados e devem ser zero.

DefaultData

Um ponteiro para o valor padrão a ser retornado se nenhuma chave correspondente for encontrada e o sinalizador RTL_QUERY_REGISTRY_REQUIRED não for especificado. Esse membro será ignorado se DefaultType = REG_NONE. Caso contrário, o tipo de dados apontados por DefaultData deverá estar em conformidade com o tipo de valor do Registro especificado pelo membro DefaultType . Para obter mais informações sobre tipos de valor do Registro, consulte a definição do parâmetro Type em KEY_VALUE_BASIC_INFORMATION.

DefaultLength

Especifica o comprimento, em bytes, do membro DefaultData . Se DefaultType for REG_SZ, REG_EXPAND_SZ ou REG_MULTI_SZ, os chamadores poderão, opcionalmente, especificar zero para indicar que RtlQueryRegistryValues deve calcular o comprimento com base no valor de dados padrão. Se DefaultType = REG_NONE, esse membro será ignorado.

[in, optional] Context

Especifica o valor passado como o parâmetro Context de uma função QueryRoutine sempre que ela é chamada.

[in, optional] Environment

Ponteiro para o ambiente usado ao expandir valores variáveis em REG_EXPAND_SZ valores do Registro ou um ponteiro NULL (opcional).

Retornar valor

RtlQueryRegistryValues retorna um código NTSTATUS. Os possíveis valores retornados incluem:

Código de retorno Descrição
STATUS_SUCCESS Toda a tabela de consulta foi processada com êxito.
STATUS_INVALID_PARAMETER O processamento da tabela de consulta terminou com uma entrada de tabela inválida. Uma entrada de tabela poderá ser inválida se os sinalizadores especificados exigirem que o membro QueryRoutine ou Name seja não NULL, mas um valor NULL foi fornecido.
STATUS_OBJECT_NAME_NOT_FOUND O parâmetro Path não corresponde a uma chave válida ou ao processamento da tabela de consulta encerrada com uma entrada com o sinalizador RTL_QUERY_REGISTRY_REQUIRED definido e nenhuma chave correspondente é encontrada. Isso ocorrerá se o membro Name for NULL e a chave atual não tiver subchaves ou se Name especificar uma subchave inexistente.
STATUS_BUFFER_TOO_SMALL O sinalizador RTL_QUERY_REGISTRY_DIRECT é definido e o buffer especificado por EntryContext é muito pequeno para conter os dados de valor de chave.
STATUS_OBJECT_TYPE_MISMATCH O sinalizador RTL_QUERY_REGISTRY_TYPECHECK é definido e o tipo do valor do Registro armazenado não corresponde ao tipo esperado pelo chamador.

RtlQueryRegistryValues também encerrará o processamento da tabela se a função QueryRoutine para uma entrada de tabela retornar um código de erro NTSTATUS e retornar esse código de erro como resultado. (Com uma exceção: se QueryRoutine retornar STATUS_BUFFER_TOO_SMALL, o código de erro será ignorado.)

Comentários

O chamador especifica um caminho de chave inicial e uma tabela. A tabela contém uma ou mais entradas que descrevem os valores de chave e os nomes de subchaves nos quais o chamador está interessado. A tabela é encerrada por uma entrada com um membro NuLLQueryRoutine e um membro nullname . A tabela deve ser alocada do pool nãopagado.

Os drivers no modo kernel devem especificar o sinalizador RTL_QUERY_REGISTRY_NOEXPAND para evitar a chamada de rotinas de variáveis de ambiente. Essas rotinas não são seguras, portanto, os drivers no modo kernel não devem usá-las.

Cuidado

Se você usar o sinalizador RTL_QUERY_REGISTRY_DIRECT, um aplicativo de modo de usuário não confiável poderá causar um estouro de buffer. Um estouro de buffer poderá ocorrer se um driver usar esse sinalizador para ler um valor do Registro ao qual o tipo errado é atribuído. Em todos os casos, um driver que usa o sinalizador RTL_QUERY_REGISTRY_DIRECT também deve usar o sinalizador RTL_QUERY_REGISTRY_TYPECHECK para evitar esses estouros.

Se o sinalizador RTL_QUERY_REGISTRY_TYPECHECK for definido em uma entrada de tabela, o chamador deverá especificar o tipo REG_XXX esperado nos 8 bits mais significativos (MSBs) do membro DefaultType de 32 bits da entrada da tabela. Conforme mostrado no exemplo de código a seguir, a constante RTL_QUERY_REGISTRY_TYPECHECK_SHIFT, que é definida como 24, pode ser usada como a contagem de deslocamentos necessária para colocar o tipo REG_XXX esperado nos 8 MSBs do membro 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;
...

Começando com Windows 8, se uma chamada RtlQueryRegistryValues acessar um hive não confiável e o chamador definir o sinalizador RTL_QUERY_REGISTRY_DIRECT para essa chamada, o chamador deverá definir o sinalizador RTL_QUERY_REGISTRY_TYPECHECK. Uma violação dessa regra por uma chamada do modo de usuário causa uma exceção. Uma violação dessa regra por uma chamada do modo kernel causa uma marcar de bugs 0x139 (KERNEL_SECURITY_CHECK_FAILURE).

Somente hives do sistema são confiáveis. Uma chamada RtlQueryRegistryValues que acessa um hive do sistema não causará uma exceção ou um bug marcar se o sinalizador RTL_QUERY_REGISTRY_DIRECT estiver definido e o sinalizador RTL_QUERY_REGISTRY_TYPECHECK não estiver definido. No entanto, como prática recomendada, o sinalizador RTL_QUERY_REGISTRY_TYPECHECK sempre deverá ser definido se o sinalizador RTL_QUERY_REGISTRY_DIRECT estiver definido.

Da mesma forma, em versões do Windows antes de Windows 8, como prática recomendada, uma chamada RtlQueryRegistryValues que define o sinalizador RTL_QUERY_REGISTRY_DIRECT também deve definir o sinalizador RTL_QUERY_REGISTRY_TYPECHECK. No entanto, a falha ao seguir essa recomendação não causa uma exceção ou um bug marcar.

Veja a seguir uma lista de hives do sistema:

  • \REGISTRY\MACHINE\HARDWARE

  • \REGISTRY\MACHINE\SOFTWARE

  • \REGISTRY\MACHINE\SYSTEM

  • \REGISTRY\MACHINE\SECURITY

  • \REGISTRY\MACHINE\SAM

O suporte para o sinalizador RTL_QUERY_REGISTRY_TYPECHECK está disponível por meio de Windows Update para Windows 7, Windows Vista, Windows Server 2003 e Windows XP. Para obter mais informações sobre essa atualização, consulte Vulnerabilidades no Kernel do Windows podem permitir elevação de privilégio (2393802). Em versões desses sistemas operacionais que não têm essa atualização, o chamador pode usar o sinalizador RTL_QUERY_REGISTRY_TYPECHECK. No entanto, esse sinalizador é ignorado pela rotina RtlQueryRegistryValues .

A partir do WDK (Kit de Driver do Windows) 8, o sinalizador RTL_QUERY_REGISTRY_TYPECHECK é definido no arquivo de cabeçalho Wdm.h da seguinte maneira:

#define RTL_QUERY_REGISTRY_TYPECHECK 0x00000100

Se uma entrada não especificar o sinalizador RTL_QUERY_REGISTRY_DIRECT, RtlQueryRegistryValues usará a função QueryRoutine especificada para relatar o nome do valor, o tipo, os dados e o comprimento dos dados, em bytes, para o chamador. Se o membro Name da entrada for NULL, RtlQueryRegistryValues relatará cada subchave direta da chave. Se o tipo de chave for REG_MULTI_SZ e o sinalizador RTL_QUERY_REGISTRY_NOEXPAND não for especificado, a rotina chamará QueryRoutine separadamente para cada cadeia de caracteres individual; caso contrário, a rotina o relata como um único valor. Se uma entrada especificar o sinalizador RTL_QUERY_REGISTRY_DIRECT, RtlQueryRegistryValues armazenará o valor da chave no buffer apontado pelo membro EntryContext da entrada. O formato dos dados retornados é o seguinte.

Tipo de dados de chave Como os dados são retornados
Uma cadeia de caracteres Unicode terminada em nulo (como REG_SZ, REG_EXPAND_SZ). EntryContext deve apontar para uma estrutura de UNICODE_STRING inicializada. Se o membro buffer do UNICODE_STRING for NULL, a rotina alocará armazenamento para os dados da cadeia de caracteres. Caso contrário, ele armazenará os dados de cadeia de caracteres no buffer para o qual o Buffer aponta.
REG_MULTI_SZ Você deve especificar o sinalizador RTL_QUERY_REGISTRY_NOEXPAND para esse tipo de dados de chave. EntryContext aponta para uma estrutura de UNICODE_STRING inicializada. A rotina armazena o valor da chave como um único valor de cadeia de caracteres. Cada componente individual dentro da cadeia de caracteres é encerrado por zero. Se o membro buffer do UNICODE_STRING for NULL, a rotina alocará armazenamento para os dados da cadeia de caracteres. Caso contrário, ele armazenará os dados de cadeia de caracteres no buffer para o qual o Buffer aponta.
Dados nãostring com tamanho, em bytes, <= sizeof(ULONG) O valor é armazenado no local de memória especificado por EntryContext.
Dados nãostring com tamanho, em bytes, >sizeof(ULONG) O buffer apontado por EntryContext deve começar com um valor LONG assinado. A magnitude do valor deve especificar o tamanho, em bytes, do buffer. Se o sinal do valor for negativo, RtlQueryRegistryValues armazenará apenas os dados do valor da chave. Caso contrário, ele usará o primeiro ULONG no buffer para registrar o comprimento do valor, em bytes, o segundo ULONG para registrar o tipo de valor e o restante do buffer para armazenar os dados de valor.

Se ocorrer um erro em qualquer estágio de processamento da tabela de consulta, RtlQueryRegistryValues interromperá o processamento da tabela e retornará o erro status.

Consulte ZwSetValueKey para obter uma descrição dos possíveis valores REG_XXX .

Requisitos

Requisito Valor
Plataforma de Destino Universal
Cabeçalho wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Biblioteca Ntoskrnl.lib
DLL Ntoskrnl.exe
IRQL PASSIVE_LEVEL

Confira também

QueryRoutine

RtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey