2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for RtlQueryRegistryValues
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
8 #define KMT_EMULATE_KERNEL
11 #ifdef KMT_KERNEL_MODE
12 #define KMT_KERNEL_HANDLE OBJ_KERNEL_HANDLE
14 #define KMT_KERNEL_HANDLE 0
18 #define RTL_NUMBER_OF(x) (sizeof(x) / sizeof(x[0]))
27 } EXPECTED_VALUE
, *PEXPECTED_VALUE
;
33 EXPECTED_VALUE Values
[20];
34 } EXPECTED_VALUES
, *PEXPECTED_VALUES
;
36 //static RTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
44 _In_ ULONG ValueLength
,
46 _In_ PVOID EntryContext
)
48 PEXPECTED_VALUES ExpectedValues
= Context
;
49 PEXPECTED_VALUE Expected
;
52 ok(ExpectedValues
->CurrentIndex
< ExpectedValues
->Count
,
53 "Call number %lu, expected only %lu\n",
54 ExpectedValues
->CurrentIndex
, ExpectedValues
->Count
);
55 if (!skip(ExpectedValues
->CurrentIndex
< ExpectedValues
->Count
, "Out of bounds\n"))
57 Expected
= &ExpectedValues
->Values
[ExpectedValues
->CurrentIndex
];
59 ok_eq_pointer(EntryContext
, Expected
);
60 ok_eq_wstr(ValueName
, Expected
->ValueName
);
61 ok_eq_ulong(ValueType
, Expected
->ValueType
);
62 ok_eq_ulong(ValueLength
, Expected
->ValueLength
);
63 EqualBytes
= RtlCompareMemory(ValueData
,
65 min(ValueLength
, Expected
->ValueLength
));
66 ok_eq_size(EqualBytes
, Expected
->ValueLength
);
69 ExpectedValues
->CurrentIndex
++;
70 return STATUS_SUCCESS
;
75 TestRtlQueryRegistryValues(
76 _In_ HANDLE KeyHandle
)
79 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"TestValue");
80 RTL_QUERY_REGISTRY_TABLE QueryTable
[] =
82 { QueryRoutine
, 0, L
"TestValue", NULL
, REG_NONE
, NULL
, 0 },
85 EXPECTED_VALUES Expected
;
91 #define CONST_STR_AND_LEN(d) { (d), sizeof(d) }
92 #define CSAL CONST_STR_AND_LEN
96 #define AUTO_DIFFERS 4
97 #define DEFAULT_DIFFERS 8
102 STR_AND_LEN Expected
[20];
104 ULONG DefaultExpectedCount
;
105 STR_AND_LEN DefaultExpected
[20];
109 { { NULL
, 0 }, 0, { { NULL
, 0 } }, NO_AUTO_LEN
| NO_DEFAULT
},
110 { CSAL(L
""), 0, { { NULL
, 0 } }, NO_AUTO_LEN
},
111 { CSAL(L
"\0"), 1, { CSAL(L
"") },
112 AUTO_DIFFERS
| DEFAULT_DIFFERS
, 0, { { NULL
, 0 } } },
113 { CSAL(L
"String"), 1, { CSAL(L
"String") }, NO_AUTO_LEN
},
114 { CSAL(L
"String\0"), 1, { CSAL(L
"String") } },
115 { CSAL(L
"String1\0String2"), 2, { CSAL(L
"String1"), CSAL(L
"String2") }, NO_AUTO_LEN
},
116 { CSAL(L
"String1\0String2\0"), 2, { CSAL(L
"String1"), CSAL(L
"String2") } },
117 { CSAL(L
"String1\0\0String3"), 3, { CSAL(L
"String1"), CSAL(L
""), CSAL(L
"String3") }, NO_AUTO_LEN
},
118 { CSAL(L
"String1\0\0String3\0"), 3, { CSAL(L
"String1"), CSAL(L
""), CSAL(L
"String3") },
119 AUTO_DIFFERS
, 1, { CSAL(L
"String1") } },
122 #define DO_QUERY(ExpectedArray, ExpectedCount) do \
125 ULONG _ExpectedCount = (ExpectedCount); \
126 for (_i = 0; _i < _ExpectedCount; _i++) \
128 Expected.Values[_i].ValueName = ValueName.Buffer; \
129 Expected.Values[_i].ValueType = REG_SZ; \
130 Expected.Values[_i].ValueData = (ExpectedArray)[_i].Str; \
131 Expected.Values[_i].ValueLength = (ExpectedArray)[_i].Len; \
133 Expected.CurrentIndex = 0; \
134 Expected.Count = _ExpectedCount; \
135 if (_ExpectedCount == 1) \
136 QueryTable[0].EntryContext = &Expected.Values[0]; \
138 QueryTable[0].EntryContext = NULL; \
139 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, \
144 ok_eq_hex(Status, STATUS_SUCCESS); \
145 ok_eq_ulong(Expected.CurrentIndex, Expected.Count); \
148 ULONG TestCount
= RTL_NUMBER_OF(Tests
);
151 for (i
= 0; i
< TestCount
; i
++)
153 trace("Set: %lu\n", i
);
154 Status
= ZwSetValueKey(KeyHandle
,
160 ok_eq_hex(Status
, STATUS_SUCCESS
);
162 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
165 /* Delete value to test default values */
166 Status
= ZwDeleteValueKey(KeyHandle
, &ValueName
);
167 ok(Status
== STATUS_SUCCESS
|| Status
== STATUS_OBJECT_NAME_NOT_FOUND
,
168 "ZwDeleteValueKey returned %lx\n", Status
);
170 /* Default: REG_NONE */
171 DO_QUERY((STR_AND_LEN
*)NULL
, 0);
173 for (i
= 0; i
< TestCount
; i
++)
175 if (Tests
[i
].Flags
& NO_DEFAULT
)
177 trace("Default: %lu\n", i
);
178 QueryTable
[0].DefaultType
= REG_MULTI_SZ
;
179 QueryTable
[0].DefaultData
= Tests
[i
].Value
.Str
;
180 QueryTable
[0].DefaultLength
= Tests
[i
].Value
.Len
;
182 if (Tests
[i
].Flags
& DEFAULT_DIFFERS
)
183 DO_QUERY(Tests
[i
].DefaultExpected
, Tests
[i
].DefaultExpectedCount
);
185 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
188 for (i
= 0; i
< TestCount
; i
++)
190 if (Tests
[i
].Flags
& NO_AUTO_LEN
)
192 trace("Auto: %lu\n", i
);
193 QueryTable
[0].DefaultType
= REG_MULTI_SZ
;
194 QueryTable
[0].DefaultData
= Tests
[i
].Value
.Str
;
195 QueryTable
[0].DefaultLength
= 0;
197 if (Tests
[i
].Flags
& AUTO_DIFFERS
)
198 DO_QUERY(Tests
[i
].DefaultExpected
, Tests
[i
].DefaultExpectedCount
);
200 DO_QUERY(Tests
[i
].Expected
, Tests
[i
].ExpectedCount
);
204 START_TEST(RtlRegistry
)
207 UNICODE_STRING KeyName
;
208 OBJECT_ATTRIBUTES ObjectAttributes
;
209 HANDLE SoftwareHandle
;
212 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\MACHINE\\Software");
213 InitializeObjectAttributes(&ObjectAttributes
,
215 OBJ_CASE_INSENSITIVE
| KMT_KERNEL_HANDLE
,
218 Status
= ZwOpenKey(&SoftwareHandle
,
221 ok_eq_hex(Status
, STATUS_SUCCESS
);
222 if (skip(NT_SUCCESS(Status
) && SoftwareHandle
!= NULL
, "No software key\n"))
225 RtlInitUnicodeString(&KeyName
, L
"RtlRegistryKmtestKey");
226 InitializeObjectAttributes(&ObjectAttributes
,
228 OBJ_CASE_INSENSITIVE
| KMT_KERNEL_HANDLE
,
231 Status
= ZwCreateKey(&KeyHandle
,
232 KEY_QUERY_VALUE
| KEY_SET_VALUE
| DELETE
,
238 ok_eq_hex(Status
, STATUS_SUCCESS
);
240 if (!skip(NT_SUCCESS(Status
) && KeyHandle
!= NULL
, "No test key\n"))
242 TestRtlQueryRegistryValues(KeyHandle
);
244 Status
= ZwDeleteKey(KeyHandle
);
245 ok_eq_hex(Status
, STATUS_SUCCESS
);
246 Status
= ZwClose(KeyHandle
);
247 ok_eq_hex(Status
, STATUS_SUCCESS
);