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 값은 다음 플래그 중 하나로 비트 ORing하여 수정할 수 있습니다.

플래그 의미
RTL_REGISTRY_OPTIONAL 이 매개 변수와 Path 매개 변수에서 참조하는 키가 선택 사항임을 지정합니다.
RTL_REGISTRY_HANDLE Path 매개 변수가 실제로 사용할 레지스트리 핸들임을 지정합니다.

[in] Path

RelativeTo 매개 변수로 지정된 알려진 위치에 상대적인 절대 레지스트리 경로 또는 경로에 대한 포인터입니다. 이러한 경로의 키 이름은 경로의 마지막 키를 포함하여 호출자에게 알려야 합니다. RTL_REGISTRY_HANDLE 플래그가 지정된 경우 이 매개 변수는 이미 열려 있는 키를 직접 쿼리할 레지스트리 핸들입니다.

[in, out] QueryTable

호출자가 관심이 있는 하나 이상의 값 이름 및 하위 키 이름의 테이블에 대한 포인터입니다. 각 테이블 항목에는 레지스트리에 있는 각 값 이름에 대해 호출되는 호출자 제공 QueryRoutine 함수의 주소가 포함됩니다. 테이블은 NULLQueryRoutine 멤버와 NULL이름 멤버가 있는 테이블 항목인 NULL 테이블 항목으로 종료해야 합니다. 쿼리 테이블 항목의 구조는 다음과 같이 정의됩니다.

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 현재 레지스트리 키 핸들을 RelativeToPath 매개 변수에 지정된 원래 키 핸들로 다시 설정합니다. 이는 RTL_QUERY_REGISTRY_SUBKEY 플래그를 사용하여 하위 키로 내림차순으로 내림차순으로 원래 노드로 다시 가져오는 데 유용합니다.
RTL_QUERY_REGISTRY_REQUIRED DefaultType = REG_NONE 경우 이 레지스트리 값이 있어야 하며, 그렇지 않으면 RtlQueryRegistryValues가 STATUS_OBJECT_NAME_NOT_FOUND 상태 코드로 즉시 종료됩니다. 이 종료는 Name 멤버가 NULL 이고 현재 키에 하위 키가 없거나 Name 이 존재하지 않는 하위 키를 지정하는 경우에 발생합니다. (이 플래그를 지정하지 않으면 NULL이 아닌 이름에 대한 일치 항목이 없으면 루틴은 DefaultValue 멤버를 값으로 사용합니다. NameNULL이고 현재 키에 하위 키가 없는 경우 루틴은 해당 테이블 항목을 건너뜁니다.)
RTL_QUERY_REGISTRY_NOVALUE 이 테이블 항목에 대한 Name 이 없더라도 호출자가 원하는 모든 콜백이 되도록 지정합니다. 즉, 호출자는 현재 키 아래의 모든 값을 열거하지 않습니다. QueryRoutineValueData경우 NULL, ValueType의 경우 REG_NONE, ValueLength에는 0을 사용하여 호출됩니다.
RTL_QUERY_REGISTRY_NOEXPAND REG_EXPAND_SZ 또는 REG_MULTI_SZ 형식의 레지스트리 값에 대해 이 플래그는 QueryRoutine 루틴을 호출하기 전에 레지스트리 값을 전처리하는 기본 동작을 재정의합니다. 기본적으로 RtlQueryRegistryValues 는 환경 변수 참조를 REG_EXPAND_SZ 값으로 확장하고, 별도의 QueryRoutine 호출에서 REG_MULTI_SZ 값으로 null로 끝나는 각 문자열을 열거하여 문자열이 동일한 ValueName을 갖는 REG_SZ 값으로 표시됩니다. 이 플래그가 설정되면 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 제외하고 이전 표의 모든 플래그 비트에 대해 받은 편지함 지원이 제공됩니다. Windows 8 시작하여 RTL_QUERY_REGISTRY_TYPECHECK 대한 받은 편지함 지원을 사용할 수 있습니다. 이전 버전의 Windows의 경우 Windows 업데이트 통해 RTL_QUERY_REGISTRY_TYPECHECK 대한 지원이 제공됩니다. 자세한 내용은 설명 부분을 참조하세요.

Name

호출자가 쿼리한 값의 이름입니다. NameNULL이면 현재 레지스트리 키와 연결된 모든 값에 대해 이 테이블 항목에 대해 지정된 QueryRoutine 함수가 호출됩니다. RTL_QUERY_REGISTRY_DIRECT 플래그가 설정된 경우 NameNULL이 아닌 값을 제공해야 합니다.

EntryContext

RTL_QUERY_REGISTRY_DIRECT 플래그가 설정된 경우 이 키에 대한 쿼리 작업의 결과를 저장하는 버퍼에 대한 포인터입니다. 그렇지 않으면 이 값이 QueryRoutineEntryContext 매개 변수로 전달됩니다.

DefaultType

일치하는 키가 없고 RTL_QUERY_REGISTRY_REQUIRED 플래그가 지정되지 않은 경우 이 멤버의 가장 중요한 바이트는 반환할 데이터의 REG_XXX 형식을 지정합니다. 기본 형식이 없는 REG_NONE 지정합니다. RTL_QUERY_REGISTRY_TYPECHECK 플래그가 설정된 경우 이 멤버의 가장 중요한 바이트는 호출자가 예상하는 저장된 레지스트리 값의 REG_XXX 형식을 지정합니다. 이 멤버의 비트 8~23은 예약되어 있으며 0이어야 합니다.

DefaultData

일치하는 키가 없고 RTL_QUERY_REGISTRY_REQUIRED 플래그가 지정되지 않은 경우 반환할 기본값에 대한 포인터입니다. DefaultType = REG_NONE 경우 이 멤버는 무시됩니다. 그렇지 않으면 DefaultData 가 가리키는 데이터 형식이 DefaultType 멤버에 의해 지정된 레지스트리 값 형식을 준수해야 합니다. 레지스트리 값 형식에 대한 자세한 내용은 KEY_VALUE_BASIC_INFORMATIONType 매개 변수 정의를 참조하세요.

DefaultLength

DefaultData 멤버의 길이(바이트)를 지정합니다. DefaultType이 REG_SZ, REG_EXPAND_SZ 또는 REG_MULTI_SZ 경우 호출자는 선택적으로 0을 지정하여 RtlQueryRegistryValues가 기본 데이터 값에 따라 길이를 계산해야 함을 나타낼 수 있습니다. DefaultType = REG_NONE 이 멤버는 무시됩니다.

[in, optional] Context

호출될 때마다 QueryRoutine 함수의 Context 매개 변수로 전달되는 값을 지정합니다.

[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 반환하면 오류 코드가 무시됩니다.

설명

호출자는 초기 키 경로와 테이블을 지정합니다. 테이블에는 호출자가 관심이 있는 키 값 및 하위 키 이름을 설명하는 하나 이상의 항목이 포함되어 있습니다. 테이블은 NULLQueryRoutine 멤버 및 NULL이름 멤버가 있는 항목에 의해 종료됩니다. 테이블은 페이지가 지정되지 않은 풀에서 할당되어야 합니다.

커널 모드 드라이버는 환경 변수 루틴을 호출하지 않도록 RTL_QUERY_REGISTRY_NOEXPAND 플래그를 지정해야 합니다. 이러한 루틴은 안전하지 않으므로 커널 모드 드라이버는 사용하지 않아야 합니다.

주의

RTL_QUERY_REGISTRY_DIRECT 플래그를 사용하는 경우 신뢰할 수 없는 사용자 모드 애플리케이션이 버퍼 오버플로를 일으킬 수 있습니다. 드라이버가 이 플래그를 사용하여 잘못된 형식이 할당된 레지스트리 값을 읽는 경우 버퍼 오버플로가 발생할 수 있습니다. 모든 경우에 RTL_QUERY_REGISTRY_DIRECT 플래그를 사용하는 드라이버는 RTL_QUERY_REGISTRY_TYPECHECK 플래그를 추가로 사용하여 이러한 오버플로를 방지해야 합니다.

RTL_QUERY_REGISTRY_TYPECHECK 플래그가 테이블 항목에 설정된 경우 호출자는 테이블 항목의 32비트 DefaultType 멤버 중 8개의 가장 중요한 비트(MSB)에서 예상되는 REG_XXX 형식을 지정해야 합니다. 다음 코드 예제와 같이 24로 정의된 RTL_QUERY_REGISTRY_TYPECHECK_SHIFT 상수를 DefaultType 멤버의 8MB에 예상 REG_XXX 형식을 배치하는 데 필요한 시프트 수로 사용할 수 있습니다.

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_DIRECT 플래그가 설정된 경우 항상 RTL_QUERY_REGISTRY_TYPECHECK 플래그를 설정해야 합니다.

마찬가지로 Windows 8 이전 Windows 버전에서는 RTL_QUERY_REGISTRY_DIRECT 플래그를 설정하는 RtlQueryRegistryValues 호출이 RTL_QUERY_REGISTRY_TYPECHECK 플래그를 추가로 설정해야 합니다. 그러나 이 권장 사항을 따르지 않으면 예외 또는 버그 검사 발생하지 않습니다.

다음은 시스템 하이브 목록입니다.

  • \REGISTRY\MACHINE\HARDWARE

  • \REGISTRY\MACHINE\SOFTWARE

  • \REGISTRY\MACHINE\SYSTEM

  • \REGISTRY\MACHINE\SECURITY

  • \REGISTRY\MACHINE\SAM

RTL_QUERY_REGISTRY_TYPECHECK 플래그에 대한 지원은 Windows 7, Windows Vista, Windows Server 2003 및 Windows XP용 Windows 업데이트 통해 사용할 수 있습니다. 이 업데이트에 대한 자세한 내용은 Windows 커널의 취약성으로 인해 권한 상승(2393802)을 참조하세요. 이 업데이트가 없는 이러한 운영 체제 버전에서 호출자는 RTL_QUERY_REGISTRY_TYPECHECK 플래그를 사용할 수 있습니다. 그러나 이 플래그는 RtlQueryRegistryValues 루틴에서 무시됩니다.

WDK(Windows 드라이버 키트) 8부터 RTL_QUERY_REGISTRY_TYPECHECK 플래그는 다음과 같이 Wdm.h 헤더 파일에 정의됩니다.

#define RTL_QUERY_REGISTRY_TYPECHECK 0x00000100

항목이 RTL_QUERY_REGISTRY_DIRECT 플래그를 지정하지 않으면 RtlQueryRegistryValues 는 지정된 QueryRoutine 함수를 사용하여 값 이름, 형식, 데이터 및 데이터 길이(바이트)를 호출자에게 보고합니다. 항목의 이름 멤버가 NULL이면 RtlQueryRegistryValues 는 키의 모든 직접 하위 키를 보고합니다. 키 형식이 REG_MULTI_SZ RTL_QUERY_REGISTRY_NOEXPAND 플래그가 지정되지 않은 경우 루틴은 각 개별 문자열에 대해 QueryRoutine 을 별도로 호출합니다. 그렇지 않으면 루틴이 단일 값으로 보고합니다. 항목이 RTL_QUERY_REGISTRY_DIRECT 플래그를 지정하는 경우 RtlQueryRegistryValues 는 항목의 EntryContext 멤버가 가리키는 버퍼에 키 값을 저장합니다. 반환된 데이터의 형식은 다음과 같습니다.

키 데이터 형식 데이터가 반환되는 방법
null로 끝나는 유니코드 문자열(예: REG_SZ, REG_EXPAND_SZ)입니다. EntryContext는 초기화된 UNICODE_STRING 구조를 가리킵니다. UNICODE_STRINGBuffer 멤버가 NULL인 경우 루틴은 문자열 데이터에 대한 스토리지를 할당합니다. 그렇지 않으면 버퍼 가 가리키는 버퍼에 문자열 데이터를 저장합니다.
REG_MULTI_SZ 이 키 데이터 형식에 대한 RTL_QUERY_REGISTRY_NOEXPAND 플래그를 지정해야 합니다. EntryContext는 초기화된 UNICODE_STRING 구조를 가리킵니다. 루틴은 키 값을 단일 문자열 값으로 저장합니다. 문자열 내의 각 개별 구성 요소는 0으로 종료됩니다. UNICODE_STRINGBuffer 멤버가 NULL인 경우 루틴은 문자열 데이터에 대한 스토리지를 할당합니다. 그렇지 않으면 버퍼 가 가리키는 버퍼에 문자열 데이터를 저장합니다.
크기(바이트 <) = 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

추가 정보

QueryRoutine

RtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey