Compartilhar via


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 Caminho é um caminho absoluto do Registro ou se é relativo a um caminho predefinido como um dos seguintes.

Valor Significado
RTL_REGISTRY_ABSOLUTE O caminho é 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, isso é \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 ORing bit a bit com um dos sinalizadores a seguir.

Bandeira 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 de 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 em que 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 existente no Registro. A tabela deve ser encerrada com uma entrada de tabela NULL , que é uma entrada de tabela com um membro nulo QueryRoutine e um membro de nome deNULL . 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 depois que a chamada RtlQueryRegistryValues retornar.

QueryRoutine

O endereço de uma função QueryRoutine chamada com o nome, o tipo, os dados e o tamanho dos dados de um valor do Registro. Se esse membro e o membro Name estiverem 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.

Sinalizadores

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 este membro.

Valor Significado
RTL_QUERY_REGISTRY_SUBKEY O Name 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 caminho . Essa alteração no foco dura até o final da tabela ou até que outra RTL_REGISTRY_SUBKEY ou RTL_QUERY_REGISTRY_TOPKEY entrada seja vista. Cada entrada desse tipo deve especificar um caminho relativo ao Path 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 de status de STATUS_OBJECT_NAME_NOT_FOUND. Essa saída ocorre 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 umde nome deNULL não, a rotina usará o DefaultValue membro como o valor. Quando Name é 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 Name para esta entrada de tabela, tudo o que o chamador deseja é um retorno de chamada: ou seja, o chamador não deseja enumerar todos os valores na chave atual. queryRoutine é chamado com NULL para ValueData, REG_NONE paraValueType 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 as referências de variável de ambiente em valores REG_EXPAND_SZ e enumera cada cadeia de caracteres terminada em nulo em um valor REG_MULTI_SZ em uma chamada queryRoutine separada, de modo que as cadeias de caracteres sejam apresentadas como valores REG_SZ que tenham o mesmo ValueName . Se esse sinalizador estiver definido, QueryRoutine receberá o valor bruto de REG_EXPAND_SZ ou REG_MULTI_SZ do registro. Para obter mais informações sobre os formatos de dados para esses valores, consulte KEY_VALUE_BASIC_INFORMATION.
RTL_QUERY_REGISTRY_DIRECT O membro QueryRoutine não é usado (e deve ser NULL) e o EntryContext aponta para o buffer para armazenar o valor. Se o chamador definir esse sinalizador, o chamador 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 REG_XXX tipo do valor armazenado do Registro 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 que elas são 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 do 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 essa entrada de tabela será chamada para todos os valores associados à chave do Registro atual. Se o sinalizador de RTL_QUERY_REGISTRY_DIRECT estiver definido, um valor de NULL nãopara de nome deverá ser fornecido.

EntryContext

Se o sinalizador de RTL_QUERY_REGISTRY_DIRECT estiver definido, esse 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 de RTL_QUERY_REGISTRY_TYPECHECK for definido, o byte mais significativo desse membro especifica o tipo REG_XXX do valor armazenado do registro que o chamador espera. Os bits 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 apontado pelo DefaultData deve estar em conformidade com o tipo de valor do Registro especificado pelo membro DefaultType. Para obter mais informações sobre os tipos de valor do Registro, consulte a definição do parâmetro tipo no 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 RtlQueryRegistryValues deverá 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 cada vez que é chamado.

[in, optional] Environment

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

Valor de retorno

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

Código de retorno Descrição
STATUS_SUCCESS A tabela de consulta inteira foi processada com êxito.
STATUS_INVALID_PARAMETER O processamento da tabela de consulta foi encerrado com uma entrada de tabela inválida. Uma entrada de tabela poderá ser inválida se os sinalizadores especificados exigirem que o membro de ou Name não sejaNULL, mas um valor de 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 da chave.
STATUS_OBJECT_TYPE_MISMATCH O sinalizador RTL_QUERY_REGISTRY_TYPECHECK é definido e o tipo do valor armazenado do Registro 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.)

Observações

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 subchave em que o chamador está interessado. A tabela é encerrada por uma entrada com um membro deNULL e um membro de nome nuloNULL. A tabela deve ser alocada do pool nãopagado.

Os drivers no modo kernel devem especificar o sinalizador RTL_QUERY_REGISTRY_NOEXPAND para impedir a chamada de rotinas de variável 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 deve usar adicionalmente o sinalizador RTL_QUERY_REGISTRY_TYPECHECK para evitar tais estouros.

Se o sinalizador de RTL_QUERY_REGISTRY_TYPECHECK estiver definido em uma entrada de tabela, o chamador deverá especificar o tipo de XXX REG_esperado nos MSBs (bits mais significativos) de 32 bits DefaultType membro 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 turnos necessária para colocar o tipo de XXX REG_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;
...

A partir do Windows 8, se um RtlQueryRegistryValues chamada acessar um hive não confiável e o chamador definir o sinalizador de RTL_QUERY_REGISTRY_DIRECT para essa chamada, o chamador deverá definir adicionalmente 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 verificação de bug 0x139 (KERNEL_SECURITY_CHECK_FAILURE).

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

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

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 do 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 a elevação de privilégios (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 de rtlQueryRegistryValues .

Começando com o WDK 8 (Windows Driver Kit), 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, ao chamador. Se o Name membro 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, as chamadas de rotina QueryRoutine separadamente para cada cadeia de caracteres individual; caso contrário, a rotina o relatará 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 buffer de membro do UNICODE_STRING for NULL, a rotina alocará o 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 buffer de membro do UNICODE_STRING for NULL, a rotina alocará o 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, >tamanho de(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 status de erro.

Consulte ZwSetValueKey para obter uma descrição dos possíveis valores de XXX REG_.

Requisitos

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

Consulte também

de QueryRoutine

rtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey