共用方式為


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 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\。預設。)
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 函式的位址,該函式會針對登錄中存在的每個值名稱呼叫。 數據表必須以 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

標誌

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

價值 意義
RTL_QUERY_REGISTRY_SUBKEY 此數據表專案 Name 是登錄機碼的另一個路徑,而下表專案則適用於該機碼,而不是 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 指定不存在的子機碼,就會結束這個結束。 (如果未指定此旗標,則當找不到非NULLName時,例程會使用 DefaultValue 成員做為值。當 NameNULL 且目前的索引鍵沒有子機碼時,例程只會略過該數據表專案。
RTL_QUERY_REGISTRY_NOVALUE 指定即使此數據表項目沒有 Name,所有呼叫端都想要回呼:也就是說,呼叫端不想列舉目前索引鍵下的所有值。 QueryRoutine 會針對 ValueData呼叫 NULLValueTypeREG_NONE,ValueLength為零。
RTL_QUERY_REGISTRY_NOEXPAND 對於類型為 REG_EXPAND_SZ 或 REG_MULTI_SZ 的登錄值,此旗標會覆寫預設行為,也就是在呼叫 QueryRoutine 例程之前,先處理登錄值。 根據預設,RtlQueryRegistryValues 會展開REG_EXPAND_SZ值中的環境變數參考,並在個別 QueryRoutine 呼叫中列舉REG_MULTI_SZ值中的每個 null 終止字符串,讓字元串 REG_SZ呈現為具有相同 ValueName的值。 如果設定此旗標,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 Update 提供RTL_QUERY_REGISTRY_TYPECHECK支援。 如需詳細資訊,請參閱。

名字

這是呼叫端查詢的 Value 名稱。 如果 Name 為 NULL,則會針對與目前登錄機碼相關聯的所有值呼叫針對這個數據表專案指定的 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 函式時,傳遞 Context 參數的值。

[in, optional] Environment

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

傳回值

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

傳回碼 描述
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旗標,且預存登錄值的型別不符合呼叫端預期的類型。

RtlQueryRegistryValues 如果數據表專案的 QueryRoutine 函式傳回 NTSTATUS 錯誤碼,並傳回該錯誤碼作為結果,也會終止處理數據表。 (有一個例外:如果 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旗標,呼叫端必須在數據表專案 成員的 8 個最大有效 位 (MSB) 中指定預期的 REG_XXX 類型。 如下列程式代碼範例所示,定義為 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 Update for Windows 7、Windows Vista、Windows Server 2003 和 Windows XP 取得。 如需此更新的詳細資訊,請參閱 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 成員 NULLRtlQueryRegistryValues 會報告索引鍵的每個直接子機碼。 如果索引鍵類型為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

要求

要求 價值
目標平臺 普遍
標頭 wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h)
連結庫 Ntoskrnl.lib
DLL Ntoskrnl.exe
IRQL PASSIVE_LEVEL

另請參閱

QueryRoutine

RtlZeroMemory

UNICODE_STRING

ZwEnumerateKey

ZwEnumerateValueKey

ZwSetValueKey