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 | 將目前的登錄機碼句柄重設為 RelativeTo 和 Path 參數所指定的原始登錄機碼句柄。 在使用 RTL_QUERY_REGISTRY_SUBKEY 旗標遞減到子機碼之後,這很適合回到原始節點。 |
RTL_QUERY_REGISTRY_REQUIRED | 指定如果 defaultType = REG_NONE |
RTL_QUERY_REGISTRY_NOVALUE | 指定即使此數據表項目沒有 Name,所有呼叫端都想要回呼:也就是說,呼叫端不想列舉目前索引鍵下的所有值。 QueryRoutine 會針對 ValueData呼叫 NULL,ValueTypeREG_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 名稱。 如果
EntryContext
如果已設定RTL_QUERY_REGISTRY_DIRECT旗標,這是緩衝區的指標,用來儲存此索引鍵的查詢作業結果。 否則,這個值會傳遞為 QueryRoutine的 EntryContext 參數。
DefaultType
如果找不到相符索引鍵且未指定RTL_QUERY_REGISTRY_REQUIRED旗標,則這個成員最不重要的位元組會指定要傳回之數據的REG_XXX 類型。 針對沒有預設類型指定REG_NONE。 如果已設定RTL_QUERY_REGISTRY_TYPECHECK旗標,這個成員中最重要的位元組會指定呼叫者預期之預存登錄值的REG_XXX 類型。 此成員的位 8 到 23 已保留,且應為零。
DefaultData
如果沒有找到相符索引鍵且未指定RTL_QUERY_REGISTRY_REQUIRED旗標,則為要傳回之預設值的指標。 如果 defaultType
DefaultLength
指定 DefaultData 成員的長度,以位元組為單位。 如果 DefaultType 是REG_SZ、REG_EXPAND_SZ或REG_MULTI_SZ,則呼叫端可以選擇性地指定零來表示 RtlQueryRegistryValues 應該根據預設值計算長度。 如果 DefaultType = REG_NONE,則會忽略此成員。
[in, optional] Context
指定每次呼叫 QueryRoutine 函式時,傳遞
[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 成員和 NULLName 成員的項目終止。 數據表必須從非分頁集區配置。
內核模式驅動程式必須指定RTL_QUERY_REGISTRY_NOEXPAND旗標,以防止呼叫環境變數例程。 這些例程不安全,因此內核模式驅動程式不應該使用它們。
謹慎
如果您使用 RTL_QUERY_REGISTRY_DIRECT 旗標,則不受信任的使用者模式應用程式可能會造成緩衝區溢位。 如果驅動程式使用此旗標來讀取指派錯誤類型的登錄值,就會發生緩衝區溢位。 在所有情況下,使用 RTL_QUERY_REGISTRY_DIRECT 旗標的驅動程序應該另外使用 RTL_QUERY_REGISTRY_TYPECHECK 旗標來防止這類溢位。
如果數據表項目中設定了RTL_QUERY_REGISTRY_TYPECHECK旗標,呼叫端必須在數據表專案 成員的 8 個最大有效
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 成員 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_STRING 的 Buffer 成員 NULL,則例程會配置字串數據的記憶體。 否則,它會將字串資料儲存在緩衝區中,Buffer 指向 。 |
REG_MULTI_SZ | 您必須為此索引鍵資料類型指定RTL_QUERY_REGISTRY_NOEXPAND旗標。 EntryContext 指向初始化的 UNICODE_STRING 結構。 例程會將索引鍵值儲存為單一字串值。 字串中的每個個別元件都會以零終止。 如果 UNICODE_STRING 的 Buffer 成員 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 |