RtlQueryRegistryValues 関数 (wdm.h)

RtlQueryRegistryValues ルーチンを使用すると、呼び出し元は 1 回の呼び出しでレジストリ サブツリーから複数の値を照会できます。

構文

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

呼び出し元が関心を持つ 1 つ以上の値名とサブキー名のテーブルへのポインター。 各テーブル エントリには、レジストリに存在する値名ごとに呼び出される、呼び出し元が指定した QueryRoutine 関数のアドレスが含まれています。 テーブルは、NULLQueryRoutine メンバーと NULLName メンバーを持つテーブル エントリである 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」を参照してください。

Flags

RTL_QUERY_REGISTRY_TABLE構造体の残りのメンバーの解釈方法を制御するフラグ。 このメンバーには、次のフラグ ビットが定義されています。

意味
RTL_QUERY_REGISTRY_SUBKEY このテーブル エントリの 名前 はレジストリ キーへの別のパスであり、次のすべてのテーブル エントリは Path パラメーターで指定されたキーではなく、そのキー用です。 このフォーカスの変更は、テーブルの最後まで、または別のRTL_REGISTRY_SUBKEYまたはRTL_QUERY_REGISTRY_TOPKEYエントリが表示されるまで続きます。 このような各エントリでは、RtlQueryRegistryValues の呼び出しで指定された Path に対する相対パスを指定する必要があります。
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 メンバーを値として使用します。 NameNULL で、現在のキーにサブキーがない場合、ルーチンはそのテーブル エントリをスキップするだけです)。
RTL_QUERY_REGISTRY_NOVALUE このテーブル エントリに Name がない場合でも、呼び出し元が必要とするのはコールバックです。つまり、呼び出し元が現在のキーのすべての値を列挙したくないことを指定します。 QueryRoutine は、ValueData場合は NULLValueType の場合は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 の場合、RTL_QUERY_REGISTRY_TYPECHECKのサポートは Windows Update を通じて提供されます。 詳細については、「解説」を参照してください。

名前

これは、呼び出し元が照会した値の名前です。 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_INFORMATIONの Type パラメーターの定義に関するページ 参照してください。

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 エラー コードを返し、そのエラー コードを結果として返す場合にも、テーブルの処理を終了します。 (1 つの例外を除き、 QueryRoutine がSTATUS_BUFFER_TOO_SMALLを返す場合、エラー コードは無視されます)。

注釈

呼び出し元は、初期キー パスとテーブルを指定します。 テーブルには、呼び出し元が関心を持つキー値とサブキー名を記述する 1 つ以上のエントリが含まれています。 テーブルは、 NULLQueryRoutine メンバーと NULLName メンバーを持つエントリによって終了します。 テーブルは、非ページ プールから割り当てる必要があります。

カーネル モード ドライバーでは、環境変数ルーチンの呼び出しを防ぐために、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 メンバーの 8 MSB に予期される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 Updateを通じて利用できます。 この更新プログラムの詳細については、「 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 メンバーが指すバッファーにキーの値を格納します。 返されるデータの形式は次のとおりです。

キー データ型 データの返し方
null で終わる Unicode 文字列 (REG_SZ、REG_EXPAND_SZ など)。 EntryContext は 、初期化された UNICODE_STRING 構造体を指している必要があります。 UNICODE_STRINGBuffer メンバーが NULL の場合、ルーチンは文字列データにストレージを割り当てます。 それ以外の場合は、 Buffer が指すバッファーに文字列データが格納されます。
REG_MULTI_SZ このキー データ型には、RTL_QUERY_REGISTRY_NOEXPAND フラグを指定する必要があります。 EntryContext は 、初期化された UNICODE_STRING 構造体を指します。 ルーチンは、キー値を 1 つの文字列値として格納します。 文字列内の個々のコンポーネントは、0 で終了します。 UNICODE_STRINGBuffer メンバーが NULL の場合、ルーチンは文字列データにストレージを割り当てます。 それ以外の場合は、 Buffer が指すバッファーに文字列データが格納されます。
size を持つ非文字列データ (バイト単位) <= sizeof(ULONG) この値は、 EntryContext で指定されたメモリ位置に格納されます。
size を持つ非文字列データ (バイト単位)、 >sizeof(ULONG) EntryContext が指すバッファーは、符号付き LONG 値で始まる必要があります。 値の大きさは、バッファーのサイズ (バイト単位) を指定する必要があります。 値の符号が負の場合、 RtlQueryRegistryValues はキー値のデータのみを格納します。 それ以外の場合は、バッファー内の最初の ULONG を使用して値の長さをバイト単位で記録し、2 番目の ULONG を使用して値の型を記録し、残りのバッファーで値データを格納します。

クエリ テーブルの処理のいずれかの段階でエラーが発生した場合、 RtlQueryRegistryValues は テーブルの処理を停止し、エラー状態を返します。

使用可能なREG_XXX 値の説明については、「ZwSetValueKey」を参照してください。

要件

要件
対象プラットフォーム ユニバーサル
Header wdm.h (Wdm.h、Ntddk.h、Ntifs.h を含む)
Library Ntoskrnl.lib
[DLL] Ntoskrnl.exe
IRQL PASSIVE_LEVEL

こちらもご覧ください

QueryRoutine

RtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey