(wdm.h) RtlQueryRegistryValues 函式

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 Path 是絕對登錄路徑。
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\。Default.)
RTL_REGISTRY_WINDOWS_NT 路徑相對於 \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion

Bitwise-ORing 可以使用下列其中一個旗標來修改 RelativeTo 值。

旗標 意義
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

Flags

用來控制如何解譯 RTL_QUERY_REGISTRY_TABLE 結構的其餘成員的旗標。 這個成員定義了下列旗標位。

意義
RTL_QUERY_REGISTRY_SUBKEY 此數據表專案 的名稱 是登錄機碼的另一個路徑,而下列所有數據表專案都是針對該機碼,而不是 Path 參數所指定的機碼。 焦點中的這項變更會持續到數據表結尾,或直到看到另一個RTL_REGISTRY_SUBKEY或RTL_QUERY_REGISTRY_TOPKEY項目為止。 每個這類項目都必須指定相對於呼叫 RtlQueryRegistryValues 中所指定 Path 的路徑。
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 且目前索引鍵沒有子機碼時,例程只會略過該數據表 entry.)
RTL_QUERY_REGISTRY_NOVALUE 指定即使此數據表項目沒有 Name ,所有呼叫端都想要是回呼:也就是說,呼叫端不想要列舉目前索引鍵下的所有值。 針對 ValueData 使用 NULL 呼叫 QueryRoutine、針對 ValueType REG_NONE,而 ValueLength 則為零。
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除外。 RTL_QUERY_REGISTRY_TYPECHECK的收件匣支援是從 Windows 8 開始提供。 對於舊版 Windows,RTL_QUERY_REGISTRY_TYPECHECK支援是透過 Windows Update 提供。 如需詳細資訊,請參閱<備註>。

名稱

這是呼叫端查詢的 Value 名稱。 如果 NameNULL,則會針對與目前登錄機碼相關聯的所有值,呼叫為此數據表專案指定的 QueryRoutine 函式。 如果已設定RTL_QUERY_REGISTRY_DIRECT旗標,則必須提供 Name 的非 NULL 值。

EntryContext

如果已設定RTL_QUERY_REGISTRY_DIRECT旗標,這是緩衝區的指標,用來儲存此索引鍵的查詢作業結果。 否則,這個值會當做 QueryRoutineEntryContext 參數傳遞。

DefaultType

如果找不到相符的索引鍵且未指定RTL_QUERY_REGISTRY_REQUIRED旗標,這個成員最不重要的位元組會指定要傳回之數據的REG_XXX 類型。 針對沒有預設類型指定REG_NONE。 如果已設定RTL_QUERY_REGISTRY_TYPECHECK旗標,則此成員最重要的位元組會指定呼叫端預期之預存登錄值的 REG_XXX 類型。 此成員的位 8 到 23 是保留的,而且應該是零。

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,則呼叫端可以選擇性地指定零來表示 RtlQueryRegistryValues 應該根據預設數據值來計算長度。 如果 DefaultType = REG_NONE,則會忽略此成員。

[in, optional] Context

指定每次呼叫 QueryRoutine 函式時傳遞為 QueryRoutine 函式 Context 參數的值。

[in, optional] Environment

在 REG_EXPAND_SZ登錄值中展開變數值時所使用的環境指標,或 NULL 指標 (選擇性) 。

傳回值

RtlQueryRegistryValues 會傳回NTSTATUS程式碼。 可能的傳回值包括:

傳回碼 Description
STATUS_SUCCESS 已成功處理整個查詢表。
STATUS_INVALID_PARAMETER 處理以無效數據表項目終止的查詢數據表。 如果指定的旗標要求 QueryRoutineName 成員為非 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旗標,且預存登錄值的型別與呼叫端預期的類型不符。

如果數據表專案的 QueryRoutine 函式傳回 NTSTATUS 錯誤碼,並傳回該錯誤碼,RtlQueryRegistryValues 也會終止數據表的處理。 (有一個例外狀況:如果 QueryRoutine 傳回STATUS_BUFFER_TOO_SMALL,則會忽略錯誤碼。)

備註

呼叫端會指定初始索引鍵路徑和數據表。 數據表包含一或多個專案,描述呼叫端感興趣的索引鍵值和子機碼名稱。 數據表會由具有 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 個最大有效位中指定預期的REG_XXX 類型, (MSB) 。 如下列程式代碼範例所示,定義為 24 的 RTL_QUERY_REGISTRY_TYPECHECK_SHIFT 常數可用來作為將預期REG_XXX 類型放在 DefaultType 成員 8 個 MSB 中所需的移位計數。

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 呼叫存取不受信任的 hive,且呼叫端設定此呼叫的RTL_QUERY_REGISTRY_DIRECT旗標,則呼叫端必須另外設定RTL_QUERY_REGISTRY_TYPECHECK旗標。 來自使用者模式的呼叫違反此規則會導致例外狀況。 來自核心模式的呼叫違反此規則會導致0x139錯誤檢查 (KERNEL_SECURITY_CHECK_FAILURE) 。

只有系統 Hives 是受信任的。 存取系統 Hive 的 RtlQueryRegistryValues 呼叫不會造成例外狀況或錯誤檢查是否已設定RTL_QUERY_REGISTRY_DIRECT旗標,且未設定RTL_QUERY_REGISTRY_TYPECHECK旗標。 不過,最佳做法是,如果已設定RTL_QUERY_REGISTRY_DIRECT旗標,應該一律設定RTL_QUERY_REGISTRY_TYPECHECK旗標。

同樣地,在 Windows 8 之前的 Windows 版本中,最佳做法是 RtlQueryRegistryValues 呼叫,該呼叫會設定RTL_QUERY_REGISTRY_DIRECT旗標,應另外設定RTL_QUERY_REGISTRY_TYPECHECK旗標。 不過,無法遵循這項建議並不會造成例外狀況或錯誤檢查。

以下是系統 Hives 的清單:

  • \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 結構。 例程會將索引鍵值儲存為單一字串值。 字串中的每個個別元件都會以零終止。 如果UNICODE_STRINGBuffer 成員是 NULL,則例程會配置字串數據的記憶體。 否則,它會將字串數據儲存在 Buffer 指向的緩衝區中。
大小為位元組的非字串數據, <= sizeof (ULONG) 此值會儲存在 EntryContext 所指定的記憶體位置中。
大小、位元組、 >sizeof (ULONG) 的非字串數據 EntryContext 所指向的緩衝區必須以帶正負號的LONG值開頭。 值的大小必須指定緩衝區的大小,以位元組為單位。 如果值的正負號, RtlQueryRegistryValues 只會儲存索引鍵值的數據。 否則,它會使用緩衝區中的第一個 ULONG 來記錄值長度、以位元組為單位、第二個 ULONG 來記錄實值類型,以及用來儲存值數據的其餘緩衝區。

如果在查詢數據表處理的任何階段發生錯誤, RtlQueryRegistryValues 會停止處理數據表並傳回錯誤狀態。

如需可能REG_XXX 值的描述,請參閱 ZwSetValueKey

規格需求

需求
目標平台 Universal
標頭 wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h)
程式庫 Ntoskrnl.lib
Dll Ntoskrnl.exe
IRQL PASSIVE_LEVEL

另請參閱

QueryRoutine

RtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey